]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Issue #24802: Merge null termination fixes from 3.4 into 3.5
authorMartin Panter <vadmium+py@gmail.com>
Sat, 7 Nov 2015 02:56:11 +0000 (02:56 +0000)
committerMartin Panter <vadmium+py@gmail.com>
Sat, 7 Nov 2015 02:56:11 +0000 (02:56 +0000)
1  2 
Lib/test/test_compile.py
Lib/test/test_float.py
Lib/test/test_int.py
Misc/NEWS
Objects/abstract.c
Objects/complexobject.c
Objects/floatobject.c
Python/bltinmodule.c

Simple merge
Simple merge
Simple merge
diff --cc Misc/NEWS
index e20c33d3cd6a6bac3a9382a54d507ec5e277eb85,a0c1a6d2d0c7b22d4392adbf0a18003df09f7f1f..f08b4ce8430adf481d42e32c1812d5aff483d279
+++ 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.
  
Simple merge
Simple merge
Simple merge
index 7f7d051c71c0f3fe006a84be149db8454aea9edc,53009e3fbdc77dc6b9cc67902b548a4fe8ca0363..a06ef610c660ac09c6c74b688801654ef3aea138
@@@ -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;
  
          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;
  
      }
  
      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;
  
  
      (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))
                                    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;