Skip to content

check all BSON reads and add an EOF check for booleans - #5332

Merged
nlohmann merged 1 commit into
nlohmann:developfrom
xevrion:fix/bson-reader-unchecked-reads
Jul 30, 2026
Merged

nlohmann merged 1 commit into
nlohmann:developfrom
xevrion:fix/bson-reader-unchecked-reads

Conversation

@xevrion

@xevrion xevrion commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Fixes #5309.

The BSON reader discarded the return values of three get_number() calls (the document size in parse_bson_internal and parse_bson_array, and the subtype in get_bson_binary) and read the boolean value with a bare get() that has no EOF check. As the issue notes, no truncated input escapes as an accepted document, but the failures surface downstream instead of at the failed read: a boolean truncated at EOF emits boolean(true) to the SAX handler before the element-list check reports the error, and a binary truncated at the subtype byte calls set_subtype() and get_binary() after its own parse error has already fired.

The two document-size reads now short-circuit with a plain if (!...) rather than JSON_HEDLEY_UNLIKELY, because that macro takes a single argument and the comma in get_number<std::int32_t, true> would be parsed as a macro argument separator; this matches the existing unwrapped call sites for the string, binary, and int32 element types. The subtype read keeps the JSON_HEDLEY_UNLIKELY guard, and the boolean is routed through get_number<std::uint8_t> so it gets the same EOF handling as every other element type.

Error messages for these truncated inputs now name the failed read (for example "BSON number" at byte 8 instead of "BSON element list" at byte 9). The existing "Incomplete BSON Input 2" assertion is unaffected because that input fails earlier, in get_bson_cstring. Valid input parses identically.

  • The changes are described in detail, both the what and why.
  • If applicable, an existing issue is referenced.
  • The Code coverage remained at 100%. A test case for every new line of code.
  • If applicable, the documentation is updated.
  • The source code is amalgamated by running make amalgamate.

Two new sections, "Incomplete BSON Input 5" and "Incomplete BSON Input 6", cover the boolean and subtype paths; the document-size branches are exercised by the existing "Incomplete BSON Input 4" and the empty-input cases. No documentation change is needed.

Signed-off-by: Yash Bavadiya <krbavadiya11@gmail.com>
@xevrion
xevrion force-pushed the fix/bson-reader-unchecked-reads branch from 5a7788d to 40fc7d9 Compare July 30, 2026 06:55

@nlohmann nlohmann left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

@nlohmann nlohmann added this to the Release 3.13.0 milestone Jul 30, 2026
@nlohmann
nlohmann merged commit dd24e2d into nlohmann:develop Jul 30, 2026
156 checks passed
@nlohmann

Copy link
Copy Markdown
Owner

Thanks!

