[FFmpeg-devel] Recent subtitle fixes backportet for upcoming FFmpeg 1.2.4

Alexander Strasser eclipse7 at gmx.net
Mon Sep 16 06:52:27 CEST 2013


Hi all,

  attached are the same fixes I backported for 2.0.2 release.

  Needed more editing and lavc/assenc patch was dropped because the
code didn't exist yet.

  FATE was successful here.

  Alexander
-------------- next part --------------
From f0324197d17c8187ba72b80f2249d9101ae5ed71 Mon Sep 17 00:00:00 2001
Message-Id: <f0324197d17c8187ba72b80f2249d9101ae5ed71.1379284923.git.eclipse7 at gmx.net>
From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= <u at pkh.me>
Date: Sun, 8 Sep 2013 16:17:46 +0200
Subject: [PATCH 1/3] avformat/srtdec: skip initial random line breaks.
To: ffdev

I found a bunch of (recent) SRT files in the wild with 3 to 10 line
breaks at the beginning.

(cherry picked from commit cfcd55db164e0acc0c30b2cf084e6eebe9741d34)

Signed-off-by: Alexander Strasser <eclipse7 at gmx.net>
---
 libavformat/srtdec.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libavformat/srtdec.c b/libavformat/srtdec.c
index 76e06e4..6b60052 100644
--- a/libavformat/srtdec.c
+++ b/libavformat/srtdec.c
@@ -37,6 +37,8 @@ static int srt_probe(AVProbeData *p)
     if (AV_RB24(ptr) == 0xEFBBBF)
         ptr += 3;  /* skip UTF-8 BOM */
 
+    while (*ptr == '\r' || *ptr == '\n')
+        ptr++;
     for (i=0; i<2; i++) {
         if ((num == i || num + 1 == i)
             && sscanf(ptr, "%*d:%*2d:%*2d%*1[,.]%*3d --> %*d:%*2d:%*2d%*1[,.]%3d", &v) == 1)
-- 

From 8745680ed37aa7ef3e99c1c5544b5a41b93031f8 Mon Sep 17 00:00:00 2001
Message-Id: <8745680ed37aa7ef3e99c1c5544b5a41b93031f8.1379284923.git.eclipse7 at gmx.net>
In-Reply-To: <f0324197d17c8187ba72b80f2249d9101ae5ed71.1379284923.git.eclipse7 at gmx.net>
References: <f0324197d17c8187ba72b80f2249d9101ae5ed71.1379284923.git.eclipse7 at gmx.net>
From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= <u at pkh.me>
Date: Sun, 8 Sep 2013 18:02:45 +0200
Subject: [PATCH 2/3] avformat/subtitles: add a next line jumper and use it.
To: ffdev

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.

NOTE:
Code of function ff_subtitles_next_line fixed by Alexander Strasser.

The original code from master did test the wrong character, but was
corrected by a subsequent commit. That commit however is not backported,
so it had to be fixed in this commit for the backport.

Conflicts:
	libavformat/mpl2dec.c

(cherry picked from commit 90fc00a623de44e137fe1601b91356e8cd8bdd54)

Signed-off-by: Alexander Strasser <eclipse7 at gmx.net>
---
 libavformat/jacosubdec.c  |  2 +-
 libavformat/matroskaenc.c |  3 ++-
 libavformat/microdvddec.c |  2 +-
 libavformat/mpl2dec.c     |  2 +-
 libavformat/mpsubdec.c    |  6 +++++-
 libavformat/srtdec.c      |  7 ++++---
 libavformat/subtitles.h   | 13 +++++++++++++
 7 files changed, 27 insertions(+), 8 deletions(-)

diff --git a/libavformat/jacosubdec.c b/libavformat/jacosubdec.c
index 89e7e1b..c622dd0 100644
--- a/libavformat/jacosubdec.c
+++ b/libavformat/jacosubdec.c
@@ -63,7 +63,7 @@ static int jacosub_probe(AVProbeData *p)
                 return AVPROBE_SCORE_MAX/2 + 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 e62d534..c506835 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -27,6 +27,7 @@
 #include "avc.h"
 #include "flacenc.h"
 #include "avlanguage.h"
+#include "subtitles.h"
 #include "libavutil/samplefmt.h"
 #include "libavutil/sha.h"
 #include "libavutil/intreadwrite.h"
@@ -1179,7 +1180,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 4b42846..5d9b13e 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 ce2061b..2f708e0 100644
--- a/libavformat/mpl2dec.c
+++ b/libavformat/mpl2dec.c
@@ -43,7 +43,7 @@ static int mpl2_probe(AVProbeData *p)
         if (sscanf(ptr, "[%"PRId64"][%"PRId64"]%c", &start, &end, &c) != 3 &&
             sscanf(ptr, "[%"PRId64"][]%c",          &start,       &c) != 2)
             return 0;
-        ptr += strcspn(ptr, "\r\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 2acafaa..360a3d83 100644
--- a/libavformat/mpsubdec.c
+++ b/libavformat/mpsubdec.c
@@ -37,12 +37,16 @@ static int mpsub_probe(AVProbeData *p)
     const char *ptr_end = p->buf + p->buf_size;
 
     while (ptr < ptr_end) {
+        int inc;
         int n;
 
         if (!memcmp(ptr, "FORMAT=TIME", 11) ||
             sscanf(ptr, "FORMAT=%d", &n) == 1)
             return AVPROBE_SCORE_MAX/2;
-        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 6b60052..ba79984 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,10 +65,11 @@ 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") + 1;
+            *buf += ff_subtitles_next_line(*buf);
             return start;
         }
-        *buf += strcspn(*buf, "\n") + 1;
+        *buf += ff_subtitles_next_line(*buf);
+
     }
     return AV_NOPTS_VALUE;
 }
