[SCM] ffmpeg/upstream-0.5: Imported Upstream version 0.5.6
siretart at users.alioth.debian.org
siretart at users.alioth.debian.org
Sun Dec 25 23:12:15 UTC 2011
The following commit has been merged in the upstream-0.5 branch:
commit 19dbcde63b68a2e20bf37a17d880f709b99264fa
Author: Reinhard Tartler <siretart at tauware.de>
Date: Mon Dec 26 00:11:36 2011 +0100
Imported Upstream version 0.5.6
diff --git a/Changelog b/Changelog
index 173cc00..1d9eb79 100644
--- a/Changelog
+++ b/Changelog
@@ -2,6 +2,22 @@ Entries are sorted chronologically from oldest to youngest within each release,
releases are sorted from youngest to oldest.
+version 0.5.6:
+- svq1dec: call avcodec_set_dimensions() after dimensions changed. (NGS00148, CVE-2011-4579)
+- vmd: fix segfaults on corruped streams (CVE-2011-4364)
+- commits related to CVE-2011-4353:
+ - vp6: partially propagate huffman tree building errors during coeff model parsing and fix misspelling
+ - Plug some memory leaks in the VP6 decoder
+ - vp6: Reset the internal state when aborting key frames header parsing
+ - vp6: Fix illegal read.
+ - vp6: Fix illegal read.
+ - Fix out of bound reads in the QDM2 decoder.
+- commits related to CVE-2011-4351:
+ - Check for out of bound writes in the QDM2 decoder.
+ - qdm2: check output buffer size before decoding
+ - Fix qdm2 decoder packet handling to match the api
+
+
version 0.5.5:
- Fix memory (re)allocation in matroskadec.c (MSVR11-011/CVE-2011-3504)
diff --git a/RELEASE b/RELEASE
index 75099ad..364a327 100644
--- a/RELEASE
+++ b/RELEASE
@@ -153,3 +153,20 @@ corrected. Additional, this release contains fixes for compilation with
gcc-4.6. Distributors and system integrators are encouraged to update
and share their patches against this branch.
+
+
+* 0.5.6 Dec 25, 2011
+
+General notes
+-------------
+
+This maintenance-only release addresses several security issues that
+were brought to our attention. In details, it features fixes for the
+QDM2 decoder (CVE-2011-4351), DoS in the VP5/VP6 decoders
+(CVE-2011-4353), and a buffer overflow in the Sierra VMD decoder
+CVE-2011-4364, and a safety fix in the SVQ1 decoder (CVE-2011-4579).
+CVE-2011-4352, a bug in the VP3 decoder, is not known to affect this
+release.
+
+Distributors and system integrators are encouraged to update and share
+their patches against this branch.
diff --git a/VERSION b/VERSION
index d1d899f..b49b253 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.5.5
+0.5.6
diff --git a/libavcodec/qdm2.c b/libavcodec/qdm2.c
index a3373a1..0a48402 100644
--- a/libavcodec/qdm2.c
+++ b/libavcodec/qdm2.c
@@ -77,6 +77,7 @@ do { \
#define SAMPLES_NEEDED_2(why) \
av_log (NULL,AV_LOG_INFO,"This file triggers some missing code. Please contact the developers.\nPosition: %s\n",why);
+#define QDM2_MAX_FRAME_SIZE 512
typedef int8_t sb_int8_array[2][30][64];
@@ -169,7 +170,7 @@ typedef struct {
/// I/O data
const uint8_t *compressed_data;
int compressed_size;
- float output_buffer[1024];
+ float output_buffer[QDM2_MAX_FRAME_SIZE * 2];
/// Synthesis filter
DECLARE_ALIGNED_16(MPA_INT, synth_buf[MPA_MAX_CHANNELS][512*2]);
@@ -1377,6 +1378,8 @@ static void qdm2_fft_decode_tones (QDM2Context *q, int duration, GetBitContext *
return;
local_int_14 = (offset >> local_int_8);
+ if (local_int_14 >= FF_ARRAY_ELEMS(fft_level_index_table))
+ return;
if (q->nb_channels > 1) {
channel = get_bits1(gb);
@@ -1821,6 +1824,8 @@ static av_cold int qdm2_decode_init(AVCodecContext *avctx)
avctx->channels = s->nb_channels = s->channels = AV_RB32(extradata);
extradata += 4;
+ if (s->channels > MPA_MAX_CHANNELS)
+ return AVERROR_INVALIDDATA;
avctx->sample_rate = AV_RB32(extradata);
extradata += 4;
@@ -1843,6 +1848,8 @@ static av_cold int qdm2_decode_init(AVCodecContext *avctx)
// something like max decodable tones
s->group_order = av_log2(s->group_size) + 1;
s->frame_size = s->group_size / 16; // 16 iterations per super block
+ if (s->frame_size > QDM2_MAX_FRAME_SIZE)
+ return AVERROR_INVALIDDATA;
s->sub_sampling = s->fft_order - 7;
s->frequency_range = 255 / (1 << (2 - s->sub_sampling));
@@ -1906,7 +1913,7 @@ static av_cold int qdm2_decode_close(AVCodecContext *avctx)
}
-static void qdm2_decode (QDM2Context *q, const uint8_t *in, int16_t *out)
+static int qdm2_decode (QDM2Context *q, const uint8_t *in, int16_t *out)
{
int ch, i;
const int frame_size = (q->frame_size * q->channels);
@@ -1942,7 +1949,7 @@ static void qdm2_decode (QDM2Context *q, const uint8_t *in, int16_t *out)
if (!q->has_errors && q->sub_packet_list_C[0].packet != NULL) {
SAMPLES_NEEDED_2("has errors, and C list is not empty")
- return;
+ return -1;
}
}
@@ -1963,6 +1970,8 @@ static void qdm2_decode (QDM2Context *q, const uint8_t *in, int16_t *out)
out[i] = value;
}
+
+ return 0;
}
@@ -1971,25 +1980,33 @@ static int qdm2_decode_frame(AVCodecContext *avctx,
const uint8_t *buf, int buf_size)
{
QDM2Context *s = avctx->priv_data;
+ int16_t *out = data;
+ int i, out_size;
if(!buf)
return 0;
if(buf_size < s->checksum_size)
return -1;
- *data_size = s->channels * s->frame_size * sizeof(int16_t);
+ out_size = 16 * s->channels * s->frame_size *
+ av_get_bits_per_sample_format(avctx->sample_fmt)/8;
+ if (*data_size < out_size) {
+ av_log(avctx, AV_LOG_ERROR, "Output buffer is too small\n");
+ return AVERROR(EINVAL);
+ }
av_log(avctx, AV_LOG_DEBUG, "decode(%d): %p[%d] -> %p[%d]\n",
buf_size, buf, s->checksum_size, data, *data_size);
- qdm2_decode(s, buf, data);
-
- // reading only when next superblock found
- if (s->sub_packet == 0) {
- return s->checksum_size;
+ for (i = 0; i < 16; i++) {
+ if (qdm2_decode(s, buf, out) < 0)
+ return -1;
+ out += s->channels * s->frame_size;
}
- return 0;
+ *data_size = out_size;
+
+ return buf_size;
}
AVCodec qdm2_decoder =
diff --git a/libavcodec/svq1dec.c b/libavcodec/svq1dec.c
index 7fef10b..7c4e5c9 100644
--- a/libavcodec/svq1dec.c
+++ b/libavcodec/svq1dec.c
@@ -676,6 +676,7 @@ static int svq1_decode_frame(AVCodecContext *avctx,
#endif
return result;
}
+ avcodec_set_dimensions(avctx, s->width, s->height);
//FIXME this avoids some confusion for "B frames" without 2 references
//this should be removed after libavcodec can handle more flexible picture types & ordering
diff --git a/libavcodec/vmdav.c b/libavcodec/vmdav.c
index 1921c81..60dc7f9 100644
--- a/libavcodec/vmdav.c
+++ b/libavcodec/vmdav.c
@@ -73,9 +73,11 @@ typedef struct VmdVideoContext {
#define QUEUE_SIZE 0x1000
#define QUEUE_MASK 0x0FFF
-static void lz_unpack(const unsigned char *src, unsigned char *dest, int dest_len)
+static void lz_unpack(const unsigned char *src, int src_len,
+ unsigned char *dest, int dest_len)
{
const unsigned char *s;
+ unsigned int s_len;
unsigned char *d;
unsigned char *d_end;
unsigned char queue[QUEUE_SIZE];
@@ -88,13 +90,16 @@ static void lz_unpack(const unsigned char *src, unsigned char *dest, int dest_le
unsigned int i, j;
s = src;
+ s_len = src_len;
d = dest;
d_end = d + dest_len;
dataleft = AV_RL32(s);
- s += 4;
+ s += 4; s_len -= 4;
memset(queue, 0x20, QUEUE_SIZE);
+ if (s_len < 4)
+ return;
if (AV_RL32(s) == 0x56781234) {
- s += 4;
+ s += 4; s_len -= 4;
qpos = 0x111;
speclen = 0xF + 3;
} else {
@@ -102,32 +107,41 @@ static void lz_unpack(const unsigned char *src, unsigned char *dest, int dest_le
speclen = 100; /* no speclen */
}
- while (dataleft > 0) {
- tag = *s++;
+ while (dataleft > 0 && s_len > 0) {
+ tag = *s++; s_len--;
if ((tag == 0xFF) && (dataleft > 8)) {
- if (d + 8 > d_end)
+ if (d + 8 > d_end || s_len < 8)
return;
for (i = 0; i < 8; i++) {
queue[qpos++] = *d++ = *s++;
qpos &= QUEUE_MASK;
}
+ s_len -= 8;
dataleft -= 8;
} else {
for (i = 0; i < 8; i++) {
if (dataleft == 0)
break;
if (tag & 0x01) {
- if (d + 1 > d_end)
+ if (d + 1 > d_end || s_len < 1)
return;
queue[qpos++] = *d++ = *s++;
qpos &= QUEUE_MASK;
dataleft--;
+ s_len--;
} else {
+ if (s_len < 2)
+ return;
chainofs = *s++;
chainofs |= ((*s & 0xF0) << 4);
chainlen = (*s++ & 0x0F) + 3;
- if (chainlen == speclen)
+ s_len -= 2;
+ if (chainlen == speclen) {
+ if (s_len < 1)
+ return;
chainlen = *s++ + 0xF + 3;
+ s_len--;
+ }
if (d + chainlen > d_end)
return;
for (j = 0; j < chainlen; j++) {
@@ -144,7 +158,7 @@ static void lz_unpack(const unsigned char *src, unsigned char *dest, int dest_le
}
static int rle_unpack(const unsigned char *src, unsigned char *dest,
- int src_len, int dest_len)
+ int src_count, int src_size, int dest_len)
{
const unsigned char *ps;
unsigned char *pd;
@@ -153,31 +167,40 @@ static int rle_unpack(const unsigned char *src, unsigned char *dest,
ps = src;
pd = dest;
- if (src_len & 1)
+ if (src_count & 1) {
+ if (src_size < 1)
+ return 0;
*pd++ = *ps++;
+ src_size--;
+ }
- src_len >>= 1;
+ src_count >>= 1;
i = 0;
do {
+ if (src_size < 1)
+ break;
l = *ps++;
+ src_size--;
if (l & 0x80) {
l = (l & 0x7F) * 2;
- if (pd + l > dest_end)
+ if (pd + l > dest_end || src_size < l)
return ps - src;
memcpy(pd, ps, l);
ps += l;
+ src_size -= l;
pd += l;
} else {
- if (pd + i > dest_end)
+ if (pd + i > dest_end || src_size < 2)
return ps - src;
for (i = 0; i < l; i++) {
*pd++ = ps[0];
*pd++ = ps[1];
}
ps += 2;
+ src_size -= 2;
}
i += l;
- } while (i < src_len);
+ } while (i < src_count);
return ps - src;
}
@@ -192,6 +215,7 @@ static void vmd_decode(VmdVideoContext *s)
const unsigned char *p = s->buf + 16;
const unsigned char *pb;
+ unsigned int pb_size;
unsigned char meth;
unsigned char *dp; /* pointer to current frame */
unsigned char *pp; /* pointer to previous frame */
@@ -206,6 +230,16 @@ static void vmd_decode(VmdVideoContext *s)
frame_y = AV_RL16(&s->buf[8]);
frame_width = AV_RL16(&s->buf[10]) - frame_x + 1;
frame_height = AV_RL16(&s->buf[12]) - frame_y + 1;
+ if (frame_x < 0 || frame_width < 0 ||
+ frame_x >= s->avctx->width ||
+ frame_width > s->avctx->width ||
+ frame_x + frame_width > s->avctx->width)
+ return;
+ if (frame_y < 0 || frame_height < 0 ||
+ frame_y >= s->avctx->height ||
+ frame_height > s->avctx->height ||
+ frame_y + frame_height > s->avctx->height)
+ return;
if ((frame_width == s->avctx->width && frame_height == s->avctx->height) &&
(frame_x || frame_y)) {
@@ -218,8 +252,9 @@ static void vmd_decode(VmdVideoContext *s)
/* if only a certain region will be updated, copy the entire previous
* frame before the decode */
- if (frame_x || frame_y || (frame_width != s->avctx->width) ||
- (frame_height != s->avctx->height)) {
+ if (s->prev_frame.data[0] &&
+ (frame_x || frame_y || (frame_width != s->avctx->width) ||
+ (frame_height != s->avctx->height))) {
memcpy(s->frame.data[0], s->prev_frame.data[0],
s->avctx->height * s->frame.linesize[0]);
@@ -237,14 +272,19 @@ static void vmd_decode(VmdVideoContext *s)
}
s->size -= (256 * 3 + 2);
}
- if (s->size >= 0) {
+ if (s->size > 0) {
/* originally UnpackFrame in VAG's code */
pb = p;
- meth = *pb++;
+ pb_size = s->buf + s->size - pb;
+ if (pb_size < 1)
+ return;
+ meth = *pb++; pb_size--;
if (meth & 0x80) {
- lz_unpack(pb, s->unpack_buffer, s->unpack_buffer_size);
+ lz_unpack(pb, pb_size,
+ s->unpack_buffer, s->unpack_buffer_size);
meth &= 0x7F;
pb = s->unpack_buffer;
+ pb_size = s->unpack_buffer_size;
}
dp = &s->frame.data[0][frame_y * s->frame.linesize[0] + frame_x];
@@ -255,17 +295,21 @@ static void vmd_decode(VmdVideoContext *s)
for (i = 0; i < frame_height; i++) {
ofs = 0;
do {
+ if (pb_size < 1)
+ return;
len = *pb++;
+ pb_size--;
if (len & 0x80) {
len = (len & 0x7F) + 1;
- if (ofs + len > frame_width)
+ if (ofs + len > frame_width || pb_size < len)
return;
memcpy(&dp[ofs], pb, len);
pb += len;
+ pb_size -= len;
ofs += len;
} else {
/* interframe pixel copy */
- if (ofs + len + 1 > frame_width)
+ if (ofs + len + 1 > frame_width || !s->prev_frame.data[0])
return;
memcpy(&dp[ofs], &pp[ofs], len + 1);
ofs += len + 1;
@@ -283,8 +327,11 @@ static void vmd_decode(VmdVideoContext *s)
case 2:
for (i = 0; i < frame_height; i++) {
+ if (pb_size < frame_width)
+ return;
memcpy(dp, pb, frame_width);
pb += frame_width;
+ pb_size -= frame_width;
dp += s->frame.linesize[0];
pp += s->prev_frame.linesize[0];
}
@@ -294,18 +341,27 @@ static void vmd_decode(VmdVideoContext *s)
for (i = 0; i < frame_height; i++) {
ofs = 0;
do {
+ if (pb_size < 1)
+ return;
len = *pb++;
+ pb_size--;
if (len & 0x80) {
len = (len & 0x7F) + 1;
+ if (pb_size < 1)
+ return;
if (*pb++ == 0xFF)
- len = rle_unpack(pb, &dp[ofs], len, frame_width - ofs);
- else
+ len = rle_unpack(pb, &dp[ofs], len, pb_size, frame_width - ofs);
+ else {
+ if (pb_size < len)
+ return;
memcpy(&dp[ofs], pb, len);
+ }
pb += len;
+ pb_size -= 1 + len;
ofs += len;
} else {
/* interframe pixel copy */
- if (ofs + len + 1 > frame_width)
+ if (ofs + len + 1 > frame_width || !s->prev_frame.data[0])
return;
memcpy(&dp[ofs], &pp[ofs], len + 1);
ofs += len + 1;
diff --git a/libavcodec/vp56.c b/libavcodec/vp56.c
index ad11b52..c09dbeb 100644
--- a/libavcodec/vp56.c
+++ b/libavcodec/vp56.c
@@ -685,6 +685,7 @@ av_cold void vp56_init(AVCodecContext *avctx, int flip, int has_alpha)
av_cold int vp56_free(AVCodecContext *avctx)
{
VP56Context *s = avctx->priv_data;
+ int pt;
av_free(s->above_blocks);
av_free(s->macroblocks);
@@ -695,5 +696,15 @@ av_cold int vp56_free(AVCodecContext *avctx)
avctx->release_buffer(avctx, s->framep[VP56_FRAME_GOLDEN2]);
if (s->framep[VP56_FRAME_PREVIOUS]->data[0])
avctx->release_buffer(avctx, s->framep[VP56_FRAME_PREVIOUS]);
+
+ for (pt=0; pt < 2; pt++) {
+ int ct, cg;
+ free_vlc(&s->dccv_vlc[pt]);
+ free_vlc(&s->runv_vlc[pt]);
+ for (ct=0; ct<3; ct++)
+ for (cg = 0; cg < 6; cg++)
+ free_vlc(&s->ract_vlc[pt][ct][cg]);
+ }
+
return 0;
}
diff --git a/libavcodec/vp6.c b/libavcodec/vp6.c
index 5071903..d9e9711 100644
--- a/libavcodec/vp6.c
+++ b/libavcodec/vp6.c
@@ -136,8 +136,11 @@ static int vp6_parse_header(VP56Context *s, const uint8_t *buf, int buf_size,
if (coeff_offset) {
buf += coeff_offset;
buf_size -= coeff_offset;
- if (buf_size < 0)
+ if (buf_size < 0) {
+ if (s->framep[VP56_FRAME_CURRENT]->key_frame)
+ avcodec_set_dimensions(s->avctx, 0, 0);
return 0;
+ }
if (s->use_huffman) {
s->parse_coeff = vp6_parse_coeff_huffman;
init_get_bits(&s->gb, buf, buf_size<<3);
@@ -212,8 +215,8 @@ static int vp6_huff_cmp(const void *va, const void *vb)
return (a->count - b->count)*16 + (b->sym - a->sym);
}
-static void vp6_build_huff_tree(VP56Context *s, uint8_t coeff_model[],
- const uint8_t *map, unsigned size, VLC *vlc)
+static int vp6_build_huff_tree(VP56Context *s, uint8_t coeff_model[],
+ const uint8_t *map, unsigned size, VLC *vlc)
{
Node nodes[2*size], *tmp = &nodes[size];
int a, b, i;
@@ -227,9 +230,10 @@ static void vp6_build_huff_tree(VP56Context *s, uint8_t coeff_model[],
nodes[map[2*i+1]].count = b + !b;
}
- /* then build the huffman tree accodring to probabilities */
- ff_huff_build_tree(s->avctx, vlc, size, nodes, vp6_huff_cmp,
- FF_HUFFMAN_FLAG_HNODE_FIRST);
+ free_vlc(vlc);
+ /* then build the huffman tree according to probabilities */
+ return ff_huff_build_tree(s->avctx, vlc, size, nodes, vp6_huff_cmp,
+ FF_HUFFMAN_FLAG_HNODE_FIRST);
}
static void vp6_parse_coeff_models(VP56Context *s)
@@ -365,7 +369,7 @@ static void vp6_parse_coeff_huffman(VP56Context *s)
if (b > 3) pt = 1;
vlc_coeff = &s->dccv_vlc[pt];
- for (coeff_idx=0; coeff_idx<64; ) {
+ for (coeff_idx = 0;;) {
int run = 1;
if (coeff_idx<2 && s->nb_null[coeff_idx][pt]) {
s->nb_null[coeff_idx][pt]--;
@@ -400,6 +404,8 @@ static void vp6_parse_coeff_huffman(VP56Context *s)
}
}
coeff_idx+=run;
+ if (coeff_idx >= 64)
+ break;
cg = FFMIN(vp6_coeff_groups[coeff_idx], 3);
vlc_coeff = &s->ract_vlc[pt][ct][cg];
}
@@ -427,7 +433,8 @@ static void vp6_parse_coeff(VP56Context *s)
model1 = model->coeff_dccv[pt];
model2 = model->coeff_dcct[pt][ctx];
- for (coeff_idx=0; coeff_idx<64; ) {
+ coeff_idx = 0;
+ for (;;) {
if ((coeff_idx>1 && ct==0) || vp56_rac_get_prob(c, model2[0])) {
/* parse a coeff */
if (vp56_rac_get_prob(c, model2[2])) {
@@ -468,8 +475,10 @@ static void vp6_parse_coeff(VP56Context *s)
run += vp56_rac_get_prob(c, model3[i+8]) << i;
}
}
-
- cg = vp6_coeff_groups[coeff_idx+=run];
+ coeff_idx += run;
+ if (coeff_idx >= 64)
+ break;
+ cg = vp6_coeff_groups[coeff_idx];
model1 = model2 = model->coeff_ract[pt][ct][cg];
}
--
Libav/FFmpeg packaging
More information about the pkg-multimedia-commits
mailing list