Commit f9779a3b for libheif
commit f9779a3bbe1bd296e47ffc4f70472ee05d35c8f2
Author: Dirk Farin <dirk.farin@gmail.com>
Date: Sat Mar 14 00:59:41 2026 +0100
jpeg: fix memory leak on error (#1718)
diff --git a/libheif/plugins/decoder_jpeg.cc b/libheif/plugins/decoder_jpeg.cc
index 79bd8a50..a21c528a 100644
--- a/libheif/plugins/decoder_jpeg.cc
+++ b/libheif/plugins/decoder_jpeg.cc
@@ -195,6 +195,8 @@ heif_error jpeg_decode_next_image2(void* decoder_raw, heif_image** out_img,
jpeg_create_decompress(&cinfo);
+ heif_image* heif_img = nullptr;
+
cinfo.err = jpeg_std_error(&jerr.mgr);
jerr.mgr.error_exit = on_jpeg_error;
if (setjmp(jerr.setjmp_buffer)) {
@@ -202,6 +204,10 @@ heif_error jpeg_decode_next_image2(void* decoder_raw, heif_image** out_img,
jpeg_destroy_decompress(&cinfo);
+ if (heif_img) {
+ heif_image_release(heif_img);
+ }
+
return heif_error{
heif_error_Decoder_plugin_error,
heif_suberror_Unspecified,
@@ -243,7 +249,6 @@ heif_error jpeg_decode_next_image2(void* decoder_raw, heif_image** out_img,
// create destination image
- heif_image* heif_img = nullptr;
heif_error err = heif_image_create(cinfo.output_width, cinfo.output_height,
heif_colorspace_monochrome,
heif_chroma_monochrome,
@@ -276,6 +281,7 @@ heif_error jpeg_decode_next_image2(void* decoder_raw, heif_image** out_img,
}
*out_img = heif_img;
+ heif_img = nullptr; // pass ownership to caller, don't delete it in the plugin during any subsequent error
}
else {
cinfo.out_color_space = JCS_YCbCr;
@@ -289,7 +295,6 @@ heif_error jpeg_decode_next_image2(void* decoder_raw, heif_image** out_img,
// create destination image
- heif_image* heif_img = nullptr;
heif_error err = heif_image_create(cinfo.output_width, cinfo.output_height,
heif_colorspace_YCbCr,
heif_chroma_420,
@@ -305,6 +310,8 @@ heif_error jpeg_decode_next_image2(void* decoder_raw, heif_image** out_img,
decoder->error_message = err.message;
err.message = decoder->error_message.c_str();
+ heif_image_release(heif_img);
+ heif_img = nullptr; // avoid double free in jpeg error handler
return err;
}
err = heif_image_add_plane_safe(heif_img, heif_channel_Cb, (cinfo.output_width + 1) / 2, (cinfo.output_height + 1) / 2, 8, limits);
@@ -313,6 +320,8 @@ heif_error jpeg_decode_next_image2(void* decoder_raw, heif_image** out_img,
decoder->error_message = err.message;
err.message = decoder->error_message.c_str();
+ heif_image_release(heif_img);
+ heif_img = nullptr; // avoid double free in jpeg error handler
return err;
}
err = heif_image_add_plane_safe(heif_img, heif_channel_Cr, (cinfo.output_width + 1) / 2, (cinfo.output_height + 1) / 2, 8, limits);
@@ -321,6 +330,8 @@ heif_error jpeg_decode_next_image2(void* decoder_raw, heif_image** out_img,
decoder->error_message = err.message;
err.message = decoder->error_message.c_str();
+ heif_image_release(heif_img);
+ heif_img = nullptr; // avoid double free in jpeg error handler
return err;
}
@@ -372,6 +383,7 @@ heif_error jpeg_decode_next_image2(void* decoder_raw, heif_image** out_img,
}
*out_img = heif_img;
+ heif_img = nullptr; // pass ownership to caller (see similar comment above)
}
if (out_user_data) {