Skip to content

Commit c79a400

Browse files
authored
Fix potential integer overflow in rowBytes multiplications
Cast the first operand to (size_t) before multiplying two uint32_t values involving rowBytes, alphaRowBytes, or yuvRowBytes to prevent unsigned integer wrap-around on large images.
1 parent 912d26b commit c79a400

5 files changed

Lines changed: 97 additions & 75 deletions

File tree

src/codec_aom.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,8 +1217,8 @@ static avifResult aomCodecEncodeImage(avifCodec * codec,
12171217
if (aomImageAllocated) {
12181218
const uint32_t bytesPerRow = ((image->depth > 8) ? 2 : 1) * image->width;
12191219
for (uint32_t j = 0; j < image->height; ++j) {
1220-
const uint8_t * srcAlphaRow = &image->alphaPlane[j * image->alphaRowBytes];
1221-
uint8_t * dstAlphaRow = &aomImage.planes[0][j * aomImage.stride[0]];
1220+
const uint8_t * srcAlphaRow = &image->alphaPlane[(size_t)j * image->alphaRowBytes];
1221+
uint8_t * dstAlphaRow = &aomImage.planes[0][(size_t)j * aomImage.stride[0]];
12221222
memcpy(dstAlphaRow, srcAlphaRow, bytesPerRow);
12231223
}
12241224
} else {
@@ -1241,8 +1241,8 @@ static avifResult aomCodecEncodeImage(avifCodec * codec,
12411241
uint32_t bytesPerRow = bytesPerPixel * planeWidth;
12421242

12431243
for (uint32_t j = 0; j < planeHeight; ++j) {
1244-
const uint8_t * srcRow = &image->yuvPlanes[yuvPlane][j * image->yuvRowBytes[yuvPlane]];
1245-
uint8_t * dstRow = &aomImage.planes[yuvPlane][j * aomImage.stride[yuvPlane]];
1244+
const uint8_t * srcRow = &image->yuvPlanes[yuvPlane][(size_t)j * image->yuvRowBytes[yuvPlane]];
1245+
uint8_t * dstRow = &aomImage.planes[yuvPlane][(size_t)j * aomImage.stride[yuvPlane]];
12461246
memcpy(dstRow, srcRow, bytesPerRow);
12471247
}
12481248
}

src/codec_avm.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -903,8 +903,8 @@ static avifResult avmCodecEncodeImage(avifCodec * codec,
903903
if (avmImageAllocated) {
904904
const uint32_t bytesPerRow = ((image->depth > 8) ? 2 : 1) * image->width;
905905
for (uint32_t j = 0; j < image->height; ++j) {
906-
const uint8_t * srcAlphaRow = &image->alphaPlane[j * image->alphaRowBytes];
907-
uint8_t * dstAlphaRow = &avmImage.planes[0][j * avmImage.stride[0]];
906+
const uint8_t * srcAlphaRow = &image->alphaPlane[(size_t)j * image->alphaRowBytes];
907+
uint8_t * dstAlphaRow = &avmImage.planes[0][(size_t)j * avmImage.stride[0]];
908908
memcpy(dstAlphaRow, srcAlphaRow, bytesPerRow);
909909
}
910910
} else {
@@ -927,8 +927,8 @@ static avifResult avmCodecEncodeImage(avifCodec * codec,
927927
uint32_t bytesPerRow = bytesPerPixel * planeWidth;
928928

929929
for (uint32_t j = 0; j < planeHeight; ++j) {
930-
const uint8_t * srcRow = &image->yuvPlanes[yuvPlane][j * image->yuvRowBytes[yuvPlane]];
931-
uint8_t * dstRow = &avmImage.planes[yuvPlane][j * avmImage.stride[yuvPlane]];
930+
const uint8_t * srcRow = &image->yuvPlanes[yuvPlane][(size_t)j * image->yuvRowBytes[yuvPlane]];
931+
uint8_t * dstRow = &avmImage.planes[yuvPlane][(size_t)j * avmImage.stride[yuvPlane]];
932932
memcpy(dstRow, srcRow, bytesPerRow);
933933
}
934934
}

src/codec_svt.c

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -274,22 +274,32 @@ static avifResult svtCodecEncodeImage(avifCodec * codec,
274274
if (alpha) {
275275
input_picture_buffer->y_stride = image->alphaRowBytes / bytesPerPixel;
276276
input_picture_buffer->luma = image->alphaPlane;
277-
input_buffer->n_filled_len = image->alphaRowBytes * image->height;
277+
const size_t alphaSize = (size_t)image->alphaRowBytes * image->height;
278+
if (alphaSize > UINT32_MAX) {
279+
goto cleanup;
280+
}
281+
input_buffer->n_filled_len = (uint32_t)alphaSize;
278282

279283
#if SVT_AV1_CHECK_VERSION(1, 8, 0)
280284
// Simulate 4:2:0 UV planes. SVT-AV1 does not support 4:0:0 samples.
281285
const uint32_t uvWidth = (image->width + y_shift) >> y_shift;
282286
const uint32_t uvRowBytes = uvWidth * bytesPerPixel;
283-
const uint32_t uvSize = uvRowBytes * uvHeight;
287+
const size_t uvSize = (size_t)uvRowBytes * uvHeight;
288+
if (uvSize > UINT32_MAX / 2) {
289+
goto cleanup;
290+
}
291+
if (uvSize * 2 > UINT32_MAX - input_buffer->n_filled_len) {
292+
goto cleanup;
293+
}
284294
uvPlanes = avifAlloc(uvSize);
285295
if (uvPlanes == NULL) {
286296
goto cleanup;
287297
}
288298
memset(uvPlanes, 0, uvSize);
289299
input_picture_buffer->cb = uvPlanes;
290-
input_buffer->n_filled_len += uvSize;
300+
input_buffer->n_filled_len += (uint32_t)uvSize;
291301
input_picture_buffer->cr = uvPlanes;
292-
input_buffer->n_filled_len += uvSize;
302+
input_buffer->n_filled_len += (uint32_t)uvSize;
293303
input_picture_buffer->cb_stride = uvWidth;
294304
input_picture_buffer->cr_stride = uvWidth;
295305
#else
@@ -300,11 +310,23 @@ static avifResult svtCodecEncodeImage(avifCodec * codec,
300310
} else {
301311
input_picture_buffer->y_stride = image->yuvRowBytes[0] / bytesPerPixel;
302312
input_picture_buffer->luma = image->yuvPlanes[0];
303-
input_buffer->n_filled_len = image->yuvRowBytes[0] * image->height;
313+
const size_t ySize = (size_t)image->yuvRowBytes[0] * image->height;
314+
if (ySize > UINT32_MAX) {
315+
goto cleanup;
316+
}
317+
input_buffer->n_filled_len = (uint32_t)ySize;
304318
input_picture_buffer->cb = image->yuvPlanes[1];
305-
input_buffer->n_filled_len += image->yuvRowBytes[1] * uvHeight;
319+
const size_t uSize = (size_t)image->yuvRowBytes[1] * uvHeight;
320+
if (uSize > UINT32_MAX - input_buffer->n_filled_len) {
321+
goto cleanup;
322+
}
323+
input_buffer->n_filled_len += (uint32_t)uSize;
306324
input_picture_buffer->cr = image->yuvPlanes[2];
307-
input_buffer->n_filled_len += image->yuvRowBytes[2] * uvHeight;
325+
const size_t vSize = (size_t)image->yuvRowBytes[2] * uvHeight;
326+
if (vSize > UINT32_MAX - input_buffer->n_filled_len) {
327+
goto cleanup;
328+
}
329+
input_buffer->n_filled_len += (uint32_t)vSize;
308330
input_picture_buffer->cb_stride = image->yuvRowBytes[1] / bytesPerPixel;
309331
input_picture_buffer->cr_stride = image->yuvRowBytes[2] / bytesPerPixel;
310332
}

src/read.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6599,8 +6599,8 @@ static avifResult avifImageLimitedToFullAlpha(avifImage * image)
65996599

66006600
if (image->depth > 8) {
66016601
for (uint32_t j = 0; j < image->height; ++j) {
6602-
const uint8_t * srcRow = &alphaPlane[j * alphaRowBytes];
6603-
uint8_t * dstRow = &image->alphaPlane[j * image->alphaRowBytes];
6602+
const uint8_t * srcRow = &alphaPlane[(size_t)j * alphaRowBytes];
6603+
uint8_t * dstRow = &image->alphaPlane[(size_t)j * image->alphaRowBytes];
66046604
for (uint32_t i = 0; i < image->width; ++i) {
66056605
int srcAlpha = *((const uint16_t *)&srcRow[i * 2]);
66066606
int dstAlpha = avifLimitedToFullY(image->depth, srcAlpha);
@@ -6609,8 +6609,8 @@ static avifResult avifImageLimitedToFullAlpha(avifImage * image)
66096609
}
66106610
} else {
66116611
for (uint32_t j = 0; j < image->height; ++j) {
6612-
const uint8_t * srcRow = &alphaPlane[j * alphaRowBytes];
6613-
uint8_t * dstRow = &image->alphaPlane[j * image->alphaRowBytes];
6612+
const uint8_t * srcRow = &alphaPlane[(size_t)j * alphaRowBytes];
6613+
uint8_t * dstRow = &image->alphaPlane[(size_t)j * image->alphaRowBytes];
66146614
for (uint32_t i = 0; i < image->width; ++i) {
66156615
int srcAlpha = srcRow[i];
66166616
int dstAlpha = avifLimitedToFullY(image->depth, srcAlpha);

0 commit comments

Comments
 (0)