0

I am trying to zlib inflate a byte array in java, however I am not getting the Z_STREAM_END returned when I inflate it. I have the code exactly the same as some C code I viewed which worked with the same data, sliding window and other parameters (I think?). I am using JZlib. Here is my Java code (dgboff is just the offset of this zlib byte array in a file):

private byte[] z_decompress(byte[] in,int insize,byte[] out,int outsize) {
    ZStream zlib = new ZStream();
    zlib.inflateInit(15);//32k window (2^15)
    zlib.next_in=in;
    zlib.avail_in=insize;
    zlib.next_out=out;
    zlib.avail_out=outsize;
    if(zlib.inflate(JZlib.Z_FINISH)!=JZlib.Z_STREAM_END) {
        System.out.println("Incomplete zlib input at offset "+dgboff+". Compressed size: "+insize+", uncompressed size: "+outsize);
        System.exit(1);
    }
    zlib.inflateEnd();
    return zlib.next_out;
}

and here is the C code, which works (ignore the messy spacing):

 z = calloc(1, sizeof(z_stream)); 
    if(!z) std_err(); 
    z->zalloc = (alloc_func)0; 
    z->zfree  = (free_func)0; 
    z->opaque = (voidpf)0; 
if(inflateInit2(z, 15)) { 
        printf("\nError: initialization error\n"); 
        exit(1); 
 } 
inflateReset(z);

z->next_in   = in;
z->avail_in  = insz;
z->next_out  = out;
z->avail_out = outsz;
if(inflate(z, Z_FINISH) != Z_STREAM_END) {
    printf("\nError: the compressed zlib/deflate input at offset 0x%08x (%d -> %d) is wrong or incomplete\n", (int)g_dbg_offset, (int)insz, (int)outsz);
    exit(1);
}
//gets to here in C

If there is anything I am missing please tell me!

The zlib header for the data I am testing is 0x649d.

  • What *does* it return? – Shawn Jul 23 '20 at 00:24
  • Also, looks like this `ZStream` class is marked as deprecated and you should probably be using a `InflaterInputStream` instead. – Shawn Jul 23 '20 at 00:46
  • Are you certain that both instances are getting the exact same sequence of bytes? `0x649d` is not a zlib header. – Mark Adler Jul 23 '20 at 01:49
  • The C one returns the length of the output bytes, and the bytes are at a pointer. – Lucas Smith Jul 23 '20 at 10:14
  • They definitely do, I changed the header to 0x329d to see if it would change anything (using a hex editor) and C version says there is an error. So it might be doing something to the bytes then? Im going to have a look at the code, maybe the byte array changes there. The C code im looking at is from ttarchext, a game archive extractor. – Lucas Smith Jul 23 '20 at 10:16
  • @MarkAdler here is the hex dump for the complete 'zlib' https://pastebin.com/fxVLRjep – Lucas Smith Jul 23 '20 at 10:27
  • That hex dump, right at the end contains the next bit of data which isnt part of the array, and you can see on the last line it says 0x649d, again. – Lucas Smith Jul 23 '20 at 10:30
  • Sorry for another reply, but If there is something wrong somewhere else in the code, every single compressed chunk in this file starts with 0x649d.DO you know which compressionl algorithm this could belong to,if its not zlib (as It might be something different?) – Lucas Smith Jul 23 '20 at 10:47

1 Answers1

1

Your data is not a zlib stream, and does not have a zlib header. It is a raw deflate stream. Neither of your code examples as shown could have worked. Your "here is the C code, which works" must have been some other C code.

To decompress raw inflate data, you need to use -15 (instead of 15) as the second argument of inflateInit2().

By the way, the deflate compressed data you provided a link for is incomplete. It is correct as far as it goes, but it does not terminate.

Mark Adler
  • 101,978
  • 13
  • 118
  • 158
  • The actual C code wasnt that, I took out the code which I didn't think was affecting anything, here is the full C method:https://pastebin.com/fHuF1LS0 – Lucas Smith Jul 23 '20 at 16:18
  • Ive fixed the code, it works now. One more problem, Im getting -5 (zstream buf error) when I try with -15. Why could this happen? – Lucas Smith Jul 23 '20 at 16:27
  • Probably because you told inflate you had provided a complete deflate stream by using `Z_FINISH`, but inflate discovered that you lied to it, and your deflate stream did not terminate. – Mark Adler Jul 23 '20 at 18:27
  • What can I do to fix this? – Lucas Smith Jul 23 '20 at 22:22
  • Find and provide a complete deflate stream. You don't have to use `Z_FINISH`, and you can use multiple `inflate()` calls to process all of the data, but you eventually need to provide a complete stream in order to get `Z_STREAM_END`. – Mark Adler Jul 23 '20 at 22:35