summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Dickinson <dickinsm@gmail.com>2009-03-21 10:26:31 (GMT)
committerMark Dickinson <dickinsm@gmail.com>2009-03-21 10:26:31 (GMT)
commitae681df4d8a0edf22a60e853d519c42012c31983 (patch)
treeac82dce2c3d3615e476e383968aff0370861b806
parente43b060b05e3d99f83bc900e5efc5cdb34298888 (diff)
downloadcpython-ae681df4d8a0edf22a60e853d519c42012c31983.zip
cpython-ae681df4d8a0edf22a60e853d519c42012c31983.tar.gz
cpython-ae681df4d8a0edf22a60e853d519c42012c31983.tar.bz2
- Issue #5463: In struct module, remove deprecated overflow wrapping
when packing an integer: for example, struct.pack('=L', -1) now raises struct.error instead of returning b'\xff\xff\xff\xff'. Thanks Andreas Schawo for the patch.
-rw-r--r--Lib/test/test_struct.py12
-rw-r--r--Misc/ACKS1
-rw-r--r--Misc/NEWS7
-rw-r--r--Modules/_struct.c189
4 files changed, 16 insertions, 193 deletions
diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py
index 3d5e028..1d10b8f 100644
--- a/Lib/test/test_struct.py
+++ b/Lib/test/test_struct.py
@@ -2,8 +2,6 @@ import array
import unittest
import struct
import warnings
-warnings.filterwarnings("ignore", "struct integer overflow masking is deprecated",
- DeprecationWarning)
from functools import wraps
from test.support import TestFailed, verbose, run_unittest
@@ -17,11 +15,9 @@ try:
import _struct
except ImportError:
PY_STRUCT_RANGE_CHECKING = 0
- PY_STRUCT_OVERFLOW_MASKING = 1
PY_STRUCT_FLOAT_COERCE = 2
else:
PY_STRUCT_RANGE_CHECKING = getattr(_struct, '_PY_STRUCT_RANGE_CHECKING', 0)
- PY_STRUCT_OVERFLOW_MASKING = getattr(_struct, '_PY_STRUCT_OVERFLOW_MASKING', 0)
PY_STRUCT_FLOAT_COERCE = getattr(_struct, '_PY_STRUCT_FLOAT_COERCE', 0)
def string_reverse(s):
@@ -51,8 +47,7 @@ def deprecated_err(func, *args):
except (struct.error, OverflowError):
pass
except DeprecationWarning:
- if not PY_STRUCT_OVERFLOW_MASKING:
- raise TestFailed("%s%s expected to raise DeprecationWarning" % (
+ raise TestFailed("%s%s expected to raise DeprecationWarning" % (
func.__name__, args))
else:
raise TestFailed("%s%s did not raise error" % (
@@ -471,11 +466,6 @@ class StructTest(unittest.TestCase):
self.check_float_coerce(endian + fmt, 1.0)
self.check_float_coerce(endian + fmt, 1.5)
- def test_issue4228(self):
- # Packing a long may yield either 32 or 64 bits
- x = struct.pack('L', -1)[:4]
- self.assertEqual(x, b'\xff'*4)
-
def test_unpack_from(self):
test_string = b'abcd01234'
fmt = '4s'
diff --git a/Misc/ACKS b/Misc/ACKS
index 7084f21..85bc8a1 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -620,6 +620,7 @@ Ilya Sandler
Ty Sarna
Ben Sayer
Michael Scharf
+Andreas Schawo
Neil Schemenauer
David Scherer
Gregor Schmid
diff --git a/Misc/NEWS b/Misc/NEWS
index 3e890f3..bad0a44 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -44,6 +44,13 @@ Library
- Issue #5016: FileIO.seekable() could return False if the file position
was negative when truncated to a C int. Patch by Victor Stinner.
+Extension Modules
+-----------------
+
+- Issue #5463: In struct module, remove deprecated overflow wrapping
+ when packing an integer: struct.pack('=L', -1) now raises
+ struct.error instead of returning b'\xff\xff\xff\xff'.
+
What's New in Python 3.1 alpha 1
================================
diff --git a/Modules/_struct.c b/Modules/_struct.c
index 57441c4..3cc9fa0 100644
--- a/Modules/_struct.c
+++ b/Modules/_struct.c
@@ -12,20 +12,6 @@
static PyTypeObject PyStructType;
-/* If PY_STRUCT_OVERFLOW_MASKING is defined, the struct module will wrap all input
- numbers for explicit endians such that they fit in the given type, much
- like explicit casting in C. A warning will be raised if the number did
- not originally fit within the range of the requested type. If it is
- not defined, then all range errors and overflow will be struct.error
- exceptions. */
-
-#define PY_STRUCT_OVERFLOW_MASKING 1
-
-#ifdef PY_STRUCT_OVERFLOW_MASKING
-static PyObject *pylong_ulong_mask = NULL;
-static PyObject *pyint_zero = NULL;
-#endif
-
/* If PY_STRUCT_FLOAT_COERCE is defined, the struct module will allow float
arguments for integer formats with a warning for backwards
compatibility. */
@@ -237,107 +223,9 @@ get_ulonglong(PyObject *v, unsigned PY_LONG_LONG *p)
#endif
-#ifdef PY_STRUCT_OVERFLOW_MASKING
-
-/* Helper routine to get a Python integer and raise the appropriate error
- if it isn't one */
-
-#define INT_OVERFLOW "struct integer overflow masking is deprecated"
-static int
-get_wrapped_long(PyObject *v, long *p)
-{
- if (get_long(v, p) < 0) {
- if (PyLong_Check(v) &&
- PyErr_ExceptionMatches(PyExc_OverflowError)) {
- PyObject *wrapped;
- long x;
- PyErr_Clear();
-#ifdef PY_STRUCT_FLOAT_COERCE
- if (PyFloat_Check(v)) {
- PyObject *o;
- int res;
- PyErr_Clear();
- if (PyErr_WarnEx(PyExc_DeprecationWarning, FLOAT_COERCE, 2) < 0)
- return -1;
- o = PyNumber_Long(v);
- if (o == NULL)
- return -1;
- res = get_wrapped_long(o, p);
- Py_DECREF(o);
- return res;
- }
-#endif
- if (PyErr_WarnEx(PyExc_DeprecationWarning, INT_OVERFLOW, 2) < 0)
- return -1;
- wrapped = PyNumber_And(v, pylong_ulong_mask);
- if (wrapped == NULL)
- return -1;
- x = (long)PyLong_AsUnsignedLong(wrapped);
- Py_DECREF(wrapped);
- if (x == -1 && PyErr_Occurred())
- return -1;
- *p = x;
- } else {
- return -1;
- }
- }
- return 0;
-}
-
-static int
-get_wrapped_ulong(PyObject *v, unsigned long *p)
-{
- long x = (long)PyLong_AsUnsignedLong(v);
- if (x == -1 && PyErr_Occurred()) {
- PyObject *wrapped;
- PyErr_Clear();
-#ifdef PY_STRUCT_FLOAT_COERCE
- if (PyFloat_Check(v)) {
- PyObject *o;
- int res;
- PyErr_Clear();
- if (PyErr_WarnEx(PyExc_DeprecationWarning, FLOAT_COERCE, 2) < 0)
- return -1;
- o = PyNumber_Long(v);
- if (o == NULL)
- return -1;
- res = get_wrapped_ulong(o, p);
- Py_DECREF(o);
- return res;
- }
-#endif
- wrapped = PyNumber_And(v, pylong_ulong_mask);
- if (wrapped == NULL)
- return -1;
- if (PyErr_WarnEx(PyExc_DeprecationWarning, INT_OVERFLOW, 2) < 0) {
- Py_DECREF(wrapped);
- return -1;
- }
- x = (long)PyLong_AsUnsignedLong(wrapped);
- Py_DECREF(wrapped);
- if (x == -1 && PyErr_Occurred())
- return -1;
- }
- *p = (unsigned long)x;
- return 0;
-}
-
-#define RANGE_ERROR(x, f, flag, mask) \
- do { \
- if (_range_error(f, flag) < 0) \
- return -1; \
- else \
- (x) &= (mask); \
- } while (0)
-
-#else
-
-#define get_wrapped_long get_long
-#define get_wrapped_ulong get_ulong
#define RANGE_ERROR(x, f, flag, mask) return _range_error(f, flag)
-#endif
/* Floating point helpers */
@@ -392,26 +280,7 @@ _range_error(const formatdef *f, int is_unsigned)
~ largest,
largest);
}
-#ifdef PY_STRUCT_OVERFLOW_MASKING
- {
- PyObject *ptype, *pvalue, *ptraceback;
- PyObject *msg;
- int rval;
- PyErr_Fetch(&ptype, &pvalue, &ptraceback);
- assert(pvalue != NULL);
- msg = PyObject_Str(pvalue);
- Py_XDECREF(ptype);
- Py_XDECREF(pvalue);
- Py_XDECREF(ptraceback);
- if (msg == NULL)
- return -1;
- rval = PyErr_WarnEx(PyExc_DeprecationWarning,
- _PyUnicode_AsString(msg), 2);
- Py_DECREF(msg);
- if (rval == 0)
- return 0;
- }
-#endif
+
return -1;
}
@@ -673,7 +542,7 @@ np_uint(char *p, PyObject *v, const formatdef *f)
{
unsigned long x;
unsigned int y;
- if (get_wrapped_ulong(v, &x) < 0)
+ if (get_ulong(v, &x) < 0)
return -1;
y = (unsigned int)x;
#if (SIZEOF_LONG > SIZEOF_INT)
@@ -698,7 +567,7 @@ static int
np_ulong(char *p, PyObject *v, const formatdef *f)
{
unsigned long x;
- if (get_wrapped_ulong(v, &x) < 0)
+ if (get_ulong(v, &x) < 0)
return -1;
memcpy(p, (char *)&x, sizeof x);
return 0;
@@ -905,7 +774,7 @@ bp_int(char *p, PyObject *v, const formatdef *f)
{
long x;
Py_ssize_t i;
- if (get_wrapped_long(v, &x) < 0)
+ if (get_long(v, &x) < 0)
return -1;
i = f->size;
if (i != SIZEOF_LONG) {
@@ -915,10 +784,6 @@ bp_int(char *p, PyObject *v, const formatdef *f)
else if ((i == 4) && (x < -2147483648L || x > 2147483647L))
RANGE_ERROR(x, f, 0, 0xffffffffL);
#endif
-#ifdef PY_STRUCT_OVERFLOW_MASKING
- else if ((i == 1) && (x < -128 || x > 127))
- RANGE_ERROR(x, f, 0, 0xffL);
-#endif
}
do {
p[--i] = (char)x;
@@ -932,7 +797,7 @@ bp_uint(char *p, PyObject *v, const formatdef *f)
{
unsigned long x;
Py_ssize_t i;
- if (get_wrapped_ulong(v, &x) < 0)
+ if (get_ulong(v, &x) < 0)
return -1;
i = f->size;
if (i != SIZEOF_LONG) {
@@ -1015,14 +880,8 @@ bp_bool(char *p, PyObject *v, const formatdef *f)
static formatdef bigendian_table[] = {
{'x', 1, 0, NULL},
-#ifdef PY_STRUCT_OVERFLOW_MASKING
- /* Native packers do range checking without overflow masking. */
- {'b', 1, 0, nu_byte, bp_int},
- {'B', 1, 0, nu_ubyte, bp_uint},
-#else
{'b', 1, 0, nu_byte, np_byte},
{'B', 1, 0, nu_ubyte, np_ubyte},
-#endif
{'c', 1, 0, nu_char, np_char},
{'s', 1, 0, NULL},
{'p', 1, 0, NULL},
@@ -1133,7 +992,7 @@ lp_int(char *p, PyObject *v, const formatdef *f)
{
long x;
Py_ssize_t i;
- if (get_wrapped_long(v, &x) < 0)
+ if (get_long(v, &x) < 0)
return -1;
i = f->size;
if (i != SIZEOF_LONG) {
@@ -1143,10 +1002,6 @@ lp_int(char *p, PyObject *v, const formatdef *f)
else if ((i == 4) && (x < -2147483648L || x > 2147483647L))
RANGE_ERROR(x, f, 0, 0xffffffffL);
#endif
-#ifdef PY_STRUCT_OVERFLOW_MASKING
- else if ((i == 1) && (x < -128 || x > 127))
- RANGE_ERROR(x, f, 0, 0xffL);
-#endif
}
do {
*p++ = (char)x;
@@ -1160,7 +1015,7 @@ lp_uint(char *p, PyObject *v, const formatdef *f)
{
unsigned long x;
Py_ssize_t i;
- if (get_wrapped_ulong(v, &x) < 0)
+ if (get_ulong(v, &x) < 0)
return -1;
i = f->size;
if (i != SIZEOF_LONG) {
@@ -1234,14 +1089,8 @@ lp_double(char *p, PyObject *v, const formatdef *f)
static formatdef lilendian_table[] = {
{'x', 1, 0, NULL},
-#ifdef PY_STRUCT_OVERFLOW_MASKING
- /* Native packers do range checking without overflow masking. */
- {'b', 1, 0, nu_byte, lp_int},
- {'B', 1, 0, nu_ubyte, lp_uint},
-#else
{'b', 1, 0, nu_byte, np_byte},
{'B', 1, 0, nu_ubyte, np_ubyte},
-#endif
{'c', 1, 0, nu_char, np_char},
{'s', 1, 0, NULL},
{'p', 1, 0, NULL},
@@ -2125,26 +1974,6 @@ PyInit__struct(void)
if (PyType_Ready(&PyStructType) < 0)
return NULL;
-#ifdef PY_STRUCT_OVERFLOW_MASKING
- if (pyint_zero == NULL) {
- pyint_zero = PyLong_FromLong(0);
- if (pyint_zero == NULL)
- return NULL;
- }
- if (pylong_ulong_mask == NULL) {
-#if (SIZEOF_LONG == 4)
- pylong_ulong_mask = PyLong_FromString("FFFFFFFF", NULL, 16);
-#else
- pylong_ulong_mask = PyLong_FromString("FFFFFFFFFFFFFFFF", NULL, 16);
-#endif
- if (pylong_ulong_mask == NULL)
- return NULL;
- }
-
-#else
- /* This speed trick can't be used until overflow masking goes away, because
- native endian always raises exceptions instead of overflow masking. */
-
/* Check endian and swap in faster functions */
{
int one = 1;
@@ -2183,7 +2012,6 @@ PyInit__struct(void)
native++;
}
}
-#endif
/* Add some symbolic constants to the module */
if (StructError == NULL) {
@@ -2201,9 +2029,6 @@ PyInit__struct(void)
PyModule_AddObject(m, "__version__", ver);
PyModule_AddIntConstant(m, "_PY_STRUCT_RANGE_CHECKING", 1);
-#ifdef PY_STRUCT_OVERFLOW_MASKING
- PyModule_AddIntConstant(m, "_PY_STRUCT_OVERFLOW_MASKING", 1);
-#endif
#ifdef PY_STRUCT_FLOAT_COERCE
PyModule_AddIntConstant(m, "_PY_STRUCT_FLOAT_COERCE", 1);
#endif