mirror of
https://github.com/nlohmann/json.git
synced 2026-09-07 16:57:59 +00:00
An embedded document (record type 0x03) or array (0x04) was read by calling back into the document reader, which read its element list, which called the element reader again for the next embedded one. The native call stack therefore grew with the nesting depth of the input, and about seven bytes buy a level, so a document of a few hundred kilobytes crashes the process (#5104). This is the last of the four binary formats to still do that. Apply the same shape as the other three: open_bson_document() reads the size prefix and opens the document, parse_bson_element_internal() calls it for both record types instead of recursing, and parse_bson_internal() loops over the element list of whichever document is innermost, closing it when its terminator is reached and resuming the one below. check_bson_document_size() is unchanged, and so is when it runs: a document is still measured from the byte before its size prefix to the byte after its terminator, and still reported before the end event. The frame carries those two values, which is what a per-document check needs once the reads are interleaved rather than nested. Nothing else about the element reader changes. unit-bson passes unchanged. Round trips through to_bson of nested objects, arrays, arrays of objects and mixed nesting are identical to the previous commit, as are the errors for a truncated document, an unsupported record type, a negative size and a size that does not match, including their byte offsets. A 30,000-level document built by to_bson is now read to completion where it used to crash. Note for sequencing: #5185 changes parse_bson_internal(), the element list and the array reader, which are the functions this commit restructures. It should land first; this commit then keeps its checks and moves them onto the loop. Signed-off-by: Niels Lohmann <mail@nlohmann.me>