]> granicus.if.org Git - php/commitdiff
Merge branch 'PHP-5.6'
authorStanislav Malyshev <stas@php.net>
Tue, 4 Aug 2015 23:14:24 +0000 (16:14 -0700)
committerStanislav Malyshev <stas@php.net>
Tue, 4 Aug 2015 23:14:24 +0000 (16:14 -0700)
* PHP-5.6:
  update NEWS
  fix test
  update NEWS
  Fix bug #70019 - limit extracted files to given directory
  Do not do convert_to_* on unserialize, it messes up references
  Fix #69793 - limit what we accept when unserializing exception
  Fixed bug #70169 (Use After Free Vulnerability in unserialize() with SplDoublyLinkedList)
  Fixed bug #70166 - Use After Free Vulnerability in unserialize() with SPLArrayObject
  ignore signatures for packages too
  Fix bug #70168 - Use After Free Vulnerability in unserialize() with SplObjectStorage
  Fixed bug #69892
  Fix bug #70014 - use RAND_bytes instead of deprecated RAND_pseudo_bytes
  Improved fix for Bug #69441
  Fix bug #70068 (Dangling pointer in the unserialization of ArrayObject items)
  Fix bug #70121 (unserialize() could lead to unexpected methods execution / NULL pointer deref)
  Fix bug #70081: check types for SOAP variables

Conflicts:
Zend/zend_exceptions.c
ext/date/php_date.c
ext/openssl/openssl.c
ext/phar/phar_internal.h
ext/soap/php_http.c
ext/spl/spl_array.c
ext/spl/spl_dllist.c
ext/spl/spl_observer.c
ext/standard/tests/serialize/bug69152.phpt
sapi/cli/tests/005.phpt

1  2 
.gitignore
Zend/zend_exceptions.c
ext/openssl/openssl.c
ext/phar/phar_internal.h
ext/phar/phar_object.c
ext/soap/php_http.c
ext/spl/spl_array.c
ext/spl/spl_observer.c
ext/standard/tests/serialize/bug69152.phpt
sapi/cli/tests/005.phpt

diff --cc .gitignore
Simple merge
index 5d6cc592596d8cc32bd2f01833c29ec1d1720e38,806c2ef9e308b27824d00a4b6fde15164befc765..51ea2319bf1523594d32f4463a590e156139d69e
@@@ -197,25 -155,16 +197,25 @@@ static zend_object *zend_default_except
  
        object_properties_init(object, class_type);
  
 -      ALLOC_ZVAL(trace);
 -      Z_UNSET_ISREF_P(trace);
 -      Z_SET_REFCOUNT_P(trace, 0);
 -      zend_fetch_debug_backtrace(trace, skip_top_traces, 0, 0 TSRMLS_CC);
 +      if (EG(current_execute_data)) {
 +              zend_fetch_debug_backtrace(&trace, skip_top_traces, 0, 0);
 +      } else {
 +              array_init(&trace);
 +      }
 +      Z_SET_REFCOUNT(trace, 0);
-       
++
 +      base_ce = i_get_exception_base(&obj);
  
 -      zend_update_property_string(default_exception_ce, &obj, "file", sizeof("file")-1, zend_get_executed_filename(TSRMLS_C) TSRMLS_CC);
 -      zend_update_property_long(default_exception_ce, &obj, "line", sizeof("line")-1, zend_get_executed_lineno(TSRMLS_C) TSRMLS_CC);
 -      zend_update_property(default_exception_ce, &obj, "trace", sizeof("trace")-1, trace TSRMLS_CC);
 +      if (EXPECTED(class_type != zend_ce_parse_error || !(filename = zend_get_compiled_filename()))) {
 +              zend_update_property_string(base_ce, &obj, "file", sizeof("file")-1, zend_get_executed_filename());
 +              zend_update_property_long(base_ce, &obj, "line", sizeof("line")-1, zend_get_executed_lineno());
 +      } else {
 +              zend_update_property_string(base_ce, &obj, "file", sizeof("file")-1, ZSTR_VAL(filename));
 +              zend_update_property_long(base_ce, &obj, "line", sizeof("line")-1, zend_get_compiled_lineno());
 +      }
 +      zend_update_property(base_ce, &obj, "trace", sizeof("trace")-1, &trace);
  
 -      return Z_OBJVAL(obj);
 +      return object;
  }
  /* }}} */
  
@@@ -279,7 -218,34 +279,33 @@@ ZEND_METHOD(exception, __construct
  }
  /* }}} */
  
 -      value = zend_read_property(default_exception_ce, object, name, sizeof(name)-1, 0 TSRMLS_CC); \
