shithub: misc

ref: 001e60ea4b45fec9cb40ab8fbbebc334b4d3e9f4
dir: /9legacy/readpng_alloc_chunk_length.diff/

View raw version
--- /n/dump/2021/0627/sys/src/cmd/jpg/readpng.c	Thu Jan 24 23:39:55 2013
+++ /sys/src/cmd/jpg/readpng.c	Tue Jul 13 11:16:50 2021
@@ -10,8 +10,6 @@
 
 enum
 {
-	IDATSIZE = 1000000,
-
 	/* filtering algorithms */
 	FilterNone =	0,	/* new[x][y] = buf[x][y] */
 	FilterSub =	1,	/* new[x][y] = buf[x][y] + new[x-1][y] */ 
@@ -51,7 +49,6 @@
 struct ZlibR
 {
 	Biobuf *io;		/* input buffer */
-	uchar *buf;		/* malloc'ed staging buffer */
 	uchar *p;			/* next byte to decompress */
 	uchar *e;			/* end of buffer */
 	ZlibW *w;
@@ -94,19 +91,28 @@
 }
 
 static int
-getchunk(Biobuf *b, char *type, uchar *d, int m)
+chunklen(Biobuf *b)
+{
+	ulong n;
+
+	uchar buf[4];
+
+	if(Bread(b, buf, 4) != 4 || (n=get4(buf)) > 0x7FFFFFFF)
+		return -1;
+	return n;
+}
+
+static int
+getchunk(Biobuf *b, char *type, uchar *d, int n)
 {
-	uchar buf[8];
+	uchar buf[4];
 	ulong crc = 0, crc2;
-	int n, nr;
+	int nr;
 
-	if(Bread(b, buf, 8) != 8)
+	if(Bread(b, buf, 4) != 4)
 		return -1;
-	n = get4(buf);
-	memmove(type, buf+4, 4);
+	memmove(type, buf, 4);
 	type[4] = 0;
-	if(n > m)
-		sysfatal("getchunk needed %d, had %d", n, m);
 	nr = Bread(b, d, n);
 	if(nr != n)
 		sysfatal("getchunk read %d, expected %d", nr, n);
@@ -117,7 +123,7 @@
 	crc2 = get4(buf);
 	if(crc != crc2)
 		sysfatal("getchunk crc failed");
-	return n;
+	return 0;
 }
 
 static int
@@ -129,25 +135,31 @@
 
 	if(z->p >= z->e){
 	Again:
-		z->p = z->buf;
+		n = chunklen(z->io);
+		if(n < 0)
+			return -1;
+		z->p = pngmalloc(n, 0);
 		z->e = z->p;
-		n = getchunk(z->io, type, z->p, IDATSIZE);
-		if(n < 0 || strcmp(type, "IEND") == 0)
+		getchunk(z->io, type, z->p, n);
+		if(strcmp(type, "IEND") == 0){
+			free(z->p);
 			return -1;
+		}
 		z->e = z->p + n;
 		if(!strcmp(type,"PLTE")){
 			if(n < 3 || n > 3*256 || n%3)
 				sysfatal("invalid PLTE chunk len %d", n);
 			memcpy(z->w->palette, z->p, n);
 			z->w->palsize = 256;
+			free(z->p);
 			goto Again;
 		}
-		if(type[0] & PropertyBit)
+		if(type[0] & PropertyBit){
+			free(z->p);
 			goto Again;  /* skip auxiliary chunks fornow */
-		if(strcmp(type,"IDAT")){
-			sysfatal("unrecognized mandatory chunk %s", type);
-			goto Again;
 		}
+		if(strcmp(type,"IDAT"))
+			sysfatal("unrecognized mandatory chunk %s", type);
 	}
 	return *z->p++;
 }
@@ -388,13 +400,18 @@
 	ZlibR zr;
 	ZlibW zw;
 
-	buf = pngmalloc(IDATSIZE, 0);
+	buf = pngmalloc(sizeof PNGmagic, 0);
 	if(Bread(b, buf, sizeof PNGmagic) != sizeof PNGmagic ||
 	    memcmp(PNGmagic, buf, sizeof PNGmagic) != 0)
 		sysfatal("bad PNGmagic");
+	free(buf);
 
-	n = getchunk(b, type, buf, IDATSIZE);
-	if(n < 13 || strcmp(type,"IHDR") != 0)
+	n = chunklen(b);
+	if(n < 13)
+		sysfatal("wrong IHDR chunk length");
+	buf = pngmalloc(n, 0);
+	getchunk(b, type, buf, n);
+	if(strcmp(type,"IHDR") != 0)
 		sysfatal("missing IHDR chunk");
 	h = buf;
 	dx = get4(h);
@@ -460,7 +477,7 @@
 	memset(&zr, 0, sizeof zr);
 	zr.w = &zw;
 	zr.io = b;
-	zr.buf = buf;
+	free(buf);
 
 	memset(&zw, 0, sizeof zw);
 	if(useadam7)
@@ -483,7 +500,6 @@
 	if(err)
 		sysfatal("inflatezlib %s\n", flateerr(err));
 
-	free(buf);
 	free(zw.scan);
 	free(zw.lastscan);
 	return image;