diff options
author | Michael W. Hudson <mwh@python.net> | 2004-08-12 17:56:29 (GMT) |
---|---|---|
committer | Michael W. Hudson <mwh@python.net> | 2004-08-12 17:56:29 (GMT) |
commit | 609346273903cd848d055b046ec46d9cc831b750 (patch) | |
tree | 1cae68cd2e72748e02ae5d5179ccfe1f8dc1bb98 /Python | |
parent | fd39ad4937f5f48142c7dafdac9d727931137c96 (diff) | |
download | cpython-609346273903cd848d055b046ec46d9cc831b750.zip cpython-609346273903cd848d055b046ec46d9cc831b750.tar.gz cpython-609346273903cd848d055b046ec46d9cc831b750.tar.bz2 |
Fix bug
[ 1005248 ] new.code() not cleanly checking its arguments
using the result of new.code() can still destroy the sun, but merely
calling the function shouldn't any more.
I also rewrote the existing tests of new.code() to use vastly less
un-bogus arguments, and added tests for the previous insane behaviours.
Diffstat (limited to 'Python')
-rw-r--r-- | Python/compile.c | 115 |
1 files changed, 88 insertions, 27 deletions
diff --git a/Python/compile.c b/Python/compile.c index 5c67987..0c405cc 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -88,6 +88,50 @@ static PyMemberDef code_memberlist[] = { {NULL} /* Sentinel */ }; +/* Helper for code_new: return a shallow copy of a tuple that is + guaranteed to contain exact strings, by converting string subclasses + to exact strings and complaining if a non-string is found. */ +static PyObject* +validate_and_copy_tuple(PyObject *tup) +{ + PyObject *newtuple; + PyObject *item; + int i, len; + + len = PyTuple_GET_SIZE(tup); + newtuple = PyTuple_New(len); + if (newtuple == NULL) + return NULL; + + for (i = 0; i < len; i++) { + item = PyTuple_GET_ITEM(tup, i); + if (PyString_CheckExact(item)) { + Py_INCREF(item); + } + else if (!PyString_Check(item)) { + PyErr_Format( + PyExc_TypeError, + "name tuples must contain only " + "strings, not '%.500s'", + item->ob_type->tp_name); + Py_DECREF(newtuple); + return NULL; + } + else { + item = PyString_FromStringAndSize( + PyString_AS_STRING(item), + PyString_GET_SIZE(item)); + if (item == NULL) { + Py_DECREF(newtuple); + return NULL; + } + } + PyTuple_SET_ITEM(newtuple, i, item); + } + + return newtuple; +} + PyDoc_STRVAR(code_doc, "code(argcount, nlocals, stacksize, flags, codestring, constants, names,\n\ varnames, filename, name, firstlineno, lnotab[, freevars[, cellvars]])\n\ @@ -101,14 +145,13 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw) int nlocals; int stacksize; int flags; - PyObject *co; - PyObject *empty = NULL; + PyObject *co = NULL;; PyObject *code; PyObject *consts; - PyObject *names; - PyObject *varnames; - PyObject *freevars = NULL; - PyObject *cellvars = NULL; + PyObject *names, *ournames = NULL; + PyObject *varnames, *ourvarnames = NULL; + PyObject *freevars = NULL, *ourfreevars = NULL; + PyObject *cellvars = NULL, *ourcellvars = NULL; PyObject *filename; PyObject *name; int firstlineno; @@ -126,27 +169,48 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw) &PyTuple_Type, &cellvars)) return NULL; - if (!PyObject_CheckReadBuffer(code)) { - PyErr_SetString(PyExc_TypeError, - "bytecode object must be a single-segment read-only buffer"); - return NULL; + if (argcount < 0) { + PyErr_SetString( + PyExc_ValueError, + "code: argcount must not be negative"); + goto cleanup; } - if (freevars == NULL || cellvars == NULL) { - empty = PyTuple_New(0); - if (empty == NULL) - return NULL; - if (freevars == NULL) - freevars = empty; - if (cellvars == NULL) - cellvars = empty; + if (nlocals < 0) { + PyErr_SetString( + PyExc_ValueError, + "code: nlocals must not be negative"); + goto cleanup; } + ournames = validate_and_copy_tuple(names); + if (ournames == NULL) + goto cleanup; + ourvarnames = validate_and_copy_tuple(varnames); + if (ourvarnames == NULL) + goto cleanup; + if (freevars) + ourfreevars = validate_and_copy_tuple(freevars); + else + ourfreevars = PyTuple_New(0); + if (ourfreevars == NULL) + goto cleanup; + if (cellvars) + ourcellvars = validate_and_copy_tuple(cellvars); + else + ourcellvars = PyTuple_New(0); + if (ourcellvars == NULL) + goto cleanup; + co = (PyObject *) PyCode_New(argcount, nlocals, stacksize, flags, - code, consts, names, varnames, - freevars, cellvars, filename, name, - firstlineno, lnotab); - Py_XDECREF(empty); + code, consts, ournames, ourvarnames, + ourfreevars, ourcellvars, filename, + name, firstlineno, lnotab); + cleanup: + Py_XDECREF(ournames); + Py_XDECREF(ourvarnames); + Py_XDECREF(ourfreevars); + Py_XDECREF(ourcellvars); return co; } @@ -302,21 +366,18 @@ all_name_chars(unsigned char *s) return 1; } -static int +static void intern_strings(PyObject *tuple) { int i; for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) { PyObject *v = PyTuple_GET_ITEM(tuple, i); - if (v == NULL || !PyString_Check(v)) { + if (v == NULL || !PyString_CheckExact(v)) { Py_FatalError("non-string found in code slot"); - PyErr_BadInternalCall(); - return -1; } PyString_InternInPlace(&PyTuple_GET_ITEM(tuple, i)); } - return 0; } #define GETARG(arr, i) ((int)((arr[i+2]<<8) + arr[i+1])) |