diff options
author | Oleg Oshmyan <chortos@inbox.lv> | 2018-01-04 02:42:09 +0200 |
---|---|---|
committer | Oleg Oshmyan <chortos@inbox.lv> | 2018-01-08 22:20:13 +0200 |
commit | 6835731c2fe4164a0c50bc91d12c43b2a2b4e799 (patch) | |
tree | 05942ee78618aad94143c63fba57c3e5bb6d4773 | |
parent | 691b422247552a86e9d3310c4f1ea096dc52a3f2 (diff) | |
download | libass-6835731c2fe4164a0c50bc91d12c43b2a2b4e799.tar.bz2 libass-6835731c2fe4164a0c50bc91d12c43b2a2b4e799.tar.xz |
parse_tags: don't recurse for nested \t()
This fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=4892
(stack overflow on deeply nested \t()).
This is possible because parentheses do not nest and the first ')'
terminates the whole tag. Thus something like \t(\t(\t(\t(\t() can be
read in a simple loop with no recursion required. Recursion is also
not required if the ')' is missing entirely and the outermost \t(...
never ends.
See https://github.com/libass/libass/pull/296 for more backstory.
-rw-r--r-- | Changelog | 3 | ||||
-rw-r--r-- | libass/ass_parse.c | 12 |
2 files changed, 14 insertions, 1 deletions
@@ -1,3 +1,6 @@ +libass (unreleased) + * Fix stack overflow on deeply nested \t tags + libass (0.14.0) * Brand new, faster and better outline stroker (replaces FreeType stroker) * Remove option to use the FreeType rasterizer diff --git a/libass/ass_parse.c b/libass/ass_parse.c index b20ef66..652ffa9 100644 --- a/libass/ass_parse.c +++ b/libass/ass_parse.c @@ -650,7 +650,17 @@ char *parse_tags(ASS_Renderer *render_priv, char *p, char *end, double pwr) k = pow(((double) (t - t1)) / delta_t, accel); } p = args[cnt].start; - p = parse_tags(render_priv, p, args[cnt].end, k); // maybe k*pwr ? no, specs forbid nested \t's + if (args[cnt].end < end) { + p = parse_tags(render_priv, p, args[cnt].end, k); + } else { + assert(q == end); + // No other tags can possibly follow this \t tag, + // so we don't need to restore pwr after parsing \t. + // The recursive call is now essentially a tail call, + // so optimize it away. + pwr = k; + q = p; + } } else if (complex_tag("clip")) { if (nargs == 4) { int x0, y0, x1, y1; |