Compare commits

...

16 Commits

Author SHA1 Message Date
e75056bc54 Update for 0.5.7
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
2011-12-25 21:43:56 +01:00
8755a7890e Merge remote-tracking branch 'qatar/release/0.5' into release/0.5
* qatar/release/0.5:
  Release notes and changelog for 0.5.6

Conflicts:
	RELEASE

Merged-by: Michael Niedermayer <michaelni@gmx.at>
2011-12-25 20:19:13 +01:00
d0688fdd31 Release notes and changelog for 0.5.6 2011-12-25 10:18:18 +01:00
0e05292a6c Merge remote-tracking branch 'qatar/release/0.5' into release/0.5
* qatar/release/0.5:
  Bump version number for 0.5.6 release.
  svq1dec: call avcodec_set_dimensions() after dimensions changed.
  vmd: fix segfaults on corruped streams
  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.
  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

Conflicts:
	libavcodec/qdm2.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
2011-12-25 00:53:49 +01:00
23f228a0d0 Bump version number for 0.5.6 release. 2011-12-24 16:32:06 +01:00
110aff4b24 svq1dec: call avcodec_set_dimensions() after dimensions changed.
Fixes NGS00148, CVE-2011-4579

Found-by: Phillip Langlois
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>

(cherry picked from commit 6e24b9488e)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
(cherry picked from commit 0eca0da06e)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
(cherry picked from commit 8ddc0b491d)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
2011-12-24 16:28:20 +01:00
4a1c3df592 vmd: fix segfaults on corruped streams
Signed-off-by: Janne Grunau <janne-libav@jannau.net>
Signed-off-by: Reinhard Tartler <siretart@tauware.de>
(cherry picked from commit 494cfacdb9)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
(cherry picked from commit b99366faef)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
2011-12-24 16:28:20 +01:00
185abfb218 vp6: partially propagate huffman tree building errors during coeff model parsing and fix misspelling
Signed-off-by: Ronald S. Bultje <rsbultje@gmail.com>
(cherry picked from commit f913eeea43)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
(cherry picked from commit 7367cbec1b)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
(cherry picked from commit 201fcfb894)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
2011-12-24 16:28:20 +01:00
280590e338 Plug some memory leaks in the VP6 decoder
Originally committed as revision 22172 to svn://svn.ffmpeg.org/ffmpeg/trunk
(cherry picked from commit 0a41faa9a7)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
2011-12-24 16:28:19 +01:00
9767ea7aa7 vp6: Reset the internal state when aborting key frames header parsing
It prevents leaving the state only half initialized.

Signed-off-by: Janne Grunau <janne-libav@jannau.net>
(cherry picked from commit a72cad0a6c)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
(cherry picked from commit c76505e0de)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
(cherry picked from commit e28bb18fdc)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
2011-12-24 16:17:42 +01:00
771ceb19f2 vp6: Fix illegal read.
Found with Address Sanitizer

Signed-off-by: Alex Converse <alex.converse@gmail.com>
(cherry picked from commit e0966eb140)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
(cherry picked from commit ba4b08b789)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
(cherry picked from commit 94aacaf508)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
2011-12-24 16:14:55 +01:00
7739947671 vp6: Fix illegal read.
(cherry picked from commit 2a6eb06254)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
(cherry picked from commit 67a7ed623b)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
(cherry picked from commit 8d68083298)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
2011-12-24 16:14:41 +01:00
8abf1d882e Fix out of bound reads in the QDM2 decoder.
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Signed-off-by: Justin Ruggles <justin.ruggles@gmail.com>
(cherry picked from commit 5a19acb17c)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
(cherry picked from commit 0d93d5c461)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
2011-12-24 16:07:49 +01:00
1a53095406 Check for out of bound writes in the QDM2 decoder.
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Signed-off-by: Justin Ruggles <justin.ruggles@gmail.com>
(cherry picked from commit 291d74a46d)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
(cherry picked from commit a31ccacb1a)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
2011-12-24 16:07:36 +01:00
60eebf5c12 qdm2: check output buffer size before decoding
(cherry picked from commit 7d49f79f1c)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
(cherry picked from commit 7347205351)

Conflicts:

	libavcodec/qdm2.c
(cherry picked from commit cfb9b47a1e)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
2011-12-24 16:06:10 +01:00
30ee6c1995 Fix qdm2 decoder packet handling to match the api
Originally committed as revision 25767 to svn://svn.ffmpeg.org/ffmpeg/trunk
(cherry picked from commit b26c1a8b7e)

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
2011-12-24 16:05:52 +01:00
7 changed files with 149 additions and 41 deletions

View File

@ -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)

17
RELEASE
View File

@ -163,3 +163,20 @@ General notes
This maintenance-only release addresses several security issues that
were brought to our attention.
* 0.5.7 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.

View File

@ -1 +1 @@
0.5.6
0.5.7

View File

@ -1378,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);
@ -1912,7 +1914,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);
@ -1951,7 +1953,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;
}
}
@ -1972,6 +1974,8 @@ static void qdm2_decode (QDM2Context *q, const uint8_t *in, int16_t *out)
out[i] = value;
}
return 0;
}
@ -1980,25 +1984,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 =

View File

@ -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 */
@ -228,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]);
@ -247,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];
@ -265,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;
@ -293,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];
}
@ -304,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;

View File

@ -695,6 +695,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);
@ -705,5 +706,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;
}

View File

@ -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];
}