This fixes a bunch of possible overread in avformat with the idiom p += strcspn(p, "\n") + 1 (strcspn() can focus on the trailing '\0' if no '\n' is found, so the +1 leads to an overread). Note on lavf/matroskaenc: no extra subtitles.o Makefile dependency is added because only the header is required for ff_subtitles_next_line(). Note on lavf/mpsubdec: code gets slightly complex to avoid an infinite loop in the probing since there is no more forced increment.tags/n2.1
| @@ -63,7 +63,7 @@ static int jacosub_probe(AVProbeData *p) | |||||
| return AVPROBE_SCORE_EXTENSION + 1; | return AVPROBE_SCORE_EXTENSION + 1; | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| ptr += strcspn(ptr, "\n") + 1; | |||||
| ptr += ff_subtitles_next_line(ptr); | |||||
| } | } | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -28,6 +28,7 @@ | |||||
| #include "isom.h" | #include "isom.h" | ||||
| #include "matroska.h" | #include "matroska.h" | ||||
| #include "riff.h" | #include "riff.h" | ||||
| #include "subtitles.h" | |||||
| #include "wv.h" | #include "wv.h" | ||||
| #include "libavutil/avstring.h" | #include "libavutil/avstring.h" | ||||
| @@ -1363,7 +1364,7 @@ static int srt_get_duration(uint8_t **buf) | |||||
| s_hsec += 1000*s_sec; e_hsec += 1000*e_sec; | s_hsec += 1000*s_sec; e_hsec += 1000*e_sec; | ||||
| duration = e_hsec - s_hsec; | duration = e_hsec - s_hsec; | ||||
| } | } | ||||
| *buf += strcspn(*buf, "\n") + 1; | |||||
| *buf += ff_subtitles_next_line(*buf); | |||||
| } | } | ||||
| return duration; | return duration; | ||||
| } | } | ||||
| @@ -47,7 +47,7 @@ static int microdvd_probe(AVProbeData *p) | |||||
| sscanf(ptr, "{%*d}{%*d}%c", &c) != 1 && | sscanf(ptr, "{%*d}{%*d}%c", &c) != 1 && | ||||
| sscanf(ptr, "{DEFAULT}{}%c", &c) != 1) | sscanf(ptr, "{DEFAULT}{}%c", &c) != 1) | ||||
| return 0; | return 0; | ||||
| ptr += strcspn(ptr, "\n") + 1; | |||||
| ptr += ff_subtitles_next_line(ptr); | |||||
| } | } | ||||
| return AVPROBE_SCORE_MAX; | return AVPROBE_SCORE_MAX; | ||||
| } | } | ||||
| @@ -43,7 +43,7 @@ static int mpl2_probe(AVProbeData *p) | |||||
| if (sscanf(ptr, "[%"SCNd64"][%"SCNd64"]%c", &start, &end, &c) != 3 && | if (sscanf(ptr, "[%"SCNd64"][%"SCNd64"]%c", &start, &end, &c) != 3 && | ||||
| sscanf(ptr, "[%"SCNd64"][]%c", &start, &c) != 2) | sscanf(ptr, "[%"SCNd64"][]%c", &start, &c) != 2) | ||||
| return 0; | return 0; | ||||
| ptr += strcspn(ptr, "\n") + 1; | |||||
| ptr += ff_subtitles_next_line(ptr); | |||||
| if (ptr >= ptr_end) | if (ptr >= ptr_end) | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -37,11 +37,16 @@ static int mpsub_probe(AVProbeData *p) | |||||
| const char *ptr_end = p->buf + p->buf_size; | const char *ptr_end = p->buf + p->buf_size; | ||||
| while (ptr < ptr_end) { | while (ptr < ptr_end) { | ||||
| int inc; | |||||
| if (!memcmp(ptr, "FORMAT=TIME", 11)) | if (!memcmp(ptr, "FORMAT=TIME", 11)) | ||||
| return AVPROBE_SCORE_EXTENSION; | return AVPROBE_SCORE_EXTENSION; | ||||
| if (!memcmp(ptr, "FORMAT=", 7)) | if (!memcmp(ptr, "FORMAT=", 7)) | ||||
| return AVPROBE_SCORE_EXTENSION / 3; | return AVPROBE_SCORE_EXTENSION / 3; | ||||
| ptr += strcspn(ptr, "\n") + 1; | |||||
| inc = ff_subtitles_next_line(ptr); | |||||
| if (!inc) | |||||
| break; | |||||
| ptr += inc; | |||||
| } | } | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -44,7 +44,7 @@ static int srt_probe(AVProbeData *p) | |||||
| && sscanf(ptr, "%*d:%*2d:%*2d%*1[,.]%*3d --> %*d:%*2d:%*2d%*1[,.]%3d", &v) == 1) | && sscanf(ptr, "%*d:%*2d:%*2d%*1[,.]%*3d --> %*d:%*2d:%*2d%*1[,.]%3d", &v) == 1) | ||||
| return AVPROBE_SCORE_MAX; | return AVPROBE_SCORE_MAX; | ||||
| num = atoi(ptr); | num = atoi(ptr); | ||||
| ptr += strcspn(ptr, "\n") + 1; | |||||
| ptr += ff_subtitles_next_line(ptr); | |||||
| } | } | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -65,12 +65,10 @@ static int64_t get_pts(const char **buf, int *duration, | |||||
| int64_t start = (hh1*3600LL + mm1*60LL + ss1) * 1000LL + ms1; | int64_t start = (hh1*3600LL + mm1*60LL + ss1) * 1000LL + ms1; | ||||
| int64_t end = (hh2*3600LL + mm2*60LL + ss2) * 1000LL + ms2; | int64_t end = (hh2*3600LL + mm2*60LL + ss2) * 1000LL + ms2; | ||||
| *duration = end - start; | *duration = end - start; | ||||
| *buf += strcspn(*buf, "\n"); | |||||
| *buf += !!**buf; | |||||
| *buf += ff_subtitles_next_line(*buf); | |||||
| return start; | return start; | ||||
| } | } | ||||
| *buf += strcspn(*buf, "\n"); | |||||
| *buf += !!**buf; | |||||
| *buf += ff_subtitles_next_line(*buf); | |||||
| } | } | ||||
| return AV_NOPTS_VALUE; | return AV_NOPTS_VALUE; | ||||
| } | } | ||||
| @@ -96,4 +96,14 @@ const char *ff_smil_get_attr_ptr(const char *s, const char *attr); | |||||
| */ | */ | ||||
| void ff_subtitles_read_chunk(AVIOContext *pb, AVBPrint *buf); | void ff_subtitles_read_chunk(AVIOContext *pb, AVBPrint *buf); | ||||
| /** | |||||
| * Get the number of characters to increment to jump to the next line, or to | |||||
| * the end of the string. | |||||
| */ | |||||
| static av_always_inline int ff_subtitles_next_line(const char *ptr) | |||||
| { | |||||
| int n = strcspn(ptr, "\n"); | |||||
| return n + !!*ptr; | |||||
| } | |||||
| #endif /* AVFORMAT_SUBTITLES_H */ | #endif /* AVFORMAT_SUBTITLES_H */ | ||||