Severity: Low / latent correctness issue
Affected file: arm/arm_init.c, line 148
Description:
The RGBA path computes row + (4 * row_width - 1) without promoting row_width to size_t, while the RGB path and scalar implementation do promote. For very large legal PNG widths, the multiplication can wrap in 32-bit arithmetic before pointer arithmetic. This may be unreachable in normal builds due to row-size or allocation limits, but the inconsistency is a latent defect and can be fixed by matching the RGB/scalar code.
RGBA path (line 148) — BUGGY:
png_byte *dp = row + (4/*RGBA*/*row_width - 1);
// ^^^^^^^^^^^^^^^^^
// png_uint_32 × int → png_uint_32 (32-bit)
// Overflows for row_width > UINT32_MAX/4 ≈ 1,073,741,823
RGB path (line 197) — CORRECT:
png_byte *dp = row + (3/*RGB*/ * (size_t)row_width - 1);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Explicit (size_t) promotion → 64-bit on 64-bit platforms
The RGBA path performs 4 * row_width in png_uint_32 (32-bit) arithmetic. The PNG specification permits image widths up to 0x7FFFFFFF (2,147,483,647), and 4 * 0x7FFFFFFF overflows a 32-bit unsigned integer. The result wraps to a small value, producing a wildly incorrect dp pointer.
The same discrepancy exists in the scalar implementation png_do_expand_palette (pngrtran.c:4434), which uses (size_t)row_width << 2 correctly. The NEON RGB branch at line 197 also uses (size_t) correctly — only the RGBA branch at line 148 is missing it.
Proof (side-by-side comparison):
| Location |
Code |
Width |
arm_init.c:148 (NEON RGBA) |
4/*RGBA*/*row_width - 1 |
32-bit (BUG) |
arm_init.c:197 (NEON RGB) |
3/*RGB*/ * (size_t)row_width - 1 |
64-bit ✓ |
pngrtran.c:4434 (scalar RGBA) |
((size_t)row_width << 2) - 1 |
64-bit ✓ |
pngrtran.c:4458 (scalar RGB) |
(size_t)row_width * 3 - 1 |
64-bit ✓ |
Impact:
On 64-bit platforms, for an image with row_width > 1,073,741,823 and color type PALETTE with tRNS (RGBA expansion path), the dp pointer would be computed incorrectly due to 32-bit wrap-around, potentially causing out-of-bounds writes to the row buffer. While such widths exceed practical image dimensions today, the PNG specification permits them, and the inconsistency between the two branches is a latent defect.
Suggested fix:
- png_byte *dp = row + (4/*RGBA*/*row_width - 1);
+ png_byte *dp = row + (4/*RGBA*/ * (size_t)row_width - 1);
This aligns the RGBA branch with the existing RGB branch at line 197 and the scalar implementation in pngrtran.c.
Severity: Low / latent correctness issue
Affected file:
arm/arm_init.c, line 148Description:
The RGBA path computes
row + (4 * row_width - 1)without promotingrow_widthtosize_t, while the RGB path and scalar implementation do promote. For very large legal PNG widths, the multiplication can wrap in 32-bit arithmetic before pointer arithmetic. This may be unreachable in normal builds due to row-size or allocation limits, but the inconsistency is a latent defect and can be fixed by matching the RGB/scalar code.RGBA path (line 148) — BUGGY:
RGB path (line 197) — CORRECT:
The RGBA path performs
4 * row_widthinpng_uint_32(32-bit) arithmetic. The PNG specification permits image widths up to0x7FFFFFFF(2,147,483,647), and4 * 0x7FFFFFFFoverflows a 32-bit unsigned integer. The result wraps to a small value, producing a wildly incorrectdppointer.The same discrepancy exists in the scalar implementation
png_do_expand_palette(pngrtran.c:4434), which uses(size_t)row_width << 2correctly. The NEON RGB branch at line 197 also uses(size_t)correctly — only the RGBA branch at line 148 is missing it.Proof (side-by-side comparison):
arm_init.c:148(NEON RGBA)4/*RGBA*/*row_width - 1arm_init.c:197(NEON RGB)3/*RGB*/ * (size_t)row_width - 1pngrtran.c:4434(scalar RGBA)((size_t)row_width << 2) - 1pngrtran.c:4458(scalar RGB)(size_t)row_width * 3 - 1Impact:
On 64-bit platforms, for an image with
row_width > 1,073,741,823and color type PALETTE with tRNS (RGBA expansion path), thedppointer would be computed incorrectly due to 32-bit wrap-around, potentially causing out-of-bounds writes to the row buffer. While such widths exceed practical image dimensions today, the PNG specification permits them, and the inconsistency between the two branches is a latent defect.Suggested fix:
This aligns the RGBA branch with the existing RGB branch at line 197 and the scalar implementation in
pngrtran.c.