new file mode 100644
@@ -0,0 +1,79 @@
+From b5a36ccbdb97298fbf9b5b5767affe92c534461f Mon Sep 17 00:00:00 2001
+From: Steven Silvester <steve.silvester@mongodb.com>
+Date: Tue, 13 Oct 2026 09:30:43 -0500
+Subject: [PATCH] PYTHON-6111 C extension accepts BSON documents where element
+ data overlaps the document terminator (#3113)
+
+CVE: CVE-2026-106435
+Upstream-Status: Backport [https://github.com/mongodb/mongo-python-driver/commit/b5a36ccbdb97298fbf9b5b5767affe92c534461f]
+
+Backport Changes:
+- Omitted doc/changelog.rst file changes.
+
+Signed-off-by: Yogita Urade <yurade@cisco.com>
+---
+ bson/_cbsonmodule.c | 7 ++++++-
+ test/test_bson.py | 34 ++++++++++++++++++++++++++++++++++
+ 2 files changed, 40 insertions(+), 1 deletion(-)
+
+diff --git a/bson/_cbsonmodule.c b/bson/_cbsonmodule.c
+--- a/bson/_cbsonmodule.c
++++ b/bson/_cbsonmodule.c
+@@ -2102,5 +2102,8 @@
+ case 8:
+ {
++ if (max < 1) {
++ goto invalid;
++ }
+ char boolean_raw = buffer[(*position)++];
+ if (0 == boolean_raw) {
+ value = Py_False;
+@@ -2290,7 +2290,9 @@
+ *position += (unsigned)pattern_length + 1;
+ start += pattern_length + 1;
+- const char* flags_nul = memchr(start, 0, max - pattern_length);
++ /* PYTHON-6111: account for the pattern NUL consumed above so
++ * the flags terminator cannot overlap the document terminator. */
++ const char* flags_nul = memchr(start, 0, max - pattern_length - 1);
+ if (!flags_nul) {
+ Py_DECREF(pattern);
+ goto invalid;
+ }
+diff --git a/test/test_bson.py b/test/test_bson.py
+--- a/test/test_bson.py
++++ b/test/test_bson.py
+@@ -438,0 +439,34 @@ class TestBSON(unittest.TestCase):
++ def test_element_overlaps_document_terminator(self):
++ # PYTHON-6111: an element whose value would consume the document
++ # terminator byte must be rejected, matching the pure-Python decoder.
++ bad_bsons = [
++ # Boolean value byte is the document terminator.
++ ("boolean value", b"\x08\x00\x00\x00\x08a\x00\x00"),
++ # Regex pattern terminator is the document terminator.
++ ("regex pattern", b"\x08\x00\x00\x00\x0ba\x00\x00"),
++ # Regex flags terminator is the document terminator.
++ ("regex flags", b"\x0a\x00\x00\x00\x0ba\x00b\x00\x00"),
++ ]
++ for description, data in bad_bsons:
++ with self.subTest(description, bad_bson=data):
++ self.assertFalse(is_valid(data))
++ with self.assertRaises(InvalidBSON):
++ decode(data)
++ with self.assertRaises(InvalidBSON):
++ decode(bytearray(data))
++ with self.assertRaises(InvalidBSON):
++ decode(memoryview(data))
++ with self.assertRaises(InvalidBSON):
++ decode(array.array("B", data))
++ with self.assertRaises(InvalidBSON):
++ list(decode_iter(data))
++ with self.assertRaises(InvalidBSON):
++ decode_all(data)
++ with mmap.mmap(-1, len(data)) as mm:
++ mm.write(data)
++ mm.seek(0)
++ with self.assertRaises(InvalidBSON):
++ decode(mm)
++ with self.assertRaises(InvalidBSON):
++ decode_all(mm)
++
new file mode 100644
@@ -0,0 +1,134 @@
+From bb8d4e195275e75bd94ebeffb53cc747d357fcf4 Mon Sep 17 00:00:00 2001
+From: Jeffrey 'Alex' Clark <aclark@aclark.net>
+Date: Thu, 8 Oct 2026 14:45:52 -0400
+Subject: [PATCH] PYTHON-6110 Bound Regex element scans to the remaining
+ document bytes (#3109)
+
+Co-authored-by: Steven Silvester <steve.silvester@mongodb.com>
+
+CVE: CVE-2026-106435
+Upstream-Status: Backport [https://github.com/mongodb/mongo-python-driver/commit/bb8d4e195275e75bd94ebeffb53cc747d357fcf4]
+
+Backport Changes:
+- Added the `struct` import used to update the malformed-regex test's BSON
+ length prefix.
+- Adapted the C hunk to 4.6.3: the new flags-NUL failure path uses the
+ `Py_DECREF(pattern); goto invalid;` cleanup, and the existing flags-length
+ size/overflow check remains after the bounded length is computed. Upstream
+ also removes the `max < pattern_length + flags_length` check.
+
+Signed-off-by: Yogita Urade <yurade@cisco.com>
+---
+ bson/_cbsonmodule.c | 25 ++++++++++++++++++--------
+ test/test_bson.py | 46 +++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 63 insertions(+), 8 deletions(-)
+
+diff --git a/bson/_cbsonmodule.c b/bson/_cbsonmodule.c
+index da86cd8..6868308 100644
+--- a/bson/_cbsonmodule.c
++++ b/bson/_cbsonmodule.c
+@@ -2270,18 +2270,31 @@ static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer,
+ PyObject* pattern;
+ int flags;
+ size_t flags_length, i;
+- size_t pattern_length = strlen(buffer + *position);
+- if (pattern_length > BSON_MAX_SIZE || max < pattern_length) {
++ /* PYTHON-6110: Search for each NUL within the bytes remaining
++ * in the document rather than scanning the buffer. */
++ const char* start = buffer + *position;
++ const char* pattern_nul = memchr(start, 0, max);
++ if (!pattern_nul) {
++ goto invalid;
++ }
++ size_t pattern_length = (size_t)(pattern_nul - start);
++ if (pattern_length > BSON_MAX_SIZE) {
+ goto invalid;
+ }
+ pattern = PyUnicode_DecodeUTF8(
+- buffer + *position, pattern_length,
++ start, pattern_length,
+ options->unicode_decode_error_handler);
+ if (!pattern) {
+ goto invalid;
+ }
+ *position += (unsigned)pattern_length + 1;
+- flags_length = strlen(buffer + *position);
++ start += pattern_length + 1;
++ const char* flags_nul = memchr(start, 0, max - pattern_length);
++ if (!flags_nul) {
++ Py_DECREF(pattern);
++ goto invalid;
++ }
++ flags_length = (size_t)(flags_nul - start);
+ if (flags_length > BSON_MAX_SIZE ||
+ (BSON_MAX_SIZE - pattern_length) < flags_length) {
+ Py_DECREF(pattern);
+@@ -2288,10 +2301,6 @@
+ goto invalid;
+ }
+- if (max < pattern_length + flags_length) {
+- Py_DECREF(pattern);
+- goto invalid;
+- }
+ flags = 0;
+ for (i = 0; i < flags_length; i++) {
+ if (buffer[*position + i] == 'i') {
+ flags |= 2;
+diff --git a/test/test_bson.py b/test/test_bson.py
+index 749c63b..483facf 100644
+--- a/test/test_bson.py
++++ b/test/test_bson.py
+@@ -23,6 +23,7 @@ import mmap
+ import os
+ import pickle
+ import re
++import struct
+ import sys
+ import tempfile
+ import uuid
+@@ -392,0 +393,45 @@ class TestBSON(unittest.TestCase):
++ def test_malformed_regex(self):
++ # PYTHON-6110: decoding a malformed Regex element must raise
++ # InvalidBSON on every accepted buffer type.
++ malformed = []
++ for pattern in ("", "x", "xx"):
++ doc = bytearray(encode({"a": Regex(pattern, "")}))
++ # Drop the trailing flags NUL and document EOO bytes, leaving
++ # the flags string unterminated after the pattern's NUL.
++ del doc[-2:]
++ # Keep the length prefix consistent with the shorter document.
++ doc[:4] = struct.pack("<i", len(doc))
++ malformed.append(bytes(doc))
++ for data in malformed:
++ with self.assertRaises(InvalidBSON):
++ decode(data)
++ with self.assertRaises(InvalidBSON):
++ decode(bytearray(data))
++ with self.assertRaises(InvalidBSON):
++ decode(memoryview(data))
++ with self.assertRaises(InvalidBSON):
++ decode(array.array("B", data))
++ with self.assertRaises(InvalidBSON):
++ list(decode_iter(data))
++ with self.assertRaises(InvalidBSON):
++ decode_all(data)
++ with mmap.mmap(-1, len(data)) as mm:
++ mm.write(data)
++ mm.seek(0)
++ with self.assertRaises(InvalidBSON):
++ decode(mm)
++ with self.assertRaises(InvalidBSON):
++ decode_all(mm)
++
++ def test_regex_empty_flags(self):
++ # PYTHON-6110: a valid regex with an empty flags string must
++ # continue to decode.
++ valid = encode({"a": Regex("b", "")})
++ expected = {"a": Regex("b", 0)}
++ self.assertEqual(decode(valid), expected)
++ with mmap.mmap(-1, len(valid)) as mm:
++ mm.write(valid)
++ mm.seek(0)
++ self.assertEqual(decode(mm), expected)
++ self.assertEqual(decode_all(mm), [expected])
++
@@ -9,6 +9,8 @@ LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://LICENSE;md5=86d3f3a95c324c9479bd8986968f4327"
SRC_URI = "file://CVE-2026-88029.patch \
+ file://CVE-2026-106435.patch \
+ file://CVE-2026-106435-regression.patch \
"
SRC_URI[sha256sum] = "400074090b9a631f120b42c61b222fd743490c133a5d2f99c0208cefcccc964e"
This patch applies the upstream fix as referenced in [3], using the commit shown in [1] and regression commit from [2]. Follow up the PYTHON-6110 CVE fix: its regex flags scan leaves a one-byte boundary error after consuming the pattern terminator. Apply PYTHON-6111's correction and terminator-overlap regression test. [1] https://github.com/mongodb/mongo-python-driver/commit/bb8d4e195275e75bd94ebeffb53cc747d357fcf4 [2] https://github.com/mongodb/mongo-python-driver/commit/b5a36ccbdb97298fbf9b5b5767affe92c534461f [3] https://jira.mongodb.org/browse/PYTHON-6110 [4] https://jira.mongodb.org/browse/PYTHON-6111 Signed-off-by: Yogita Urade <yurade@cisco.com> --- .../CVE-2026-106435-regression.patch | 79 +++++++++++ .../python3-pymongo/CVE-2026-106435.patch | 134 ++++++++++++++++++ .../python/python3-pymongo_4.6.3.bb | 2 + 3 files changed, 215 insertions(+) create mode 100644 meta-python/recipes-devtools/python/python3-pymongo/CVE-2026-106435-regression.patch create mode 100644 meta-python/recipes-devtools/python/python3-pymongo/CVE-2026-106435.patch