Update Decode() for ImageDecoder API 3.1.0 - #71
Conversation
xbmc/xbmc#29068 added size_t pixelBufferSize to the C++ Decode() signature. The old five-argument override no longer matches the base virtual, so this does not compile against the new dev-kit rather than merely warning. Signature only; the argument is used in the next commit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
| Filename | Overview |
|---|---|
| src/MPOPicture.cpp | Adds the buffer-size guard, but its horizontal-offset calculation can underestimate the guarded write for odd aggregate widths. |
| src/MPOPicture.h | Updates the virtual Decode declaration to match the ImageDecoder API 3.1.0 signature. |
Reviews (1): Last reviewed commit: "Refuse a decode that would not fit the o..." | Re-trigger Greptile
| // row_stride / 3 pixels from that offset. | ||
| const size_t bytesPerPixel = (format == ADDON_IMG_FMT_A8R8G8B8) ? 4 : 3; | ||
| if (m_height == 0 || row_stride <= 0 || | ||
| static_cast<size_t>(m_height - 1) * pitch + image * (m_width / 2 * 4) + |
There was a problem hiding this comment.
When an MPO has an odd aggregate m_width, this check divides the width before multiplying by image, while the guarded destination pointer multiplies first. For later images the check therefore underestimates the actual write extent, allowing the pixel loop to overrun a tightly sized output buffer. How this was verified: The two integer expressions produce different offsets for reachable odd widths.
| static_cast<size_t>(m_height - 1) * pitch + image * (m_width / 2 * 4) + | |
| static_cast<size_t>(m_height - 1) * pitch + image * m_width / 2 * 4 + |
Use the pixelBufferSize argument added in the previous commit: work out what the copy loop actually reaches and return false rather than write past the end. The loop's dimensions are not always the ones Kodi passed, which is what makes the check worth having. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The copy loop writes B,G,R and fills the fourth byte only for A8R8G8B8, so that is the only format actually produced. Every other value fell through to that same loop and returned true with output that does not match the request. ADDON_IMG_FMT_A8 was the worst of them: one byte per pixel is asked for and three are written. The previous commit's bounds check now refuses that, but it should not be reached at all. Latent today only because CTexture::LoadIImage() asks for A8R8G8B8. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Greptile's security finding was right, and I introduced it — the guard's horizontal offset did not mirror the write. The write loop computes Corrected in const size_t tileOffset = image * m_width / 2 * 4;Checked the sibling PRs for the same class of error — heif and raw derive their extent from the same operands in the same order as their loops, so neither diverges. The branch has also gained a third commit since that review: Written by my AI co-author (Claude Code); posted from my account. |
b25826d to
4e246b5
Compare
|
Thanks for the improvement! |
|
@cinema-ONE I got all the "Update Decode()" PRs, the rest might need to be rebased. |
|
All four are rebased already — #72, #73, #74 and xbmc/imagedecoder.heif#92 are #71 conflicted with #73 and #74 in Order that reads easiest: xbmc/imagedecoder.heif#92 and #72 are the TinyEXIF resync and stand alone. #73 is the libjpeg Written by my AI co-author (Claude Code); posted from my account. |
Readies the add-on for ImageDecoder API 3.1.0 (xbmc/xbmc#29068), which added
size_t pixelBufferSizeto the C++Decode()signature.This is a source break rather than a rebuild: the old five-argument
Decode(...) overrideno longer matches the base virtual, so it fails to compile against the new dev-kit.Two commits, separable. The first is the signature alone and unblocks the build. The second uses the argument for a bounds check and can be dropped if you would rather not take it now.
The check is worth having here because the loop is driven by
m_heightandrow_stridefrom the JPEG rather than theheightKodi passed, and each of them_imagesis tiled at a furtherm_width / 2 * 4offset.Verified by building against a Kodi tree carrying the merged API: configure and build clean,
.soproduced. The generatedaddon.xmlpicks upminversion="3.1.0" version="3.1.0"from the dev-kit on its own, so nothing needs hardcoding inaddon.xml.in.Written by my AI co-author (Claude Code); posted from my account.