nlohmann added a commit that referenced this pull request Aug 4, 2026
…ple reference types (#5359)

* 📝 Document exceptions newly thrown by the binary-format hardening

A round of binary-format input validation (#5274, #5284, #5287, #5332)
added new failure modes without updating exceptions.md, and left two
descriptions factually narrower than the code:

- parse_error.110 said "CBOR or MessagePack"; BSON and UBJSON also
  throw it. Generalized, and added the BSON EOF example (#5332).
- parse_error.112: added the BSON document-size mismatch example
  (#5287).
- parse_error.113 said "while parsing a map key", but its own existing
  UBJSON char example already contradicted that. Broadened to cover
  invalid length specifications, and added the negative-string-length
  example (#5284).
- out_of_range.408 said "of an UBJSON array or object"; CBOR now throws
  it too (#5274). Generalized and added both CBOR examples.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* 📝 Correct which types may be referenced in a tuple extraction

The note added in #5271 said a referenced type must be one the library
stores "or an arithmetic type it can convert to/from". The parenthetical
is wrong: is_compatible_reference_type requires an exact match against
the stored types, so std::tuple<int&> is rejected by static_assert even
though int converts fine as a value. Only the value case is permissive.

Spell out the eight admissible types, give the int& counter-example, and
separate the reference restriction from by-value conversion.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
sahilkamate03 pushed a commit to fork-of-sahil/json that referenced this pull request Aug 7, 2026
Signed-off-by: Yash Bavadiya <krbavadiya11@gmail.com>
sahilkamate03 pushed a commit to fork-of-sahil/json that referenced this pull request Aug 7, 2026
…ple reference types (nlohmann#5359)

* 📝 Document exceptions newly thrown by the binary-format hardening

A round of binary-format input validation (nlohmann#5274, nlohmann#5284, nlohmann#5287, nlohmann#5332)
added new failure modes without updating exceptions.md, and left two
descriptions factually narrower than the code:

- parse_error.110 said "CBOR or MessagePack"; BSON and UBJSON also
  throw it. Generalized, and added the BSON EOF example (nlohmann#5332).
- parse_error.112: added the BSON document-size mismatch example
  (nlohmann#5287).
- parse_error.113 said "while parsing a map key", but its own existing
  UBJSON char example already contradicted that. Broadened to cover
  invalid length specifications, and added the negative-string-length
  example (nlohmann#5284).
- out_of_range.408 said "of an UBJSON array or object"; CBOR now throws
  it too (nlohmann#5274). Generalized and added both CBOR examples.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* 📝 Correct which types may be referenced in a tuple extraction

The note added in nlohmann#5271 said a referenced type must be one the library
stores "or an arithmetic type it can convert to/from". The parenthetical
is wrong: is_compatible_reference_type requires an exact match against
the stored types, so std::tuple<int&> is rejected by static_assert even
though int converts fine as a value. Only the value case is permissive.

Spell out the eight admissible types, give the int& counter-example, and
separate the reference restriction from by-value conversion.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
sahilkamate03 pushed a commit to fork-of-sahil/json that referenced this pull request Aug 7, 2026
Signed-off-by: Yash Bavadiya <krbavadiya11@gmail.com>
Signed-off-by: sahilkamate03 <45514385+sahilkamate03@users.noreply.github.com>
sahilkamate03 pushed a commit to fork-of-sahil/json that referenced this pull request Aug 7, 2026
…ple reference types (nlohmann#5359)

* 📝 Document exceptions newly thrown by the binary-format hardening

A round of binary-format input validation (nlohmann#5274, nlohmann#5284, nlohmann#5287, nlohmann#5332)
added new failure modes without updating exceptions.md, and left two
descriptions factually narrower than the code:

- parse_error.110 said "CBOR or MessagePack"; BSON and UBJSON also
  throw it. Generalized, and added the BSON EOF example (nlohmann#5332).
- parse_error.112: added the BSON document-size mismatch example
  (nlohmann#5287).
- parse_error.113 said "while parsing a map key", but its own existing
  UBJSON char example already contradicted that. Broadened to cover
  invalid length specifications, and added the negative-string-length
  example (nlohmann#5284).
- out_of_range.408 said "of an UBJSON array or object"; CBOR now throws
  it too (nlohmann#5274). Generalized and added both CBOR examples.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* 📝 Correct which types may be referenced in a tuple extraction

The note added in nlohmann#5271 said a referenced type must be one the library
stores "or an arithmetic type it can convert to/from". The parenthetical
is wrong: is_compatible_reference_type requires an exact match against
the stored types, so std::tuple<int&> is rejected by static_assert even
though int converts fine as a value. Only the value case is permissive.

Spell out the eight admissible types, give the int& counter-example, and
separate the reference restriction from by-value conversion.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
Signed-off-by: sahilkamate03 <45514385+sahilkamate03@users.noreply.github.com>
jwnimmer-tri pushed a commit to jwnimmer-tri/json that referenced this pull request Sep 21, 2026
Signed-off-by: Yash Bavadiya <krbavadiya11@gmail.com>
jwnimmer-tri pushed a commit to jwnimmer-tri/json that referenced this pull request Sep 21, 2026
…ple reference types (nlohmann#5359)

* 📝 Document exceptions newly thrown by the binary-format hardening

A round of binary-format input validation (nlohmann#5274, nlohmann#5284, nlohmann#5287, nlohmann#5332)
added new failure modes without updating exceptions.md, and left two
descriptions factually narrower than the code:

- parse_error.110 said "CBOR or MessagePack"; BSON and UBJSON also
  throw it. Generalized, and added the BSON EOF example (nlohmann#5332).
- parse_error.112: added the BSON document-size mismatch example
  (nlohmann#5287).
- parse_error.113 said "while parsing a map key", but its own existing
  UBJSON char example already contradicted that. Broadened to cover
  invalid length specifications, and added the negative-string-length
  example (nlohmann#5284).
- out_of_range.408 said "of an UBJSON array or object"; CBOR now throws
  it too (nlohmann#5274). Generalized and added both CBOR examples.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* 📝 Correct which types may be referenced in a tuple extraction

The note added in nlohmann#5271 said a referenced type must be one the library
stores "or an arithmetic type it can convert to/from". The parenthetical
is wrong: is_compatible_reference_type requires an exact match against
the stored types, so std::tuple<int&> is rejected by static_assert even
though int converts fine as a value. Only the value case is permissive.

Spell out the eight admissible types, give the int& counter-example, and
separate the reference restriction from by-value conversion.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BSON reader ignores get_number() return values and skips an EOF check for booleans

2 participants