mirror of
https://github.com/python/cpython.git
synced 2025-07-30 06:34:15 +00:00
Issue #1523: Remove deprecated overflow masking in struct module, and
make sure that out-of-range values consistently raise struct.error.
This commit is contained in:
parent
bb3895cfc6
commit
5fd3af24a2
3 changed files with 37 additions and 238 deletions
|
@ -26,12 +26,8 @@ else:
|
||||||
try:
|
try:
|
||||||
import _struct
|
import _struct
|
||||||
except ImportError:
|
except ImportError:
|
||||||
PY_STRUCT_RANGE_CHECKING = 0
|
|
||||||
PY_STRUCT_OVERFLOW_MASKING = 1
|
|
||||||
PY_STRUCT_FLOAT_COERCE = 2
|
PY_STRUCT_FLOAT_COERCE = 2
|
||||||
else:
|
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)
|
PY_STRUCT_FLOAT_COERCE = getattr(_struct, '_PY_STRUCT_FLOAT_COERCE', 0)
|
||||||
|
|
||||||
def string_reverse(s):
|
def string_reverse(s):
|
||||||
|
@ -54,20 +50,6 @@ def with_warning_restore(func):
|
||||||
return func(*args, **kw)
|
return func(*args, **kw)
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
@with_warning_restore
|
|
||||||
def deprecated_err(func, *args):
|
|
||||||
try:
|
|
||||||
func(*args)
|
|
||||||
except (struct.error, OverflowError):
|
|
||||||
pass
|
|
||||||
except DeprecationWarning:
|
|
||||||
if not PY_STRUCT_OVERFLOW_MASKING:
|
|
||||||
raise TestFailed, "%s%s expected to raise DeprecationWarning" % (
|
|
||||||
func.__name__, args)
|
|
||||||
else:
|
|
||||||
raise TestFailed, "%s%s did not raise error" % (
|
|
||||||
func.__name__, args)
|
|
||||||
|
|
||||||
class StructTest(unittest.TestCase):
|
class StructTest(unittest.TestCase):
|
||||||
|
|
||||||
@with_warning_restore
|
@with_warning_restore
|
||||||
|
@ -289,7 +271,7 @@ class StructTest(unittest.TestCase):
|
||||||
'\x01' + got)
|
'\x01' + got)
|
||||||
else:
|
else:
|
||||||
# x is out of range -- verify pack realizes that.
|
# x is out of range -- verify pack realizes that.
|
||||||
deprecated_err(pack, format, x)
|
self.assertRaises(struct.error, pack, format, x)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
from random import randrange
|
from random import randrange
|
||||||
|
|
|
@ -1173,6 +1173,10 @@ C-API
|
||||||
Extension Modules
|
Extension Modules
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Issue #1523: Remove deprecated overflow wrapping for struct.pack
|
||||||
|
with an integer format code ('bBhHiIlLqQ'). Packing an out-of-range
|
||||||
|
integer now consistently raises struct.error.
|
||||||
|
|
||||||
- Issues #1530559, #1741130: Fix various struct.pack inconsistencies
|
- Issues #1530559, #1741130: Fix various struct.pack inconsistencies
|
||||||
for the integer formats ('bBhHiIlLqQ'). In the following, '*'
|
for the integer formats ('bBhHiIlLqQ'). In the following, '*'
|
||||||
represents any of '=', '<', '>'.
|
represents any of '=', '<', '>'.
|
||||||
|
|
|
@ -17,20 +17,6 @@ static PyTypeObject PyStructType;
|
||||||
typedef int Py_ssize_t;
|
typedef int Py_ssize_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* 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
|
/* If PY_STRUCT_FLOAT_COERCE is defined, the struct module will allow float
|
||||||
arguments for integer formats with a warning for backwards
|
arguments for integer formats with a warning for backwards
|
||||||
compatibility. */
|
compatibility. */
|
||||||
|
@ -119,6 +105,8 @@ typedef struct { char c; _Bool x; } s_bool;
|
||||||
#pragma options align=reset
|
#pragma options align=reset
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static char *integer_codes = "bBhHiIlLqQ";
|
||||||
|
|
||||||
/* Helper to get a PyLongObject by hook or by crook. Caller should decref. */
|
/* Helper to get a PyLongObject by hook or by crook. Caller should decref. */
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -143,8 +131,9 @@ get_pylong(PyObject *v)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper to convert a Python object to a C long. Raise StructError and
|
/* Helper to convert a Python object to a C long. Sets an exception
|
||||||
return -1 if v has the wrong type or is outside the range of a long. */
|
(struct.error for an inconvertible type, OverflowError for
|
||||||
|
out-of-range values) and returns -1 on error. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
get_long(PyObject *v, long *p)
|
get_long(PyObject *v, long *p)
|
||||||
|
@ -157,19 +146,14 @@ get_long(PyObject *v, long *p)
|
||||||
assert(PyLong_Check(v));
|
assert(PyLong_Check(v));
|
||||||
x = PyLong_AsLong(v);
|
x = PyLong_AsLong(v);
|
||||||
Py_DECREF(v);
|
Py_DECREF(v);
|
||||||
if (x == (long)-1 && PyErr_Occurred()) {
|
if (x == (long)-1 && PyErr_Occurred())
|
||||||
if (PyErr_ExceptionMatches(PyExc_OverflowError))
|
|
||||||
PyErr_SetString(StructError,
|
|
||||||
"argument out of range");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
*p = x;
|
*p = x;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Same, but handling unsigned long */
|
/* Same, but handling unsigned long */
|
||||||
|
|
||||||
#ifndef PY_STRUCT_OVERFLOW_MASKING
|
|
||||||
static int
|
static int
|
||||||
get_ulong(PyObject *v, unsigned long *p)
|
get_ulong(PyObject *v, unsigned long *p)
|
||||||
{
|
{
|
||||||
|
@ -181,16 +165,11 @@ get_ulong(PyObject *v, unsigned long *p)
|
||||||
assert(PyLong_Check(v));
|
assert(PyLong_Check(v));
|
||||||
x = PyLong_AsUnsignedLong(v);
|
x = PyLong_AsUnsignedLong(v);
|
||||||
Py_DECREF(v);
|
Py_DECREF(v);
|
||||||
if (x == (unsigned long)-1 && PyErr_Occurred()) {
|
if (x == (unsigned long)-1 && PyErr_Occurred())
|
||||||
if (PyErr_ExceptionMatches(PyExc_OverflowError))
|
|
||||||
PyErr_SetString(StructError,
|
|
||||||
"argument out of range");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
*p = x;
|
*p = x;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* PY_STRUCT_OVERFLOW_MASKING */
|
|
||||||
|
|
||||||
#ifdef HAVE_LONG_LONG
|
#ifdef HAVE_LONG_LONG
|
||||||
|
|
||||||
|
@ -207,12 +186,8 @@ get_longlong(PyObject *v, PY_LONG_LONG *p)
|
||||||
assert(PyLong_Check(v));
|
assert(PyLong_Check(v));
|
||||||
x = PyLong_AsLongLong(v);
|
x = PyLong_AsLongLong(v);
|
||||||
Py_DECREF(v);
|
Py_DECREF(v);
|
||||||
if (x == (PY_LONG_LONG)-1 && PyErr_Occurred()) {
|
if (x == (PY_LONG_LONG)-1 && PyErr_Occurred())
|
||||||
if (PyErr_ExceptionMatches(PyExc_OverflowError))
|
|
||||||
PyErr_SetString(StructError,
|
|
||||||
"argument out of range");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
*p = x;
|
*p = x;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -230,121 +205,16 @@ get_ulonglong(PyObject *v, unsigned PY_LONG_LONG *p)
|
||||||
assert(PyLong_Check(v));
|
assert(PyLong_Check(v));
|
||||||
x = PyLong_AsUnsignedLongLong(v);
|
x = PyLong_AsUnsignedLongLong(v);
|
||||||
Py_DECREF(v);
|
Py_DECREF(v);
|
||||||
if (x == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred()) {
|
if (x == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())
|
||||||
if (PyErr_ExceptionMatches(PyExc_OverflowError))
|
|
||||||
PyErr_SetString(StructError,
|
|
||||||
"argument out of range");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
*p = x;
|
*p = x;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#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)
|
|
||||||
{
|
|
||||||
PyObject *wrapped;
|
|
||||||
long x;
|
|
||||||
|
|
||||||
v = get_pylong(v);
|
|
||||||
if (v == NULL)
|
|
||||||
return -1;
|
|
||||||
assert(PyLong_Check(v));
|
|
||||||
|
|
||||||
x = PyLong_AsLong(v);
|
|
||||||
if (!(x == (long)-1 && PyErr_Occurred())) {
|
|
||||||
/* PyLong_AsLong succeeded; no need to wrap */
|
|
||||||
Py_DECREF(v);
|
|
||||||
*p = x;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!PyErr_ExceptionMatches(PyExc_OverflowError)) {
|
|
||||||
Py_DECREF(v);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyErr_Clear();
|
|
||||||
if (PyErr_WarnEx(PyExc_DeprecationWarning, INT_OVERFLOW, 2) < 0) {
|
|
||||||
Py_DECREF(v);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
wrapped = PyNumber_And(v, pylong_ulong_mask);
|
|
||||||
Py_DECREF(v);
|
|
||||||
if (wrapped == NULL)
|
|
||||||
return -1;
|
|
||||||
/* XXX we're relying on the (long) cast to preserve the value modulo
|
|
||||||
ULONG_MAX+1, but the C standards don't guarantee this */
|
|
||||||
x = (long)PyLong_AsUnsignedLong(wrapped);
|
|
||||||
Py_DECREF(wrapped);
|
|
||||||
if (x == (long)-1 && PyErr_Occurred())
|
|
||||||
return -1;
|
|
||||||
*p = x;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
get_wrapped_ulong(PyObject *v, unsigned long *p)
|
|
||||||
{
|
|
||||||
PyObject *wrapped;
|
|
||||||
unsigned long x;
|
|
||||||
|
|
||||||
v = get_pylong(v);
|
|
||||||
if (v == NULL)
|
|
||||||
return -1;
|
|
||||||
assert(PyLong_Check(v));
|
|
||||||
|
|
||||||
x = PyLong_AsUnsignedLong(v);
|
|
||||||
if (!(x == (unsigned long)-1 && PyErr_Occurred())) {
|
|
||||||
Py_DECREF(v);
|
|
||||||
*p = x;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!PyErr_ExceptionMatches(PyExc_OverflowError)) {
|
|
||||||
Py_DECREF(v);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyErr_Clear();
|
|
||||||
if (PyErr_WarnEx(PyExc_DeprecationWarning, INT_OVERFLOW, 2) < 0) {
|
|
||||||
Py_DECREF(v);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
wrapped = PyNumber_And(v, pylong_ulong_mask);
|
|
||||||
Py_DECREF(v);
|
|
||||||
if (wrapped == NULL)
|
|
||||||
return -1;
|
|
||||||
x = PyLong_AsUnsignedLong(wrapped);
|
|
||||||
Py_DECREF(wrapped);
|
|
||||||
if (x == (unsigned long)-1 && PyErr_Occurred())
|
|
||||||
return -1;
|
|
||||||
*p = 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_long get_long
|
||||||
#define get_wrapped_ulong get_ulong
|
#define get_wrapped_ulong get_ulong
|
||||||
#define RANGE_ERROR(x, f, flag, mask) return _range_error(f, flag)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Floating point helpers */
|
/* Floating point helpers */
|
||||||
|
|
||||||
|
@ -399,26 +269,6 @@ _range_error(const formatdef *f, int is_unsigned)
|
||||||
~ largest,
|
~ largest,
|
||||||
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,
|
|
||||||
PyString_AS_STRING(msg), 2);
|
|
||||||
Py_DECREF(msg);
|
|
||||||
if (rval == 0)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -663,7 +513,7 @@ np_int(char *p, PyObject *v, const formatdef *f)
|
||||||
return -1;
|
return -1;
|
||||||
#if (SIZEOF_LONG > SIZEOF_INT)
|
#if (SIZEOF_LONG > SIZEOF_INT)
|
||||||
if ((x < ((long)INT_MIN)) || (x > ((long)INT_MAX)))
|
if ((x < ((long)INT_MIN)) || (x > ((long)INT_MAX)))
|
||||||
RANGE_ERROR(x, f, 0, -1);
|
return _range_error(f, 0);
|
||||||
#endif
|
#endif
|
||||||
y = (int)x;
|
y = (int)x;
|
||||||
memcpy(p, (char *)&y, sizeof y);
|
memcpy(p, (char *)&y, sizeof y);
|
||||||
|
@ -680,7 +530,7 @@ np_uint(char *p, PyObject *v, const formatdef *f)
|
||||||
y = (unsigned int)x;
|
y = (unsigned int)x;
|
||||||
#if (SIZEOF_LONG > SIZEOF_INT)
|
#if (SIZEOF_LONG > SIZEOF_INT)
|
||||||
if (x > ((unsigned long)UINT_MAX))
|
if (x > ((unsigned long)UINT_MAX))
|
||||||
RANGE_ERROR(y, f, 1, -1);
|
return _range_error(f, 1);
|
||||||
#endif
|
#endif
|
||||||
memcpy(p, (char *)&y, sizeof y);
|
memcpy(p, (char *)&y, sizeof y);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -912,14 +762,10 @@ bp_int(char *p, PyObject *v, const formatdef *f)
|
||||||
i = f->size;
|
i = f->size;
|
||||||
if (i != SIZEOF_LONG) {
|
if (i != SIZEOF_LONG) {
|
||||||
if ((i == 2) && (x < -32768 || x > 32767))
|
if ((i == 2) && (x < -32768 || x > 32767))
|
||||||
RANGE_ERROR(x, f, 0, 0xffffL);
|
return _range_error(f, 0);
|
||||||
#if (SIZEOF_LONG != 4)
|
#if (SIZEOF_LONG != 4)
|
||||||
else if ((i == 4) && (x < -2147483648L || x > 2147483647L))
|
else if ((i == 4) && (x < -2147483648L || x > 2147483647L))
|
||||||
RANGE_ERROR(x, f, 0, 0xffffffffL);
|
return _range_error(f, 0);
|
||||||
#endif
|
|
||||||
#ifdef PY_STRUCT_OVERFLOW_MASKING
|
|
||||||
else if ((i == 1) && (x < -128 || x > 127))
|
|
||||||
RANGE_ERROR(x, f, 0, 0xffL);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
@ -941,7 +787,7 @@ bp_uint(char *p, PyObject *v, const formatdef *f)
|
||||||
unsigned long maxint = 1;
|
unsigned long maxint = 1;
|
||||||
maxint <<= (unsigned long)(i * 8);
|
maxint <<= (unsigned long)(i * 8);
|
||||||
if (x >= maxint)
|
if (x >= maxint)
|
||||||
RANGE_ERROR(x, f, 1, maxint - 1);
|
return _range_error(f, 1);
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
p[--i] = (char)x;
|
p[--i] = (char)x;
|
||||||
|
@ -1017,14 +863,8 @@ bp_bool(char *p, PyObject *v, const formatdef *f)
|
||||||
|
|
||||||
static formatdef bigendian_table[] = {
|
static formatdef bigendian_table[] = {
|
||||||
{'x', 1, 0, NULL},
|
{'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_byte, np_byte},
|
||||||
{'B', 1, 0, nu_ubyte, np_ubyte},
|
{'B', 1, 0, nu_ubyte, np_ubyte},
|
||||||
#endif
|
|
||||||
{'c', 1, 0, nu_char, np_char},
|
{'c', 1, 0, nu_char, np_char},
|
||||||
{'s', 1, 0, NULL},
|
{'s', 1, 0, NULL},
|
||||||
{'p', 1, 0, NULL},
|
{'p', 1, 0, NULL},
|
||||||
|
@ -1140,14 +980,10 @@ lp_int(char *p, PyObject *v, const formatdef *f)
|
||||||
i = f->size;
|
i = f->size;
|
||||||
if (i != SIZEOF_LONG) {
|
if (i != SIZEOF_LONG) {
|
||||||
if ((i == 2) && (x < -32768 || x > 32767))
|
if ((i == 2) && (x < -32768 || x > 32767))
|
||||||
RANGE_ERROR(x, f, 0, 0xffffL);
|
return _range_error(f, 0);
|
||||||
#if (SIZEOF_LONG != 4)
|
#if (SIZEOF_LONG != 4)
|
||||||
else if ((i == 4) && (x < -2147483648L || x > 2147483647L))
|
else if ((i == 4) && (x < -2147483648L || x > 2147483647L))
|
||||||
RANGE_ERROR(x, f, 0, 0xffffffffL);
|
return _range_error(f, 0);
|
||||||
#endif
|
|
||||||
#ifdef PY_STRUCT_OVERFLOW_MASKING
|
|
||||||
else if ((i == 1) && (x < -128 || x > 127))
|
|
||||||
RANGE_ERROR(x, f, 0, 0xffL);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
@ -1169,7 +1005,7 @@ lp_uint(char *p, PyObject *v, const formatdef *f)
|
||||||
unsigned long maxint = 1;
|
unsigned long maxint = 1;
|
||||||
maxint <<= (unsigned long)(i * 8);
|
maxint <<= (unsigned long)(i * 8);
|
||||||
if (x >= maxint)
|
if (x >= maxint)
|
||||||
RANGE_ERROR(x, f, 1, maxint - 1);
|
return _range_error(f, 1);
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
*p++ = (char)x;
|
*p++ = (char)x;
|
||||||
|
@ -1236,14 +1072,8 @@ lp_double(char *p, PyObject *v, const formatdef *f)
|
||||||
|
|
||||||
static formatdef lilendian_table[] = {
|
static formatdef lilendian_table[] = {
|
||||||
{'x', 1, 0, NULL},
|
{'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_byte, np_byte},
|
||||||
{'B', 1, 0, nu_ubyte, np_ubyte},
|
{'B', 1, 0, nu_ubyte, np_ubyte},
|
||||||
#endif
|
|
||||||
{'c', 1, 0, nu_char, np_char},
|
{'c', 1, 0, nu_char, np_char},
|
||||||
{'s', 1, 0, NULL},
|
{'s', 1, 0, NULL},
|
||||||
{'p', 1, 0, NULL},
|
{'p', 1, 0, NULL},
|
||||||
|
@ -1645,7 +1475,8 @@ s_pack_internal(PyStructObject *soself, PyObject *args, int offset, char* buf)
|
||||||
if (e->format == 's') {
|
if (e->format == 's') {
|
||||||
if (!PyString_Check(v)) {
|
if (!PyString_Check(v)) {
|
||||||
PyErr_SetString(StructError,
|
PyErr_SetString(StructError,
|
||||||
"argument for 's' must be a string");
|
"argument for 's' must "
|
||||||
|
"be a string");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
n = PyString_GET_SIZE(v);
|
n = PyString_GET_SIZE(v);
|
||||||
|
@ -1656,7 +1487,8 @@ s_pack_internal(PyStructObject *soself, PyObject *args, int offset, char* buf)
|
||||||
} else if (e->format == 'p') {
|
} else if (e->format == 'p') {
|
||||||
if (!PyString_Check(v)) {
|
if (!PyString_Check(v)) {
|
||||||
PyErr_SetString(StructError,
|
PyErr_SetString(StructError,
|
||||||
"argument for 'p' must be a string");
|
"argument for 'p' must "
|
||||||
|
"be a string");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
n = PyString_GET_SIZE(v);
|
n = PyString_GET_SIZE(v);
|
||||||
|
@ -1667,15 +1499,16 @@ s_pack_internal(PyStructObject *soself, PyObject *args, int offset, char* buf)
|
||||||
if (n > 255)
|
if (n > 255)
|
||||||
n = 255;
|
n = 255;
|
||||||
*res = Py_SAFE_DOWNCAST(n, Py_ssize_t, unsigned char);
|
*res = Py_SAFE_DOWNCAST(n, Py_ssize_t, unsigned char);
|
||||||
} else {
|
} else if (e->pack(res, v, e) < 0) {
|
||||||
if (e->pack(res, v, e) < 0) {
|
if (strchr(integer_codes, e->format) != NULL &&
|
||||||
if (PyLong_Check(v) && PyErr_ExceptionMatches(PyExc_OverflowError))
|
PyErr_ExceptionMatches(PyExc_OverflowError))
|
||||||
PyErr_SetString(StructError,
|
PyErr_Format(StructError,
|
||||||
"long too large to convert to int");
|
"integer out of range for "
|
||||||
|
"'%c' format code",
|
||||||
|
e->format);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Success */
|
/* Success */
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2081,25 +1914,9 @@ init_struct(void)
|
||||||
if (PyType_Ready(&PyStructType) < 0)
|
if (PyType_Ready(&PyStructType) < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef PY_STRUCT_OVERFLOW_MASKING
|
/* This speed trick can't be used until overflow masking goes
|
||||||
if (pyint_zero == NULL) {
|
away, because native endian always raises exceptions
|
||||||
pyint_zero = PyInt_FromLong(0);
|
instead of overflow masking. */
|
||||||
if (pyint_zero == NULL)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
#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 */
|
/* Check endian and swap in faster functions */
|
||||||
{
|
{
|
||||||
|
@ -2139,7 +1956,6 @@ init_struct(void)
|
||||||
native++;
|
native++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Add some symbolic constants to the module */
|
/* Add some symbolic constants to the module */
|
||||||
if (StructError == NULL) {
|
if (StructError == NULL) {
|
||||||
|
@ -2157,9 +1973,6 @@ init_struct(void)
|
||||||
PyModule_AddObject(m, "__version__", ver);
|
PyModule_AddObject(m, "__version__", ver);
|
||||||
|
|
||||||
PyModule_AddIntConstant(m, "_PY_STRUCT_RANGE_CHECKING", 1);
|
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
|
#ifdef PY_STRUCT_FLOAT_COERCE
|
||||||
PyModule_AddIntConstant(m, "_PY_STRUCT_FLOAT_COERCE", 1);
|
PyModule_AddIntConstant(m, "_PY_STRUCT_FLOAT_COERCE", 1);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue