]> granicus.if.org Git - python/commitdiff
(Most of) SF patch 601369 (Christos Georgiou): obmalloc,structmodule:
authorGuido van Rossum <guido@python.org>
Tue, 3 Sep 2002 18:42:21 +0000 (18:42 +0000)
committerGuido van Rossum <guido@python.org>
Tue, 3 Sep 2002 18:42:21 +0000 (18:42 +0000)
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.

Modules/structmodule.c

index 093cd7b9e1be12580ea507e87f55a06da8330b1f..d4f8d861c275724aa4597c74444823c9243dc734 100644 (file)
@@ -1,4 +1,3 @@
-
 /* struct module -- pack values into and (out of) strings */
 
 /* New version supporting byte order, alignment and size options,
@@ -482,6 +481,14 @@ typedef struct _formatdef {
 */
 
 /* 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 *
 nu_char(const char *p, const formatdef *f)
@@ -504,38 +511,49 @@ nu_ubyte(const char *p, const formatdef *f)
 static PyObject *
 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 *
 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 *
 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 *
 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);
 }
 
 static PyObject *
 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 *
 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
@@ -546,27 +564,26 @@ nu_ulong(const char *p, const formatdef *f)
 static PyObject *
 nu_longlong(const char *p, const formatdef *f)
 {
-       /* p may not be properly aligned */
        LONG_LONG x;
-       memcpy(&x, p, sizeof(LONG_LONG));
+       memcpy((char *)&x, p, sizeof x);
        return PyLong_FromLongLong(x);
 }
 
 static PyObject *
 nu_ulonglong(const char *p, const formatdef *f)
 {
-       /* p may not be properly aligned */
        unsigned LONG_LONG x;
-       memcpy(&x, p, sizeof(unsigned LONG_LONG));
+       memcpy((char *)&x, p, sizeof x);
        return PyLong_FromUnsignedLongLong(x);
 }
+
 #endif
 
 static PyObject *
 nu_float(const char *p, const formatdef *f)
 {
        float x;
-       memcpy((char *)&x, p, sizeof(float));
+       memcpy((char *)&x, p, sizeof x);
        return PyFloat_FromDouble((double)x);
 }
 
@@ -574,14 +591,16 @@ static PyObject *
 nu_double(const char *p, const formatdef *f)
 {
        double x;
-       memcpy((char *)&x, p, sizeof(double));
+       memcpy((char *)&x, p, sizeof x);
        return PyFloat_FromDouble(x);
 }
 
 static PyObject *
 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
@@ -630,15 +649,17 @@ static int
 np_short(char *p, PyObject *v, const formatdef *f)
 {
        long x;
+       short y;
        if (get_long(v, &x) < 0)
                return -1;
        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;
        }
-       * (short *)p = (short)x;
+       y = (short)x;
+       memcpy(p, (char *)&y, sizeof y);
        return 0;
 }
 
@@ -646,6 +667,7 @@ static int
 np_ushort(char *p, PyObject *v, const formatdef *f)
 {
        long x;
+       unsigned short y;
        if (get_long(v, &x) < 0)
                return -1;
        if (x < 0 || x > USHRT_MAX){
@@ -653,7 +675,8 @@ np_ushort(char *p, PyObject *v, const formatdef *f)
                                "short format requires 0<=number<=" STRINGIFY(USHRT_MAX));
                return -1;
        }
-       * (unsigned short *)p = (unsigned short)x;
+       y = (unsigned short)x;
+       memcpy(p, (char *)&y, sizeof y);
        return 0;
 }
 
@@ -661,9 +684,11 @@ static int
 np_int(char *p, PyObject *v, const formatdef *f)
 {
        long x;
+       int y;
        if (get_long(v, &x) < 0)
                return -1;
-       * (int *)p = x;
+       y = (int)x;
+       memcpy(p, (char *)&y, sizeof y);
        return 0;
 }
 
@@ -671,9 +696,11 @@ static int
 np_uint(char *p, PyObject *v, const formatdef *f)
 {
        unsigned long x;
+       unsigned int y;
        if (get_ulong(v, &x) < 0)
                return -1;
-       * (unsigned int *)p = x;
+       y = (unsigned int)x;
+       memcpy(p, (char *)&y, sizeof y);
        return 0;
 }
 
@@ -683,7 +710,7 @@ np_long(char *p, PyObject *v, const formatdef *f)
        long x;
        if (get_long(v, &x) < 0)
                return -1;
-       * (long *)p = x;
+       memcpy(p, (char *)&x, sizeof x);
        return 0;
 }
 
@@ -693,7 +720,7 @@ np_ulong(char *p, PyObject *v, const formatdef *f)
        unsigned long x;
        if (get_ulong(v, &x) < 0)
                return -1;
-       * (unsigned long *)p = x;
+       memcpy(p, (char *)&x, sizeof x);
        return 0;
 }
 
@@ -705,7 +732,7 @@ np_longlong(char *p, PyObject *v, const formatdef *f)
        LONG_LONG x;
        if (get_longlong(v, &x) < 0)
                return -1;
-       memcpy(p, &x, sizeof(LONG_LONG));
+       memcpy(p, (char *)&x, sizeof x);
        return 0;
 }
 
@@ -715,7 +742,7 @@ np_ulonglong(char *p, PyObject *v, const formatdef *f)
        unsigned LONG_LONG x;
        if (get_ulonglong(v, &x) < 0)
                return -1;
-       memcpy(p, &x, sizeof(unsigned LONG_LONG));
+       memcpy(p, (char *)&x, sizeof x);
        return 0;
 }
 #endif
@@ -729,7 +756,7 @@ np_float(char *p, PyObject *v, const formatdef *f)
                                "required argument is not a float");
                return -1;
        }
-       memcpy(p, (char *)&x, sizeof(float));
+       memcpy(p, (char *)&x, sizeof x);
        return 0;
 }
 
@@ -757,7 +784,7 @@ np_void_p(char *p, PyObject *v, const formatdef *f)
                                        "required argument is not an integer");
                return -1;
        }
-       *(void **)p = x;
+       memcpy(p, (char *)&x, sizeof x);
        return 0;
 }
 
@@ -1217,7 +1244,7 @@ calcsize(const char *fmt, const formatdef *f)
                size += x;
                if (x/itemsize != num || size < 0) {
                        PyErr_SetString(StructError,
-                                        "total struct size too long");
+                                       "total struct size too long");
                        return -1;
                }
        }
@@ -1266,7 +1293,7 @@ struct_pack(PyObject *self, PyObject *args)
 
        if (args == NULL || !PyTuple_Check(args) ||
            (n = PyTuple_Size(args)) < 1)
-        {
+       {
                PyErr_SetString(PyExc_TypeError,
                        "struct.pack requires at least one argument");
                return NULL;