Closed Bug 775743 Opened 12 years ago Closed 12 years ago

lzma ByteArray return out of memory when run on swf generated from other lzma algorithm

Categories

(Tamarin Graveyard :: Virtual Machine, defect)

x86
macOS
defect
Not set
normal

Tracking

(Not tracked)

RESOLVED WORKSFORME

People

(Reporter: dschaffe, Unassigned)

References

Details

Attachments

(5 files)

This swf was compressed with lzma from flashpro.  The swf is from a customer.  

running simple code the attached swf in the shell produces an out of memory error.

import avmplus.File
import flash.utils.ByteArray
import flash.utils.CompressionAlgorithm
var bytearray:ByteArray=File.readByteArray("test.swf");
bytearray.uncompress(CompressionAlgorithm.LZMA);
print(bytearray);

$ avmshell /Users/dschaffe/bugs/3283218/test.abc
Error: Error #1000: The system is out of memory.
	at flash.utils::ByteArray/_uncompress()
	at flash.utils::ByteArray/uncompress()
	at global$init()
Depends on: 763519
I also generated an empty swf using Flash Authoring (lzma) note: lzma is not the default compression, you have enable it with  Publish Settings... Advanced/Compress Movie=LZMA (default is Deflate)

I created a byte array inside the source to make the test simpler.  See the attachment.
$ avmshell bug775743-2.abc
Error: Error #1000: The system is out of memory.
	at flash.utils::ByteArray/_uncompress()
	at flash.utils::ByteArray/uncompress()
	at global$init()
Regarding these two compressed you've attached: Have you confirmed that they are decompressable via the 7zip tool?

