diff options
Diffstat (limited to 'Build/source/libs/libpng/libpng-src/contrib')
-rw-r--r-- | Build/source/libs/libpng/libpng-src/contrib/intel/intel_sse.patch | 37 | ||||
-rw-r--r-- | Build/source/libs/libpng/libpng-src/contrib/libtests/pngvalid.c | 545 |
2 files changed, 487 insertions, 95 deletions
diff --git a/Build/source/libs/libpng/libpng-src/contrib/intel/intel_sse.patch b/Build/source/libs/libpng/libpng-src/contrib/intel/intel_sse.patch index d9d02bb8fcb..f000c11a9d0 100644 --- a/Build/source/libs/libpng/libpng-src/contrib/intel/intel_sse.patch +++ b/Build/source/libs/libpng/libpng-src/contrib/intel/intel_sse.patch @@ -1,6 +1,6 @@ -diff --git libpng-1.6.22-orig/configure.ac libpng-1.6.22/configure.ac ---- libpng-1.6.22-orig/configure.ac 2016-05-25 18:59:10.000000000 -0400 -+++ libpng-1.6.22/configure.ac 2016-05-25 19:48:10.631751170 -0400 +diff --git a/configure.ac b/configure.ac +--- a/configure.ac 2016-05-25 18:59:10.000000000 -0400 ++++ b/configure.ac 2016-05-25 19:48:10.631751170 -0400 @@ -341,16 +341,50 @@ AC_ARG_ENABLE([arm-neon], AM_CONDITIONAL([PNG_ARM_NEON], @@ -52,9 +52,9 @@ diff --git libpng-1.6.22-orig/configure.ac libpng-1.6.22/configure.ac [chmod +x libpng-config]) AC_OUTPUT -diff --git libpng-1.6.22-orig/Makefile.am libpng-1.6.22/Makefile.am ---- libpng-1.6.22-orig/Makefile.am 2016-05-17 18:15:12.000000000 -0400 -+++ libpng-1.6.22/Makefile.am 2016-05-25 19:48:10.631751170 -0400 +diff --git a/Makefile.am b/Makefile.am +--- a/Makefile.am 2016-05-17 18:15:12.000000000 -0400 ++++ b/Makefile.am 2016-05-25 19:48:10.631751170 -0400 @@ -89,16 +89,20 @@ libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SO pngset.c pngtrans.c pngwio.c pngwrite.c pngwtran.c pngwutil.c\ png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h pngusr.dfa @@ -76,9 +76,9 @@ diff --git libpng-1.6.22-orig/Makefile.am libpng-1.6.22/Makefile.am if HAVE_LD_VERSION_SCRIPT # Versioned symbols and restricted exports if HAVE_SOLARIS_LD -diff --git libpng-1.6.22-orig/pngpriv.h libpng-1.6.22/pngpriv.h ---- libpng-1.6.22-orig/pngpriv.h 2016-05-25 18:59:10.000000000 -0400 -+++ libpng-1.6.22/pngpriv.h 2016-05-25 19:48:10.635751171 -0400 +diff --git a/pngpriv.h b/pngpriv.h +--- a/pngpriv.h 2016-05-31 09:20:34.442885047 -0500 ++++ b/pngpriv.h 2016-05-31 09:14:54.583492341 -0500 @@ -177,16 +177,52 @@ # endif /* !PNG_ARM_NEON_IMPLEMENTATION */ @@ -162,3 +162,22 @@ diff --git libpng-1.6.22-orig/pngpriv.h libpng-1.6.22/pngpriv.h PNG_INTERNAL_FUNCTION(void,png_read_IDAT_data,(png_structrp png_ptr, png_bytep output, png_alloc_size_t avail_out),PNG_EMPTY); /* Read 'avail_out' bytes of data from the IDAT stream. If the output buffer +@@ -1910,16 +1959,18 @@ PNG_INTERNAL_FUNCTION(void, PNG_FILTER_O + /* Just declare the optimization that will be used */ + #else + /* List *all* the possible optimizations here - this branch is required if + * the builder of libpng passes the definition of PNG_FILTER_OPTIMIZATIONS in + * CFLAGS in place of CPPFLAGS *and* uses symbol prefixing. + */ + PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon, + (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2, ++ (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); + #endif + + PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr, + png_const_charp key, png_bytep new_key), PNG_EMPTY); + + /* Maintainer: Put new private prototypes here ^ */ + + #include "pngdebug.h" diff --git a/Build/source/libs/libpng/libpng-src/contrib/libtests/pngvalid.c b/Build/source/libs/libpng/libpng-src/contrib/libtests/pngvalid.c index ce409b1a79f..7a42d1350ed 100644 --- a/Build/source/libs/libpng/libpng-src/contrib/libtests/pngvalid.c +++ b/Build/source/libs/libpng/libpng-src/contrib/libtests/pngvalid.c @@ -1,7 +1,7 @@ /* pngvalid.c - validate libpng by constructing then reading png files. * - * Last changed in libpng 1.6.22 [May 26, 2016] + * Last changed in libpng 1.6.23 [June 9, 2016] * Copyright (c) 2014-2016 Glenn Randers-Pehrson * Written by John Cunningham Bowler * @@ -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. */ @@ -297,38 +308,33 @@ randomize(void *pv, size_t size) #define R8(this) randomize(&(this), sizeof (this)) -static void r16(png_uint_16p p16, size_t count) +#ifdef PNG_READ_SUPPORTED +static png_byte +random_byte(void) { - size_t i; - - for (i=0; i<count; ++i) - { - unsigned char b2[2]; - randomize(b2, sizeof b2); - *p16++ = png_get_uint_16(b2); - } + unsigned char b1[1]; + randomize(b1, sizeof b1); + return b1[0]; } +#endif /* READ */ -#define R16(this) r16(&(this), (sizeof (this))/(sizeof (png_uint_16))) -#define R16_1(this) r16(&(this), (size_t) 1U) +static png_uint_16 +random_u16(void) +{ + unsigned char b2[2]; + randomize(b2, sizeof b2); + return png_get_uint_16(b2); +} #if defined PNG_READ_RGB_TO_GRAY_SUPPORTED ||\ defined PNG_READ_FILLER_SUPPORTED -static void r32(png_uint_32p p32, size_t count) +static png_uint_32 +random_u32(void) { - size_t i; - - for (i=0; i<count; ++i) - { - unsigned char b4[4]; - randomize(b4, sizeof b4); - *p32++ = png_get_uint_32(b4); - } + unsigned char b4[4]; + randomize(b4, sizeof b4); + return png_get_uint_32(b4); } - -#define R32(this) r32(&(this), (sizeof (this))/(sizeof (png_uint_32))) -#define R32_1(this) r32(&(this), (size_t) 1U) - #endif /* READ_FILLER || READ_RGB_TO_GRAY */ #endif /* READ || WRITE_tRNS || WRITE_FILTER */ @@ -338,11 +344,7 @@ static void r32(png_uint_32p p32, size_t count) static unsigned int random_mod(unsigned int max) { - png_uint_16 x; - - R16_1(x); - - return x % max; /* 0 .. max-1 */ + return random_u16() % max; /* 0 .. max-1 */ } #endif /* READ_TRANSFORMS || WRITE_FILTER */ @@ -351,11 +353,7 @@ random_mod(unsigned int max) static int random_choice(void) { - unsigned char x; - - R8(x); - - return x & 1; + return random_byte() & 1; } #endif /* READ_RGB_TO_GRAY || READ_FILLER */ @@ -711,6 +709,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 +766,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 +782,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 +871,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 +898,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 +916,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 +946,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 +1115,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 +1257,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 +1389,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 +1413,6 @@ store_read_buffer_avail(png_store *ps) return 0; } -#endif static int store_read_buffer_next(png_store *ps) @@ -1331,6 +1464,240 @@ 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 = random_byte(); + + /* 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: IDAT_len = random_u32(); + 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. + */ + IDAT_len = random_u32(); + 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 +1707,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 +2104,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 +2123,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 +2965,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 +3004,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 +3014,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 +3055,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 +3072,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 +3138,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. */ @@ -3333,8 +3706,8 @@ set_random_tRNS(png_structp pp, png_infop pi, const png_byte colour_type, { if (bit_depth == 8) { - R16(tRNS.red); - R16(tRNS.green); + tRNS.red = random_u16(); + tRNS.green = random_u16(); tRNS.blue = tRNS.red ^ tRNS.green; tRNS.red &= mask; tRNS.green &= mask; @@ -3343,7 +3716,7 @@ set_random_tRNS(png_structp pp, png_infop pi, const png_byte colour_type, else /* bit_depth == 16 */ { - R16(tRNS.red); + tRNS.red = random_u16(); tRNS.green = (png_uint_16)(tRNS.red * 257); tRNS.blue = (png_uint_16)(tRNS.green * 17); } @@ -3351,7 +3724,7 @@ set_random_tRNS(png_structp pp, png_infop pi, const png_byte colour_type, else { - R16(tRNS.gray); + tRNS.gray = random_u16(); tRNS.gray &= mask; } @@ -7303,7 +7676,7 @@ image_transform_png_set_rgb_to_gray_ini(const image_transform *this, png_uint_32 ru; double total; - R32_1(ru); + ru = random_u32(); data.green_coefficient = total = (ru & 0xffff) / 65535.; ru >>= 16; data.red_coefficient = (1 - total) * (ru & 0xffff) / 65535.; @@ -8231,7 +8604,7 @@ image_transform_png_set_filler_set(const image_transform *this, * filler. The 'filler' value has all 32 bits set, but only bit_depth * will be used. At this point we don't know bit_depth. */ - R32(data.filler); + data.filler = random_u32(); data.flags = random_choice(); png_set_filler(pp, data.filler, data.flags); @@ -8304,7 +8677,7 @@ image_transform_png_set_add_alpha_set(const image_transform *this, * filler. The 'filler' value has all 32 bits set, but only bit_depth * will be used. At this point we don't know bit_depth. */ - R32(data.filler); + data.filler = random_u32(); data.flags = random_choice(); png_set_add_alpha(pp, data.filler, data.flags); |