summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorMartin Panter <vadmium+py@gmail.com>2015-11-07 02:32:21 (GMT)
committerMartin Panter <vadmium+py@gmail.com>2015-11-07 02:32:21 (GMT)
commiteeb896c4116dd763efea45cb3c1b53257128f4e4 (patch)
tree34e8df45212ee5c99849dfca30977b92901615d6 /Python
parent9ad0aae6566311c6982a20955381cda5a2954519 (diff)
downloadcpython-eeb896c4116dd763efea45cb3c1b53257128f4e4.zip
cpython-eeb896c4116dd763efea45cb3c1b53257128f4e4.tar.gz
cpython-eeb896c4116dd763efea45cb3c1b53257128f4e4.tar.bz2
Issue #24802: Copy bytes-like objects to null-terminated buffers if necessary
This avoids possible buffer overreads when int(), float(), compile(), exec() and eval() are passed bytes-like objects. Similar code is removed from the complex() constructor, where it was not reachable. Patch by John Leitch, Serhiy Storchaka and Martin Panter.
Diffstat (limited to 'Python')
-rw-r--r--Python/bltinmodule.c48
1 files changed, 32 insertions, 16 deletions
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index aed93e5..53009e3 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -560,20 +560,37 @@ Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff.");
static const char *
-source_as_string(PyObject *cmd, const char *funcname, const char *what, PyCompilerFlags *cf, Py_buffer *view)
+source_as_string(PyObject *cmd, const char *funcname, const char *what, PyCompilerFlags *cf, PyObject **cmd_copy)
{
const char *str;
Py_ssize_t size;
+ Py_buffer view;
+ *cmd_copy = NULL;
if (PyUnicode_Check(cmd)) {
cf->cf_flags |= PyCF_IGNORE_COOKIE;
str = PyUnicode_AsUTF8AndSize(cmd, &size);
if (str == NULL)
return NULL;
}
- else if (PyObject_GetBuffer(cmd, view, PyBUF_SIMPLE) == 0) {
- str = (const char *)view->buf;
- size = view->len;
+ else if (PyBytes_Check(cmd)) {
+ str = PyBytes_AS_STRING(cmd);
+ size = PyBytes_GET_SIZE(cmd);
+ }
+ else if (PyByteArray_Check(cmd)) {
+ str = PyByteArray_AS_STRING(cmd);
+ size = PyByteArray_GET_SIZE(cmd);
+ }
+ else if (PyObject_GetBuffer(cmd, &view, PyBUF_SIMPLE) == 0) {
+ /* Copy to NUL-terminated buffer. */
+ *cmd_copy = PyBytes_FromStringAndSize(
+ (const char *)view.buf, view.len);
+ PyBuffer_Release(&view);
+ if (*cmd_copy == NULL) {
+ return NULL;
+ }
+ str = PyBytes_AS_STRING(*cmd_copy);
+ size = PyBytes_GET_SIZE(*cmd_copy);
}
else {
PyErr_Format(PyExc_TypeError,
@@ -585,7 +602,7 @@ source_as_string(PyObject *cmd, const char *funcname, const char *what, PyCompil
if (strlen(str) != size) {
PyErr_SetString(PyExc_TypeError,
"source code string cannot contain null bytes");
- PyBuffer_Release(view);
+ Py_CLEAR(*cmd_copy);
return NULL;
}
return str;
@@ -594,7 +611,7 @@ source_as_string(PyObject *cmd, const char *funcname, const char *what, PyCompil
static PyObject *
builtin_compile(PyObject *self, PyObject *args, PyObject *kwds)
{
- Py_buffer view = {NULL, NULL};
+ PyObject *cmd_copy;
const char *str;
PyObject *filename;
char *startstr;
@@ -681,12 +698,12 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds)
goto finally;
}
- str = source_as_string(cmd, "compile", "string, bytes or AST", &cf, &view);
+ str = source_as_string(cmd, "compile", "string, bytes or AST", &cf, &cmd_copy);
if (str == NULL)
goto error;
result = Py_CompileStringObject(str, filename, start[mode], &cf, optimize);
- PyBuffer_Release(&view);
+ Py_XDECREF(cmd_copy);
goto finally;
error:
@@ -754,9 +771,8 @@ Return the tuple ((x-x%y)/y, x%y). Invariant: div*y + mod == x.");
static PyObject *
builtin_eval(PyObject *self, PyObject *args)
{
- PyObject *cmd, *result, *tmp = NULL;
+ PyObject *cmd, *result, *cmd_copy;
PyObject *globals = Py_None, *locals = Py_None;
- Py_buffer view = {NULL, NULL};
const char *str;
PyCompilerFlags cf;
@@ -806,7 +822,7 @@ builtin_eval(PyObject *self, PyObject *args)
}
cf.cf_flags = PyCF_SOURCE_IS_UTF8;
- str = source_as_string(cmd, "eval", "string, bytes or code", &cf, &view);
+ str = source_as_string(cmd, "eval", "string, bytes or code", &cf, &cmd_copy);
if (str == NULL)
return NULL;
@@ -815,8 +831,7 @@ builtin_eval(PyObject *self, PyObject *args)
(void)PyEval_MergeCompilerFlags(&cf);
result = PyRun_StringFlags(str, Py_eval_input, globals, locals, &cf);
- PyBuffer_Release(&view);
- Py_XDECREF(tmp);
+ Py_XDECREF(cmd_copy);
return result;
}
@@ -882,12 +897,13 @@ builtin_exec(PyObject *self, PyObject *args)
v = PyEval_EvalCode(prog, globals, locals);
}
else {
- Py_buffer view = {NULL, NULL};
+ PyObject *prog_copy;
const char *str;
PyCompilerFlags cf;
cf.cf_flags = PyCF_SOURCE_IS_UTF8;
str = source_as_string(prog, "exec",
- "string, bytes or code", &cf, &view);
+ "string, bytes or code", &cf,
+ &prog_copy);
if (str == NULL)
return NULL;
if (PyEval_MergeCompilerFlags(&cf))
@@ -895,7 +911,7 @@ builtin_exec(PyObject *self, PyObject *args)
locals, &cf);
else
v = PyRun_String(str, Py_file_input, globals, locals);
- PyBuffer_Release(&view);
+ Py_XDECREF(prog_copy);
}
if (v == NULL)
return NULL;