]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Backport fixes for #1523610 (crashes in PyArg_ParseTuple):
authorGeorg Brandl <georg@python.org>
Wed, 9 Aug 2006 07:15:29 +0000 (07:15 +0000)
committerGeorg Brandl <georg@python.org>
Wed, 9 Aug 2006 07:15:29 +0000 (07:15 +0000)
rev. 51158 and rev. 50843.

Lib/test/test_getargs2.py
Modules/_testcapimodule.c
Python/getargs.c

index 47db73f73f42bd807080cc0e963e866ac6f497fe..e6bc4561d67859f25985e765eda01430fd06000e 100644 (file)
@@ -216,8 +216,25 @@ class LongLong_TestCase(unittest.TestCase):
 
         self.failUnlessEqual(VERY_LARGE & ULLONG_MAX, getargs_K(VERY_LARGE))
 
+
+class Tuple_TestCase(unittest.TestCase):
+    def test_tuple(self):
+        from _testcapi import getargs_tuple
+        
+        ret = getargs_tuple(1, (2, 3))
+        self.assertEquals(ret, (1,2,3))
+
+        # make sure invalid tuple arguments are handled correctly
+        class seq:
+            def __len__(self):
+                return 2
+            def __getitem__(self, n):
+                raise ValueError
+        self.assertRaises(TypeError, getargs_tuple, 1, seq())
+
+
 def test_main():
-    tests = [Signed_TestCase, Unsigned_TestCase]
+    tests = [Signed_TestCase, Unsigned_TestCase, Tuple_TestCase]
     try:
         from _testcapi import getargs_L, getargs_K
     except ImportError:
index 6ac2572f1158c320bcf3defc662677ac678bad74..287099b2d9065d2fef53af4d3a99bfbacc767a6d 100644 (file)
@@ -294,6 +294,16 @@ test_L_code(PyObject *self)
 
 #endif /* ifdef HAVE_LONG_LONG */
 
+/* Test tuple argument processing */
+static PyObject *
+getargs_tuple(PyObject *self, PyObject *args)
+{
+       int a, b, c;
+       if (!PyArg_ParseTuple(args, "i(ii)", &a, &b, &c))
+               return NULL;
+       return Py_BuildValue("iii", a, b, c);
+}
+
 /* Functions to call PyArg_ParseTuple with integer format codes,
    and return the result.
 */
@@ -804,6 +814,7 @@ static PyMethodDef TestMethods[] = {
        {"test_k_code",         (PyCFunction)test_k_code,        METH_NOARGS},
        {"test_null_strings",   (PyCFunction)test_null_strings,  METH_NOARGS},
 
+       {"getargs_tuple",       (PyCFunction)getargs_tuple,      METH_VARARGS},
        {"getargs_b",           (PyCFunction)getargs_b,          METH_VARARGS},
        {"getargs_B",           (PyCFunction)getargs_B,          METH_VARARGS},
        {"getargs_H",           (PyCFunction)getargs_H,          METH_VARARGS},
index 2d231ce14c34c42935239605fad99b078d87627a..537cf905872398332174cd1f50d3117849d3af52 100644 (file)
@@ -144,6 +144,9 @@ vgetargs1(PyObject *args, char *format, va_list *p_va, int compat)
                        if (level == 0)
                                max++;
                        level++;
+                       if (level >= 30)
+                               Py_FatalError("too many tuple nesting levels "
+                                             "in argument format string");
                        break;
                case ')':
                        if (level == 0)
@@ -287,8 +290,8 @@ seterror(int iarg, char *msg, int *levels, char *fname, char *message)
                                      "argument %d", iarg);
                        i = 0;
                        p += strlen(p);
-                       while (levels[i] > 0 && (int)(p-buf) < 220) {
-                               PyOS_snprintf(p, sizeof(buf) - (buf - p),
+                       while (levels[i] > 0 && i < 32 && (int)(p-buf) < 220) {
+                               PyOS_snprintf(p, sizeof(buf) - (p - buf),
                                              ", item %d", levels[i]-1);
                                p += strlen(p);
                                i++;
@@ -374,6 +377,13 @@ converttuple(PyObject *arg, char **p_format, va_list *p_va, int *levels,
                char *msg;
                PyObject *item;
                item = PySequence_GetItem(arg, i);
+               if (item == NULL) {
+                       PyErr_Clear();
+                       levels[0] = i+1;
+                       levels[1] = 0;
+                       strncpy(msgbuf, "is not retrievable", bufsize);
+                       return msgbuf;
+               }
                msg = convertitem(item, &format, p_va, levels+1, msgbuf,
                                  bufsize, freelist);
                /* PySequence_GetItem calls tp->sq_item, which INCREFs */
@@ -1361,6 +1371,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, char *format,
                else {
                        msg = skipitem(&format, p_va);
                        if (msg) {
+                               levels[0] = 0;
                                seterror(i+1, msg, levels, fname, message);
                                return cleanreturn(0, freelist);
                        }