[issue38913] Py_BuildValue("(s#O)", ...) segfaults if entered with exception raised

2019-11-25 Thread danielen


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

2019-11-26 Thread danielen


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

2019-11-26 Thread danielen


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