If PyFormatter::dump_string attempting to format non-printable characters
can result in a nullptr being passed to dump_pyobject, causing a segfault.
It occured in the following case - crash module tried to load the crash entries
containing matedata with non-printable characters.
when these were passed to PyFormatter, the resulting crash prevented ceph-mgr
from starting.
Fix this by attempting to create a python object using PyUnicode_FromString.
If it returns nullptr (indicating a decoding failure), the code now falls
back to decoding using Latin1.
Additionally, add a guard in dump_pyobject to prevent processing nullptr objects,
providing a secondary layer of protection against segfaults.
Fixes: https://tracker.ceph.com/issues/74379
Signed-off-by: Nitzan Mordechai <nmordec@ibm.com>
void PyFormatter::dump_string(std::string_view name, std::string_view s)
{
- dump_pyobject(name, PyUnicode_FromString(s.data()));
+ PyObject *p = PyUnicode_FromStringAndSize(s.data(), s.size());
+ if (!p) {
+ PyErr_Clear();
+ p = PyUnicode_DecodeLatin1(s.data(), s.size(), nullptr);
+ ceph_assert(p);
+ }
+
+ dump_pyobject(name, p);
}
void PyFormatter::dump_bool(std::string_view name, bool b)
*/
void PyFormatter::dump_pyobject(std::string_view name, PyObject *p)
{
+ if (!p) {
+ ceph_abort_msg("PyFormatter::dump_pyobject received null PyObject");
+ }
if (PyList_Check(cursor)) {
PyList_Append(cursor, p);
Py_DECREF(p);