Seite 1 von 1

LZMA-Packer will einen zu kleinen Ausgangspuffer?

Verfasst: 14.11.2013 16:24
von Sauer-RAM
Ich meine einen Bug in dem Pack- oder UnpackMemory (weiß ich leider nicht mehr genau, aber ich meine es war unpack) entdeckt zu haben:
Daten lassen sich mit dem LZMA Algorithmus scheinbar nur entpacken, wenn der Ausgangspuffer exakt so groß oder sogar kleiner ist als die Größe der Daten nach dem Entpacken, so dass man nicht einfach präventiv einen größeren Ausgangspuffer nehmen kann.

Bei ZIP funktioniert das Entpacken nur wenn der Ausgangspuffer größer oder gleich ist, was mir logischer erscheint.
Ist das ein Bug, oder ist das so gewollt?

Gruß

Felix

PS: Ich benutze die PB-Vollversion 5.20

Verschoben von NicTheQuick von 'Bugs' nach 'Allgemein'.

Re: LZMA-Packer will einen zu kleinen Ausgangspuffer?

Verfasst: 14.11.2013 16:59
von NicTheQuick
Das ist wohl kaum ein Bug-Report. Lies dir dazu bitte mal durch wie man einen Bug postet.

Hier fehlt auf jeden Fall schon mal die Möglichkeit das nachzuvollziehen. Also wo ist der Code, der nicht so funktioniert, wie er soll?

Re: LZMA-Packer will einen zu kleinen Ausgangspuffer?

Verfasst: 14.11.2013 19:59
von Sauer-RAM
Ok, tut mir Leid... In meinem "Verbesserungseifer" habe ich die Anleitung zu spät gelesen und von selbst empfand ich einen Testcode für überflüssig. Aber nun gut.

Hier ist ein Testcode.

Code: Alles auswählen

UseZipPacker()
UseLZMAPacker()

*UngepackteDaten = AllocateMemory(100)
RandomSeed(100)                           ;Damit die Daten immer gleich sind

RandomData(*UngepackteDaten,100)          ;Daten in den Eingangspuffer

;---------------------------------------------------------------------------LZMApuffer verpacken
*LZMAUnformatiert = AllocateMemory(1000)                    ;Die gepackten Daten werden größer sein, da sich Zufallsdaten
                                                            ;nicht gut komprimieren lassen.

