[libpng15] Added LSR() macro to defend against buggy compilers that evaluate

non-taken code branches and complain about out-of-range shifts.
This commit is contained in:
Glenn Randers-Pehrson 2011-10-27 12:05:58 -05:00
parent b2068640d1
commit ef02d563a3
3 changed files with 51 additions and 36 deletions

View File

@ -1,5 +1,5 @@
Libpng 1.5.6rc02 - October 26, 2011 Libpng 1.5.6rc02 - October 27, 2011
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.
@ -92,8 +92,9 @@ Version 1.5.6beta07 [October 21, 2011]
Version 1.5.6rc01 [October 26, 2011] Version 1.5.6rc01 [October 26, 2011]
Changed misleading "Missing PLTE before cHRM" warning to "Out of place cHRM" Changed misleading "Missing PLTE before cHRM" warning to "Out of place cHRM"
Version 1.5.6rc02 [October 26, 2011] Version 1.5.6rc02 [October 27, 2011]
Added LSR() macro to defend against buggy compilers that evaluate non-taken
code branches and complain about out-of-range shifts.
Send comments/corrections/commendations to png-mng-implement at lists.sf.net: Send comments/corrections/commendations to png-mng-implement at lists.sf.net:
(subscription required; visit (subscription required; visit

View File

@ -3653,7 +3653,9 @@ Version 1.5.6beta07 [October 21, 2011]
Version 1.5.6rc01 [October 26, 2011] Version 1.5.6rc01 [October 26, 2011]
Changed misleading "Missing PLTE before cHRM" warning to "Out of place cHRM" Changed misleading "Missing PLTE before cHRM" warning to "Out of place cHRM"
Version 1.5.6rc02 [October 26, 2011] Version 1.5.6rc02 [October 27, 2011]
Added LSR() macro to defend against buggy compilers that evaluate non-taken
code branches and complain about out-of-range shifts.
Send comments/corrections/commendations to png-mng-implement at lists.sf.net Send comments/corrections/commendations to png-mng-implement at lists.sf.net
(subscription required; visit (subscription required; visit

View File

@ -301,7 +301,7 @@ png_inflate(png_structp png_ptr, png_bytep data, png_size_t size,
{ {
int ret, avail; int ret, avail;
/* The setting of 'avail_in' used to be outside the loop, by setting it /* The setting of 'avail_in' used to be outside the loop; by setting it
* inside it is possible to chunk the input to zlib and simply rely on * inside it is possible to chunk the input to zlib and simply rely on
* zlib to advance the 'next_in' pointer. This allows arbitrary amounts o * zlib to advance the 'next_in' pointer. This allows arbitrary amounts o
* data to be passed through zlib at the unavoidable cost of requiring a * data to be passed through zlib at the unavoidable cost of requiring a
@ -2817,7 +2817,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
end_mask = (pixel_depth * row_width) & 7; end_mask = (pixel_depth * row_width) & 7;
if (end_mask != 0) if (end_mask != 0)
{ {
/* ep == NULL is a flag to say do nothing */ /* end_ptr == NULL is a flag to say do nothing */
end_ptr = dp + PNG_ROWBYTES(pixel_depth, row_width) - 1; end_ptr = dp + PNG_ROWBYTES(pixel_depth, row_width) - 1;
end_byte = *end_ptr; end_byte = *end_ptr;
# ifdef PNG_READ_PACKSWAP_SUPPORTED # ifdef PNG_READ_PACKSWAP_SUPPORTED
@ -2830,9 +2830,11 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
/* end_mask is now the bits to *keep* from the destination row */ /* end_mask is now the bits to *keep* from the destination row */
} }
/* This reduces to a memcpy for non-interlaced images and for the case where /* For non-interlaced images this reduces to a png_memcpy(). A png_memcpy()
* interlacing isn't supported or isn't done (in that case the caller gets a * will also happen if interlacing isn't supported or if the application
* sequence of interlace pass rows.) * does not call png_set_interlace_handling(). In the latter cases the
* caller just gets a sequence of the unexpanded rows from each interlace
* pass.
*/ */
#ifdef PNG_READ_INTERLACING_SUPPORTED #ifdef PNG_READ_INTERLACING_SUPPORTED
if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE) && if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE) &&
@ -2848,9 +2850,9 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
if (pixel_depth < 8) if (pixel_depth < 8)
{ {
/* For pixel depths up to 4bpp the 8-pixel mask can be expanded to fit /* For pixel depths up to 4-bpp the 8-pixel mask can be expanded to fit
* into 32 bits, then a single loop over the bytes using the four byte * into 32 bits, then a single loop over the bytes using the four byte
* values in the 32 bit mask can be used. For the 'display' option the * values in the 32-bit mask can be used. For the 'display' option the
* expanded mask may also not require any masking within a byte. To * expanded mask may also not require any masking within a byte. To
* make this work the PACKSWAP option must be taken into account - it * make this work the PACKSWAP option must be taken into account - it
* simply requires the pixels to be reversed in each byte. * simply requires the pixels to be reversed in each byte.
@ -2869,15 +2871,25 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
* *
* The following defines allow generation of compile time constant bit * The following defines allow generation of compile time constant bit
* masks for each pixel depth and each possibility of swapped or not * masks for each pixel depth and each possibility of swapped or not
* swapped bytes. Pass is in the range 0..6, 'x', a pixel index, is in * swapped bytes. Pass 'p' is in the range 0..6; 'x', a pixel index,
* the range 0..7, the result is 1 if the pixel is to be copied in the * is in the range 0..7; and the result is 1 if the pixel is to be
* pass, 0 if not. 'S' is for the sparkle method, 'B' for the block * copied in the pass, 0 if not. 'S' is for the sparkle method, 'B'
* method. * for the block method.
*
* With Microsoft Visual C and potentially other compilers the shifts
* below to extract the relevant fields from a 64 bit value are faulted
* if evaluated at compile time because the non-taken branch has an
* invalid shift (negative or more than 31), hence the following.
*/ */
# define S_COPY(p,x) (((p)<4 ? 0x80088822 >> ((3-(p))*8+(7-(x))) :\ # if defined PNG_USE_COMPILE_TIME_MASKS && defined _MSC_VER
0xaa55ff00 >> ((7-(p))*8+(7-(x)))) & 1) # define LSR(x,s) ((x)>>((s) & 0x1f))
# define B_COPY(p,x) (((p)<4 ? 0xff0fff33 >> ((3-(p))*8+(7-(x))) :\ # else
0xff55ff00 >> ((7-(p))*8+(7-(x)))) & 1) # define LSR(x,s) ((x)>>(s))
# endif
# define S_COPY(p,x) (((p)<4 ? LSR(0x80088822,(3-(p))*8+(7-(x))) :\
LSR(0xaa55ff00,(7-(p))*8+(7-(x)))) & 1)
# define B_COPY(p,x) (((p)<4 ? LSR(0xff0fff33,(3-(p))*8+(7-(x))) :\
LSR(0xff55ff00,(7-(p))*8+(7-(x)))) & 1)
/* Return a mask for pass 'p' pixel 'x' at depth 'd'. The mask is /* Return a mask for pass 'p' pixel 'x' at depth 'd'. The mask is
* little endian - the first pixel is at bit 0 - however the extra * little endian - the first pixel is at bit 0 - however the extra
@ -2892,9 +2904,9 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
# define S_MASKx(p,x,d,s) (S_COPY(p,x)?PIXEL_MASK(p,x,d,s):0) # define S_MASKx(p,x,d,s) (S_COPY(p,x)?PIXEL_MASK(p,x,d,s):0)
# define B_MASKx(p,x,d,s) (B_COPY(p,x)?PIXEL_MASK(p,x,d,s):0) # define B_MASKx(p,x,d,s) (B_COPY(p,x)?PIXEL_MASK(p,x,d,s):0)
/* Combine 8 of these to get the full mask. For the 1 and 2 bpp cases /* Combine 8 of these to get the full mask. For the 1-bpp and 2-bpp
* the result needs replicating, for the 4bpp case the above generates * cases the result needs replicating, for the 4-bpp case the above
* a full 32 bits. * generates a full 32 bits.
*/ */
# define MASK_EXPAND(m,d) ((m)*((d)==1?0x01010101:((d)==2?0x00010001:1))) # define MASK_EXPAND(m,d) ((m)*((d)==1?0x01010101:((d)==2?0x00010001:1)))
@ -2972,7 +2984,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
png_uint_32 m; png_uint_32 m;
/* It doesn't matter in the following if png_uint_32 has more than /* It doesn't matter in the following if png_uint_32 has more than
* 32 bits because the high bits always match those in m<<24, it is, * 32 bits because the high bits always match those in m<<24; it is,
* however, essential to use OR here, not +, because of this. * however, essential to use OR here, not +, because of this.
*/ */
m = mask; m = mask;
@ -2988,7 +3000,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
} }
/* NOTE: this may overwrite the last byte with garbage if the image /* NOTE: this may overwrite the last byte with garbage if the image
* is not an exact number of bytes wide, libpng has always done * is not an exact number of bytes wide; libpng has always done
* this. * this.
*/ */
if (row_width <= pixels_per_byte) if (row_width <= pixels_per_byte)
@ -3044,7 +3056,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
bytes_to_jump = PNG_PASS_COL_OFFSET(pass) * pixel_depth; bytes_to_jump = PNG_PASS_COL_OFFSET(pass) * pixel_depth;
/* And simply copy these bytes. Some optimization is possible here, /* And simply copy these bytes. Some optimization is possible here,
* depending on the value of 'bytes_to_copy'. Speical case the low * depending on the value of 'bytes_to_copy'. Special case the low
* byte counts, which we know to be frequent. * byte counts, which we know to be frequent.
* *
* Notice that these cases all 'return' rather than 'break' - this * Notice that these cases all 'return' rather than 'break' - this
@ -3067,7 +3079,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
} }
case 2: case 2:
/* There is a possibility of a partial copy at the end here, this /* There is a possibility of a partial copy at the end here; this
* slows the code down somewhat. * slows the code down somewhat.
*/ */
do do
@ -3105,12 +3117,12 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
default: default:
#if PNG_ALIGN_TYPE != PNG_ALIGN_NONE #if PNG_ALIGN_TYPE != PNG_ALIGN_NONE
/* Check for double byte alignment and, if possible, use a 16 /* Check for double byte alignment and, if possible, use a
* bit copy. Don't attempt this for narrow images - ones that * 16-bit copy. Don't attempt this for narrow images - ones that
* are less than an interlace panel wide. Don't attempt it for * are less than an interlace panel wide. Don't attempt it for
* wide bytes-to-copy either - use the memcpy there. * wide bytes-to-copy either - use the png_memcpy there.
*/ */
if (bytes_to_copy < 16 /*else use memcpy*/ && if (bytes_to_copy < 16 /*else use png_memcpy*/ &&
png_isaligned(dp, png_uint_16) && png_isaligned(dp, png_uint_16) &&
png_isaligned(sp, png_uint_16) && png_isaligned(sp, png_uint_16) &&
bytes_to_copy % sizeof (png_uint_16) == 0 && bytes_to_copy % sizeof (png_uint_16) == 0 &&
@ -3150,7 +3162,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
/* Get to here when the row_width truncates the final copy. /* Get to here when the row_width truncates the final copy.
* There will be 1-3 bytes left to copy, so don't try the * There will be 1-3 bytes left to copy, so don't try the
* 16bit loop below. * 16-bit loop below.
*/ */
dp = (png_bytep)dp32; dp = (png_bytep)dp32;
sp = (png_const_bytep)sp32; sp = (png_const_bytep)sp32;
@ -3160,7 +3172,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
return; return;
} }
/* Else do it in 16 bit quantities, but only if the size is /* Else do it in 16-bit quantities, but only if the size is
* not too large. * not too large.
*/ */
else else
@ -3189,7 +3201,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
} }
while (bytes_to_copy <= row_width); while (bytes_to_copy <= row_width);
/* End of row - 1 byte left, bytes_to_copy>row_width: */ /* End of row - 1 byte left, bytes_to_copy > row_width: */
dp = (png_bytep)dp16; dp = (png_bytep)dp16;
sp = (png_const_bytep)sp16; sp = (png_const_bytep)sp16;
do do
@ -3200,7 +3212,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
} }
#endif /* PNG_ALIGN_ code */ #endif /* PNG_ALIGN_ code */
/* The true default - use a memcpy: */ /* The true default - use a png_memcpy: */
for (;;) for (;;)
{ {
png_memcpy(dp, sp, bytes_to_copy); png_memcpy(dp, sp, bytes_to_copy);
@ -3224,7 +3236,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
else else
#endif #endif
/* If here then the switch above wasn't used so just memcpy the whole row /* If here then the switch above wasn't used so just png_memcpy the whole row
* from the temporary row buffer (notice that this overwrites the end of the * from the temporary row buffer (notice that this overwrites the end of the
* destination row if it is a partial byte.) * destination row if it is a partial byte.)
*/ */