From 5f135787ec4040bfbeb16f2944086028635151db Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Wed, 26 Jul 2006 08:03:10 +0000 Subject: Part of bug #1523610: fix miscalculation of buffer length. Also add a guard against NULL in converttuple and add a test case (that previously would have crashed). --- Lib/test/test_getargs2.py | 19 ++++++++++++++++++- Modules/_testcapimodule.c | 11 +++++++++++ Python/getargs.c | 12 ++++++++++-- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_getargs2.py b/Lib/test/test_getargs2.py index 10481b0..0d9cbd6 100644 --- a/Lib/test/test_getargs2.py +++ b/Lib/test/test_getargs2.py @@ -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: diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 6b9dffd..b90ca57 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -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}, diff --git a/Python/getargs.c b/Python/getargs.c index 1552790..508055e 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -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); } -- cgit v0.12