diff Modules/structmodule.c @ 25366:0b68d810a8be 2.2

Backport 2.57 from trunk: (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.
author Guido van Rossum <guido@python.org>
date Mon, 23 Sep 2002 20:54:04 +0000
parents edd9d0b3c47e
children eec3fd164a7d
line wrap: on
line diff
--- a/Modules/structmodule.c	Mon Sep 23 20:49:43 2002 +0000
+++ b/Modules/structmodule.c	Mon Sep 23 20:54:04 2002 +0000
@@ -1,4 +1,3 @@
-
 /* struct module -- pack values into and (out of) strings */
 
 /* New version supporting byte order, alignment and size options,
@@ -483,6 +482,14 @@
 */
 
 /* 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)
@@ -505,38 +512,49 @@
 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
@@ -547,27 +565,26 @@
 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);
 }
 
@@ -575,14 +592,16 @@
 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
@@ -631,15 +650,17 @@
 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;
 }
 
@@ -647,6 +668,7 @@
 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){
@@ -654,7 +676,8 @@
 				"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;
 }
 
@@ -662,9 +685,11 @@
 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;
 }
 
@@ -672,9 +697,11 @@
 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;
 }
 
@@ -684,7 +711,7 @@
 	long x;
 	if (get_long(v, &x) < 0)
 		return -1;
-	* (long *)p = x;
+	memcpy(p, (char *)&x, sizeof x);
 	return 0;
 }
 
@@ -694,7 +721,7 @@
 	unsigned long x;
 	if (get_ulong(v, &x) < 0)
 		return -1;
-	* (unsigned long *)p = x;
+	memcpy(p, (char *)&x, sizeof x);
 	return 0;
 }
 
@@ -706,7 +733,7 @@
 	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;
 }
 
@@ -716,7 +743,7 @@
 	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
@@ -730,7 +757,7 @@
 				"required argument is not a float");
 		return -1;
 	}
-	memcpy(p, (char *)&x, sizeof(float));
+	memcpy(p, (char *)&x, sizeof x);
 	return 0;
 }
 
@@ -758,7 +785,7 @@
 					"required argument is not an integer");
 		return -1;
 	}
-	*(void **)p = x;
+	memcpy(p, (char *)&x, sizeof x);
 	return 0;
 }
 
@@ -1218,7 +1245,7 @@
 		size += x;
 		if (x/itemsize != num || size < 0) {
 			PyErr_SetString(StructError,
-                                        "total struct size too long");
+					"total struct size too long");
 			return -1;
 		}
 	}
@@ -1267,7 +1294,7 @@
 
 	if (args == NULL || !PyTuple_Check(args) ||
 	    (n = PyTuple_Size(args)) < 1)
-        {
+	{
 		PyErr_SetString(PyExc_TypeError,
 			"struct.pack requires at least one argument");
 		return NULL;