LZMASize = CompressMemory(*UngepackteDaten,100,*LZMAUnformatiert,1000,#PB_PackerPlugin_LZMA)

*LZMAFormatiert = AllocateMemory(LZMASize)
MoveMemory(*LZMAUnformatiert,*LZMAFormatiert,LZMASize)
;-----------------------------------------------------------------------------------------------


;---------------------------------------------------------------------------ZIPpuffer verpacken
*ZIPUnformatiert = AllocateMemory(1000)                   ;Die gepackten Daten werden größer sein, da sich Zufallsdaten
                                                          ;nicht gut komprimieren lassen.

ZIPSize = CompressMemory(*UngepackteDaten,100,*ZIPUnformatiert,1000,#PB_PackerPlugin_Zip)

*ZIPFormatiert = AllocateMemory(ZIPSize)
MoveMemory(*ZIPUnformatiert,*ZIPFormatiert,ZIPSize)
;----------------------------------------------------------------------------------------------

;-------------------------------------------------------------------------ZIP Dekomprimierung (erfolgreich)
*ZIPOutput = AllocateMemory(MemorySize(*ZIPFormatiert) * 20)    ;Da man in normalen Anwendungen die Anfangsgröße nicht kennt,
                                                                ;nimmt man einen größeren Wert an.

ZIPErgebnis = UncompressMemory(*ZIPFormatiert,ZIPSize,*ZIPOutput,MemorySize(*ZIPOutput),#PB_PackerPlugin_Zip)
If ZIPErgebnis
  Debug "ZIP war erfolgreich"
  Debug "Daten des ZIP-Decomprimierers:"
  Debug PeekS(*ZIPOutput,ZIPErgebnis)
  Debug ""
Else
  Debug "ZIP war nicht erfolgreich"
  Debug ""
EndIf
;----------------------------------------------------------------------------------------------------------

;-------------------------------------------------------------------------LZMA Dekomprimierung (nicht erfolgreich)
*LZMAOutput = AllocateMemory(MemorySize(*LZMAFormatiert) * 20)    ;Da man in normalen Anwendungen die Anfangsgröße nicht kennt,
                                                                ;nimmt man einen größeren Wert an.

LZMAErgebnis = UncompressMemory(*LZMAFormatiert,LZMASize,*LZMAOutput,MemorySize(*LZMAOutput),#PB_PackerPlugin_LZMA)
If LZMAErgebnis
  Debug "LZMA war erfolgreich"
  Debug "Daten des LZMA-Decomprimierers:"
  Debug ""
  Debug PeekS(*LZMAOutput,ZIPErgebnis)
Else
  Debug "LZMA war nicht erfolgreich. Der Puffer ist seltsamerweise ZU GROSS?!?"
  Debug ""
EndIf
;----------------------------------------------------------------------------------------------------------

;-------------------------------------------------------------------------LZMA Dekomprimierung (erfolgreich)
*LZMAOutput = AllocateMemory(MemorySize(*LZMAFormatiert) * 0.5) ;Hier nehme ich eine eindeutig zu kleinen Ausgangsgröße an

LZMAErgebnis = UncompressMemory(*LZMAFormatiert,LZMASize,*LZMAOutput,MemorySize(*LZMAOutput),#PB_PackerPlugin_LZMA)
If LZMAErgebnis
  Debug "LZMA war erfolgreich"
  Debug "Daten des LZMA-Decomprimierers:"
  Debug PeekS(*LZMAOutput,ZIPErgebnis)
  Debug ""
Else
  Debug "LZMA war nicht erfolgreich. Der Puffer ist seltsamerweise ZU GROSS?!?"
  Debug ""
EndIf
;----------------------------------------------------------------------------------------------------------

;-------------------------------------------------------------------------LZMA Dekomprimierung (erfolgreich 2)
*LZMAOutput = AllocateMemory(100) ;Hier gebe ich die exakte Ausgangsgröße an, die ich in anderen Programmen nicht kenne.

LZMAErgebnis = UncompressMemory(*LZMAFormatiert,LZMASize,*LZMAOutput,MemorySize(*LZMAOutput),#PB_PackerPlugin_LZMA)
If LZMAErgebnis
  Debug "LZMA war erfolgreich"
  Debug "Daten des LZMA-Decomprimierers:"
  Debug PeekS(*LZMAOutput,ZIPErgebnis)
  Debug ""
Else
  Debug "LZMA war nicht erfolgreich. Der Puffer ist seltsamerweise ZU GROSS?!?"
  Debug ""
EndIf
;----------------------------------------------------------------------------------------------------------
Ich habe in dem Code darauf verzichtet zu beweisen dass der ZIP-Packer bei zu kleinen Ausgangspuffern nicht funktioniert, aber ich gehe davon aus, dass dies nur logisch ist und eigentlich nicht direkt mit dem Bug zusammenhängt. Natürlich könnt ihr dies durch kleine Modifikationen des Codes selbst teste.
Desweiteren habe ich untypischerweise pseudozufällige Daten angenommen, bei denen die komprimierung der Daten größer ist als die unkomprimierten. Auch hier lässt sich durch modifikation meines Codes beweisen, dass der Effekt auch bei "realen" Daten vorkommt.

Der Code wurde mit dem Debuger, im ASCII-Modus auf einem Windoof 7 Home Premium (32 Bit) SP 1 mit der PB-Vollversion 5.20 LTS ausgeführt.

Sollte ich etwas vergessen haben, bitte ich um Rückmeldung.

Gruß

Felix

Re: LZMA-Packer will einen zu kleinen Ausgangspuffer?

Verfasst: 14.11.2013 20:13
von ts-soft
Wenn man die Grösse des Originals nicht kennt, macht man eindeutig was verkehrt :wink:
Jedes Archivformat (als Datei) enthält Header mit Informationen über die gepackte, ungepackte, prüfsummen usw.
Wenn man im Speicher komprimiert, erstellt man sich natürlich auch einen solchen Header, alles andere ist jedenfalls
sehr unprofessionell und mit Sicherheit kein Bug!

Gruß
Thomas

Re: LZMA-Packer will einen zu kleinen Ausgangspuffer?

Verfasst: 14.11.2013 23:10
von Sauer-RAM
In meinem Fall benutze ich die Komprimierung um die Redundanzen aus Texten zu nehmen um diese danach zu verschlüsseln und dadurch einen Statistischen Angriff zu erschweren oder du verhindern. Ich möchte auch keinerlei Hinweise auf den Inhalt der Daten in der Verschlüsselung übermitteln, also auch keine Größe. Zudem erzeugt das nur einen Unnötigen Overhead, der bei sehr kleinen Nachrichten und großer Anzahl dieser schon ins Gewicht fällt.

Ich habe mich nur gewundert, warum zu große Puffer bei dem Zip geht, bei dem LZMA nicht. Naja, dann hat sich die Sache wohl erledigt.
Wenn aber jemand eine Antwort auf meine Frage weiß, dann würde ich mich über eine Antwort freuen.

Gruß

Felix

P.S. Die Daten werden per TCP übertragen, haben also schon eine Fehlerkorrektur und dann kann ich mir meine eigene größtenteils sparen.
Und wenn ich durch einen größeren Buffer den gleichen Effekt wie durch einen größeren Overhead erreichen kann, dann wähle ich den Buffer. Ich habe genug RAM ^^. Lieber verbrat ich 0,08% mehr Rechenzeit und Arbeitsspeicher, als dass ich bei kleinen Paketen ca 7,5% mehr Daten übertragen muss.

Re: LZMA-Packer will einen zu kleinen Ausgangspuffer?

Verfasst: 15.11.2013 09:31
von Thorium
Die dekomprimierte Größe ist bereits Teil des LZMA Headers, wenn PB den nicht entfernt.

Von der Logik her sollte man aber auf jeden Fall in größere Puffer entpacken können. Kann schließlich sein das ich vor oder nach dem entpacken noch was in den Puffer schreiben möchte.

Etwas zu entpacken ohne die korrekte Größe zu kennen kann zum Sicherheitsproblem werden. Es darf nie in einen zu kleinen Puffer entpackt werden, so das er nicht überläuft.

Re: LZMA-Packer will einen zu kleinen Ausgangspuffer?

Verfasst: 15.11.2013 12:45
von matbal
Laut PB-Hilfetext soll UncompressMemory() die Größe der dekomprimierten Daten zurückgeben.
Beim LZMA-Packer wird aber 0 zurückgegeben, obwohl richtig entpackt wurde. Für mich sieht das nach Fehler aus.

Code: Alles auswählen

EnableExplicit

UseLZMAPacker()
Define Plugin = #PB_PackerPlugin_LZMA

;UseZipPacker()
;Define Plugin = #PB_PackerPlugin_Zip


Define *Buffer1 = AllocateMemory(1000) ; Eingabe
Define *Buffer2 = AllocateMemory(1000) ; Komprimiert
Define *Buffer3 = AllocateMemory(1000) ; Unkompimiert


Define Text$ = "Das ist der zu packende Text, der viel zu groß ist"
Define InpLen = Len(Text$)
Define CmpLen
Define DecLen

PokeS(*Buffer1, Text$, InpLen, #PB_Ascii)

Debug "Text Original: " + PeekS(*Buffer1, #PB_All, #PB_Ascii)
Debug "Länge Original: " + InpLen

CmpLen = CompressMemory(*Buffer1, InpLen, *Buffer2, 1000, Plugin)
Debug "Länge komprimiert: " + CmpLen

DecLen = UncompressMemory(*Buffer2, CmpLen, *Buffer3, 1000, Plugin)
Debug "Länge dekomprimiert: " + DecLen

Debug "Text dekomprimiert: " + PeekS(*Buffer3, #PB_All, #PB_Ascii)



Re: LZMA-Packer will einen zu kleinen Ausgangspuffer?

Verfasst: 15.11.2013 15:26
von Sauer-RAM
Ja, du hast recht. Der LZMA entpackt zwar korrekt, bei zu großem Ausgangspuffer gibt er jedoch 0 zurück.
Das ist ein Bug. Ob es nun sinnvoll ist die Länge an die zu übermittelnden Daten anzufügen oder nicht.
Bug bleib Bug.