Fix out-of-bounds read in dump() for large indentation widths#5273
Fix out-of-bounds read in dump() for large indentation widths#5273Angadi56 wants to merge 2 commits into
Conversation
Signed-off-by: Angadi Yashaswini <angadi@digiscrypt.com>
| // variable to hold indentation for recursive calls | ||
| const auto new_indent = current_indent + indent_step; | ||
| if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) | ||
| while (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) |
There was a problem hiding this comment.
Maybe instead go in a single step instead of growing over multiple calls.
indent_string.resize((std::max)(indent_string.size() * 2, new_indent));
There was a problem hiding this comment.
Good call, that's cleaner. Switched to the single resize with (std::max)(size*2, new_indent) so it still doubles for amortized growth but jumps straight to the needed width when one doubling wouldn't cover it. Had to cast new_indent to string_t::size_type so max deduces one type. Pushed and re-amalgamated.
Signed-off-by: Angadi Yashaswini <angadi@digiscrypt.com>
|
Thanks for the report and fix! This looks like a duplicate of #5186, which I opened back in May and is still open. Both fix the same underlying bug in #5186 additionally fixes a second bug where the resize used a literal space instead of the configured I'll consolidate on #5186 (possibly folding in the Generated by Claude Code |
When pretty-printing, the serializer keeps one reusable
indent_stringbuffer and widens it on demand before writing a run of indentation. The width it needs iscurrent_indent + indent_step, which grows with nesting depth and with the indent argument given todump(). The buffer only doubled once behind anif, so when the required width was more than twice the current size the buffer stayed too short and the followingwrite_characters(indent_string.c_str(), new_indent)ran off its end, copying whatever heap bytes followed into the output. It reproduces under AddressSanitizer withjson j = {{"a", 1}}; j.dump(1100);, which reads 1100 bytes out of a 1040-byte allocation. Looping the doubling until the buffer actually holdsnew_indentcloses it while keeping the same amortized growth. I applied it to the three pretty-print branches (object, array, binary) that share the pattern, and added a serialization test that checks the emitted indentation is the expected run of spaces at a width past the first doubling.make amalgamate.