From c65eca35b9fd56969f506c535957c9b02879e571 Mon Sep 17 00:00:00 2001 From: YooLCD Date: Mon, 30 Mar 2026 12:59:43 +0900 Subject: [PATCH 1/3] reformat: use size_t casts for row offset arithmetic and replace strcpy with memcpy --- src/read.c | 4 +++- src/reformat.c | 56 +++++++++++++++++++++++++------------------------- 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/src/read.c b/src/read.c index a768ed9a2d..18c3fe5f62 100644 --- a/src/read.c +++ b/src/read.c @@ -4524,7 +4524,9 @@ static avifResult avifParseMinimizedImageBox(avifDecoderData * data, colorItem->premByID = alphaIsPremultiplied; avifProperty * alphaAuxProp = avifMetaCreateProperty(meta, "auxC"); AVIF_CHECKERR(alphaAuxProp, AVIF_RESULT_OUT_OF_MEMORY); - strcpy(alphaAuxProp->u.auxC.auxType, AVIF_URN_ALPHA0); + // Use memcpy instead of strcpy to make the buffer boundary explicit. + // AVIF_URN_ALPHA0 is 43 bytes + null terminator, well within AUXTYPE_SIZE (64). + memcpy(alphaAuxProp->u.auxC.auxType, AVIF_URN_ALPHA0, sizeof(AVIF_URN_ALPHA0)); AVIF_CHECKERR(avifDecoderItemAddProperty(alphaItem, alphaAuxProp), AVIF_RESULT_OUT_OF_MEMORY); // Property with fixed index 2 (reused). diff --git a/src/reformat.c b/src/reformat.c index 0575b4f4b6..6b82861cda 100644 --- a/src/reformat.c +++ b/src/reformat.c @@ -430,13 +430,13 @@ avifResult avifImageRGBToYUV(avifImage * image, const avifRGBImage * rgb) int uvI = outerI >> chromaShiftX; int uvJ = outerJ >> chromaShiftY; if (state.yuv.channelBytes > 1) { - uint16_t * pU = (uint16_t *)&uPlane[(uvI * 2) + (uvJ * uRowBytes)]; + uint16_t * pU = (uint16_t *)&uPlane[(uvI * 2) + ((size_t)uvJ * uRowBytes)]; *pU = (uint16_t)avifYUVColorSpaceInfoUVToUNorm(&state.yuv, avgU); - uint16_t * pV = (uint16_t *)&vPlane[(uvI * 2) + (uvJ * vRowBytes)]; + uint16_t * pV = (uint16_t *)&vPlane[(uvI * 2) + ((size_t)uvJ * vRowBytes)]; *pV = (uint16_t)avifYUVColorSpaceInfoUVToUNorm(&state.yuv, avgV); } else { - uPlane[uvI + (uvJ * uRowBytes)] = (uint8_t)avifYUVColorSpaceInfoUVToUNorm(&state.yuv, avgU); - vPlane[uvI + (uvJ * vRowBytes)] = (uint8_t)avifYUVColorSpaceInfoUVToUNorm(&state.yuv, avgV); + uPlane[uvI + ((size_t)uvJ * uRowBytes)] = (uint8_t)avifYUVColorSpaceInfoUVToUNorm(&state.yuv, avgU); + vPlane[uvI + ((size_t)uvJ * vRowBytes)] = (uint8_t)avifYUVColorSpaceInfoUVToUNorm(&state.yuv, avgV); } } else if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV422) { // YUV422, average 2 samples (1x2), twice @@ -456,13 +456,13 @@ avifResult avifImageRGBToYUV(avifImage * image, const avifRGBImage * rgb) int uvI = outerI >> chromaShiftX; int uvJ = outerJ + bJ; if (state.yuv.channelBytes > 1) { - uint16_t * pU = (uint16_t *)&uPlane[(uvI * 2) + (uvJ * uRowBytes)]; + uint16_t * pU = (uint16_t *)&uPlane[(uvI * 2) + ((size_t)uvJ * uRowBytes)]; *pU = (uint16_t)avifYUVColorSpaceInfoUVToUNorm(&state.yuv, avgU); - uint16_t * pV = (uint16_t *)&vPlane[(uvI * 2) + (uvJ * vRowBytes)]; + uint16_t * pV = (uint16_t *)&vPlane[(uvI * 2) + ((size_t)uvJ * vRowBytes)]; *pV = (uint16_t)avifYUVColorSpaceInfoUVToUNorm(&state.yuv, avgV); } else { - uPlane[uvI + (uvJ * uRowBytes)] = (uint8_t)avifYUVColorSpaceInfoUVToUNorm(&state.yuv, avgU); - vPlane[uvI + (uvJ * vRowBytes)] = (uint8_t)avifYUVColorSpaceInfoUVToUNorm(&state.yuv, avgV); + uPlane[uvI + ((size_t)uvJ * uRowBytes)] = (uint8_t)avifYUVColorSpaceInfoUVToUNorm(&state.yuv, avgU); + vPlane[uvI + ((size_t)uvJ * vRowBytes)] = (uint8_t)avifYUVColorSpaceInfoUVToUNorm(&state.yuv, avgV); } } } @@ -686,10 +686,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]; + 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; @@ -795,23 +795,23 @@ static avifResult avifImageYUVAnyToRGBAnySlow(const avifImage * image, } 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[((size_t)uvJ * uRowBytes) + (uvI * yuvChannelBytes)]; + unormV[0][0] = vPlane[((size_t)uvJ * vRowBytes) + (uvI * yuvChannelBytes)]; + unormU[1][0] = uPlane[((size_t)uvJ * uRowBytes) + (uvI * yuvChannelBytes) + uAdjCol]; + unormV[1][0] = vPlane[((size_t)uvJ * vRowBytes) + (uvI * yuvChannelBytes) + vAdjCol]; + unormU[0][1] = uPlane[((size_t)uvJ * uRowBytes) + (uvI * yuvChannelBytes) + uAdjRow]; + unormV[0][1] = vPlane[((size_t)uvJ * vRowBytes) + (uvI * yuvChannelBytes) + vAdjRow]; + unormU[1][1] = uPlane[((size_t)uvJ * uRowBytes) + (uvI * yuvChannelBytes) + uAdjCol + uAdjRow]; + unormV[1][1] = vPlane[((size_t)uvJ * vRowBytes) + (uvI * yuvChannelBytes) + 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[((size_t)uvJ * uRowBytes) + (uvI * yuvChannelBytes)]); + unormV[0][0] = *((const uint16_t *)&vPlane[((size_t)uvJ * vRowBytes) + (uvI * yuvChannelBytes)]); + unormU[1][0] = *((const uint16_t *)&uPlane[((size_t)uvJ * uRowBytes) + (uvI * yuvChannelBytes) + uAdjCol]); + unormV[1][0] = *((const uint16_t *)&vPlane[((size_t)uvJ * vRowBytes) + (uvI * yuvChannelBytes) + vAdjCol]); + unormU[0][1] = *((const uint16_t *)&uPlane[((size_t)uvJ * uRowBytes) + (uvI * yuvChannelBytes) + uAdjRow]); + unormV[0][1] = *((const uint16_t *)&vPlane[((size_t)uvJ * vRowBytes) + (uvI * yuvChannelBytes) + vAdjRow]); + unormU[1][1] = *((const uint16_t *)&uPlane[((size_t)uvJ * uRowBytes) + (uvI * yuvChannelBytes) + uAdjCol + uAdjRow]); + unormV[1][1] = *((const uint16_t *)&vPlane[((size_t)uvJ * vRowBytes) + (uvI * yuvChannelBytes) + vAdjCol + vAdjRow]); // clamp incoming data to protect against bad LUT lookups for (int bJ = 0; bJ < 2; ++bJ) { From 7358896e872cc702540d3c95dbb21e6c059b2c0c Mon Sep 17 00:00:00 2001 From: YooLCD Date: Tue, 31 Mar 2026 10:19:39 +0900 Subject: [PATCH 2/3] Revert slow path changes, remove memcpy comments --- src/read.c | 2 -- src/reformat.c | 40 ++++++++++++++++++++-------------------- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/read.c b/src/read.c index 18c3fe5f62..bf2dda5b69 100644 --- a/src/read.c +++ b/src/read.c @@ -4524,8 +4524,6 @@ static avifResult avifParseMinimizedImageBox(avifDecoderData * data, colorItem->premByID = alphaIsPremultiplied; avifProperty * alphaAuxProp = avifMetaCreateProperty(meta, "auxC"); AVIF_CHECKERR(alphaAuxProp, AVIF_RESULT_OUT_OF_MEMORY); - // Use memcpy instead of strcpy to make the buffer boundary explicit. - // AVIF_URN_ALPHA0 is 43 bytes + null terminator, well within AUXTYPE_SIZE (64). memcpy(alphaAuxProp->u.auxC.auxType, AVIF_URN_ALPHA0, sizeof(AVIF_URN_ALPHA0)); AVIF_CHECKERR(avifDecoderItemAddProperty(alphaItem, alphaAuxProp), AVIF_RESULT_OUT_OF_MEMORY); diff --git a/src/reformat.c b/src/reformat.c index 6b82861cda..47a2600a11 100644 --- a/src/reformat.c +++ b/src/reformat.c @@ -686,10 +686,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[(size_t)j * yRowBytes]; - 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 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 uint16_t * ptrY16 = (const uint16_t *)ptrY8; const uint16_t * ptrU16 = (const uint16_t *)ptrU8; const uint16_t * ptrV16 = (const uint16_t *)ptrV8; @@ -795,23 +795,23 @@ static avifResult avifImageYUVAnyToRGBAnySlow(const avifImage * image, } if (image->depth == 8) { - unormU[0][0] = uPlane[((size_t)uvJ * uRowBytes) + (uvI * yuvChannelBytes)]; - unormV[0][0] = vPlane[((size_t)uvJ * vRowBytes) + (uvI * yuvChannelBytes)]; - unormU[1][0] = uPlane[((size_t)uvJ * uRowBytes) + (uvI * yuvChannelBytes) + uAdjCol]; - unormV[1][0] = vPlane[((size_t)uvJ * vRowBytes) + (uvI * yuvChannelBytes) + vAdjCol]; - unormU[0][1] = uPlane[((size_t)uvJ * uRowBytes) + (uvI * yuvChannelBytes) + uAdjRow]; - unormV[0][1] = vPlane[((size_t)uvJ * vRowBytes) + (uvI * yuvChannelBytes) + vAdjRow]; - unormU[1][1] = uPlane[((size_t)uvJ * uRowBytes) + (uvI * yuvChannelBytes) + uAdjCol + uAdjRow]; - unormV[1][1] = vPlane[((size_t)uvJ * vRowBytes) + (uvI * yuvChannelBytes) + vAdjCol + vAdjRow]; + 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]; } else { - unormU[0][0] = *((const uint16_t *)&uPlane[((size_t)uvJ * uRowBytes) + (uvI * yuvChannelBytes)]); - unormV[0][0] = *((const uint16_t *)&vPlane[((size_t)uvJ * vRowBytes) + (uvI * yuvChannelBytes)]); - unormU[1][0] = *((const uint16_t *)&uPlane[((size_t)uvJ * uRowBytes) + (uvI * yuvChannelBytes) + uAdjCol]); - unormV[1][0] = *((const uint16_t *)&vPlane[((size_t)uvJ * vRowBytes) + (uvI * yuvChannelBytes) + vAdjCol]); - unormU[0][1] = *((const uint16_t *)&uPlane[((size_t)uvJ * uRowBytes) + (uvI * yuvChannelBytes) + uAdjRow]); - unormV[0][1] = *((const uint16_t *)&vPlane[((size_t)uvJ * vRowBytes) + (uvI * yuvChannelBytes) + vAdjRow]); - unormU[1][1] = *((const uint16_t *)&uPlane[((size_t)uvJ * uRowBytes) + (uvI * yuvChannelBytes) + uAdjCol + uAdjRow]); - unormV[1][1] = *((const uint16_t *)&vPlane[((size_t)uvJ * vRowBytes) + (uvI * yuvChannelBytes) + vAdjCol + vAdjRow]); + 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]); // clamp incoming data to protect against bad LUT lookups for (int bJ = 0; bJ < 2; ++bJ) { From 565dc563900660d0785a53250e75cdc2dd1e1ee9 Mon Sep 17 00:00:00 2001 From: YooLCD Date: Wed, 1 Apr 2026 10:19:07 +0900 Subject: [PATCH 3/3] Revert read.c change --- src/read.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/read.c b/src/read.c index bf2dda5b69..a768ed9a2d 100644 --- a/src/read.c +++ b/src/read.c @@ -4524,7 +4524,7 @@ static avifResult avifParseMinimizedImageBox(avifDecoderData * data, colorItem->premByID = alphaIsPremultiplied; avifProperty * alphaAuxProp = avifMetaCreateProperty(meta, "auxC"); AVIF_CHECKERR(alphaAuxProp, AVIF_RESULT_OUT_OF_MEMORY); - memcpy(alphaAuxProp->u.auxC.auxType, AVIF_URN_ALPHA0, sizeof(AVIF_URN_ALPHA0)); + strcpy(alphaAuxProp->u.auxC.auxType, AVIF_URN_ALPHA0); AVIF_CHECKERR(avifDecoderItemAddProperty(alphaItem, alphaAuxProp), AVIF_RESULT_OUT_OF_MEMORY); // Property with fixed index 2 (reused).