Warum erkennt BCL GZipStream (mit StreamReader) Datenfehler mit CRC32 nicht zuverlässig?

8

Neulich stieß ich auf die Frage GZipStream nicht detect korrupte Daten (selbst CRC32-Pässe)? (Von denen dies sehr wohl ein "Duplikat" sein könnte, habe ich gemischte Gefühle zu diesem Thema. Ich war auch derjenige, der die CRC32 zum Titel hinzugefügt hat, aber rückblickend das fühlt sich fehl am Platz mit dem Rest der Post). Nachdem ich das Problem ein wenig selbst untersucht habe, denke ich, dass das Problem viel größer ist als die andere Frage, die anfangs dargestellt wird.

Ich habe die andere Frage erweitert und den Testcode unter LINQPad ausführbar gemacht und versucht, CRC32 (Cyclic Redundancy Check) Problem, wenn es tatsächlich existiert. (Da der Code nur eine leichte Modifikation ist, die auf dem Original basiert, ist es möglich, dass der Testaufbau / die Testmethodik fehlerhaft ist oder es eine andere merkwürdige Eigenart / PEBCAK gibt.)

Die Ergebnisse sind ungerade, da die beschädigten Daten nicht immer sind und eine (beliebige!) Ausnahme ausgelöst werden. Beachten Sie, dass nur manchmal scheint die CRC32-Prüfung tatsächlich zu "funktionieren". Die beschädigten Bytes, die den Index-out-of-range / bad-Header / bad footer verursachen, können ignoriert werden, da wir davon ausgehen können, dass diese die Dekomprimierung prior für den CRC32-Test beenden (was perfekt ist) verständlich , selbst wenn die IndexOutOfRangeException wahrscheinlich von einer InvalidDataException umschlossen wird),

Warum ist der CRC32-Test wesentlich weniger zuverlässig als er eigentlich sein sollte? (Warum gibt es unten "Ungültige Daten (keine Ausnahme)"?)

Da die GZip-Fußzeile enthält beide die CRC32 und Länge der unkomprimierten Daten scheint, dass die Fehlererkennungsrate "signifikant höher" sein sollte Das heißt, ich würde nicht einen einzigen Fehler unten erwarten, geschweige denn eine Anzahl nicht erkannter beschädigter Streams. (Natürlich ist es schön, einen verdorbenen Dampf so schnell wie möglich zu entdecken: aber die letzte Sicherheits-Prüfsumme scheint in Fällen regelrecht ignoriert zu werden.)

Format ist CorruptByteIndex+FailedDetections: Message :

%Vor%

Hier ist der Test, der copy'n'paste in LINQPad ausführbar ist (für .NET 3.5 und 4 verwenden Sie den "als C # -Anweisungen" -Modus):

%Vor%

Hier sind die komprimierten Daten in .NET 3.5 (GZipStream ist notorisch schlecht beim "Komprimieren" kleiner Payloads, aber es ist ein "Will not Fix" -Problem, da der Stream immer noch technisch gültig ist):

%Vor%

(Und nur zum Kichern erzeugt es in .NET 4 einen etwas größeren / anderen komprimierten Stream.)

%Vor%

Zusätzliche Hinweise:

Der Test kann in diesem Fall subtil fehlerhaft sein. Wenn der GZipStream "keine Beschädigung erkennt" (keine Ausnahme), dann sind die vom StreamReader gelesenen Daten "" (eine leere Zeichenfolge): Warum verursacht ReadToEnd() nicht eine Ausnahme ( IOException oder anders)?

Ist es also nicht GZipStream, sondern der StreamReader, der hier "skurril" ist oder ist das immer noch ein Problem mit dem GZipStream (um keine Ausnahme auszulösen)? Gibt es einen richtigen Weg, um diesen Anwendungsfall zuverlässig zu handhaben? (Überlegen Sie, wann der Eingabestrom von der aktuellen Position wirklich leer ist.)

    
Community 27.02.2012, 20:30
quelle

1 Antwort

10

Vorwort

.NET [4 und vorherige] Benutzer sollten unter keinen Umständen die von Microsoft bereitgestellten GZipStream- oder DeflateStream-Klassen verwenden, es sei denn, Microsoft ersetzt sie vollständig durch etwas, das funktioniert. Verwenden Sie stattdessen die DotNetZip-Bibliothek.

Update zu Vorwort

Das .NET Framework 4.5 und höher haben das Komprimierungsproblem behoben, und GZipStream und DeflateStream verwenden zlib in diesen Versionen. Ich weiß nicht, ob das unten erwähnte CRC-Problem behoben wurde.

Ein weiteres Update

Der CRC-Fehler ist nicht nur nicht behoben, sondern Microsoft hat entschieden, dass sie wird es nicht reparieren es!

Meine Antwort in Warum produziert mein C # gzip eine größere Datei als Fiddler oder PHP? zeigt, dass dieses Verhalten nicht funktioniert eine korrekte Implementierung der gzip-Korruptionserkennung widerspiegeln. In allen getesteten Fällen würde der Fehler durch eine geeignete Implementierung erkannt werden. (Diese Antwort stellt auch fest, warum sieben der Fälle zu guten Daten führen.)

Eine andere Frage ist: Wie erzeugt diese "Komprimierungs" -Methode 174 Bytes Ausgabe von einer 94-Byte-Zeichenfolge? Vor allem, weil die Zeichenkette komprimierbar ist - gzip reduziert sie auf 84 Bytes, sogar mit dem Overhead eines 18-Byte-Headers und -Trailers. Können Sie einen Hex-Dump dieser 174 Bytes bereitstellen?

    
Mark Adler 27.02.2012, 20:48
quelle