From 90fc00a623de44e137fe1601b91356e8cd8bdd54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= Date: Sun, 8 Sep 2013 18:02:45 +0200 Subject: [PATCH] avformat/subtitles: add a next line jumper and use it. 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. --- libavformat/jacosubdec.c | 2 +- libavformat/matroskaenc.c | 3 ++- libavformat/microdvddec.c | 2 +- libavformat/mpl2dec.c | 2 +- libavformat/mpsubdec.c | 7 ++++++- libavformat/srtdec.c | 8 +++----- libavformat/subtitles.h | 10 ++++++++++ 7 files changed, 24 insertions(+), 10 deletions(-) diff --git a/libavformat/jacosubdec.c b/libavformat/jacosubdec.c index da1afadf1b..e2cbaad83e 100644 --- a/libavformat/jacosubdec.c +++ b/libavformat/jacosubdec.c @@ -63,7 +63,7 @@ static int jacosub_probe(AVProbeData *p) return AVPROBE_SCORE_EXTENSION + 1; return 0; } - ptr += strcspn(ptr, "\n") + 1; + ptr += ff_subtitles_next_line(ptr); } return 0; } diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 7b69bc3abf..2c128ccbb7 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -28,6 +28,7 @@ #include "isom.h" #include "matroska.h" #include "riff.h" +#include "subtitles.h" #include "wv.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; duration = e_hsec - s_hsec; } - *buf += strcspn(*buf, "\n") + 1; + *buf += ff_subtitles_next_line(*buf); } return duration; } diff --git a/libavformat/microdvddec.c b/libavformat/microdvddec.c index 7254bcf7f8..7b49e43976 100644 --- a/libavformat/microdvddec.c +++ b/libavformat/microdvddec.c @@ -47,7 +47,7 @@ static int microdvd_probe(AVProbeData *p) sscanf(ptr, "{%*d}{%*d}%c", &c) != 1 && sscanf(ptr, "{DEFAULT}{}%c", &c) != 1) return 0; - ptr += strcspn(ptr, "\n") + 1; + ptr += ff_subtitles_next_line(ptr); } return AVPROBE_SCORE_MAX; } diff --git a/libavformat/mpl2dec.c b/libavformat/mpl2dec.c index ffe1d83991..17b302ddfa 100644 --- a/libavformat/mpl2dec.c +++ b/libavformat/mpl2dec.c @@ -43,7 +43,7 @@ static int mpl2_probe(AVProbeData *p) if (sscanf(ptr, "[%"SCNd64"][%"SCNd64"]%c", &start, &end, &c) != 3 && sscanf(ptr, "[%"SCNd64"][]%c", &start, &c) != 2) return 0; - ptr += strcspn(ptr, "\n") + 1; + ptr += ff_subtitles_next_line(ptr); if (ptr >= ptr_end) return 0; } diff --git a/libavformat/mpsubdec.c b/libavformat/mpsubdec.c index 6a0cefbeb6..c5bdcdb626 100644 --- a/libavformat/mpsubdec.c +++ b/libavformat/mpsubdec.c @@ -37,11 +37,16 @@ static int mpsub_probe(AVProbeData *p) const char *ptr_end = p->buf + p->buf_size; while (ptr < ptr_end) { + int inc; + if (!memcmp(ptr, "FORMAT=TIME", 11)) return AVPROBE_SCORE_EXTENSION; if (!memcmp(ptr, "FORMAT=", 7)) return AVPROBE_SCORE_EXTENSION / 3; - ptr += strcspn(ptr, "\n") + 1; + inc = ff_subtitles_next_line(ptr); + if (!inc) + break; + ptr += inc; } return 0; } diff --git a/libavformat/srtdec.c b/libavformat/srtdec.c index ac783d9e3b..7f911bd05b 100644 --- a/libavformat/srtdec.c +++ b/libavformat/srtdec.c @@ -44,7 +44,7 @@ static int srt_probe(AVProbeData *p) && sscanf(ptr, "%*d:%*2d:%*2d%*1[,.]%*3d --> %*d:%*2d:%*2d%*1[,.]%3d", &v) == 1) return AVPROBE_SCORE_MAX; num = atoi(ptr); - ptr += strcspn(ptr, "\n") + 1; + ptr += ff_subtitles_next_line(ptr); } 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 end = (hh2*3600LL + mm2*60LL + ss2) * 1000LL + ms2; *duration = end - start; - *buf += strcspn(*buf, "\n"); - *buf += !!**buf; + *buf += ff_subtitles_next_line(*buf); return start; } - *buf += strcspn(*buf, "\n"); - *buf += !!**buf; + *buf += ff_subtitles_next_line(*buf); } return AV_NOPTS_VALUE; } diff --git a/libavformat/subtitles.h b/libavformat/subtitles.h index 455b374f25..96de9fa5d4 100644 --- a/libavformat/subtitles.h +++ b/libavformat/subtitles.h @@ -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); +/** + * 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 */