Hi,
according to the WebP Lossless Bitstream Specification [1] "each
transform is allowed to be used only once". Attached patch adds checks
for this to avoid crashes decoding broken files.
Best regards,
Andreas
1:
https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification#3_transformations
>From d80baa7f786ca326891e145a000fbecdde55da80 Mon Sep 17 00:00:00 2001
From: Andreas Cadhalpun <andreas.cadhal...@googlemail.com>
Date: Thu, 5 Mar 2015 22:48:28 +0100
Subject: [PATCH] webp: ensure that each transform is only used once
According to the WebP Lossless Bitstream Specification
"each transform is allowed to be used only once".
If a transform is more than once this can lead to memory
corruption.
Signed-off-by: Andreas Cadhalpun <andreas.cadhal...@googlemail.com>
---
libavcodec/webp.c | 39 +++++++++++++++++++++++++++++++++++----
1 file changed, 35 insertions(+), 4 deletions(-)
diff --git a/libavcodec/webp.c b/libavcodec/webp.c
index 9549c0e..2cd976f 100644
--- a/libavcodec/webp.c
+++ b/libavcodec/webp.c
@@ -1104,7 +1104,7 @@ static int vp8_lossless_decode_frame(AVCodecContext *avctx, AVFrame *p,
unsigned int data_size, int is_alpha_chunk)
{
WebPContext *s = avctx->priv_data;
- int w, h, ret, i;
+ int w, h, ret, i, used;
if (!is_alpha_chunk) {
s->lossless = 1;
@@ -1154,18 +1154,49 @@ static int vp8_lossless_decode_frame(AVCodecContext *avctx, AVFrame *p,
/* parse transformations */
s->nb_transforms = 0;
s->reduced_width = 0;
+ used = 0;
while (get_bits1(&s->gb)) {
enum TransformType transform = get_bits(&s->gb, 2);
s->transforms[s->nb_transforms++] = transform;
switch (transform) {
case PREDICTOR_TRANSFORM:
- ret = parse_transform_predictor(s);
+ if (used & 1) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Predictor transform used more than once\n");
+ ret = AVERROR_INVALIDDATA;
+ } else {
+ used |= 1;
+ ret = parse_transform_predictor(s);
+ }
break;
case COLOR_TRANSFORM:
- ret = parse_transform_color(s);
+ if (used & 2) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Color transform used more than once\n");
+ ret = AVERROR_INVALIDDATA;
+ } else {
+ used |= 2;
+ ret = parse_transform_color(s);
+ }
+ break;
+ case SUBTRACT_GREEN:
+ if (used & 4) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Subtract green used more than once\n");
+ ret = AVERROR_INVALIDDATA;
+ } else {
+ used |= 4;
+ }
break;
case COLOR_INDEXING_TRANSFORM:
- ret = parse_transform_color_indexing(s);
+ if (used & 8) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Color indexing transform used more than once\n");
+ ret = AVERROR_INVALIDDATA;
+ } else {
+ used |= 8;
+ ret = parse_transform_color_indexing(s);
+ }
break;
}
if (ret < 0)
--
2.1.4
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel