avformat/subtitles: add a next line jumper and use it.
authorClément Bœsch <u@pkh.me>
Sun, 8 Sep 2013 16:02:45 +0000 (18:02 +0200)
committerClément Bœsch <u@pkh.me>
Sun, 8 Sep 2013 16:48:09 +0000 (18:48 +0200)
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
libavformat/matroskaenc.c
libavformat/microdvddec.c
libavformat/mpl2dec.c
libavformat/mpsubdec.c
libavformat/srtdec.c
libavformat/subtitles.h

index da1afad..e2cbaad 100644 (file)
@@ -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;
 }
index 7b69bc3..2c128cc 100644 (file)
@@ -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;
 }
index 7254bcf..7b49e43 100644 (file)
@@ -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;
 }
index ffe1d83..17b302d 100644 (file)
@@ -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;
     }
index 6a0cefb..c5bdcdb 100644 (file)
@@ -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;
 }
index ac783d9..7f911bd 100644 (file)
@@ -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;
 }
index 455b374..96de9fa 100644 (file)
@@ -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 */