Skip to content

fix size overflow in S_strbuf_grow_by and S_parser_feed - #654

Open
zayeem06 wants to merge 1 commit into
commonmark:masterfrom
zayeem06:strbuf-size-overflow
Open

zayeem06 wants to merge 1 commit into
commonmark:masterfrom
zayeem06:strbuf-size-overflow

Conversation

@zayeem06

@zayeem06 zayeem06 commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

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().

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.
@jgm

jgm commented Nov 2, 2026

Copy link
Copy Markdown
Member

@nwellnhof can you have a look?

@nwellnhof

Copy link
Copy Markdown
Contributor

Maybe it's better to make the strbuf functions take a size_t or ptrdiff_t length? The buffer size would still be checked against INT32_MAX, but this would make code involving pointer arithmetic more safe, for example allowing cmark_strbuf_put(buf, data, end - data).

To find such issues, the clang option -Wshorten-64-to-32 is a great help. Interestingly, it only spots the code in question:

src/blocks.c:618:22: warning: implicit conversion loses integer precision: 'long' to 'bufsize_t' (aka 'int') [-Wshorten-64-to-32]
  618 |     chunk_len = (eol - buffer);
      |               ~  ~~~~^~~~~~~~
1 warning generated.

@jgm

jgm commented Nov 6, 2026

Copy link
Copy Markdown
Member

I'd have no objections to that.
And maybe we could add that flag to the build flags for clang?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants