You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-07-16 22:42:38 +02:00
avcodec/mjpegdec: Fix leak in case ICC array allocations fail partially
If only one of the two arrays used for the ICC profile could be successfully allocated, it might be overwritten and leak when the next ICC entry is encountered. Fix this by using a common struct, so that one has only one array to allocate. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
@ -2088,28 +2088,26 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
|
|||||||
|
|
||||||
/* Allocate if this is the first APP2 we've seen. */
|
/* Allocate if this is the first APP2 we've seen. */
|
||||||
if (s->iccnum == 0) {
|
if (s->iccnum == 0) {
|
||||||
s->iccdata = av_mallocz(nummarkers * sizeof(*(s->iccdata)));
|
if (!FF_ALLOCZ_TYPED_ARRAY(s->iccentries, nummarkers)) {
|
||||||
s->iccdatalens = av_mallocz(nummarkers * sizeof(*(s->iccdatalens)));
|
|
||||||
if (!s->iccdata || !s->iccdatalens) {
|
|
||||||
av_log(s->avctx, AV_LOG_ERROR, "Could not allocate ICC data arrays\n");
|
av_log(s->avctx, AV_LOG_ERROR, "Could not allocate ICC data arrays\n");
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
}
|
}
|
||||||
s->iccnum = nummarkers;
|
s->iccnum = nummarkers;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->iccdata[seqno - 1]) {
|
if (s->iccentries[seqno - 1].data) {
|
||||||
av_log(s->avctx, AV_LOG_WARNING, "Duplicate ICC sequence number\n");
|
av_log(s->avctx, AV_LOG_WARNING, "Duplicate ICC sequence number\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->iccdatalens[seqno - 1] = len;
|
s->iccentries[seqno - 1].length = len;
|
||||||
s->iccdata[seqno - 1] = av_malloc(len);
|
s->iccentries[seqno - 1].data = av_malloc(len);
|
||||||
if (!s->iccdata[seqno - 1]) {
|
if (!s->iccentries[seqno - 1].data) {
|
||||||
av_log(s->avctx, AV_LOG_ERROR, "Could not allocate ICC data buffer\n");
|
av_log(s->avctx, AV_LOG_ERROR, "Could not allocate ICC data buffer\n");
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(s->iccdata[seqno - 1], align_get_bits(&s->gb), len);
|
memcpy(s->iccentries[seqno - 1].data, align_get_bits(&s->gb), len);
|
||||||
skip_bits(&s->gb, len << 3);
|
skip_bits(&s->gb, len << 3);
|
||||||
len = 0;
|
len = 0;
|
||||||
s->iccread++;
|
s->iccread++;
|
||||||
@ -2318,11 +2316,11 @@ static void reset_icc_profile(MJpegDecodeContext *s)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (s->iccdata)
|
if (s->iccentries) {
|
||||||
for (i = 0; i < s->iccnum; i++)
|
for (i = 0; i < s->iccnum; i++)
|
||||||
av_freep(&s->iccdata[i]);
|
av_freep(&s->iccentries[i].data);
|
||||||
av_freep(&s->iccdata);
|
av_freep(&s->iccentries);
|
||||||
av_freep(&s->iccdatalens);
|
}
|
||||||
|
|
||||||
s->iccread = 0;
|
s->iccread = 0;
|
||||||
s->iccnum = 0;
|
s->iccnum = 0;
|
||||||
@ -2838,7 +2836,7 @@ the_end:
|
|||||||
|
|
||||||
/* Sum size of all parts. */
|
/* Sum size of all parts. */
|
||||||
for (i = 0; i < s->iccnum; i++)
|
for (i = 0; i < s->iccnum; i++)
|
||||||
total_size += s->iccdatalens[i];
|
total_size += s->iccentries[i].length;
|
||||||
|
|
||||||
sd = av_frame_new_side_data(frame, AV_FRAME_DATA_ICC_PROFILE, total_size);
|
sd = av_frame_new_side_data(frame, AV_FRAME_DATA_ICC_PROFILE, total_size);
|
||||||
if (!sd) {
|
if (!sd) {
|
||||||
@ -2848,8 +2846,8 @@ the_end:
|
|||||||
|
|
||||||
/* Reassemble the parts, which are now in-order. */
|
/* Reassemble the parts, which are now in-order. */
|
||||||
for (i = 0; i < s->iccnum; i++) {
|
for (i = 0; i < s->iccnum; i++) {
|
||||||
memcpy(sd->data + offset, s->iccdata[i], s->iccdatalens[i]);
|
memcpy(sd->data + offset, s->iccentries[i].data, s->iccentries[i].length);
|
||||||
offset += s->iccdatalens[i];
|
offset += s->iccentries[i].length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,11 @@
|
|||||||
|
|
||||||
#define MAX_COMPONENTS 4
|
#define MAX_COMPONENTS 4
|
||||||
|
|
||||||
|
typedef struct ICCEntry {
|
||||||
|
uint8_t *data;
|
||||||
|
int length;
|
||||||
|
} ICCEntry;
|
||||||
|
|
||||||
typedef struct MJpegDecodeContext {
|
typedef struct MJpegDecodeContext {
|
||||||
AVClass *class;
|
AVClass *class;
|
||||||
AVCodecContext *avctx;
|
AVCodecContext *avctx;
|
||||||
@ -138,8 +143,7 @@ typedef struct MJpegDecodeContext {
|
|||||||
|
|
||||||
const AVPixFmtDescriptor *pix_desc;
|
const AVPixFmtDescriptor *pix_desc;
|
||||||
|
|
||||||
uint8_t **iccdata;
|
ICCEntry *iccentries;
|
||||||
int *iccdatalens;
|
|
||||||
int iccnum;
|
int iccnum;
|
||||||
int iccread;
|
int iccread;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user