summaryrefslogtreecommitdiffstats
path: root/libass
diff options
context:
space:
mode:
authorOleg Oshmyan <chortos@inbox.lv>2016-12-28 21:14:21 +0200
committerOleg Oshmyan <chortos@inbox.lv>2016-12-29 00:36:38 +0200
commit3ebd1945b44327450fec3fdd164f591921c3f281 (patch)
treed02cd29d84fef3bd3d9f197395226c477c799b05 /libass
parentca0ea14cba8b37eb6af8593d8e4adedbc906389f (diff)
downloadlibass-3ebd1945b44327450fec3fdd164f591921c3f281.tar.bz2
libass-3ebd1945b44327450fec3fdd164f591921c3f281.tar.xz
Fix buffer overread in parse_tag when end points to a space
When parse_tag is invoked recursively to handle the animated tags inside a \t tag, the `end` argument is taken from the `end` field of a struct arg in the enclosing parse_tag. When struct arg is filled by push_arg, this field is always right-trimmed using rskip_spaces. Ultimately, the inner parse_tag invokation sees its `end` argument point not to the ')' or '}' of the \t as it expects but rather to the spaces preceding the ')' or '}'. At this point, when parse_tag calls skip_spaces, which is ignorant of the end pointer, it happily skips over the spaces preceding the ')', moving the pointer past `end`. Subsequent `pointer != end` comparisons in parse_tag fail (as in fact `pointer > end`), and parse_tag thinks it is still inside the substring to be parsed. This is harmless in many cases, but given either of the following inputs, parse_tag reads past the end of the actual buffer that stores the string: {\t(\ } {\t(\ )(} After this commit, parse_tag knows that `end` can point to a sequence of spaces and avoids calling skip_spaces on `end`, thus avoiding the overread. Discovered by OSS-Fuzz. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=194.
Diffstat (limited to 'libass')
-rw-r--r--libass/ass_parse.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/libass/ass_parse.c b/libass/ass_parse.c
index 5698669..0a25c64 100644
--- a/libass/ass_parse.c
+++ b/libass/ass_parse.c
@@ -262,7 +262,8 @@ static int parse_vector_clip(ASS_Renderer *render_priv,
/**
* \brief Parse style override tag.
* \param p string to parse
- * \param end end of string to parse, which must be '}' or ')'
+ * \param end end of string to parse, which must be '}', ')', or the first
+ * of a number of spaces immediately preceding '}' or ')'
* \param pwr multiplier for some tag effects (comes from \t tags)
*/
char *parse_tag(ASS_Renderer *render_priv, char *p, char *end, double pwr)
@@ -272,7 +273,8 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, char *end, double pwr)
if (*p != '\\')
return p;
++p;
- skip_spaces(&p);
+ if (p != end)
+ skip_spaces(&p);
char *q = p;
while (*q != '(' && *q != '\\' && q != end)
@@ -293,7 +295,8 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, char *end, double pwr)
if (*q == '(') {
++q;
while (1) {
- skip_spaces(&q);
+ if (q != end)
+ skip_spaces(&q);
// Split on commas. If there is a backslash, ignore any
// commas following it and lump everything starting from