Skip to content

Commit 960bc54

Browse files
committed
(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.
1 parent 683c0fe commit 960bc54

1 file changed

Lines changed: 54 additions & 27 deletions

File tree

Modules/structmodule.c

Lines changed: 54 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
/* struct module -- pack values into and (out of) strings */
32

43
/* New version supporting byte order, alignment and size options,
@@ -482,6 +481,14 @@ typedef struct _formatdef {
482481
*/
483482

484483
/* Native mode routines. ****************************************************/
484+
/* NOTE:
485+
In all n[up]_<type> routines handling types larger than 1 byte, there is
486+
*no* guarantee that the p pointer is properly aligned for each type,
487+
therefore memcpy is called. An intermediate variable is used to
488+
compensate for big-endian architectures.
489+
Normally both the intermediate variable and the memcpy call will be
490+
skipped by C optimisation in little-endian architectures (gcc >= 2.91
491+
does this). */
485492

486493
static PyObject *
487494
nu_char(const char *p, const formatdef *f)
@@ -504,38 +511,49 @@ nu_ubyte(const char *p, const formatdef *f)
504511
static PyObject *
505512
nu_short(const char *p, const formatdef *f)
506513
{
507-
return PyInt_FromLong((long) *(short *)p);
514+
short x;
515+
memcpy((char *)&x, p, sizeof x);
516+
return PyInt_FromLong((long)x);
508517
}
509518

510519
static PyObject *
511520
nu_ushort(const char *p, const formatdef *f)
512521
{
513-
return PyInt_FromLong((long) *(unsigned short *)p);
522+
unsigned short x;
523+
memcpy((char *)&x, p, sizeof x);
524+
return PyInt_FromLong((long)x);
514525
}
515526

516527
static PyObject *
517528
nu_int(const char *p, const formatdef *f)
518529
{
519-
return PyInt_FromLong((long) *(int *)p);
530+
int x;
531+
memcpy((char *)&x, p, sizeof x);
532+
return PyInt_FromLong((long)x);
520533
}
521534

522535
static PyObject *
523536
nu_uint(const char *p, const formatdef *f)
524537
{
525-
unsigned int x = *(unsigned int *)p;
538+
unsigned int x;
539+
memcpy((char *)&x, p, sizeof x);
526540
return PyLong_FromUnsignedLong((unsigned long)x);
527541
}
528542

529543
static PyObject *
530544
nu_long(const char *p, const formatdef *f)
531545
{
532-
return PyInt_FromLong(*(long *)p);
546+
long x;
547+
memcpy((char *)&x, p, sizeof x);
548+
return PyInt_FromLong(x);
533549
}
534550

535551
static PyObject *
536552
nu_ulong(const char *p, const formatdef *f)
537553
{
538-
return PyLong_FromUnsignedLong(*(unsigned long *)p);
554+
unsigned long x;
555+
memcpy((char *)&x, p, sizeof x);
556+
return PyLong_FromUnsignedLong(x);
539557
}
540558

541559
/* Native mode doesn't support q or Q unless the platform C supports
@@ -546,42 +564,43 @@ nu_ulong(const char *p, const formatdef *f)
546564
static PyObject *
547565
nu_longlong(const char *p, const formatdef *f)
548566
{
549-
/* p may not be properly aligned */
550567
LONG_LONG x;
551-
memcpy(&x, p, sizeof(LONG_LONG));
568+
memcpy((char *)&x, p, sizeof x);
552569
return PyLong_FromLongLong(x);
553570
}
554571

555572
static PyObject *
556573
nu_ulonglong(const char *p, const formatdef *f)
557574
{
558-
/* p may not be properly aligned */
559575
unsigned LONG_LONG x;
560-
memcpy(&x, p, sizeof(unsigned LONG_LONG));
576+
memcpy((char *)&x, p, sizeof x);
561577
return PyLong_FromUnsignedLongLong(x);
562578
}
579+
563580
#endif
564581

565582
static PyObject *
566583
nu_float(const char *p, const formatdef *f)
567584
{
568585
float x;
569-
memcpy((char *)&x, p, sizeof(float));
586+
memcpy((char *)&x, p, sizeof x);
570587
return PyFloat_FromDouble((double)x);
571588
}
572589

573590
static PyObject *
574591
nu_double(const char *p, const formatdef *f)
575592
{
576593
double x;
577-
memcpy((char *)&x, p, sizeof(double));
594+
memcpy((char *)&x, p, sizeof x);
578595
return PyFloat_FromDouble(x);
579596
}
580597

581598
static PyObject *
582599
nu_void_p(const char *p, const formatdef *f)
583600
{
584-
return PyLong_FromVoidPtr(*(void **)p);
601+
void *x;
602+
memcpy((char *)&x, p, sizeof x);
603+
return PyLong_FromVoidPtr(x);
585604
}
586605

