]> granicus.if.org Git - python/commitdiff
Part of bug #1523610: fix miscalculation of buffer length.
authorGeorg Brandl <georg@python.org>
Wed, 26 Jul 2006 08:03:10 +0000 (08:03 +0000)
committerGeorg Brandl <georg@python.org>
Wed, 26 Jul 2006 08:03:10 +0000 (08:03 +0000)
Also add a guard against NULL in converttuple and add a test case
(that previously would have crashed).

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

index 10481b01ab797827928d2ef86da34abde119471b..0d9cbd67825ce3cf5fadbab16494bf77c559bcd8 100644 (file)
@@ -233,8 +233,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 6b9dffde464356700e6cb8bb246c2609c1237c8e..b90ca5763c9c8aac96db7d0d09fbea334e2dd9e5 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.
 */
@@ -707,6 +717,7 @@ static PyMethodDef TestMethods[] = {
        {"test_null_strings",   (PyCFunction)test_null_strings,  METH_NOARGS},
        {"test_string_from_format", (PyCFunction)test_string_from_format, METH_NOARGS},
 
+       {"getargs_tuple",       getargs_tuple,                   METH_VARARGS},
        {"getargs_b",           getargs_b,                       METH_VARARGS},
        {"getargs_B",           getargs_B,                       METH_VARARGS},
        {"getargs_H",           getargs_H,                       METH_VARARGS},
index 1552790ef0805281b58051175a73f8abfeca9bb7..508055e6905bccce832f01d5e5b6664b5c939ed0 100644 (file)
@@ -351,8 +351,8 @@ seterror(int iarg, const char *msg, int *levels, const char *fname,
                                      "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++;
@@ -439,6 +439,13 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
                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, flags, levels+1, 
                                  msgbuf, bufsize, freelist);
                /* PySequence_GetItem calls tp->sq_item, which INCREFs */
@@ -1509,6 +1516,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,
                else {
                        msg = skipitem(&format, p_va, flags);
                        if (msg) {
+                               levels[0] = 0;
                                seterror(i+1, msg, levels, fname, message);
                                return cleanreturn(0, freelist);
                        }