Prevent out of array writes.
Similar to what Michael Niedermayer did to address the same issue.
Bug-Id: CVE-2014-2263
CC: libav-stable@libav.org
Signed-off-by: Diego Biurrun <diego@biurrun.de>
... | ... |
@@ -226,7 +226,7 @@ static void mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) |
226 | 226 |
{ |
227 | 227 |
MpegTSWrite *ts = s->priv_data; |
228 | 228 |
uint8_t data[SECTION_LENGTH], *q, *desc_length_ptr, *program_info_length_ptr; |
229 |
- int val, stream_type, i; |
|
229 |
+ int val, stream_type, i, err = 0; |
|
230 | 230 |
|
231 | 231 |
q = data; |
232 | 232 |
put16(&q, 0xe000 | service->pcr_pid); |
... | ... |
@@ -244,6 +244,11 @@ static void mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) |
244 | 244 |
AVStream *st = s->streams[i]; |
245 | 245 |
MpegTSWriteStream *ts_st = st->priv_data; |
246 | 246 |
AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0); |
247 |
+ |
|
248 |
+ if (q - data > SECTION_LENGTH - 3 - 2 - 6) { |
|
249 |
+ err = 1; |
|
250 |
+ break; |
|
251 |
+ } |
|
247 | 252 |
switch (st->codec->codec_id) { |
248 | 253 |
case AV_CODEC_ID_MPEG1VIDEO: |
249 | 254 |
case AV_CODEC_ID_MPEG2VIDEO: |
... | ... |
@@ -301,6 +306,10 @@ static void mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) |
301 | 301 |
*len_ptr = 0; |
302 | 302 |
|
303 | 303 |
for (p = lang->value; next && *len_ptr < 255 / 4 * 4; p = next + 1) { |
304 |
+ if (q - data > SECTION_LENGTH - 4) { |
|
305 |
+ err = 1; |
|
306 |
+ break; |
|
307 |
+ } |
|
304 | 308 |
next = strchr(p, ','); |
305 | 309 |
if (strlen(p) != 3 && (!next || next != p + 3)) |
306 | 310 |
continue; /* not a 3-letter code */ |
... | ... |
@@ -335,6 +344,12 @@ static void mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) |
335 | 335 |
*q++ = language[1]; |
336 | 336 |
*q++ = language[2]; |
337 | 337 |
*q++ = 0x10; /* normal subtitles (0x20 = if hearing pb) */ |
338 |
+ |
|
339 |
+ if (q - data > SECTION_LENGTH - 4) { |
|
340 |
+ err = 1; |
|
341 |
+ break; |
|
342 |
+ } |
|
343 |
+ |
|
338 | 344 |
if (st->codec->extradata_size == 4) { |
339 | 345 |
memcpy(q, st->codec->extradata, 4); |
340 | 346 |
q += 4; |
... | ... |
@@ -360,6 +375,13 @@ static void mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) |
360 | 360 |
desc_length_ptr[0] = val >> 8; |
361 | 361 |
desc_length_ptr[1] = val; |
362 | 362 |
} |
363 |
+ |
|
364 |
+ if (err) |
|
365 |
+ av_log(s, AV_LOG_ERROR, |
|
366 |
+ "The PMT section cannot fit stream %d and all following streams.\n" |
|
367 |
+ "Try reducing the number of languages in the audio streams " |
|
368 |
+ "or the total number of streams.\n", i); |
|
369 |
+ |
|
363 | 370 |
mpegts_write_section1(&service->pmt, PMT_TID, service->sid, 0, 0, 0, |
364 | 371 |
data, q - data); |
365 | 372 |
} |