replace 'ptr + y * stride' by 'ptr += stride'

This is to prevent potential overflow.

Change-Id: I9d21cfe790ba975bd5e117b025ea4d9deaeae4ab
This commit is contained in:
Pascal Massimino 2017-01-04 00:54:23 -08:00
parent 00b08c88c0
commit 259e98286a
4 changed files with 134 additions and 98 deletions

View File

@ -150,6 +150,7 @@ static int DumpFrame(const char filename[], const char dump_folder[],
const char* base_name = NULL; const char* base_name = NULL;
char* file_name = NULL; char* file_name = NULL;
FILE* f = NULL; FILE* f = NULL;
const char* row;
base_name = strrchr(filename, '/'); base_name = strrchr(filename, '/');
base_name = (base_name == NULL) ? filename : base_name + 1; base_name = (base_name == NULL) ? filename : base_name + 1;
@ -176,12 +177,13 @@ static int DumpFrame(const char filename[], const char dump_folder[],
fprintf(stderr, "Write error for file %s\n", file_name); fprintf(stderr, "Write error for file %s\n", file_name);
goto End; goto End;
} }
row = (const char*)rgba;
for (y = 0; y < canvas_height; ++y) { for (y = 0; y < canvas_height; ++y) {
if (fwrite((const char*)(rgba) + y * canvas_width * kNumChannels, if (fwrite(row, canvas_width * kNumChannels, 1, f) != 1) {
canvas_width * kNumChannels, 1, f) != 1) {
fprintf(stderr, "Error writing to file: %s\n", file_name); fprintf(stderr, "Error writing to file: %s\n", file_name);
goto End; goto End;
} }
row += canvas_width * kNumChannels;
} }
ok = 1; ok = 1;
End: End:
@ -743,7 +745,7 @@ void GetDiffAndPSNR(const uint8_t rgba1[], const uint8_t rgba2[],
for (y = 0; y < height; ++y) { for (y = 0; y < height; ++y) {
for (x = 0; x < stride; x += kNumChannels) { for (x = 0; x < stride; x += kNumChannels) {
int k; int k;
const size_t offset = y * stride + x; const size_t offset = (size_t)y * stride + x;
const int alpha1 = rgba1[offset + kAlphaChannel]; const int alpha1 = rgba1[offset + kAlphaChannel];
const int alpha2 = rgba2[offset + kAlphaChannel]; const int alpha2 = rgba2[offset + kAlphaChannel];
Accumulate(alpha1, alpha2, &f_max_diff, &sse); Accumulate(alpha1, alpha2, &f_max_diff, &sse);

View File

@ -297,6 +297,10 @@ static int DumpPicture(const WebPPicture* const picture, const char* PGM_name) {
const int uv_width = (picture->width + 1) / 2; const int uv_width = (picture->width + 1) / 2;
const int uv_height = (picture->height + 1) / 2; const int uv_height = (picture->height + 1) / 2;
const int stride = (picture->width + 1) & ~1; const int stride = (picture->width + 1) & ~1;
const uint8_t* src_y = picture->y;
const uint8_t* src_u = picture->u;
const uint8_t* src_v = picture->v;
const uint8_t* src_a = picture->a;
const int alpha_height = const int alpha_height =
WebPPictureHasTransparency(picture) ? picture->height : 0; WebPPictureHasTransparency(picture) ? picture->height : 0;
const int height = picture->height + uv_height + alpha_height; const int height = picture->height + uv_height + alpha_height;
@ -304,24 +308,20 @@ static int DumpPicture(const WebPPicture* const picture, const char* PGM_name) {
if (f == NULL) return 0; if (f == NULL) return 0;
fprintf(f, "P5\n%d %d\n255\n", stride, height); fprintf(f, "P5\n%d %d\n255\n", stride, height);
for (y = 0; y < picture->height; ++y) { for (y = 0; y < picture->height; ++y) {
if (fwrite(picture->y + y * picture->y_stride, picture->width, 1, f) != 1) { if (fwrite(src_y, picture->width, 1, f) != 1) return 0;
return 0;
}
if (picture->width & 1) fputc(0, f); // pad if (picture->width & 1) fputc(0, f); // pad
src_y += picture->y_stride;
} }
for (y = 0; y < uv_height; ++y) { for (y = 0; y < uv_height; ++y) {
if (fwrite(picture->u + y * picture->uv_stride, uv_width, 1, f) != 1) { if (fwrite(src_u, uv_width, 1, f) != 1) return 0;
return 0; if (fwrite(src_v, uv_width, 1, f) != 1) return 0;
} src_u += picture->uv_stride;
if (fwrite(picture->v + y * picture->uv_stride, uv_width, 1, f) != 1) { src_v += picture->uv_stride;
return 0;
}
} }
for (y = 0; y < alpha_height; ++y) { for (y = 0; y < alpha_height; ++y) {
if (fwrite(picture->a + y * picture->a_stride, picture->width, 1, f) != 1) { if (fwrite(src_a, picture->width, 1, f) != 1) return 0;
return 0;
}
if (picture->width & 1) fputc(0, f); // pad if (picture->width & 1) fputc(0, f); // pad
src_a += picture->a_stride;
} }
fclose(f); fclose(f);
return 1; return 1;

View File

@ -160,7 +160,7 @@ static void PNGAPI PNGErrorFunction(png_structp png, png_const_charp dummy) {
int WebPWritePNG(FILE* out_file, const WebPDecBuffer* const buffer) { int WebPWritePNG(FILE* out_file, const WebPDecBuffer* const buffer) {
const uint32_t width = buffer->width; const uint32_t width = buffer->width;
const uint32_t height = buffer->height; const uint32_t height = buffer->height;
uint8_t* const rgb = buffer->u.RGBA.rgba; png_bytep row = buffer->u.RGBA.rgba;
const int stride = buffer->u.RGBA.stride; const int stride = buffer->u.RGBA.stride;
const int has_alpha = WebPIsAlphaMode(buffer->colorspace); const int has_alpha = WebPIsAlphaMode(buffer->colorspace);
volatile png_structp png; volatile png_structp png;
@ -190,8 +190,8 @@ int WebPWritePNG(FILE* out_file, const WebPDecBuffer* const buffer) {
PNG_FILTER_TYPE_DEFAULT); PNG_FILTER_TYPE_DEFAULT);
png_write_info(png, info); png_write_info(png, info);
for (y = 0; y < height; ++y) { for (y = 0; y < height; ++y) {
png_bytep row = rgb + y * stride;
png_write_rows(png, &row, 1); png_write_rows(png, &row, 1);
row += stride;
} }
png_write_end(png, info); png_write_end(png, info);
png_destroy_write_struct((png_structpp)&png, (png_infopp)&info); png_destroy_write_struct((png_structpp)&png, (png_infopp)&info);
@ -213,14 +213,17 @@ int WebPWritePNG(FILE* fout, const WebPDecBuffer* const buffer) {
static int WritePPMPAM(FILE* fout, const WebPDecBuffer* const buffer, static int WritePPMPAM(FILE* fout, const WebPDecBuffer* const buffer,
int alpha) { int alpha) {
if (fout == NULL || buffer == NULL) {
return 0;
} else {
const uint32_t width = buffer->width; const uint32_t width = buffer->width;
const uint32_t height = buffer->height; const uint32_t height = buffer->height;
const uint8_t* const rgb = buffer->u.RGBA.rgba; const uint8_t* row = buffer->u.RGBA.rgba;
const int stride = buffer->u.RGBA.stride; const int stride = buffer->u.RGBA.stride;
const size_t bytes_per_px = alpha ? 4 : 3; const size_t bytes_per_px = alpha ? 4 : 3;
uint32_t y; uint32_t y;
if (fout == NULL || buffer == NULL || rgb == NULL) return 0; if (row == NULL) return 0;
if (alpha) { if (alpha) {
fprintf(fout, "P7\nWIDTH %u\nHEIGHT %u\nDEPTH 4\nMAXVAL 255\n" fprintf(fout, "P7\nWIDTH %u\nHEIGHT %u\nDEPTH 4\nMAXVAL 255\n"
@ -229,9 +232,11 @@ static int WritePPMPAM(FILE* fout, const WebPDecBuffer* const buffer,
fprintf(fout, "P6\n%u %u\n255\n", width, height); fprintf(fout, "P6\n%u %u\n255\n", width, height);
} }
for (y = 0; y < height; ++y) { for (y = 0; y < height; ++y) {
if (fwrite(rgb + y * stride, width, bytes_per_px, fout) != bytes_per_px) { if (fwrite(row, width, bytes_per_px, fout) != bytes_per_px) {
return 0; return 0;
} }
row += stride;
}
} }
return 1; return 1;
} }
@ -251,7 +256,7 @@ int WebPWritePAM(FILE* fout, const WebPDecBuffer* const buffer) {
int WebPWrite16bAsPGM(FILE* fout, const WebPDecBuffer* const buffer) { int WebPWrite16bAsPGM(FILE* fout, const WebPDecBuffer* const buffer) {
const uint32_t width = buffer->width; const uint32_t width = buffer->width;
const uint32_t height = buffer->height; const uint32_t height = buffer->height;
const uint8_t* const rgba = buffer->u.RGBA.rgba; const uint8_t* rgba = buffer->u.RGBA.rgba;
const int stride = buffer->u.RGBA.stride; const int stride = buffer->u.RGBA.stride;
const uint32_t bytes_per_px = 2; const uint32_t bytes_per_px = 2;
uint32_t y; uint32_t y;
@ -260,9 +265,10 @@ int WebPWrite16bAsPGM(FILE* fout, const WebPDecBuffer* const buffer) {
fprintf(fout, "P5\n%u %u\n255\n", width * bytes_per_px, height); fprintf(fout, "P5\n%u %u\n255\n", width * bytes_per_px, height);
for (y = 0; y < height; ++y) { for (y = 0; y < height; ++y) {
if (fwrite(rgba + y * stride, width, bytes_per_px, fout) != bytes_per_px) { if (fwrite(rgba, width, bytes_per_px, fout) != bytes_per_px) {
return 0; return 0;
} }
rgba += stride;
} }
return 1; return 1;
} }
@ -285,7 +291,7 @@ int WebPWriteBMP(FILE* fout, const WebPDecBuffer* const buffer) {
const int has_alpha = WebPIsAlphaMode(buffer->colorspace); const int has_alpha = WebPIsAlphaMode(buffer->colorspace);
const uint32_t width = buffer->width; const uint32_t width = buffer->width;
const uint32_t height = buffer->height; const uint32_t height = buffer->height;
const uint8_t* const rgba = buffer->u.RGBA.rgba; const uint8_t* rgba = buffer->u.RGBA.rgba;
const int stride = buffer->u.RGBA.stride; const int stride = buffer->u.RGBA.stride;
const uint32_t bytes_per_px = has_alpha ? 4 : 3; const uint32_t bytes_per_px = has_alpha ? 4 : 3;
uint32_t y; uint32_t y;
@ -323,7 +329,7 @@ int WebPWriteBMP(FILE* fout, const WebPDecBuffer* const buffer) {
// write pixel array // write pixel array
for (y = 0; y < height; ++y) { for (y = 0; y < height; ++y) {
if (fwrite(rgba + y * stride, line_size, 1, fout) != 1) { if (fwrite(rgba, line_size, 1, fout) != 1) {
return 0; return 0;
} }
// write padding zeroes // write padding zeroes
@ -333,6 +339,7 @@ int WebPWriteBMP(FILE* fout, const WebPDecBuffer* const buffer) {
return 0; return 0;
} }
} }
rgba += stride;
} }
return 1; return 1;
} }
@ -351,7 +358,7 @@ int WebPWriteTIFF(FILE* fout, const WebPDecBuffer* const buffer) {
const int has_alpha = WebPIsAlphaMode(buffer->colorspace); const int has_alpha = WebPIsAlphaMode(buffer->colorspace);
const uint32_t width = buffer->width; const uint32_t width = buffer->width;
const uint32_t height = buffer->height; const uint32_t height = buffer->height;
const uint8_t* const rgba = buffer->u.RGBA.rgba; const uint8_t* rgba = buffer->u.RGBA.rgba;
const int stride = buffer->u.RGBA.stride; const int stride = buffer->u.RGBA.stride;
const uint8_t bytes_per_px = has_alpha ? 4 : 3; const uint8_t bytes_per_px = has_alpha ? 4 : 3;
// For non-alpha case, we omit tag 0x152 (ExtraSamples). // For non-alpha case, we omit tag 0x152 (ExtraSamples).
@ -404,9 +411,10 @@ int WebPWriteTIFF(FILE* fout, const WebPDecBuffer* const buffer) {
} }
// write pixel values // write pixel values
for (y = 0; y < height; ++y) { for (y = 0; y < height; ++y) {
if (fwrite(rgba + y * stride, bytes_per_px, width, fout) != width) { if (fwrite(rgba, bytes_per_px, width, fout) != width) {
return 0; return 0;
} }
rgba += stride;
} }
return 1; return 1;
@ -421,86 +429,111 @@ int WebPWriteTIFF(FILE* fout, const WebPDecBuffer* const buffer) {
// Raw Alpha // Raw Alpha
int WebPWriteAlphaPlane(FILE* fout, const WebPDecBuffer* const buffer) { int WebPWriteAlphaPlane(FILE* fout, const WebPDecBuffer* const buffer) {
if (fout == NULL || buffer == NULL) {
return 0;
} else {
const uint32_t width = buffer->width; const uint32_t width = buffer->width;
const uint32_t height = buffer->height; const uint32_t height = buffer->height;
const uint8_t* const a = buffer->u.YUVA.a; const uint8_t* a = buffer->u.YUVA.a;
const int a_stride = buffer->u.YUVA.a_stride; const int a_stride = buffer->u.YUVA.a_stride;
uint32_t y; uint32_t y;
if (fout == NULL || buffer == NULL || a == NULL) return 0; if (a == NULL) return 0;
fprintf(fout, "P5\n%u %u\n255\n", width, height); fprintf(fout, "P5\n%u %u\n255\n", width, height);
for (y = 0; y < height; ++y) { for (y = 0; y < height; ++y) {
if (fwrite(a + y * a_stride, width, 1, fout) != 1) { if (fwrite(a, width, 1, fout) != 1) return 0;
return 0; a += a_stride;
}
} }
return 1; return 1;
} }
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// PGM with IMC4 layout // PGM with IMC4 layout
int WebPWritePGM(FILE* fout, const WebPDecBuffer* const buffer) { int WebPWritePGM(FILE* fout, const WebPDecBuffer* const buffer) {
if (fout == NULL || buffer == NULL) {
return 0;
} else {
const int width = buffer->width; const int width = buffer->width;
const int height = buffer->height; const int height = buffer->height;
const WebPYUVABuffer* const yuv = &buffer->u.YUVA; const WebPYUVABuffer* const yuv = &buffer->u.YUVA;
const uint8_t* src_y = yuv->y;
const uint8_t* src_u = yuv->u;
const uint8_t* src_v = yuv->v;
const uint8_t* src_a = yuv->a;
const int uv_width = (width + 1) / 2; const int uv_width = (width + 1) / 2;
const int uv_height = (height + 1) / 2; const int uv_height = (height + 1) / 2;
const int a_height = (yuv->a != NULL) ? height : 0; const int a_height = (src_a != NULL) ? height : 0;
int ok = 1; int ok = 1;
int y; int y;
if (fout == NULL || buffer == NULL) return 0; if (src_y == NULL || src_u == NULL || src_v == NULL) return 0;
if (yuv->y == NULL || yuv->u == NULL || yuv->v == NULL) return 0;
fprintf(fout, "P5\n%d %d\n255\n", fprintf(fout, "P5\n%d %d\n255\n",
(width + 1) & ~1, height + uv_height + a_height); (width + 1) & ~1, height + uv_height + a_height);
for (y = 0; ok && y < height; ++y) { for (y = 0; ok && y < height; ++y) {
ok &= (fwrite(yuv->y + y * yuv->y_stride, width, 1, fout) == 1); ok &= (fwrite(src_y, width, 1, fout) == 1);
if (width & 1) fputc(0, fout); // padding byte if (width & 1) fputc(0, fout); // padding byte
src_y += yuv->y_stride;
} }
for (y = 0; ok && y < uv_height; ++y) { for (y = 0; ok && y < uv_height; ++y) {
ok &= (fwrite(yuv->u + y * yuv->u_stride, uv_width, 1, fout) == 1); ok &= (fwrite(src_u, uv_width, 1, fout) == 1);
ok &= (fwrite(yuv->v + y * yuv->v_stride, uv_width, 1, fout) == 1); ok &= (fwrite(src_v, uv_width, 1, fout) == 1);
src_u += yuv->u_stride;
src_v += yuv->v_stride;
} }
for (y = 0; ok && y < a_height; ++y) { for (y = 0; ok && y < a_height; ++y) {
ok &= (fwrite(yuv->a + y * yuv->a_stride, width, 1, fout) == 1); ok &= (fwrite(src_a, width, 1, fout) == 1);
if (width & 1) fputc(0, fout); // padding byte if (width & 1) fputc(0, fout); // padding byte
src_a += yuv->a_stride;
} }
return ok; return ok;
} }
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Raw YUV(A) planes // Raw YUV(A) planes
int WebPWriteYUV(FILE* fout, const WebPDecBuffer* const buffer) { int WebPWriteYUV(FILE* fout, const WebPDecBuffer* const buffer) {
if (fout == NULL || buffer == NULL) {
return 0;
} else {
const int width = buffer->width; const int width = buffer->width;
const int height = buffer->height; const int height = buffer->height;
const WebPYUVABuffer* const yuv = &buffer->u.YUVA; const WebPYUVABuffer* const yuv = &buffer->u.YUVA;
const uint8_t* src_y = yuv->y;
const uint8_t* src_u = yuv->u;
const uint8_t* src_v = yuv->v;
const uint8_t* src_a = yuv->a;
const int uv_width = (width + 1) / 2; const int uv_width = (width + 1) / 2;
const int uv_height = (height + 1) / 2; const int uv_height = (height + 1) / 2;
const int a_height = (yuv->a != NULL) ? height : 0; const int a_height = (src_a != NULL) ? height : 0;
int ok = 1; int ok = 1;
int y; int y;
if (fout == NULL || buffer == NULL) return 0; if (src_y == NULL || src_u == NULL || src_v == NULL) return 0;
if (yuv->y == NULL || yuv->u == NULL || yuv->v == NULL) return 0;
for (y = 0; ok && y < height; ++y) { for (y = 0; ok && y < height; ++y) {
ok &= (fwrite(yuv->y + y * yuv->y_stride, width, 1, fout) == 1); ok &= (fwrite(src_y, width, 1, fout) == 1);
src_y += yuv->y_stride;
} }
for (y = 0; ok && y < uv_height; ++y) { for (y = 0; ok && y < uv_height; ++y) {
ok &= (fwrite(yuv->u + y * yuv->u_stride, uv_width, 1, fout) == 1); ok &= (fwrite(src_u, uv_width, 1, fout) == 1);
src_u += yuv->u_stride;
} }
for (y = 0; ok && y < uv_height; ++y) { for (y = 0; ok && y < uv_height; ++y) {
ok &= (fwrite(yuv->v + y * yuv->v_stride, uv_width, 1, fout) == 1); ok &= (fwrite(src_v, uv_width, 1, fout) == 1);
src_v += yuv->v_stride;
} }
for (y = 0; ok && y < a_height; ++y) { for (y = 0; ok && y < a_height; ++y) {
ok &= (fwrite(yuv->a + y * yuv->a_stride, width, 1, fout) == 1); ok &= (fwrite(src_a, width, 1, fout) == 1);
src_a += yuv->a_stride;
} }
return ok; return ok;
} }
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Generic top-level call // Generic top-level call

View File

@ -282,9 +282,10 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
rgb = (uint8_t*)malloc((size_t)stride * height); rgb = (uint8_t*)malloc((size_t)stride * height);
if (rgb == NULL) goto Error; if (rgb == NULL) goto Error;
for (p = 0; p < num_passes; ++p) { for (p = 0; p < num_passes; ++p) {
png_bytep row = rgb;
for (y = 0; y < height; ++y) { for (y = 0; y < height; ++y) {
png_bytep row = (png_bytep)(rgb + y * stride);
png_read_rows(png, &row, NULL, 1); png_read_rows(png, &row, NULL, 1);
row += stride;
} }
} }
png_read_end(png, end_info); png_read_end(png, end_info);