From 5c6fc5833cc28a545f619fc256c106cb63534296 Mon Sep 17 00:00:00 2001 From: Navjot Singh Date: Thu, 12 Sep 2024 15:42:21 +0100 Subject: [PATCH 1/4] Updated Invalid Document error message to have doc --- bson/__init__.py | 5 ++++- bson/_cbsonmodule.c | 39 +++++++++++++++++++++++++++++++++++++++ test/test_bson.py | 16 ++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/bson/__init__.py b/bson/__init__.py index e8ac7c4441..5b4c470161 100644 --- a/bson/__init__.py +++ b/bson/__init__.py @@ -1006,7 +1006,10 @@ def _dict_to_bson( elements.append(_name_value_to_bson(b"_id\x00", doc["_id"], check_keys, opts)) for key, value in doc.items(): if not top_level or key != "_id": - elements.append(_element_to_bson(key, value, check_keys, opts)) + try: + elements.append(_element_to_bson(key, value, check_keys, opts)) + except InvalidDocument as err: + raise InvalidDocument("Invalid document {} | {}".format(doc,err)) from err except AttributeError: raise TypeError(f"encoder expected a mapping type but got: {doc!r}") from None diff --git a/bson/_cbsonmodule.c b/bson/_cbsonmodule.c index 3e9d5ecc26..ec010d0775 100644 --- a/bson/_cbsonmodule.c +++ b/bson/_cbsonmodule.c @@ -1743,6 +1743,45 @@ int write_dict(PyObject* self, buffer_t buffer, while (PyDict_Next(dict, &pos, &key, &value)) { if (!decode_and_write_pair(self, buffer, key, value, check_keys, options, top_level)) { + if (PyErr_Occurred()) { + PyObject *etype, *evalue, *etrace; + PyErr_Fetch(&etype, &evalue, &etrace); + PyObject *InvalidDocument = _error("InvalidDocument"); + + if (PyErr_GivenExceptionMatches(etype, InvalidDocument)) { + + if (InvalidDocument) { + Py_DECREF(etype); + etype = InvalidDocument; + + if (evalue) { + PyObject *msg = PyObject_Str(evalue); + Py_DECREF(evalue); + + if (msg) { + // Prepend doc to the existing message + PyObject *dict_str = PyObject_Str(dict); + PyObject *new_msg = PyUnicode_FromFormat("Invalid document %s | %s", PyUnicode_AsUTF8(dict_str), PyUnicode_AsUTF8(msg)); + Py_DECREF(dict_str); + + if (new_msg) { + evalue = new_msg; + Py_DECREF(new_msg); + } + else{ + evalue = msg; + } + + Py_DECREF(msg); + + } + } + PyErr_NormalizeException(&etype, &evalue, &etrace); + } + } + PyErr_Restore(etype, evalue, etrace); + Py_DECREF(InvalidDocument); + } return 0; } } diff --git a/test/test_bson.py b/test/test_bson.py index a0190ef2d8..6ac515e45c 100644 --- a/test/test_bson.py +++ b/test/test_bson.py @@ -1000,6 +1000,22 @@ def __repr__(self): ): encode({"t": Wrapper(1)}) + def test_doc_in_invalid_document_error_message(self): + + class Wrapper: + def __init__(self, val): + self.val = val + + def __repr__(self): + return repr(self.val) + + self.assertEqual("1", repr(Wrapper(1))) + doc = {"t": Wrapper(1)} + with self.assertRaisesRegex( + InvalidDocument, "Invalid document {}".format(doc) + ): + encode(doc) + class TestCodecOptions(unittest.TestCase): def test_document_class(self): From 65f9beb7fb164e2653a2f4ffe3ed1338fe9518ea Mon Sep 17 00:00:00 2001 From: Navjot Singh Date: Fri, 13 Sep 2024 17:13:15 +0100 Subject: [PATCH 2/4] fixed segmentation fault --- bson/_cbsonmodule.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/bson/_cbsonmodule.c b/bson/_cbsonmodule.c index ec010d0775..68a1c3eda8 100644 --- a/bson/_cbsonmodule.c +++ b/bson/_cbsonmodule.c @@ -1749,7 +1749,6 @@ int write_dict(PyObject* self, buffer_t buffer, PyObject *InvalidDocument = _error("InvalidDocument"); if (PyErr_GivenExceptionMatches(etype, InvalidDocument)) { - if (InvalidDocument) { Py_DECREF(etype); etype = InvalidDocument; @@ -1766,21 +1765,19 @@ int write_dict(PyObject* self, buffer_t buffer, if (new_msg) { evalue = new_msg; - Py_DECREF(new_msg); } - else{ + else { evalue = msg; } - - Py_DECREF(msg); - } } PyErr_NormalizeException(&etype, &evalue, &etrace); } } + else { + Py_DECREF(InvalidDocument); + } PyErr_Restore(etype, evalue, etrace); - Py_DECREF(InvalidDocument); } return 0; } From 73d38c89509215627bd6ead7dffed3830d514874 Mon Sep 17 00:00:00 2001 From: Navjot Singh Date: Fri, 13 Sep 2024 17:22:07 +0100 Subject: [PATCH 3/4] fixed linting errors and added name in contributors --- bson/__init__.py | 2 +- doc/contributors.rst | 1 + test/test_bson.py | 5 +---- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/bson/__init__.py b/bson/__init__.py index 5b4c470161..8b3f6a9f76 100644 --- a/bson/__init__.py +++ b/bson/__init__.py @@ -1009,7 +1009,7 @@ def _dict_to_bson( try: elements.append(_element_to_bson(key, value, check_keys, opts)) except InvalidDocument as err: - raise InvalidDocument("Invalid document {} | {}".format(doc,err)) from err + raise InvalidDocument(f"Invalid document {doc} | {err}") from err except AttributeError: raise TypeError(f"encoder expected a mapping type but got: {doc!r}") from None diff --git a/doc/contributors.rst b/doc/contributors.rst index 272b81d6ae..4a7f5424b1 100644 --- a/doc/contributors.rst +++ b/doc/contributors.rst @@ -102,3 +102,4 @@ The following is a list of people who have contributed to - Ivan Lukyanchikov (ilukyanchikov) - Terry Patterson - Romain Morotti +- Navjot Singh (navjots18) diff --git a/test/test_bson.py b/test/test_bson.py index 6ac515e45c..556762a4a3 100644 --- a/test/test_bson.py +++ b/test/test_bson.py @@ -1001,7 +1001,6 @@ def __repr__(self): encode({"t": Wrapper(1)}) def test_doc_in_invalid_document_error_message(self): - class Wrapper: def __init__(self, val): self.val = val @@ -1011,9 +1010,7 @@ def __repr__(self): self.assertEqual("1", repr(Wrapper(1))) doc = {"t": Wrapper(1)} - with self.assertRaisesRegex( - InvalidDocument, "Invalid document {}".format(doc) - ): + with self.assertRaisesRegex(InvalidDocument, f"Invalid document {doc}"): encode(doc) From 50d9130828336303582e37a0193c6b2839790152 Mon Sep 17 00:00:00 2001 From: Navjot Singh Date: Thu, 7 Nov 2024 20:32:36 +0000 Subject: [PATCH 4/4] fixed nesting issue and added top level check --- bson/_cbsonmodule.c | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/bson/_cbsonmodule.c b/bson/_cbsonmodule.c index 68a1c3eda8..4ef20b0a1f 100644 --- a/bson/_cbsonmodule.c +++ b/bson/_cbsonmodule.c @@ -1744,35 +1744,34 @@ int write_dict(PyObject* self, buffer_t buffer, if (!decode_and_write_pair(self, buffer, key, value, check_keys, options, top_level)) { if (PyErr_Occurred()) { - PyObject *etype, *evalue, *etrace; + PyObject *etype = NULL, *evalue = NULL, *etrace = NULL; PyErr_Fetch(&etype, &evalue, &etrace); PyObject *InvalidDocument = _error("InvalidDocument"); - if (PyErr_GivenExceptionMatches(etype, InvalidDocument)) { - if (InvalidDocument) { - Py_DECREF(etype); - etype = InvalidDocument; - - if (evalue) { - PyObject *msg = PyObject_Str(evalue); - Py_DECREF(evalue); - - if (msg) { - // Prepend doc to the existing message - PyObject *dict_str = PyObject_Str(dict); - PyObject *new_msg = PyUnicode_FromFormat("Invalid document %s | %s", PyUnicode_AsUTF8(dict_str), PyUnicode_AsUTF8(msg)); - Py_DECREF(dict_str); - - if (new_msg) { - evalue = new_msg; - } - else { - evalue = msg; - } + if (top_level && InvalidDocument && PyErr_GivenExceptionMatches(etype, InvalidDocument)) { + + Py_DECREF(etype); + etype = InvalidDocument; + + if (evalue) { + PyObject *msg = PyObject_Str(evalue); + Py_DECREF(evalue); + + if (msg) { + // Prepend doc to the existing message + PyObject *dict_str = PyObject_Str(dict); + PyObject *new_msg = PyUnicode_FromFormat("Invalid document %s | %s", PyUnicode_AsUTF8(dict_str), PyUnicode_AsUTF8(msg)); + Py_DECREF(dict_str); + + if (new_msg) { + evalue = new_msg; + } + else { + evalue = msg; } } - PyErr_NormalizeException(&etype, &evalue, &etrace); } + PyErr_NormalizeException(&etype, &evalue, &etrace); } else { Py_DECREF(InvalidDocument);