@@ -739,32 +739,32 @@ PHP_FUNCTION(unpack)
739
739
while (formatlen -- > 0 ) {
740
740
char type = * (format ++ );
741
741
char c ;
742
- int arg = 1 , argb ;
742
+ int repetitions = 1 , argb ;
743
743
char * name ;
744
744
int namelen ;
745
- int size = 0 ;
745
+ int size = 0 ;
746
746
747
747
/* Handle format arguments if any */
748
748
if (formatlen > 0 ) {
749
749
c = * format ;
750
750
751
751
if (c >= '0' && c <= '9' ) {
752
- arg = atoi (format );
752
+ repetitions = atoi (format );
753
753
754
754
while (formatlen > 0 && * format >= '0' && * format <= '9' ) {
755
755
format ++ ;
756
756
formatlen -- ;
757
757
}
758
758
} else if (c == '*' ) {
759
- arg = -1 ;
759
+ repetitions = -1 ;
760
760
format ++ ;
761
761
formatlen -- ;
762
762
}
763
763
}
764
764
765
765
/* Get of new value in array */
766
766
name = format ;
767
- argb = arg ;
767
+ argb = repetitions ;
768
768
769
769
while (formatlen > 0 && * format != '/' ) {
770
770
formatlen -- ;
@@ -780,9 +780,9 @@ PHP_FUNCTION(unpack)
780
780
/* Never use any input */
781
781
case 'X' :
782
782
size = -1 ;
783
- if (arg < 0 ) {
783
+ if (repetitions < 0 ) {
784
784
php_error_docref (NULL , E_WARNING , "Type %c: '*' ignored" , type );
785
- arg = 1 ;
785
+ repetitions = 1 ;
786
786
}
787
787
break ;
788
788
@@ -793,14 +793,14 @@ PHP_FUNCTION(unpack)
793
793
case 'a' :
794
794
case 'A' :
795
795
case 'Z' :
796
- size = arg ;
797
- arg = 1 ;
796
+ size = repetitions ;
797
+ repetitions = 1 ;
798
798
break ;
799
799
800
800
case 'h' :
801
801
case 'H' :
802
- size = (arg > 0 ) ? (arg + (arg % 2 )) / 2 : arg ;
803
- arg = 1 ;
802
+ size = (repetitions > 0 ) ? (repetitions + (repetitions % 2 )) / 2 : repetitions ;
803
+ repetitions = 1 ;
804
804
break ;
805
805
806
806
/* Use 1 byte of input */
@@ -870,18 +870,9 @@ PHP_FUNCTION(unpack)
870
870
RETURN_FALSE ;
871
871
}
872
872
873
- /* Do actual unpacking */
874
- for (i = 0 ; i != arg ; i ++ ) {
875
- /* Space for name + number, safe as namelen is ensured <= 200 */
876
- char n [256 ];
877
873
878
- if (arg != 1 || namelen == 0 ) {
879
- /* Need to add element number to name */
880
- snprintf (n , sizeof (n ), "%.*s%d" , namelen , name , i + 1 );
881
- } else {
882
- /* Truncate name to next format code or end of string */
883
- snprintf (n , sizeof (n ), "%.*s" , namelen , name );
884
- }
874
+ /* Do actual unpacking */
875
+ for (i = 0 ; i != repetitions ; i ++ ) {
885
876
886
877
if (size != 0 && size != -1 && INT_MAX - size + 1 < inputpos ) {
887
878
php_error_docref (NULL , E_WARNING , "Type %c: integer overflow" , type );
@@ -890,6 +881,22 @@ PHP_FUNCTION(unpack)
890
881
}
891
882
892
883
if ((inputpos + size ) <= inputlen ) {
884
+
885
+ zend_string * real_name ;
886
+ zval val ;
887
+
888
+ if (repetitions == 1 && namelen > 0 ) {
889
+ /* Use a part of the formatarg argument directly as the name. */
890
+ real_name = zend_string_init_fast (name , namelen );
891
+
892
+ } else {
893
+ /* Need to add the 1-based element number to the name */
894
+ char buf [MAX_LENGTH_OF_LONG + 1 ];
895
+ char * res = zend_print_ulong_to_buf (buf + sizeof (buf ) - 1 , i + 1 );
896
+ size_t digits = buf + sizeof (buf ) - 1 - res ;
897
+ real_name = zend_string_concat2 (name , namelen , res , digits );
898
+ }
899
+
893
900
switch ((int ) type ) {
894
901
case 'a' : {
895
902
/* a will not strip any trailing whitespace or null padding */
@@ -902,7 +909,8 @@ PHP_FUNCTION(unpack)
902
909
903
910
size = len ;
904
911
905
- add_assoc_stringl (return_value , n , & input [inputpos ], len );
912
+ ZVAL_STRINGL (& val , & input [inputpos ], len );
913
+ zend_symtable_update (Z_ARRVAL_P (return_value ), real_name , & val );
906
914
break ;
907
915
}
908
916
case 'A' : {
@@ -928,7 +936,8 @@ PHP_FUNCTION(unpack)
928
936
break ;
929
937
}
930
938
931
- add_assoc_stringl (return_value , n , & input [inputpos ], len + 1 );
939
+ ZVAL_STRINGL (& val , & input [inputpos ], len + 1 );
940
+ zend_symtable_update (Z_ARRVAL_P (return_value ), real_name , & val );
932
941
break ;
933
942
}
934
943
/* New option added for Z to remain in-line with the Perl implementation */
@@ -952,7 +961,8 @@ PHP_FUNCTION(unpack)
952
961
}
953
962
len = s ;
954
963
955
- add_assoc_stringl (return_value , n , & input [inputpos ], len );
964
+ ZVAL_STRINGL (& val , & input [inputpos ], len );
965
+ zend_symtable_update (Z_ARRVAL_P (return_value ), real_name , & val );
956
966
break ;
957
967
}
958
968
@@ -995,15 +1005,19 @@ PHP_FUNCTION(unpack)
995
1005
}
996
1006
997
1007
ZSTR_VAL (buf )[len ] = '\0' ;
998
- add_assoc_str (return_value , n , buf );
1008
+
1009
+ ZVAL_STR (& val , buf );
1010
+ zend_symtable_update (Z_ARRVAL_P (return_value ), real_name , & val );
999
1011
break ;
1000
1012
}
1001
1013
1002
1014
case 'c' : /* signed */
1003
1015
case 'C' : { /* unsigned */
1004
1016
uint8_t x = input [inputpos ];
1005
1017
zend_long v = (type == 'c' ) ? (int8_t ) x : x ;
1006
- add_assoc_long (return_value , n , v );
1018
+
1019
+ ZVAL_LONG (& val , v );
1020
+ zend_symtable_update (Z_ARRVAL_P (return_value ), real_name , & val );
1007
1021
break ;
1008
1022
}
1009
1023
@@ -1022,15 +1036,18 @@ PHP_FUNCTION(unpack)
1022
1036
v = x ;
1023
1037
}
1024
1038
1025
- add_assoc_long (return_value , n , v );
1039
+ ZVAL_LONG (& val , v );
1040
+ zend_symtable_update (Z_ARRVAL_P (return_value ), real_name , & val );
1026
1041
break ;
1027
1042
}
1028
1043
1029
1044
case 'i' : /* signed integer, machine size, machine endian */
1030
1045
case 'I' : { /* unsigned integer, machine size, machine endian */
1031
1046
unsigned int x = * ((unaligned_uint * ) & input [inputpos ]);
1032
1047
zend_long v = (type == 'i' ) ? (int ) x : x ;
1033
- add_assoc_long (return_value , n , v );
1048
+
1049
+ ZVAL_LONG (& val , v );
1050
+ zend_symtable_update (Z_ARRVAL_P (return_value ), real_name , & val );
1034
1051
break ;
1035
1052
}
1036
1053
@@ -1049,7 +1066,9 @@ PHP_FUNCTION(unpack)
1049
1066
v = x ;
1050
1067
}
1051
1068
1052
- add_assoc_long (return_value , n , v );
1069
+ ZVAL_LONG (& val , v );
1070
+ zend_symtable_update (Z_ARRVAL_P (return_value ), real_name , & val );
1071
+
1053
1072
break ;
1054
1073
}
1055
1074
@@ -1069,7 +1088,8 @@ PHP_FUNCTION(unpack)
1069
1088
v = x ;
1070
1089
}
1071
1090
1072
- add_assoc_long (return_value , n , v );
1091
+ ZVAL_LONG (& val , v );
1092
+ zend_symtable_update (Z_ARRVAL_P (return_value ), real_name , & val );
1073
1093
break ;
1074
1094
}
1075
1095
#endif
@@ -1088,7 +1108,8 @@ PHP_FUNCTION(unpack)
1088
1108
memcpy (& v , & input [inputpos ], sizeof (float ));
1089
1109
}
1090
1110
1091
- add_assoc_double (return_value , n , (double )v );
1111
+ ZVAL_DOUBLE (& val , v );
1112
+ zend_symtable_update (Z_ARRVAL_P (return_value ), real_name , & val );
1092
1113
break ;
1093
1114
}
1094
1115
@@ -1105,7 +1126,9 @@ PHP_FUNCTION(unpack)
1105
1126
} else {
1106
1127
memcpy (& v , & input [inputpos ], sizeof (double ));
1107
1128
}
1108
- add_assoc_double (return_value , n , v );
1129
+
1130
+ ZVAL_DOUBLE (& val , v );
1131
+ zend_symtable_update (Z_ARRVAL_P (return_value ), real_name , & val );
1109
1132
break ;
1110
1133
}
1111
1134
@@ -1116,33 +1139,35 @@ PHP_FUNCTION(unpack)
1116
1139
case 'X' :
1117
1140
if (inputpos < size ) {
1118
1141
inputpos = - size ;
1119
- i = arg - 1 ; /* Break out of for loop */
1142
+ i = repetitions - 1 ; /* Break out of for loop */
1120
1143
1121
- if (arg >= 0 ) {
1144
+ if (repetitions >= 0 ) {
1122
1145
php_error_docref (NULL , E_WARNING , "Type %c: outside of string" , type );
1123
1146
}
1124
1147
}
1125
1148
break ;
1126
1149
1127
1150
case '@' :
1128
- if (arg <= inputlen ) {
1129
- inputpos = arg ;
1151
+ if (repetitions <= inputlen ) {
1152
+ inputpos = repetitions ;
1130
1153
} else {
1131
1154
php_error_docref (NULL , E_WARNING , "Type %c: outside of string" , type );
1132
1155
}
1133
1156
1134
- i = arg - 1 ; /* Done, break out of for loop */
1157
+ i = repetitions - 1 ; /* Done, break out of for loop */
1135
1158
break ;
1136
1159
}
1137
1160
1161
+ zend_string_release (real_name );
1162
+
1138
1163
inputpos += size ;
1139
1164
if (inputpos < 0 ) {
1140
1165
if (size != -1 ) { /* only print warning if not working with * */
1141
1166
php_error_docref (NULL , E_WARNING , "Type %c: outside of string" , type );
1142
1167
}
1143
1168
inputpos = 0 ;
1144
1169
}
1145
- } else if (arg < 0 ) {
1170
+ } else if (repetitions < 0 ) {
1146
1171
/* Reached end of input for '*' repeater */
1147
1172
break ;
1148
1173
} else {
0 commit comments