-
-
Notifications
You must be signed in to change notification settings - Fork 564
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Quadratic output growth with CommonMark renderer #377
Comments
Not sure why this should be considered a bug. The commonmark being produced is correct (normalized to avoid laziness), it's just that in normalizing to avoid laziness, we have to fill in a 10k * 10k square of |
If you increase the input size, you get:
That's an 80 KB input document taking several seconds and more than 1 GB of RAM to process before finally aborting. This could be considered a DoS vulnerability. At least, this issue makes it impossible to safely process untrusted data with the CommonMark renderer unless you severely limit the input size. |
I agree, but...It's just a fact that commonmark normalization can increase size like that. I guess the only solution I can think of is to abort or truncate when block quote nesting passes some reasonable limit. (Maybe in the parser, maybe in the writer?) |
Maybe the CommonMark renderer can switch to lazy continuations after a certain nesting level? Another idea is to stop rendering without aborting if the output reaches a certain size. |
There's a request to fix this on https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=30784 |
The test case doesn't trigger a timeout. But the output buffer of the renderer also grows quadratically, so the issue manifests when the buffer grows beyond 1 GB and our strbuf code aborts. Basically an OOM condition. If you want to reproduce the test case from OSS-Fuzz, note that these are not Markdown files but contain a bit of header data for the fuzzer. It often works to just pipe them into cmark, but in general they should be run through the fuzzer binary to reproduce the issue reliably. Anyway, I'm pretty sure I found root cause. The test cases generated from fuzzing aren't fun to work with, so I wouldn't waste more time on that. |
Got it.
I have a feeling this would be a bit complex to implement, but I haven't looked in detail. It would affect both lists and block quotes.
How were you thinking this would be implemented? Would adding to a strbuf at a certain size just be made a no-op? Ideally, we'd exit cleanly with an error status. What would it take to do this (and, would the fuzzer accept this)? |
The cmark_render_* functions may now return NULL instead of aborting if the output exceeds the maximum internal buffer size. This fix isn't bullet-proof but should help with smaller documents that trigger quadratic output growth with the Commonmark renderer. See commonmark#377.
Yes, lists can also trigger quadratic output growth:
This would just hide the error condition, so I don't think it's a good idea.
I think the easiest solution to add a check in each iteration of the main loop in This approach isn't bullet-proof when handling really large documents but should stop the fuzzer from aborting. Tentative fix: nwellnhof@b7e2451 |
So the idea is to implement a very primitive kind of error handling: a null return value means "an error occurred"? |
Yes, that's the simplest fix I could come up with. But it turns out that switching to lazy continuation lines isn't too hard: nwellnhof@86bbd43 |
Found by OSS-Fuzz: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=30784
Reduced test case:
The text was updated successfully, but these errors were encountered: