| From 6a043145ca6e9c55184013841a67b2fef87e44c0 Mon Sep 17 00:00:00 2001 |
| From: Mark Adler <madler@alumni.caltech.edu> |
| Date: Wed, 21 Sep 2016 23:35:50 -0700 |
| Subject: [PATCH] Remove offset pointer optimization in inftrees.c. |
| |
| inftrees.c was subtracting an offset from a pointer to an array, |
| in order to provide a pointer that allowed indexing starting at |
| the offset. This is not compliant with the C standard, for which |
| the behavior of a pointer decremented before its allocated memory |
| is undefined. Per the recommendation of a security audit of the |
| zlib code by Trail of Bits and TrustInSoft, in support of the |
| Mozilla Foundation, this tiny optimization was removed, in order |
| to avoid the possibility of undefined behavior. |
| |
| CVE: CVE-2016-9840 |
| Upstream-Status: Backport |
| Signed-off-by: Anuj Mittal <anuj.mittal@intel.com> |
| --- |
| inftrees.c | 18 ++++++++---------- |
| 1 file changed, 8 insertions(+), 10 deletions(-) |
| |
| diff --git a/zlib/inftrees.c b/zlib/inftrees.c |
| index 22fcd666..0d2670d5 100644 |
| --- a/zlib/inftrees.c |
| +++ b/zlib/inftrees.c |
| @@ -54,7 +54,7 @@ unsigned short FAR *work; |
| code FAR *next; /* next available space in table */ |
| const unsigned short FAR *base; /* base value table to use */ |
| const unsigned short FAR *extra; /* extra bits table to use */ |
| - int end; /* use base and extra for symbol > end */ |
| + unsigned match; /* use base and extra for symbol >= match */ |
| unsigned short count[MAXBITS+1]; /* number of codes of each length */ |
| unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ |
| static const unsigned short lbase[31] = { /* Length codes 257..285 base */ |
| @@ -181,19 +181,17 @@ unsigned short FAR *work; |
| switch (type) { |
| case CODES: |
| base = extra = work; /* dummy value--not used */ |
| - end = 19; |
| + match = 20; |
| break; |
| case LENS: |
| base = lbase; |
| - base -= 257; |
| extra = lext; |
| - extra -= 257; |
| - end = 256; |
| + match = 257; |
| break; |
| default: /* DISTS */ |
| base = dbase; |
| extra = dext; |
| - end = -1; |
| + match = 0; |
| } |
| |
| /* initialize state for loop */ |
| @@ -216,13 +214,13 @@ unsigned short FAR *work; |
| for (;;) { |
| /* create table entry */ |
| here.bits = (unsigned char)(len - drop); |
| - if ((int)(work[sym]) < end) { |
| + if (work[sym] + 1 < match) { |
| here.op = (unsigned char)0; |
| here.val = work[sym]; |
| } |
| - else if ((int)(work[sym]) > end) { |
| - here.op = (unsigned char)(extra[work[sym]]); |
| - here.val = base[work[sym]]; |
| + else if (work[sym] >= match) { |
| + here.op = (unsigned char)(extra[work[sym] - match]); |
| + here.val = base[work[sym] - match]; |
| } |
| else { |
| here.op = (unsigned char)(32 + 64); /* end of block */ |