[issue38913] Py_BuildValue("(s#O)", ...) segfaults if entered with exception raised
New submission from danielen : The following code results in a segmentation fault in CPython 3.8 while executes fines (raises a SystemError) in CPython 3.7. PyObject* debug(PyObject *self, PyObject *args) { const char * debug = "debug"; PyErr_SetString(PyExc_ValueError, "debug!"); return Py_BuildValue("(s#O)", debug, strlen(debug), Py_None); } It seems necessary for the format string to contain both an instance of "s#" and "O" to trigger the bug. I'm attaching a C module that reproduces the problem. -- components: Extension Modules files: module.c messages: 357485 nosy: danielen priority: normal severity: normal status: open title: Py_BuildValue("(s#O)", ...) segfaults if entered with exception raised versions: Python 3.8 Added file: https://bugs.python.org/file48743/module.c ___ Python tracker <https://bugs.python.org/issue38913> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue38913] Py_BuildValue("(s#O)", ...) segfaults if entered with exception raised
danielen added the comment: It is not reproducible with PY_SSIZE_T_CLEAN defined. -- ___ Python tracker <https://bugs.python.org/issue38913> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue38913] Py_BuildValue("(s#O)", ...) segfaults if entered with exception raised
danielen added the comment: The problem arises from this code in do_mktuple(), staring at line 394 in modsupport.c: if (**p_format == '#') { ++*p_format; if (flags & FLAG_SIZE_T) n = va_arg(*p_va, Py_ssize_t); else { if (PyErr_WarnEx(PyExc_DeprecationWarning, "PY_SSIZE_T_CLEAN will be required for '#' formats", 1)) { return NULL; } n = va_arg(*p_va, int); } } If this is entered with an exception raised, PyErr_WarnEx() return NULL, thus this function return NULL without consuming the argument relative to the string length for the "s#" specifier. This argument is then consumed at the next iteration for the "O" specifier, resulting in a segmentation fault when the string length is interpreted as an object pointer. I don't know what is the best solution: either ignoring the return value of PyErr_WarnEx or swapping the lines from if (PyErr_WarnEx(PyExc_DeprecationWarning, "PY_SSIZE_T_CLEAN will be required for '#' formats", 1)) { return NULL; } n = va_arg(*p_va, int); to n = va_arg(*p_va, int); if (PyErr_WarnEx(PyExc_DeprecationWarning, "PY_SSIZE_T_CLEAN will be required for '#' formats", 1)) { return NULL; } The handling of the "y#" just below suffers from the same problem. -- ___ Python tracker <https://bugs.python.org/issue38913> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com