[FFmpeg-devel] [PATCH 1/6] lavc/ass_split: Fix parser bugs

Rodger Combs rodger.combs at gmail.com
Thu Sep 10 18:12:14 CEST 2015


Specifically:
- Skip writing drawings as text
- Parse \h correctly
- Handle comments and unknown tags correctly
---
 libavcodec/ass_split.c | 29 +++++++++++++++++------------
 1 file changed, 17 insertions(+), 12 deletions(-)

diff --git a/libavcodec/ass_split.c b/libavcodec/ass_split.c
index 9bc7b9d..e9b100d 100644
--- a/libavcodec/ass_split.c
+++ b/libavcodec/ass_split.c
@@ -428,30 +428,37 @@ int ff_ass_split_override_codes(const ASSCodesCallbacks *callbacks, void *priv,
     const char *text = NULL;
     char new_line[2];
     int text_len = 0;
+    int drawing = 0;
 
     while (buf && *buf) {
         if (text && callbacks->text &&
-            (sscanf(buf, "\\%1[nN]", new_line) == 1 ||
-             !strncmp(buf, "{\\", 2))) {
-            callbacks->text(priv, text, text_len);
+            (sscanf(buf, "\\%1[nNh]", new_line) == 1 ||
+             *buf == '{')) {
+            if (!drawing)
+                callbacks->text(priv, text, text_len);
             text = NULL;
         }
-        if (sscanf(buf, "\\%1[nN]", new_line) == 1) {
+        if (sscanf(buf, "\\%1h", new_line) == 1) {
+            callbacks->text(priv, "\u00A0", 2);
+            buf += 2;
+        } else if (sscanf(buf, "\\%1[nN]", new_line) == 1) {
             if (callbacks->new_line)
                 callbacks->new_line(priv, new_line[0] == 'N');
             buf += 2;
-        } else if (!strncmp(buf, "{\\", 2)) {
-            buf++;
+        } else if (*buf == '{' && strchr(buf, '}')) {
+            buf += strcspn(buf, "\\}"); // skip comments
             while (*buf == '\\') {
                 char style[2], c[2], sep[2], c_num[2] = "0", tmp[128] = {0};
                 unsigned int color = 0xFFFFFFFF;
-                int len, size = -1, an = -1, alpha = -1;
+                int len = 2, size = -1, an = -1, alpha = -1;
                 int x1, y1, x2, y2, t1 = -1, t2 = -1;
                 if (sscanf(buf, "\\%1[bisu]%1[01\\}]%n", style, c, &len) > 1) {
                     int close = c[0] == '0' ? 1 : c[0] == '1' ? 0 : -1;
                     len += close != -1;
                     if (callbacks->style)
                         callbacks->style(priv, style[0], close);
+                } else if (sscanf(buf, "\\p%u%1[\\}]%n", &size, sep, &len) > 1) {
+                    drawing = (size > 0);
                 } else if (sscanf(buf, "\\c%1[\\}]%n", sep, &len) > 0 ||
                            sscanf(buf, "\\c&H%X&%1[\\}]%n", &color, sep, &len) > 1 ||
                            sscanf(buf, "\\%1[1234]c%1[\\}]%n", c_num, sep, &len) > 1 ||
@@ -494,13 +501,11 @@ int ff_ass_split_override_codes(const ASSCodesCallbacks *callbacks, void *priv,
                 } else if (sscanf(buf, "\\org(%d,%d)%1[\\}]%n", &x1, &y1, sep, &len) > 2) {
                     if (callbacks->origin)
                         callbacks->origin(priv, x1, y1);
-                } else {
-                    len = strcspn(buf+1, "\\}") + 2;  /* skip unknown code */
                 }
                 buf += len - 1;
+                buf += strcspn(buf, "\\}"); // skip comments
             }
-            if (*buf++ != '}')
-                return AVERROR_INVALIDDATA;
+            buf++; // skip }
         } else {
             if (!text) {
                 text = buf;
@@ -510,7 +515,7 @@ int ff_ass_split_override_codes(const ASSCodesCallbacks *callbacks, void *priv,
             buf++;
         }
     }
-    if (text && callbacks->text)
+    if (text && callbacks->text && !drawing)
         callbacks->text(priv, text, text_len);
     if (callbacks->end)
         callbacks->end(priv);
-- 
2.5.1



More information about the ffmpeg-devel mailing list