@@ -129,24 +129,25 @@ static inline size_t align_to(size_t pos, size_t alignment) {
129
129
return pos + (offset ? alignment - offset : 0 );
130
130
}
131
131
132
- static size_t parse_serialize_spec (const char * * specp , size_t * pos , size_t * sz ,
133
- size_t * max_alignment ) {
132
+ static size_t parse_serialize_spec (
133
+ const char * * specp , size_t * pos , size_t * sz , size_t * max_alignment ) {
134
134
size_t count , alignment ;
135
135
const char * spec = * specp ;
136
136
/* parse size */
137
- if (* spec == 's' ) {
137
+ if (* spec == 's' || * spec == 'S' ) {
138
138
* sz = 2 ;
139
139
alignment = __alignof__(uint16_t ); /* usually 2 */
140
- } else if (* spec == 'l' ) {
140
+ } else if (* spec == 'l' || * spec == 'L' ) {
141
141
* sz = 4 ;
142
142
alignment = __alignof__(uint32_t ); /* usually 4 */
143
- } else if (* spec == 'q' ) {
143
+ } else if (* spec == 'q' || * spec == 'Q' ) {
144
144
* sz = 8 ;
145
145
alignment = __alignof__(uint64_t ); /* usually 8 */
146
- } else if (* spec == 'i' ) {
146
+ } else if (* spec == 'i' || * spec == 'I' ) {
147
147
* sz = sizeof (int );
148
148
alignment = __alignof__(int ); /* usually 4 */
149
149
} else {
150
+ ZEND_ASSERT (* spec == 'b' || * spec == 'B' );
150
151
* sz = 1 ;
151
152
alignment = 1 ;
152
153
}
@@ -179,6 +180,7 @@ static uint64_t one_from_buffer(size_t sz, const unsigned char *buf) {
179
180
const uint64_t * x = (const uint64_t * ) buf ;
180
181
return * x ;
181
182
} else {
183
+ ZEND_ASSERT (sz == 1 );
182
184
return * buf ;
183
185
}
184
186
}
@@ -194,6 +196,7 @@ static void one_to_buffer(size_t sz, unsigned char *buf, uint64_t val) {
194
196
uint64_t * x = (uint64_t * ) buf ;
195
197
* x = val ;
196
198
} else {
199
+ ZEND_ASSERT (sz == 1 );
197
200
* buf = val ;
198
201
}
199
202
}
@@ -205,7 +208,8 @@ static void one_to_buffer(size_t sz, unsigned char *buf, uint64_t val) {
205
208
l[COUNT] -- serialize COUNT 32-bit integers
206
209
q[COUNT] -- serialize COUNT 64-bit integers
207
210
i[COUNT] -- serialize COUNT `int`s
208
- -[COUNT] -- skip COUNT bytes
211
+ B[COUNT] -- skip COUNT bytes
212
+ S[COUNT], L[COUNT], etc. -- uppercase versions skip instead of read
209
213
. (must be last character) -- assert that the hash context has exactly
210
214
this size
211
215
Example: "llllllb64l16." is the spec for an MD5 context: 6 32-bit
@@ -218,21 +222,20 @@ static void one_to_buffer(size_t sz, unsigned char *buf, uint64_t val) {
218
222
significant bits first. This allows 32-bit and 64-bit architectures to
219
223
interchange serialized HashContexts. */
220
224
221
- PHP_HASH_API int php_hash_serialize_spec (const php_hashcontext_object * hash , zend_long * magic , zval * zv , const char * spec ) /* {{{ */
225
+ PHP_HASH_API int php_hash_serialize_spec (const php_hashcontext_object * hash , zval * zv , const char * spec ) /* {{{ */
222
226
{
223
227
size_t pos = 0 , max_alignment = 1 , sz , count ;
224
228
unsigned char * buf = (unsigned char * ) hash -> context ;
225
229
zval tmp ;
226
- * magic = PHP_HASH_SERIALIZE_MAGIC_SPEC ;
227
230
array_init (zv );
228
231
while (* spec != '\0' && * spec != '.' ) {
229
- char specch = * spec ;
232
+ char spec_ch = * spec ;
230
233
count = parse_serialize_spec (& spec , & pos , & sz , & max_alignment );
231
234
if (pos + count * sz > hash -> ops -> context_size ) {
232
235
return FAILURE ;
233
236
}
234
- if (specch == '-' ) {
235
- pos += count ;
237
+ if (isupper (( unsigned char ) spec_ch ) ) {
238
+ pos += count * sz ;
236
239
} else if (sz == 1 && count > 1 ) {
237
240
ZVAL_STRINGL (& tmp , (char * ) buf + pos , count );
238
241
zend_hash_next_index_insert (Z_ARRVAL_P (zv ), & tmp );
@@ -264,22 +267,22 @@ PHP_HASH_API int php_hash_serialize_spec(const php_hashcontext_object *hash, zen
264
267
-999 == spec wrong size for context
265
268
-1000 - POS == problem at byte offset POS */
266
269
267
- PHP_HASH_API int php_hash_unserialize_spec (php_hashcontext_object * hash , zend_long magic , const zval * zv , const char * spec ) /* {{{ */
270
+ PHP_HASH_API int php_hash_unserialize_spec (php_hashcontext_object * hash , const zval * zv , const char * spec ) /* {{{ */
268
271
{
269
272
size_t pos = 0 , max_alignment = 1 , sz , count , j = 0 ;
270
273
unsigned char * buf = (unsigned char * ) hash -> context ;
271
274
zval * elt ;
272
- if (magic != PHP_HASH_SERIALIZE_MAGIC_SPEC || Z_TYPE_P (zv ) != IS_ARRAY ) {
275
+ if (Z_TYPE_P (zv ) != IS_ARRAY ) {
273
276
return FAILURE ;
274
277
}
275
278
while (* spec != '\0' && * spec != '.' ) {
276
- char specch = * spec ;
279
+ char spec_ch = * spec ;
277
280
count = parse_serialize_spec (& spec , & pos , & sz , & max_alignment );
278
281
if (pos + count * sz > hash -> ops -> context_size ) {
279
282
return -999 ;
280
283
}
281
- if (specch == '-' ) {
282
- pos += count ;
284
+ if (isupper (( unsigned char ) spec_ch ) ) {
285
+ pos += count * sz ;
283
286
} else if (sz == 1 && count > 1 ) {
284
287
elt = zend_hash_index_find (Z_ARRVAL_P (zv ), j );
285
288
if (!elt || Z_TYPE_P (elt ) != IS_STRING || Z_STRLEN_P (elt ) != count ) {
@@ -296,14 +299,14 @@ PHP_HASH_API int php_hash_unserialize_spec(php_hashcontext_object *hash, zend_lo
296
299
return -1000 - pos ;
297
300
}
298
301
++ j ;
299
- val = (uint32_t ) zval_get_long (elt );
302
+ val = (uint32_t ) Z_LVAL_P (elt );
300
303
if (sz == 8 ) {
301
304
elt = zend_hash_index_find (Z_ARRVAL_P (zv ), j );
302
305
if (!elt || Z_TYPE_P (elt ) != IS_LONG ) {
303
306
return -1000 - pos ;
304
307
}
305
308
++ j ;
306
- val += ((uint64_t ) zval_get_long (elt )) << 32 ;
309
+ val += ((uint64_t ) Z_LVAL_P (elt )) << 32 ;
307
310
}
308
311
one_to_buffer (sz , buf + pos , val );
309
312
pos += sz ;
@@ -321,27 +324,21 @@ PHP_HASH_API int php_hash_unserialize_spec(php_hashcontext_object *hash, zend_lo
321
324
PHP_HASH_API int php_hash_serialize (const php_hashcontext_object * hash , zend_long * magic , zval * zv ) /* {{{ */
322
325
{
323
326
if (hash -> ops -> serialize_spec ) {
324
- return php_hash_serialize_spec (hash , magic , zv , hash -> ops -> serialize_spec );
327
+ * magic = PHP_HASH_SERIALIZE_MAGIC_SPEC ;
328
+ return php_hash_serialize_spec (hash , zv , hash -> ops -> serialize_spec );
325
329
} else {
326
- * magic = PHP_HASH_SERIALIZE_MAGIC ;
327
- ZVAL_STRINGL (zv , (const char * ) hash -> context , hash -> ops -> context_size );
328
- return SUCCESS ;
330
+ return FAILURE ;
329
331
}
330
332
}
331
333
/* }}} */
332
334
333
335
PHP_HASH_API int php_hash_unserialize (php_hashcontext_object * hash , zend_long magic , const zval * zv ) /* {{{ */
334
336
{
335
- if (hash -> ops -> serialize_spec ) {
336
- return php_hash_unserialize_spec (hash , magic , zv , hash -> ops -> serialize_spec );
337
+ if (hash -> ops -> serialize_spec
338
+ && magic == PHP_HASH_SERIALIZE_MAGIC_SPEC ) {
339
+ return php_hash_unserialize_spec (hash , zv , hash -> ops -> serialize_spec );
337
340
} else {
338
- if (Z_TYPE_P (zv ) != IS_STRING
339
- || Z_STRLEN_P (zv ) != hash -> ops -> context_size
340
- || magic != PHP_HASH_SERIALIZE_MAGIC ) {
341
- return FAILURE ;
342
- }
343
- memcpy (hash -> context , Z_STRVAL_P (zv ), hash -> ops -> context_size );
344
- return SUCCESS ;
341
+ return FAILURE ;
345
342
}
346
343
}
347
344
/* }}} */
@@ -1466,7 +1463,7 @@ PHP_METHOD(HashContext, __serialize)
1466
1463
return ;
1467
1464
1468
1465
serialize_failure :
1469
- zend_value_error ("HashContext for algorithm '%s' cannot be serialized" , hash -> ops -> algo );
1466
+ zend_value_error ("HashContext for algorithm \"%s\" cannot be serialized" , hash -> ops -> algo );
1470
1467
RETURN_THROWS ();
1471
1468
}
1472
1469
/* }}} */
@@ -1508,8 +1505,8 @@ PHP_METHOD(HashContext, __unserialize)
1508
1505
RETURN_THROWS ();
1509
1506
}
1510
1507
1511
- magic = zval_get_long (magic_zv );
1512
- options = zval_get_long (options_zv );
1508
+ magic = Z_LVAL_P (magic_zv );
1509
+ options = Z_LVAL_P (options_zv );
1513
1510
if (options & PHP_HASH_HMAC ) {
1514
1511
zend_value_error ("HashContext with HASH_HMAC option cannot be serialized" );
1515
1512
RETURN_THROWS ();
@@ -1520,7 +1517,7 @@ PHP_METHOD(HashContext, __unserialize)
1520
1517
zend_value_error ("Unknown hash algorithm" );
1521
1518
RETURN_THROWS ();
1522
1519
} else if (!ops -> hash_unserialize ) {
1523
- zend_value_error ("Hash algorithm '%s' cannot be unserialized" , ops -> algo );
1520
+ zend_value_error ("Hash algorithm \"%s\" cannot be unserialized" , ops -> algo );
1524
1521
RETURN_THROWS ();
1525
1522
}
1526
1523
@@ -1531,7 +1528,7 @@ PHP_METHOD(HashContext, __unserialize)
1531
1528
1532
1529
unserialize_result = ops -> hash_unserialize (hash , magic , hash_zv );
1533
1530
if (unserialize_result != SUCCESS ) {
1534
- zend_value_error ("HashContext for algorithm '%s' cannot be unserialized, format may be non-portable (code %d)" , ops -> algo , unserialize_result );
1531
+ zend_value_error ("HashContext for algorithm \"%s\" cannot be unserialized, format may be non-portable (code %d)" , ops -> algo , unserialize_result );
1535
1532
/* Free internally allocated resources */
1536
1533
php_hashcontext_dtor (Z_OBJ_P (object ));
1537
1534
RETURN_THROWS ();
0 commit comments