diff -r 4828cb77bf2a Lib/test/test_funcattrs.py --- a/Lib/test/test_funcattrs.py Wed Feb 11 17:49:01 2015 -0800 +++ b/Lib/test/test_funcattrs.py Thu Feb 12 22:29:54 2015 +0200 @@ -187,6 +187,15 @@ class FunctionPropertiesTest(FuncAttrsTe self.fail("__defaults__ does not update; deleting it does not " "remove requirement") + @support.cpython_only + def test_func_default_args_overflow(self): + def func(a=1, b=2): + return a+b + self.assertEqual(func.__defaults__, (1, 2)) + with self.assertRaises(ValueError): + func.__defaults__ = (3,)*256 + self.assertEqual(func.__defaults__, (1, 2)) + class InstancemethodAttrTest(FuncAttrsTest): diff -r 4828cb77bf2a Objects/codeobject.c --- a/Objects/codeobject.c Wed Feb 11 17:49:01 2015 -0800 +++ b/Objects/codeobject.c Thu Feb 12 22:29:54 2015 +0200 @@ -97,6 +97,11 @@ PyCode_New(int argcount, int kwonlyargco ((flags & CO_VARARGS) != 0) + ((flags & CO_VARKEYWORDS) != 0); Py_ssize_t alloc_size = sizeof(unsigned char) * n_cellvars; int used_cell2arg = 0; + if (total_args > 255) { + PyErr_Format(PyExc_TypeError, + "too many parameters in %U()", name); + return NULL; + } cell2arg = PyMem_MALLOC(alloc_size); if (cell2arg == NULL) return NULL; @@ -108,7 +113,8 @@ PyCode_New(int argcount, int kwonlyargco for (j = 0; j < total_args; j++) { PyObject *arg = PyTuple_GET_ITEM(varnames, j); if (!PyUnicode_Compare(cell, arg)) { - cell2arg[i] = j; + assert(j <= 255); + cell2arg[i] = (unsigned char)j; used_cell2arg = 1; break; } diff -r 4828cb77bf2a Objects/funcobject.c --- a/Objects/funcobject.c Wed Feb 11 17:49:01 2015 -0800 +++ b/Objects/funcobject.c Thu Feb 12 22:29:54 2015 +0200 @@ -121,6 +121,11 @@ PyFunction_SetDefaults(PyObject *op, PyO if (defaults == Py_None) defaults = NULL; else if (defaults && PyTuple_Check(defaults)) { + if (Py_SIZE(defaults) > 255) { + PyErr_SetString(PyExc_SystemError, + "more than 255 default values"); + return -1; + } Py_INCREF(defaults); } else { @@ -358,6 +363,11 @@ func_set_defaults(PyFunctionObject *op, "__defaults__ must be set to a tuple object"); return -1; } + if (value != NULL && Py_SIZE(value) > 255) { + PyErr_SetString(PyExc_ValueError, + "more than 255 default values"); + return -1; + } tmp = op->func_defaults; Py_XINCREF(value); op->func_defaults = value; @@ -492,6 +502,11 @@ func_new(PyTypeObject* type, PyObject* a "arg 4 (defaults) must be None or tuple"); return NULL; } + if (defaults != Py_None && Py_SIZE(defaults) > 255) { + PyErr_SetString(PyExc_ValueError, + "more than 255 default values"); + return NULL; + } nfree = PyTuple_GET_SIZE(code->co_freevars); if (!PyTuple_Check(closure)) { if (nfree && closure == Py_None) { @@ -597,12 +612,13 @@ function_call(PyObject *func, PyObject * PyObject *argdefs; PyObject *kwtuple = NULL; PyObject **d, **k; - Py_ssize_t nk, nd; + Py_ssize_t na, nk, nd; argdefs = PyFunction_GET_DEFAULTS(func); if (argdefs != NULL && PyTuple_Check(argdefs)) { d = &PyTuple_GET_ITEM((PyTupleObject *)argdefs, 0); nd = PyTuple_GET_SIZE(argdefs); + assert(nd <= INT_MAX); } else { d = NULL; @@ -622,18 +638,35 @@ function_call(PyObject *func, PyObject * Py_INCREF(k[i+1]); i += 2; } + assert(nk == i/2); nk = i/2; + if (nk > 1000) { + PyErr_Format(PyExc_TypeError, + "too many keyword arguments for %U", + ((PyFunctionObject*)func)->func_name); + Py_DECREF(kwtuple); + return NULL; + } } else { k = NULL; nk = 0; } + na = PyTuple_GET_SIZE(arg); + if (na > 1000) { + PyErr_Format(PyExc_TypeError, + "too many positional arguments for %U", + ((PyFunctionObject*)func)->func_name); + return NULL; + } + result = PyEval_EvalCodeEx( PyFunction_GET_CODE(func), PyFunction_GET_GLOBALS(func), (PyObject *)NULL, - &PyTuple_GET_ITEM(arg, 0), PyTuple_GET_SIZE(arg), - k, nk, d, nd, + &PyTuple_GET_ITEM(arg, 0), (int)na, + k, (int)nk, + d, (int)nd, PyFunction_GET_KW_DEFAULTS(func), PyFunction_GET_CLOSURE(func)); diff -r 4828cb77bf2a Python/ceval.c --- a/Python/ceval.c Wed Feb 11 17:49:01 2015 -0800 +++ b/Python/ceval.c Thu Feb 12 22:29:54 2015 +0200 @@ -4375,8 +4375,10 @@ fast_function(PyObject *func, PyObject * return retval; } if (argdefs != NULL) { + assert(PyTuple_Check(argdefs)); d = &PyTuple_GET_ITEM(argdefs, 0); - nd = Py_SIZE(argdefs); + assert(Py_SIZE(argdefs) <= INT_MAX); + nd = (int)Py_SIZE(argdefs); } return _PyEval_EvalCodeWithName((PyObject*)co, globals, (PyObject *)NULL, (*pp_stack)-n, na, @@ -4511,7 +4513,7 @@ call_fail: static PyObject * ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk) { - int nstar = 0; + Py_ssize_t nstar = 0; PyObject *callargs = NULL; PyObject *stararg = NULL; PyObject *kwdict = NULL; @@ -4566,13 +4568,19 @@ ext_do_call(PyObject *func, PyObject *** stararg = t; } nstar = PyTuple_GET_SIZE(stararg); + if (nstar > INT_MAX - na) { + PyErr_Format(PyExc_TypeError, + "too many positional arguments for %.200s", + PyEval_GetFuncName(func)); + goto ext_call_fail; + } } if (nk > 0) { kwdict = update_keyword_args(kwdict, nk, pp_stack, func); if (kwdict == NULL) goto ext_call_fail; } - callargs = update_star_args(na, nstar, stararg, pp_stack); + callargs = update_star_args(na, (int)nstar, stararg, pp_stack); if (callargs == NULL) goto ext_call_fail; #ifdef CALL_PROFILE