summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorMichael W. Hudson <mwh@python.net>2004-08-12 17:56:29 (GMT)
committerMichael W. Hudson <mwh@python.net>2004-08-12 17:56:29 (GMT)
commit609346273903cd848d055b046ec46d9cc831b750 (patch)
tree1cae68cd2e72748e02ae5d5179ccfe1f8dc1bb98 /Python
parentfd39ad4937f5f48142c7dafdac9d727931137c96 (diff)
downloadcpython-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.c115
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]))