summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFred Drake <fdrake@acm.org>2000-06-28 17:49:30 (GMT)
committerFred Drake <fdrake@acm.org>2000-06-28 17:49:30 (GMT)
commit541dc3b7b2606906e0ee2d9088a984443b1fa64c (patch)
tree5617b98464b3e3190cb34e5652fe265e4c3365f5
parentc82634c13cce7d846236eba8ab345c52cebc3567 (diff)
downloadcpython-541dc3b7b2606906e0ee2d9088a984443b1fa64c.zip
cpython-541dc3b7b2606906e0ee2d9088a984443b1fa64c.tar.gz
cpython-541dc3b7b2606906e0ee2d9088a984443b1fa64c.tar.bz2
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.
-rw-r--r--Modules/arraymodule.c105
1 files changed, 95 insertions, 10 deletions
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
index 7966e0a..96ec793 100644
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -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 [] =