Fix uninitialized reads on malformed ogg files.
[ffmpeg:ffmpeg.git] / libavformat / oggdec.c
1 /*
2  * Ogg bitstream support
3  * Luca Barbato <lu_zero@gentoo.org>
4  * Based on tcvp implementation
5  */
6
7 /*
8     Copyright (C) 2005  Michael Ahlberg, Måns Rullgård
9
10     Permission is hereby granted, free of charge, to any person
11     obtaining a copy of this software and associated documentation
12     files (the "Software"), to deal in the Software without
13     restriction, including without limitation the rights to use, copy,
14     modify, merge, publish, distribute, sublicense, and/or sell copies
15     of the Software, and to permit persons to whom the Software is
16     furnished to do so, subject to the following conditions:
17
18     The above copyright notice and this permission notice shall be
19     included in all copies or substantial portions of the Software.
20
21     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28     DEALINGS IN THE SOFTWARE.
29  */
30
31
32 #include <stdio.h>
33 #include "oggdec.h"
34 #include "avformat.h"
35 #include "internal.h"
36 #include "vorbiscomment.h"
37
38 #define MAX_PAGE_SIZE 65307
39 #define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
40
41 static const struct ogg_codec * const ogg_codecs[] = {
42     &ff_skeleton_codec,
43     &ff_dirac_codec,
44     &ff_speex_codec,
45     &ff_vorbis_codec,
46     &ff_theora_codec,
47     &ff_flac_codec,
48     &ff_celt_codec,
49     &ff_old_dirac_codec,
50     &ff_old_flac_codec,
51     &ff_ogm_video_codec,
52     &ff_ogm_audio_codec,
53     &ff_ogm_text_codec,
54     &ff_ogm_old_codec,
55     NULL
56 };
57
58 //FIXME We could avoid some structure duplication
59 static int ogg_save(AVFormatContext *s)
60 {
61     struct ogg *ogg = s->priv_data;
62     struct ogg_state *ost =
63         av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams));
64     int i;
65     ost->pos = avio_tell (s->pb);
66     ost->curidx = ogg->curidx;
67     ost->next = ogg->state;
68     ost->nstreams = ogg->nstreams;
69     memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
70
71     for (i = 0; i < ogg->nstreams; i++){
72         struct ogg_stream *os = ogg->streams + i;
73         os->buf = av_mallocz (os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
74         memcpy (os->buf, ost->streams[i].buf, os->bufpos);
75     }
76
77     ogg->state = ost;
78
79     return 0;
80 }
81
82 static int ogg_restore(AVFormatContext *s, int discard)
83 {
84     struct ogg *ogg = s->priv_data;
85     AVIOContext *bc = s->pb;
86     struct ogg_state *ost = ogg->state;
87     int i;
88
89     if (!ost)
90         return 0;
91
92     ogg->state = ost->next;
93
94     if (!discard){
95         struct ogg_stream *old_streams = ogg->streams;
96
97         for (i = 0; i < ogg->nstreams; i++)
98             av_free (ogg->streams[i].buf);
99
100         avio_seek (bc, ost->pos, SEEK_SET);
101         ogg->curidx = ost->curidx;
102         ogg->nstreams = ost->nstreams;
103         ogg->streams = av_realloc (ogg->streams,
104                                    ogg->nstreams * sizeof (*ogg->streams));
105
106         if (ogg->streams) {
107             memcpy(ogg->streams, ost->streams,
108                    ost->nstreams * sizeof(*ogg->streams));
109         } else {
110             av_free(old_streams);
111             ogg->nstreams = 0;
112         }
113     }
114
115     av_free (ost);
116
117     return 0;
118 }
119
120 static int ogg_reset(struct ogg *ogg)
121 {
122     int i;
123
124     for (i = 0; i < ogg->nstreams; i++){
125         struct ogg_stream *os = ogg->streams + i;
126         os->bufpos = 0;
127         os->pstart = 0;
128         os->psize = 0;
129         os->granule = -1;
130         os->lastpts = AV_NOPTS_VALUE;
131         os->lastdts = AV_NOPTS_VALUE;
132         os->sync_pos = -1;
133         os->page_pos = 0;
134         os->nsegs = 0;
135         os->segp = 0;
136         os->incomplete = 0;
137     }
138
139     ogg->curidx = -1;
140
141     return 0;
142 }
143
144 static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
145 {
146     int i;
147
148     for (i = 0; ogg_codecs[i]; i++)
149         if (size >= ogg_codecs[i]->magicsize &&
150             !memcmp (buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
151             return ogg_codecs[i];
152
153     return NULL;
154 }
155
156 static int ogg_new_stream(AVFormatContext *s, uint32_t serial, int new_avstream)
157 {
158
159     struct ogg *ogg = s->priv_data;
160     int idx = ogg->nstreams++;
161     AVStream *st;
162     struct ogg_stream *os;
163
164     ogg->streams = av_realloc (ogg->streams,
165                                ogg->nstreams * sizeof (*ogg->streams));
166     memset (ogg->streams + idx, 0, sizeof (*ogg->streams));
167     os = ogg->streams + idx;
168     os->serial = serial;
169     os->bufsize = DECODER_BUFFER_SIZE;
170     os->buf = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
171     os->header = -1;
172
173     if (new_avstream) {
174         st = avformat_new_stream(s, NULL);
175         if (!st)
176             return AVERROR(ENOMEM);
177
178         st->id = idx;
179         avpriv_set_pts_info(st, 64, 1, 1000000);
180     }
181
182     return idx;
183 }
184
185 static int ogg_new_buf(struct ogg *ogg, int idx)
186 {
187     struct ogg_stream *os = ogg->streams + idx;
188     uint8_t *nb = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
189     int size = os->bufpos - os->pstart;
190     if(os->buf){
191         memcpy(nb, os->buf + os->pstart, size);
192         av_free(os->buf);
193     }
194     os->buf = nb;
195     os->bufpos = size;
196     os->pstart = 0;
197
198     return 0;
199 }
200
201 static int ogg_read_page(AVFormatContext *s, int *str)
202 {
203     AVIOContext *bc = s->pb;
204     struct ogg *ogg = s->priv_data;
205     struct ogg_stream *os;
206     int ret, i = 0;
207     int flags, nsegs;
208     uint64_t gp;
209     uint32_t serial;
210     int size, idx;
211     uint8_t sync[4];
212     int sp = 0;
213
214     ret = avio_read(bc, sync, 4);
215     if (ret < 4)
216         return ret < 0 ? ret : AVERROR_EOF;
217
218     do{
219         int c;
220
221         if (sync[sp & 3] == 'O' &&
222             sync[(sp + 1) & 3] == 'g' &&
223             sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
224             break;
225
226         c = avio_r8(bc);
227         if (bc->eof_reached)
228             return AVERROR_EOF;
229         sync[sp++ & 3] = c;
230     }while (i++ < MAX_PAGE_SIZE);
231
232     if (i >= MAX_PAGE_SIZE){
233         av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
234         return AVERROR_INVALIDDATA;
235     }
236
237     if (avio_r8(bc) != 0)      /* version */
238         return AVERROR_INVALIDDATA;
239
240     flags = avio_r8(bc);
241     gp = avio_rl64 (bc);
242     serial = avio_rl32 (bc);
243     avio_skip(bc, 8); /* seq, crc */
244     nsegs = avio_r8(bc);
245
246     idx = ogg_find_stream (ogg, serial);
247     if (idx < 0){
248         if (ogg->headers) {
249             int n;
250
251             for (n = 0; n < ogg->nstreams; n++) {
252                 av_freep(&ogg->streams[n].buf);
253                 if (!ogg->state || ogg->state->streams[n].private != ogg->streams[n].private)
254                     av_freep(&ogg->streams[n].private);
255             }
256             ogg->curidx   = -1;
257             ogg->nstreams = 0;
258             idx = ogg_new_stream(s, serial, 0);
259         } else {
260             idx = ogg_new_stream(s, serial, 1);
261         }
262         if (idx < 0)
263             return idx;
264     }
265
266     os = ogg->streams + idx;
267     os->page_pos = avio_tell(bc) - 27;
268
269     if(os->psize > 0)
270         ogg_new_buf(ogg, idx);
271
272     ret = avio_read(bc, os->segments, nsegs);
273     if (ret < nsegs)
274         return ret < 0 ? ret : AVERROR_EOF;
275
276     os->nsegs = nsegs;
277     os->segp = 0;
278
279     size = 0;
280     for (i = 0; i < nsegs; i++)
281         size += os->segments[i];
282
283     if (flags & OGG_FLAG_CONT || os->incomplete){
284         if (!os->psize){
285             while (os->segp < os->nsegs){
286                 int seg = os->segments[os->segp++];
287                 os->pstart += seg;
288                 if (seg < 255)
289                     break;
290             }
291             os->sync_pos = os->page_pos;
292         }
293     }else{
294         os->psize = 0;
295         os->sync_pos = os->page_pos;
296     }
297
298     if (os->bufsize - os->bufpos < size){
299         uint8_t *nb = av_malloc ((os->bufsize *= 2) + FF_INPUT_BUFFER_PADDING_SIZE);
300         memcpy (nb, os->buf, os->bufpos);
301         av_free (os->buf);
302         os->buf = nb;
303     }
304
305     ret = avio_read(bc, os->buf + os->bufpos, size);
306     if (ret < size)
307         return ret < 0 ? ret : AVERROR_EOF;
308
309     os->bufpos += size;
310     os->granule = gp;
311     os->flags = flags;
312
313     memset(os->buf + os->bufpos, 0, FF_INPUT_BUFFER_PADDING_SIZE);
314     if (str)
315         *str = idx;
316
317     return 0;
318 }
319
320 static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize,
321                       int64_t *fpos)
322 {
323     struct ogg *ogg = s->priv_data;
324     int idx, i, ret;
325     struct ogg_stream *os;
326     int complete = 0;
327     int segp = 0, psize = 0;
328
329     av_dlog(s, "ogg_packet: curidx=%i\n", ogg->curidx);
330
331     do{
332         idx = ogg->curidx;
333
334         while (idx < 0){
335             ret = ogg_read_page(s, &idx);
336             if (ret < 0)
337                 return ret;
338         }
339
340         os = ogg->streams + idx;
341
342         av_dlog(s, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
343                 idx, os->pstart, os->psize, os->segp, os->nsegs);
344
345         if (!os->codec){
346             if (os->header < 0){
347                 os->codec = ogg_find_codec (os->buf, os->bufpos);
348                 if (!os->codec){
349                     av_log(s, AV_LOG_WARNING, "Codec not found\n");
350                     os->header = 0;
351                     return 0;
352                 }
353             }else{
354                 return 0;
355             }
356         }
357
358         segp = os->segp;
359         psize = os->psize;
360
361         while (os->segp < os->nsegs){
362             int ss = os->segments[os->segp++];
363             os->psize += ss;
364             if (ss < 255){
365                 complete = 1;
366                 break;
367             }
368         }
369
370         if (!complete && os->segp == os->nsegs){
371             ogg->curidx = -1;
372             os->incomplete = 1;
373         }
374     }while (!complete);
375
376     av_dlog(s, "ogg_packet: idx %i, frame size %i, start %i\n",
377             idx, os->psize, os->pstart);
378
379     if (os->granule == -1)
380         av_log(s, AV_LOG_WARNING, "Page at %"PRId64" is missing granule\n", os->page_pos);
381
382     ogg->curidx = idx;
383     os->incomplete = 0;
384
385     if (os->header) {
386         os->header = os->codec->header (s, idx);
387         if (!os->header){
388             os->segp = segp;
389             os->psize = psize;
390
391             // We have reached the first non-header packet in this stream.
392             // Unfortunately more header packets may still follow for others,
393             // but if we continue with header parsing we may lose data packets.
394             ogg->headers = 1;
395
396             // Update the header state for all streams and
397             // compute the data_offset.
398             if (!s->data_offset)
399                 s->data_offset = os->sync_pos;
400             for (i = 0; i < ogg->nstreams; i++) {
401                 struct ogg_stream *cur_os = ogg->streams + i;
402
403                 // if we have a partial non-header packet, its start is
404                 // obviously at or after the data start
405                 if (cur_os->incomplete)
406                     s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
407             }
408         }else{
409             os->pstart += os->psize;
410             os->psize = 0;
411         }
412     } else {
413         os->pflags = 0;
414         os->pduration = 0;
415         if (os->codec && os->codec->packet)
416             os->codec->packet (s, idx);
417         if (str)
418             *str = idx;
419         if (dstart)
420             *dstart = os->pstart;
421         if (dsize)
422             *dsize = os->psize;
423         if (fpos)
424             *fpos = os->sync_pos;
425         os->pstart += os->psize;
426         os->psize = 0;
427         os->sync_pos = os->page_pos;
428     }
429
430     // determine whether there are more complete packets in this page
431     // if not, the page's granule will apply to this packet
432     os->page_end = 1;
433     for (i = os->segp; i < os->nsegs; i++)
434         if (os->segments[i] < 255) {
435             os->page_end = 0;
436             break;
437         }
438
439     if (os->segp == os->nsegs)
440         ogg->curidx = -1;
441
442     return 0;
443 }
444
445 static int ogg_get_headers(AVFormatContext *s)
446 {
447     struct ogg *ogg = s->priv_data;
448     int ret;
449
450     do{
451         ret = ogg_packet(s, NULL, NULL, NULL, NULL);
452         if (ret < 0)
453             return ret;
454     }while (!ogg->headers);
455
456     av_dlog(s, "found headers\n");
457
458     return 0;
459 }
460
461 static int ogg_get_length(AVFormatContext *s)
462 {
463     struct ogg *ogg = s->priv_data;
464     int i;
465     int64_t size, end;
466
467     if(!s->pb->seekable)
468         return 0;
469
470 // already set
471     if (s->duration != AV_NOPTS_VALUE)
472         return 0;
473
474     size = avio_size(s->pb);
475     if(size < 0)
476         return 0;
477     end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
478
479     ogg_save (s);
480     avio_seek (s->pb, end, SEEK_SET);
481
482     while (!ogg_read_page (s, &i)){
483         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
484             ogg->streams[i].codec) {
485             s->streams[i]->duration =
486                 ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
487             if (s->streams[i]->start_time != AV_NOPTS_VALUE)
488                 s->streams[i]->duration -= s->streams[i]->start_time;
489         }
490     }
491
492     ogg_restore (s, 0);
493
494     return 0;
495 }
496
497 static int ogg_read_header(AVFormatContext *s)
498 {
499     struct ogg *ogg = s->priv_data;
500     int ret, i;
501     ogg->curidx = -1;
502     //linear headers seek from start
503     ret = ogg_get_headers(s);
504     if (ret < 0)
505         return ret;
506
507     for (i = 0; i < ogg->nstreams; i++)
508         if (ogg->streams[i].header < 0)
509             ogg->streams[i].codec = NULL;
510
511     //linear granulepos seek from end
512     ogg_get_length (s);
513
514     //fill the extradata in the per codec callbacks
515     return 0;
516 }
517
518 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
519 {
520     struct ogg *ogg = s->priv_data;
521     struct ogg_stream *os = ogg->streams + idx;
522     int64_t pts = AV_NOPTS_VALUE;
523
524     if (dts)
525         *dts = AV_NOPTS_VALUE;
526
527     if (os->lastpts != AV_NOPTS_VALUE) {
528         pts = os->lastpts;
529         os->lastpts = AV_NOPTS_VALUE;
530     }
531     if (os->lastdts != AV_NOPTS_VALUE) {
532         if (dts)
533             *dts = os->lastdts;
534         os->lastdts = AV_NOPTS_VALUE;
535     }
536     if (os->page_end) {
537         if (os->granule != -1LL) {
538             if (os->codec && os->codec->granule_is_start)
539                 pts = ogg_gptopts(s, idx, os->granule, dts);
540             else
541                 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
542             os->granule = -1LL;
543         }
544     }
545     return pts;
546 }
547
548 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
549 {
550     struct ogg *ogg;
551     struct ogg_stream *os;
552     int idx = -1, ret;
553     int pstart, psize;
554     int64_t fpos, pts, dts;
555
556     //Get an ogg packet
557 retry:
558     do{
559         ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
560         if (ret < 0)
561             return ret;
562     }while (idx < 0 || !s->streams[idx]);
563
564     ogg = s->priv_data;
565     os = ogg->streams + idx;
566
567     // pflags might not be set until after this
568     pts = ogg_calc_pts(s, idx, &dts);
569
570     if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
571         goto retry;
572     os->keyframe_seek = 0;
573
574     //Alloc a pkt
575     ret = av_new_packet(pkt, psize);
576     if (ret < 0)
577         return ret;
578     pkt->stream_index = idx;
579     memcpy (pkt->data, os->buf + pstart, psize);
580
581     pkt->pts = pts;
582     pkt->dts = dts;
583     pkt->flags = os->pflags;
584     pkt->duration = os->pduration;
585     pkt->pos = fpos;
586
587     return psize;
588 }
589
590 static int ogg_read_close(AVFormatContext *s)
591 {
592     struct ogg *ogg = s->priv_data;
593     int i;
594
595     for (i = 0; i < ogg->nstreams; i++){
596         av_free (ogg->streams[i].buf);
597         av_free (ogg->streams[i].private);
598     }
599     av_free (ogg->streams);
600     return 0;
601 }
602
603 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
604                                   int64_t *pos_arg, int64_t pos_limit)
605 {
606     struct ogg *ogg = s->priv_data;
607     AVIOContext *bc = s->pb;
608     int64_t pts = AV_NOPTS_VALUE;
609     int i = -1;
610     avio_seek(bc, *pos_arg, SEEK_SET);
611     ogg_reset(ogg);
612
613     while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
614         if (i == stream_index) {
615             struct ogg_stream *os = ogg->streams + stream_index;
616             pts = ogg_calc_pts(s, i, NULL);
617             if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
618                 pts = AV_NOPTS_VALUE;
619         }
620         if (pts != AV_NOPTS_VALUE)
621             break;
622     }
623     ogg_reset(ogg);
624     return pts;
625 }
626
627 static int ogg_read_seek(AVFormatContext *s, int stream_index,
628                          int64_t timestamp, int flags)
629 {
630     struct ogg *ogg = s->priv_data;
631     struct ogg_stream *os = ogg->streams + stream_index;
632     int ret;
633
634     // Try seeking to a keyframe first. If this fails (very possible),
635     // av_seek_frame will fall back to ignoring keyframes
636     if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
637         && !(flags & AVSEEK_FLAG_ANY))
638         os->keyframe_seek = 1;
639
640     ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
641     os = ogg->streams + stream_index;
642     if (ret < 0)
643         os->keyframe_seek = 0;
644     return ret;
645 }
646
647 static int ogg_probe(AVProbeData *p)
648 {
649     if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
650         return AVPROBE_SCORE_MAX;
651     return 0;
652 }
653
654 AVInputFormat ff_ogg_demuxer = {
655     .name           = "ogg",
656     .long_name      = NULL_IF_CONFIG_SMALL("Ogg"),
657     .priv_data_size = sizeof(struct ogg),
658     .read_probe     = ogg_probe,
659     .read_header    = ogg_read_header,
660     .read_packet    = ogg_read_packet,
661     .read_close     = ogg_read_close,
662     .read_seek      = ogg_read_seek,
663     .read_timestamp = ogg_read_timestamp,
664     .extensions     = "ogg",
665     .flags          = AVFMT_GENERIC_INDEX,
666 };