From: Mike Alexander Date: Thu, 28 Nov 2013 23:21:23 +0800 Subject: Fix a bug loading some compressed files For https://bugzilla.gnome.org/show_bug.cgi?id=712528 Related to https://bugzilla.redhat.com/show_bug.cgi?id=877567 There is a bug in xzlib.c which causes certain compressed XML files to fail to load correctly. The code in xz_decomp which attempts to verify the checksum and length of the expanded data fails if the checksum or length at the end of the file crosses a 1024 byte boundary. It calls gz_next4 to get those two values. This function uses the stream state in state->zstrm, but calls xz_avail which uses the state->strm stream info. This causes gz_next4 to signal a premature EOF if the data it is fetching crosses a 1024 byte boundary. --- xzlib.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/xzlib.c b/xzlib.c index 928bd17..cd045fa 100644 --- a/xzlib.c +++ b/xzlib.c @@ -245,6 +245,20 @@ xz_avail(xz_statep state) return 0; } +#ifdef HAVE_ZLIB_H +static int +xz_avail_zstrm(xz_statep state) +{ + int ret; + state->strm.avail_in = state->zstrm.avail_in; + state->strm.next_in = state->zstrm.next_in; + ret = xz_avail(state); + state->zstrm.avail_in = (uInt) state->strm.avail_in; + state->zstrm.next_in = (Bytef *) state->strm.next_in; + return ret; +} +#endif + static int is_format_xz(xz_statep state) { @@ -314,6 +328,10 @@ is_format_lzma(xz_statep state) #define NEXT() ((strm->avail_in == 0 && xz_avail(state) == -1) ? -1 : \ (strm->avail_in == 0 ? -1 : \ (strm->avail_in--, *(strm->next_in)++))) +/* Same thing, but from zstrm */ +#define NEXTZ() ((strm->avail_in == 0 && xz_avail_zstrm(state) == -1) ? -1 : \ + (strm->avail_in == 0 ? -1 : \ + (strm->avail_in--, *(strm->next_in)++))) /* Get a four-byte little-endian integer and return 0 on success and the value in *ret. Otherwise -1 is returned and *ret is not modified. */ @@ -324,10 +342,10 @@ gz_next4(xz_statep state, unsigned long *ret) unsigned long val; z_streamp strm = &(state->zstrm); - val = NEXT(); - val += (unsigned) NEXT() << 8; - val += (unsigned long) NEXT() << 16; - ch = NEXT(); + val = NEXTZ(); + val += (unsigned) NEXTZ() << 8; + val += (unsigned long) NEXTZ() << 16; + ch = NEXTZ(); if (ch == -1) return -1; val += (unsigned long) ch << 24;