If we're linking against liblzma, allow the decompressor to use up to
1<<30 bytes of memory, which is required for some streams. Also, try to make the taster more discriminating about raw lzma streams. The detection here is still really weak, though; please use xz instead of lzma.
This commit is contained in:
parent
dc7c0661df
commit
84b1d75646
@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "archive.h"
|
#include "archive.h"
|
||||||
|
#include "archive_endian.h"
|
||||||
#include "archive_private.h"
|
#include "archive_private.h"
|
||||||
#include "archive_read_private.h"
|
#include "archive_read_private.h"
|
||||||
|
|
||||||
@ -205,37 +206,100 @@ lzma_bidder_bid(struct archive_read_filter_bidder *self,
|
|||||||
{
|
{
|
||||||
const unsigned char *buffer;
|
const unsigned char *buffer;
|
||||||
ssize_t avail;
|
ssize_t avail;
|
||||||
|
uint32_t dicsize;
|
||||||
|
uint64_t uncompressed_size;
|
||||||
int bits_checked;
|
int bits_checked;
|
||||||
|
|
||||||
(void)self; /* UNUSED */
|
(void)self; /* UNUSED */
|
||||||
|
|
||||||
buffer = __archive_read_filter_ahead(filter, 6, &avail);
|
buffer = __archive_read_filter_ahead(filter, 14, &avail);
|
||||||
if (buffer == NULL)
|
if (buffer == NULL)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
/* First byte of raw LZMA stream is always 0x5d. */
|
/* First byte of raw LZMA stream is commonly 0x5d.
|
||||||
|
* The first byte is a special number, which consists of
|
||||||
|
* three parameters of LZMA compression, a number of literal
|
||||||
|
* context bits(which is from 0 to 8, default is 3), a number
|
||||||
|
* of literal pos bits(which is from 0 to 4, default is 0),
|
||||||
|
* a number of pos bits(which is from 0 to 4, default is 2).
|
||||||
|
* The first byte is made by
|
||||||
|
* (pos bits * 5 + literal pos bit) * 9 + * literal contest bit,
|
||||||
|
* and so the default value in this field is
|
||||||
|
* (2 * 5 + 0) * 9 + 3 = 0x5d.
|
||||||
|
* lzma of LZMA SDK has options to change those parameters.
|
||||||
|
* It means a range of this field is from 0 to 224. And lzma of
|
||||||
|
* XZ Utils with option -e records 0x5e in this field. */
|
||||||
|
/* NOTE: If this checking of the first byte increases false
|
||||||
|
* recognition, we should allow only 0x5d and 0x5e for the first
|
||||||
|
* byte of LZMA stream. */
|
||||||
bits_checked = 0;
|
bits_checked = 0;
|
||||||
if (buffer[0] != 0x5d)
|
if (buffer[0] > (4 * 5 + 4) * 9 + 8)
|
||||||
return (0);
|
return (0);
|
||||||
bits_checked += 8;
|
/* Most likely value in the first byte of LZMA stream. */
|
||||||
|
if (buffer[0] == 0x5d || buffer[0] == 0x5e)
|
||||||
|
bits_checked += 8;
|
||||||
|
|
||||||
/* Second through fifth bytes are dictionary code, stored in
|
/* Sixth through fourteenth bytes are uncompressed size,
|
||||||
* little-endian order. The two least-significant bytes are
|
* stored in little-endian order. `-1' means uncompressed
|
||||||
* always zero. */
|
* size is unknown and lzma of XZ Utils always records `-1'
|
||||||
if (buffer[1] != 0 || buffer[2] != 0)
|
* in this field. */
|
||||||
return (0);
|
uncompressed_size = archive_le64dec(buffer+5);
|
||||||
bits_checked += 16;
|
if (uncompressed_size == (uint64_t)ARCHIVE_LITERAL_LL(-1))
|
||||||
|
bits_checked += 64;
|
||||||
|
|
||||||
/* ??? TODO: Fix this. ??? */
|
/* Second through fifth bytes are dictionary size, stored in
|
||||||
/* NSIS format check uses this, but I've seen tar.lzma
|
* little-endian order. The minimum dictionary size is
|
||||||
* archives where this byte is 0xff, not 0. Can it
|
* 1 << 12(4KiB) which the lzma of LZMA SDK uses with option
|
||||||
* ever be anything other than 0 or 0xff?
|
* -d12 and the maxinam dictionary size is 1 << 27(128MiB)
|
||||||
*/
|
* which the one uses with option -d27.
|
||||||
#if 0
|
* NOTE: A comment of LZMA SDK source code says this dictionary
|
||||||
if (buffer[5] != 0)
|
* range is from 1 << 12 to 1 << 30. */
|
||||||
|
dicsize = archive_le32dec(buffer+1);
|
||||||
|
switch (dicsize) {
|
||||||
|
case 0x00001000:/* lzma of LZMA SDK option -d12. */
|
||||||
|
case 0x00002000:/* lzma of LZMA SDK option -d13. */
|
||||||
|
case 0x00004000:/* lzma of LZMA SDK option -d14. */
|
||||||
|
case 0x00008000:/* lzma of LZMA SDK option -d15. */
|
||||||
|
case 0x00010000:/* lzma of XZ Utils option -0 and -1.
|
||||||
|
* lzma of LZMA SDK option -d16. */
|
||||||
|
case 0x00020000:/* lzma of LZMA SDK option -d17. */
|
||||||
|
case 0x00040000:/* lzma of LZMA SDK option -d18. */
|
||||||
|
case 0x00080000:/* lzma of XZ Utils option -2.
|
||||||
|
* lzma of LZMA SDK option -d19. */
|
||||||
|
case 0x00100000:/* lzma of XZ Utils option -3.
|
||||||
|
* lzma of LZMA SDK option -d20. */
|
||||||
|
case 0x00200000:/* lzma of XZ Utils option -4.
|
||||||
|
* lzma of LZMA SDK option -d21. */
|
||||||
|
case 0x00400000:/* lzma of XZ Utils option -5.
|
||||||
|
* lzma of LZMA SDK option -d22. */
|
||||||
|
case 0x00800000:/* lzma of XZ Utils option -6.
|
||||||
|
* lzma of LZMA SDK option -d23. */
|
||||||
|
case 0x01000000:/* lzma of XZ Utils option -7.
|
||||||
|
* lzma of LZMA SDK option -d24. */
|
||||||
|
case 0x02000000:/* lzma of XZ Utils option -8.
|
||||||
|
* lzma of LZMA SDK option -d25. */
|
||||||
|
case 0x04000000:/* lzma of XZ Utils option -9.
|
||||||
|
* lzma of LZMA SDK option -d26. */
|
||||||
|
case 0x08000000:/* lzma of LZMA SDK option -d27. */
|
||||||
|
bits_checked += 32;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* If a memory usage for encoding was not enough on
|
||||||
|
* the platform where LZMA stream was made, lzma of
|
||||||
|
* XZ Utils automatically decreased the dictionary
|
||||||
|
* size to enough memory for encoding by 1Mi bytes
|
||||||
|
* (1 << 20).*/
|
||||||
|
if (dicsize <= 0x03F00000 && dicsize >= 0x00300000 &&
|
||||||
|
(dicsize & ((1 << 20)-1)) == 0 &&
|
||||||
|
bits_checked == 8 + 64) {
|
||||||
|
bits_checked += 32;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Otherwise dictionary size is unlikely. But it is
|
||||||
|
* possible that someone makes lzma stream with
|
||||||
|
* liblzma/LZMA SDK in one's dictionary size. */
|
||||||
return (0);
|
return (0);
|
||||||
bits_checked += 8;
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* TODO: The above test is still very weak. It would be
|
/* TODO: The above test is still very weak. It would be
|
||||||
* good to do better. */
|
* good to do better. */
|
||||||
@ -304,11 +368,11 @@ xz_lzma_bidder_init(struct archive_read_filter *self)
|
|||||||
*/
|
*/
|
||||||
if (self->code == ARCHIVE_COMPRESSION_XZ)
|
if (self->code == ARCHIVE_COMPRESSION_XZ)
|
||||||
ret = lzma_stream_decoder(&(state->stream),
|
ret = lzma_stream_decoder(&(state->stream),
|
||||||
(1U << 23) + (1U << 21),/* memlimit */
|
(1U << 30),/* memlimit */
|
||||||
LZMA_CONCATENATED);
|
LZMA_CONCATENATED);
|
||||||
else
|
else
|
||||||
ret = lzma_alone_decoder(&(state->stream),
|
ret = lzma_alone_decoder(&(state->stream),
|
||||||
(1U << 23) + (1U << 21));/* memlimit */
|
(1U << 30));/* memlimit */
|
||||||
|
|
||||||
if (ret == LZMA_OK)
|
if (ret == LZMA_OK)
|
||||||
return (ARCHIVE_OK);
|
return (ARCHIVE_OK);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user