summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Bernat <bernat@luffy.cx>2014-08-23 22:43:26 +0200
committerVincent Bernat <bernat@luffy.cx>2014-08-23 22:43:26 +0200
commite1055928c6ac7ed52b3fcf07c84dee0dd6f248d7 (patch)
treed3991d57edd2d9ecb843c4455918f2d889bda678
parentbe112737267709d4ab604a86c696ecde11cda67f (diff)
downloadcffi-e1055928c6ac7ed52b3fcf07c84dee0dd6f248d7.tar.gz
Use memcpy() instead of unaligned accesses.
When a structure is packed, some members may be unaligned. Some architectures like Sparc are unable to handle those and will be terminated with a SIGBUS. This changeset use memcpy() to avoid any unaligned accesses.
-rw-r--r--c/_cffi_backend.c107
1 files changed, 51 insertions, 56 deletions
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
index 4be4fd2..1d87239 100644
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -740,95 +740,90 @@ _my_PyLong_AsUnsignedLongLong(PyObject *ob, int strict)
return (unsigned PY_LONG_LONG)-1;
}
+#define _read_raw_data(type) \
+ do { \
+ if (size == sizeof(type)) { \
+ type r; \
+ memcpy(&r, target, sizeof(type)); \
+ return r; \
+ } \
+ } while(0)
+
static PY_LONG_LONG
read_raw_signed_data(char *target, int size)
{
- if (size == sizeof(signed char))
- return *((signed char*)target);
- else if (size == sizeof(short))
- return *((short*)target);
- else if (size == sizeof(int))
- return *((int*)target);
- else if (size == sizeof(long))
- return *((long*)target);
- else if (size == sizeof(PY_LONG_LONG))
- return *((PY_LONG_LONG*)target);
- else {
- Py_FatalError("read_raw_signed_data: bad integer size");
- return 0;
- }
+ _read_raw_data(signed char);
+ _read_raw_data(short);
+ _read_raw_data(int);
+ _read_raw_data(long);
+ _read_raw_data(PY_LONG_LONG);
+ Py_FatalError("read_raw_signed_data: bad integer size");
+ return 0;
}
static unsigned PY_LONG_LONG
read_raw_unsigned_data(char *target, int size)
{
- if (size == sizeof(unsigned char))
- return *((unsigned char*)target);
- else if (size == sizeof(unsigned short))
- return *((unsigned short*)target);
- else if (size == sizeof(unsigned int))
- return *((unsigned int*)target);
- else if (size == sizeof(unsigned long))
- return *((unsigned long*)target);
- else if (size == sizeof(unsigned PY_LONG_LONG))
- return *((unsigned PY_LONG_LONG*)target);
- else {
- Py_FatalError("read_raw_unsigned_data: bad integer size");
- return 0;
- }
+ _read_raw_data(unsigned char);
+ _read_raw_data(unsigned short);
+ _read_raw_data(unsigned int);
+ _read_raw_data(unsigned long);
+ _read_raw_data(unsigned PY_LONG_LONG);
+ Py_FatalError("read_raw_unsigned_data: bad integer size");
+ return 0;
}
+#define _write_raw_data(type) \
+ do { \
+ if (size == sizeof(type)) { \
+ type r = source; \
+ memcpy(target, &r, sizeof(type)); \
+ return; \
+ } \
+ } while(0)
+
static void
write_raw_integer_data(char *target, unsigned PY_LONG_LONG source, int size)
{
- if (size == sizeof(unsigned char))
- *((unsigned char*)target) = (unsigned char)source;
- else if (size == sizeof(unsigned short))
- *((unsigned short*)target) = (unsigned short)source;
- else if (size == sizeof(unsigned int))
- *((unsigned int*)target) = (unsigned int)source;
- else if (size == sizeof(unsigned long))
- *((unsigned long*)target) = (unsigned long)source;
- else if (size == sizeof(unsigned PY_LONG_LONG))
- *((unsigned PY_LONG_LONG*)target) = source;
- else
- Py_FatalError("write_raw_integer_data: bad integer size");
+ _write_raw_data(unsigned char);
+ _write_raw_data(unsigned short);
+ _write_raw_data(unsigned int);
+ _write_raw_data(unsigned long);
+ _write_raw_data(unsigned PY_LONG_LONG);
+ Py_FatalError("write_raw_integer_data: bad integer size");
}
static double
read_raw_float_data(char *target, int size)
{
- if (size == sizeof(float))
- return *((float*)target);
- else if (size == sizeof(double))
- return *((double*)target);
- else {
- Py_FatalError("read_raw_float_data: bad float size");
- return 0;
- }
+ _read_raw_data(float);
+ _read_raw_data(double);
+ Py_FatalError("read_raw_float_data: bad float size");
+ return 0;
}
static long double
read_raw_longdouble_data(char *target)
{
- return *((long double*)target);
+ int size = sizeof(long double);
+ _read_raw_data(long double);
+ Py_FatalError("read_raw_longdouble_data: bad long double size");
+ return 0;
}
static void
write_raw_float_data(char *target, double source, int size)
{
- if (size == sizeof(float))
- *((float*)target) = (float)source;
- else if (size == sizeof(double))
- *((double*)target) = source;
- else
- Py_FatalError("write_raw_float_data: bad float size");
+ _write_raw_data(float);
+ _write_raw_data(double);
+ Py_FatalError("write_raw_float_data: bad float size");
}
static void
write_raw_longdouble_data(char *target, long double source)
{
- *((long double*)target) = source;
+ int size = sizeof(long double);
+ _write_raw_data(long double);
}
static PyObject *