+ /* {{{ proto Exception::__wakeup()
+    Exception unserialize checks */
+ #define CHECK_EXC_TYPE(name, type) \
 -      zval *value;
++      zend_read_property(i_get_exception_base(object), (object), name, sizeof(name) - 1, 1, &value); \
+       if(value && Z_TYPE_P(value) != type) { \
+               zval *tmp; \
+               MAKE_STD_ZVAL(tmp); \
+               ZVAL_STRINGL(tmp, name, sizeof(name)-1, 1); \
+               Z_OBJ_HANDLER_P(object, unset_property)(object, tmp, 0 TSRMLS_CC); \
+               zval_ptr_dtor(&tmp); \
+       }
+ ZEND_METHOD(exception, __wakeup)
+ {
 -      HashTable *intern_ht = zend_std_get_properties(getThis() TSRMLS_CC);
++      zval value;
+       zval *object = getThis();
 -/* {{{ proto ErrorException::__construct(string message, int code, int severity [, string filename [, int lineno [, Exception previous]]])
+       CHECK_EXC_TYPE("message", IS_STRING);
+       CHECK_EXC_TYPE("string", IS_STRING);
+       CHECK_EXC_TYPE("code", IS_LONG);
+       CHECK_EXC_TYPE("file", IS_STRING);
+       CHECK_EXC_TYPE("line", IS_LONG);
+       CHECK_EXC_TYPE("trace", IS_ARRAY);
+       CHECK_EXC_TYPE("previous", IS_OBJECT);
+ }
+ /* }}} */
 +/* {{{ proto ErrorException::__construct(string message, int code, int severity [, string filename [, int lineno [, Throwable previous]]])
     ErrorException constructor */
  ZEND_METHOD(error_exception, __construct)
  {
@@@ -600,19 -608,13 +626,19 @@@ static void _build_trace_string(smart_s
     Obtain the backtrace for the exception as a string (instead of an array) */
  ZEND_METHOD(exception, getTraceAsString)
  {
 -      zval *trace;
 -      char *res, **str, *s_tmp;
 -      int res_len = 0, *len = &res_len, num = 0;
 +      zval *trace, *frame, rv;
 +      zend_ulong index;
 +      zval *object;
 +      zend_class_entry *base_ce;
 +      smart_str str = {0};
 +      uint32_t num = 0;
  
        DEFAULT_0_PARAMS;
-       
 -      trace = zend_read_property(default_exception_ce, getThis(), "trace", sizeof("trace")-1, 1 TSRMLS_CC);
 +      object = getThis();
 +      base_ce = i_get_exception_base(object);
 +
 +      trace = zend_read_property(base_ce, object, "trace", sizeof("trace")-1, 1, &rv);
        if (Z_TYPE_P(trace) != IS_ARRAY) {
                RETURN_FALSE;
        }
@@@ -779,9 -752,10 +805,10 @@@ ZEND_BEGIN_ARG_INFO_EX(arginfo_exceptio
        ZEND_ARG_INFO(0, previous)
  ZEND_END_ARG_INFO()
  
 -const static zend_function_entry default_exception_functions[] = {
 +static const zend_function_entry default_exception_functions[] = {
        ZEND_ME(exception, __clone, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
        ZEND_ME(exception, __construct, arginfo_exception___construct, ZEND_ACC_PUBLIC)
+       ZEND_ME(exception, __wakeup, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
        ZEND_ME(exception, getMessage, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
        ZEND_ME(exception, getCode, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
        ZEND_ME(exception, getFile, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
@@@ -809,12 -783,13 +836,12 @@@ static const zend_function_entry error_
  };
  /* }}} */
  
 -void zend_register_default_exception(TSRMLS_D) /* {{{ */
 +void zend_register_default_exception(void) /* {{{ */
  {
        zend_class_entry ce;
-       
 -      INIT_CLASS_ENTRY(ce, "Exception", default_exception_functions);
 -      default_exception_ce = zend_register_internal_class(&ce TSRMLS_CC);
 -      default_exception_ce->create_object = zend_default_exception_new;
 +      REGISTER_MAGIC_INTERFACE(throwable, Throwable);
 +
        memcpy(&default_exception_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
        default_exception_handlers.clone_obj = NULL;
  
  }
  /* }}} */
  
 -ZEND_API zend_class_entry *zend_exception_get_default(TSRMLS_D) /* {{{ */
 +/* {{{ Deprecated - Use zend_ce_exception directly instead */
- ZEND_API zend_class_entry *zend_exception_get_default(void) 
++ZEND_API zend_class_entry *zend_exception_get_default(void)
  {
 -      return default_exception_ce;
 +      return zend_ce_exception;
  }
  /* }}} */
  
index b3ef5ad00369811400c71dceb8d87caf75963296,ef5162283bb1cde4d7ef251bc3173d0030713926..8f2adab7f76d6cc104887f72bac2039549c18ad3
@@@ -5425,12 -5387,11 +5425,11 @@@ PHP_FUNCTION(openssl_dh_compute_key
     Returns a string of the length specified filled with random pseudo bytes */
  PHP_FUNCTION(openssl_random_pseudo_bytes)
  {
 -      long buffer_length;
 -      unsigned char *buffer = NULL;
 +      zend_long buffer_length;
 +      zend_string *buffer = NULL;
        zval *zstrong_result_returned = NULL;
-       int strong_result = 0;
  
 -      if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|z", &buffer_length, &zstrong_result_returned) == FAILURE) {
 +      if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|z/", &buffer_length, &zstrong_result_returned) == FAILURE) {
                return;
        }
  
  
        if (zstrong_result_returned) {
                zval_dtor(zstrong_result_returned);
 -              ZVAL_BOOL(zstrong_result_returned, 0);
 +              ZVAL_FALSE(zstrong_result_returned);
        }
  
 -      buffer = emalloc(buffer_length + 1);
 +      buffer = zend_string_alloc(buffer_length, 0);
  
  #ifdef PHP_WIN32
-       strong_result = 1;
        /* random/urandom equivalent on Windows */
 -      if (php_win32_get_random_bytes(buffer, (size_t) buffer_length) == FAILURE){
 -              efree(buffer);
 +      if (php_win32_get_random_bytes((unsigned char*)buffer->val, (size_t) buffer_length) == FAILURE){
 +              zend_string_release(buffer);
                if (zstrong_result_returned) {
 -                      ZVAL_BOOL(zstrong_result_returned, 0);
 +                      ZVAL_FALSE(zstrong_result_returned);
                }
                RETURN_FALSE;
        }
  #else
-       if ((strong_result = RAND_pseudo_bytes((unsigned char*)ZSTR_VAL(buffer), buffer_length)) < 0) {
 -      if (RAND_bytes(buffer, buffer_length) <= 0) {
 -              efree(buffer);
++      if (RAND_bytes((unsigned char*)ZSTR_VAL(buffer), buffer_length) <= 0) {
 +              zend_string_release(buffer);
                if (zstrong_result_returned) {
 -                      ZVAL_BOOL(zstrong_result_returned, 0);
 +                      ZVAL_FALSE(zstrong_result_returned);
                }
                RETURN_FALSE;
        }
  #endif
  
 -      buffer[buffer_length] = 0;
 -      RETVAL_STRINGL((char *)buffer, buffer_length, 0);
 +      ZSTR_VAL(buffer)[buffer_length] = 0;
 +      RETVAL_STR(buffer);
  
        if (zstrong_result_returned) {
-               ZVAL_BOOL(zstrong_result_returned, strong_result);
+               ZVAL_BOOL(zstrong_result_returned, 1);
        }
  }
  /* }}} */
index 48dfb9f7fa63495f12f60cd972e73f64a9a4f1fd,aa369abe3a891535f612d78f16e522705f26bdfc..184f96662329a74819817ebe5878bd9060e17565
@@@ -524,14 -536,17 +524,17 @@@ static inline void phar_set_inode(phar_
  {
        char tmp[MAXPATHLEN];
        int tmp_len;
-       size_t len;
+       size_t len1, len2;
  
        tmp_len = MIN(MAXPATHLEN, entry->filename_len + entry->phar->fname_len);
-       len = MIN(entry->phar->fname_len, tmp_len);
-       memcpy(tmp, entry->phar->fname, len);
-       len = MIN(tmp_len - len, entry->filename_len);
-       memcpy(tmp + entry->phar->fname_len, entry->filename, len);
-       entry->inode = (unsigned short)zend_hash_func(tmp, tmp_len);
+       len1 = MIN(entry->phar->fname_len, tmp_len);
+       memcpy(tmp, entry->phar->fname, len1);
+       len2 = MIN(tmp_len - len1, entry->filename_len);
+       memcpy(tmp + len1, entry->filename, len2);
 -      entry->inode = (unsigned short)zend_get_hash_value(tmp, tmp_len);
++      entry->inode = (unsigned short) zend_hash_func(tmp, tmp_len);
  }
  /* }}} */
  
Simple merge
index 60dd9dd3ae0f956043d7b0df4659b67da3979d92,c8eba98bc80c38bf57a4fba3b371b2c5c349b22b..61573eb77e1cc0948707e17b0e1f4346b0f77810
@@@ -810,28 -817,31 +810,29 @@@ try_again
                        int i, n;
  
                        has_cookies = 1;
 -                      n = zend_hash_num_elements(Z_ARRVAL_PP(cookies));
 +                      n = zend_hash_num_elements(Z_ARRVAL_P(cookies));
                        if (n > 0) {
 -                              zend_hash_internal_pointer_reset(Z_ARRVAL_PP(cookies));
 +                              zend_hash_internal_pointer_reset(Z_ARRVAL_P(cookies));
                                smart_str_append_const(&soap_headers, "Cookie: ");
                                for (i = 0; i < n; i++) {
 -                                      int res = zend_hash_get_current_key_ex(Z_ARRVAL_PP(cookies), &key, &key_len, &numindx, 0, NULL);
 -                                      zend_hash_get_current_data(Z_ARRVAL_PP(cookies), (void **)&data);
 -
 -                                      if (res == HASH_KEY_IS_STRING && Z_TYPE_PP(data) == IS_ARRAY) {
 -                                        zval** value;
 -
 -                                              if (zend_hash_index_find(Z_ARRVAL_PP(data), 0, (void**)&value) == SUCCESS &&
 -                                                  Z_TYPE_PP(value) == IS_STRING) {
 -                                                zval **tmp;
 -                                                if ((zend_hash_index_find(Z_ARRVAL_PP(data), 1, (void**)&tmp) == FAILURE ||
 -                                                 Z_TYPE_PP(tmp) != IS_STRING ||
 -                                                     strncmp(phpurl->path?phpurl->path:"/",Z_STRVAL_PP(tmp),Z_STRLEN_PP(tmp)) == 0) &&
 -                                                    (zend_hash_index_find(Z_ARRVAL_PP(data), 2, (void**)&tmp) == FAILURE ||
 -                                                     Z_TYPE_PP(tmp) != IS_STRING ||
 -                                                     in_domain(phpurl->host,Z_STRVAL_PP(tmp))) &&
 -                                                    (use_ssl || zend_hash_index_find(Z_ARRVAL_PP(data), 3, (void**)&tmp) == FAILURE)) {
 -                                                              smart_str_appendl(&soap_headers, key, key_len-1);
+                                       ulong numindx;
-                                       zend_hash_get_current_key(Z_ARRVAL_P(cookies), &key, NULL);
-                                       if (Z_TYPE_P(data) == IS_ARRAY) {
++                                      int res = zend_hash_get_current_key(Z_ARRVAL_P(cookies), &key, &numindx);
 +                                      data = zend_hash_get_current_data(Z_ARRVAL_P(cookies));
++                                      
++                                      if (res == HASH_KEY_IS_STRING && Z_TYPE_P(data) == IS_ARRAY) {
 +                                        zval *value;
 +
 +                                              if ((value = zend_hash_index_find(Z_ARRVAL_P(data), 0)) != NULL &&
 +                                                  Z_TYPE_P(value) == IS_STRING) {
 +                                                zval *tmp;
 +                                                if (((tmp = zend_hash_index_find(Z_ARRVAL_P(data), 1)) == NULL ||
 +                                                     strncmp(phpurl->path?phpurl->path:"/",Z_STRVAL_P(tmp),Z_STRLEN_P(tmp)) == 0) &&
 +                                                    ((tmp = zend_hash_index_find(Z_ARRVAL_P(data), 2)) == NULL ||
 +                                                     in_domain(phpurl->host,Z_STRVAL_P(tmp))) &&
 +                                                    (use_ssl || (tmp = zend_hash_index_find(Z_ARRVAL_P(data), 3)) == NULL)) {
 +                                                              smart_str_append(&soap_headers, key);
                                                                smart_str_appendc(&soap_headers, '=');
 -                                                              smart_str_appendl(&soap_headers, Z_STRVAL_PP(value), Z_STRLEN_PP(value));
 +                                                              smart_str_append(&soap_headers, Z_STR_P(value));
                                                                smart_str_appendc(&soap_headers, ';');
                                                        }
                                                }
index 2835876e33a37ec6ac662025886253affd246864,42490fc0079b6569ac1b3230f0bfba45c55b451e..1ec6ea17b2db0b33feed099e1e34b84288a9f54c
@@@ -1741,8 -1773,9 +1741,9 @@@ SPL_METHOD(Array, unserialize
                goto outexcept;
        }
  
+       var_push_dtor(&var_hash, &pflags);
        --p; /* for ';' */
 -      flags = Z_LVAL_P(pflags);
 +      flags = Z_LVAL(zflags);
        /* flags needs to be verified and we also need to verify whether the next
         * thing we get is ';'. After that we require an 'm' or somethign else
         * where 'm' stands for members and anything else should be an array. If
                intern->ar_flags &= ~SPL_ARRAY_CLONE_MASK;
                intern->ar_flags |= flags & SPL_ARRAY_CLONE_MASK;
                zval_ptr_dtor(&intern->array);
 -              ALLOC_INIT_ZVAL(intern->array);
 -              if (!php_var_unserialize(&intern->array, &p, s + buf_len, &var_hash TSRMLS_CC)) {
 +              if (!php_var_unserialize(&intern->array, &p, s + buf_len, &var_hash)) {
                        goto outexcept;
                }
+               var_push_dtor(&var_hash, &intern->array);
        }
        if (*p != ';') {
                goto outexcept;
                goto outexcept;
        }
  
+       var_push_dtor(&var_hash, &pmembers);
        /* copy members */
 -      if (!intern->std.properties) {
 -              rebuild_object_properties(&intern->std);
 -      }
 -      zend_hash_copy(intern->std.properties, Z_ARRVAL_P(pmembers), (copy_ctor_func_t) zval_add_ref, (void *) NULL, sizeof(zval *));
 -      zval_ptr_dtor(&pmembers);
 +      object_properties_load(&intern->std, Z_ARRVAL(members));
 +      zval_ptr_dtor(&members);
  
        /* done reading $serialized */
  
index 6a9e27a6016ccb148fd534f547c83e4b3d293be3,43f4d7d29d75167b7dbe2ee1b2c786617038ab8e..315c0f8bcddc903331fea2d1a6e680782a3a84ad
@@@ -809,12 -838,14 +809,13 @@@ SPL_METHOD(SplObjectStorage, unserializ
                goto outexcept;
        }
  
+       var_push_dtor(&var_hash, &pcount);
        --p; /* for ';' */
 -      count = Z_LVAL_P(pcount);
 +      count = Z_LVAL(pcount);
  
 -      while(count-- > 0) {
 +      while (count-- > 0) {
                spl_SplObjectStorageElement *pelement;
 -              char *hash;
 -              int hash_len;
 +              zend_string *hash;
  
                if (*p != ';') {
                        goto outexcept;
index b766c0afbdee95c83ed9c1640cf64b53f59d3ff1,bc2b302ddb75da9cfacea209287a732d8cdaf2bb..be3aa273ed1e54be7055ef4a43a0d3502e871cf9
@@@ -9,7 -9,8 +9,8 @@@ $x->test()
  
  ?>
  --EXPECTF--
 -exception 'Exception' in %s:%d
+ Notice: Undefined property: Exception::$previous in %s on line %d
 +Exception in %s:%d
  Stack trace:
  #0 {main}
  
index 60af3fc992722649aa3fecc3eb1f0c964f9c1dab,a840e8ffd2efc22e1027346245e70553d63d54e1..cf50a968f4833386cd4683ac3c8a54fe330ddc6c
@@@ -74,28 -74,31 +74,31 @@@ string(1544) "Class [ <internal:Core> c
        }
      }
  
 -    Method [ <internal:Core> final public method __wakeup ] {
++    Method [ <internal:Core, prototype Throwable> final public method __wakeup ] {
+     }
 -    Method [ <internal:Core> final public method getMessage ] {
 +    Method [ <internal:Core, prototype Throwable> final public method getMessage ] {
      }
  
 -    Method [ <internal:Core> final public method getCode ] {
 +    Method [ <internal:Core, prototype Throwable> final public method getCode ] {
      }
  
 -    Method [ <internal:Core> final public method getFile ] {
 +    Method [ <internal:Core, prototype Throwable> final public method getFile ] {
      }
  
 -    Method [ <internal:Core> final public method getLine ] {
 +    Method [ <internal:Core, prototype Throwable> final public method getLine ] {
      }
  
 -    Method [ <internal:Core> final public method getTrace ] {
 +    Method [ <internal:Core, prototype Throwable> final public method getTrace ] {
      }
  
 -    Method [ <internal:Core> final public method getPrevious ] {
 +    Method [ <internal:Core, prototype Throwable> final public method getPrevious ] {
      }
  
 -    Method [ <internal:Core> final public method getTraceAsString ] {
 +    Method [ <internal:Core, prototype Throwable> final public method getTraceAsString ] {
      }
  
 -    Method [ <internal:Core> public method __toString ] {
 +    Method [ <internal:Core, prototype Throwable> public method __toString ] {
      }
    }
  }