diff mbox

[FFmpeg-devel,2/2] avcodec/htmlsubtitles: Fixes denial of service due to use of sscanf in inner loop for handling braces

Message ID 20190213002238.32283-2-michael@niedermayer.cc
State Accepted
Commit 894995c41e0795c7a44f81adc4838dedc3932e65
Headers show

Commit Message

Michael Niedermayer Feb. 13, 2019, 12:22 a.m. UTC
From: Kevin Backhouse via RT <security-reports@semmle.com>

Fixes: [Semmle Security Reports #19439]
Fixes: dos_sscanf2.mkv

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
---
 libavcodec/htmlsubtitles.c | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)
diff mbox

Patch

diff --git a/libavcodec/htmlsubtitles.c b/libavcodec/htmlsubtitles.c
index c0cfccfb16..d9221ba16b 100644
--- a/libavcodec/htmlsubtitles.c
+++ b/libavcodec/htmlsubtitles.c
@@ -24,6 +24,7 @@ 
 #include "libavutil/common.h"
 #include "libavutil/parseutils.h"
 #include "htmlsubtitles.h"
+#include <ctype.h>
 
 static int html_color_parse(void *log_ctx, const char *str)
 {
@@ -44,14 +45,32 @@  static void rstrip_spaces_buf(AVBPrint *buf)
             buf->str[--buf->len] = 0;
 }
 
+/*
+ * Fast code for scanning text enclosed in braces. Functionally
+ * equivalent to this sscanf call:
+ *
+ * sscanf(in, "{\\an%*1u}%n", &len) >= 0 && len > 0
+ */
+static int scanbraces(const char* in) {
+    if (strncmp(in, "{\\an", 4) != 0) {
+        return 0;
+    }
+    if (!isdigit(in[4])) {
+        return 0;
+    }
+    if (in[5] != '}') {
+        return 0;
+    }
+    return 1;
+}
+
 /* skip all {\xxx} substrings except for {\an%d}
    and all microdvd like styles such as {Y:xxx} */
 static void handle_open_brace(AVBPrint *dst, const char **inp, int *an, int *closing_brace_missing)
 {
-    int len = 0;
     const char *in = *inp;
 
-    *an += sscanf(in, "{\\an%*1u}%n", &len) >= 0 && len > 0;
+    *an += scanbraces(in);
 
     if (!*closing_brace_missing) {
         if (   (*an != 1 && in[1] == '\\')