]> granicus.if.org Git - php/commitdiff
Merge branch 'PHP-5.6' into PHP-7.0
authorYasuo Ohgaki <yohgaki@php.net>
Tue, 6 Sep 2016 07:41:52 +0000 (16:41 +0900)
committerYasuo Ohgaki <yohgaki@php.net>
Tue, 6 Sep 2016 07:41:52 +0000 (16:41 +0900)
* PHP-5.6:
  Fixed Bug #66964 mb_convert_variables() cannot detect recursion

1  2 
ext/mbstring/mbstring.c

index c9200b8ce5173debff0035b7036a90cb8e1a39b6,18e348ddaea3051f66243fc6adf908a36ce7a718..baec14c70c0785bada9182e6588740ef38477bc4
@@@ -3701,8 -3531,9 +3701,9 @@@ PHP_FUNCTION(mb_convert_variables
        const mbfl_encoding **elist;
        char *to_enc;
        void *ptmp;
+       int recursion_error = 0;
  
 -      if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sZ+", &to_enc, &to_enc_len, &zfrom_enc, &args, &argc) == FAILURE) {
 +      if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz+", &to_enc, &to_enc_len, &zfrom_enc, &args, &argc) == FAILURE) {
                return;
        }
  
                                        }
                                } else {
                                        stack_level--;
 -                                      var = stack[stack_level];
 +                                      var = &stack[stack_level];
                                }
 -                              if (Z_TYPE_PP(var) == IS_ARRAY || Z_TYPE_PP(var) == IS_OBJECT) {
 -                                      target_hash = HASH_OF(*var);
 +                              if (Z_TYPE_P(var) == IS_ARRAY || Z_TYPE_P(var) == IS_OBJECT) {
 +                                      target_hash = HASH_OF(var);
                                        if (target_hash != NULL) {
 -                                              while (zend_hash_get_current_data(target_hash, (void **) &hash_entry) != FAILURE) {
 -                                                      if (++target_hash->nApplyCount > 1) {
 -                                                              --target_hash->nApplyCount;
 +                                              while ((hash_entry = zend_hash_get_current_data(target_hash)) != NULL) {
++                                                      if (++target_hash->u.v.nApplyCount > 1) {
++                                                              --target_hash->u.v.nApplyCount;
+                                                               recursion_error = 1;
+                                                               goto detect_end;
+                                                       }
                                                        zend_hash_move_forward(target_hash);
 -                                                      if (Z_TYPE_PP(hash_entry) == IS_ARRAY || Z_TYPE_PP(hash_entry) == IS_OBJECT) {
 +                                                      if (Z_TYPE_P(hash_entry) == IS_INDIRECT) {
 +                                                              hash_entry = Z_INDIRECT_P(hash_entry);
 +                                                      }
 +                                                      ZVAL_DEREF(hash_entry);
 +                                                      if (Z_TYPE_P(hash_entry) == IS_ARRAY || Z_TYPE_P(hash_entry) == IS_OBJECT) {
                                                                if (stack_level >= stack_max) {
                                                                        stack_max += PHP_MBSTR_STACK_BLOCK_SIZE;
 -                                                                      ptmp = erealloc(stack, sizeof(zval **)*stack_max);
 -                                                                      stack = (zval ***)ptmp;
 +                                                                      ptmp = erealloc(stack, sizeof(zval) * stack_max);
 +                                                                      stack = (zval *)ptmp;
                                                                }
 -                                                              stack[stack_level] = var;
 +                                                              ZVAL_COPY_VALUE(&stack[stack_level], var);
                                                                stack_level++;
                                                                var = hash_entry;
 -                                                              target_hash = HASH_OF(*var);
 +                                                              target_hash = HASH_OF(var);
                                                                if (target_hash != NULL) {
                                                                        zend_hash_internal_pointer_reset(target_hash);
                                                                        continue;
@@@ -3805,6 -3635,20 +3811,19 @@@ detect_end
                        from_encoding = mbfl_encoding_detector_judge2(identd);
                        mbfl_encoding_detector_delete(identd);
                }
 -                      while(stack_level-- && (var = stack[stack_level])) {
 -                              if (HASH_OF(*var)->nApplyCount > 1) {
 -                                      HASH_OF(*var)->nApplyCount--;
+               if (recursion_error) {
 -                      efree(args);
++                      while(stack_level-- && (var = &stack[stack_level])) {
++                              if (HASH_OF(var)->u.v.nApplyCount > 1) {
++                                      HASH_OF(var)->u.v.nApplyCount--;
+                               }
+                       }
+                       efree(stack);
+                       if (elist != NULL) {
+                               efree((void *)elist);
+                       }
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot handle recursive references");
+                       RETURN_FALSE;
+               }
                efree(stack);
  
                if (!from_encoding) {
                                }
                        } else {
                                stack_level--;
 -                              var = stack[stack_level];
 +                              var = &stack[stack_level];
                        }
 -                      if (Z_TYPE_PP(var) == IS_ARRAY || Z_TYPE_PP(var) == IS_OBJECT) {
 -                              target_hash = HASH_OF(*var);
 +                      if (Z_TYPE_P(var) == IS_ARRAY || Z_TYPE_P(var) == IS_OBJECT) {
 +                              target_hash = HASH_OF(var);
                                if (target_hash != NULL) {
 -                                      while (zend_hash_get_current_data(target_hash, (void **) &hash_entry) != FAILURE) {
 +                                      while ((hash_entry_ptr = zend_hash_get_current_data(target_hash)) != NULL) {
                                                zend_hash_move_forward(target_hash);
 -                                              if (Z_TYPE_PP(hash_entry) == IS_ARRAY || Z_TYPE_PP(hash_entry) == IS_OBJECT) {
 -                                                      if (++(HASH_OF(*hash_entry)->nApplyCount) > 1) {
 -                                                              --(HASH_OF(*hash_entry)->nApplyCount);
 +                                              if (Z_TYPE_P(hash_entry_ptr) == IS_INDIRECT) {
 +                                                      hash_entry_ptr = Z_INDIRECT_P(hash_entry_ptr);
 +                                              }
 +                                              hash_entry = hash_entry_ptr;
 +                                              ZVAL_DEREF(hash_entry);
 +                                              if (Z_TYPE_P(hash_entry) == IS_ARRAY || Z_TYPE_P(hash_entry) == IS_OBJECT) {
++                                                      if (++(HASH_OF(hash_entry)->u.v.nApplyCount) > 1) {
++                                                              --(HASH_OF(hash_entry)->u.v.nApplyCount);
+                                                               recursion_error = 1;
+                                                               goto conv_end;
+                                                       }
                                                        if (stack_level >= stack_max) {
                                                                stack_max += PHP_MBSTR_STACK_BLOCK_SIZE;
 -                                                              ptmp = erealloc(stack, sizeof(zval **)*stack_max);
 -                                                              stack = (zval ***)ptmp;
 +                                                              ptmp = erealloc(stack, sizeof(zval) * stack_max);
 +                                                              stack = (zval *)ptmp;
                                                        }
 -                                                      stack[stack_level] = var;
 +                                                      ZVAL_COPY_VALUE(&stack[stack_level], var);
                                                        stack_level++;
                                                        var = hash_entry;
 -                                                      target_hash = HASH_OF(*var);
 +                                                      SEPARATE_ZVAL(hash_entry);
 +                                                      target_hash = HASH_OF(var);
                                                        if (target_hash != NULL) {
                                                                zend_hash_internal_pointer_reset(target_hash);
                                                                continue;
                                }
                        }
                }
-               efree(stack);
  
+ conv_end:
                MBSTRG(illegalchars) += mbfl_buffer_illegalchars(convd);
                mbfl_buffer_converter_delete(convd);
 -                      while(stack_level-- && (var = stack[stack_level])) {
 -                              if (HASH_OF(*var)->nApplyCount > 1) {
 -                                      HASH_OF(*var)->nApplyCount--;
+               if (recursion_error) {
 -                      efree(args);
++                      while(stack_level-- && (var = &stack[stack_level])) {
++                              if (HASH_OF(var)->u.v.nApplyCount > 1) {
++                                      HASH_OF(var)->u.v.nApplyCount--;
+                               }
+                       }
+                       efree(stack);
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot handle recursive references");
+                       RETURN_FALSE;
+               }
+               efree(stack);
        }
  
 -      efree(args);
 -
        if (from_encoding) {
 -              RETURN_STRING(from_encoding->name, 1);
 +              RETURN_STRING(from_encoding->name);
        } else {
                RETURN_FALSE;
        }