1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-23 12:43:46 +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>
(cherry picked from commit a5b2f06b0c)
This commit is contained in:
Andreas Rheinhardt 2021-04-03 15:39:35 +02:00
parent 5621d10b7a
commit 6aad0b1bb5
2 changed files with 19 additions and 17 deletions

View File

@ -2087,28 +2087,26 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
/* Allocate if this is the first APP2 we've seen. */
if (s->iccnum == 0) {
s->iccdata = av_mallocz(nummarkers * sizeof(*(s->iccdata)));
s->iccdatalens = av_mallocz(nummarkers * sizeof(*(s->iccdatalens)));
if (!s->iccdata || !s->iccdatalens) {
if (!FF_ALLOCZ_TYPED_ARRAY(s->iccentries, nummarkers)) {
av_log(s->avctx, AV_LOG_ERROR, "Could not allocate ICC data arrays\n");
return AVERROR(ENOMEM);
}
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");
goto out;
}
s->iccdatalens[seqno - 1] = len;
s->iccdata[seqno - 1] = av_malloc(len);
if (!s->iccdata[seqno - 1]) {
s->iccentries[seqno - 1].length = len;
s->iccentries[seqno - 1].data = av_malloc(len);
if (!s->iccentries[seqno - 1].data) {
av_log(s->avctx, AV_LOG_ERROR, "Could not allocate ICC data buffer\n");
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);
len = 0;
s->iccread++;
@ -2317,11 +2315,11 @@ static void reset_icc_profile(MJpegDecodeContext *s)
{
int i;
if (s->iccdata)
if (s->iccentries) {
for (i = 0; i < s->iccnum; i++)
av_freep(&s->iccdata[i]);
av_freep(&s->iccdata);
av_freep(&s->iccdatalens);
av_freep(&s->iccentries[i].data);
av_freep(&s->iccentries);
}
s->iccread = 0;
s->iccnum = 0;
@ -2837,7 +2835,7 @@ the_end:
/* Sum size of all parts. */
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);
if (!sd) {
@ -2847,8 +2845,8 @@ the_end:
/* Reassemble the parts, which are now in-order. */
for (i = 0; i < s->iccnum; i++) {
memcpy(sd->data + offset, s->iccdata[i], s->iccdatalens[i]);
offset += s->iccdatalens[i];
memcpy(sd->data + offset, s->iccentries[i].data, s->iccentries[i].length);
offset += s->iccentries[i].length;
}
}

View File

@ -44,6 +44,11 @@
#define MAX_COMPONENTS 4
typedef struct ICCEntry {
uint8_t *data;
int length;
} ICCEntry;
typedef struct MJpegDecodeContext {
AVClass *class;
AVCodecContext *avctx;
@ -138,8 +143,7 @@ typedef struct MJpegDecodeContext {
const AVPixFmtDescriptor *pix_desc;
uint8_t **iccdata;
int *iccdatalens;
ICCEntry *iccentries;
int iccnum;
int iccread;