Author: cazfi Date: Tue Sep 22 21:17:11 2015 New Revision: 29954 URL: http://svn.gna.org/viewcvs/freeciv?rev=29954&view=rev Log: Increase xz decompression memory usage limit to 65Mb
Reported by Christian Knoke <chrisk> See bug #23891 Modified: branches/S2_6/utility/ioz.c Modified: branches/S2_6/utility/ioz.c URL: http://svn.gna.org/viewcvs/freeciv/branches/S2_6/utility/ioz.c?rev=29954&r1=29953&r2=29954&view=diff ============================================================================== --- branches/S2_6/utility/ioz.c (original) +++ branches/S2_6/utility/ioz.c Tue Sep 22 21:17:11 2015 @@ -74,12 +74,15 @@ #define XZ_DECODER_TEST_SIZE (4*1024) /* 4kb */ /* In my tests 7Mb proved to be not enough and with 10Mb decompression - succeeded. */ -#define XZ_DECODER_MEMLIMIT (15*1024*1024) /* 15Mb */ + succeeded in typical case. */ +#define XZ_DECODER_MEMLIMIT (65*1024*1024) /* 65Mb */ +#define XZ_DECODER_MEMLIMIT_STEP (25*1024*1024) /* Increase 25Mb at a time */ +#define XZ_DECODER_MEMLIMIT_FINAL (100*1024*1024) /* 100Mb */ struct xz_struct { lzma_stream stream; int out_index; + uint64_t memlimit; /* liblzma bug workaround. This is what stream.avail_out should be, calculated correctly. Used only when reading file. */ @@ -104,6 +107,7 @@ }; static bool xz_outbuffer_to_file(fz_FILE *fp, lzma_action action); +static void xz_action(fz_FILE *fp, lzma_action action); #endif /* FREECIV_HAVE_LIBLZMA */ @@ -278,9 +282,10 @@ #ifdef FREECIV_HAVE_LIBLZMA /* Try to open as xz file */ + fp->u.xz.memlimit = XZ_DECODER_MEMLIMIT; memset(&fp->u.xz.stream, 0, sizeof(lzma_stream)); fp->u.xz.error = lzma_stream_decoder(&fp->u.xz.stream, - XZ_DECODER_MEMLIMIT, + fp->u.xz.memlimit, LZMA_CONCATENATED); if (fp->u.xz.error != LZMA_OK) { free(fp); @@ -310,7 +315,7 @@ fp->u.xz.hack_byte_used = FALSE; action = LZMA_FINISH; } - fp->u.xz.error = lzma_code(&fp->u.xz.stream, action); + xz_action(fp, action); if (fp->u.xz.error == LZMA_OK || fp->u.xz.error == LZMA_STREAM_END) { fp->method = FZ_XZ; fp->u.xz.out_index = 0; @@ -604,7 +609,7 @@ } else { fp->u.xz.stream.next_out = fp->u.xz.out_buf; fp->u.xz.stream.avail_out = PLAIN_FILE_BUF_SIZE; - fp->u.xz.error = lzma_code(&fp->u.xz.stream, LZMA_FINISH); + xz_action(fp, LZMA_FINISH); fp->u.xz.out_index = 0; fp->u.xz.out_avail = fp->u.xz.stream.total_out - fp->u.xz.total_read; @@ -625,7 +630,7 @@ } else { action = LZMA_FINISH; } - fp->u.xz.error = lzma_code(&fp->u.xz.stream, action); + xz_action(fp, action); fp->u.xz.out_avail = fp->u.xz.stream.total_out - fp->u.xz.total_read; fp->u.xz.out_index = 0; @@ -729,6 +734,28 @@ return TRUE; } + +/*************************************************************** + Helper function to do given decompression action. +***************************************************************/ +static void xz_action(fz_FILE *fp, lzma_action action) +{ + fp->u.xz.error = lzma_code(&fp->u.xz.stream, action); + if (fp->u.xz.error != LZMA_MEMLIMIT_ERROR) { + return; + } + + while (fp->u.xz.error == LZMA_MEMLIMIT_ERROR + && fp->u.xz.memlimit < XZ_DECODER_MEMLIMIT_FINAL) { + fp->u.xz.memlimit += XZ_DECODER_MEMLIMIT_STEP; + if (fp->u.xz.memlimit > XZ_DECODER_MEMLIMIT_FINAL) { + fp->u.xz.memlimit = XZ_DECODER_MEMLIMIT_FINAL; + } + fp->u.xz.error = lzma_memlimit_set(&fp->u.xz.stream, fp->u.xz.memlimit); + } + + fp->u.xz.error = lzma_code(&fp->u.xz.stream, action); +} #endif /* FREECIV_HAVE_LIBLZMA */ /*************************************************************** _______________________________________________ Freeciv-commits mailing list Freeciv-commits@gna.org https://mail.gna.org/listinfo/freeciv-commits