diff options
author | Kevin Backhouse via RT <security-reports@semmle.com> | 2019-02-06 11:29:22 +0000 |
---|---|---|
committer | Michael Niedermayer <michael@niedermayer.cc> | 2019-03-21 10:42:52 +0100 |
commit | 381fa4a29d38e4ddef2a83876fb8f76e96f45a5d (patch) | |
tree | 565bcaf232c75ebec285dde8e1377b32a7f996f2 /libavcodec | |
parent | c50ba3cb6cec30daa09bb579295ac619498de9ac (diff) | |
download | ffmpeg-381fa4a29d38e4ddef2a83876fb8f76e96f45a5d.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>
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/htmlsubtitles.c | 30 |
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 == ' ') { |