unlzma: fix erroneous "while" instead of "if". Closes 4682

These parts of the code essentially check whether
stepping back by rep0 goes negative or not.

LZMA SDK from lzma1604.7z has the following in the corresponding places:

... = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]

Clearly, not loop here.

Technically, "while" here works: if condition is false (because pos
underflowed), it iterates once, adds header.dict_size (a.k.a. dicBufSize),
this makes pos positive but smaller than header.dict_size, and loop exits.

Now we'll just check for negative result of subtraction, which is less code:

function                                             old     new   delta
unpack_lzma_stream                                  2659    2641     -18

(I hope 2 Gbyte+ dictionaries won't be in use soon).

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2017-01-09 13:55:11 +01:00
parent 8c1d857d25
commit 3989e5adf4

View File

@ -278,9 +278,10 @@ unpack_lzma_stream(transformer_state_t *xstate)
if (state >= LZMA_NUM_LIT_STATES) { if (state >= LZMA_NUM_LIT_STATES) {
int match_byte; int match_byte;
uint32_t pos = buffer_pos - rep0; uint32_t pos;
while (pos >= header.dict_size) pos = buffer_pos - rep0;
if ((int32_t)pos < 0)
pos += header.dict_size; pos += header.dict_size;
match_byte = buffer[pos]; match_byte = buffer[pos];
do { do {
@ -336,9 +337,11 @@ unpack_lzma_stream(transformer_state_t *xstate)
); );
if (!rc_is_bit_1(rc, prob2)) { if (!rc_is_bit_1(rc, prob2)) {
#if ENABLE_FEATURE_LZMA_FAST #if ENABLE_FEATURE_LZMA_FAST
uint32_t pos = buffer_pos - rep0; uint32_t pos;
state = state < LZMA_NUM_LIT_STATES ? 9 : 11; state = state < LZMA_NUM_LIT_STATES ? 9 : 11;
while (pos >= header.dict_size)
pos = buffer_pos - rep0;
if ((int32_t)pos < 0)
pos += header.dict_size; pos += header.dict_size;
previous_byte = buffer[pos]; previous_byte = buffer[pos];
goto one_byte1; goto one_byte1;
@ -432,7 +435,7 @@ unpack_lzma_stream(transformer_state_t *xstate)
IF_NOT_FEATURE_LZMA_FAST(string:) IF_NOT_FEATURE_LZMA_FAST(string:)
do { do {
uint32_t pos = buffer_pos - rep0; uint32_t pos = buffer_pos - rep0;
while (pos >= header.dict_size) if ((int32_t)pos < 0)
pos += header.dict_size; pos += header.dict_size;
previous_byte = buffer[pos]; previous_byte = buffer[pos];
IF_NOT_FEATURE_LZMA_FAST(one_byte2:) IF_NOT_FEATURE_LZMA_FAST(one_byte2:)