fix array overrun in PfmFile.resize()

This commit is contained in:
David Rose 2019-10-17 08:31:39 -07:00
parent a019520dbc
commit 210780f021
3 changed files with 44 additions and 22 deletions

View File

@ -43,8 +43,9 @@ FUNCTION_NAME(IMAGETYPE &dest, const IMAGETYPE &source,
WorkType *filter;
float filter_width;
int actual_width;
make_filter(scale, width, filter, filter_width);
make_filter(scale, width, filter, filter_width, actual_width);
for (b = 0; b < source.BSIZE(); b++) {
for (a = 0; a < source.ASIZE(); a++) {
@ -54,7 +55,7 @@ FUNCTION_NAME(IMAGETYPE &dest, const IMAGETYPE &source,
filter_row(temp_dest, dest.ASIZE(),
temp_source, source.ASIZE(),
scale,
filter, filter_width);
filter, filter_width, actual_width);
for (a = 0; a < dest.ASIZE(); a++) {
matrix[a][b] = temp_dest[a];
@ -69,13 +70,13 @@ FUNCTION_NAME(IMAGETYPE &dest, const IMAGETYPE &source,
scale = (float)dest.BSIZE() / (float)source.BSIZE();
temp_dest = (StoreType *)PANDA_MALLOC_ARRAY(dest.BSIZE() * sizeof(StoreType));
make_filter(scale, width, filter, filter_width);
make_filter(scale, width, filter, filter_width, actual_width);
for (a = 0; a < dest.ASIZE(); a++) {
filter_row(temp_dest, dest.BSIZE(),
matrix[a], source.BSIZE(),
scale,
filter, filter_width);
filter, filter_width, actual_width);
for (b = 0; b < dest.BSIZE(); b++) {
dest.SETVAL(a, b, channel, (float)temp_dest[b]/(float)source_max);

View File

@ -49,10 +49,12 @@ FUNCTION_NAME(IMAGETYPE &dest, const IMAGETYPE &source,
WorkType *filter;
float filter_width;
int actual_width;
make_filter(scale, width, filter, filter_width);
make_filter(scale, width, filter, filter_width, actual_width);
for (b = 0; b < source.BSIZE(); b++) {
memset(temp_source, 0, source.ASIZE() * sizeof(StoreType));
memset(temp_source_weight, 0, source.ASIZE() * sizeof(StoreType));
for (a = 0; a < source.ASIZE(); a++) {
if (source.HASVAL(a, b)) {
@ -64,9 +66,10 @@ FUNCTION_NAME(IMAGETYPE &dest, const IMAGETYPE &source,
filter_sparse_row(temp_dest, temp_dest_weight, dest.ASIZE(),
temp_source, temp_source_weight, source.ASIZE(),
scale,
filter, filter_width);
filter, filter_width, actual_width);
for (a = 0; a < dest.ASIZE(); a++) {
nassertv(!isnan(temp_dest[a]) && !isnan(temp_dest_weight[a]));
matrix[a][b] = temp_dest[a];
matrix_weight[a][b] = temp_dest_weight[a];
}
@ -83,17 +86,19 @@ FUNCTION_NAME(IMAGETYPE &dest, const IMAGETYPE &source,
temp_dest = (StoreType *)PANDA_MALLOC_ARRAY(dest.BSIZE() * sizeof(StoreType));
temp_dest_weight = (StoreType *)PANDA_MALLOC_ARRAY(dest.BSIZE() * sizeof(StoreType));
make_filter(scale, width, filter, filter_width);
make_filter(scale, width, filter, filter_width, actual_width);
for (a = 0; a < dest.ASIZE(); a++) {
filter_sparse_row(temp_dest, temp_dest_weight, dest.BSIZE(),
matrix[a], matrix_weight[a], source.BSIZE(),
scale,
filter, filter_width);
filter, filter_width, actual_width);
for (b = 0; b < dest.BSIZE(); b++) {
nassertv(!isnan(temp_dest[b]) && !isnan(temp_dest_weight[b]));
if (temp_dest_weight[b] != 0) {
dest.SETVAL(a, b, channel, (float)temp_dest[b]/(float)source_max);
dest.SETVAL(a, b, channel, (float)temp_dest[b]/(float)temp_dest_weight[b]);
nassertv(!isnan(dest.GETVAL(a, b, channel)));
}
}
}

View File

@ -110,7 +110,8 @@ filter_row(StoreType dest[], int dest_len,
const StoreType source[], int source_len,
float scale, // == dest_len / source_len
const WorkType filter[],
float filter_width) {
float filter_width,
int actual_width) {
// If we are expanding the row (scale > 1.0), we need to look at a
// fractional granularity. Hence, we scale our filter index by scale. If
// we are compressing (scale < 1.0), we don't need to fiddle with the filter
@ -147,13 +148,15 @@ filter_row(StoreType dest[], int dest_len,
// of center--so we don't have to incur the overhead of calling fabs()
// each time through the loop.
for (source_x = left; source_x < right_center; source_x++) {
index = (int)(iscale * (center - source_x) + 0.5f);
index = (int)cfloor(iscale * (center - source_x) + 0.5f);
nassertv(index >= 0 && index < actual_width);
net_value += filter[index] * source[source_x];
net_weight += filter[index];
}
for (; source_x <= right; source_x++) {
index = (int)(iscale * (source_x - center) + 0.5f);
index = (int)cfloor(iscale * (source_x - center) + 0.5f);
nassertv(index >= 0 && index < actual_width);
net_value += filter[index] * source[source_x];
net_weight += filter[index];
}
@ -174,15 +177,16 @@ filter_sparse_row(StoreType dest[], StoreType dest_weight[], int dest_len,
const StoreType source[], const StoreType source_weight[], int source_len,
float scale, // == dest_len / source_len
const WorkType filter[],
float filter_width) {
float filter_width,
int actual_width) {
// If we are expanding the row (scale > 1.0), we need to look at a
// fractional granularity. Hence, we scale our filter index by scale. If
// we are compressing (scale < 1.0), we don't need to fiddle with the filter
// index, so we leave it at one.
float iscale;
if (scale < 1.0) {
iscale = 1.0;
if (scale < 1.0f) {
iscale = 1.0f;
filter_width /= scale;
} else {
iscale = scale;
@ -211,13 +215,15 @@ filter_sparse_row(StoreType dest[], StoreType dest_weight[], int dest_len,
// of center--so we don't have to incur the overhead of calling fabs()
// each time through the loop.
for (source_x = left; source_x < right_center; source_x++) {
index = (int)(iscale * (center - source_x) + 0.5f);
index = (int)cfloor(iscale * (center - source_x) + 0.5f);
nassertv(index >= 0 && index < actual_width);
net_value += filter[index] * source[source_x] * source_weight[source_x];
net_weight += filter[index] * source_weight[source_x];
}
for (; source_x <= right; source_x++) {
index = (int)(iscale * (source_x - center) + 0.5f);
index = (int)cfloor(iscale * (source_x - center) + 0.5f);
nassertv(index >= 0 && index < actual_width);
net_value += filter[index] * source[source_x] * source_weight[source_x];
net_weight += filter[index] * source_weight[source_x];
}
@ -244,11 +250,12 @@ filter_sparse_row(StoreType dest[], StoreType dest_weight[], int dest_len,
// corresponding to values in the range -filter_width to filter_width.
typedef void FilterFunction(float scale, float width,
WorkType *&filter, float &filter_width);
WorkType *&filter, float &filter_width, int &actual_width);
static void
box_filter_impl(float scale, float width,
WorkType *&filter, float &filter_width) {
WorkType *&filter, float &filter_width,
int &actual_width) {
float fscale;
if (scale < 1.0) {
// If we are compressing the image, we want to expand the range of the
@ -263,7 +270,11 @@ box_filter_impl(float scale, float width,
fscale = scale;
}
filter_width = width;
int actual_width = (int)cceil((filter_width + 1) * fscale) + 1;
// It seems we need a buffer of two extra values in the filter array
// to allow room for all calculations (especially including the 1/2
// pixel offset).
actual_width = (int)cceil((filter_width + 1) * fscale) + 2;
filter = (WorkType *)PANDA_MALLOC_ARRAY(actual_width * sizeof(WorkType));
@ -274,7 +285,8 @@ box_filter_impl(float scale, float width,
static void
gaussian_filter_impl(float scale, float width,
WorkType *&filter, float &filter_width) {
WorkType *&filter, float &filter_width,
int &actual_width) {
float fscale;
if (scale < 1.0) {
// If we are compressing the image, we want to expand the range of the
@ -291,7 +303,11 @@ gaussian_filter_impl(float scale, float width,
float sigma = width/2;
filter_width = 3.0 * sigma;
int actual_width = (int)cceil((filter_width + 1) * fscale);
// It seems we need a buffer of two extra values in the filter array
// to allow room for all calculations (especially including the 1/2
// pixel offset).
actual_width = (int)cceil((filter_width + 1) * fscale) + 2;
// G(x, y) = (1(2 pi sigma^2)) * exp( - (x^2 + y^2) (2 sigma^2))