aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Backhouse via RT <security-reports@semmle.com>2019-02-06 11:29:22 +0000
committerMichael Niedermayer <michael@niedermayer.cc>2019-03-14 00:24:44 +0100
commitcc5361ed18ab0f69cfbead7afc88fb81ed4b36ae (patch)
tree52629b827ff4833ef5f424ba006d4e799de13bf7
parent4d1fcd734e877b0bcb635664dbc7a0a0ff0627ec (diff)
downloadffmpeg-cc5361ed18ab0f69cfbead7afc88fb81ed4b36ae.tar.gz
avcodec/htmlsubtitles: Fixes denial of service due to use of sscanf in inner loop for tag scaning
Fixes: [Semmle Security Reports #19438] Fixes: dos_sscanf1.mkv Signed-off-by: Michael Niedermayer <michael@niedermayer.cc> (cherry picked from commit 1f00c97bc3475c477f3c468cf2d924d5761d0982) Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
-rw-r--r--libavcodec/htmlsubtitles.c30
1 files changed, 29 insertions, 1 deletions
diff --git a/libavcodec/htmlsubtitles.c b/libavcodec/htmlsubtitles.c
index fb9f900422..c0cfccfb16 100644
--- a/libavcodec/htmlsubtitles.c
+++ b/libavcodec/htmlsubtitles.c
@@ -75,6 +75,34 @@ struct font_tag {
};
/*
+ * Fast code for scanning the rest of a tag. Functionally equivalent to
+ * this sscanf call:
+ *
+ * sscanf(in, "%127[^<>]>%n", buffer, lenp) == 2
+ */
+static int scantag(const char* in, char* buffer, int* lenp) {
+ int len;
+
+ for (len = 0; len < 128; len++) {
+ const char c = *in++;
+ switch (c) {
+ case '\0':
+ return 0;
+ case '<':
+ return 0;
+ case '>':
+ buffer[len] = '\0';
+ *lenp = len+1;
+ return 1;
+ default:
+ break;
+ }
+ buffer[len] = c;
+ }
+ return 0;
+}
+
+/*
* The general politic of the convert is to mask unsupported tags or formatting
* errors (but still alert the user/subtitles writer with an error/warning)
* without dropping any actual text content for the final user.
@@ -155,7 +183,7 @@ int ff_htmlmarkup_to_ass(void *log_ctx, AVBPrint *dst, const char *in)
len = 0;
- if (sscanf(in+tag_close+1, "%127[^<>]>%n", buffer, &len) >= 1 && len > 0) {
+ if (scantag(in+tag_close+1, buffer, &len) && len > 0) {
const int skip = len + tag_close;
const char *tagname = buffer;
while (*tagname == ' ') {