Commit 541dc3b7 authored by Fred Drake's avatar Fred Drake

Trent Mick <trentm@activestate.com>:

The cause: Relatively recent (last month) patches to getargs.c added
overflow checking to the PyArg_Parse*() integral formatters thereby
restricting 'b' to unsigned char value and 'h','i', and 'l' to signed
integral values (i.e. if the incoming value is outside of the
specified bounds you get an OverflowError, previous it silently
overflowed).

The problem: This broke the array module (as Fredrik pointed out)
because *its* formatters relied on the loose allowance of signed and
unsigned ranges being able to pass through PyArg_Parse*()'s
formatters.

The fix: This patch fixes the array module to work with the more
strict bounds checking now in PyArg_Parse*().

How: If the type signature of a formatter in the arraymodule exactly
matches one in PyArg_Parse*(), then use that directly. If there is no
equivalent type signature in PyArg_Parse*() (e.g. there is no unsigned
int formatter in PyArg_Parse*()), then use the next one up and do some
extra bounds checking in the array module.

This partially closes SourceForge patch #100506.
parent c82634c1
......@@ -114,11 +114,24 @@ b_setitem(ap, i, v)
int i;
PyObject *v;
{
char x;
if (!PyArg_Parse(v, "b;array item must be integer", &x))
short x;
/* PyArg_Parse's 'b' formatter is for an unsigned char, therefore
must use the next size up that is signed ('h') and manually do
the overflow checking */
if (!PyArg_Parse(v, "h;array item must be integer", &x))
return -1;
else if (x < CHAR_MIN) {
PyErr_SetString(PyExc_OverflowError,
"signed char is less than minimum");
return -1;
}
else if (x > CHAR_MAX) {
PyErr_SetString(PyExc_OverflowError,
"signed char is greater than maximum");
return -1;
}
if (i >= 0)
((char *)ap->ob_item)[i] = x;
((char *)ap->ob_item)[i] = (char)x;
return 0;
}
......@@ -131,7 +144,20 @@ BB_getitem(ap, i)
return PyInt_FromLong(x);
}
#define BB_setitem b_setitem
static int
BB_setitem(ap, i, v)
arrayobject *ap;
int i;
PyObject *v;
{
unsigned char x;
/* 'B' == unsigned char, maps to PyArg_Parse's 'b' formatter */
if (!PyArg_Parse(v, "b;array item must be integer", &x))
return -1;
if (i >= 0)
((char *)ap->ob_item)[i] = x;
return 0;
}
static PyObject *
h_getitem(ap, i)
......@@ -148,6 +174,7 @@ h_setitem(ap, i, v)
PyObject *v;
{
short x;
/* 'h' == signed short, maps to PyArg_Parse's 'h' formatter */
if (!PyArg_Parse(v, "h;array item must be integer", &x))
return -1;
if (i >= 0)
......@@ -163,7 +190,31 @@ HH_getitem(ap, i)
return PyInt_FromLong((long) ((unsigned short *)ap->ob_item)[i]);
}
#define HH_setitem h_setitem
static int
HH_setitem(ap, i, v)
arrayobject *ap;
int i;
PyObject *v;
{
int x;
/* PyArg_Parse's 'h' formatter is for a signed short, therefore
must use the next size up and manually do the overflow checking */
if (!PyArg_Parse(v, "i;array item must be integer", &x))
return -1;
else if (x < 0) {
PyErr_SetString(PyExc_OverflowError,
"unsigned short is less than minimum");
return -1;
}
else if (x > USHRT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"unsigned short is greater than maximum");
return -1;
}
if (i >= 0)
((short *)ap->ob_item)[i] = (short)x;
return 0;
}
static PyObject *
i_getitem(ap, i)
......@@ -180,6 +231,7 @@ i_setitem(ap, i, v)
PyObject *v;
{
int x;
/* 'i' == signed int, maps to PyArg_Parse's 'i' formatter */
if (!PyArg_Parse(v, "i;array item must be integer", &x))
return -1;
if (i >= 0)
......@@ -209,11 +261,25 @@ II_setitem(ap, i, v)
return -1;
}
else {
if (!PyArg_Parse(v, "l;array item must be integer", &x))
long y;
if (!PyArg_Parse(v, "l;array item must be integer", &y))
return -1;
if (y < 0) {
PyErr_SetString(PyExc_OverflowError,
"unsigned int is less than minimum");
return -1;
}
x = (unsigned long)y;
}
if (x > UINT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"unsigned int is greater than maximum");
return -1;
}
if (i >= 0)
((unsigned int *)ap->ob_item)[i] = x;
((unsigned int *)ap->ob_item)[i] = (unsigned int)x;
return 0;
}
......@@ -260,9 +326,23 @@ LL_setitem(ap, i, v)
return -1;
}
else {
if (!PyArg_Parse(v, "l;array item must be integer", &x))
long y;
if (!PyArg_Parse(v, "l;array item must be integer", &y))
return -1;
if (y < 0) {
PyErr_SetString(PyExc_OverflowError,
"unsigned long is less than minimum");
return -1;
}
x = (unsigned long)y;
}
if (x > ULONG_MAX) {
PyErr_SetString(PyExc_OverflowError,
"unsigned long is greater than maximum");
return -1;
}
if (i >= 0)
((unsigned long *)ap->ob_item)[i] = x;
return 0;
......@@ -725,8 +805,13 @@ array_buffer_info(self, args)
arrayobject *self;
PyObject *args;
{
return Py_BuildValue("ll",
(long)(self->ob_item), (long)(self->ob_size));
PyObject* retval = PyTuple_New(2);
if (!retval) return NULL;
PyTuple_SET_ITEM(retval, 0, PyLong_FromVoidPtr(self->ob_item));
PyTuple_SET_ITEM(retval, 1, PyInt_FromLong((long)(self->ob_size)));
return retval;
}
static char buffer_info_doc [] =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment