summaryrefslogtreecommitdiff
path: root/pngmem.c
diff options
context:
space:
mode:
authorJohn Bowler <jbowler@acm.org>2013-01-19 23:18:59 -0600
committerGlenn Randers-Pehrson <glennrp at users.sourceforge.net>2013-01-19 23:18:59 -0600
commit2414bd99d8c76f92ca9272f1b1b1eff55709298a (patch)
treefb298f2d454e502fb24fbd11fadd9007f8ddf62f /pngmem.c
parent1f76e62d6cf80e5aa29b113a6e0fc1304e17826b (diff)
downloadlibpng-2414bd99d8c76f92ca9272f1b1b1eff55709298a.tar.gz
[libpng16] Use consistent handling of overflows in text, sPLT and unknown
png_set_* APIs
Diffstat (limited to 'pngmem.c')
-rw-r--r--pngmem.c64
1 files changed, 63 insertions, 1 deletions
diff --git a/pngmem.c b/pngmem.c
index 5cc345093..b94e9bbf6 100644
--- a/pngmem.c
+++ b/pngmem.c
@@ -76,7 +76,7 @@ png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size),
#ifdef PNG_USER_MEM_SUPPORTED
PNG_UNUSED(png_ptr)
#endif
- if (size > 0 && size <= ~(size_t)0
+ if (size > 0 && size <= PNG_SIZE_MAX
# ifdef PNG_MAX_MALLOC_64K
&& size <= 65536U
# endif
@@ -95,6 +95,68 @@ png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size),
return NULL;
}
+/* This is really here only to work round a spurious warning in GCC 4.6 and 4.7
+ * that arises because of the checks in png_realloc_array that are repeated in
+ * png_malloc_array.
+ */
+static png_voidp
+png_malloc_array_checked(png_const_structrp png_ptr, int nelements,
+ size_t element_size)
+{
+ png_alloc_size_t req = nelements; /* known to be > 0 */
+
+ if (req <= PNG_SIZE_MAX/element_size)
+ return png_malloc_base(png_ptr, req * element_size);
+
+ /* The failure case when the request is too large */
+ return NULL;
+}
+
+PNG_FUNCTION(png_voidp /* PRIVATE */,
+png_malloc_array,(png_const_structrp png_ptr, int nelements,
+ size_t element_size),PNG_ALLOCATED)
+{
+ if (nelements <= 0 || element_size == 0)
+ png_error(png_ptr, "internal error: array alloc");
+
+ return png_malloc_array_checked(png_ptr, nelements, element_size);
+}
+
+PNG_FUNCTION(png_voidp /* PRIVATE */,
+png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array,
+ int old_elements, int add_elements, size_t element_size),PNG_ALLOCATED)
+{
+ /* These are internal errors: */
+ if (add_elements <= 0 || element_size == 0 || old_elements < 0 ||
+ (old_array == NULL && old_elements > 0))
+ png_error(png_ptr, "internal error: array realloc");
+
+ /* Check for overflow on the elements count (so the caller does not have to
+ * check.)
+ */
+ if (add_elements <= INT_MAX - old_elements)
+ {
+ png_voidp new_array = png_malloc_array_checked(png_ptr,
+ old_elements+add_elements, element_size);
+
+ if (new_array != NULL)
+ {
+ /* Because png_malloc_array worked the size calculations below cannot
+ * overflow.
+ */
+ if (old_elements > 0)
+ memcpy(new_array, old_array, element_size*(unsigned)old_elements);
+
+ memset((char*)new_array + element_size*(unsigned)old_elements, 0,
+ element_size*(unsigned)add_elements);
+
+ return new_array;
+ }
+ }
+
+ return NULL; /* error */
+}
+
/* Various functions that have different error handling are derived from this.
* png_malloc always exists, but if PNG_USER_MEM_SUPPORTED is defined a separate
* function png_malloc_default is also provided.