From bc5915e2dec741236df51d513229f882430962f3 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 19 Sep 2020 19:39:42 -0700 Subject: [PATCH] Fixed unsigned integer overflow ASAN error when hash_head > s->strstart. zlib-ng/deflate_medium.c:244:47: runtime error: unsigned integer overflow: 58442 - 58452 cannot be represented in type 'unsigned int' Co-authored-by: Mika Lindqvist Co-authored-by: Hans Kristian Rosbach --- deflate_fast.c | 6 +++++- deflate_medium.c | 8 ++++++-- deflate_quick.c | 9 +++++---- deflate_slow.c | 4 +++- 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/deflate_fast.c b/deflate_fast.c index a88e6027..14718ba1 100644 --- a/deflate_fast.c +++ b/deflate_fast.c @@ -19,6 +19,7 @@ Z_INTERNAL block_state deflate_fast(deflate_state *s, int flush) { Pos hash_head; /* head of the hash chain */ int bflush = 0; /* set if current block must be flushed */ + int64_t dist; uint32_t match_len = 0; for (;;) { @@ -41,10 +42,13 @@ Z_INTERNAL block_state deflate_fast(deflate_state *s, int flush) { */ if (s->lookahead >= MIN_MATCH) { hash_head = functable.quick_insert_string(s, s->strstart); + dist = (int64_t)s->strstart - hash_head; + /* Find the longest match, discarding those <= prev_length. * At this point we have always match length < MIN_MATCH */ - if (hash_head != 0 && s->strstart - hash_head <= MAX_DIST(s)) { + + if (dist <= MAX_DIST(s) && dist > 0) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). diff --git a/deflate_medium.c b/deflate_medium.c index a5b1b9a1..27ca1905 100644 --- a/deflate_medium.c +++ b/deflate_medium.c @@ -171,6 +171,7 @@ Z_INTERNAL block_state deflate_medium(deflate_state *s, int flush) { for (;;) { Pos hash_head = 0; /* head of the hash chain */ int bflush = 0; /* set if current block must be flushed */ + int64_t dist; /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes @@ -208,7 +209,8 @@ Z_INTERNAL block_state deflate_medium(deflate_state *s, int flush) { * At this point we have always match_length < MIN_MATCH */ - if (hash_head != 0 && s->strstart - hash_head <= MAX_DIST(s)) { + dist = (int64_t)s->strstart - hash_head; + if (dist <= MAX_DIST(s) && dist > 0) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). @@ -241,7 +243,9 @@ Z_INTERNAL block_state deflate_medium(deflate_state *s, int flush) { /* Find the longest match, discarding those <= prev_length. * At this point we have always match_length < MIN_MATCH */ - if (hash_head != 0 && s->strstart - hash_head <= MAX_DIST(s)) { + + dist = (int64_t)s->strstart - hash_head; + if (dist <= MAX_DIST(s) && dist > 0) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). diff --git a/deflate_quick.c b/deflate_quick.c index 3ed934cb..268cce80 100644 --- a/deflate_quick.c +++ b/deflate_quick.c @@ -45,7 +45,8 @@ extern const ct_data static_dtree[D_CODES]; Z_INTERNAL block_state deflate_quick(deflate_state *s, int flush) { Pos hash_head; - unsigned dist, match_len, last; + int64_t dist; + unsigned match_len, last; last = (flush == Z_FINISH) ? 1 : 0; @@ -85,9 +86,9 @@ Z_INTERNAL block_state deflate_quick(deflate_state *s, int flush) { if (LIKELY(s->lookahead >= MIN_MATCH)) { hash_head = functable.quick_insert_string(s, s->strstart); - dist = s->strstart - hash_head; + dist = (int64_t)s->strstart - hash_head; - if (dist > 0 && dist < MAX_DIST(s)) { + if (dist <= MAX_DIST(s) && dist > 0) { match_len = functable.compare258(s->window + s->strstart, s->window + hash_head); if (match_len >= MIN_MATCH) { @@ -96,7 +97,7 @@ Z_INTERNAL block_state deflate_quick(deflate_state *s, int flush) { check_match(s, s->strstart, hash_head, match_len); - zng_tr_emit_dist(s, static_ltree, static_dtree, match_len - MIN_MATCH, dist); + zng_tr_emit_dist(s, static_ltree, static_dtree, match_len - MIN_MATCH, (uint32_t)dist); s->lookahead -= match_len; s->strstart += match_len; continue; diff --git a/deflate_slow.c b/deflate_slow.c index ea5eed84..cac8a962 100644 --- a/deflate_slow.c +++ b/deflate_slow.c @@ -17,6 +17,7 @@ Z_INTERNAL block_state deflate_slow(deflate_state *s, int flush) { Pos hash_head; /* head of hash chain */ int bflush; /* set if current block must be flushed */ + int64_t dist; uint32_t match_len; /* Process the input block. */ @@ -47,8 +48,9 @@ Z_INTERNAL block_state deflate_slow(deflate_state *s, int flush) { */ s->prev_match = (Pos)s->match_start; match_len = MIN_MATCH-1; + dist = (int64_t)s->strstart - hash_head; - if (hash_head != 0 && s->prev_length < s->max_lazy_match && s->strstart - hash_head <= MAX_DIST(s)) { + if (dist <= MAX_DIST(s) && dist > 0 && s->prev_length < s->max_lazy_match) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). -- 2.47.2