ref: e4ef7a58376951b392786e9a7cc38e32b7d9cdc6
dir: /9legacy/readpng_alloc_chunk_length.diff/
--- /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;