static int aa_read_header(AVFormatContext *s)
{
int i, j, idx, largest_idx = -1;
- uint32_t nkey, nval, toc_size, npairs, header_seed = 0, start;
- char key[128], val[128], codec_name[64] = {0};
+ uint32_t toc_size, npairs, header_seed = 0, start;
+ char codec_name[64] = {0};
uint8_t output[24], dst[8], src[8];
int64_t largest_size = -1, current_size = -1, chapter_pos;
struct toc_entry {
AADemuxContext *c = s->priv_data;
AVIOContext *pb = s->pb;
AVStream *st;
+ int ret;
/* parse .aa header */
avio_skip(pb, 4); // file size
avio_skip(pb, 4); // magic string
toc_size = avio_rb32(pb); // TOC size
avio_skip(pb, 4); // unidentified integer
- if (toc_size > MAX_TOC_ENTRIES)
+ if (toc_size > MAX_TOC_ENTRIES || toc_size < 2)
return AVERROR_INVALIDDATA;
for (i = 0; i < toc_size; i++) { // read TOC
avio_skip(pb, 4); // TOC entry index
if (npairs > MAX_DICTIONARY_ENTRIES)
return AVERROR_INVALIDDATA;
for (i = 0; i < npairs; i++) {
- memset(val, 0, sizeof(val));
- memset(key, 0, sizeof(key));
+ char key[128], val[128];
+ uint32_t nkey, nval;
+
avio_skip(pb, 1); // unidentified integer
nkey = avio_rb32(pb); // key string length
nval = avio_rb32(pb); // value string length
avio_get_str(pb, nval, val, sizeof(val));
if (!strcmp(key, "codec")) {
av_log(s, AV_LOG_DEBUG, "Codec is <%s>\n", val);
- strncpy(codec_name, val, sizeof(codec_name) - 1);
+ av_strlcpy(codec_name, val, sizeof(codec_name));
} else if (!strcmp(key, "HeaderSeed")) {
av_log(s, AV_LOG_DEBUG, "HeaderSeed is <%s>\n", val);
header_seed = atoi(val);
} else if (!strcmp(key, "HeaderKey")) { // this looks like "1234567890 1234567890 1234567890 1234567890"
av_log(s, AV_LOG_DEBUG, "HeaderKey is <%s>\n", val);
- sscanf(val, "%"SCNu32"%"SCNu32"%"SCNu32"%"SCNu32,
+
+ ret = sscanf(val, "%"SCNu32"%"SCNu32"%"SCNu32"%"SCNu32,
&header_key_part[0], &header_key_part[1], &header_key_part[2], &header_key_part[3]);
+ if (ret != 4)
+ return AVERROR_INVALIDDATA;
+
for (idx = 0; idx < 4; idx++) {
AV_WB32(&header_key[idx * 4], header_key_part[idx]); // convert each part to BE!
}
c->content_end = start + largest_size;
while ((chapter_pos = avio_tell(pb)) >= 0 && chapter_pos < c->content_end) {
- int chapter_idx = s->nb_chapters;
+ unsigned chapter_idx = s->nb_chapters;
uint32_t chapter_size = avio_rb32(pb);
- if (chapter_size == 0) break;
+ if (chapter_size == 0 || avio_feof(pb))
+ break;
chapter_pos -= start + CHAPTER_HEADER_SIZE * chapter_idx;
avio_skip(pb, 4 + chapter_size);
if (!avpriv_new_chapter(s, chapter_idx, st->time_base,
- chapter_pos * TIMEPREC, (chapter_pos + chapter_size) * TIMEPREC, NULL))
- return AVERROR(ENOMEM);
+ chapter_pos * TIMEPREC,
+ (chapter_pos + chapter_size) * TIMEPREC, NULL)) {
+ av_freep(&c->tea_ctx);
+ return AVERROR(ENOMEM);
+ }
}
st->duration = (largest_size - CHAPTER_HEADER_SIZE * s->nb_chapters) * TIMEPREC;
.version = LIBAVUTIL_VERSION_INT,
};
-AVInputFormat ff_aa_demuxer = {
+const AVInputFormat ff_aa_demuxer = {
.name = "aa",
.long_name = NULL_IF_CONFIG_SMALL("Audible AA format files"),
.priv_class = &aa_class,