diff --git a/ddtrace/appsec/_iast/_taint_tracking/Utils/StringUtils.cpp b/ddtrace/appsec/_iast/_taint_tracking/Utils/StringUtils.cpp index 2878a3631ea..e13b2bdd6c4 100644 --- a/ddtrace/appsec/_iast/_taint_tracking/Utils/StringUtils.cpp +++ b/ddtrace/appsec/_iast/_taint_tracking/Utils/StringUtils.cpp @@ -79,31 +79,65 @@ PyObjectToString(PyObject* obj) PyObject* new_pyobject_id(PyObject* tainted_object) { + if (!tainted_object) + return nullptr; + if (PyUnicode_Check(tainted_object)) { PyObject* empty_unicode = PyUnicode_New(0, 127); + if (!empty_unicode) + return tainted_object; PyObject* val = Py_BuildValue("(OO)", tainted_object, empty_unicode); + if (!val) { + Py_XDECREF(empty_unicode); + return tainted_object; + } PyObject* result = PyUnicode_Join(empty_unicode, val); - Py_DecRef(empty_unicode); - Py_DecRef(val); + if (!result) { + result = tainted_object; + } + Py_XDECREF(empty_unicode); + Py_XDECREF(val); return result; } if (PyBytes_Check(tainted_object)) { PyObject* empty_bytes = PyBytes_FromString(""); - auto bytes_join_ptr = py::reinterpret_borrow(empty_bytes).attr("join"); - auto val = Py_BuildValue("(OO)", tainted_object, empty_bytes); - auto res = PyObject_CallFunctionObjArgs(bytes_join_ptr.ptr(), val, NULL); - Py_DecRef(val); - Py_DecRef(empty_bytes); + if (!empty_bytes) + return tainted_object; + + const auto bytes_join_ptr = py::reinterpret_borrow(empty_bytes).attr("join"); + const auto val = Py_BuildValue("(OO)", tainted_object, empty_bytes); + if (!val or !bytes_join_ptr.ptr()) { + Py_XDECREF(empty_bytes); + return tainted_object; + } + + const auto res = PyObject_CallFunctionObjArgs(bytes_join_ptr.ptr(), val, NULL); + Py_XDECREF(val); + Py_XDECREF(empty_bytes); return res; } else if (PyByteArray_Check(tainted_object)) { PyObject* empty_bytes = PyBytes_FromString(""); + if (!empty_bytes) + return tainted_object; + PyObject* empty_bytearray = PyByteArray_FromObject(empty_bytes); - auto bytearray_join_ptr = py::reinterpret_borrow(empty_bytearray).attr("join"); - auto val = Py_BuildValue("(OO)", tainted_object, empty_bytearray); - auto res = PyObject_CallFunctionObjArgs(bytearray_join_ptr.ptr(), val, NULL); - Py_DecRef(val); - Py_DecRef(empty_bytes); - Py_DecRef(empty_bytearray); + if (!empty_bytearray) { + Py_XDECREF(empty_bytes); + return tainted_object; + } + + const auto bytearray_join_ptr = py::reinterpret_borrow(empty_bytearray).attr("join"); + const auto val = Py_BuildValue("(OO)", tainted_object, empty_bytearray); + if (!val or !bytearray_join_ptr.ptr()) { + Py_XDECREF(empty_bytes); + Py_XDECREF(empty_bytearray); + return tainted_object; + } + + const auto res = PyObject_CallFunctionObjArgs(bytearray_join_ptr.ptr(), val, NULL); + Py_XDECREF(val); + Py_XDECREF(empty_bytes); + Py_XDECREF(empty_bytearray); return res; } return tainted_object; @@ -121,4 +155,4 @@ get_pyobject_size(PyObject* obj) len_candidate_text = PyByteArray_Size(obj); } return len_candidate_text; -} \ No newline at end of file +} diff --git a/releasenotes/notes/iast-new-pyobject-check-6aecf9c4f22e2ae9.yaml b/releasenotes/notes/iast-new-pyobject-check-6aecf9c4f22e2ae9.yaml new file mode 100644 index 00000000000..ff38ff60deb --- /dev/null +++ b/releasenotes/notes/iast-new-pyobject-check-6aecf9c4f22e2ae9.yaml @@ -0,0 +1,4 @@ +--- +fixes: + - | + Code Security: add null pointer checks when creating new objects ids.