Commit 960bc549 authored by Guido van Rossum's avatar Guido van Rossum

(Most of) SF patch 601369 (Christos Georgiou): obmalloc,structmodule:

64bit, big endian (issue 2 only).

This adds a bunch of memcpy calls via a temporary variable to avoid
alignment errors.  That's needed for some platforms.
parent 683c0fe4
/* struct module -- pack values into and (out of) strings */ /* struct module -- pack values into and (out of) strings */
/* New version supporting byte order, alignment and size options, /* New version supporting byte order, alignment and size options,
...@@ -482,6 +481,14 @@ typedef struct _formatdef { ...@@ -482,6 +481,14 @@ typedef struct _formatdef {
*/ */
/* Native mode routines. ****************************************************/ /* Native mode routines. ****************************************************/
/* NOTE:
In all n[up]_<type> routines handling types larger than 1 byte, there is
*no* guarantee that the p pointer is properly aligned for each type,
therefore memcpy is called. An intermediate variable is used to
compensate for big-endian architectures.
Normally both the intermediate variable and the memcpy call will be
skipped by C optimisation in little-endian architectures (gcc >= 2.91
does this). */
static PyObject * static PyObject *
nu_char(const char *p, const formatdef *f) nu_char(const char *p, const formatdef *f)
...@@ -504,38 +511,49 @@ nu_ubyte(const char *p, const formatdef *f) ...@@ -504,38 +511,49 @@ nu_ubyte(const char *p, const formatdef *f)
static PyObject * static PyObject *
nu_short(const char *p, const formatdef *f) nu_short(const char *p, const formatdef *f)
{ {
return PyInt_FromLong((long) *(short *)p); short x;
memcpy((char *)&x, p, sizeof x);
return PyInt_FromLong((long)x);
} }
static PyObject * static PyObject *
nu_ushort(const char *p, const formatdef *f) nu_ushort(const char *p, const formatdef *f)
{ {
return PyInt_FromLong((long) *(unsigned short *)p); unsigned short x;
memcpy((char *)&x, p, sizeof x);
return PyInt_FromLong((long)x);
} }
static PyObject * static PyObject *
nu_int(const char *p, const formatdef *f) nu_int(const char *p, const formatdef *f)
{ {
return PyInt_FromLong((long) *(int *)p); int x;
memcpy((char *)&x, p, sizeof x);
return PyInt_FromLong((long)x);
} }
static PyObject * static PyObject *
nu_uint(const char *p, const formatdef *f) nu_uint(const char *p, const formatdef *f)
{ {
unsigned int x = *(unsigned int *)p; unsigned int x;
memcpy((char *)&x, p, sizeof x);
return PyLong_FromUnsignedLong((unsigned long)x); return PyLong_FromUnsignedLong((unsigned long)x);
} }
static PyObject * static PyObject *
nu_long(const char *p, const formatdef *f) nu_long(const char *p, const formatdef *f)
{ {
return PyInt_FromLong(*(long *)p); long x;
memcpy((char *)&x, p, sizeof x);
return PyInt_FromLong(x);
} }
static PyObject * static PyObject *
nu_ulong(const char *p, const formatdef *f) nu_ulong(const char *p, const formatdef *f)
{ {
return PyLong_FromUnsignedLong(*(unsigned long *)p); unsigned long x;
memcpy((char *)&x, p, sizeof x);
return PyLong_FromUnsignedLong(x);
} }
/* Native mode doesn't support q or Q unless the platform C supports /* Native mode doesn't support q or Q unless the platform C supports
...@@ -546,27 +564,26 @@ nu_ulong(const char *p, const formatdef *f) ...@@ -546,27 +564,26 @@ nu_ulong(const char *p, const formatdef *f)
static PyObject * static PyObject *
nu_longlong(const char *p, const formatdef *f) nu_longlong(const char *p, const formatdef *f)
{ {
/* p may not be properly aligned */
LONG_LONG x; LONG_LONG x;
memcpy(&x, p, sizeof(LONG_LONG)); memcpy((char *)&x, p, sizeof x);
return PyLong_FromLongLong(x); return PyLong_FromLongLong(x);
} }
static PyObject * static PyObject *
nu_ulonglong(const char *p, const formatdef *f) nu_ulonglong(const char *p, const formatdef *f)
{ {
/* p may not be properly aligned */
unsigned LONG_LONG x; unsigned LONG_LONG x;
memcpy(&x, p, sizeof(unsigned LONG_LONG)); memcpy((char *)&x, p, sizeof x);
return PyLong_FromUnsignedLongLong(x); return PyLong_FromUnsignedLongLong(x);
} }
#endif #endif
static PyObject * static PyObject *
nu_float(const char *p, const formatdef *f) nu_float(const char *p, const formatdef *f)
{ {
float x; float x;
memcpy((char *)&x, p, sizeof(float)); memcpy((char *)&x, p, sizeof x);
return PyFloat_FromDouble((double)x); return PyFloat_FromDouble((double)x);
} }
...@@ -574,14 +591,16 @@ static PyObject * ...@@ -574,14 +591,16 @@ static PyObject *
nu_double(const char *p, const formatdef *f) nu_double(const char *p, const formatdef *f)
{ {
double x; double x;
memcpy((char *)&x, p, sizeof(double)); memcpy((char *)&x, p, sizeof x);
return PyFloat_FromDouble(x); return PyFloat_FromDouble(x);
} }
static PyObject * static PyObject *
nu_void_p(const char *p, const formatdef *f) nu_void_p(const char *p, const formatdef *f)
{ {
return PyLong_FromVoidPtr(*(void **)p); void *x;
memcpy((char *)&x, p, sizeof x);
return PyLong_FromVoidPtr(x);
} }
static int static int
...@@ -630,15 +649,17 @@ static int ...@@ -630,15 +649,17 @@ static int
np_short(char *p, PyObject *v, const formatdef *f) np_short(char *p, PyObject *v, const formatdef *f)
{ {
long x; long x;
short y;
if (get_long(v, &x) < 0) if (get_long(v, &x) < 0)
return -1; return -1;
if (x < SHRT_MIN || x > SHRT_MAX){ if (x < SHRT_MIN || x > SHRT_MAX){
PyErr_SetString(StructError, PyErr_SetString(StructError,
"short format requires " STRINGIFY(SHRT_MIN) "short format requires " STRINGIFY(SHRT_MIN)
"<=number<=" STRINGIFY(SHRT_MAX)); "<=number<=" STRINGIFY(SHRT_MAX));
return -1; return -1;
} }
* (short *)p = (short)x; y = (short)x;
memcpy(p, (char *)&y, sizeof y);
return 0; return 0;
} }
...@@ -646,6 +667,7 @@ static int ...@@ -646,6 +667,7 @@ static int
np_ushort(char *p, PyObject *v, const formatdef *f) np_ushort(char *p, PyObject *v, const formatdef *f)
{ {
long x; long x;
unsigned short y;
if (get_long(v, &x) < 0) if (get_long(v, &x) < 0)
return -1; return -1;
if (x < 0 || x > USHRT_MAX){ if (x < 0 || x > USHRT_MAX){
...@@ -653,7 +675,8 @@ np_ushort(char *p, PyObject *v, const formatdef *f) ...@@ -653,7 +675,8 @@ np_ushort(char *p, PyObject *v, const formatdef *f)
"short format requires 0<=number<=" STRINGIFY(USHRT_MAX)); "short format requires 0<=number<=" STRINGIFY(USHRT_MAX));
return -1; return -1;
} }
* (unsigned short *)p = (unsigned short)x; y = (unsigned short)x;
memcpy(p, (char *)&y, sizeof y);
return 0; return 0;
} }
...@@ -661,9 +684,11 @@ static int ...@@ -661,9 +684,11 @@ static int
np_int(char *p, PyObject *v, const formatdef *f) np_int(char *p, PyObject *v, const formatdef *f)
{ {
long x; long x;
int y;
if (get_long(v, &x) < 0) if (get_long(v, &x) < 0)
return -1; return -1;
* (int *)p = x; y = (int)x;
memcpy(p, (char *)&y, sizeof y);
return 0; return 0;
} }
...@@ -671,9 +696,11 @@ static int ...@@ -671,9 +696,11 @@ static int
np_uint(char *p, PyObject *v, const formatdef *f) np_uint(char *p, PyObject *v, const formatdef *f)
{ {
unsigned long x; unsigned long x;
unsigned int y;
if (get_ulong(v, &x) < 0) if (get_ulong(v, &x) < 0)
return -1; return -1;
* (unsigned int *)p = x; y = (unsigned int)x;
memcpy(p, (char *)&y, sizeof y);
return 0; return 0;
} }
...@@ -683,7 +710,7 @@ np_long(char *p, PyObject *v, const formatdef *f) ...@@ -683,7 +710,7 @@ np_long(char *p, PyObject *v, const formatdef *f)
long x; long x;
if (get_long(v, &x) < 0) if (get_long(v, &x) < 0)
return -1; return -1;
* (long *)p = x; memcpy(p, (char *)&x, sizeof x);
return 0; return 0;
} }
...@@ -693,7 +720,7 @@ np_ulong(char *p, PyObject *v, const formatdef *f) ...@@ -693,7 +720,7 @@ np_ulong(char *p, PyObject *v, const formatdef *f)
unsigned long x; unsigned long x;
if (get_ulong(v, &x) < 0) if (get_ulong(v, &x) < 0)
return -1; return -1;
* (unsigned long *)p = x; memcpy(p, (char *)&x, sizeof x);
return 0; return 0;
} }
...@@ -705,7 +732,7 @@ np_longlong(char *p, PyObject *v, const formatdef *f) ...@@ -705,7 +732,7 @@ np_longlong(char *p, PyObject *v, const formatdef *f)
LONG_LONG x; LONG_LONG x;
if (get_longlong(v, &x) < 0) if (get_longlong(v, &x) < 0)
return -1; return -1;
memcpy(p, &x, sizeof(LONG_LONG)); memcpy(p, (char *)&x, sizeof x);
return 0; return 0;
} }
...@@ -715,7 +742,7 @@ np_ulonglong(char *p, PyObject *v, const formatdef *f) ...@@ -715,7 +742,7 @@ np_ulonglong(char *p, PyObject *v, const formatdef *f)
unsigned LONG_LONG x; unsigned LONG_LONG x;
if (get_ulonglong(v, &x) < 0) if (get_ulonglong(v, &x) < 0)
return -1; return -1;
memcpy(p, &x, sizeof(unsigned LONG_LONG)); memcpy(p, (char *)&x, sizeof x);
return 0; return 0;
} }
#endif #endif
...@@ -729,7 +756,7 @@ np_float(char *p, PyObject *v, const formatdef *f) ...@@ -729,7 +756,7 @@ np_float(char *p, PyObject *v, const formatdef *f)
"required argument is not a float"); "required argument is not a float");
return -1; return -1;
} }
memcpy(p, (char *)&x, sizeof(float)); memcpy(p, (char *)&x, sizeof x);
return 0; return 0;
} }
...@@ -757,7 +784,7 @@ np_void_p(char *p, PyObject *v, const formatdef *f) ...@@ -757,7 +784,7 @@ np_void_p(char *p, PyObject *v, const formatdef *f)
"required argument is not an integer"); "required argument is not an integer");
return -1; return -1;
} }
*(void **)p = x; memcpy(p, (char *)&x, sizeof x);
return 0; return 0;
} }
...@@ -1217,7 +1244,7 @@ calcsize(const char *fmt, const formatdef *f) ...@@ -1217,7 +1244,7 @@ calcsize(const char *fmt, const formatdef *f)
size += x; size += x;
if (x/itemsize != num || size < 0) { if (x/itemsize != num || size < 0) {
PyErr_SetString(StructError, PyErr_SetString(StructError,
"total struct size too long"); "total struct size too long");
return -1; return -1;
} }
} }
...@@ -1266,7 +1293,7 @@ struct_pack(PyObject *self, PyObject *args) ...@@ -1266,7 +1293,7 @@ struct_pack(PyObject *self, PyObject *args)
if (args == NULL || !PyTuple_Check(args) || if (args == NULL || !PyTuple_Check(args) ||
(n = PyTuple_Size(args)) < 1) (n = PyTuple_Size(args)) < 1)
{ {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"struct.pack requires at least one argument"); "struct.pack requires at least one argument");
return NULL; return NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment