Bug 9131

Summary: gzip compression level and off-by-one bug
Product: Busybox Reporter: Natanael Copa <ncopa>
Component: OtherAssignee: unassigned
Status: RESOLVED FIXED    
Severity: major CC: busybox-cvs
Priority: P5    
Version: 1.24.x   
Target Milestone: ---   
Hardware: All   
OS: Linux   
Host: Target:
Build:

Description Natanael Copa 2016-08-03 13:52:11 UTC
gzip -9 will output a file that is bigger than when using -1. This appear to be due to the logic in mapping the option to index for gzip_level_config[] being broken, which results in an off-by-one error.

To analyze what is actually going on, try this temp patch:

diff --git a/archival/gzip.c b/archival/gzip.c
index 8f1e4ff..272d49a 100644
--- a/archival/gzip.c
+++ b/archival/gzip.c
@@ -2224,6 +2224,7 @@ int gzip_main(int argc UNUSED_PARAM, char **argv)
        if (opt & 0x7)
                opt |= 1 << 4;
        opt = ffs(opt >> 3);
+       fprintf(stderr, "opt=%x\n", opt);
        max_chain_length = 1 << gzip_level_config[opt].chain_shift;
        good_match       = gzip_level_config[opt].good;
        max_lazy_match   = gzip_level_config[opt].lazy2 * 2;


and run:

  for i in $(seq 1 9); do echo -n "-$i: " ; ./busybox gzip -c -$i /bin/busybox > /dev/null; done

The output gives:
-1: opt=2
-2: opt=2
-3: opt=2
-4: opt=1
-5: opt=2
-6: opt=3
-7: opt=4
-8: opt=5
-9: opt=6

Also note the output of: ./busybox gzip -c ./busybox >/dev/null
opt=4


This means that effectively:
- gzip without options will currently default to compression level 8 instead of level 6 as the comments claims.

- gzip -1|-2|-3 will currently set compression level to level 6.

- gzip -4|-5|-6|-7|-8 will currently set compression level 5-9

- gzip -9 (with opt=6) will result in out-of-bounds access of gzip_level_config[] array
Comment 1 Denys Vlasenko 2016-08-14 23:32:51 UTC
Fixed in git.