summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Bowler <jbowler@acm.org>2016-05-29 12:44:22 -0700
committerJohn Bowler <jbowler@acm.org>2016-05-29 12:44:22 -0700
commit6a1a8df343a7db4e2d395825f265d69dfdbf69e1 (patch)
tree2db147f38ae6e0e8d75b70df0ae4d550b8d76b56
parent6fb875a54ea8a950111a4eac6100d01d6025a4ac (diff)
downloadlibpng-6a1a8df343a7db4e2d395825f265d69dfdbf69e1.tar.gz
Backported pngvalid changes from libpng 1.6
Signed-off-by: John Bowler <jbowler@acm.org>
-rw-r--r--contrib/libtests/pngvalid.c476
1 files changed, 432 insertions, 44 deletions
diff --git a/contrib/libtests/pngvalid.c b/contrib/libtests/pngvalid.c
index ce409b1a7..60bde8d6c 100644
--- a/contrib/libtests/pngvalid.c
+++ b/contrib/libtests/pngvalid.c
@@ -131,6 +131,17 @@ typedef png_byte *png_const_bytep;
#include <string.h> /* For memcpy, memset */
#include <math.h> /* For floor */
+/* Convenience macros. */
+#define CHUNK(a,b,c,d) (((a)<<24)+((b)<<16)+((c)<<8)+(d))
+#define CHUNK_IHDR CHUNK(73,72,68,82)
+#define CHUNK_PLTE CHUNK(80,76,84,69)
+#define CHUNK_IDAT CHUNK(73,68,65,84)
+#define CHUNK_IEND CHUNK(73,69,78,68)
+#define CHUNK_cHRM CHUNK(99,72,82,77)
+#define CHUNK_gAMA CHUNK(103,65,77,65)
+#define CHUNK_sBIT CHUNK(115,66,73,84)
+#define CHUNK_sRGB CHUNK(115,82,71,66)
+
/* Unused formal parameter errors are removed using the following macro which is
* expected to have no bad effects on performance.
*/
@@ -711,6 +722,8 @@ typedef struct png_store_file
{
struct png_store_file* next; /* as many as you like... */
char name[FILE_NAME_SIZE];
+ unsigned int IDAT_bits; /* Number of bits in IDAT size */
+ png_uint_32 IDAT_size; /* Total size of IDAT data */
png_uint_32 id; /* must be correct (see FILEID) */
png_size_t datacount; /* In this (the last) buffer */
png_store_buffer data; /* Last buffer in file */
@@ -766,6 +779,13 @@ typedef struct png_store
char test[128]; /* Name of test */
char error[256];
+ /* Share fields */
+ png_uint_32 chunklen; /* Length of chunk+overhead (chunkpos >= 8) */
+ png_uint_32 chunktype;/* Type of chunk (valid if chunkpos >= 4) */
+ png_uint_32 chunkpos; /* Position in chunk */
+ png_uint_32 IDAT_size;/* Accumulated IDAT size in .new */
+ unsigned int IDAT_bits;/* Cache of the file store value */
+
/* Read fields */
png_structp pread; /* Used to read a saved file */
png_infop piread;
@@ -775,6 +795,9 @@ typedef struct png_store
png_byte* image; /* Buffer for reading interlaced images */
png_size_t cb_image; /* Size of this buffer */
png_size_t cb_row; /* Row size of the image(s) */
+ uLong IDAT_crc;
+ png_uint_32 IDAT_len; /* Used when re-chunking IDAT chunks */
+ png_uint_32 IDAT_pos; /* Used when re-chunking IDAT chunks */
png_uint_32 image_h; /* Number of rows in a single image */
store_pool read_memory_pool;
@@ -861,6 +884,11 @@ store_init(png_store* ps)
ps->pwrite = NULL;
ps->piwrite = NULL;
ps->writepos = 0;
+ ps->chunkpos = 8;
+ ps->chunktype = 0;
+ ps->chunklen = 16;
+ ps->IDAT_size = 0;
+ ps->IDAT_bits = 0;
ps->new.prev = NULL;
ps->palette = NULL;
ps->npalette = 0;
@@ -883,6 +911,11 @@ store_freenew(png_store *ps)
{
store_freebuffer(&ps->new);
ps->writepos = 0;
+ ps->chunkpos = 8;
+ ps->chunktype = 0;
+ ps->chunklen = 16;
+ ps->IDAT_size = 0;
+ ps->IDAT_bits = 0;
if (ps->palette != NULL)
{
free(ps->palette);
@@ -896,9 +929,6 @@ store_storenew(png_store *ps)
{
png_store_buffer *pb;
- if (ps->writepos != STORE_BUFFER_SIZE)
- png_error(ps->pwrite, "invalid store call");
-
pb = voidcast(png_store_buffer*, malloc(sizeof *pb));
if (pb == NULL)
@@ -929,21 +959,52 @@ store_freefile(png_store_file **ppf)
}
}
+static unsigned int
+bits_of(png_uint_32 num)
+{
+ /* Return the number of bits in 'num' */
+ unsigned int b = 0;
+
+ if (num & 0xffff0000U) b += 16U, num >>= 16;
+ if (num & 0xff00U) b += 8U, num >>= 8;
+ if (num & 0xf0U) b += 4U, num >>= 4;
+ if (num & 0xcU) b += 2U, num >>= 2;
+ if (num & 0x2U) ++b, num >>= 1;
+ if (num) ++b;
+
+ return b; /* 0..32 */
+}
+
/* Main interface to file storeage, after writing a new PNG file (see the API
* below) call store_storefile to store the result with the given name and id.
*/
static void
store_storefile(png_store *ps, png_uint_32 id)
{
- png_store_file *pf = voidcast(png_store_file*, malloc(sizeof *pf));
+ png_store_file *pf;
+
+ if (ps->chunkpos != 0U || ps->chunktype != 0U || ps->chunklen != 0U ||
+ ps->IDAT_size == 0)
+ png_error(ps->pwrite, "storefile: incomplete write");
+
+ pf = voidcast(png_store_file*, malloc(sizeof *pf));
if (pf == NULL)
png_error(ps->pwrite, "storefile: OOM");
safecat(pf->name, sizeof pf->name, 0, ps->wname);
pf->id = id;
pf->data = ps->new;
pf->datacount = ps->writepos;
+ pf->IDAT_size = ps->IDAT_size;
+ pf->IDAT_bits = bits_of(ps->IDAT_size);
+ /* Because the IDAT always has zlib header stuff this must be true: */
+ if (pf->IDAT_bits == 0U)
+ png_error(ps->pwrite, "storefile: 0 sized IDAT");
ps->new.prev = NULL;
ps->writepos = 0;
+ ps->chunkpos = 8;
+ ps->chunktype = 0;
+ ps->chunklen = 16;
+ ps->IDAT_size = 0;
pf->palette = ps->palette;
pf->npalette = ps->npalette;
ps->palette = 0;
@@ -1067,7 +1128,7 @@ store_warning(png_structp ppIn, png_const_charp message)
if (!ps->expect_warning)
store_log(ps, pp, message, 0 /* warning */);
else
- ps->saw_warning = 1;
+ ps->saw_warning = 1;
}
/* These somewhat odd functions are used when reading an image to ensure that
@@ -1209,32 +1270,119 @@ store_image_check(const png_store* ps, png_const_structp pp, int iImage)
}
#endif /* PNG_READ_SUPPORTED */
+static int
+valid_chunktype(png_uint_32 chunktype)
+{
+ /* Each byte in the chunk type must be in one of the ranges 65..90, 97..122
+ * (both inclusive), so:
+ */
+ unsigned int i;
+
+ for (i=0; i<4; ++i)
+ {
+ unsigned int c = chunktype & 0xffU;
+
+ if (!((c >= 65U && c <= 90U) || (c >= 97U && c <= 122U)))
+ return 0;
+
+ chunktype >>= 8;
+ }
+
+ return 1; /* It's valid */
+}
+
static void PNGCBAPI
store_write(png_structp ppIn, png_bytep pb, png_size_t st)
{
png_const_structp pp = ppIn;
png_store *ps = voidcast(png_store*, png_get_io_ptr(pp));
+ size_t writepos = ps->writepos;
+ png_uint_32 chunkpos = ps->chunkpos;
+ png_uint_32 chunktype = ps->chunktype;
+ png_uint_32 chunklen = ps->chunklen;
if (ps->pwrite != pp)
png_error(pp, "store state damaged");
+ /* Technically this is legal, but in practice libpng never writes more than
+ * the maximum chunk size at once so if it happens something weird has
+ * changed inside libpng (probably).
+ */
+ if (st > 0x7fffffffU)
+ png_error(pp, "unexpected write size");
+
+ /* Now process the bytes to be written. Do this in units of the space in the
+ * output (write) buffer or, at the start 4 bytes for the chunk type and
+ * length limited in any case by the amount of data.
+ */
while (st > 0)
{
- size_t cb;
+ if (writepos >= STORE_BUFFER_SIZE)
+ store_storenew(ps), writepos = 0;
- if (ps->writepos >= STORE_BUFFER_SIZE)
- store_storenew(ps);
+ if (chunkpos < 4)
+ {
+ png_byte b = *pb++;
+ --st;
+ chunklen = (chunklen << 8) + b;
+ ps->new.buffer[writepos++] = b;
+ ++chunkpos;
+ }
- cb = st;
+ else if (chunkpos < 8)
+ {
+ png_byte b = *pb++;
+ --st;
+ chunktype = (chunktype << 8) + b;
+ ps->new.buffer[writepos++] = b;
- if (cb > STORE_BUFFER_SIZE - ps->writepos)
- cb = STORE_BUFFER_SIZE - ps->writepos;
+ if (++chunkpos == 8)
+ {
+ chunklen &= 0xffffffffU;
+ if (chunklen > 0x7fffffffU)
+ png_error(pp, "chunk length too great");
- memcpy(ps->new.buffer + ps->writepos, pb, cb);
- pb += cb;
- st -= cb;
- ps->writepos += cb;
- }
+ chunktype &= 0xffffffffU;
+ if (chunktype == CHUNK_IDAT)
+ {
+ if (chunklen > ~ps->IDAT_size)
+ png_error(pp, "pngvalid internal image too large");
+
+ ps->IDAT_size += chunklen;
+ }
+
+ else if (!valid_chunktype(chunktype))
+ png_error(pp, "invalid chunk type");
+
+ chunklen += 12; /* for header and CRC */
+ }
+ }
+
+ else /* chunkpos >= 8 */
+ {
+ png_size_t cb = st;
+
+ if (cb > STORE_BUFFER_SIZE - writepos)
+ cb = STORE_BUFFER_SIZE - writepos;
+
+ if (cb > chunklen - chunkpos/* bytes left in chunk*/)
+ cb = (png_size_t)/*SAFE*/(chunklen - chunkpos);
+
+ memcpy(ps->new.buffer + writepos, pb, cb);
+ chunkpos += (png_uint_32)/*SAFE*/cb;
+ pb += cb;
+ writepos += cb;
+ st -= cb;
+
+ if (chunkpos >= chunklen) /* must be equal */
+ chunkpos = chunktype = chunklen = 0;
+ }
+ } /* while (st > 0) */
+
+ ps->writepos = writepos;
+ ps->chunkpos = chunkpos;
+ ps->chunktype = chunktype;
+ ps->chunklen = chunklen;
}
static void PNGCBAPI
@@ -1254,7 +1402,6 @@ store_read_buffer_size(png_store *ps)
return ps->current->datacount;
}
-#ifdef PNG_READ_TRANSFORMS_SUPPORTED
/* Return total bytes available for read. */
static size_t
store_read_buffer_avail(png_store *ps)
@@ -1279,7 +1426,6 @@ store_read_buffer_avail(png_store *ps)
return 0;
}
-#endif
static int
store_read_buffer_next(png_store *ps)
@@ -1331,6 +1477,242 @@ store_read_imp(png_store *ps, png_bytep pb, png_size_t st)
}
}
+static png_size_t
+store_read_chunk(png_store *ps, png_bytep pb, const png_size_t max,
+ const png_size_t min)
+{
+ png_uint_32 chunklen = ps->chunklen;
+ png_uint_32 chunktype = ps->chunktype;
+ png_uint_32 chunkpos = ps->chunkpos;
+ png_size_t st = max;
+
+ if (st > 0) do
+ {
+ if (chunkpos >= chunklen) /* end of last chunk */
+ {
+ png_byte buffer[8];
+
+ /* Read the header of the next chunk: */
+ store_read_imp(ps, buffer, 8U);
+ chunklen = png_get_uint_32(buffer) + 12U;
+ chunktype = png_get_uint_32(buffer+4U);
+ chunkpos = 0U; /* Position read so far */
+ }
+
+ if (chunktype == CHUNK_IDAT)
+ {
+ png_uint_32 IDAT_pos = ps->IDAT_pos;
+ png_uint_32 IDAT_len = ps->IDAT_len;
+ png_uint_32 IDAT_size = ps->IDAT_size;
+
+ /* The IDAT headers are constructed here; skip the input header. */
+ if (chunkpos < 8U)
+ chunkpos = 8U;
+
+ if (IDAT_pos == IDAT_len)
+ {
+ png_byte random;
+
+ R8(random);
+
+ /* Make a new IDAT chunk, if IDAT_len is 0 this is the first IDAT,
+ * if IDAT_size is 0 this is the end. At present this is set up
+ * using a random number so that there is a 25% chance before
+ * the start of the first IDAT chunk being 0 length.
+ */
+ if (IDAT_len == 0U) /* First IDAT */
+ {
+ switch (random & 3U)
+ {
+ case 0U: IDAT_len = 12U; break; /* 0 bytes */
+ case 1U: IDAT_len = 13U; break; /* 1 byte */
+ default: R32(IDAT_len);
+ IDAT_len %= IDAT_size;
+ IDAT_len += 13U; /* 1..IDAT_size bytes */
+ break;
+ }
+ }
+
+ else if (IDAT_size == 0U) /* all IDAT data read */
+ {
+ /* The last (IDAT) chunk should be positioned at the CRC now: */
+ if (chunkpos != chunklen-4U)
+ png_error(ps->pread, "internal: IDAT size mismatch");
+
+ /* The only option here is to add a zero length IDAT, this
+ * happens 25% of the time. Because of the check above
+ * chunklen-4U-chunkpos must be zero, we just need to skip the
+ * CRC now.
+ */
+ if ((random & 3U) == 0U)
+ IDAT_len = 12U; /* Output another 0 length IDAT */
+
+ else
+ {
+ /* End of IDATs, skip the CRC to make the code above load the
+ * next chunk header next time round.
+ */
+ png_byte buffer[4];
+
+ store_read_imp(ps, buffer, 4U);
+ chunkpos += 4U;
+ ps->IDAT_pos = IDAT_pos;
+ ps->IDAT_len = IDAT_len;
+ ps->IDAT_size = 0U;
+ continue; /* Read the next chunk */
+ }
+ }
+
+ else
+ {
+ /* Middle of IDATs, use 'random' to determine the number of bits
+ * to use in the IDAT length.
+ */
+ R32(IDAT_len);
+ IDAT_len &= (1U << (1U + random % ps->IDAT_bits)) - 1U;
+ if (IDAT_len > IDAT_size)
+ IDAT_len = IDAT_size;
+ IDAT_len += 12U; /* zero bytes may occur */
+ }
+
+ IDAT_pos = 0U;
+ ps->IDAT_crc = 0x35af061e; /* Ie: crc32(0UL, "IDAT", 4) */
+ } /* IDAT_pos == IDAT_len */
+
+ if (IDAT_pos < 8U) /* Return the header */ do
+ {
+ png_uint_32 b;
+ unsigned int shift;
+
+ if (IDAT_pos < 4U)
+ b = IDAT_len - 12U;
+
+ else
+ b = CHUNK_IDAT;
+
+ shift = 3U & IDAT_pos;
+ ++IDAT_pos;
+
+ if (shift < 3U)
+ b >>= 8U*(3U-shift);
+
+ *pb++ = 0xffU & b;
+ }
+ while (--st > 0 && IDAT_pos < 8);
+
+ else if (IDAT_pos < IDAT_len - 4U) /* I.e not the CRC */
+ {
+ if (chunkpos < chunklen-4U)
+ {
+ uInt avail = -1;
+
+ if (avail > (IDAT_len-4U) - IDAT_pos)
+ avail = (uInt)/*SAFE*/((IDAT_len-4U) - IDAT_pos);
+
+ if (avail > st)
+ avail = (uInt)/*SAFE*/st;
+
+ if (avail > (chunklen-4U) - chunkpos)
+ avail = (uInt)/*SAFE*/((chunklen-4U) - chunkpos);
+
+ store_read_imp(ps, pb, avail);
+ ps->IDAT_crc = crc32(ps->IDAT_crc, pb, avail);
+ pb += (png_size_t)/*SAFE*/avail;
+ st -= (png_size_t)/*SAFE*/avail;
+ chunkpos += (png_uint_32)/*SAFE*/avail;
+ IDAT_size -= (png_uint_32)/*SAFE*/avail;
+ IDAT_pos += (png_uint_32)/*SAFE*/avail;
+ }
+
+ else /* skip the input CRC */
+ {
+ png_byte buffer[4];
+
+ store_read_imp(ps, buffer, 4U);
+ chunkpos += 4U;
+ }
+ }
+
+ else /* IDAT crc */ do
+ {
+ uLong b = ps->IDAT_crc;
+ unsigned int shift = (IDAT_len - IDAT_pos); /* 4..1 */
+ ++IDAT_pos;
+
+ if (shift > 1U)
+ b >>= 8U*(shift-1U);
+
+ *pb++ = 0xffU & b;
+ }
+ while (--st > 0 && IDAT_pos < IDAT_len);
+
+ ps->IDAT_pos = IDAT_pos;
+ ps->IDAT_len = IDAT_len;
+ ps->IDAT_size = IDAT_size;
+ }
+
+ else /* !IDAT */
+ {
+ /* If there is still some pending IDAT data after the IDAT chunks have
+ * been processed there is a problem:
+ */
+ if (ps->IDAT_len > 0 && ps->IDAT_size > 0)
+ png_error(ps->pread, "internal: missing IDAT data");
+
+ if (chunktype == CHUNK_IEND && ps->IDAT_len == 0U)
+ png_error(ps->pread, "internal: missing IDAT");
+
+ if (chunkpos < 8U) /* Return the header */ do
+ {
+ png_uint_32 b;
+ unsigned int shift;
+
+ if (chunkpos < 4U)
+ b = chunklen - 12U;
+
+ else
+ b = chunktype;
+
+ shift = 3U & chunkpos;
+ ++chunkpos;
+
+ if (shift < 3U)
+ b >>= 8U*(3U-shift);
+
+ *pb++ = 0xffU & b;
+ }
+ while (--st > 0 && chunkpos < 8);
+
+ else /* Return chunk bytes, including the CRC */
+ {
+ png_size_t avail = st;
+
+ if (avail > chunklen - chunkpos)
+ avail = (png_size_t)/*SAFE*/(chunklen - chunkpos);
+
+ store_read_imp(ps, pb, avail);
+ pb += avail;
+ st -= avail;
+ chunkpos += (png_uint_32)/*SAFE*/avail;
+
+ /* Check for end of chunk and end-of-file; don't try to read a new
+ * chunk header at this point unless instructed to do so by 'min'.
+ */
+ if (chunkpos >= chunklen && max-st >= min &&
+ store_read_buffer_avail(ps) == 0)
+ break;
+ }
+ } /* !IDAT */
+ }
+ while (st > 0);
+
+ ps->chunklen = chunklen;
+ ps->chunktype = chunktype;
+ ps->chunkpos = chunkpos;
+
+ return st; /* space left */
+}
+
static void PNGCBAPI
store_read(png_structp ppIn, png_bytep pb, png_size_t st)
{
@@ -1340,26 +1722,33 @@ store_read(png_structp ppIn, png_bytep pb, png_size_t st)
if (ps == NULL || ps->pread != pp)
png_error(pp, "bad store read call");
- store_read_imp(ps, pb, st);
+ store_read_chunk(ps, pb, st, st);
}
static void
store_progressive_read(png_store *ps, png_structp pp, png_infop pi)
{
- /* Notice that a call to store_read will cause this function to fail because
- * readpos will be set.
- */
if (ps->pread != pp || ps->current == NULL || ps->next == NULL)
png_error(pp, "store state damaged (progressive)");
- do
+ /* This is another Horowitz and Hill random noise generator. In this case
+ * the aim is to stress the progressive reader with truly horrible variable
+ * buffer sizes in the range 1..500, so a sequence of 9 bit random numbers
+ * is generated. We could probably just count from 1 to 32767 and get as
+ * good a result.
+ */
+ while (store_read_buffer_avail(ps) > 0)
{
- if (ps->readpos != 0)
- png_error(pp, "store_read called during progressive read");
+ static png_uint_32 noise = 2;
+ png_size_t cb;
+ png_byte buffer[512];
- png_process_data(pp, pi, ps->next->buffer, store_read_buffer_size(ps));
+ /* Generate 15 more bits of stuff: */
+ noise = (noise << 9) | ((noise ^ (noise >> (9-5))) & 0x1ff);
+ cb = noise & 0x1ff;
+ cb -= store_read_chunk(ps, buffer, cb, 1);
+ png_process_data(pp, pi, buffer, cb);
}
- while (store_read_buffer_next(ps));
}
#endif /* PNG_READ_SUPPORTED */
@@ -1730,6 +2119,11 @@ store_read_reset(png_store *ps)
ps->next = NULL;
ps->readpos = 0;
ps->validated = 0;
+
+ ps->chunkpos = 8;
+ ps->chunktype = 0;
+ ps->chunklen = 16;
+ ps->IDAT_size = 0;
}
#ifdef PNG_READ_SUPPORTED
@@ -1744,6 +2138,11 @@ store_read_set(png_store *ps, png_uint_32 id)
{
ps->current = pf;
ps->next = NULL;
+ ps->IDAT_size = pf->IDAT_size;
+ ps->IDAT_bits = pf->IDAT_bits; /* just a cache */
+ ps->IDAT_len = 0;
+ ps->IDAT_pos = 0;
+ ps->IDAT_crc = 0UL;
store_read_buffer_next(ps);
return;
}
@@ -2581,17 +2980,6 @@ modifier_color_encoding_is_set(const png_modifier *pm)
return pm->current_gamma != 0;
}
-/* Convenience macros. */
-#define CHUNK(a,b,c,d) (((a)<<24)+((b)<<16)+((c)<<8)+(d))
-#define CHUNK_IHDR CHUNK(73,72,68,82)
-#define CHUNK_PLTE CHUNK(80,76,84,69)
-#define CHUNK_IDAT CHUNK(73,68,65,84)
-#define CHUNK_IEND CHUNK(73,69,78,68)
-#define CHUNK_cHRM CHUNK(99,72,82,77)
-#define CHUNK_gAMA CHUNK(103,65,77,65)
-#define CHUNK_sBIT CHUNK(115,66,73,84)
-#define CHUNK_sRGB CHUNK(115,82,71,66)
-
/* The guts of modification are performed during a read. */
static void
modifier_crc(png_bytep buffer)
@@ -2631,7 +3019,7 @@ modifier_read_imp(png_modifier *pm, png_bytep pb, png_size_t st)
{
static png_byte sign[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
case modifier_start:
- store_read_imp(&pm->this, pm->buffer, 8); /* size of signature. */
+ store_read_chunk(&pm->this, pm->buffer, 8, 8); /* signature. */
pm->buffer_count = 8;
pm->buffer_position = 0;
@@ -2641,7 +3029,7 @@ modifier_read_imp(png_modifier *pm, png_bytep pb, png_size_t st)
break;
case modifier_signature:
- store_read_imp(&pm->this, pm->buffer, 13+12); /* size of IHDR */
+ store_read_chunk(&pm->this, pm->buffer, 13+12, 13+12); /* IHDR */
pm->buffer_count = 13+12;
pm->buffer_position = 0;
@@ -2682,7 +3070,7 @@ modifier_read_imp(png_modifier *pm, png_bytep pb, png_size_t st)
{
if (cb > st) cb = st;
pm->flush -= cb;
- store_read_imp(&pm->this, pb, cb);
+ store_read_chunk(&pm->this, pb, cb, cb);
pb += cb;
st -= cb;
if (st == 0) return;
@@ -2699,7 +3087,7 @@ modifier_read_imp(png_modifier *pm, png_bytep pb, png_size_t st)
pm->pending_chunk = 0;
}
else
- store_read_imp(&pm->this, pm->buffer, 8);
+ store_read_chunk(&pm->this, pm->buffer, 8, 8);
pm->buffer_count = 8;
pm->buffer_position = 0;
@@ -2765,8 +3153,8 @@ modifier_read_imp(png_modifier *pm, png_bytep pb, png_size_t st)
*/
if (len+12 <= sizeof pm->buffer)
{
- store_read_imp(&pm->this, pm->buffer+pm->buffer_count,
- len+12-pm->buffer_count);
+ png_size_t s = len+12-pm->buffer_count;
+ store_read_chunk(&pm->this, pm->buffer+pm->buffer_count, s, s);
pm->buffer_count = len+12;
/* Check for a modification, else leave it be. */