На днях я столкнулся с вопросом GZipStream не обнаруживает поврежденные данные (даже CRC32 проходит)? (Из которых это вполне может быть "дубликат", у меня смешанные чувства по этому поводу.Я также был тем, кто добавил CRC32 в заголовок, но, оглядываясь назад, я чувствую себя неуместным по отношению к остальной части сообщения). Изучив проблему самостоятельно, я думаю, что проблема намного серьезнее , чем первоначально изображается в другом вопросе.
Я расширил другой вопрос и сделал тестовый код работающим под LINQPad и попытался лучше продемонстрировать проблему CRC32 (Cyclic Redundancy Check) , если она действительно существует. (Так как код представляет собой лишь небольшую модификацию , основанную на оригинале, возможно, что установка / методика тестирования ошибочны или есть еще одна странная причуда / PEBCAK и то и другое.)
Результаты нечеткие, потому что поврежденные данные не всегда вызывают (любое!) Исключение . Обратите внимание, что только иногда проверка CRC32 кажется действительно "работающей".Поврежденные байты, которые вызывают выход за пределы диапазона индекса / неверный заголовок / неверный нижний колонтитул, можно игнорировать, потому что мы можем предположить, что они убивают распаковку до проверки CRC32 (что совершенно понятно , даже если IndexOutOfRangeException, вероятно, должно быть заключено в InvalidDataException) так,
Почему проверка CRC32 значительно менее надежна, чем должна быть? (Почему это так, что есть «Недействительные данные» (Без исключения) "ниже?)
Поскольку нижний колонтитул GZip содержит как CRC32, так и длину несжатых данных , похоже, что частота обнаружения ошибок должен быть "значительно выше" - то есть я не ожидал ни одного случая отказа ниже, не говоря уже о количестве необнаруженных поврежденных потоков. (Конечно, приятно обнаруживать поврежденный Steam как можно скорее: но конечная контрольная сумма защиты, кажется, совершенно игнорируется в некоторых случаях.)
Формат: CorruptByteIndex + FailedDetections: Сообщение
:
0+0: System.IO.InvalidDataException:The magic number in GZip header is not correct. Make sure you are passing in a GZip stream. 1+0: System.IO.InvalidDataException:The magic number in GZip header is not correct. Make sure you are passing in a GZip stream. 2+0: System.IO.InvalidDataException:The compression mode specified in GZip header is unknown. 3+0: Good data (No Exception) 4+0: Good data (No Exception) 5+0: Good data (No Exception) 6+0: Good data (No Exception) 7+0: Good data (No Exception) 8+0: Good data (No Exception) 9+0: Good data (No Exception) 10+0: System.IO.InvalidDataException:Unknown block type. Stream might be corrupted. 11+1: Invalid data (No Exception) 12+1: System.IO.InvalidDataException:Found invalid data while decoding. 13+1: System.IO.InvalidDataException:Found invalid data while decoding. 14+1: System.IO.InvalidDataException:Found invalid data while decoding. 15+1: System.IO.InvalidDataException:Found invalid data while decoding. 16+1: System.IO.InvalidDataException:Found invalid data while decoding. 17+2: Invalid data (No Exception) 18+2: System.IO.InvalidDataException:Found invalid data while decoding. 19+2: System.IndexOutOfRangeException:Index was outside the bounds of the array. 20+2: System.IndexOutOfRangeException:Index was outside the bounds of the array. 21+3: Invalid data (No Exception) 22+3: System.IndexOutOfRangeException:Index was outside the bounds of the array. 23+3: System.IndexOutOfRangeException:Index was outside the bounds of the array. 24+4: Invalid data (No Exception) 25+4: System.IndexOutOfRangeException:Index was outside the bounds of the array. 26+4: System.IndexOutOfRangeException:Index was outside the bounds of the array. 27+4: System.IndexOutOfRangeException:Index was outside the bounds of the array. 28+4: System.IndexOutOfRangeException:Index was outside the bounds of the array. 29+5: Invalid data (No Exception) 30+5: System.IndexOutOfRangeException:Index was outside the bounds of the array. 31+6: Invalid data (No Exception) 32+7: Invalid data (No Exception) 33+7: System.IndexOutOfRangeException:Index was outside the bounds of the array. 34+7: System.IndexOutOfRangeException:Index was outside the bounds of the array. 35+7: System.IndexOutOfRangeException:Index was outside the bounds of the array. 36+8: Invalid data (No Exception) 37+8: System.IndexOutOfRangeException:Index was outside the bounds of the array. 38+8: System.IndexOutOfRangeException:Index was outside the bounds of the array. 39+9: Invalid data (No Exception) 40+9: System.IndexOutOfRangeException:Index was outside the bounds of the array. 41+9: System.IndexOutOfRangeException:Index was outside the bounds of the array. 42+10: Invalid data (No Exception) 43+10: System.IO.InvalidDataException:Found invalid data while decoding. 44+10: System.IndexOutOfRangeException:Index was outside the bounds of the array. 45+10: System.IO.InvalidDataException:Found invalid data while decoding. 46+11: Invalid data (No Exception) 47+11: System.IndexOutOfRangeException:Index was outside the bounds of the array. 48+11: System.IndexOutOfRangeException:Index was outside the bounds of the array. 49+11: System.IndexOutOfRangeException:Index was outside the bounds of the array. 50+12: Invalid data (No Exception) 51+12: System.IndexOutOfRangeException:Index was outside the bounds of the array. 52+12: System.IndexOutOfRangeException:Index was outside the bounds of the array. 53+13: Invalid data (No Exception) 54+13: System.IndexOutOfRangeException:Index was outside the bounds of the array. 55+14: Invalid data (No Exception) 56+14: System.IndexOutOfRangeException:Index was outside the bounds of the array. 57+15: Invalid data (No Exception) 58+15: System.IndexOutOfRangeException:Index was outside the bounds of the array. 59+15: System.IndexOutOfRangeException:Index was outside the bounds of the array. 60+16: Invalid data (No Exception) 61+17: Invalid data (No Exception) 62+18: Invalid data (No Exception) 63+19: Invalid data (No Exception) 64+19: System.IndexOutOfRangeException:Index was outside the bounds of the array. 65+19: System.IndexOutOfRangeException:Index was outside the bounds of the array. 66+19: System.IndexOutOfRangeException:Index was outside the bounds of the array. 67+19: System.IndexOutOfRangeException:Index was outside the bounds of the array. 68+19: System.IndexOutOfRangeException:Index was outside the bounds of the array. 69+19: System.IndexOutOfRangeException:Index was outside the bounds of the array. 70+19: System.IO.InvalidDataException:Found invalid data while decoding. 71+19: System.IndexOutOfRangeException:Index was outside the bounds of the array. 72+19: System.IndexOutOfRangeException:Index was outside the bounds of the array. 73+19: System.IndexOutOfRangeException:Index was outside the bounds of the array. 74+19: System.IndexOutOfRangeException:Index was outside the bounds of the array. 75+19: System.IO.InvalidDataException:Found invalid data while decoding. 76+19: System.IndexOutOfRangeException:Index was outside the bounds of the array. 77+19: System.IndexOutOfRangeException:Index was outside the bounds of the array. 78+19: System.IndexOutOfRangeException:Index was outside the bounds of the array. 79+19: System.IndexOutOfRangeException:Index was outside the bounds of the array. 80+19: System.IndexOutOfRangeException:Index was outside the bounds of the array. 81+19: System.IO.InvalidDataException:Found invalid data while decoding. 82+19: System.IndexOutOfRangeException:Index was outside the bounds of the array. 83+20: Invalid data (No Exception) 84+21: Invalid data (No Exception) 85+22: Invalid data (No Exception) 86+22: System.IndexOutOfRangeException:Index was outside the bounds of the array. 87+23: Invalid data (No Exception) 88+24: Invalid data (No Exception) 89+25: Invalid data (No Exception) 90+25: System.IndexOutOfRangeException:Index was outside the bounds of the array. 91+26: Invalid data (No Exception) 92+26: System.IO.InvalidDataException:Found invalid data while decoding. 93+26: System.IndexOutOfRangeException:Index was outside the bounds of the array. 94+27: Invalid data (No Exception) 95+27: System.IndexOutOfRangeException:Index was outside the bounds of the array. 96+27: System.IndexOutOfRangeException:Index was outside the bounds of the array. 97+28: Invalid data (No Exception) 98+28: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 99+28: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 100+29: Invalid data (No Exception) 101+30: Invalid data (No Exception) 102+31: Invalid data (No Exception) 103+32: Invalid data (No Exception) 104+32: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 105+33: Invalid data (No Exception) 106+34: Invalid data (No Exception) 107+35: Invalid data (No Exception) 108+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 109+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 110+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 111+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 112+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 113+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 114+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 115+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 116+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 117+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 118+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 119+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 120+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 121+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 122+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 123+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 124+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 125+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 126+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 127+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 128+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 129+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 130+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 131+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 132+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 133+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 134+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 135+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 136+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 137+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 138+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 139+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 140+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 141+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 142+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 143+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 144+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 145+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 146+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 147+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 148+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 149+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 150+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 151+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 152+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 153+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 154+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 155+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 156+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 157+35: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 158+36: Invalid data (No Exception) 159+36: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 160+36: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 161+37: Invalid data (No Exception) 162+38: Invalid data (No Exception) 163+39: Invalid data (No Exception) 164+40: Invalid data (No Exception) 165+41: Invalid data (No Exception) 166+41: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 167+41: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 168+41: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 169+41: System.IO.InvalidDataException:The CRC in GZip footer does not match the CRC calculated from the decompressed data. 170+41: System.IO.InvalidDataException:The stream size in GZip footer does not match the real stream size. 171+41: System.IO.InvalidDataException:The stream size in GZip footer does not match the real stream size. 172+41: System.IO.InvalidDataException:The stream size in GZip footer does not match the real stream size. 173+41: System.IO.InvalidDataException:The stream size in GZip footer does not match the real stream size.
Вот тест, который можно скопировать и вставить в LINQPad (для .NET 3.5 и 4 используйте режим «как операторы C #»):
string sample = "This is a compression test of microsoft .net gzip compression method and decompression methods";
var encoding = new ASCIIEncoding();
var data = encoding.GetBytes(sample);
string sampleOut = null;
byte[] cmpData;
// Compress
using (var cmpStream = new MemoryStream())
{
using (var hgs = new System.IO.Compression.GZipStream(cmpStream, System.IO.Compression.CompressionMode.Compress))
{
hgs.Write(data, 0, data.Length);
}
cmpData = cmpStream.ToArray();
}
int corruptBytesNotDetected = 0;
// corrupt data byte by byte
for (var byteToCorrupt = 0; byteToCorrupt < cmpData.Length; byteToCorrupt++)
{
var corruptData = new List(cmpData).ToArray();
// corrupt the data
corruptData[byteToCorrupt]++;
using (var decomStream = new MemoryStream(corruptData))
{
using (var hgs = new System.IO.Compression.GZipStream(decomStream, System.IO.Compression.CompressionMode.Decompress))
{
using (var reader = new StreamReader(hgs))
{
string message;
try
{
sampleOut = reader.ReadToEnd();
// if we get here, the corrupt data was not detected by GZipStream
// ... okay so long as the correct data is extracted
if (!sample.SequenceEqual(sampleOut)) {
corruptBytesNotDetected++;
message = "Invalid data (No Exception)";
} else {
message = "Good data (No Exception)";
}
}
catch(Exception ex)
{
message = (ex.GetType() + ":" + ex.Message);
}
string.Format("{0}+{1}: {2}",
byteToCorrupt, corruptBytesNotDetected, message).Dump();
}
}
}
}
Вот сжатые данные в .NET 3.5 (GZipStream, как известно, плохо «сжимает» небольшие полезные данные, но это проблема «не исправить», потому что поток все еще технически действителен):
1F 8B 08 00 00 00 00 00 04 00 ED BD 07 60 1C 49 96 25 26 2F 6D CA 7B 7F 4A F5 4A D7 E0 74 A1 08 80 60 13 24 D8 90 40 10 EC C1 88 CD E6 92 EC 1D 69 47 23 29 AB 2A 81 CA 65 56 65 5D 66 16 40 CC ED 9D BC F7 DE 7B EF BD F7 DE 7B EF BD F7 BA 3B 9D 4E 27 F7 DF FF 3F 5C 66 64 01 6C F6 CE 4A DA C9 9E 21 80 AA C8 1F 3F 7E 7C 1F 3F 22 DE CC 8B 26 A5 FF 65 E9 B4 5A AC EA BC 69 8A 6A 99 B6 79 D3 A6 D5 79 BA 28 A6 75 D5 54 E7 6D 3A 5E E6 6D 7A F1 83 62 15 B4 5B E4 ED BC 9A A5 D9 72 96 CE F2 FE 17 CD FF 03 5C 51 5E 27 5E 00 00 00
(И, просто для смеха, в .NET 4 он генерирует немного больший / другой сжатый поток.)
1F 8B 08 00 00 00 00 00 04 00 EC BD 07 60 1C 49 96 25 26 2F 6D CA 7B 7F 4A F5 4A D7 E0 74 A1 08 80 60 13 24 D8 90 40 10 EC C1 88 CD E6 92 EC 1D 69 47 23 29 AB 2A 81 CA 65 56 65 5D 66 16 40 CC ED 9D BC F7 DE 7B EF BD F7 DE 7B EF BD F7 BA 3B 9D 4E 27 F7 DF FF 3F 5C 66 64 01 6C F6 CE 4A DA C9 9E 21 80 AA C8 1F 3F 7E 7C 1F 3F 22 DE CC 8B 26 A5 FF 65 E9 B4 5A AC EA BC 69 8A 6A 99 B6 79 D3 A6 D5 79 BA 28 A6 75 D5 54 E7 6D 3A 5E E6 6D 7A F1 83 62 15 B4 5B E4 ED BC 9A A5 D9 72 96 CE F2 FE 17 CD FF 13 00 00 FF FF 5C 51 5E 27 5E 00 00 00
Дополнительные примечания:
В этом случае тест может быть некорректно .Когда GZipStream «не может обнаружить повреждение» (без исключения), тогда данные, прочитанные из StreamReader, будут «» (пустая строка): в этом случае, почему ReadToEnd ()
не вызывает Исключение (IOException или иное)?
Таким образом, не GZipStream, а скорее StreamReader, который здесь "необычный", или это все еще проблема с GZipStream (из-за того, что исключение не генерируется)? Есть ли какой-нибудь правильный способ надежно справиться с этим вариантом использования? (Учтите, когда входной поток из текущей позиции действительно пуст.)