From: Martin Panter Date: Sat, 7 Nov 2015 02:56:11 +0000 (+0000) Subject: Issue #24802: Merge null termination fixes from 3.4 into 3.5 X-Git-Tag: v3.5.1rc1~84 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=61d6e4ae9db80e3f87104a03499ff89d3c275b22;p=thirdparty%2FPython%2Fcpython.git Issue #24802: Merge null termination fixes from 3.4 into 3.5 --- 61d6e4ae9db80e3f87104a03499ff89d3c275b22 diff --cc Misc/NEWS index e20c33d3cd6a,a0c1a6d2d0c7..f08b4ce8430a --- a/Misc/NEWS +++ b/Misc/NEWS @@@ -11,20 -10,10 +11,24 @@@ Release date: TB Core and Builtins ----------------- + - Issue #24802: Avoid buffer overreads when int(), float(), compile(), exec() + and eval() are passed bytes-like objects. These objects are not + necessarily terminated by a null byte, but the functions assumed they were. + +- Issue #24726: Fixed a crash and leaking NULL in repr() of OrderedDict that + was mutated by direct calls of dict methods. + +- Issue #25449: Iterating OrderedDict with keys with unstable hash now raises + KeyError in C implementations as well as in Python implementation. + +- Issue #25395: Fixed crash when highly nested OrderedDict structures were + garbage collected. + +- Issue #25274: sys.setrecursionlimit() now raises a RecursionError if the new + recursion limit is too low depending at the current recursion depth. Modify + also the "lower-water mark" formula to make it monotonic. This mark is used + to decide when the overflowed flag of the thread state is reset. + - Issue #24402: Fix input() to prompt to the redirected stdout when sys.stdout.fileno() fails. diff --cc Python/bltinmodule.c index 7f7d051c71c0,53009e3fbdc7..a06ef610c660 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@@ -621,50 -599,31 +638,50 @@@ source_as_string(PyObject *cmd, const c return NULL; } - if (strlen(str) != size) { - PyErr_SetString(PyExc_TypeError, + if (strlen(str) != (size_t)size) { + PyErr_SetString(PyExc_ValueError, "source code string cannot contain null bytes"); - PyBuffer_Release(view); + Py_CLEAR(*cmd_copy); return NULL; } return str; } +/*[clinic input] +compile as builtin_compile + + source: object + filename: object(converter="PyUnicode_FSDecoder") + mode: str + flags: int = 0 + dont_inherit: int(c_default="0") = False + optimize: int = -1 + +Compile source into a code object that can be executed by exec() or eval(). + +The source code may represent a Python module, statement or expression. +The filename will be used for run-time error messages. +The mode must be 'exec' to compile a module, 'single' to compile a +single (interactive) statement, or 'eval' to compile an expression. +The flags argument, if present, controls which future statements influence +the compilation of the code. +The dont_inherit argument, if true, stops the compilation inheriting +the effects of any future statements in effect in the code calling +compile; if absent or false these statements do influence the compilation, +in addition to any features explicitly specified. +[clinic start generated code]*/ + static PyObject * -builtin_compile(PyObject *self, PyObject *args, PyObject *kwds) +builtin_compile_impl(PyModuleDef *module, PyObject *source, + PyObject *filename, const char *mode, int flags, + int dont_inherit, int optimize) +/*[clinic end generated code: output=31881762c1bb90c4 input=9d53e8cfb3c86414]*/ { - Py_buffer view = {NULL, NULL}; - PyObject *cmd_copy; ++ PyObject *source_copy; const char *str; - PyObject *filename; - char *startstr; - int mode = -1; - int dont_inherit = 0; - int supplied_flags = 0; - int optimize = -1; + int compile_mode = -1; int is_ast; PyCompilerFlags cf; - PyObject *cmd; - static char *kwlist[] = {"source", "filename", "mode", "flags", - "dont_inherit", "optimize", NULL}; int start[] = {Py_file_input, Py_eval_input, Py_single_input}; PyObject *result; @@@ -732,12 -698,12 +749,12 @@@ goto finally; } - str = source_as_string(source, "compile", "string, bytes or AST", &cf, &view); - str = source_as_string(cmd, "compile", "string, bytes or AST", &cf, &cmd_copy); ++ str = source_as_string(source, "compile", "string, bytes or AST", &cf, &source_copy); if (str == NULL) goto error; - result = Py_CompileStringObject(str, filename, start[mode], &cf, optimize); - Py_XDECREF(cmd_copy); + result = Py_CompileStringObject(str, filename, start[compile_mode], &cf, optimize); - PyBuffer_Release(&view); ++ Py_XDECREF(source_copy); goto finally; error: @@@ -772,48 -752,27 +789,47 @@@ PyDoc_STRVAR(dir_doc " for any other object: its attributes, its class's attributes, and\n" " recursively the attributes of its class's base classes."); +/*[clinic input] +divmod as builtin_divmod + + x: object + y: object + / + +Return the tuple ((x-x%y)/y, x%y). Invariant: div*y + mod == x. +[clinic start generated code]*/ + static PyObject * -builtin_divmod(PyObject *self, PyObject *args) +builtin_divmod_impl(PyModuleDef *module, PyObject *x, PyObject *y) +/*[clinic end generated code: output=9ad0076120ebf9ac input=7fdb15f8a97a5fe7]*/ { - PyObject *v, *w; - - if (!PyArg_UnpackTuple(args, "divmod", 2, 2, &v, &w)) - return NULL; - return PyNumber_Divmod(v, w); + return PyNumber_Divmod(x, y); } -PyDoc_STRVAR(divmod_doc, -"divmod(x, y) -> (div, mod)\n\ -\n\ -Return the tuple ((x-x%y)/y, x%y). Invariant: div*y + mod == x."); +/*[clinic input] +eval as builtin_eval + + source: object + globals: object = None + locals: object = None + / + +Evaluate the given source in the context of globals and locals. + +The source may be a string representing a Python expression +or a code object as returned by compile(). +The globals must be a dictionary and locals can be any mapping, +defaulting to the current globals and locals. +If only globals is given, locals defaults to it. +[clinic start generated code]*/ static PyObject * -builtin_eval(PyObject *self, PyObject *args) +builtin_eval_impl(PyModuleDef *module, PyObject *source, PyObject *globals, + PyObject *locals) +/*[clinic end generated code: output=7284501fb7b4d666 input=11ee718a8640e527]*/ { - PyObject *result, *tmp = NULL; - Py_buffer view = {NULL, NULL}; - PyObject *cmd, *result, *cmd_copy; - PyObject *globals = Py_None, *locals = Py_None; ++ PyObject *result, *source_copy; const char *str; PyCompilerFlags cf; @@@ -861,7 -822,7 +877,7 @@@ } cf.cf_flags = PyCF_SOURCE_IS_UTF8; - str = source_as_string(source, "eval", "string, bytes or code", &cf, &view); - str = source_as_string(cmd, "eval", "string, bytes or code", &cf, &cmd_copy); ++ str = source_as_string(source, "eval", "string, bytes or code", &cf, &source_copy); if (str == NULL) return NULL; @@@ -870,8 -831,7 +886,7 @@@ (void)PyEval_MergeCompilerFlags(&cf); result = PyRun_StringFlags(str, Py_eval_input, globals, locals, &cf); - PyBuffer_Release(&view); - Py_XDECREF(tmp); - Py_XDECREF(cmd_copy); ++ Py_XDECREF(source_copy); return result; } @@@ -939,15 -894,16 +954,16 @@@ builtin_exec_impl(PyModuleDef *module, "contain free variables"); return NULL; } - v = PyEval_EvalCode(prog, globals, locals); + v = PyEval_EvalCode(source, globals, locals); } else { - Py_buffer view = {NULL, NULL}; - PyObject *prog_copy; ++ PyObject *source_copy; const char *str; PyCompilerFlags cf; cf.cf_flags = PyCF_SOURCE_IS_UTF8; - str = source_as_string(prog, "exec", - "string, bytes or code", &cf, - &prog_copy); + str = source_as_string(source, "exec", - "string, bytes or code", &cf, &view); ++ "string, bytes or code", &cf, ++ &source_copy); if (str == NULL) return NULL; if (PyEval_MergeCompilerFlags(&cf)) @@@ -955,7 -911,7 +971,7 @@@ locals, &cf); else v = PyRun_String(str, Py_file_input, globals, locals); - PyBuffer_Release(&view); - Py_XDECREF(prog_copy); ++ Py_XDECREF(source_copy); } if (v == NULL) return NULL;