mirror of
https://git.code.sf.net/p/libpng/code.git
synced 2025-07-10 18:04:09 +02:00
[libpng17] Revised overflow detection in pngwutil.c
This commit is contained in:
parent
d368235da4
commit
1d3a1e36a7
246
pngwutil.c
246
pngwutil.c
@ -1974,7 +1974,8 @@ png_write_alloc_filter_row_buffers(png_structrp png_ptr, int filters)
|
||||
num_filters++;
|
||||
|
||||
if (num_filters > 1)
|
||||
png_ptr->tst_row = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size));
|
||||
png_ptr->tst_row = png_voidcast(png_bytep,
|
||||
png_malloc(png_ptr, buf_size));
|
||||
}
|
||||
}
|
||||
#endif /* WRITE_FILTER */
|
||||
@ -2372,17 +2373,9 @@ png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp,
|
||||
for (lp = png_ptr->row_buf + 1; i < row_bytes;
|
||||
i++, rp++, lp++, dp++)
|
||||
{
|
||||
png_size_t old_sum = sum;
|
||||
|
||||
v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
|
||||
sum += (v < 128) ? v : 256 - v;
|
||||
|
||||
if (sum < old_sum) /* overflow happened */
|
||||
{
|
||||
sum = PNG_SIZE_MAX - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sum > lmins) /* We are already worse, don't continue. */
|
||||
break;
|
||||
}
|
||||
@ -2405,17 +2398,9 @@ png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes,
|
||||
pp = png_ptr->prev_row + 1; i < row_bytes;
|
||||
i++, rp++, pp++, dp++)
|
||||
{
|
||||
png_size_t old_sum = sum;
|
||||
|
||||
v = *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
|
||||
sum += (v < 128) ? v : 256 - v;
|
||||
|
||||
if (sum < old_sum) /* overflow happened */
|
||||
{
|
||||
sum = PNG_SIZE_MAX - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sum > lmins) /* We are already worse, don't continue. */
|
||||
break;
|
||||
}
|
||||
@ -2444,19 +2429,11 @@ png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp,
|
||||
|
||||
for (lp = png_ptr->row_buf + 1; i < row_bytes; i++)
|
||||
{
|
||||
png_size_t old_sum = sum;
|
||||
|
||||
v = *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
|
||||
& 0xff);
|
||||
|
||||
sum += (v < 128) ? v : 256 - v;
|
||||
|
||||
if (sum < old_sum) /* overflow happened */
|
||||
{
|
||||
sum = PNG_SIZE_MAX - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sum > lmins) /* We are already worse, don't continue. */
|
||||
break;
|
||||
}
|
||||
@ -2487,7 +2464,6 @@ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp,
|
||||
i++)
|
||||
{
|
||||
int a, b, c, pa, pb, pc, p;
|
||||
png_size_t old_sum = sum;
|
||||
|
||||
b = *pp++;
|
||||
c = *cp++;
|
||||
@ -2512,12 +2488,6 @@ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp,
|
||||
|
||||
sum += (v < 128) ? v : 256 - v;
|
||||
|
||||
if (sum < old_sum) /* overflow happened */
|
||||
{
|
||||
sum = PNG_SIZE_MAX - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sum > lmins) /* We are already worse, don't continue. */
|
||||
break;
|
||||
}
|
||||
@ -2525,12 +2495,54 @@ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp,
|
||||
return (sum);
|
||||
}
|
||||
|
||||
#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1)
|
||||
|
||||
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
|
||||
|
||||
#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1)
|
||||
#define PNG_HISHIFT 10
|
||||
#define PNG_LOMASK ((png_uint_32)0xffffL)
|
||||
#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT))
|
||||
|
||||
static png_size_t /* PRIVATE */
|
||||
png_increase_lmins(png_structrp png_ptr, png_size_t lmins)
|
||||
{
|
||||
/* We temporarily increase the "minimum sum" by the factor we
|
||||
* would reduce the sum of this filter, so that we can do the
|
||||
* early exit comparison without scaling the sum each time.
|
||||
*/
|
||||
int j;
|
||||
png_uint_32 lmhi, lmlo;
|
||||
lmlo = lmins & PNG_LOMASK;
|
||||
lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
|
||||
|
||||
for (j = 0; j < png_ptr->num_prev_filters; j++)
|
||||
{
|
||||
if (png_ptr->prev_filters[j] == png_ptr->try_row[0])
|
||||
{
|
||||
lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
|
||||
PNG_WEIGHT_SHIFT;
|
||||
|
||||
lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
|
||||
PNG_WEIGHT_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
lmlo = (lmlo * png_ptr->inv_filter_costs[png_ptr->try_row[0]]) >>
|
||||
PNG_COST_SHIFT;
|
||||
|
||||
lmhi = (lmhi * png_ptr->inv_filter_costs[png_ptr->try_row[0]]) >>
|
||||
PNG_COST_SHIFT;
|
||||
|
||||
if (lmhi > PNG_HIMASK)
|
||||
lmins = PNG_MAXSUM;
|
||||
|
||||
else
|
||||
lmins = (lmhi << PNG_HISHIFT) + lmlo;
|
||||
|
||||
return (lmins);
|
||||
}
|
||||
#endif /* WRITE_WEIGHTED_FILTER */
|
||||
|
||||
#endif /* WRITE_FILTER */
|
||||
|
||||
void /* PRIVATE */
|
||||
@ -2563,7 +2575,8 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
|
||||
bpp = (row_info->pixel_depth + 7) >> 3;
|
||||
|
||||
row_buf = png_ptr->row_buf;
|
||||
mins = PNG_SIZE_MAX;
|
||||
mins = PNG_SIZE_MAX - 256/* so we can detect potential overflow of the
|
||||
running sum */;
|
||||
|
||||
/* The prediction method we use is to find which method provides the
|
||||
* smallest value when summing the absolute values of the distances
|
||||
@ -2595,6 +2608,7 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
|
||||
*/
|
||||
best_row = png_ptr->row_buf;
|
||||
|
||||
|
||||
if ((filter_to_do & PNG_FILTER_NONE) != 0 && filter_to_do != PNG_FILTER_NONE)
|
||||
{
|
||||
png_bytep rp;
|
||||
@ -2602,12 +2616,6 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
|
||||
png_size_t i;
|
||||
int v;
|
||||
|
||||
for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
|
||||
{
|
||||
v = *rp;
|
||||
sum += (v < 128) ? v : 256 - v;
|
||||
}
|
||||
|
||||
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
|
||||
if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
|
||||
{
|
||||
@ -2646,6 +2654,28 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
|
||||
sum = (sumhi << PNG_HISHIFT) + sumlo;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (PNG_SIZE_MAX/128 <= row_bytes)
|
||||
{
|
||||
for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
|
||||
{
|
||||
/* Check for overflow */
|
||||
if (sum > PNG_SIZE_MAX/128 - 256)
|
||||
break;
|
||||
|
||||
v = *rp;
|
||||
sum += (v < 128) ? v : 256 - v;
|
||||
}
|
||||
}
|
||||
else /* Overflow is not possible */
|
||||
{
|
||||
for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
|
||||
{
|
||||
v = *rp;
|
||||
sum += (v < 128) ? v : 256 - v;
|
||||
}
|
||||
}
|
||||
|
||||
mins = sum;
|
||||
}
|
||||
|
||||
@ -2661,43 +2691,10 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
|
||||
{
|
||||
png_size_t sum;
|
||||
png_size_t lmins = mins;
|
||||
|
||||
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
|
||||
/* We temporarily increase the "minimum sum" by the factor we
|
||||
* would reduce the sum of this filter, so that we can do the
|
||||
* early exit comparison without scaling the sum each time.
|
||||
*/
|
||||
png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB;
|
||||
if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
|
||||
{
|
||||
int j;
|
||||
png_uint_32 lmhi, lmlo;
|
||||
lmlo = lmins & PNG_LOMASK;
|
||||
lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
|
||||
|
||||
for (j = 0; j < num_p_filters; j++)
|
||||
{
|
||||
if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
|
||||
{
|
||||
lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
|
||||
PNG_WEIGHT_SHIFT;
|
||||
|
||||
lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
|
||||
PNG_WEIGHT_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
|
||||
PNG_COST_SHIFT;
|
||||
|
||||
lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
|
||||
PNG_COST_SHIFT;
|
||||
|
||||
if (lmhi > PNG_HIMASK)
|
||||
lmins = PNG_MAXSUM;
|
||||
|
||||
else
|
||||
lmins = (lmhi << PNG_HISHIFT) + lmlo;
|
||||
}
|
||||
lmins = png_increase_lmins(png_ptr, lmins);
|
||||
#endif
|
||||
|
||||
sum = png_setup_sub_row(png_ptr, bpp, row_bytes, lmins);
|
||||
@ -2759,39 +2756,10 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
|
||||
{
|
||||
png_size_t sum;
|
||||
png_size_t lmins = mins;
|
||||
|
||||
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
|
||||
png_ptr->try_row[0] = PNG_FILTER_VALUE_UP;
|
||||
if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
|
||||
{
|
||||
int j;
|
||||
png_uint_32 lmhi, lmlo;
|
||||
lmlo = lmins & PNG_LOMASK;
|
||||
lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
|
||||
|
||||
for (j = 0; j < num_p_filters; j++)
|
||||
{
|
||||
if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
|
||||
{
|
||||
lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
|
||||
PNG_WEIGHT_SHIFT;
|
||||
|
||||
lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
|
||||
PNG_WEIGHT_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
|
||||
PNG_COST_SHIFT;
|
||||
|
||||
lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
|
||||
PNG_COST_SHIFT;
|
||||
|
||||
if (lmhi > PNG_HIMASK)
|
||||
lmins = PNG_MAXSUM;
|
||||
|
||||
else
|
||||
lmins = (lmhi << PNG_HISHIFT) + lmlo;
|
||||
}
|
||||
lmins = png_increase_lmins(png_ptr, lmins);
|
||||
#endif
|
||||
|
||||
sum = png_setup_up_row(png_ptr, row_bytes, lmins);
|
||||
@ -2853,39 +2821,10 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
|
||||
{
|
||||
png_size_t sum;
|
||||
png_size_t lmins = mins;
|
||||
|
||||
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
|
||||
png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG;
|
||||
if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
|
||||
{
|
||||
int j;
|
||||
png_uint_32 lmhi, lmlo;
|
||||
lmlo = lmins & PNG_LOMASK;
|
||||
lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
|
||||
|
||||
for (j = 0; j < num_p_filters; j++)
|
||||
{
|
||||
if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG)
|
||||
{
|
||||
lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
|
||||
PNG_WEIGHT_SHIFT;
|
||||
|
||||
lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
|
||||
PNG_WEIGHT_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
|
||||
PNG_COST_SHIFT;
|
||||
|
||||
lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
|
||||
PNG_COST_SHIFT;
|
||||
|
||||
if (lmhi > PNG_HIMASK)
|
||||
lmins = PNG_MAXSUM;
|
||||
|
||||
else
|
||||
lmins = (lmhi << PNG_HISHIFT) + lmlo;
|
||||
}
|
||||
lmins = png_increase_lmins(png_ptr, lmins);
|
||||
#endif
|
||||
|
||||
sum= png_setup_avg_row(png_ptr, bpp, row_bytes, lmins);
|
||||
@ -2947,39 +2886,10 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
|
||||
{
|
||||
png_size_t sum;
|
||||
png_size_t lmins = mins;
|
||||
|
||||
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
|
||||
png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH;
|
||||
if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
|
||||
{
|
||||
int j;
|
||||
png_uint_32 lmhi, lmlo;
|
||||
lmlo = lmins & PNG_LOMASK;
|
||||
lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
|
||||
|
||||
for (j = 0; j < num_p_filters; j++)
|
||||
{
|
||||
if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
|
||||
{
|
||||
lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
|
||||
PNG_WEIGHT_SHIFT;
|
||||
|
||||
lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
|
||||
PNG_WEIGHT_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
|
||||
PNG_COST_SHIFT;
|
||||
|
||||
lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
|
||||
PNG_COST_SHIFT;
|
||||
|
||||
if (lmhi > PNG_HIMASK)
|
||||
lmins = PNG_MAXSUM;
|
||||
|
||||
else
|
||||
lmins = (lmhi << PNG_HISHIFT) + lmlo;
|
||||
}
|
||||
lmins = png_increase_lmins(png_ptr, lmins);
|
||||
#endif
|
||||
|
||||
sum = png_setup_paeth_row(png_ptr, bpp, row_bytes, lmins);
|
||||
|
Loading…
x
Reference in New Issue
Block a user