mirror of
https://git.code.sf.net/p/libpng/code.git
synced 2025-07-10 18:04:09 +02:00
[libpng16] Fixed conceivable but difficult to repro overflow. Also added
two test programs to generate and test a PNG which should have the problem.
This commit is contained in:
parent
37109a9f5b
commit
1c6e22a360
7
ANNOUNCE
7
ANNOUNCE
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
Libpng 1.6.0beta37 - January 1, 2013
|
Libpng 1.6.0beta37 - January 10, 2013
|
||||||
|
|
||||||
This is not intended to be a public release. It will be replaced
|
This is not intended to be a public release. It will be replaced
|
||||||
within a few weeks by a public version or by another test version.
|
within a few weeks by a public version or by another test version.
|
||||||
@ -11,7 +11,6 @@ Source files with LF line endings (for Unix/Linux) and with a
|
|||||||
|
|
||||||
1.6.0beta37.tar.xz (LZMA-compressed, recommended)
|
1.6.0beta37.tar.xz (LZMA-compressed, recommended)
|
||||||
1.6.0beta37.tar.gz
|
1.6.0beta37.tar.gz
|
||||||
1.6.0beta37.tar.bz2
|
|
||||||
|
|
||||||
Source files with CRLF line endings (for Windows), without the
|
Source files with CRLF line endings (for Windows), without the
|
||||||
"configure" script
|
"configure" script
|
||||||
@ -584,7 +583,9 @@ Version 1.6.0beta36 [January 2, 2013]
|
|||||||
Rebuilt configure with autoconf-2.69 (inadvertently not done in beta33)
|
Rebuilt configure with autoconf-2.69 (inadvertently not done in beta33)
|
||||||
Fixed 'make distcheck' on SUN OS - libpng.so was not being removed
|
Fixed 'make distcheck' on SUN OS - libpng.so was not being removed
|
||||||
|
|
||||||
Version 1.6.0beta37 [January 1, 2013]
|
Version 1.6.0beta37 [January 10, 2013]
|
||||||
|
Fixed conceivable but difficult to repro overflow. Also added two test
|
||||||
|
programs to generate and test a PNG which should have the problem.
|
||||||
|
|
||||||
===========================================================================
|
===========================================================================
|
||||||
NOTICE November 17, 2012:
|
NOTICE November 17, 2012:
|
||||||
|
4
CHANGES
4
CHANGES
@ -4336,7 +4336,9 @@ Version 1.6.0beta36 [January 2, 2013]
|
|||||||
Rebuilt configure with autoconf-2.69 (inadvertently not done in beta33)
|
Rebuilt configure with autoconf-2.69 (inadvertently not done in beta33)
|
||||||
Fixed 'make distcheck' on SUN OS - libpng.so was not being removed
|
Fixed 'make distcheck' on SUN OS - libpng.so was not being removed
|
||||||
|
|
||||||
Version 1.6.0beta37 [January 1, 2013]
|
Version 1.6.0beta37 [January 10, 2013]
|
||||||
|
Fixed conceivable but difficult to repro overflow. Also added two test
|
||||||
|
programs to generate and test a PNG which should have the problem.
|
||||||
|
|
||||||
===========================================================================
|
===========================================================================
|
||||||
NOTICE November 17, 2012:
|
NOTICE November 17, 2012:
|
||||||
|
57
contrib/libtests/fakepng.c
Normal file
57
contrib/libtests/fakepng.c
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/* Fake a PNG - just write it out directly. */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <zlib.h> /* for crc32 */
|
||||||
|
|
||||||
|
void
|
||||||
|
put_uLong(uLong val)
|
||||||
|
{
|
||||||
|
putchar(val >> 24);
|
||||||
|
putchar(val >> 16);
|
||||||
|
putchar(val >> 8);
|
||||||
|
putchar(val >> 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
put_chunk(const unsigned char *chunk, uInt length)
|
||||||
|
{
|
||||||
|
uLong crc;
|
||||||
|
|
||||||
|
put_uLong(length-4); /* Exclude the tag */
|
||||||
|
|
||||||
|
fwrite(chunk, length, 1, stdout);
|
||||||
|
|
||||||
|
crc = crc32(0, Z_NULL, 0);
|
||||||
|
put_uLong(crc32(crc, chunk, length));
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned char signature[] =
|
||||||
|
{
|
||||||
|
137, 80, 78, 71, 13, 10, 26, 10
|
||||||
|
};
|
||||||
|
|
||||||
|
const unsigned char IHDR[] =
|
||||||
|
{
|
||||||
|
73, 72, 68, 82, /* IHDR */
|
||||||
|
0, 0, 0, 1, /* width */
|
||||||
|
0, 0, 0, 1, /* height */
|
||||||
|
1, /* bit depth */
|
||||||
|
0, /* color type: greyscale */
|
||||||
|
0, /* compression method */
|
||||||
|
0, /* filter method */
|
||||||
|
0 /* interlace method: none */
|
||||||
|
};
|
||||||
|
|
||||||
|
const unsigned char unknown[] =
|
||||||
|
{
|
||||||
|
'u', 'n', 'K', 'n' /* "unKn" - private safe to copy */
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
fwrite(signature, sizeof signature, 1, stdout);
|
||||||
|
put_chunk(IHDR, sizeof IHDR);
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
put_chunk(unknown, sizeof unknown);
|
||||||
|
}
|
104
contrib/libtests/readpng.c
Normal file
104
contrib/libtests/readpng.c
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/* readpng.c
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 John Cunningham Bowler
|
||||||
|
*
|
||||||
|
* Last changed in libpng 1.6.0 [(PENDING RELEASE)]
|
||||||
|
*
|
||||||
|
* This code is released under the libpng license.
|
||||||
|
* For conditions of distribution and use, see the disclaimer
|
||||||
|
* and license in png.h
|
||||||
|
*
|
||||||
|
* Load an arbitrary number of PNG files (from the command line, or, if there
|
||||||
|
* are no arguments on the command line, from stdin) then run a time test by
|
||||||
|
* reading each file by row. The test does nothing with the read result and
|
||||||
|
* does no transforms. The only output is a time as a floating point number of
|
||||||
|
* seconds with 9 decimal digits.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if (defined HAVE_CONFIG_H) && !(defined PNG_NO_CONFIG_H)
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define the following to use this test against your installed libpng, rather
|
||||||
|
* than the one being built here:
|
||||||
|
*/
|
||||||
|
#ifdef PNG_FREESTANDING_TESTS
|
||||||
|
# include <png.h>
|
||||||
|
#else
|
||||||
|
# include "../../png.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int
|
||||||
|
read_png(FILE *fp)
|
||||||
|
{
|
||||||
|
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0);
|
||||||
|
png_infop info_ptr = NULL;
|
||||||
|
png_bytep row = NULL, display = NULL;
|
||||||
|
|
||||||
|
if (png_ptr == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (setjmp(png_jmpbuf(png_ptr)))
|
||||||
|
{
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
if (row != NULL) free(row);
|
||||||
|
if (display != NULL) free(display);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
png_init_io(png_ptr, fp);
|
||||||
|
|
||||||
|
info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
if (info_ptr == NULL)
|
||||||
|
png_error(png_ptr, "OOM allocating info structure");
|
||||||
|
|
||||||
|
png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, NULL, 0);
|
||||||
|
|
||||||
|
png_read_info(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
{
|
||||||
|
png_size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
row = malloc(rowbytes);
|
||||||
|
display = malloc(rowbytes);
|
||||||
|
|
||||||
|
if (row == NULL || display == NULL)
|
||||||
|
png_error(png_ptr, "OOM allocating row buffers");
|
||||||
|
|
||||||
|
{
|
||||||
|
png_uint_32 height = png_get_image_height(png_ptr, info_ptr);
|
||||||
|
int passes = png_set_interlace_handling(png_ptr);
|
||||||
|
int pass;
|
||||||
|
|
||||||
|
png_start_read_image(png_ptr);
|
||||||
|
|
||||||
|
for (pass = 0; pass < passes; ++pass)
|
||||||
|
{
|
||||||
|
png_uint_32 y = height;
|
||||||
|
|
||||||
|
/* NOTE: this trashes the row each time; interlace handling won't
|
||||||
|
* work, but this avoids memory thrashing for speed testing.
|
||||||
|
*/
|
||||||
|
while (y-- > 0)
|
||||||
|
png_read_row(png_ptr, row, display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure to read to the end of the file: */
|
||||||
|
png_read_end(png_ptr, info_ptr);
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
free(row);
|
||||||
|
free(display);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
/* Exit code 0 on success. */
|
||||||
|
return !read_png(stdin);
|
||||||
|
}
|
@ -223,7 +223,10 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
|
|||||||
#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
|
#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
|
||||||
/* Storage for unknown chunks that the library doesn't recognize. */
|
/* Storage for unknown chunks that the library doesn't recognize. */
|
||||||
png_unknown_chunkp unknown_chunks;
|
png_unknown_chunkp unknown_chunks;
|
||||||
unsigned int unknown_chunks_num;
|
/* The type of this field must match png_struct::user_chunk_cache_max,
|
||||||
|
* else overflow can occur.
|
||||||
|
*/
|
||||||
|
png_uint_32 unknown_chunks_num;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PNG_sPLT_SUPPORTED
|
#ifdef PNG_sPLT_SUPPORTED
|
||||||
|
28
pngset.c
28
pngset.c
@ -1086,11 +1086,12 @@ check_location(png_const_structrp png_ptr, int location)
|
|||||||
|
|
||||||
void PNGAPI
|
void PNGAPI
|
||||||
png_set_unknown_chunks(png_const_structrp png_ptr,
|
png_set_unknown_chunks(png_const_structrp png_ptr,
|
||||||
png_inforp info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns)
|
png_inforp info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns_in)
|
||||||
{
|
{
|
||||||
|
png_uint_32 num_unknowns;
|
||||||
png_unknown_chunkp np;
|
png_unknown_chunkp np;
|
||||||
|
|
||||||
if (png_ptr == NULL || info_ptr == NULL || num_unknowns <= 0)
|
if (png_ptr == NULL || info_ptr == NULL || num_unknowns_in <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Check for the failure cases where support has been disabled at compile
|
/* Check for the failure cases where support has been disabled at compile
|
||||||
@ -1121,9 +1122,24 @@ png_set_unknown_chunks(png_const_structrp png_ptr,
|
|||||||
* undefined behavior. Changing to png_malloc fixes this by producing a
|
* undefined behavior. Changing to png_malloc fixes this by producing a
|
||||||
* png_error. The (png_size_t) cast was also removed as it hides a potential
|
* png_error. The (png_size_t) cast was also removed as it hides a potential
|
||||||
* overflow.
|
* overflow.
|
||||||
*
|
|
||||||
* TODO: fix the potential overflow in the multiply
|
|
||||||
*/
|
*/
|
||||||
|
num_unknowns = (unsigned int)/*SAFE*/num_unknowns_in;
|
||||||
|
|
||||||
|
/* There are two overflow conditions, one on the count one on memory, on a
|
||||||
|
* 32-bit system the memory limit is critical, on a 64-bit system the count
|
||||||
|
* limit.
|
||||||
|
*/
|
||||||
|
if (num_unknowns > PNG_UINT_32_MAX - info_ptr->unknown_chunks_num ||
|
||||||
|
num_unknowns > PNG_SIZE_MAX/(sizeof *np) - info_ptr->unknown_chunks_num)
|
||||||
|
{
|
||||||
|
/* This is a benign read error (user limits are disabled and we are about
|
||||||
|
* to overflow 2^32 chunks) and an application write error.
|
||||||
|
*/
|
||||||
|
png_chunk_report(png_ptr, "too many unknown chunks",
|
||||||
|
PNG_CHUNK_WRITE_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
np = png_voidcast(png_unknown_chunkp, png_malloc(png_ptr,
|
np = png_voidcast(png_unknown_chunkp, png_malloc(png_ptr,
|
||||||
(info_ptr->unknown_chunks_num + (unsigned int)num_unknowns) *
|
(info_ptr->unknown_chunks_num + (unsigned int)num_unknowns) *
|
||||||
(sizeof (png_unknown_chunk))));
|
(sizeof (png_unknown_chunk))));
|
||||||
@ -1140,8 +1156,8 @@ png_set_unknown_chunks(png_const_structrp png_ptr,
|
|||||||
/* Increment unknown_chunks_num each time round the loop to protect the
|
/* Increment unknown_chunks_num each time round the loop to protect the
|
||||||
* just-allocated chunk data.
|
* just-allocated chunk data.
|
||||||
*/
|
*/
|
||||||
for (; --num_unknowns >= 0;
|
for (; num_unknowns > 0;
|
||||||
++np, ++unknowns, ++(info_ptr->unknown_chunks_num))
|
--num_unknowns, ++np, ++unknowns, ++(info_ptr->unknown_chunks_num))
|
||||||
{
|
{
|
||||||
memcpy(np->name, unknowns->name, (sizeof unknowns->name));
|
memcpy(np->name, unknowns->name, (sizeof unknowns->name));
|
||||||
np->name[(sizeof np->name)-1] = '\0';
|
np->name[(sizeof np->name)-1] = '\0';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user