New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PyNumber_Long Buffer Over-read.patch #68991
Comments
Python suffers from a buffer over-read in PyNumber_Long() that is caused by the incorrect assumption that buffers returned by PyObject_GetBuffer() are null-terminated. This could potentially result in the disclosure of adjacent memory. PyObject * if (PyObject_GetBuffer(o, &view, PyBUF_SIMPLE) == 0) { <<<< The unterminated buffer
is retreived here.
/* need to do extra error checking that PyLong_FromString()
* doesn't do. In particular int('9\x005') must raise an
* exception, not truncate at the null.
*/
PyObject *result = _PyLong_FromBytes(view.buf, view.len, 10); <<<< The buffer
is then passed to _PyLong_FromBytes(),
which ultimately passes it to
PyLong_FromString().
PyBuffer_Release(&view);
return result;
}
} PyObject *
PyLong_FromString(const char *str, char **pend, int base)
{
int sign = 1, error_if_nonzero = 0;
const char *start, *orig_str = str;
PyLongObject *z = NULL;
PyObject *strobj;
Py_ssize_t slen;
onError:
if (pend != NULL)
*pend = (char *)str;
Py_XDECREF(z);
slen = strlen(orig_str) < 200 ? strlen(orig_str) : 200; <<<< If this path is taken,
orig_str is pointing to the
unterminated string, resulting in
strlen reading off the end of the
buffer.
strobj = PyUnicode_FromStringAndSize(orig_str, slen); <<<< The incorrect length is
then used to create a Python
string.
if (strobj == NULL)
return NULL;
PyErr_Format(PyExc_ValueError,
"invalid literal for int() with base %d: %.200R",
base, strobj);
Py_DECREF(strobj);
return NULL;
} A script that reproduces the issue is as follows: import array
int(array.array("B",b"A"*0x10)) And it produces the following exception: 0:000> p
FAULTING_IP: EXCEPTION_RECORD: ffffffff -- (.exr 0xffffffffffffffff) CONTEXT: 0000000 -- (.cxr 0x0;r) FAULTING_THREAD: 00000e5c DEFAULT_BUCKET_ID: INVALID_POINTER_READ PROCESS_NAME: python.exe ERROR_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%p referenced memory at 0x%p. The memory could not be %s. EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%p referenced memory at 0x%p. The memory could not be %s. EXCEPTION_PARAMETER1: 0000000 EXCEPTION_PARAMETER2: 096ff000 READ_ADDRESS: 096ff000 FOLLOWUP_IP: NTGLOBALFLAG: 2000000 APPLICATION_VERIFIER_FLAGS: 0 APP: python.exe ANALYSIS_VERSION: 6.3.9600.17029 (debuggers(dbg).140219-1702) x86fre PRIMARY_PROBLEM_CLASS: INVALID_POINTER_READ BUGCHECK_STR: APPLICATION_FAULT_INVALID_POINTER_READ LAST_CONTROL_TRANSFER: from 5da3a60d to 5da3a567 STACK_TEXT: STACK_COMMAND: .cxr 0x0 ; kb FAULTING_SOURCE_LINE: c:\build\cpython\objects\longobject.c FAULTING_SOURCE_FILE: c:\build\cpython\objects\longobject.c FAULTING_SOURCE_LINE_NUMBER: 2293 FAULTING_SOURCE_CODE:
SYMBOL_STACK_INDEX: 0 SYMBOL_NAME: python35!PyLong_FromString+4d7 FOLLOWUP_NAME: MachineOwner MODULE_NAME: python35 IMAGE_NAME: python35.dll DEBUG_FLR_IMAGE_TIMESTAMP: 5598ccc2 FAILURE_BUCKET_ID: INVALID_POINTER_READ_c0000005_python35.dll!PyLong_FromString BUCKET_ID: APPLICATION_FAULT_INVALID_POINTER_READ_python35!PyLong_FromString+4d7 ANALYSIS_SOURCE: UM FAILURE_ID_HASH_STRING: um:invalid_pointer_read_c0000005_python35.dll!pylong_fromstring FAILURE_ID_HASH: {e857bdce-f7a2-f3d9-b507-e98e25bcd084} Followup: MachineOwner To fix the issue, it is recommended that PyNumber_Long() check the type of argument o after a successful PyObject_GetBuffer() call to determine if the buffer is null-terminated or otherwise. A proposed patch is attached. |
Attaching repro. |
Merged with bpo-24802. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: