1919#include <stdlib.h>
2020#include <errno.h>
2121#include <sys/types.h>
22- #include "pack.h"
2322
2423#define INC_OUTPUTPOS (a ,b ) \
2524 if ((a) < 0 || ((INT_MAX - outputpos)/((int)b)) < (a)) { \
3029 } \
3130 outputpos += (a)*(b);
3231
32+ typedef enum {
33+ PHP_LITTLE_ENDIAN ,
34+ PHP_BIG_ENDIAN ,
35+ } php_pack_endianness ;
36+
3337#ifdef WORDS_BIGENDIAN
34- #define MACHINE_LITTLE_ENDIAN 0
38+ # define MACHINE_LITTLE_ENDIAN 0
39+ # define PHP_MACHINE_ENDIAN PHP_BIG_ENDIAN
3540#else
36- #define MACHINE_LITTLE_ENDIAN 1
41+ # define MACHINE_LITTLE_ENDIAN 1
42+ # define PHP_MACHINE_ENDIAN PHP_LITTLE_ENDIAN
43+ #endif
44+
45+ #ifdef ZEND_ENABLE_ZVAL_LONG64
46+ # define PHP_LONG_BSWAP (u ) ZEND_BYTES_SWAP64(u)
47+ #else
48+ # define PHP_LONG_BSWAP (u ) ZEND_BYTES_SWAP32(u)
3749#endif
3850
3951typedef ZEND_SET_ALIGNED (1 , uint16_t unaligned_uint16_t ) ;
@@ -42,41 +54,23 @@ typedef ZEND_SET_ALIGNED(1, uint64_t unaligned_uint64_t);
4254typedef ZEND_SET_ALIGNED (1 , unsigned int unaligned_uint ) ;
4355typedef ZEND_SET_ALIGNED (1 , int unaligned_int ) ;
4456
45- /* Mapping of byte from char (8bit) to long for machine endian */
46- static int byte_map [1 ];
47-
48- /* Mappings of bytes from int (machine dependent) to int for machine endian */
49- static int int_map [sizeof (int )];
50-
51- /* Mappings of bytes from shorts (16bit) for all endian environments */
52- static int machine_endian_short_map [2 ];
53- static int big_endian_short_map [2 ];
54- static int little_endian_short_map [2 ];
55-
56- /* Mappings of bytes from longs (32bit) for all endian environments */
57- static int machine_endian_long_map [4 ];
58- static int big_endian_long_map [4 ];
59- static int little_endian_long_map [4 ];
60-
61- #if SIZEOF_ZEND_LONG > 4
62- /* Mappings of bytes from quads (64bit) for all endian environments */
63- static int machine_endian_longlong_map [8 ];
64- static int big_endian_longlong_map [8 ];
65- static int little_endian_longlong_map [8 ];
66- #endif
67-
6857/* {{{ php_pack */
69- static void php_pack (zval * val , size_t size , int * map , char * output )
58+ static void php_pack (const zval * val , size_t size , php_pack_endianness endianness , char * output )
7059{
71- size_t i ;
72- char * v ;
73-
74- convert_to_long (val );
75- v = (char * ) & Z_LVAL_P (val );
60+ zend_ulong zl = zval_get_long (val );
7661
77- for (i = 0 ; i < size ; i ++ ) {
78- * output ++ = v [map [i ]];
62+ if ((endianness == PHP_LITTLE_ENDIAN ) != MACHINE_LITTLE_ENDIAN ) {
63+ zl = PHP_LONG_BSWAP (zl );
64+ #if MACHINE_LITTLE_ENDIAN
65+ zl >>= (sizeof (zl ) - size ) * 8 ;
66+ #endif
67+ } else {
68+ #if !MACHINE_LITTLE_ENDIAN
69+ zl <<= (sizeof (zl ) - size ) * 8 ;
70+ #endif
7971 }
72+
73+ memcpy (output , (const char * ) & zl , size );
8074}
8175/* }}} */
8276
@@ -88,10 +82,7 @@ ZEND_ATTRIBUTE_CONST static inline uint16_t php_pack_reverse_int16(uint16_t arg)
8882/* {{{ php_pack_reverse_int32 */
8983ZEND_ATTRIBUTE_CONST static inline uint32_t php_pack_reverse_int32 (uint32_t arg )
9084{
91- uint32_t result ;
92- result = ((arg & 0xFF ) << 24 ) | ((arg & 0xFF00 ) << 8 ) | ((arg >> 8 ) & 0xFF00 ) | ((arg >> 24 ) & 0xFF );
93-
94- return result ;
85+ return ZEND_BYTES_SWAP32 (arg );
9586}
9687/* }}} */
9788
@@ -509,7 +500,7 @@ PHP_FUNCTION(pack)
509500 case 'c' :
510501 case 'C' :
511502 while (arg -- > 0 ) {
512- php_pack (& argv [currentarg ++ ], 1 , byte_map , & ZSTR_VAL (output )[outputpos ]);
503+ php_pack (& argv [currentarg ++ ], 1 , PHP_MACHINE_ENDIAN , & ZSTR_VAL (output )[outputpos ]);
513504 outputpos ++ ;
514505 }
515506 break ;
@@ -518,16 +509,16 @@ PHP_FUNCTION(pack)
518509 case 'S' :
519510 case 'n' :
520511 case 'v' : {
521- int * map = machine_endian_short_map ;
512+ php_pack_endianness endianness = PHP_MACHINE_ENDIAN ;
522513
523514 if (code == 'n' ) {
524- map = big_endian_short_map ;
515+ endianness = PHP_BIG_ENDIAN ;
525516 } else if (code == 'v' ) {
526- map = little_endian_short_map ;
517+ endianness = PHP_LITTLE_ENDIAN ;
527518 }
528519
529520 while (arg -- > 0 ) {
530- php_pack (& argv [currentarg ++ ], 2 , map , & ZSTR_VAL (output )[outputpos ]);
521+ php_pack (& argv [currentarg ++ ], 2 , endianness , & ZSTR_VAL (output )[outputpos ]);
531522 outputpos += 2 ;
532523 }
533524 break ;
@@ -536,7 +527,7 @@ PHP_FUNCTION(pack)
536527 case 'i' :
537528 case 'I' :
538529 while (arg -- > 0 ) {
539- php_pack (& argv [currentarg ++ ], sizeof (int ), int_map , & ZSTR_VAL (output )[outputpos ]);
530+ php_pack (& argv [currentarg ++ ], sizeof (int ), PHP_MACHINE_ENDIAN , & ZSTR_VAL (output )[outputpos ]);
540531 outputpos += sizeof (int );
541532 }
542533 break ;
@@ -545,16 +536,16 @@ PHP_FUNCTION(pack)
545536 case 'L' :
546537 case 'N' :
547538 case 'V' : {
548- int * map = machine_endian_long_map ;
539+ php_pack_endianness endianness = PHP_MACHINE_ENDIAN ;
549540
550541 if (code == 'N' ) {
551- map = big_endian_long_map ;
542+ endianness = PHP_BIG_ENDIAN ;
552543 } else if (code == 'V' ) {
553- map = little_endian_long_map ;
544+ endianness = PHP_LITTLE_ENDIAN ;
554545 }
555546
556547 while (arg -- > 0 ) {
557- php_pack (& argv [currentarg ++ ], 4 , map , & ZSTR_VAL (output )[outputpos ]);
548+ php_pack (& argv [currentarg ++ ], 4 , endianness , & ZSTR_VAL (output )[outputpos ]);
558549 outputpos += 4 ;
559550 }
560551 break ;
@@ -565,16 +556,16 @@ PHP_FUNCTION(pack)
565556 case 'Q' :
566557 case 'J' :
567558 case 'P' : {
568- int * map = machine_endian_longlong_map ;
559+ php_pack_endianness endianness = PHP_MACHINE_ENDIAN ;
569560
570561 if (code == 'J' ) {
571- map = big_endian_longlong_map ;
562+ endianness = PHP_BIG_ENDIAN ;
572563 } else if (code == 'P' ) {
573- map = little_endian_longlong_map ;
564+ endianness = PHP_LITTLE_ENDIAN ;
574565 }
575566
576567 while (arg -- > 0 ) {
577- php_pack (& argv [currentarg ++ ], 8 , map , & ZSTR_VAL (output )[outputpos ]);
568+ php_pack (& argv [currentarg ++ ], 8 , endianness , & ZSTR_VAL (output )[outputpos ]);
578569 outputpos += 8 ;
579570 }
580571 break ;
@@ -1178,127 +1169,3 @@ PHP_FUNCTION(unpack)
11781169 }
11791170}
11801171/* }}} */
1181-
1182- /* {{{ PHP_MINIT_FUNCTION */
1183- PHP_MINIT_FUNCTION (pack )
1184- {
1185- int i ;
1186-
1187- if (MACHINE_LITTLE_ENDIAN ) {
1188- /* Where to get lo to hi bytes from */
1189- byte_map [0 ] = 0 ;
1190-
1191- for (i = 0 ; i < (int )sizeof (int ); i ++ ) {
1192- int_map [i ] = i ;
1193- }
1194-
1195- machine_endian_short_map [0 ] = 0 ;
1196- machine_endian_short_map [1 ] = 1 ;
1197- big_endian_short_map [0 ] = 1 ;
1198- big_endian_short_map [1 ] = 0 ;
1199- little_endian_short_map [0 ] = 0 ;
1200- little_endian_short_map [1 ] = 1 ;
1201-
1202- machine_endian_long_map [0 ] = 0 ;
1203- machine_endian_long_map [1 ] = 1 ;
1204- machine_endian_long_map [2 ] = 2 ;
1205- machine_endian_long_map [3 ] = 3 ;
1206- big_endian_long_map [0 ] = 3 ;
1207- big_endian_long_map [1 ] = 2 ;
1208- big_endian_long_map [2 ] = 1 ;
1209- big_endian_long_map [3 ] = 0 ;
1210- little_endian_long_map [0 ] = 0 ;
1211- little_endian_long_map [1 ] = 1 ;
1212- little_endian_long_map [2 ] = 2 ;
1213- little_endian_long_map [3 ] = 3 ;
1214-
1215- #if SIZEOF_ZEND_LONG > 4
1216- machine_endian_longlong_map [0 ] = 0 ;
1217- machine_endian_longlong_map [1 ] = 1 ;
1218- machine_endian_longlong_map [2 ] = 2 ;
1219- machine_endian_longlong_map [3 ] = 3 ;
1220- machine_endian_longlong_map [4 ] = 4 ;
1221- machine_endian_longlong_map [5 ] = 5 ;
1222- machine_endian_longlong_map [6 ] = 6 ;
1223- machine_endian_longlong_map [7 ] = 7 ;
1224- big_endian_longlong_map [0 ] = 7 ;
1225- big_endian_longlong_map [1 ] = 6 ;
1226- big_endian_longlong_map [2 ] = 5 ;
1227- big_endian_longlong_map [3 ] = 4 ;
1228- big_endian_longlong_map [4 ] = 3 ;
1229- big_endian_longlong_map [5 ] = 2 ;
1230- big_endian_longlong_map [6 ] = 1 ;
1231- big_endian_longlong_map [7 ] = 0 ;
1232- little_endian_longlong_map [0 ] = 0 ;
1233- little_endian_longlong_map [1 ] = 1 ;
1234- little_endian_longlong_map [2 ] = 2 ;
1235- little_endian_longlong_map [3 ] = 3 ;
1236- little_endian_longlong_map [4 ] = 4 ;
1237- little_endian_longlong_map [5 ] = 5 ;
1238- little_endian_longlong_map [6 ] = 6 ;
1239- little_endian_longlong_map [7 ] = 7 ;
1240- #endif
1241- }
1242- else {
1243- zval val ;
1244- int size = sizeof (Z_LVAL (val ));
1245- Z_LVAL (val )= 0 ; /*silence a warning*/
1246-
1247- /* Where to get hi to lo bytes from */
1248- byte_map [0 ] = size - 1 ;
1249-
1250- for (i = 0 ; i < (int )sizeof (int ); i ++ ) {
1251- int_map [i ] = size - (sizeof (int ) - i );
1252- }
1253-
1254- machine_endian_short_map [0 ] = size - 2 ;
1255- machine_endian_short_map [1 ] = size - 1 ;
1256- big_endian_short_map [0 ] = size - 2 ;
1257- big_endian_short_map [1 ] = size - 1 ;
1258- little_endian_short_map [0 ] = size - 1 ;
1259- little_endian_short_map [1 ] = size - 2 ;
1260-
1261- machine_endian_long_map [0 ] = size - 4 ;
1262- machine_endian_long_map [1 ] = size - 3 ;
1263- machine_endian_long_map [2 ] = size - 2 ;
1264- machine_endian_long_map [3 ] = size - 1 ;
1265- big_endian_long_map [0 ] = size - 4 ;
1266- big_endian_long_map [1 ] = size - 3 ;
1267- big_endian_long_map [2 ] = size - 2 ;
1268- big_endian_long_map [3 ] = size - 1 ;
1269- little_endian_long_map [0 ] = size - 1 ;
1270- little_endian_long_map [1 ] = size - 2 ;
1271- little_endian_long_map [2 ] = size - 3 ;
1272- little_endian_long_map [3 ] = size - 4 ;
1273-
1274- #if SIZEOF_ZEND_LONG > 4
1275- machine_endian_longlong_map [0 ] = size - 8 ;
1276- machine_endian_longlong_map [1 ] = size - 7 ;
1277- machine_endian_longlong_map [2 ] = size - 6 ;
1278- machine_endian_longlong_map [3 ] = size - 5 ;
1279- machine_endian_longlong_map [4 ] = size - 4 ;
1280- machine_endian_longlong_map [5 ] = size - 3 ;
1281- machine_endian_longlong_map [6 ] = size - 2 ;
1282- machine_endian_longlong_map [7 ] = size - 1 ;
1283- big_endian_longlong_map [0 ] = size - 8 ;
1284- big_endian_longlong_map [1 ] = size - 7 ;
1285- big_endian_longlong_map [2 ] = size - 6 ;
1286- big_endian_longlong_map [3 ] = size - 5 ;
1287- big_endian_longlong_map [4 ] = size - 4 ;
1288- big_endian_longlong_map [5 ] = size - 3 ;
1289- big_endian_longlong_map [6 ] = size - 2 ;
1290- big_endian_longlong_map [7 ] = size - 1 ;
1291- little_endian_longlong_map [0 ] = size - 1 ;
1292- little_endian_longlong_map [1 ] = size - 2 ;
1293- little_endian_longlong_map [2 ] = size - 3 ;
1294- little_endian_longlong_map [3 ] = size - 4 ;
1295- little_endian_longlong_map [4 ] = size - 5 ;
1296- little_endian_longlong_map [5 ] = size - 6 ;
1297- little_endian_longlong_map [6 ] = size - 7 ;
1298- little_endian_longlong_map [7 ] = size - 8 ;
1299- #endif
1300- }
1301-
1302- return SUCCESS ;
1303- }
1304- /* }}} */
0 commit comments