diff --git a/libavformat/subtitles.h b/libavformat/subtitles.h
index 455b374..8f68e7b 100644
--- a/libavformat/subtitles.h
+++ b/libavformat/subtitles.h
@@ -96,4 +96,17 @@ 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");
+    ptr += n;
+    if (*ptr == '\n')
+        n++;
+    return n;
+}
+
 #endif /* AVFORMAT_SUBTITLES_H */
-- 

From 8b796cd94663f25a57b6a49e4d739f08cf8dac94 Mon Sep 17 00:00:00 2001
Message-Id: <8b796cd94663f25a57b6a49e4d739f08cf8dac94.1379284923.git.eclipse7 at gmx.net>
In-Reply-To: <f0324197d17c8187ba72b80f2249d9101ae5ed71.1379284923.git.eclipse7 at gmx.net>
References: <f0324197d17c8187ba72b80f2249d9101ae5ed71.1379284923.git.eclipse7 at gmx.net>
From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= <u at pkh.me>
Date: Sun, 8 Sep 2013 18:28:11 +0200
Subject: [PATCH 3/3] avcodec/srtdec: fix potential overread.
To: ffdev

(cherry picked from commit 3a54c221d574ec944db1eddf9df895808f32bf9e)

Signed-off-by: Alexander Strasser <eclipse7 at gmx.net>
---
 libavcodec/srtdec.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libavcodec/srtdec.c b/libavcodec/srtdec.c
index 267561c..b16645a 100644
--- a/libavcodec/srtdec.c
+++ b/libavcodec/srtdec.c
@@ -204,7 +204,8 @@ static const char *read_ts(const char *buf, int *ts_start, int *ts_end,
                        "%*[ ]X1:%u X2:%u Y1:%u Y2:%u",
                        &hs, &ms, &ss, ts_start, &he, &me, &se, ts_end,
                        x1, x2, y1, y2);
-        buf += strcspn(buf, "\n") + 1;
+        buf += strcspn(buf, "\n");
+        buf += !!*buf;
         if (c >= 8) {
             *ts_start = 100*(ss + 60*(ms + 60*hs)) + *ts_start/10;
             *ts_end   = 100*(se + 60*(me + 60*he)) + *ts_end  /10;
-- 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20130916/b2a28c26/attachment.asc>


More information about the ffmpeg-devel mailing list