Add remaining-buffer bound check in _array_of_documents_to_buffer

XMLWordPrintableJSON

    • Type: Task
    • Resolution: Unresolved
    • Priority: Unknown
    • None
    • Affects Version/s: None
    • Component/s: None
    • None
    • None
    • None
    • None
    • None
    • None
    • None

      AgentGymLeader has created PR #2872: PYTHON-XXXX Add remaining-buffer bound check in _array_of_documents_to_buffer in mongo-python-driver

      Issue Text:

        1. What

      Adds a single upper-bound check on the per-element embedded-document length
      (`value_length`) in `_cbson_array_of_documents_to_buffer` (in
      `bson/_cbsonmodule.c`), immediately before the `pymongo_buffer_write` /
      `memcpy` call that copies the element into the output buffer.

      ```c
      if (value_length > (uint32_t)(size - position)) {
      PyObject* InvalidBSON = _error("InvalidBSON");
      if (InvalidBSON)

      { PyErr_SetString(InvalidBSON, "invalid array content"); Py_DECREF(InvalidBSON); }

      goto fail;
      }
      ```

        1. Why

      `_cbson_array_of_documents_to_buffer` is the C fast-path used by
      `Collection.find_raw_batches()` and `aggregate_raw_batches()` to convert a
      raw BSON array (from a server `firstBatch`/`nextBatch`) into a flat stream
      of BSON documents.

      The function reads a per-element length `value_length` from the raw bytes and
      then passes it directly to `pymongo_buffer_write(buffer, string + position,
      value_length)`. Before this patch it only checked the lower bound:

      ```c
      if (value_length < BSON_MIN_SIZE)

      { … goto fail; }

      ```

      There was no corresponding upper-bound check that `value_length` does not
      exceed the bytes remaining in the array document (`size - position`). A
      crafted raw-batch reply — from a malicious or compromised server — with an
      inner `value_length` larger than the remaining buffer causes
      `pymongo_buffer_write` → `memcpy` to read past the end of the heap allocation,
      constituting an out-of-bounds read.

      The pure-Python counterpart `get_object_size` in `bson/init_.py` already
      enforces this invariant. The C fast-path dropped it.

      The loop already guarantees `position < size` and
      `(size - position) >= BSON_MIN_SIZE` via the prior guard (line ~3221), so the
      subtraction `size - position` cannot underflow (both variables are `uint32_t`
      and `position < size` is assured).

      This belongs to the same bug class as *CVE-2024-5629* (out-of-bounds read in
      the bson C extension, fixed in 4.6.3) but affects a different function
      (`_cbson_array_of_documents_to_buffer` vs the one patched in 4.6.3).

        1. Change scope
      • *One file changed*: `bson/_cbsonmodule.c`
      • *Nine lines added*: the guard block + one blank separator line
      • No reformatting, no other logic changes

            Assignee:
            Jib Adegunloye
            Reporter:
            TPM Jira Automations Bot
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: