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++;
|
num_filters++;
|
||||||
|
|
||||||
if (num_filters > 1)
|
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 */
|
#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;
|
for (lp = png_ptr->row_buf + 1; i < row_bytes;
|
||||||
i++, rp++, lp++, dp++)
|
i++, rp++, lp++, dp++)
|
||||||
{
|
{
|
||||||
png_size_t old_sum = sum;
|
|
||||||
|
|
||||||
v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
|
v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
|
||||||
sum += (v < 128) ? v : 256 - v;
|
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. */
|
if (sum > lmins) /* We are already worse, don't continue. */
|
||||||
break;
|
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;
|
pp = png_ptr->prev_row + 1; i < row_bytes;
|
||||||
i++, rp++, pp++, dp++)
|
i++, rp++, pp++, dp++)
|
||||||
{
|
{
|
||||||
png_size_t old_sum = sum;
|
|
||||||
|
|
||||||
v = *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
|
v = *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
|
||||||
sum += (v < 128) ? v : 256 - v;
|
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. */
|
if (sum > lmins) /* We are already worse, don't continue. */
|
||||||
break;
|
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++)
|
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))
|
v = *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
|
||||||
& 0xff);
|
& 0xff);
|
||||||
|
|
||||||
sum += (v < 128) ? v : 256 - v;
|
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. */
|
if (sum > lmins) /* We are already worse, don't continue. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2487,7 +2464,6 @@ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp,
|
|||||||
i++)
|
i++)
|
||||||
{
|
{
|
||||||
int a, b, c, pa, pb, pc, p;
|
int a, b, c, pa, pb, pc, p;
|
||||||
png_size_t old_sum = sum;
|
|
||||||
|
|
||||||
b = *pp++;
|
b = *pp++;
|
||||||
c = *cp++;
|
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;
|
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. */
|
if (sum > lmins) /* We are already worse, don't continue. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2525,12 +2495,54 @@ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp,
|
|||||||
return (sum);
|
return (sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1)
|
|
||||||
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
|
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
|
||||||
|
|
||||||
|
#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1)
|
||||||
#define PNG_HISHIFT 10
|
#define PNG_HISHIFT 10
|
||||||
#define PNG_LOMASK ((png_uint_32)0xffffL)
|
#define PNG_LOMASK ((png_uint_32)0xffffL)
|
||||||
#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT))
|
#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_WEIGHTED_FILTER */
|
||||||
|
|
||||||
#endif /* WRITE_FILTER */
|
#endif /* WRITE_FILTER */
|
||||||
|
|
||||||
void /* PRIVATE */
|
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;
|
bpp = (row_info->pixel_depth + 7) >> 3;
|
||||||
|
|
||||||
row_buf = png_ptr->row_buf;
|
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
|
/* The prediction method we use is to find which method provides the
|
||||||
* smallest value when summing the absolute values of the distances
|
* 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;
|
best_row = png_ptr->row_buf;
|
||||||
|
|
||||||
|
|
||||||
if ((filter_to_do & PNG_FILTER_NONE) != 0 && filter_to_do != PNG_FILTER_NONE)
|
if ((filter_to_do & PNG_FILTER_NONE) != 0 && filter_to_do != PNG_FILTER_NONE)
|
||||||
{
|
{
|
||||||
png_bytep rp;
|
png_bytep rp;
|
||||||
@ -2602,12 +2616,6 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
|
|||||||
png_size_t i;
|
png_size_t i;
|
||||||
int v;
|
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
|
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
|
||||||
if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
|
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;
|
sum = (sumhi << PNG_HISHIFT) + sumlo;
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
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 sum;
|
||||||
png_size_t lmins = mins;
|
png_size_t lmins = mins;
|
||||||
|
|
||||||
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
|
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
|
||||||
/* We temporarily increase the "minimum sum" by the factor we
|
png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB;
|
||||||
* would reduce the sum of this filter, so that we can do the
|
|
||||||
* early exit comparison without scaling the sum each time.
|
|
||||||
*/
|
|
||||||
if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
|
if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
|
||||||
{
|
lmins = png_increase_lmins(png_ptr, lmins);
|
||||||
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;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sum = png_setup_sub_row(png_ptr, bpp, row_bytes, lmins);
|
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 sum;
|
||||||
png_size_t lmins = mins;
|
png_size_t lmins = mins;
|
||||||
|
|
||||||
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
|
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
|
||||||
|
png_ptr->try_row[0] = PNG_FILTER_VALUE_UP;
|
||||||
if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
|
if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
|
||||||
{
|
lmins = png_increase_lmins(png_ptr, lmins);
|
||||||
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;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sum = png_setup_up_row(png_ptr, row_bytes, lmins);
|
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 sum;
|
||||||
png_size_t lmins = mins;
|
png_size_t lmins = mins;
|
||||||
|
|
||||||
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
|
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
|
||||||
|
png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG;
|
||||||
if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
|
if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
|
||||||
{
|
lmins = png_increase_lmins(png_ptr, lmins);
|
||||||
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;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sum= png_setup_avg_row(png_ptr, bpp, row_bytes, lmins);
|
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 sum;
|
||||||
png_size_t lmins = mins;
|
png_size_t lmins = mins;
|
||||||
|
|
||||||
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
|
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
|
||||||
|
png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH;
|
||||||
if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
|
if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
|
||||||
{
|
lmins = png_increase_lmins(png_ptr, lmins);
|
||||||
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;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sum = png_setup_paeth_row(png_ptr, bpp, row_bytes, lmins);
|
sum = png_setup_paeth_row(png_ptr, bpp, row_bytes, lmins);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user