unlzma: fix erroneous "while" instead of "if". Closes 4682
authorDenys Vlasenko <vda.linux@googlemail.com>
Mon, 9 Jan 2017 12:55:11 +0000 (13:55 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Mon, 9 Jan 2017 13:02:55 +0000 (14:02 +0100)
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>
archival/libarchive/decompress_unlzma.c

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