[Python-checkins] CVS: python/dist/src/Modules arraymodule.c,2.40,2.41

Fred L. Drake python-dev@python.org
Wed, 28 Jun 2000 10:49:32 -0700


Update of /cvsroot/python/python/dist/src/Modules
In directory slayer.i.sourceforge.net:/tmp/cvs-serv31291/Modules

Modified Files:
	arraymodule.c 
Log Message:
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.


Index: arraymodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/arraymodule.c,v
retrieving revision 2.40
retrieving revision 2.41
diff -C2 -r2.40 -r2.41
*** arraymodule.c	2000/06/01 02:02:46	2.40
--- arraymodule.c	2000/06/28 17:49:30	2.41
***************
*** 115,123 ****
  	PyObject *v;
  {
! 	char x;
! 	if (!PyArg_Parse(v, "b;array item must be integer", &x))
  		return -1;
  	if (i >= 0)
! 		     ((char *)ap->ob_item)[i] = x;
  	return 0;
  }
--- 115,136 ----
  	PyObject *v;
  {
! 	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] = (char)x;
  	return 0;
  }
***************
*** 132,136 ****
  }
  
! #define BB_setitem b_setitem
  
  static PyObject *
--- 145,162 ----
  }
  
! 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 *
***************
*** 149,152 ****
--- 175,179 ----
  {
  	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;
***************
*** 164,168 ****
  }
  
! #define HH_setitem h_setitem
  
  static PyObject *
--- 191,219 ----
  }
  
! 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 *
***************
*** 181,184 ****
--- 232,236 ----
  {
  	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;
***************
*** 210,218 ****
  	}
  	else {
! 		if (!PyArg_Parse(v, "l;array item must be integer", &x))
  			return -1;
  	}
  	if (i >= 0)
! 		((unsigned int *)ap->ob_item)[i] = x;
  	return 0;
  }
--- 262,284 ----
  	}
  	else {
! 		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] = (unsigned int)x;
  	return 0;
  }
***************
*** 261,267 ****
  	}
  	else {
! 		if (!PyArg_Parse(v, "l;array item must be integer", &x))
  			return -1;
  	}
  	if (i >= 0)
  		((unsigned long *)ap->ob_item)[i] = x;
--- 327,347 ----
  	}
  	else {
! 		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;
***************
*** 726,731 ****
  	PyObject *args;
  {
! 	return Py_BuildValue("ll",
! 			     (long)(self->ob_item), (long)(self->ob_size));
  }
  
--- 806,816 ----
  	PyObject *args;
  {
! 	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;
  }