This gets at the heart of my question: I have no reason to belive that a swf compressed via Flash Authoring follows the format used by a raw 7zip lzma-compressed file.  (I'm happy to be proven wrong on this point.)
Attachment #644023 - Attachment description: reproducible testcase → script A v1: reproducible testcase
Attachment #644024 - Attachment description: simple lzma compressed swf → swf S v1: simple lzma compressed swf
Attachment #644306 - Attachment description: testcase generating blank lzma swf in Authoring CS6 → script B v1: testcase generating blank lzma swf in Authoring CS6
(In reply to Felix S Klock II from comment #5)
> Regarding these two compressed you've attached: Have you confirmed that they
> are decompressable via the 7zip tool?
> 
> This gets at the heart of my question: I have no reason to belive that a swf
> compressed via Flash Authoring follows the format used by a raw 7zip
> lzma-compressed file.  (I'm happy to be proven wrong on this point.)

Here's a concrete example of what I am talking about.  Here is me running LZMA.jar to compress and then decompress some input.

% java -jar ~/Dev/Lzma/LZMA.jar e hello-input.txt hello-compressed.lz
% java -jar ~/Dev/Lzma/LZMA.jar d hello-compressed.lz hello-output.txt
% ls -lh hello-input.txt hello-compressed.lz 
-rw-r--r--  1 fklockii  staff   253B Jul 20 11:39 hello-compressed.lz
-rw-r--r--  1 fklockii  staff   349B Jul 20 11:37 hello-input.txt
% diff hello-input.txt hello-output.txt 
%

Here is me running LZMA.jar to attempt to decompress the supposedly LZMA-compressed input: 

% java -jar ~/Dev/Lzma/LZMA.jar d test.swf output

LZMA (Java) 4.61  2008-11-23

Exception in thread "main" java.lang.Exception: Incorrect stream properties
	at SevenZip.LzmaAlone.main(LzmaAlone.java:233)



This is evidence that the Flash Authoring SWF-compression has *nothing* to do with raw compression.  This difference in behavior is *expected*.  I vote: "Not a bug"
(this is the third-party LZMA.jar I used for my earlier demonstration)
This content appears to correctly decompress for me using LZMA.jar:

% java -jar ~/Dev/Bugz/bugz775743/LZMA.jar d hello.lzma hello.lzma.dec

LZMA (Java) 4.61  2008-11-23

% cat hello.lzma.dec 
Hello World !


So now to see how ByteArray handles it.
(In reply to Felix S Klock II from comment #8)
> Created attachment 645294 [details]
> lzma H: hello.lzma, developered supplied 7-zip compressed input
> 
> This content appears to correctly decompress for me using LZMA.jar:
> 
> % java -jar ~/Dev/Bugz/bugz775743/LZMA.jar d hello.lzma hello.lzma.dec
> 
> LZMA (Java) 4.61  2008-11-23
> 
> % cat hello.lzma.dec 
> Hello World !
> 
> 
> So now to see how ByteArray handles it.

  % ~/Dev/tamarin-redux/objdir-ged64/shell/avmshell -repl
  avmplus interactive shell
  Type '?' for help
  
  > import avmplus.File; var F = File;
  [class File]
  > var b = F.readByteArray("hello.lzma");
  ]$IoÈ_æՊ_x²@ì
  > b.uncompress("lzma")
  > b
  Hello World !
  
  > 

So this looks fine to me.  I'm not sure what the end-developer was doing on their end, but this decompresses fine for me.
I also confirmed the hello.lz the customer provided.   The first time I ran I got Error #2038 then I realized I did:
bytearray.uncompress()   instead of:  bytearray.uncompress("lzma") 

The default compression is "deflate/zlib".  I wonder if the user made the same mistake?  I want to try a few more examples and use a swf instead of an abc and also test a few more platforms before closing the bug.  It looks like everything is working.
Here is the note on how to convert a swf-lzma to a 7z-lzma so it works with ByteArray.uncompress("lzma"):

The swf lzma format can be converted into the 7z lzma format (used by ByteArray.uncompress) format by updating the header.  

The swf lzma header is:
bytes 0-3: ZWS+version
bytes 4-7: uncompressed length (includes ZWS+version+uncompressed length (0-7)
bytes 8-11: compressed length 
bytes 12-16: lzma properties
bytes 17-(n-6): compressed data
bytes (n-6)-n: 6 byte end marker

The 7z lzma format is:
bytes 0-4: lzma properties
bytes 5-12: uncompressed length (take the swf lzma length  - 8 (don't include bytes 0-7, ZWS/version + uncompressed length))
bytes 13-n: compressed data

Here is a sample update to abcdump.as to show how the conversion can be implemented:

var data:ByteArray = File.readByteArray(file)
data.endian = "littleEndian"
var version:uint = data.readUnsignedInt()
switch (version&0xffffffff) {
...
case 90|87<<8|83<<16: // SWZ = lzma compressed
            if (doDecompressOnly)
               System.exit(0)
            udata=new ByteArray
            udata.endian = "littleEndian"
            var ptr;
            // put lzma properties in 0-4
            for (ptr=0;ptr<5;ptr++) {
                udata[ptr]=data[12+ptr]
            }
            // calculate uncompressed length, subtract 8 (swf header)
            var scriptlen:uint=data[4]+(data[5]<<8)+(data[6]<<16)+(data[7]<<24)-8;

            // write lzma properties bytes: 0-4
            for (ptr=0;ptr<4;ptr++) {
                udata[5+ptr]=data[8+ptr]
            }

            // write the uncompressed length: 5-8
            udata[5]=scriptlen&0xFF;
            udata[6]=(scriptlen>>8) & 0xFF;
            udata[7]=(scriptlen>>16) & 0xFF;
            udata[8]=(scriptlen>>24) & 0xFF;

            // add 4 extra 0 to compressed length: 9-12
            for (ptr=0;ptr<4;ptr++) {
                udata[9+ptr]=0
            }

            data.position = 17
            data.readBytes(udata,13,data.length-data.position)

            udata.position=0
            csize = udata.length
            udata.uncompress(CompressionAlgorithm.LZMA)
            infoPrint("decompressed swf "+csize+" -> "+udata.length)
            /*var swf:Swf =*/ new Swf(udata)
            break
I confirmed both the cases in the flash player.  The cases were uncompressing hello.lz and testlzma.swf (lzma encoded swf from flash authoring CS6) in the player.  Both cases worked.  Marking the bug as WORKSFORME.  It is not a bug.
Status: NEW → RESOLVED
Closed: 12 years ago
Resolution: --- → WORKSFORME
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: