From 608688b3088bb10186700a38b459443d649d6325 Mon Sep 17 00:00:00 2001
From: Andy Green <andy@warmcat.com>
Date: Mon, 11 Jul 2022 17:51:19 +0100
Subject: [PATCH] upng-gzip: fuzz: size temp arrays to worst huff size

https://oss-fuzz.com/testcase-detail/5964400971874304

The original upng code this is based on just sizes the temp buffers for 15,
but the trees can come in 19, 32, or 288 lengths.  Set the buffer sizes for
the worst case.

Add some asserts to help catch any further problems more directly.
---
 lib/misc/upng-gzip.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/lib/misc/upng-gzip.c b/lib/misc/upng-gzip.c
index 722fa3a0..a59998a5 100644
--- a/lib/misc/upng-gzip.c
+++ b/lib/misc/upng-gzip.c
@@ -242,19 +242,32 @@ huffman_tree_init(htree_t *tree, huff_t *buffer, uint16_t numcodes,
 static lws_stateful_ret_t
 huffman_tree_create_lengths(htree_t *tree, const unsigned *bitlen)
 {
-	unsigned int tree1d[MAX_SYMBOLS], blcount[MAX_BIT_LENGTH],
-		     nextcode[MAX_BIT_LENGTH + 1];
-	unsigned int bits, n, i, nodefilled = 0, treepos = 0;
+	unsigned int tree1d[NUM_DEFLATE_CODE_SYMBOLS], /* sized to worst */
+		     blcount[NUM_DEFLATE_CODE_SYMBOLS], /* sized to worst */
+		     nextcode[MAX_BIT_LENGTH + 1], bits, n, i,
+		     nodefilled = 0, treepos = 0;
 
 	memset(blcount, 0, sizeof(blcount));
 	memset(nextcode, 0, sizeof(nextcode));
 
-	for (bits = 0; bits < tree->numcodes; bits++)
+	assert(tree->numcodes <= LWS_ARRAY_SIZE(blcount));
+
+	for (bits = 0; bits < tree->numcodes; bits++) {
+		/* any counts exceeding our private buffer length are fatal */
+		if (bitlen[bits] >= LWS_ARRAY_SIZE(blcount))
+			return LWS_SRET_FATAL + 1;
+
 		blcount[bitlen[bits]]++;
+	}
+
+	assert(tree->maxbitlen && tree->maxbitlen - 1u <= LWS_ARRAY_SIZE(blcount));
+	assert(tree->maxbitlen - 1u <= LWS_ARRAY_SIZE(nextcode));
 
 	for (bits = 1; bits <= (unsigned int)tree->maxbitlen; bits++)
 		nextcode[bits] = (nextcode[bits - 1] + blcount[bits - 1]) << 1;
 
+	assert(tree->numcodes <= LWS_ARRAY_SIZE(tree1d));
+
 	for (n = 0; n < tree->numcodes; n++)
 		if (bitlen[n])
 			tree1d[n] = nextcode[bitlen[n]]++;