Hi, Png is using a fix size to allocate space for the chunks. I noticed it because it couldn't open some png files (the chunk size was bigger than IDATSIZE).
This patch removes IDATSIZE and instead makes png to allocate the size of the chunk before reading it. --- sys/src/cmd/jpg/readpng.c Thu Jan 24 23:39:55 2013 +++ /sys/src/cmd/jpg/readpng.c Sat Jul 10 13:09:13 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,26 @@ } static int -getchunk(Biobuf *b, char *type, uchar *d, int m) +chunklen(Biobuf *b) { - uchar buf[8]; + uchar buf[4]; + + if(Bread(b, buf, 4) != 4) + return -1; + return get4(buf); +} + +static int +getchunk(Biobuf *b, char *type, uchar *d, int n) +{ + 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 +121,7 @@ crc2 = get4(buf); if(crc != crc2) sysfatal("getchunk crc failed"); - return n; + return 0; } static int @@ -129,25 +133,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++; } @@ -383,18 +393,23 @@ { char type[5]; int bpc, colorfmt, dx, dy, err, n, nchan, nout, useadam7; - uchar *buf, *h; + uchar *buf, *mag, *h; Rawimage *image; ZlibR zr; ZlibW zw; - buf = pngmalloc(IDATSIZE, 0); - if(Bread(b, buf, sizeof PNGmagic) != sizeof PNGmagic || - memcmp(PNGmagic, buf, sizeof PNGmagic) != 0) + mag = pngmalloc(sizeof PNGmagic, 0); + if(Bread(b, mag, sizeof PNGmagic) != sizeof PNGmagic || + memcmp(PNGmagic, mag, sizeof PNGmagic) != 0) sysfatal("bad PNGmagic"); + free(mag); - n = getchunk(b, type, buf, IDATSIZE); - if(n < 13 || strcmp(type,"IHDR") != 0) + n = chunklen(b); + if(n < 0) + sysfatal("missing IHDR chunk"); + 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 +475,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 +498,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-Mdb82973047397d68fdedb7c3 Delivery options: https://9fans.topicbox.com/groups/9fans/subscription