diff options
author | Oneric <oneric@oneric.stub> | 2022-09-29 19:06:15 +0200 |
---|---|---|
committer | Oneric <oneric@oneric.stub> | 2022-09-29 23:33:47 +0200 |
commit | 44f6532daf5eb13cb1aa95f5449a77b5df1dd85b (patch) | |
tree | 9ffc944c3629b57750cac26f0ae568e8673928e9 | |
parent | abd7cd51d86d299b72d5827332352bfdbeb359db (diff) | |
download | libass-44f6532daf5eb13cb1aa95f5449a77b5df1dd85b.tar.bz2 libass-44f6532daf5eb13cb1aa95f5449a77b5df1dd85b.tar.xz |
ass: discard invalid events early
They cannot possibly produce any rendering output,
so there's no benefit in keeping them around. On the
contrary, keeping them around can significantly slow down
processing of fuzzing samples as discovered by OSS-Fuzz.
For its sample, there's one valid event with a large Text entry
(516503 bytes) and 9786 invalid events.
Processing just the one valid events takes a few seconds, which
isn't fast but still bearable and given the large amount of text being
parsed, shaped and rendered not too surprising.
If now the invalid events are kept around, processing the sample still
wasn't finished after 5 minutes. While processing of invalid events ends
early in ass_render_event and they won't create any output themselves,
their time overlaps with the costly, valid event. Meaning this costly
event now get's rendered thousands of times and processing cost is
amplified via just a few bytes being added by the fuzzing engine.
We already do a similar discarding for Styles in process_style().
Unlike the former, process_event_tail() doesn't allocate the new
event itself, so discarding is instead done by its callers.
Fixes: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=47952
-rw-r--r-- | libass/ass.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/libass/ass.c b/libass/ass.c index 5ec8a95..19cc460 100644 --- a/libass/ass.c +++ b/libass/ass.c @@ -822,7 +822,13 @@ static int process_events_line(ASS_Track *track, char *str) return -1; event = track->events + eid; - return process_event_tail(track, event, str, 0); + int ret = process_event_tail(track, event, str, 0); + if (!ret) + return 0; + // If something went wrong, discard the useless Event + ass_free_event(track, eid); + track->n_events--; + return ret; } else { ass_msg(track->library, MSGL_V, "Not understood: '%.30s'", str); } @@ -1125,7 +1131,8 @@ void ass_process_chunk(ASS_Track *track, char *data, int size, NEXT(p, token); event->Layer = atoi(token); - process_event_tail(track, event, p, 3); + if (process_event_tail(track, event, p, 3)) + break; event->Start = timecode; event->Duration = duration; |