-int32_t mp4ff_total_tracks(const mp4ff_t * f)
-{
- return f->total_tracks;
-}
-
-static int32_t mp4ff_read_data(mp4ff_t * f, void *data, uint32_t size)
-{
- int32_t result = 1;
-
- result = f->stream->read(f->stream->user_data, data, size);
-
- if (result < size)
- f->stream->read_error++;
-
- f->current_position += size;
-
- return result;
-}
-
-/* parse atom header size */
-static int32_t mp4ff_atom_get_size(const int8_t * data)
-{
- uint32_t result;
- uint32_t a, b, c, d;
-
- a = (uint8_t) data[0];
- b = (uint8_t) data[1];
- c = (uint8_t) data[2];
- d = (uint8_t) data[3];
-
- result = (a << 24) | (b << 16) | (c << 8) | d;
- return (int32_t) result;
-}
-
-static uint64_t mp4ff_read_int64(mp4ff_t * f)
-{
- uint8_t data[8];
- uint64_t result = 0;
- int8_t i;
-
- mp4ff_read_data(f, data, 8);
-
- for (i = 0; i < 8; i++) {
- result |= ((uint64_t) data[i]) << ((7 - i) * 8);
- }
-
- return result;
-}
-
-/* comnapre 2 atom names, returns 1 for equal, 0 for unequal */
-static int32_t mp4ff_atom_compare(const int8_t a1, const int8_t b1,
- const int8_t c1, const int8_t d1,
- const int8_t a2, const int8_t b2,
- const int8_t c2, const int8_t d2)
-{
- if (a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2)
- return 1;
- else
- return 0;
-}
-
-#define TRACK_AUDIO 1
-#define TRACK_VIDEO 2
-#define TRACK_SYSTEM 3
-#define TRACK_UNKNOWN 0
-
-/* atoms with subatoms */
-#define ATOM_MOOV 1
-#define ATOM_TRAK 2
-#define ATOM_EDTS 3
-#define ATOM_MDIA 4
-#define ATOM_MINF 5
-#define ATOM_STBL 6
-#define ATOM_UDTA 7
-#define ATOM_ILST 8 /* iTunes Metadata list */
-#define ATOM_TITLE 9
-#define ATOM_ARTIST 10
-#define ATOM_WRITER 11
-#define ATOM_ALBUM 12
-#define ATOM_DATE 13
-#define ATOM_TOOL 14
-#define ATOM_COMMENT 15
-#define ATOM_GENRE1 16
-#define ATOM_TRACK 17
-#define ATOM_DISC 18
-#define ATOM_COMPILATION 19
-#define ATOM_GENRE2 20
-#define ATOM_TEMPO 21
-#define ATOM_COVER 22
-#define ATOM_DRMS 23
-#define ATOM_SINF 24
-#define ATOM_SCHI 25
-
-#define SUBATOMIC 128
-
-/* atoms without subatoms */
-#define ATOM_FTYP 129
-#define ATOM_MDAT 130
-#define ATOM_MVHD 131
-#define ATOM_TKHD 132
-#define ATOM_TREF 133
-#define ATOM_MDHD 134
-#define ATOM_VMHD 135
-#define ATOM_SMHD 136
-#define ATOM_HMHD 137
-#define ATOM_STSD 138
-#define ATOM_STTS 139
-#define ATOM_STSZ 140
-#define ATOM_STZ2 141
-#define ATOM_STCO 142
-#define ATOM_STSC 143
-#define ATOM_MP4A 144
-#define ATOM_MP4V 145
-#define ATOM_MP4S 146
-#define ATOM_ESDS 147
-#define ATOM_META 148 /* iTunes Metadata box */
-#define ATOM_NAME 149 /* iTunes Metadata name box */
-#define ATOM_DATA 150 /* iTunes Metadata data box */
-#define ATOM_CTTS 151
-#define ATOM_FRMA 152
-#define ATOM_IVIV 153
-#define ATOM_PRIV 154
-#define ATOM_USER 155
-#define ATOM_KEY 156
-#define ATOM_ALBUM_ARTIST 157
-#define ATOM_CONTENTGROUP 158
-#define ATOM_LYRICS 159
-#define ATOM_DESCRIPTION 160
-#define ATOM_NETWORK 161
-#define ATOM_SHOW 162
-#define ATOM_EPISODENAME 163
-#define ATOM_SORTTITLE 164
-#define ATOM_SORTALBUM 165
-#define ATOM_SORTARTIST 166
-#define ATOM_SORTALBUMARTIST 167
-#define ATOM_SORTWRITER 168
-#define ATOM_SORTSHOW 169
-#define ATOM_SEASON 170
-#define ATOM_EPISODE 171
-#define ATOM_PODCAST 172
-
-#define ATOM_UNKNOWN 255
-#define ATOM_FREE ATOM_UNKNOWN
-#define ATOM_SKIP ATOM_UNKNOWN
-
-#define COPYRIGHT_SYMBOL ((int8_t)0xA9)
-
-static uint8_t mp4ff_atom_name_to_type(const int8_t a, const int8_t b,
- const int8_t c, const int8_t d)
-{
- if (a == 'm') {
- if (mp4ff_atom_compare(a, b, c, d, 'm', 'o', 'o', 'v'))
- return ATOM_MOOV;
- else if (mp4ff_atom_compare(a, b, c, d, 'm', 'i', 'n', 'f'))
- return ATOM_MINF;
- else if (mp4ff_atom_compare(a, b, c, d, 'm', 'd', 'i', 'a'))
- return ATOM_MDIA;
- else if (mp4ff_atom_compare(a, b, c, d, 'm', 'd', 'a', 't'))
- return ATOM_MDAT;
- else if (mp4ff_atom_compare(a, b, c, d, 'm', 'd', 'h', 'd'))
- return ATOM_MDHD;
- else if (mp4ff_atom_compare(a, b, c, d, 'm', 'v', 'h', 'd'))
- return ATOM_MVHD;
- else if (mp4ff_atom_compare(a, b, c, d, 'm', 'p', '4', 'a'))
- return ATOM_MP4A;
- else if (mp4ff_atom_compare(a, b, c, d, 'm', 'p', '4', 'v'))
- return ATOM_MP4V;
- else if (mp4ff_atom_compare(a, b, c, d, 'm', 'p', '4', 's'))
- return ATOM_MP4S;
- else if (mp4ff_atom_compare(a, b, c, d, 'm', 'e', 't', 'a'))
- return ATOM_META;
- } else if (a == 't') {
- if (mp4ff_atom_compare(a, b, c, d, 't', 'r', 'a', 'k'))
- return ATOM_TRAK;
- else if (mp4ff_atom_compare(a, b, c, d, 't', 'k', 'h', 'd'))
- return ATOM_TKHD;
- else if (mp4ff_atom_compare(a, b, c, d, 't', 'r', 'e', 'f'))
- return ATOM_TREF;
- else if (mp4ff_atom_compare(a, b, c, d, 't', 'r', 'k', 'n'))
- return ATOM_TRACK;
- else if (mp4ff_atom_compare(a, b, c, d, 't', 'm', 'p', 'o'))
- return ATOM_TEMPO;
- else if (mp4ff_atom_compare(a, b, c, d, 't', 'v', 'n', 'n'))
- return ATOM_NETWORK;
- else if (mp4ff_atom_compare(a, b, c, d, 't', 'v', 's', 'h'))
- return ATOM_SHOW;
- else if (mp4ff_atom_compare(a, b, c, d, 't', 'v', 'e', 'n'))
- return ATOM_EPISODENAME;
- else if (mp4ff_atom_compare(a, b, c, d, 't', 'v', 's', 'n'))
- return ATOM_SEASON;
- else if (mp4ff_atom_compare(a, b, c, d, 't', 'v', 'e', 's'))
- return ATOM_EPISODE;
- } else if (a == 's') {
- if (mp4ff_atom_compare(a, b, c, d, 's', 't', 'b', 'l'))
- return ATOM_STBL;
- else if (mp4ff_atom_compare(a, b, c, d, 's', 'm', 'h', 'd'))
- return ATOM_SMHD;
- else if (mp4ff_atom_compare(a, b, c, d, 's', 't', 's', 'd'))
- return ATOM_STSD;
- else if (mp4ff_atom_compare(a, b, c, d, 's', 't', 't', 's'))
- return ATOM_STTS;
- else if (mp4ff_atom_compare(a, b, c, d, 's', 't', 'c', 'o'))
- return ATOM_STCO;
- else if (mp4ff_atom_compare(a, b, c, d, 's', 't', 's', 'c'))
- return ATOM_STSC;
- else if (mp4ff_atom_compare(a, b, c, d, 's', 't', 's', 'z'))
- return ATOM_STSZ;
- else if (mp4ff_atom_compare(a, b, c, d, 's', 't', 'z', '2'))
- return ATOM_STZ2;
- else if (mp4ff_atom_compare(a, b, c, d, 's', 'k', 'i', 'p'))
- return ATOM_SKIP;
- else if (mp4ff_atom_compare(a, b, c, d, 's', 'i', 'n', 'f'))
- return ATOM_SINF;
- else if (mp4ff_atom_compare(a, b, c, d, 's', 'c', 'h', 'i'))
- return ATOM_SCHI;
- else if (mp4ff_atom_compare(a, b, c, d, 's', 'o', 'n', 'm'))
- return ATOM_SORTTITLE;
- else if (mp4ff_atom_compare(a, b, c, d, 's', 'o', 'a', 'l'))
- return ATOM_SORTALBUM;
- else if (mp4ff_atom_compare(a, b, c, d, 's', 'o', 'a', 'r'))
- return ATOM_SORTARTIST;
- else if (mp4ff_atom_compare(a, b, c, d, 's', 'o', 'a', 'a'))
- return ATOM_SORTALBUMARTIST;
- else if (mp4ff_atom_compare(a, b, c, d, 's', 'o', 'c', 'o'))
- return ATOM_SORTWRITER;
- else if (mp4ff_atom_compare(a, b, c, d, 's', 'o', 's', 'n'))
- return ATOM_SORTSHOW;
- } else if (a == COPYRIGHT_SYMBOL) {
- if (mp4ff_atom_compare
- (a, b, c, d, COPYRIGHT_SYMBOL, 'n', 'a', 'm'))
- return ATOM_TITLE;
- else if (mp4ff_atom_compare
- (a, b, c, d, COPYRIGHT_SYMBOL, 'A', 'R', 'T'))
- return ATOM_ARTIST;
- else if (mp4ff_atom_compare
- (a, b, c, d, COPYRIGHT_SYMBOL, 'w', 'r', 't'))
- return ATOM_WRITER;
- else if (mp4ff_atom_compare
- (a, b, c, d, COPYRIGHT_SYMBOL, 'a', 'l', 'b'))
- return ATOM_ALBUM;
- else if (mp4ff_atom_compare
- (a, b, c, d, COPYRIGHT_SYMBOL, 'd', 'a', 'y'))
- return ATOM_DATE;
- else if (mp4ff_atom_compare
- (a, b, c, d, COPYRIGHT_SYMBOL, 't', 'o', 'o'))
- return ATOM_TOOL;
- else if (mp4ff_atom_compare
- (a, b, c, d, COPYRIGHT_SYMBOL, 'c', 'm', 't'))
- return ATOM_COMMENT;
- else if (mp4ff_atom_compare
- (a, b, c, d, COPYRIGHT_SYMBOL, 'g', 'e', 'n'))
- return ATOM_GENRE1;
- else if (mp4ff_atom_compare
- (a, b, c, d, COPYRIGHT_SYMBOL, 'g', 'r', 'p'))
- return ATOM_CONTENTGROUP;
- else if (mp4ff_atom_compare
- (a, b, c, d, COPYRIGHT_SYMBOL, 'l', 'y', 'r'))
- return ATOM_LYRICS;
- }
-
- if (mp4ff_atom_compare(a, b, c, d, 'e', 'd', 't', 's'))
- return ATOM_EDTS;
- else if (mp4ff_atom_compare(a, b, c, d, 'e', 's', 'd', 's'))
- return ATOM_ESDS;
- else if (mp4ff_atom_compare(a, b, c, d, 'f', 't', 'y', 'p'))
- return ATOM_FTYP;
- else if (mp4ff_atom_compare(a, b, c, d, 'f', 'r', 'e', 'e'))
- return ATOM_FREE;
- else if (mp4ff_atom_compare(a, b, c, d, 'h', 'm', 'h', 'd'))
- return ATOM_HMHD;
- else if (mp4ff_atom_compare(a, b, c, d, 'v', 'm', 'h', 'd'))
- return ATOM_VMHD;
- else if (mp4ff_atom_compare(a, b, c, d, 'u', 'd', 't', 'a'))
- return ATOM_UDTA;
- else if (mp4ff_atom_compare(a, b, c, d, 'i', 'l', 's', 't'))
- return ATOM_ILST;
- else if (mp4ff_atom_compare(a, b, c, d, 'n', 'a', 'm', 'e'))
- return ATOM_NAME;
- else if (mp4ff_atom_compare(a, b, c, d, 'd', 'a', 't', 'a'))
- return ATOM_DATA;
- else if (mp4ff_atom_compare(a, b, c, d, 'd', 'i', 's', 'k'))
- return ATOM_DISC;
- else if (mp4ff_atom_compare(a, b, c, d, 'g', 'n', 'r', 'e'))
- return ATOM_GENRE2;
- else if (mp4ff_atom_compare(a, b, c, d, 'c', 'o', 'v', 'r'))
- return ATOM_COVER;
- else if (mp4ff_atom_compare(a, b, c, d, 'c', 'p', 'i', 'l'))
- return ATOM_COMPILATION;
- else if (mp4ff_atom_compare(a, b, c, d, 'c', 't', 't', 's'))
- return ATOM_CTTS;
- else if (mp4ff_atom_compare(a, b, c, d, 'd', 'r', 'm', 's'))
- return ATOM_DRMS;
- else if (mp4ff_atom_compare(a, b, c, d, 'f', 'r', 'm', 'a'))
- return ATOM_FRMA;
- else if (mp4ff_atom_compare(a, b, c, d, 'p', 'r', 'i', 'v'))
- return ATOM_PRIV;
- else if (mp4ff_atom_compare(a, b, c, d, 'i', 'v', 'i', 'v'))
- return ATOM_IVIV;
- else if (mp4ff_atom_compare(a, b, c, d, 'u', 's', 'e', 'r'))
- return ATOM_USER;
- else if (mp4ff_atom_compare(a, b, c, d, 'k', 'e', 'y', ' '))
- return ATOM_KEY;
- else if (mp4ff_atom_compare(a, b, c, d, 'a', 'A', 'R', 'T'))
- return ATOM_ALBUM_ARTIST;
- else if (mp4ff_atom_compare(a, b, c, d, 'd', 'e', 's', 'c'))
- return ATOM_DESCRIPTION;
- else if (mp4ff_atom_compare(a, b, c, d, 'p', 'c', 's', 't'))
- return ATOM_PODCAST;
- else
- return ATOM_UNKNOWN;
-}
-
-/* read atom header, return atom size, atom size is with header included */
-static uint64_t mp4ff_atom_read_header(mp4ff_t * f, uint8_t * atom_type,
- uint8_t * header_size)
-{
- uint64_t size;
- int32_t ret;
- int8_t atom_header[8];
-
- ret = mp4ff_read_data(f, atom_header, 8);
- if (ret != 8)
- return 0;
-
- size = mp4ff_atom_get_size(atom_header);
- *header_size = 8;
-
- /* check for 64 bit atom size */
- if (size == 1) {
- *header_size = 16;
- size = mp4ff_read_int64(f);
- }
- *atom_type = mp4ff_atom_name_to_type(atom_header[4], atom_header[5],
- atom_header[6], atom_header[7]);
- return size;
-}
-
-static int64_t mp4ff_position(const mp4ff_t * f)
-{
- return f->current_position;
-}
-
-static int need_parse_when_meta_only(uint8_t atom_type)
-{
- switch (atom_type) {
- case ATOM_EDTS:
- case ATOM_DRMS:
- case ATOM_SINF:
- case ATOM_SCHI:
- case ATOM_STTS:
- case ATOM_STSZ:
- case ATOM_STZ2:
- case ATOM_STCO:
- case ATOM_STSC:
- case ATOM_FRMA:
- case ATOM_IVIV:
- case ATOM_PRIV:
- return 0;
- default:
- return 1;
- }
-}
-
-static int32_t mp4ff_set_position(mp4ff_t * f, const int64_t position)
-{
- f->stream->seek(f->stream->user_data, position);
- f->current_position = position;
-
- return 0;
-}
-
-static void mp4ff_track_add(mp4ff_t * f)
-{
- f->total_tracks++;
-
- if (f->total_tracks > MAX_TRACKS) {
- f->total_tracks = 0;
- f->error++;
- return;
- }
-
- f->track[f->total_tracks - 1] = malloc(sizeof (mp4ff_track_t));
-
- memset(f->track[f->total_tracks - 1], 0, sizeof (mp4ff_track_t));
-}
-
-static uint8_t mp4ff_read_char(mp4ff_t * f)
-{
- uint8_t output;
- mp4ff_read_data(f, &output, 1);
- return output;
-}
-
-static uint32_t mp4ff_read_int24(mp4ff_t * f)
-{
- uint32_t result;
- uint32_t a, b, c;
- int8_t data[4];
-
- mp4ff_read_data(f, data, 3);
- a = (uint8_t) data[0];
- b = (uint8_t) data[1];
- c = (uint8_t) data[2];
-
- result = (a << 16) | (b << 8) | c;
- return (uint32_t) result;
-}
-
-static uint32_t mp4ff_read_int32(mp4ff_t * f)
-{
- uint32_t result;
- uint32_t a, b, c, d;
- int8_t data[4];
-
- mp4ff_read_data(f, data, 4);
- a = (uint8_t) data[0];
- b = (uint8_t) data[1];
- c = (uint8_t) data[2];
- d = (uint8_t) data[3];
-
- result = (a << 24) | (b << 16) | (c << 8) | d;
- return (uint32_t) result;
-}
-
-static int32_t mp4ff_read_stsz(mp4ff_t * f)
-{
- if (f->total_tracks == 0)
- return f->error++;
-
- mp4ff_read_char(f); /* version */
- mp4ff_read_int24(f); /* flags */
- f->track[f->total_tracks - 1]->stsz_sample_size = mp4ff_read_int32(f);
- f->track[f->total_tracks - 1]->stsz_sample_count = mp4ff_read_int32(f);
-
- if (f->track[f->total_tracks - 1]->stsz_sample_size == 0) {
- int32_t i;
- f->track[f->total_tracks - 1]->stsz_table =
- (int32_t *)malloc(f->track[f->total_tracks - 1]->stsz_sample_count
- * sizeof (int32_t));
-
- if (!f->track[f->total_tracks - 1]->stsz_table)
- return f->error++;
-
- for (i = 0; i < f->track[f->total_tracks - 1]->stsz_sample_count
- && !f->stream->read_error; i++) {
- f->track[f->total_tracks - 1]->stsz_table[i] = mp4ff_read_int32(f);
- }
- }
- return 0;
-}
-
-static int32_t mp4ff_read_stts(mp4ff_t * f)
-{
- int32_t i;
- mp4ff_track_t *p_track;
-
- /* CVE-2017-9223 */
- if (f->total_tracks == 0)
- return f->error++;
-
- p_track = f->track[f->total_tracks - 1];
-
- if (p_track->stts_entry_count)
- return 0;
-
- mp4ff_read_char(f); /* version */
- mp4ff_read_int24(f); /* flags */
- p_track->stts_entry_count = mp4ff_read_int32(f);
-
- p_track->stts_sample_count = (int32_t *)malloc(p_track->stts_entry_count
- * sizeof (int32_t));
- p_track->stts_sample_delta = (int32_t *)malloc(p_track->stts_entry_count
- * sizeof (int32_t));
-
- if (p_track->stts_sample_count == 0 || p_track->stts_sample_delta == 0) {
- if (p_track->stts_sample_count) {
- free(p_track->stts_sample_count);
- p_track->stts_sample_count = 0;
- }
- if (p_track->stts_sample_delta) {
- free(p_track->stts_sample_delta);
- p_track->stts_sample_delta = 0;
- }
- p_track->stts_entry_count = 0;
- return 0;
- } else {
- for (i = 0; i < f->track[f->total_tracks - 1]->stts_entry_count && !f->stream->read_error; i++) { /* CVE-2017-9254 */
- p_track->stts_sample_count[i] = mp4ff_read_int32(f);
- p_track->stts_sample_delta[i] = mp4ff_read_int32(f);
- }
- return 1;
- }
-}
-
-static int32_t mp4ff_read_ctts(mp4ff_t * f)
-{
- int32_t i;
- mp4ff_track_t *p_track;
-
- if (f->total_tracks == 0)
- return f->error++;
-
- p_track = f->track[f->total_tracks - 1];
- if (p_track->ctts_entry_count)
- return 0;
-
- mp4ff_read_char(f); /* version */
- mp4ff_read_int24(f); /* flags */
- p_track->ctts_entry_count = mp4ff_read_int32(f);
-
- p_track->ctts_sample_count = (int32_t *)malloc(p_track->ctts_entry_count
- * sizeof (int32_t));
- p_track->ctts_sample_offset = (int32_t *)malloc(p_track->ctts_entry_count
- * sizeof (int32_t));
-
- if (p_track->ctts_sample_count == 0 || p_track->ctts_sample_offset == 0) {
- if (p_track->ctts_sample_count) {
- free(p_track->ctts_sample_count);
- p_track->ctts_sample_count = 0;
- }
- if (p_track->ctts_sample_offset) {
- free(p_track->ctts_sample_offset);
- p_track->ctts_sample_offset = 0;
- }
- p_track->ctts_entry_count = 0;
- return 0;
- } else {
- for (i = 0; i < f->track[f->total_tracks - 1]->ctts_entry_count && !f->stream->read_error; i++) { /* CVE-2017-9257 */
- p_track->ctts_sample_count[i] = mp4ff_read_int32(f);
- p_track->ctts_sample_offset[i] = mp4ff_read_int32(f);
- }
- return 1;
- }
-}
-
-static int32_t mp4ff_read_stsc(mp4ff_t * f)
-{
- int32_t i;
-
- if (f->total_tracks == 0)
- return f->error++;
-
- mp4ff_read_char(f); /* version */
- mp4ff_read_int24(f); /* flags */
- f->track[f->total_tracks - 1]->stsc_entry_count = mp4ff_read_int32(f);
-
- f->track[f->total_tracks - 1]->stsc_first_chunk =
- (int32_t *) malloc(f->track[f->total_tracks - 1]->stsc_entry_count *
- sizeof (int32_t));
- f->track[f->total_tracks - 1]->stsc_samples_per_chunk =
- (int32_t *) malloc(f->track[f->total_tracks - 1]->stsc_entry_count *
- sizeof (int32_t));
- f->track[f->total_tracks - 1]->stsc_sample_desc_index =
- (int32_t *) malloc(f->track[f->total_tracks - 1]->stsc_entry_count *
- sizeof (int32_t));
-
- /* CVE-2017-9219 */
- if (!f->track[f->total_tracks - 1]->stsc_first_chunk) {
- return f->error++;
- }
- if (!f->track[f->total_tracks - 1]->stsc_samples_per_chunk) {
- free(f->track[f->total_tracks - 1]->stsc_first_chunk);
- f->track[f->total_tracks - 1]->stsc_first_chunk = NULL;
- return f->error++;
- }
- if (!f->track[f->total_tracks - 1]->stsc_sample_desc_index) {
- free(f->track[f->total_tracks - 1]->stsc_first_chunk);
- f->track[f->total_tracks - 1]->stsc_first_chunk = NULL;
- free(f->track[f->total_tracks - 1]->stsc_samples_per_chunk);
- f->track[f->total_tracks - 1]->stsc_samples_per_chunk = NULL;
- return f->error++;
- }
-
- for (i = 0; i < f->track[f->total_tracks - 1]->stsc_entry_count && !f->stream->read_error; i++) { /* CVE-2017-9255 */
- f->track[f->total_tracks - 1]->stsc_first_chunk[i] =
- mp4ff_read_int32(f);
- f->track[f->total_tracks - 1]->stsc_samples_per_chunk[i] =
- mp4ff_read_int32(f);
- f->track[f->total_tracks - 1]->stsc_sample_desc_index[i] =
- mp4ff_read_int32(f);
- }
-
- return 0;
-}
-
-static int32_t mp4ff_read_stco(mp4ff_t * f)
-{
- int32_t i;
-
- if (f->total_tracks == 0)
- return f->error++;
-
- mp4ff_read_char(f); /* version */
- mp4ff_read_int24(f); /* flags */
- f->track[f->total_tracks - 1]->stco_entry_count = mp4ff_read_int32(f);
-
- f->track[f->total_tracks - 1]->stco_chunk_offset =
- (int32_t *) malloc(f->track[f->total_tracks - 1]->stco_entry_count *
- sizeof (int32_t));
-
- /* CVE-2017-9220 */
- if (!f->track[f->total_tracks - 1]->stco_chunk_offset)
- return f->error++;
-
- for (i = 0; i < f->track[f->total_tracks - 1]->stco_entry_count && !f->stream->read_error; i++) { /* CVE-2017-9256 */
- f->track[f->total_tracks - 1]->stco_chunk_offset[i] =
- mp4ff_read_int32(f);
- }
-
- return 0;
-}
-
-static uint16_t mp4ff_read_int16(mp4ff_t * f)
-{
- uint32_t result;
- uint32_t a, b;
- int8_t data[2];
-
- mp4ff_read_data(f, data, 2);
- a = (uint8_t) data[0];
- b = (uint8_t) data[1];
-
- result = (a << 8) | b;
- return (uint16_t) result;
-}
-
-static uint32_t mp4ff_read_mp4_descr_length(mp4ff_t * f)
-{
- uint8_t b;
- uint8_t numBytes = 0;
- uint32_t length = 0;
-
- do {
- b = mp4ff_read_char(f);
- numBytes++;
- length = (length << 7) | (b & 0x7F);
- } while ((b & 0x80) && numBytes < 4);
-
- return length;
-}
-static int32_t mp4ff_read_esds(mp4ff_t * f)
-{
- uint8_t tag;
- uint32_t temp;
-
- if (f->total_tracks == 0)
- return f->error++;
-
- mp4ff_read_char(f); /* version */
- mp4ff_read_int24(f); /* flags */
-
- /* get and verify ES_DescrTag */
- tag = mp4ff_read_char(f);
- if (tag == 0x03) {
- /* read length */
- if (mp4ff_read_mp4_descr_length(f) < 5 + 15) {
- return 1;
- }
- /* skip 3 bytes */
- mp4ff_read_int24(f);
- } else {
- /* skip 2 bytes */
- mp4ff_read_int16(f);
- }
-
- /* get and verify DecoderConfigDescrTab */
- if (mp4ff_read_char(f) != 0x04) {
- return 1;
- }
-
- /* read length */
- temp = mp4ff_read_mp4_descr_length(f);
- if (temp < 13)
- return 1;
-
- f->track[f->total_tracks - 1]->audioType = mp4ff_read_char(f);
- mp4ff_read_int32(f); //0x15000414 ????
- f->track[f->total_tracks - 1]->maxBitrate = mp4ff_read_int32(f);
- f->track[f->total_tracks - 1]->avgBitrate = mp4ff_read_int32(f);
-
- /* get and verify DecSpecificInfoTag */
- if (mp4ff_read_char(f) != 0x05) {
- return 1;
- }
-
- /* read length */
- f->track[f->total_tracks - 1]->decoderConfigLen =
- mp4ff_read_mp4_descr_length(f);
-
- if (f->track[f->total_tracks - 1]->decoderConfig)
- free(f->track[f->total_tracks - 1]->decoderConfig);
- f->track[f->total_tracks - 1]->decoderConfig =
- malloc(f->track[f->total_tracks - 1]->decoderConfigLen);
- if (f->track[f->total_tracks - 1]->decoderConfig) {
- mp4ff_read_data(f, f->track[f->total_tracks - 1]->decoderConfig,
- f->track[f->total_tracks -
- 1]->decoderConfigLen);
- } else {
- f->track[f->total_tracks - 1]->decoderConfigLen = 0;
- }
-
- /* will skip the remainder of the atom */
- return 0;
-}
-static int32_t mp4ff_read_mp4a(mp4ff_t * f)
-{
- int32_t i;
- uint8_t atom_type = 0;
- uint8_t header_size = 0;
-
- if (f->total_tracks == 0)
- return f->error++;
-
- for (i = 0; i < 6; i++) {
- mp4ff_read_char(f); /* reserved */
- }
- /* data_reference_index */ mp4ff_read_int16(f);
-
- mp4ff_read_int32(f); /* reserved */
- mp4ff_read_int32(f); /* reserved */
-
- f->track[f->total_tracks - 1]->channelCount = mp4ff_read_int16(f);
- f->track[f->total_tracks - 1]->sampleSize = mp4ff_read_int16(f);
-
- mp4ff_read_int16(f);
- mp4ff_read_int16(f);
-
- f->track[f->total_tracks - 1]->sampleRate = mp4ff_read_int16(f);
-
- mp4ff_read_int16(f);
-
- mp4ff_atom_read_header(f, &atom_type, &header_size);
- if (atom_type == ATOM_ESDS) {
- mp4ff_read_esds(f);
- }
-
- return 0;
-}
-
-static int32_t mp4ff_read_stsd(mp4ff_t * f)
-{
- int32_t i;
- uint8_t header_size = 0;
-
- /* CVE-2017-9218 */
- if (f->total_tracks == 0)
- return f->error++;
-
- mp4ff_read_char(f); /* version */
- mp4ff_read_int24(f); /* flags */
-
- f->track[f->total_tracks - 1]->stsd_entry_count = mp4ff_read_int32(f);
-
- for (i = 0; i < f->track[f->total_tracks - 1]->stsd_entry_count && !f->stream->read_error; i++) { /* CVE-2017-9253 */
- uint64_t skip = mp4ff_position(f);
- uint64_t size;
- uint8_t atom_type = 0;
- size = mp4ff_atom_read_header(f, &atom_type, &header_size);
- skip += size;
-
- if (atom_type == ATOM_MP4A) {
- f->track[f->total_tracks - 1]->type = TRACK_AUDIO;
- mp4ff_read_mp4a(f);
- } else if (atom_type == ATOM_MP4V) {
- f->track[f->total_tracks - 1]->type = TRACK_VIDEO;
- } else if (atom_type == ATOM_MP4S) {
- f->track[f->total_tracks - 1]->type = TRACK_SYSTEM;
- } else {
- f->track[f->total_tracks - 1]->type = TRACK_UNKNOWN;
- }