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
486493static PyObject *
487494nu_char (const char * p , const formatdef * f )
@@ -504,38 +511,49 @@ nu_ubyte(const char *p, const formatdef *f)
504511static PyObject *
505512nu_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
510519static PyObject *
511520nu_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
516527static PyObject *
517528nu_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
522535static PyObject *
523536nu_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
529543static PyObject *
530544nu_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
535551static PyObject *
536552nu_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)
546564static PyObject *
547565nu_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
555572static PyObject *
556573nu_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
565582static PyObject *
566583nu_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
573590static PyObject *
574591nu_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
581598static PyObject *
582599nu_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
587606static int
@@ -630,50 +649,58 @@ static int
630649np_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
645666static int
646667np_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
660683static int
661684np_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
670695static int
671696np_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