Skip to content

BSON reader accepts input the spec forbids (array keys, boolean bytes, subtype 0x02) without documenting the leniency #5310

Description

@nlohmann

Description

Three reader behaviours deviate from bsonspec.org and are not documented on the BSON feature page. Leniency is a defensible choice here, but it should be an explicit one — the docs currently imply spec conformance.

1. Array element keys are not validated. parse_bson_element_list(is_array=true) (include/nlohmann/detail/input/binary_reader.hpp:392) reads each key and discards it. The spec requires array keys to be the decimal strings "0", "1", … in order.

2. Boolean accepts any non-zero byte. case 0x08 (binary_reader.hpp:343) does sax->boolean(get() != 0). The spec permits only \x00 and \x01.

3. Binary subtype 0x02 is passed through raw. Subtype 0x02 ("Binary (old)") carries its own inner int32 length prefix per spec; the reader returns those four bytes as part of the payload.

Reproduction steps / Minimal code example

#include <nlohmann/json.hpp>
#include <iostream>
using json = nlohmann::json;

int main()
{
    // 1. array with keys "x" and "9" instead of "0" and "1"
    std::cout << json::from_bson(std::vector<std::uint8_t>{
        0x1a, 0x00, 0x00, 0x00,
        0x04, 'a', 0x00,
        0x12, 0x00, 0x00, 0x00,
        0x10, 'x', 0x00, 0x01, 0x00, 0x00, 0x00,
        0x10, '9', 0x00, 0x02, 0x00, 0x00, 0x00,
        0x00,
        0x00
    }).dump() << '\n';

    // 2. boolean encoded as 0x02
    std::cout << json::from_bson(std::vector<std::uint8_t>{
        0x0a, 0x00, 0x00, 0x00,
        0x08, 'a', 0x00, 0x02,
        0x00
    }).dump() << '\n';

    // 3. binary subtype 0x02 with inner length prefix
    std::cout << json::from_bson(std::vector<std::uint8_t>{
        0x15, 0x00, 0x00, 0x00,
        0x05, 'a', 0x00,
        0x08, 0x00, 0x00, 0x00,
        0x02,
        0x04, 0x00, 0x00, 0x00,
        0x01, 0x02, 0x03, 0x04,
        0x00
    }).dump() << '\n';
}

Expected vs. actual results

Actual:

{"a":[1,2]}
{"a":true}
{"a":{"bytes":[4,0,0,0,1,2,3,4],"subtype":2}}

Expected: either a parse_error for (1) and (2) and the inner prefix stripped for (3), or — if the lenient behaviour is intentional — an explicit statement of it on the BSON feature page so users relying on from_bson() for validation are not misled.

Compiler and operating system

g++ 13.3.0 (Ubuntu 24.04), -std=c++11 -O2, Linux x86-64

Library version

develop @ 06ac77f

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions