Repository navigation
Conversation
buf->size + add is computed as int32_t, so a chunk near 2 GiB wraps to a negative target size, cmark_strbuf_grow returns without growing and cmark_strbuf_put writes past the buffer. A line of 2 GiB or more also truncates chunk_len in S_parser_feed, which then moves buffer backwards and reads out of bounds. Take the existing abort path for both.
|
@nwellnhof can you have a look? |
|
Maybe it's better to make the strbuf functions take a To find such issues, the clang option |
|
I'd have no objections to that. |
cmark_strbuf_grow, cmark_strbuf_set and cmark_strbuf_put now take a ptrdiff_t length, so pointer differences can be passed without truncation. The buffer size is still limited by the check in cmark_strbuf_grow. S_parser_feed, S_process_line and cmark_utf8proc_check carry the line length as ptrdiff_t too, which makes the separate long-line abort in S_parser_feed unnecessary. Also build with -Wshorten-64-to-32 on clang.
|
Switched cmark_strbuf_grow/set/put to ptrdiff_t lengths. I went with ptrdiff_t over size_t so the existing I also added -Wshorten-64-to-32 for Clang/AppleClang in cmark_add_compile_options. The clang build is warning-free with it, and the tests pass. The three 2 GiB cases from the description (NUL in the line, two feeds, one long line) all abort in cmark_strbuf_grow under ASan instead of overflowing. The only behaviour change worth a look is in utf8proc_valid, which now gets a ptrdiff_t length. It only compares that length against the 1-4 byte sequence length, so the cast back to int on the short-input path is safe. |
S_strbuf_grow_by adds buf->size and add as int32_t, so a chunk near 2 GiB wraps the target size negative, cmark_strbuf_grow returns without growing (its assert is compiled out in Release) and cmark_strbuf_put writes past the buffer. cmark_markdown_to_html hits this on
a, a NUL byte and 0x7fffffff bytes with no newline, which ASan reports as a heap-buffer-overflow write of 2147483647 bytes, and a single line of 2 GiB or more makes chunk_len negative in S_parser_feed, which moves buffer backwards and reads out of bounds. Both now take the abort cmark_strbuf_grow already uses for oversized buffers, so please check that aborting is the behaviour you want here; there is no test because the trigger needs a 2 GiB buffer and ends in abort().