587606
static int
@@ -630,50 +649,58 @@ static int
630649
np_short(char *p, PyObject *v, const formatdef *f)
631650
{
632651
long x;
652+
short y;
633653
if (get_long(v, &x) < 0)
634654
return -1;
635655
if (x < SHRT_MIN || x > SHRT_MAX){
636656
PyErr_SetString(StructError,
637657
"short format requires " STRINGIFY(SHRT_MIN)
638-
"<=number<=" STRINGIFY(SHRT_MAX));
658+
"<=number<=" STRINGIFY(SHRT_MAX));
639659
return -1;
640660
}
641-
* (short *)p = (short)x;
661+
y = (short)x;
662+
memcpy(p, (char *)&y, sizeof y);
642663
return 0;
643664
}
644665

645666
static int
646667
np_ushort(char *p, PyObject *v, const formatdef *f)
647668
{
648669
long x;
670+
unsigned short y;
649671
if (get_long(v, &x) < 0)
650672
return -1;
651673
if (x < 0 || x > USHRT_MAX){
652674
PyErr_SetString(StructError,
653675
"short format requires 0<=number<=" STRINGIFY(USHRT_MAX));
654676
return -1;
655677
}
656-
* (unsigned short *)p = (unsigned short)x;
678+
y = (unsigned short)x;
679+
memcpy(p, (char *)&y, sizeof y);
657680
return 0;
658681
}
659682

660683
static int
661684
np_int(char *p, PyObject *v, const formatdef *f)
662685
{
663686
long x;
687+
int y;
664688
if (get_long(v, &x) < 0)
665689
return -1;
666-
* (int *)p = x;
690+
y = (int)x;
691+
memcpy(p, (char *)&y, sizeof y);
667692
return 0;
668693
}
669694

670695
static int
671696
np_uint(char *p, PyObject *v, const formatdef *f)
672697
{
673698
unsigned long x;
699+
unsigned int y;
674700
if (get_ulong(v, &x) < 0)
675701
return -1;
676-
* (unsigned int *)p = x;
702+
y = (unsigned int)x;
703+
memcpy(p, (char *)&y, sizeof y);
677704
return 0;
678705
}
679706

@@ -683,7 +710,7 @@ np_long(char *p, PyObject *v, const formatdef *f)
683710
long x;
684711
if (get_long(v, &x) < 0)
685712
return -1;
686-
* (long *)p = x;
713+
memcpy(p, (char *)&x, sizeof x);
687714
return 0;
688715
}
689716

@@ -693,7 +720,7 @@ np_ulong(char *p, PyObject *v, const formatdef *f)
693720
unsigned long x;
694721
if (get_ulong(v, &x) < 0)
695722
return -1;
696-
* (unsigned long *)p = x;
723+
memcpy(p, (char *)&x, sizeof x);
697724
return 0;
698725
}
699726

@@ -705,7 +732,7 @@ np_longlong(char *p, PyObject *v, const formatdef *f)
705732
LONG_LONG x;
706733
if (get_longlong(v, &x) < 0)
707734
return -1;
708-
memcpy(p, &x, sizeof(LONG_LONG));
735+
memcpy(p, (char *)&x, sizeof x);
709736
return 0;
710737
}
711738

@@ -715,7 +742,7 @@ np_ulonglong(char *p, PyObject *v, const formatdef *f)
715742
unsigned LONG_LONG x;
716743
if (get_ulonglong(v, &x) < 0)
717744
return -1;
718-
memcpy(p, &x, sizeof(unsigned LONG_LONG));
745+
memcpy(p, (char *)&x, sizeof x);
719746
return 0;
720747
}
721748
#endif
@@ -729,7 +756,7 @@ np_float(char *p, PyObject *v, const formatdef *f)
729756
"required argument is not a float");
730757
return -1;
731758
}
732-
memcpy(p, (char *)&x, sizeof(float));
759+
memcpy(p, (char *)&x, sizeof x);
733760
return 0;
734761
}
735762

@@ -757,7 +784,7 @@ np_void_p(char *p, PyObject *v, const formatdef *f)
757784
"required argument is not an integer");
758785
return -1;
759786
}
760-
*(void **)p = x;
787+
memcpy(p, (char *)&x, sizeof x);
761788
return 0;
762789
}
763790

@@ -1217,7 +1244,7 @@ calcsize(const char *fmt, const formatdef *f)
12171244
size += x;
12181245
if (x/itemsize != num || size < 0) {
12191246
PyErr_SetString(StructError,
1220-
"total struct size too long");
1247+
"total struct size too long");
12211248
return -1;
12221249
}
12231250
}
@@ -1266,7 +1293,7 @@ struct_pack(PyObject *self, PyObject *args)
12661293

12671294
if (args == NULL || !PyTuple_Check(args) ||
12681295
(n = PyTuple_Size(args)) < 1)
1269-
{
1296+
{
12701297
PyErr_SetString(PyExc_TypeError,
12711298
"struct.pack requires at least one argument");
12721299
return NULL;

0 commit comments

Comments
 (0)