summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Oshmyan <chortos@inbox.lv>2020-09-19 17:06:48 +0300
committerOleg Oshmyan <chortos@inbox.lv>2020-09-19 17:35:15 +0300
commit7cc111d16586716781e0265b3b96cd6768883cec (patch)
tree5e81539af5ce6b0b97313bebedb1c0f64a590a7a
parent66cef6774386d558e1e39096db926d677dad6882 (diff)
downloadlibass-7cc111d16586716781e0265b3b96cd6768883cec.tar.bz2
libass-7cc111d16586716781e0265b3b96cd6768883cec.tar.xz
Skip fully parsing \t if there is no backslash
The assertion in commit 66cef6774386d558e1e39096db926d677dad6882 fires on the following ASS code: \t(\t(foobar,) (where "foobar" is any nonblank sequence that does not contain a backslash) The outer \t is parsed as having a single argument "\t(foobar," including the comma. The inner \t is parsed as having a single argument "foobar" *excluding* the comma. As a result, in the inner parse_tags, args[cnt].end == end - 1 && nested, and the assert fires. This is because arguments that contain backslashes are parsed differently from arguments that do not. But if the argument to \t contains no backslashes, why bother parsing it at all? It clearly has no override tags and affects nothing. Rather than try to make the assert more clever (and more convoluted), this commit skips parsing the last \t argument if it has no backslash. The assert is now valid. This probably does not significantly affect parsing speed in either direction. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=25796.
-rw-r--r--libass/ass_parse.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/libass/ass_parse.c b/libass/ass_parse.c
index 8188cbc..5c0ea40 100644
--- a/libass/ass_parse.c
+++ b/libass/ass_parse.c
@@ -235,6 +235,7 @@ char *parse_tags(ASS_Renderer *render_priv, char *p, char *end, double pwr,
// Store one extra element to be able to detect excess arguments
struct arg args[MAX_VALID_NARGS + 1];
int nargs = 0;
+ bool has_backslash_arg = false;
for (int i = 0; i <= MAX_VALID_NARGS; ++i)
args[i].start = args[i].end = "";
@@ -261,8 +262,11 @@ char *parse_tags(ASS_Renderer *render_priv, char *p, char *end, double pwr,
} else {
// Swallow the rest of the parenthesized string. This could
// be either a backslash-argument or simply the last argument.
- while (*r != ')' && r != end)
- ++r;
+ if (*r == '\\') {
+ has_backslash_arg = true;
+ while (*r != ')' && r != end)
+ ++r;
+ }
push_arg(args, &nargs, q, r);
q = r;
// The closing parenthesis could be missing.
@@ -634,6 +638,10 @@ char *parse_tags(ASS_Renderer *render_priv, char *p, char *end, double pwr,
pwr = k;
if (cnt < 0 || cnt > 3)
continue;
+ // If there's no backslash in the arguments, there are no
+ // override tags, so it's pointless to try to parse them.
+ if (!has_backslash_arg)
+ continue;
p = args[cnt].start;
if (args[cnt].end < end) {
assert(!nested);