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 da1afadf1b283ab2148801781951bff2d1736086..e2cbaad83e581acc61f17fb479f76baa70788a1e 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 7b69bc3abfe46be493e3b854c5dc806440f8a856..2c128ccbb775440509f09ea62f4798e27a48803c 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 7254bcf7f8c9b7a64b727380a391ec9a1830bd64..7b49e439765bbe661135b095acc948307cb27917 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 ffe1d839915bc0bcc2a8ff90562dbed844843fc1..17b302ddfa6674c2e3504b438ff0c6000dfdd19a 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 6a0cefbeb68e1537b1b4fffa248146ca844f534b..c5bdcdb626a674da532ce8d44738c876bdf38b82 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 ac783d9e3bb8e45ca4dad1301beb69501c666410..7f911bd05b381347562d8a2c7b53945732d526af 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 455b374f259a35987a10bc11ccf18a72057a872d..96de9fa5d40b6ab5af61e01aa18ee7d8181a83e2 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 */