aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Niedermayer <michael@niedermayer.cc>2018-01-31 17:50:21 +0100
committerMichael Niedermayer <michael@niedermayer.cc>2018-04-13 00:35:15 +0200
commitd07a0ae1af038ad6d4a4084d22940b4efbea141e (patch)
tree097b87155d1c1b63fb42f0d1f315f4c502c4cf41
parent55f9c21363af98b0f00c927b7d9c9a92f2f378d2 (diff)
downloadffmpeg-d07a0ae1af038ad6d4a4084d22940b4efbea141e.tar.gz
avcodec/exr: Fix memleaks in decode_header()
Fixes: 4793/clusterfuzz-testcase-minimized-5707366629638144 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer <michael@niedermayer.cc> (cherry picked from commit 0a2560a9775be7c5df09c85c9908b05e711a54a3) Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
-rw-r--r--libavcodec/exr.c82
1 files changed, 56 insertions, 26 deletions
diff --git a/libavcodec/exr.c b/libavcodec/exr.c
index 7fa17ca887..fe978805c5 100644
--- a/libavcodec/exr.c
+++ b/libavcodec/exr.c
@@ -1317,6 +1317,7 @@ static int decode_header(EXRContext *s, AVFrame *frame)
AVDictionary *metadata = NULL;
int magic_number, version, i, flags, sar = 0;
int layer_match = 0;
+ int ret;
s->current_channel_offset = 0;
s->xmin = ~0;
@@ -1375,8 +1376,10 @@ static int decode_header(EXRContext *s, AVFrame *frame)
if ((var_size = check_header_variable(s, "channels",
"chlist", 38)) >= 0) {
GetByteContext ch_gb;
- if (!var_size)
- return AVERROR_INVALIDDATA;
+ if (!var_size) {
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
bytestream2_init(&ch_gb, s->gb.buffer, var_size);
@@ -1435,14 +1438,16 @@ static int decode_header(EXRContext *s, AVFrame *frame)
if (bytestream2_get_bytes_left(&ch_gb) < 4) {
av_log(s->avctx, AV_LOG_ERROR, "Incomplete header.\n");
- return AVERROR_INVALIDDATA;
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
}
current_pixel_type = bytestream2_get_le32(&ch_gb);
if (current_pixel_type >= EXR_UNKNOWN) {
avpriv_report_missing_feature(s->avctx, "Pixel type %d",
current_pixel_type);
- return AVERROR_PATCHWELCOME;
+ ret = AVERROR_PATCHWELCOME;
+ goto fail;
}
bytestream2_skip(&ch_gb, 4);
@@ -1453,7 +1458,8 @@ static int decode_header(EXRContext *s, AVFrame *frame)
avpriv_report_missing_feature(s->avctx,
"Subsampling %dx%d",
xsub, ysub);
- return AVERROR_PATCHWELCOME;
+ ret = AVERROR_PATCHWELCOME;
+ goto fail;
}
if (channel_index >= 0 && s->channel_offsets[channel_index] == -1) { /* channel has not been previously assigned */
@@ -1461,7 +1467,8 @@ static int decode_header(EXRContext *s, AVFrame *frame)
s->pixel_type != current_pixel_type) {
av_log(s->avctx, AV_LOG_ERROR,
"RGB channels not of the same depth.\n");
- return AVERROR_INVALIDDATA;
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
}
s->pixel_type = current_pixel_type;
s->channel_offsets[channel_index] = s->current_channel_offset;
@@ -1469,8 +1476,10 @@ static int decode_header(EXRContext *s, AVFrame *frame)
s->channels = av_realloc(s->channels,
++s->nb_channels * sizeof(EXRChannel));
- if (!s->channels)
- return AVERROR(ENOMEM);
+ if (!s->channels) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
channel = &s->channels[s->nb_channels - 1];
channel->pixel_type = current_pixel_type;
channel->xsub = xsub;
@@ -1495,7 +1504,8 @@ static int decode_header(EXRContext *s, AVFrame *frame)
av_log(s->avctx, AV_LOG_ERROR, "Missing green channel.\n");
if (s->channel_offsets[2] < 0)
av_log(s->avctx, AV_LOG_ERROR, "Missing blue channel.\n");
- return AVERROR_INVALIDDATA;
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
}
}
@@ -1504,8 +1514,10 @@ static int decode_header(EXRContext *s, AVFrame *frame)
continue;
} else if ((var_size = check_header_variable(s, "dataWindow", "box2i",
31)) >= 0) {
- if (!var_size)
- return AVERROR_INVALIDDATA;
+ if (!var_size) {
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
s->xmin = bytestream2_get_le32(&s->gb);
s->ymin = bytestream2_get_le32(&s->gb);
@@ -1517,8 +1529,10 @@ static int decode_header(EXRContext *s, AVFrame *frame)
continue;
} else if ((var_size = check_header_variable(s, "displayWindow",
"box2i", 34)) >= 0) {
- if (!var_size)
- return AVERROR_INVALIDDATA;
+ if (!var_size) {
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
bytestream2_skip(&s->gb, 8);
s->w = bytestream2_get_le32(&s->gb) + 1;
@@ -1528,29 +1542,36 @@ static int decode_header(EXRContext *s, AVFrame *frame)
} else if ((var_size = check_header_variable(s, "lineOrder",
"lineOrder", 25)) >= 0) {
int line_order;
- if (!var_size)
- return AVERROR_INVALIDDATA;
+ if (!var_size) {
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
line_order = bytestream2_get_byte(&s->gb);
av_log(s->avctx, AV_LOG_DEBUG, "line order: %d.\n", line_order);
if (line_order > 2) {
av_log(s->avctx, AV_LOG_ERROR, "Unknown line order.\n");
- return AVERROR_INVALIDDATA;
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
}
continue;
} else if ((var_size = check_header_variable(s, "pixelAspectRatio",
"float", 31)) >= 0) {
- if (!var_size)
- return AVERROR_INVALIDDATA;
+ if (!var_size) {
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
sar = bytestream2_get_le32(&s->gb);
continue;
} else if ((var_size = check_header_variable(s, "compression",
"compression", 29)) >= 0) {
- if (!var_size)
- return AVERROR_INVALIDDATA;
+ if (!var_size) {
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
if (s->compression == EXR_UNKN)
s->compression = bytestream2_get_byte(&s->gb);
@@ -1577,13 +1598,15 @@ static int decode_header(EXRContext *s, AVFrame *frame)
if (s->tile_attr.level_mode >= EXR_TILE_LEVEL_UNKNOWN){
avpriv_report_missing_feature(s->avctx, "Tile level mode %d",
s->tile_attr.level_mode);
- return AVERROR_PATCHWELCOME;
+ ret = AVERROR_PATCHWELCOME;
+ goto fail;
}
if (s->tile_attr.level_round >= EXR_TILE_ROUND_UNKNOWN) {
avpriv_report_missing_feature(s->avctx, "Tile level round %d",
s->tile_attr.level_round);
- return AVERROR_PATCHWELCOME;
+ ret = AVERROR_PATCHWELCOME;
+ goto fail;
}
continue;
@@ -1600,7 +1623,8 @@ static int decode_header(EXRContext *s, AVFrame *frame)
// Check if there are enough bytes for a header
if (bytestream2_get_bytes_left(&s->gb) <= 9) {
av_log(s->avctx, AV_LOG_ERROR, "Incomplete header\n");
- return AVERROR_INVALIDDATA;
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
}
// Process unknown variables
@@ -1615,19 +1639,22 @@ static int decode_header(EXRContext *s, AVFrame *frame)
if (s->compression == EXR_UNKN) {
av_log(s->avctx, AV_LOG_ERROR, "Missing compression attribute.\n");
- return AVERROR_INVALIDDATA;
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
}
if (s->is_tile) {
if (s->tile_attr.xSize < 1 || s->tile_attr.ySize < 1) {
av_log(s->avctx, AV_LOG_ERROR, "Invalid tile attribute.\n");
- return AVERROR_INVALIDDATA;
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
}
}
if (bytestream2_get_bytes_left(&s->gb) <= 0) {
av_log(s->avctx, AV_LOG_ERROR, "Incomplete frame.\n");
- return AVERROR_INVALIDDATA;
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
}
av_frame_set_metadata(frame, metadata);
@@ -1635,6 +1662,9 @@ static int decode_header(EXRContext *s, AVFrame *frame)
// aaand we are done
bytestream2_skip(&s->gb, 1);
return 0;
+fail:
+ av_dict_free(&metadata);
+ return ret;
}
static int decode_frame(AVCodecContext *avctx, void *data,