Reallocate MJPEG databuf when scanline count changes

MJpegDecoder reuses its per-component scanline buffers across calls to
LoadFrame. The databuf_ buffer for each component is sized as
scanlines_size * databuf_stride, but it was only reallocated when the
stride changed (databuf_strides_[i] != databuf_stride). A subsequent
frame with the same component width (hence the same stride) but a larger
scanlines_size -- for example a different vertical sampling factor --
would reuse the previously allocated, now undersized, buffer. jpeglib
then writes scanlines_size rows into it during decoding, overflowing the
heap allocation.

Track whether scanlines_size changed and reallocate databuf_ in that
case as well, so the buffer always matches the size used to compute
databuf_size.

R=fbarchard@google.com

Change-Id: Ie8bf7b7da9eb5e12bd59e578c704988b93d5816c
This commit is contained in:
Maximilian Hils 2026-07-22 10:37:01 +00:00 committed by Max Hils
parent b56492e2df
commit cca2d83f38

View File

@ -125,7 +125,11 @@ LIBYUV_BOOL MJpegDecoder::LoadFrame(const uint8_t* src, size_t src_len) {
AllocOutputBuffers(GetNumComponents());
for (int i = 0; i < num_outbufs_; ++i) {
int scanlines_size = GetComponentScanlinesPerImcuRow(i);
if (scanlines_sizes_[i] != scanlines_size) {
// The number of scanlines can change between frames (e.g. a different
// vertical sampling factor). The databuf below is sized from it, so track
// whether it changed to know when the databuf must be reallocated too.
int scanlines_size_changed = scanlines_sizes_[i] != scanlines_size;
if (scanlines_size_changed) {
if (scanlines_[i]) {
delete[] scanlines_[i];
}
@ -141,7 +145,7 @@ LIBYUV_BOOL MJpegDecoder::LoadFrame(const uint8_t* src, size_t src_len) {
// next scanline.
int databuf_stride = GetComponentStride(i);
int databuf_size = scanlines_size * databuf_stride;
if (databuf_strides_[i] != databuf_stride) {
if (databuf_strides_[i] != databuf_stride || scanlines_size_changed) {
if (databuf_[i]) {
delete[] databuf_[i];
}