By the way, the lenght should be checked to not exceed 0x7FFFFFFF
so a corrupt chunk can be detected early.


--- /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;

------------------------------------------
9fans: 9fans
Permalink: 
https://9fans.topicbox.com/groups/9fans/T4a714ed14c50767a-M13a5098cf3af92b1671aa59c
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription

Reply via email to