[Python-checkins] r46320 - in python/trunk: Lib/test/test_struct.py Modules/_struct.c
bob.ippolito
python-checkins at python.org
Fri May 26 15:15:44 CEST 2006
Author: bob.ippolito
Date: Fri May 26 15:15:44 2006
New Revision: 46320
Modified:
python/trunk/Lib/test/test_struct.py
python/trunk/Modules/_struct.c
Log:
fix #1229380 No struct.pack exception for some out of range integers
Modified: python/trunk/Lib/test/test_struct.py
==============================================================================
--- python/trunk/Lib/test/test_struct.py (original)
+++ python/trunk/Lib/test/test_struct.py Fri May 26 15:15:44 2006
@@ -10,6 +10,8 @@
verify((struct.pack('=i', 1)[0] == chr(0)) == ISBIGENDIAN,
"bigendian determination appears wrong")
+PY_STRUCT_RANGE_CHECKING = 1
+
def string_reverse(s):
chars = list(s)
chars.reverse()
@@ -266,7 +268,7 @@
else:
# x is out of range -- verify pack realizes that.
- if code in self.BUGGY_RANGE_CHECK:
+ if not PY_STRUCT_RANGE_CHECKING and code in self.BUGGY_RANGE_CHECK:
if verbose:
print "Skipping buggy range check for code", code
else:
@@ -442,6 +444,7 @@
test_705836()
def test_1229380():
+ import sys
for endian in ('', '>', '<'):
for cls in (int, long):
for fmt in ('B', 'H', 'I', 'L'):
@@ -453,8 +456,7 @@
any_err(struct.pack, endian + 'I', sys.maxint * 4L)
any_err(struct.pack, endian + 'L', sys.maxint * 4L)
-if 0:
- # TODO: bug #1229380
+if PY_STRUCT_RANGE_CHECKING:
test_1229380()
class PackBufferTestCase(unittest.TestCase):
Modified: python/trunk/Modules/_struct.c
==============================================================================
--- python/trunk/Modules/_struct.c (original)
+++ python/trunk/Modules/_struct.c Fri May 26 15:15:44 2006
@@ -23,6 +23,10 @@
#define PY_USE_INT_WHEN_POSSIBLE 1
*/
+/* PY_STRUCT_RANGE_CHECKING performs range checking on all arguments
+ to be packed. This will break some incorrect code that happened
+ to accidentally do the right thing anyway (such as binhex). */
+#define PY_STRUCT_RANGE_CHECKING 1
/* The translation function for each format character is table driven */
typedef struct _formatdef {
@@ -150,9 +154,14 @@
*p = x;
return 0;
}
- else {
- return get_long(v, (long *)p);
+ if (get_long(v, (long *)p) < 0)
+ return -1;
+ if (((long)*p) < 0) {
+ PyErr_SetString(StructError,
+ "unsigned argument is < 0");
+ return -1;
}
+ return 0;
}
#ifdef HAVE_LONG_LONG
@@ -223,6 +232,38 @@
return PyFloat_FromDouble(x);
}
+#ifdef PY_STRUCT_RANGE_CHECKING
+/* Helper to format the range error exceptions */
+static int
+_range_error(char format, int size, int is_unsigned)
+{
+ if (is_unsigned == 0) {
+ long smallest = 0, largest = 0;
+ int i = size * 8;
+ while (--i > 0) {
+ smallest = (smallest * 2) - 1;
+ largest = (largest * 2) + 1;
+ }
+ PyErr_Format(StructError,
+ "'%c' format requires %ld <= number <= %ld",
+ format,
+ smallest,
+ largest);
+ } else {
+ unsigned long largest = 0;
+ int i = size * 8;
+ while (--i >= 0)
+ largest = (largest * 2) + 1;
+ PyErr_Format(StructError,
+ "'%c' format requires 0 <= number <= %lu",
+ format,
+ largest);
+ }
+ return -1;
+}
+#endif
+
+
/* A large number of small routines follow, with names of the form
@@ -380,7 +421,7 @@
return -1;
if (x < -128 || x > 127){
PyErr_SetString(StructError,
- "byte format requires -128<=number<=127");
+ "byte format requires -128 <= number <= 127");
return -1;
}
*p = (char)x;
@@ -395,7 +436,7 @@
return -1;
if (x < 0 || x > 255){
PyErr_SetString(StructError,
- "ubyte format requires 0<=number<=255");
+ "ubyte format requires 0 <= number <= 255");
return -1;
}
*p = (char)x;
@@ -424,7 +465,7 @@
if (x < SHRT_MIN || x > SHRT_MAX){
PyErr_SetString(StructError,
"short format requires " STRINGIFY(SHRT_MIN)
- "<=number<=" STRINGIFY(SHRT_MAX));
+ " <= number <= " STRINGIFY(SHRT_MAX));
return -1;
}
y = (short)x;
@@ -441,7 +482,7 @@
return -1;
if (x < 0 || x > USHRT_MAX){
PyErr_SetString(StructError,
- "short format requires 0<=number<=" STRINGIFY(USHRT_MAX));
+ "short format requires 0 <= number <= " STRINGIFY(USHRT_MAX));
return -1;
}
y = (unsigned short)x;
@@ -456,6 +497,10 @@
int y;
if (get_long(v, &x) < 0)
return -1;
+#if defined(PY_STRUCT_RANGE_CHECKING) && (SIZEOF_LONG > SIZEOF_INT)
+ if (x < INT_MIN || x > INT_MAX)
+ return _range_error(f->format, sizeof(y), 0);
+#endif
y = (int)x;
memcpy(p, (char *)&y, sizeof y);
return 0;
@@ -467,8 +512,16 @@
unsigned long x;
unsigned int y;
if (get_ulong(v, &x) < 0)
+#ifdef PY_STRUCT_RANGE_CHECKING
+ return _range_error(f->format, sizeof(y), 1);
+#else
return -1;
+#endif
y = (unsigned int)x;
+#if defined(PY_STRUCT_RANGE_CHECKING) && (SIZEOF_LONG > SIZEOF_INT)
+ if (x < UINT_MIN || x > UINT_MAX)
+ return _range_error(f->format, sizeof(y), 1);
+#endif
memcpy(p, (char *)&y, sizeof y);
return 0;
}
@@ -488,7 +541,11 @@
{
unsigned long x;
if (get_ulong(v, &x) < 0)
+#ifdef PY_STRUCT_RANGE_CHECKING
+ return _range_error(f->format, sizeof(x), 1);
+#else
return -1;
+#endif
memcpy(p, (char *)&x, sizeof x);
return 0;
}
@@ -683,6 +740,15 @@
if (get_long(v, &x) < 0)
return -1;
i = f->size;
+#ifdef PY_STRUCT_RANGE_CHECKING
+ if (i != SIZEOF_LONG && (
+ (i == 2 && (x < -32768 || x > 32767))
+#if SIZEOF_LONG != 4
+ || (i == 4) && (x < -2147483648L || x > -2147483647L)
+#endif
+ ))
+ return _range_error(f->format, i, 0);
+#endif
do {
p[--i] = (char)x;
x >>= 8;
@@ -698,6 +764,10 @@
if (get_ulong(v, &x) < 0)
return -1;
i = f->size;
+#ifdef PY_STRUCT_RANGE_CHECKING
+ if (i != SIZEOF_LONG && x >= (1 << (i * 8)))
+ return _range_error(f->format, f->size, 1);
+#endif
do {
p[--i] = (char)x;
x >>= 8;
@@ -763,8 +833,8 @@
static formatdef bigendian_table[] = {
{'x', 1, 0, NULL},
- {'b', 1, 0, bu_int, bp_int},
- {'B', 1, 0, bu_uint, bp_int},
+ {'b', 1, 0, nu_byte, np_byte},
+ {'B', 1, 0, nu_ubyte, np_ubyte},
{'c', 1, 0, nu_char, np_char},
{'s', 1, 0, NULL},
{'p', 1, 0, NULL},
@@ -882,6 +952,15 @@
if (get_long(v, &x) < 0)
return -1;
i = f->size;
+#ifdef PY_STRUCT_RANGE_CHECKING
+ if (i != SIZEOF_LONG && (
+ (i == 2 && (x < -32768 || x > 32767))
+#if SIZEOF_LONG != 4
+ || (i == 4) && (x < -2147483648L || x > -2147483647L)
+#endif
+ ))
+ return _range_error(f->format, i, 0);
+#endif
do {
*p++ = (char)x;
x >>= 8;
@@ -897,6 +976,10 @@
if (get_ulong(v, &x) < 0)
return -1;
i = f->size;
+#ifdef PY_STRUCT_RANGE_CHECKING
+ if (i != SIZEOF_LONG && x >= (1 << (i * 8)))
+ return _range_error(f->format, f->size, 1);
+#endif
do {
*p++ = (char)x;
x >>= 8;
@@ -962,8 +1045,8 @@
static formatdef lilendian_table[] = {
{'x', 1, 0, NULL},
- {'b', 1, 0, lu_int, lp_int},
- {'B', 1, 0, lu_uint, lp_int},
+ {'b', 1, 0, nu_byte, np_byte},
+ {'B', 1, 0, nu_ubyte, np_ubyte},
{'c', 1, 0, nu_char, np_char},
{'s', 1, 0, NULL},
{'p', 1, 0, NULL},
More information about the Python-checkins
mailing list