Skip to content

Commit 5f13578

Browse files
committed
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).
1 parent 0619a32 commit 5f13578

3 files changed

Lines changed: 39 additions & 3 deletions

File tree

Lib/test/test_getargs2.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,25 @@ def test_K(self):
233233

234234
self.failUnlessEqual(VERY_LARGE & ULLONG_MAX, getargs_K(VERY_LARGE))
235235

236+
237+
class Tuple_TestCase(unittest.TestCase):
238+
def test_tuple(self):
239+
from _testcapi import getargs_tuple
240+
241+
ret = getargs_tuple(1, (2, 3))
242+
self.assertEquals(ret, (1,2,3))
243+
244+
# make sure invalid tuple arguments are handled correctly
245+
class seq:
246+
def __len__(self):
247+
return 2
248+
def __getitem__(self, n):
249+
raise ValueError
250+
self.assertRaises(TypeError, getargs_tuple, 1, seq())
251+
252+
236253
def test_main():
237-
tests = [Signed_TestCase, Unsigned_TestCase]
254+
tests = [Signed_TestCase, Unsigned_TestCase, Tuple_TestCase]
238255
try:
239256
from _testcapi import getargs_L, getargs_K
240257
except ImportError:

Modules/_testcapimodule.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,16 @@ test_L_code(PyObject *self)
294294

295295
#endif /* ifdef HAVE_LONG_LONG */
296296

297+
/* Test tuple argument processing */
298+
static PyObject *
299+
getargs_tuple(PyObject *self, PyObject *args)
300+
{
301+
int a, b, c;
302+
if (!PyArg_ParseTuple(args, "i(ii)", &a, &b, &c))
303+
return NULL;
304+
return Py_BuildValue("iii", a, b, c);
305+
}
306+
297307
/* Functions to call PyArg_ParseTuple with integer format codes,
298308
and return the result.
299309
*/
@@ -707,6 +717,7 @@ static PyMethodDef TestMethods[] = {
707717
{"test_null_strings", (PyCFunction)test_null_strings, METH_NOARGS},
708718
{"test_string_from_format", (PyCFunction)test_string_from_format, METH_NOARGS},
709719

720+
{"getargs_tuple", getargs_tuple, METH_VARARGS},
710721
{"getargs_b", getargs_b, METH_VARARGS},
711722
{"getargs_B", getargs_B, METH_VARARGS},
712723
{"getargs_H", getargs_H, METH_VARARGS},

Python/getargs.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -351,8 +351,8 @@ seterror(int iarg, const char *msg, int *levels, const char *fname,
351351
"argument %d", iarg);
352352
i = 0;
353353
p += strlen(p);
354-
while (levels[i] > 0 && (int)(p-buf) < 220) {
355-
PyOS_snprintf(p, sizeof(buf) - (buf - p),
354+
while (levels[i] > 0 && i < 32 && (int)(p-buf) < 220) {
355+
PyOS_snprintf(p, sizeof(buf) - (p - buf),
356356
", item %d", levels[i]-1);
357357
p += strlen(p);
358358
i++;
@@ -439,6 +439,13 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
439439
char *msg;
440440
PyObject *item;
441441
item = PySequence_GetItem(arg, i);
442+
if (item == NULL) {
443+
PyErr_Clear();
444+
levels[0] = i+1;
445+
levels[1] = 0;
446+
strncpy(msgbuf, "is not retrievable", bufsize);
447+
return msgbuf;
448+
}
442449
msg = convertitem(item, &format, p_va, flags, levels+1,
443450
msgbuf, bufsize, freelist);
444451
/* PySequence_GetItem calls tp->sq_item, which INCREFs */
@@ -1509,6 +1516,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,
15091516
else {
15101517
msg = skipitem(&format, p_va, flags);
15111518
if (msg) {
1519+
levels[0] = 0;
15121520
seterror(i+1, msg, levels, fname, message);
15131521
return cleanreturn(0, freelist);
15141522
}

0 commit comments

Comments
 (0)