C # - Арифметическое переполнение - Распаковка строки с помощью gzipstream

У меня возникла проблема с реализацией распаковщика строк GZIP. Сжатая строка имеет вид a20d32fdda14b300b28aa6b72982af3b, как показано ниже. Однако при запуске этого кода я получаю сообщение об ошибке:

«Возникло исключение System.OverflowException
HResult = 0x80131516
Сообщение = Арифметическая операция привела к переполнению.
StackTrace:
в GZipDecompressor.Decompress.Main (String [] args)
"

при выполнении строки, начинающейся с "byte[] buffer2"

using System;
using System.IO;
using System.IO.Compression;
using System.Text;

namespace GZipDecompressor
{
    class Decompress
    {
        public static void Main(string[] args)
        {
            string compressedText = "a20d32fdda14b300b28aa6b72982af3b";
            int length = compressedText.Length;
            byte[] buffer = Convert.FromBase64String(compressedText);
            using (MemoryStream stream = new MemoryStream())
            {
                stream.Write(buffer, 4, buffer.Length - 4);
                byte[] buffer2 = new byte[BitConverter.ToInt32(buffer, 0)];
                stream.Position = 0;
                using (GZipStream stream2 = new GZipStream(stream, CompressionMode.Decompress))
                {
                    stream2.Read(buffer2, 0, buffer2.Length);
                }
                Console.WriteLine(Encoding.UTF8.GetString(buffer2));
            }
        }
    }
}

Не мог бы кто-нибудь объяснить, почему это происходит и как это решить.


person Kavinda JD    schedule 27.06.2017    source источник
comment
Содержит ли вход длину исходных несжатых данных как int в первых 4 байтах?   -  person Lasse V. Karlsen    schedule 27.06.2017
comment
BitConverter.ToInt32(buffer, 0) - buffer - это байт [24] ...   -  person dovid    schedule 27.06.2017
comment
Насколько вы уверены, что введенная вами строка действительно действительна? Откуда это?   -  person Chris    schedule 27.06.2017
comment
@lomed Да, похоже, это факты. См. Мой вопрос.   -  person Lasse V. Karlsen    schedule 27.06.2017
comment
Пожалуйста, обращайтесь ко всем, кто использует синтаксис @. Ты у меня спрашиваешь? Это не мой код, см. Мой вопрос в моем первом комментарии. Содержит ли ввод длину как первые 4 байта?   -  person Lasse V. Karlsen    schedule 27.06.2017
comment
@lomed: Возможно, вы захотите быть более точным в том, о чем вы говорите. Строка кода, которую вы цитируете, вполне верна. Вызов ToInt32 вернет число, состоящее из первых четырех байтов в массиве. Я предполагаю, что это сделано намеренно, и именно поэтому поток памяти пропускает первые четыре байта (потому что они имеют другое назначение). Если вы думаете, что что-то не так, вам следует сказать, что это, вместо того, чтобы быть расплывчатым ...   -  person Chris    schedule 27.06.2017
comment
@ LasseV.Karlsen: Не уверен.   -  person Kavinda JD    schedule 27.06.2017
comment
@ LasseV.Karlsen: Строка распаковывается до 121013301333232an   -  person Kavinda JD    schedule 27.06.2017
comment
Потом проверьте, проверьте. Сначала перепишите свою программу, захватив этот int (BitConverter.ToInt32(buffer, 0)) в переменную, затем отладьте свою программу и проверьте, какое число вы получили. Скорее всего, вы получите действительно большое число.   -  person Lasse V. Karlsen    schedule 27.06.2017
comment
@KavindaJD, вы уверены, что compressedText действительно закодирован в base64? Похоже, что он содержит только шестнадцатеричные символы.   -  person C.Evenhuis    schedule 27.06.2017
comment
@Chris: Это скорее проект обратной инженерии. Программа вывела файл с именем a20d32fdda14b300b28aa6b72982af3b. Он был извлечен из более крупного zip-файла. Я предполагаю, что он использует распаковку GZip, поскольку я декомпилировал .dll, который выполняет распаковку.   -  person Kavinda JD    schedule 27.06.2017
comment
Значит, вы даже не знаете, использует ли он gzip?   -  person Lasse V. Karlsen    schedule 27.06.2017
comment
Действительный поток gzip начинается с байтов 0x1f 0x8b. Ваша строка не содержит этих байтов, будь то сырые, в виде шестнадцатеричной строки или декодированные как Base64. Вам нужно будет внимательнее взглянуть на то, что производит эту строку. Также обратите внимание, что ZIP не является GZip.   -  person Jeroen Mostert    schedule 27.06.2017
comment
Тогда я голосую за то, чтобы закрыть этот вопрос как неясный. Вы должны исходить из того, что ваш код просто глючит. Если ваш вопрос действительно состоит в том, что у меня есть этот волшебный файл, как я могу его расшифровать, это совершенно другой вопрос.   -  person Lasse V. Karlsen    schedule 27.06.2017
comment
@ C.Evenhuis: Полагаю, это так. Я не знаю другой формы, которую это могло бы принять.   -  person Kavinda JD    schedule 27.06.2017
comment
@ LasseV.Karlsen: Хорошо, приглядимся.   -  person Kavinda JD    schedule 27.06.2017
comment
@KavindaJD Вы учли, что это может быть шестнадцатеричное представление байтов? Я не знаю вашего уровня знаний, поэтому исключение возможностей на основании того, что вы о них не знаете, может быть плохой отправной точкой.   -  person C.Evenhuis    schedule 27.06.2017
comment
Предположение, что имя файла содержит зашифрованные данные, кажется очень странным. Скорее всего, это просто руководство, созданное для обеспечения уникального имени файла. Тот факт, что это 32-символьная строка шестнадцатеричных цифр, подтверждает эту теорию, поскольку это точно то же самое, что и guid (за исключением того, что guid обычно отображаются с - для разделения блоков, но их можно легко удалить).   -  person Chris    schedule 27.06.2017


Ответы (1)


BitConverter.ToInt32(buffer, 0) дает отрицательное значение, которое недопустимо для размещения массива.

person vasek    schedule 27.06.2017
comment
Это даст другое сообщение об исключении, чем показано. OP говорит, что это дает арифметическую операцию, приводящую к переполнению, тогда как отрицательное число (что да, оно воспроизводится из показанного кода) дает размеры массива, превышающие поддерживаемый диапазон - person Lasse V. Karlsen; 27.06.2017
comment
@LasseV.Karlsen Я также пытался, и в моем поле инициализация массива с отрицательной длиной также дает арифметическую операцию, приводящую к исключению переполнения. - person C.Evenhuis; 27.06.2017
comment
Кажется, что отрицательное значение должно быть в переменной. Если вы сделаете new byte[-1], я получу ошибку компиляции Cannot create an array with a negative size. Если я сделаю int temp = -1; var array = new byte[temp];, я получу ошибку переполнения. - person Chris; 27.06.2017
comment
comment
@ LasseV.Karlsen: Я получаю -551719573. Отрицательный, как обсуждалось. - person Kavinda JD; 27.06.2017