aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRam Mohan <ram.mohan@ittiam.com>2023-10-18 17:25:35 +0530
committerRam Mohan M <ram.mohan@ittiam.com>2023-10-18 18:05:44 +0530
commit0876ae4f1c4e41b131f03420f6d8430d54a284e2 (patch)
tree8885642136086d49227ed834cab673ece5b9b7e1
parent9a3ef84909d87c56899acb0d23265f6ef9498967 (diff)
downloadlibultrahdr-0876ae4f1c4e41b131f03420f6d8430d54a284e2.tar.gz
Memory leaks due to longjmp over std::unique_ptr dtors
The jpeg decoder helper class is using long jumps if errors are seen during decode. This is by passing the calls to destructors of std::unique_ptr causing a memory leak. Move these allocs to parent class there by ensuring the dtor calls Bug: oss-fuzz-63337 Test: ./ultrahdr_dec_fuzzer
-rw-r--r--include/ultrahdr/jpegdecoderhelper.h4
-rw-r--r--jpegdecoderhelper.cpp25
2 files changed, 15 insertions, 14 deletions
diff --git a/include/ultrahdr/jpegdecoderhelper.h b/include/ultrahdr/jpegdecoderhelper.h
index bc3d517..4c8b601 100644
--- a/include/ultrahdr/jpegdecoderhelper.h
+++ b/include/ultrahdr/jpegdecoderhelper.h
@@ -32,6 +32,7 @@ extern "C" {
#endif
#include <cstdint>
+#include <memory>
#include <vector>
// constraint on max width and max height is only due to device alloc constraints
@@ -145,6 +146,9 @@ private:
// Position of EXIF package, default value is -1 which means no EXIF package appears.
int mExifPos = -1;
+
+ std::unique_ptr<uint8_t[]> mEmpty = nullptr;
+ std::unique_ptr<uint8_t[]> mBufferIntermediate = nullptr;
};
} /* namespace ultrahdr */
diff --git a/jpegdecoderhelper.cpp b/jpegdecoderhelper.cpp
index 91bab65..3f36743 100644
--- a/jpegdecoderhelper.cpp
+++ b/jpegdecoderhelper.cpp
@@ -18,7 +18,6 @@
#include <setjmp.h>
#include <cstring>
-#include <memory>
#include "ultrahdr/ultrahdrcommon.h"
#include "ultrahdr/ultrahdr.h"
@@ -435,12 +434,11 @@ bool JpegDecoderHelper::decompressYUV(jpeg_decompress_struct* cinfo, const uint8
uint8_t* y_plane = const_cast<uint8_t*>(dest);
uint8_t* u_plane = const_cast<uint8_t*>(dest + y_plane_size);
uint8_t* v_plane = const_cast<uint8_t*>(dest + y_plane_size + uv_plane_size);
- std::unique_ptr<uint8_t[]> empty = std::make_unique<uint8_t[]>(cinfo->image_width);
- memset(empty.get(), 0, cinfo->image_width);
+ mEmpty = std::make_unique<uint8_t[]>(cinfo->image_width);
+ memset(mEmpty.get(), 0, cinfo->image_width);
const size_t aligned_width = ALIGNM(cinfo->image_width, kCompressBatchSize);
bool is_width_aligned = (aligned_width == cinfo->image_width);
- std::unique_ptr<uint8_t[]> buffer_intrm = nullptr;
uint8_t* y_plane_intrm = nullptr;
uint8_t* u_plane_intrm = nullptr;
uint8_t* v_plane_intrm = nullptr;
@@ -450,8 +448,8 @@ bool JpegDecoderHelper::decompressYUV(jpeg_decompress_struct* cinfo, const uint8
JSAMPARRAY planes_intrm[3]{y_intrm, cb_intrm, cr_intrm};
if (!is_width_aligned) {
size_t mcu_row_size = aligned_width * kCompressBatchSize * 3 / 2;
- buffer_intrm = std::make_unique<uint8_t[]>(mcu_row_size);
- y_plane_intrm = buffer_intrm.get();
+ mBufferIntermediate = std::make_unique<uint8_t[]>(mcu_row_size);
+ y_plane_intrm = mBufferIntermediate.get();
u_plane_intrm = y_plane_intrm + (aligned_width * kCompressBatchSize);
v_plane_intrm = u_plane_intrm + (aligned_width * kCompressBatchSize) / 4;
for (int i = 0; i < kCompressBatchSize; ++i) {
@@ -470,7 +468,7 @@ bool JpegDecoderHelper::decompressYUV(jpeg_decompress_struct* cinfo, const uint8
if (scanline < cinfo->image_height) {
y[i] = y_plane + scanline * cinfo->image_width;
} else {
- y[i] = empty.get();
+ y[i] = mEmpty.get();
}
}
// cb, cr only have half scanlines
@@ -481,7 +479,7 @@ bool JpegDecoderHelper::decompressYUV(jpeg_decompress_struct* cinfo, const uint8
cb[i] = u_plane + offset;
cr[i] = v_plane + offset;
} else {
- cb[i] = cr[i] = empty.get();
+ cb[i] = cr[i] = mEmpty.get();
}
}
@@ -510,19 +508,18 @@ bool JpegDecoderHelper::decompressSingleChannel(jpeg_decompress_struct* cinfo,
JSAMPARRAY planes[1]{y};
uint8_t* y_plane = const_cast<uint8_t*>(dest);
- std::unique_ptr<uint8_t[]> empty = std::make_unique<uint8_t[]>(cinfo->image_width);
- memset(empty.get(), 0, cinfo->image_width);
+ mEmpty = std::make_unique<uint8_t[]>(cinfo->image_width);
+ memset(mEmpty.get(), 0, cinfo->image_width);
const size_t aligned_width = ALIGNM(cinfo->image_width, kCompressBatchSize);
bool is_width_aligned = (aligned_width == cinfo->image_width);
- std::unique_ptr<uint8_t[]> buffer_intrm = nullptr;
uint8_t* y_plane_intrm = nullptr;
JSAMPROW y_intrm[kCompressBatchSize];
JSAMPARRAY planes_intrm[1]{y_intrm};
if (!is_width_aligned) {
size_t mcu_row_size = aligned_width * kCompressBatchSize;
- buffer_intrm = std::make_unique<uint8_t[]>(mcu_row_size);
- y_plane_intrm = buffer_intrm.get();
+ mBufferIntermediate = std::make_unique<uint8_t[]>(mcu_row_size);
+ y_plane_intrm = mBufferIntermediate.get();
for (int i = 0; i < kCompressBatchSize; ++i) {
y_intrm[i] = y_plane_intrm + i * aligned_width;
}
@@ -534,7 +531,7 @@ bool JpegDecoderHelper::decompressSingleChannel(jpeg_decompress_struct* cinfo,
if (scanline < cinfo->image_height) {
y[i] = y_plane + scanline * cinfo->image_width;
} else {
- y[i] = empty.get();
+ y[i] = mEmpty.get();
}
}