Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 32 additions & 29 deletions src/reformat.c
Original file line number Diff line number Diff line change
Expand Up @@ -683,10 +683,10 @@ static avifResult avifImageYUVAnyToRGBAnySlow(const avifImage * image,
for (uint32_t j = 0; j < image->height; ++j) {
// uvJ is used only when yuvHasColor is true.
const uint32_t uvJ = yuvHasColor ? (j >> state->yuv.formatInfo.chromaShiftY) : 0;
const uint8_t * ptrY8 = &yPlane[j * yRowBytes];
const uint8_t * ptrU8 = uPlane ? &uPlane[(uvJ * uRowBytes)] : NULL;
const uint8_t * ptrV8 = vPlane ? &vPlane[(uvJ * vRowBytes)] : NULL;
const uint8_t * ptrA8 = aPlane ? &aPlane[j * aRowBytes] : NULL;
const uint8_t * ptrY8 = &yPlane[(size_t)j * yRowBytes];
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use uint64_t as size_t can be 32 bit on 32 bit platforms.

Copy link
Copy Markdown
Collaborator

@wantehchang wantehchang Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vincent: Please see my comment at #3097 (review), which explains why we can multiply rowBytes by height or an index that is less than height using the size_t type after the pixel buffer has been allocated successfully.

This is why libavif uses the size_t type in such multiplications. Before we allocate a pixel buffer, it is not safe to do these multiplications using the size_t type, so we need to either detect overflow or use the uin64_t type.

In the avifImageYUVAnyToRGBAnySlow() function (the subject of this pull request), we may multiply rowBytes by -1 to go back the the previous row, so we need to use the signed ptrdiff_t type in those places. We need to review the changes to this function carefully.

const uint8_t * ptrU8 = uPlane ? &uPlane[(size_t)uvJ * uRowBytes] : NULL;
const uint8_t * ptrV8 = vPlane ? &vPlane[(size_t)uvJ * vRowBytes] : NULL;
const uint8_t * ptrA8 = aPlane ? &aPlane[(size_t)j * aRowBytes] : NULL;
const uint16_t * ptrY16 = (const uint16_t *)ptrY8;
const uint16_t * ptrU16 = (const uint16_t *)ptrU8;
const uint16_t * ptrV16 = (const uint16_t *)ptrV8;
Expand Down Expand Up @@ -761,17 +761,17 @@ static avifResult avifImageYUVAnyToRGBAnySlow(const avifImage * image,
uint16_t unormU[2][2], unormV[2][2];

// How many bytes to add to a uint8_t pointer index to get to the adjacent (lesser) sample in a given direction
int uAdjCol, vAdjCol, uAdjRow, vAdjRow;
ptrdiff_t uAdjCol, vAdjCol, uAdjRow, vAdjRow;
if ((i == 0) || ((i == (image->width - 1)) && ((i % 2) != 0))) {
uAdjCol = 0;
vAdjCol = 0;
} else {
if ((i % 2) != 0) {
uAdjCol = yuvChannelBytes;
vAdjCol = yuvChannelBytes;
uAdjCol = (ptrdiff_t)yuvChannelBytes;
vAdjCol = (ptrdiff_t)yuvChannelBytes;
} else {
uAdjCol = -1 * yuvChannelBytes;
vAdjCol = -1 * yuvChannelBytes;
uAdjCol = -(ptrdiff_t)yuvChannelBytes;
vAdjCol = -(ptrdiff_t)yuvChannelBytes;
}
}

Expand All @@ -783,32 +783,35 @@ static avifResult avifImageYUVAnyToRGBAnySlow(const avifImage * image,
vAdjRow = 0;
} else {
if ((j % 2) != 0) {
uAdjRow = (int)uRowBytes;
vAdjRow = (int)vRowBytes;
uAdjRow = (ptrdiff_t)uRowBytes;
vAdjRow = (ptrdiff_t)vRowBytes;
} else {
uAdjRow = -1 * (int)uRowBytes;
vAdjRow = -1 * (int)vRowBytes;
uAdjRow = -(ptrdiff_t)uRowBytes;
vAdjRow = -(ptrdiff_t)vRowBytes;
}
}

const ptrdiff_t uBase = (ptrdiff_t)uvJ * uRowBytes + (ptrdiff_t)uvI * yuvChannelBytes;
const ptrdiff_t vBase = (ptrdiff_t)uvJ * vRowBytes + (ptrdiff_t)uvI * yuvChannelBytes;

if (image->depth == 8) {
unormU[0][0] = uPlane[(uvJ * uRowBytes) + (uvI * yuvChannelBytes)];
unormV[0][0] = vPlane[(uvJ * vRowBytes) + (uvI * yuvChannelBytes)];
unormU[1][0] = uPlane[(uvJ * uRowBytes) + (uvI * yuvChannelBytes) + uAdjCol];
unormV[1][0] = vPlane[(uvJ * vRowBytes) + (uvI * yuvChannelBytes) + vAdjCol];
unormU[0][1] = uPlane[(uvJ * uRowBytes) + (uvI * yuvChannelBytes) + uAdjRow];
unormV[0][1] = vPlane[(uvJ * vRowBytes) + (uvI * yuvChannelBytes) + vAdjRow];
unormU[1][1] = uPlane[(uvJ * uRowBytes) + (uvI * yuvChannelBytes) + uAdjCol + uAdjRow];
unormV[1][1] = vPlane[(uvJ * vRowBytes) + (uvI * yuvChannelBytes) + vAdjCol + vAdjRow];
unormU[0][0] = uPlane[uBase];
unormV[0][0] = vPlane[vBase];
unormU[1][0] = uPlane[uBase + uAdjCol];
unormV[1][0] = vPlane[vBase + vAdjCol];
unormU[0][1] = uPlane[uBase + uAdjRow];
unormV[0][1] = vPlane[vBase + vAdjRow];
unormU[1][1] = uPlane[uBase + uAdjCol + uAdjRow];
unormV[1][1] = vPlane[vBase + vAdjCol + vAdjRow];
} else {
unormU[0][0] = *((const uint16_t *)&uPlane[(uvJ * uRowBytes) + (uvI * yuvChannelBytes)]);
unormV[0][0] = *((const uint16_t *)&vPlane[(uvJ * vRowBytes) + (uvI * yuvChannelBytes)]);
unormU[1][0] = *((const uint16_t *)&uPlane[(uvJ * uRowBytes) + (uvI * yuvChannelBytes) + uAdjCol]);
unormV[1][0] = *((const uint16_t *)&vPlane[(uvJ * vRowBytes) + (uvI * yuvChannelBytes) + vAdjCol]);
unormU[0][1] = *((const uint16_t *)&uPlane[(uvJ * uRowBytes) + (uvI * yuvChannelBytes) + uAdjRow]);
unormV[0][1] = *((const uint16_t *)&vPlane[(uvJ * vRowBytes) + (uvI * yuvChannelBytes) + vAdjRow]);
unormU[1][1] = *((const uint16_t *)&uPlane[(uvJ * uRowBytes) + (uvI * yuvChannelBytes) + uAdjCol + uAdjRow]);
unormV[1][1] = *((const uint16_t *)&vPlane[(uvJ * vRowBytes) + (uvI * yuvChannelBytes) + vAdjCol + vAdjRow]);
unormU[0][0] = *((const uint16_t *)&uPlane[uBase]);
unormV[0][0] = *((const uint16_t *)&vPlane[vBase]);
unormU[1][0] = *((const uint16_t *)&uPlane[uBase + uAdjCol]);
unormV[1][0] = *((const uint16_t *)&vPlane[vBase + vAdjCol]);
unormU[0][1] = *((const uint16_t *)&uPlane[uBase + uAdjRow]);
unormV[0][1] = *((const uint16_t *)&vPlane[vBase + vAdjRow]);
unormU[1][1] = *((const uint16_t *)&uPlane[uBase + uAdjCol + uAdjRow]);
unormV[1][1] = *((const uint16_t *)&vPlane[vBase + vAdjCol + vAdjRow]);

// clamp incoming data to protect against bad LUT lookups
for (int bJ = 0; bJ < 2; ++bJ) {
Expand Down
Loading