[Python-checkins] r51159 - in python/branches/release24-maint: Lib/test/test_getargs2.py Modules/_testcapimodule.c Python/getargs.c

georg.brandl python-checkins at python.org
Wed Aug 9 09:15:30 CEST 2006


Author: georg.brandl
Date: Wed Aug  9 09:15:29 2006
New Revision: 51159

Modified:
   python/branches/release24-maint/Lib/test/test_getargs2.py
   python/branches/release24-maint/Modules/_testcapimodule.c
   python/branches/release24-maint/Python/getargs.c
Log:
Backport fixes for #1523610 (crashes in PyArg_ParseTuple):
rev. 51158 and rev. 50843.



Modified: python/branches/release24-maint/Lib/test/test_getargs2.py
==============================================================================
--- python/branches/release24-maint/Lib/test/test_getargs2.py	(original)
+++ python/branches/release24-maint/Lib/test/test_getargs2.py	Wed Aug  9 09:15:29 2006
@@ -216,8 +216,25 @@
 
         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:

Modified: python/branches/release24-maint/Modules/_testcapimodule.c
==============================================================================
--- python/branches/release24-maint/Modules/_testcapimodule.c	(original)
+++ python/branches/release24-maint/Modules/_testcapimodule.c	Wed Aug  9 09:15:29 2006
@@ -294,6 +294,16 @@
 
 #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 @@
 	{"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},

Modified: python/branches/release24-maint/Python/getargs.c
==============================================================================
--- python/branches/release24-maint/Python/getargs.c	(original)
+++ python/branches/release24-maint/Python/getargs.c	Wed Aug  9 09:15:29 2006
@@ -144,6 +144,9 @@
 			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 @@
 				      "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 @@
 		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 @@
 		else {
 			msg = skipitem(&format, p_va);
 			if (msg) {
+				levels[0] = 0;
 				seterror(i+1, msg, levels, fname, message);
 				return cleanreturn(0, freelist);
 			}


More information about the Python-checkins mailing list