From f3f7e147278af44f66974a3d453496ce4d6ed0e3 Mon Sep 17 00:00:00 2001 From: John Bowler Date: Fri, 9 Sep 2011 07:32:37 -0500 Subject: [PATCH] [libpng15] Fixed 64-bit compilation errors (gcc). The errors fixed relate to conditions where types that are 32 bits in the GCC 32-bit world (uLong and png_size_t) become 64 bits in the 64-bit world. This produces potential truncation errors which the compiler correctly flags. --- ANNOUNCE | 5 +++++ CHANGES | 5 +++++ png.c | 34 +++++++++++++++++++++++++++++++--- png.h | 2 +- pngpriv.h | 51 +++++++++++++++++++++++++-------------------------- pngrutil.c | 4 ++-- pngset.c | 8 ++++---- pngvalid.c | 5 ++++- pngwutil.c | 14 ++++++-------- 9 files changed, 83 insertions(+), 45 deletions(-) diff --git a/ANNOUNCE b/ANNOUNCE index 15a6b3ee7..e86ad55c0 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -88,6 +88,11 @@ Version 1.5.5beta07 [September 7, 2011] png_XYZ_from_xy_checked(). Version 1.5.5beta08 [September 9, 2011] + Fixed 64-bit compilation errors (gcc). The errors fixed relate + to conditions where types that are 32 bits in the GCC 32-bit + world (uLong and png_size_t) become 64 bits in the 64-bit + world. This produces potential truncation errors which the + compiler correctly flags. Send comments/corrections/commendations to png-mng-implement at lists.sf.net: (subscription required; visit diff --git a/CHANGES b/CHANGES index f063a1c18..8511a73b0 100644 --- a/CHANGES +++ b/CHANGES @@ -3572,6 +3572,11 @@ Version 1.5.5beta07 [September 7, 2011] png_XYZ_from_xy_checked(). Version 1.5.5beta08 [September 9, 2011] + Fixed 64-bit compilation errors (gcc). The errors fixed relate + to conditions where types that are 32 bits in the GCC 32-bit + world (uLong and png_size_t) become 64 bits in the 64-bit + world. This produces potential truncation errors which the + compiler correctly flags. Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit diff --git a/png.c b/png.c index b16ae9ac5..3e18b995d 100644 --- a/png.c +++ b/png.c @@ -107,7 +107,8 @@ png_zfree(voidpf png_ptr, voidpf ptr) void /* PRIVATE */ png_reset_crc(png_structp png_ptr) { - png_ptr->crc = crc32(0, Z_NULL, 0); + /* The cast is safe because the crc is a 32 bit value. */ + png_ptr->crc = (png_uint_32)crc32(0, Z_NULL, 0); } /* Calculate the CRC over a section of data. We can only pass as @@ -133,8 +134,35 @@ png_calculate_crc(png_structp png_ptr, png_const_bytep ptr, png_size_t length) need_crc = 0; } - if (need_crc) - png_ptr->crc = crc32(png_ptr->crc, ptr, (uInt)length); + /* 'uLong' is defined as unsigned long, this means that on some systems it is + * a 64 bit value. crc32, however, returns 32 bits so the following cast is + * safe. 'uInt' may be no more than 16 bits, so it is necessary to perform a + * loop here. + */ + if (need_crc && length > 0) + { + uLong crc = png_ptr->crc; /* Should never issue a warning */ + + do + { + uInt safeLength = (uInt)length; + if (safeLength == 0) + safeLength = (uInt)-1; /* evil, but safe */ + + crc = crc32(crc, ptr, safeLength); + + /* The following should never issue compiler warnings, if they do the + * target system has characteristics that will probably violate other + * assumptions within the libpng code. + */ + ptr += safeLength; + length -= safeLength; + } + while (length > 0); + + /* And the following is always safe because the crc is only 32 bits. */ + png_ptr->crc = (png_uint_32)crc; + } } /* Check a user supplied version number, called from both read and write diff --git a/png.h b/png.h index 84411e45c..bf557f43a 100644 --- a/png.h +++ b/png.h @@ -795,7 +795,7 @@ typedef png_info FAR * FAR * png_infopp; #define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ #define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ #define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ -#define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000 /* ESR, 1.0.6 */ /* This is used for the transformation routines, as some of them * change these values for the row. It also should enable using diff --git a/pngpriv.h b/pngpriv.h index 9ca489d9e..92e39ab49 100644 --- a/pngpriv.h +++ b/pngpriv.h @@ -372,16 +372,15 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; #define PNG_USER_TRANSFORM 0x100000L #define PNG_RGB_TO_GRAY_ERR 0x200000L #define PNG_RGB_TO_GRAY_WARN 0x400000L -#define PNG_RGB_TO_GRAY 0x600000L /* two bits, RGB_TO_GRAY_ERR|WARN */ -#define PNG_ENCODE_ALPHA 0x800000L /* Added to libpng-1.5.4 */ -#define PNG_ADD_ALPHA 0x1000000L /* Added to libpng-1.2.7 */ -#define PNG_EXPAND_tRNS 0x2000000L /* Added to libpng-1.2.9 */ -#define PNG_SCALE_16_TO_8 0x4000000L /* Added to libpng-1.5.4 */ - /* 0x8000000L unused */ - /* 0x10000000L unused */ - /* 0x20000000L unused */ - /* 0x40000000L unused */ - +#define PNG_RGB_TO_GRAY 0x600000L /* two bits, RGB_TO_GRAY_ERR|WARN */ +#define PNG_ENCODE_ALPHA 0x800000L /* Added to libpng-1.5.4 */ +#define PNG_ADD_ALPHA 0x1000000L /* Added to libpng-1.2.7 */ +#define PNG_EXPAND_tRNS 0x2000000L /* Added to libpng-1.2.9 */ +#define PNG_SCALE_16_TO_8 0x4000000L /* Added to libpng-1.5.4 */ + /* 0x8000000L unused */ + /* 0x10000000L unused */ + /* 0x20000000L unused */ + /* 0x40000000L unused */ /* Flags for png_create_struct */ #define PNG_STRUCT_PNG 0x0001 #define PNG_STRUCT_INFO 0x0002 @@ -406,22 +405,22 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; #define PNG_FLAG_ASSUME_sRGB 0x1000 /* Added to libpng-1.5.4 */ #define PNG_FLAG_OPTIMIZE_ALPHA 0x2000 /* Added to libpng-1.5.4 */ #define PNG_FLAG_DETECT_UNINITIALIZED 0x4000 /* Added to libpng-1.5.4 */ -#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000L -#define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000L -#define PNG_FLAG_LIBRARY_MISMATCH 0x20000L -#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000L -#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000L -#define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000L - /* 0x200000L unused */ - /* 0x400000L unused */ -#define PNG_FLAG_BENIGN_ERRORS_WARN 0x800000L /* Added to libpng-1.4.0 */ -#define PNG_FLAG_ZTXT_CUSTOM_STRATEGY 0x1000000L /* 5 lines added */ -#define PNG_FLAG_ZTXT_CUSTOM_LEVEL 0x2000000L /* to libpng-1.5.4 */ -#define PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL 0x4000000L -#define PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS 0x8000000L -#define PNG_FLAG_ZTXT_CUSTOM_METHOD 0x10000000L - /* 0x20000000L unused */ - /* 0x40000000L unused */ +#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000 +#define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000 +#define PNG_FLAG_LIBRARY_MISMATCH 0x20000 +#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000 +#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000 +#define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000 + /* 0x200000 unused */ + /* 0x400000 unused */ +#define PNG_FLAG_BENIGN_ERRORS_WARN 0x800000 /* Added to libpng-1.4.0 */ +#define PNG_FLAG_ZTXT_CUSTOM_STRATEGY 0x1000000 /* 5 lines added */ +#define PNG_FLAG_ZTXT_CUSTOM_LEVEL 0x2000000 /* to libpng-1.5.4 */ +#define PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL 0x4000000 +#define PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS 0x8000000 +#define PNG_FLAG_ZTXT_CUSTOM_METHOD 0x10000000 + /* 0x20000000 unused */ + /* 0x40000000 unused */ #define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ PNG_FLAG_CRC_ANCILLARY_NOWARN) diff --git a/pngrutil.c b/pngrutil.c index 99bfdca79..039c77fac 100644 --- a/pngrutil.c +++ b/pngrutil.c @@ -87,10 +87,10 @@ png_int_32 (PNGAPI png_get_int_32)(png_const_bytep buf) { png_uint_32 uval = png_get_uint_32(buf); - if ((uval & 0x80000000L) == 0) /* non-negative */ + if ((uval & 0x80000000) == 0) /* non-negative */ return uval; - uval = (uval ^ 0xffffffffL) + 1; /* 2's complement: -x = ~x+1 */ + uval = (uval ^ 0xffffffff) + 1; /* 2's complement: -x = ~x+1 */ return -(png_int_32)uval; } diff --git a/pngset.c b/pngset.c index ac90d467f..79968d3b8 100644 --- a/pngset.c +++ b/pngset.c @@ -620,7 +620,7 @@ png_set_iCCP(png_structp png_ptr, png_infop info_ptr, { png_charp new_iccp_name; png_bytep new_iccp_profile; - png_uint_32 length; + png_size_t length; png_debug1(1, "in %s storage function", "iCCP"); @@ -966,10 +966,10 @@ png_set_sPLT(png_structp png_ptr, { png_sPLT_tp to = np + info_ptr->splt_palettes_num + i; png_const_sPLT_tp from = entries + i; - png_uint_32 length; + png_size_t length; length = png_strlen(from->name) + 1; - to->name = (png_charp)png_malloc_warn(png_ptr, (png_size_t)length); + to->name = (png_charp)png_malloc_warn(png_ptr, length); if (to->name == NULL) { @@ -980,7 +980,7 @@ png_set_sPLT(png_structp png_ptr, png_memcpy(to->name, from->name, length); to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr, - (png_size_t)(from->nentries * png_sizeof(png_sPLT_entry))); + from->nentries * png_sizeof(png_sPLT_entry)); if (to->entries == NULL) { diff --git a/pngvalid.c b/pngvalid.c index 0b441a3d5..8c2eb0de2 100644 --- a/pngvalid.c +++ b/pngvalid.c @@ -2217,7 +2217,10 @@ modifier_crc(png_bytep buffer) * the buffer, at the start. */ uInt datalen = png_get_uint_32(buffer); - png_save_uint_32(buffer+datalen+8, crc32(0L, buffer+4, datalen+4)); + uLong crc = crc32(0L, buffer+4, datalen+4); + /* The cast to png_uint_32 is safe because a crc32 is always a 32 bit value. + */ + png_save_uint_32(buffer+datalen+8, (png_uint_32)crc); } static void diff --git a/pngwutil.c b/pngwutil.c index 3ae5ed4e2..4e422ce68 100644 --- a/pngwutil.c +++ b/pngwutil.c @@ -1860,7 +1860,7 @@ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, { PNG_pCAL; png_size_t purpose_len, units_len, total_len; - png_uint_32p params_len; + png_size_tp params_len; png_byte buf[10]; png_charp new_purpose; int i; @@ -1876,8 +1876,8 @@ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, png_debug1(3, "pCAL units length = %d", (int)units_len); total_len = purpose_len + units_len + 10; - params_len = (png_uint_32p)png_malloc(png_ptr, - (png_alloc_size_t)(nparams * png_sizeof(png_uint_32))); + params_len = (png_size_tp)png_malloc(png_ptr, + (png_alloc_size_t)(nparams * png_sizeof(png_size_t))); /* Find the length of each parameter, making sure we don't count the * null terminator for the last parameter. @@ -1887,13 +1887,12 @@ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1); png_debug2(3, "pCAL parameter %d length = %lu", i, (unsigned long)params_len[i]); - total_len += (png_size_t)params_len[i]; + total_len += params_len[i]; } png_debug1(3, "pCAL total length = %d", (int)total_len); png_write_chunk_start(png_ptr, png_pCAL, (png_uint_32)total_len); - png_write_chunk_data(png_ptr, (png_const_bytep)new_purpose, - (png_size_t)purpose_len); + png_write_chunk_data(png_ptr, (png_const_bytep)new_purpose, purpose_len); png_save_int_32(buf, X0); png_save_int_32(buf + 4, X1); buf[8] = (png_byte)type; @@ -1905,8 +1904,7 @@ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, for (i = 0; i < nparams; i++) { - png_write_chunk_data(png_ptr, (png_const_bytep)params[i], - (png_size_t)params_len[i]); + png_write_chunk_data(png_ptr, (png_const_bytep)params[i], params_len[i]); } png_free(png_ptr, params_len);