@@ -129,24 +129,25 @@ static inline size_t align_to(size_t pos, size_t alignment) {
129129 return pos + (offset ? alignment - offset : 0 );
130130}
131131
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 ) {
134134 size_t count , alignment ;
135135 const char * spec = * specp ;
136136 /* parse size */
137- if (* spec == 's' ) {
137+ if (* spec == 's' || * spec == 'S' ) {
138138 * sz = 2 ;
139139 alignment = __alignof__(uint16_t ); /* usually 2 */
140- } else if (* spec == 'l' ) {
140+ } else if (* spec == 'l' || * spec == 'L' ) {
141141 * sz = 4 ;
142142 alignment = __alignof__(uint32_t ); /* usually 4 */
143- } else if (* spec == 'q' ) {
143+ } else if (* spec == 'q' || * spec == 'Q' ) {
144144 * sz = 8 ;
145145 alignment = __alignof__(uint64_t ); /* usually 8 */
146- } else if (* spec == 'i' ) {
146+ } else if (* spec == 'i' || * spec == 'I' ) {
147147 * sz = sizeof (int );
148148 alignment = __alignof__(int ); /* usually 4 */
149149 } else {
150+ ZEND_ASSERT (* spec == 'b' || * spec == 'B' );
150151 * sz = 1 ;
151152 alignment = 1 ;
152153 }
@@ -179,6 +180,7 @@ static uint64_t one_from_buffer(size_t sz, const unsigned char *buf) {
179180 const uint64_t * x = (const uint64_t * ) buf ;
180181 return * x ;
181182 } else {
183+ ZEND_ASSERT (sz == 1 );
182184 return * buf ;
183185 }
184186}
@@ -194,6 +196,7 @@ static void one_to_buffer(size_t sz, unsigned char *buf, uint64_t val) {
194196 uint64_t * x = (uint64_t * ) buf ;
195197 * x = val ;
196198 } else {
199+ ZEND_ASSERT (sz == 1 );
197200 * buf = val ;
198201 }
199202}
@@ -205,7 +208,8 @@ static void one_to_buffer(size_t sz, unsigned char *buf, uint64_t val) {
205208 l[COUNT] -- serialize COUNT 32-bit integers
206209 q[COUNT] -- serialize COUNT 64-bit integers
207210 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
209213 . (must be last character) -- assert that the hash context has exactly
210214 this size
211215 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) {
218222 significant bits first. This allows 32-bit and 64-bit architectures to
219223 interchange serialized HashContexts. */
220224
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 ) /* {{{ */
222226{
223227 size_t pos = 0 , max_alignment = 1 , sz , count ;
224228 unsigned char * buf = (unsigned char * ) hash -> context ;
225229 zval tmp ;
226- * magic = PHP_HASH_SERIALIZE_MAGIC_SPEC ;
227230 array_init (zv );
228231 while (* spec != '\0' && * spec != '.' ) {
229- char specch = * spec ;
232+ char spec_ch = * spec ;
230233 count = parse_serialize_spec (& spec , & pos , & sz , & max_alignment );
231234 if (pos + count * sz > hash -> ops -> context_size ) {
232235 return FAILURE ;
233236 }
234- if (specch == '-' ) {
235- pos += count ;
237+ if (isupper (( unsigned char ) spec_ch ) ) {
238+ pos += count * sz ;
236239 } else if (sz == 1 && count > 1 ) {
237240 ZVAL_STRINGL (& tmp , (char * ) buf + pos , count );
238241 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
264267 -999 == spec wrong size for context
265268 -1000 - POS == problem at byte offset POS */
266269
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 ) /* {{{ */
268271{
269272 size_t pos = 0 , max_alignment = 1 , sz , count , j = 0 ;
270273 unsigned char * buf = (unsigned char * ) hash -> context ;
271274 zval * elt ;
272- if (magic != PHP_HASH_SERIALIZE_MAGIC_SPEC || Z_TYPE_P (zv ) != IS_ARRAY ) {
275+ if (Z_TYPE_P (zv ) != IS_ARRAY ) {
273276 return FAILURE ;
274277 }
275278 while (* spec != '\0' && * spec != '.' ) {
276- char specch = * spec ;
279+ char spec_ch = * spec ;
277280 count = parse_serialize_spec (& spec , & pos , & sz , & max_alignment );
278281 if (pos + count * sz > hash -> ops -> context_size ) {
279282 return -999 ;
280283 }
281- if (specch == '-' ) {
282- pos += count ;
284+ if (isupper (( unsigned char ) spec_ch ) ) {
285+ pos += count * sz ;
283286 } else if (sz == 1 && count > 1 ) {
284287 elt = zend_hash_index_find (Z_ARRVAL_P (zv ), j );
285288 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
296299 return -1000 - pos ;
297300 }
298301 ++ j ;
299- val = (uint32_t ) zval_get_long (elt );
302+ val = (uint32_t ) Z_LVAL_P (elt );
300303 if (sz == 8 ) {
301304 elt = zend_hash_index_find (Z_ARRVAL_P (zv ), j );
302305 if (!elt || Z_TYPE_P (elt ) != IS_LONG ) {
303306 return -1000 - pos ;
304307 }
305308 ++ j ;
306- val += ((uint64_t ) zval_get_long (elt )) << 32 ;
309+ val += ((uint64_t ) Z_LVAL_P (elt )) << 32 ;
307310 }
308311 one_to_buffer (sz , buf + pos , val );
309312 pos += sz ;
@@ -321,27 +324,21 @@ PHP_HASH_API int php_hash_unserialize_spec(php_hashcontext_object *hash, zend_lo
321324PHP_HASH_API int php_hash_serialize (const php_hashcontext_object * hash , zend_long * magic , zval * zv ) /* {{{ */
322325{
323326 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 );
325329 } 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 ;
329331 }
330332}
331333/* }}} */
332334
333335PHP_HASH_API int php_hash_unserialize (php_hashcontext_object * hash , zend_long magic , const zval * zv ) /* {{{ */
334336{
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 );
337340 } 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 ;
345342 }
346343}
347344/* }}} */
@@ -1466,7 +1463,7 @@ PHP_METHOD(HashContext, __serialize)
14661463 return ;
14671464
14681465serialize_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 );
14701467 RETURN_THROWS ();
14711468}
14721469/* }}} */
@@ -1508,8 +1505,8 @@ PHP_METHOD(HashContext, __unserialize)
15081505 RETURN_THROWS ();
15091506 }
15101507
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 );
15131510 if (options & PHP_HASH_HMAC ) {
15141511 zend_value_error ("HashContext with HASH_HMAC option cannot be serialized" );
15151512 RETURN_THROWS ();
@@ -1520,7 +1517,7 @@ PHP_METHOD(HashContext, __unserialize)
15201517 zend_value_error ("Unknown hash algorithm" );
15211518 RETURN_THROWS ();
15221519 } 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 );
15241521 RETURN_THROWS ();
15251522 }
15261523
@@ -1531,7 +1528,7 @@ PHP_METHOD(HashContext, __unserialize)
15311528
15321529 unserialize_result = ops -> hash_unserialize (hash , magic , hash_zv );
15331530 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 );
15351532 /* Free internally allocated resources */
15361533 php_hashcontext_dtor (Z_OBJ_P (object ));
15371534 RETURN_THROWS ();
0 commit comments