Subject: Re: bug#56247: inflate fails to reject invalid distance
From: Paul Eggert <[email-masked]>
To: "Adler, Mark" <[email-masked]>
Cc: Young Mo Kang <[email-masked]>, GNU bug 56247 <[email-masked]>
Date: Tue, 28 Jun 2022 22:44:57 -0500
List-Id: <debbugs-submit.debbugs.gnu.org>

On 6/27/22 16:29, Adler, Mark wrote:
> Paul,
>
> gzip should reject invalid inflate input. The patch below does that.
>
Thanks for the quick patch. I installed that, along with Young Mo Kang's 
test case, as per the attached.
From 4b58eee79d3af3647adb4c78938d83970e788975 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@trombone>
Date: Tue, 28 Jun 2022 22:30:08 -0500
Subject: [PATCH 1/2] gzip: detect invalid input

Problem reported by Young Mo Kang and fix from Mark Adler (Bug#56247).
* inflate.c: Include stdbool.h.
(fresh): New static var.
* inflate.c (flush_output): Clear it.
(inflate): Set it.
(inflate_codes): Fail if the offset is outside a fresh input window.
---
 inflate.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/inflate.c b/inflate.c
index 199a935..4fbb1be 100644
--- a/inflate.c
+++ b/inflate.c
@@ -117,6 +117,7 @@
 
 #include <config.h>
 
+#include <stdbool.h>
 #include <stdlib.h>
 
 #include "tailor.h"
@@ -153,8 +154,9 @@ static int huft_free (struct huft *);
    "uch *slide;" and then malloc'ed in the latter case.  The definition
    must be in unzip.h, included above. */
 /* unsigned wp;             current position in slide */
+static bool fresh;
 #define wp outcnt
-#define flush_output(w) (wp=(w),flush_window())
+#define flush_output(w) (fresh = false, wp = (w), flush_window ())
 
 /* Tables for deflate from PKZIP's appnote.txt. */
 static unsigned border[] = {    /* Order of the bit length code lengths */
@@ -582,6 +584,8 @@ inflate_codes(struct huft *tl, struct huft *td, int bl, int bd)
       NEEDBITS(e)
       d = w - t->v.n - ((unsigned)b & mask_bits[e]);
       DUMPBITS(e)
+      if (fresh && w <= d)
+	return 1;
       Tracevv ((stderr, "\\[%u,%u]", w - d, n));
 
       /* do the copy */
@@ -964,6 +968,7 @@ inflate(void)
   wp = 0;
   bk = 0;
   bb = 0;
+  fresh = true;

   /* decompress until the last block */
-- 
2.25.1

From 3e32e3c3583e5249394d45f7a1f9bf3156c8d32f Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@trombone>
Date: Tue, 28 Jun 2022 22:32:09 -0500
Subject: [PATCH 2/2] gzip: test invalid-input bug

* NEWS: Mention the bug.
* tests/unpack-invalid: Test for the bug.
---
 NEWS                 | 6 ++++++
 tests/unpack-invalid | 1 +
 2 files changed, 7 insertions(+)

diff --git a/NEWS b/NEWS
index 1074c66..364811a 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,12 @@ GNU gzip NEWS                                    -*- outline -*-
 
 * Noteworthy changes in release ?.? (????-??-??) [?]
 
+** Bug fixes
+
+  'gzip -d' no longer fails to report invalid compressed data
+  that uses a dictionary distance outside the input window.
+  [bug present since the beginning]
+
 
 * Noteworthy changes in release 1.12 (2022-04-07) [stable]
 
diff --git a/tests/unpack-invalid b/tests/unpack-invalid
index 14984a1..f659aa8 100755
--- a/tests/unpack-invalid
+++ b/tests/unpack-invalid
@@ -22,6 +22,7 @@
 
 fail=0
 for input in \
+  '\37\213\b\0\0\0\0\0\0\3s\212\31204t\214T\v\216\274)q)\210\201A\341\377\377\37\f\23\30B\4\30\30\27+\\aih`hpd8\300\252\320\300\310\300\340\300\300\330\340\350\300\261\200!$\331M\201!\205q\341\253\214o+LM\331W\2300\310-|\305\300\256r\341\213\377\357\312\266$N\16E6\206\24\206\365\346\22\253\332L3l\366\334]]\244\275lM\355I\241;\377\343x\23\26M9\330\252\375\261\\%%\270\225\223wb\257\252\2\302\5\336\377\205\302\30\30\30\243$\03700010214\b0\260002p.`0dv\270 5o\371+7\237\366%%WL\246YMZ\234\367FN\277{\247\322\34\r\17\325\377\235\332\20\177\0\0@\23a\3\315\0\0\0' \
   '\037\036\000\000\037\213\010\000\000\000\000\000\002\003\036\000\000\000\002\003\037\213\010\000\000\000\000\000\002\003\355\301\001\015\000\000\000\302\240\037\000\302\240\037\213\010\000\000\000\000\000\002\003\355\301' \
   '\037\213\010\000\000\000\000\000\002\003\355\301\001\015\000\000\000\302\240\076\366\017\370\036\016\030\000\000\000\000\000\000\000\000\000\034\010\105\140\104\025\020\047\000\000\037\036\016\030\000\000\000'; do
 
-- 
2.25.1