summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
authorNikita Popov <nikic@php.net>2014-08-16 21:55:08 +0200
committerNikita Popov <nikic@php.net>2014-08-16 21:55:08 +0200
commit71675a4bf830d7b9400663275fe48275480d34f4 (patch)
tree8ce9b1fdda30d26121334fb5c228df7884f6f7c2 /Zend
parentf72d6f97ecf976f00abc0dc21b5d1ef4838de60a (diff)
parent8b66d64b2343bc4fd8aeabb690024edb850a0155 (diff)
downloadphp-git-71675a4bf830d7b9400663275fe48275480d34f4.tar.gz
Merge remote-tracking branch 'php-src/phpng' into ast
Conflicts: Zend/zend_ast.c Zend/zend_compile.c Zend/zend_language_parser.y Incomplete merge!
Diffstat (limited to 'Zend')
-rw-r--r--Zend/tests/constant_expressions_arrays.phpt35
-rw-r--r--Zend/tests/constant_expressions_self_referencing_array.phpt2
-rw-r--r--Zend/tests/errmsg_040.phpt12
-rw-r--r--Zend/tests/gc_029.phpt4
-rw-r--r--Zend/tests/ns_059.phpt5
-rw-r--r--Zend/zend.c63
-rw-r--r--Zend/zend.h2
-rw-r--r--Zend/zend_API.c4
-rw-r--r--Zend/zend_API.h261
-rw-r--r--Zend/zend_ast.c29
-rw-r--r--Zend/zend_compile.c39
-rw-r--r--Zend/zend_compile.h11
-rw-r--r--Zend/zend_constants.c6
-rw-r--r--Zend/zend_execute.c88
-rw-r--r--Zend/zend_execute.h5
-rw-r--r--Zend/zend_execute_API.c1
-rw-r--r--Zend/zend_gc.c129
-rw-r--r--Zend/zend_gc.h5
-rw-r--r--Zend/zend_hash.c5
-rw-r--r--Zend/zend_hash.h11
-rw-r--r--Zend/zend_ini.c4
-rw-r--r--Zend/zend_multibyte.c4
-rw-r--r--Zend/zend_object_handlers.c23
-rw-r--r--Zend/zend_operators.c24
-rw-r--r--Zend/zend_ts_hash.c33
-rw-r--r--Zend/zend_ts_hash.h35
-rw-r--r--Zend/zend_vm_def.h22
-rw-r--r--Zend/zend_vm_execute.h174
28 files changed, 690 insertions, 346 deletions
diff --git a/Zend/tests/constant_expressions_arrays.phpt b/Zend/tests/constant_expressions_arrays.phpt
index 061fcc6a92..2ab03453de 100644
--- a/Zend/tests/constant_expressions_arrays.phpt
+++ b/Zend/tests/constant_expressions_arrays.phpt
@@ -22,7 +22,7 @@ class foo {
var_dump(foo::bar);
-var_dump(a); // Eventually allow that later with array dereferencing of constants
+var_dump(a, a[0], a[2], a[2][1], a[3]);
?>
--EXPECTF--
@@ -32,4 +32,35 @@ int(1)
int(4)
int(1)
-Fatal error: Arrays are not allowed in constants at run-time in %s on line %d
+Notice: Undefined offset: 3 in %s on line %d
+array(3) {
+ [0]=>
+ int(1)
+ [1]=>
+ int(2)
+ [2]=>
+ array(2) {
+ [0]=>
+ int(3)
+ [1]=>
+ array(1) {
+ [0]=>
+ int(4)
+ }
+ }
+}
+int(1)
+array(2) {
+ [0]=>
+ int(3)
+ [1]=>
+ array(1) {
+ [0]=>
+ int(4)
+ }
+}
+array(1) {
+ [0]=>
+ int(4)
+}
+NULL
diff --git a/Zend/tests/constant_expressions_self_referencing_array.phpt b/Zend/tests/constant_expressions_self_referencing_array.phpt
index 09f862e048..ae76a08602 100644
--- a/Zend/tests/constant_expressions_self_referencing_array.phpt
+++ b/Zend/tests/constant_expressions_self_referencing_array.phpt
@@ -1,7 +1,5 @@
--TEST--
Self-referencing constant expression (part of a constant AST)
---XFAIL--
-Not yet fixed, to be fixed for PHP 5.6
--FILE--
<?php
class A {
diff --git a/Zend/tests/errmsg_040.phpt b/Zend/tests/errmsg_040.phpt
index f3d0afcf0a..d5d2bf38d3 100644
--- a/Zend/tests/errmsg_040.phpt
+++ b/Zend/tests/errmsg_040.phpt
@@ -6,8 +6,16 @@ errmsg: arrays are not allowed in class constants
class test {
const TEST = array(1,2,3);
}
-
+var_dump(test::TEST);
echo "Done\n";
?>
--EXPECTF--
-Fatal error: Arrays are not allowed in class constants in %s on line %d
+array(3) {
+ [0]=>
+ int(1)
+ [1]=>
+ int(2)
+ [2]=>
+ int(3)
+}
+Done
diff --git a/Zend/tests/gc_029.phpt b/Zend/tests/gc_029.phpt
index 18fef3c7d7..3873d8becd 100644
--- a/Zend/tests/gc_029.phpt
+++ b/Zend/tests/gc_029.phpt
@@ -33,5 +33,5 @@ unset($foo);
unset($bar);
var_dump(gc_collect_cycles());
?>
---EXPECT--
-int(3)
+--EXPECTREGEX--
+int\([23]\)
diff --git a/Zend/tests/ns_059.phpt b/Zend/tests/ns_059.phpt
index ea66037b43..301a6fc830 100644
--- a/Zend/tests/ns_059.phpt
+++ b/Zend/tests/ns_059.phpt
@@ -3,6 +3,7 @@
--FILE--
<?php
const C = array();
+var_dump(C);
--EXPECTF--
-Fatal error: Arrays are not allowed as constants in %sns_059.php on line 2
-
+array(0) {
+}
diff --git a/Zend/zend.c b/Zend/zend.c
index 5ab8ee3eb4..8bcdbd82c2 100644
--- a/Zend/zend.c
+++ b/Zend/zend.c
@@ -212,7 +212,7 @@ static void print_flat_hash(HashTable *ht TSRMLS_DC) /* {{{ */
}
/* }}} */
-ZEND_API int zend_make_printable_zval(zval *expr, zval *expr_copy) /* {{{ */
+ZEND_API int zend_make_printable_zval(zval *expr, zval *expr_copy TSRMLS_DC) /* {{{ */
{
if (Z_TYPE_P(expr) == IS_STRING) {
return 0;
@@ -221,15 +221,16 @@ ZEND_API int zend_make_printable_zval(zval *expr, zval *expr_copy) /* {{{ */
again:
switch (Z_TYPE_P(expr)) {
case IS_NULL:
- case IS_FALSE: {
- TSRMLS_FETCH();
+ case IS_FALSE:
ZVAL_EMPTY_STRING(expr_copy);
- break;
- }
+ break;
case IS_TRUE:
- // TODO: use interned string ???
- ZVAL_NEW_STR(expr_copy, STR_INIT("1", 1, 0));
- break;
+ if (CG(one_char_string)['1']) {
+ ZVAL_INT_STR(expr_copy, CG(one_char_string)['1']);
+ } else {
+ ZVAL_NEW_STR(expr_copy, STR_INIT("1", 1, 0));
+ }
+ break;
case IS_RESOURCE: {
char buf[sizeof("Resource id #") + MAX_LENGTH_OF_LONG];
int len;
@@ -244,35 +245,31 @@ again:
ZVAL_NEW_STR(expr_copy, STR_INIT("Array", sizeof("Array") - 1, 0));
break;
case IS_OBJECT:
- {
- TSRMLS_FETCH();
-
- if (Z_OBJ_HANDLER_P(expr, cast_object)) {
- Z_ADDREF_P(expr);
- if (Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_STRING TSRMLS_CC) == SUCCESS) {
- zval_ptr_dtor(expr);
- break;
- }
+ if (Z_OBJ_HANDLER_P(expr, cast_object)) {
+ Z_ADDREF_P(expr);
+ if (Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_STRING TSRMLS_CC) == SUCCESS) {
zval_ptr_dtor(expr);
+ break;
}
- if (!Z_OBJ_HANDLER_P(expr, cast_object) && Z_OBJ_HANDLER_P(expr, get)) {
- zval rv;
- zval *z = Z_OBJ_HANDLER_P(expr, get)(expr, &rv TSRMLS_CC);
-
- Z_ADDREF_P(z);
- if (Z_TYPE_P(z) != IS_OBJECT) {
- if (zend_make_printable_zval(z, expr_copy)) {
- zval_ptr_dtor(z);
- } else {
- ZVAL_ZVAL(expr_copy, z, 0, 1);
- }
- return 1;
+ zval_ptr_dtor(expr);
+ }
+ if (!Z_OBJ_HANDLER_P(expr, cast_object) && Z_OBJ_HANDLER_P(expr, get)) {
+ zval rv;
+ zval *z = Z_OBJ_HANDLER_P(expr, get)(expr, &rv TSRMLS_CC);
+
+ Z_ADDREF_P(z);
+ if (Z_TYPE_P(z) != IS_OBJECT) {
+ if (zend_make_printable_zval(z, expr_copy TSRMLS_CC)) {
+ zval_ptr_dtor(z);
+ } else {
+ ZVAL_ZVAL(expr_copy, z, 0, 1);
}
- zval_ptr_dtor(z);
+ return 1;
}
- zend_error(EG(exception) ? E_ERROR : E_RECOVERABLE_ERROR, "Object of class %s could not be converted to string", Z_OBJCE_P(expr)->name->val);
- ZVAL_EMPTY_STRING(expr_copy);
+ zval_ptr_dtor(z);
}
+ zend_error(EG(exception) ? E_ERROR : E_RECOVERABLE_ERROR, "Object of class %s could not be converted to string", Z_OBJCE_P(expr)->name->val);
+ ZVAL_EMPTY_STRING(expr_copy);
break;
case IS_DOUBLE:
ZVAL_DUP(expr_copy, expr);
@@ -540,7 +537,7 @@ static void compiler_globals_dtor(zend_compiler_globals *compiler_globals TSRMLS
free(compiler_globals->static_members_table);
}
if (compiler_globals->script_encoding_list) {
- pefree(compiler_globals->script_encoding_list, 1);
+ pefree((char*)compiler_globals->script_encoding_list, 1);
}
compiler_globals->last_static_member = 0;
}
diff --git a/Zend/zend.h b/Zend/zend.h
index 5548c7be1b..0520d4dda1 100644
--- a/Zend/zend.h
+++ b/Zend/zend.h
@@ -609,7 +609,7 @@ END_EXTERN_C()
BEGIN_EXTERN_C()
ZEND_API char *get_zend_version(void);
-ZEND_API int zend_make_printable_zval(zval *expr, zval *expr_copy);
+ZEND_API int zend_make_printable_zval(zval *expr, zval *expr_copy TSRMLS_DC);
ZEND_API int zend_print_zval(zval *expr, int indent TSRMLS_DC);
ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int indent TSRMLS_DC);
ZEND_API void zend_print_zval_r(zval *expr, int indent TSRMLS_DC);
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 5baa26ea54..9881740c06 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -249,7 +249,7 @@ static int parse_arg_object_to_string(zval *arg, char **p, int *pl, int type TSR
if(Z_TYPE_P(z) != IS_OBJECT) {
zval_dtor(arg);
ZVAL_NULL(arg);
- if (!zend_make_printable_zval(z, arg)) {
+ if (!zend_make_printable_zval(z, arg TSRMLS_CC)) {
ZVAL_ZVAL(arg, z, 1, 1);
}
*pl = Z_STRLEN_P(arg);
@@ -288,7 +288,7 @@ ZEND_API int parse_arg_object_to_str(zval *arg, zend_string **str, int type TSRM
if(Z_TYPE_P(z) != IS_OBJECT) {
zval_dtor(arg);
ZVAL_NULL(arg);
- if (!zend_make_printable_zval(z, arg)) {
+ if (!zend_make_printable_zval(z, arg TSRMLS_CC)) {
ZVAL_ZVAL(arg, z, 1, 1);
}
*str = Z_STR_P(arg);
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index 3a242c249e..b40afc162f 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -248,7 +248,7 @@ ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array TS
/* Parameter parsing API -- andrei */
-#define ZEND_PARSE_PARAMS_QUIET 1<<1
+#define ZEND_PARSE_PARAMS_QUIET (1<<1)
ZEND_API int zend_parse_parameters(int num_args TSRMLS_DC, const char *type_spec, ...);
ZEND_API int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, const char *type_spec, ...);
ZEND_API char *zend_zval_type_name(const zval *arg);
@@ -646,6 +646,7 @@ END_EXTERN_C()
} \
} while (0)
#else // attempt to support calls to parent::__construct() ???
+ // see: ext/date/tests/bug67118.phpt
#define ZEND_CTOR_MAKE_NULL() do { \
if (EG(current_execute_data)->return_value) { \
zval_ptr_dtor(EG(current_execute_data)->return_value); \
@@ -716,53 +717,61 @@ ZEND_API void zend_wrong_paramer_class_error(int num, char *name, zval *arg TSRM
ZEND_API void zend_wrong_callback_error(int severity, int num, char *error TSRMLS_DC);
ZEND_API int _z_param_class(zval *arg, zend_class_entry **pce, int num, int check_null TSRMLS_DC);
+#define ZPP_ERROR_OK 0
+#define ZPP_ERROR_FAILURE 1
+#define ZPP_ERROR_WRONG_CALLBACK 2
+#define ZPP_ERROR_WRONG_CLASS 3
+#define ZPP_ERROR_WRONG_ARG 4
+#define ZPP_ERROR_WRONG_COUNT 5
+
#define ZEND_PARSE_PARAMETERS_START_EX(flags, min_num_args, max_num_args) do { \
const int _flags = (flags); \
int _min_num_args = (min_num_args); \
int _max_num_args = (max_num_args); \
int _num_args = EG(current_execute_data)->num_args; \
int _i; \
- zval *_real_arg, *_arg; \
- zend_expected_type _expected_type; \
- char *_error; \
+ zval *_real_arg, *_arg = NULL; \
+ zend_expected_type _expected_type = IS_UNDEF; \
+ char *_error = NULL; \
zend_bool _dummy; \
+ zend_bool _optional = 0; \
+ int error_code = ZPP_ERROR_OK; \
((void)_i); \
((void)_real_arg); \
((void)_arg); \
((void)_expected_type); \
((void)_error); \
((void)_dummy); \
- if (UNEXPECTED(_num_args < _min_num_args) || \
- (UNEXPECTED(_num_args > _max_num_args) && \
- EXPECTED(_max_num_args >= 0))) { \
- if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \
- zend_wrong_paramers_count_error(_num_args, _min_num_args, _max_num_args TSRMLS_CC); \
+ ((void)_optional); \
+ \
+ do { \
+ if (UNEXPECTED(_num_args < _min_num_args) || \
+ (UNEXPECTED(_num_args > _max_num_args) && \
+ EXPECTED(_max_num_args >= 0))) { \
+ if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \
+ zend_wrong_paramers_count_error(_num_args, _min_num_args, _max_num_args TSRMLS_CC); \
+ } \
+ error_code = ZPP_ERROR_FAILURE; \
+ break; \
} \
- goto zend_parse_params_failure; \
- } \
- _i = 0; \
- _real_arg = ZEND_CALL_ARG(EG(current_execute_data), 0);
+ _i = 0; \
+ _real_arg = ZEND_CALL_ARG(EG(current_execute_data), 0);
#define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args) \
ZEND_PARSE_PARAMETERS_START_EX(0, min_num_args, max_num_args)
#define ZEND_PARSE_PARAMETERS_END_EX(failure) \
- if (0) { \
-zend_parse_params_wrong_callback: ZEND_ATTRIBUTE_UNUSED_LABEL \
- if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \
- zend_wrong_callback_error(E_WARNING, _i, _error TSRMLS_CC); \
- } \
- goto zend_parse_params_failure; \
-zend_parse_params_wrong_class: ZEND_ATTRIBUTE_UNUSED_LABEL \
- if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \
- zend_wrong_paramer_class_error(_i, _error, _arg TSRMLS_CC); \
- } \
- goto zend_parse_params_failure; \
-zend_parse_params_wrong_arg: ZEND_ATTRIBUTE_UNUSED_LABEL \
+ } while (0); \
+ if (UNEXPECTED(error_code != ZPP_ERROR_OK)) { \
if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \
- zend_wrong_paramer_type_error(_i, _expected_type, _arg TSRMLS_CC); \
+ if (error_code == ZPP_ERROR_WRONG_CALLBACK) { \
+ zend_wrong_callback_error(E_WARNING, _i, _error TSRMLS_CC); \
+ } else if (error_code == ZPP_ERROR_WRONG_CLASS) { \
+ zend_wrong_paramer_class_error(_i, _error, _arg TSRMLS_CC); \
+ } else if (error_code == ZPP_ERROR_WRONG_ARG) { \
+ zend_wrong_paramer_type_error(_i, _expected_type, _arg TSRMLS_CC); \
+ } \
} \
-zend_parse_params_failure: ZEND_ATTRIBUTE_UNUSED_LABEL \
failure; \
} \
} while (0)
@@ -771,7 +780,10 @@ zend_parse_params_failure: ZEND_ATTRIBUTE_UNUSED_LABEL \
ZEND_PARSE_PARAMETERS_END_EX(return)
#define Z_PARAM_PROLOGUE(separate) \
- if (UNEXPECTED(++_i >_num_args)) break; \
+ ++_i; \
+ if (_optional) { \
+ if (UNEXPECTED(_i >_num_args)) break; \
+ } \
_real_arg++; \
_arg = _real_arg; \
ZVAL_DEREF(_arg); \
@@ -780,224 +792,227 @@ zend_parse_params_failure: ZEND_ATTRIBUTE_UNUSED_LABEL \
}
/* old "|" */
-#define Z_PARAM_OPTIONAL
+#define Z_PARAM_OPTIONAL \
+ _optional = 1;
/* old "a" */
-#define Z_PARAM_ARRAY_EX(dest, check_null, separate) do { \
+#define Z_PARAM_ARRAY_EX(dest, check_null, separate) \
Z_PARAM_PROLOGUE(separate); \
- if (!_z_param_array(_arg, &dest, check_null, 0)) { \
+ if (UNEXPECTED(!_z_param_array(_arg, &dest, check_null, 0))) { \
_expected_type = Z_EXPECTED_ARRAY; \
- goto zend_parse_params_wrong_arg; \
- } \
- } while (0);
+ error_code = ZPP_ERROR_WRONG_ARG; \
+ break; \
+ }
#define Z_PARAM_ARRAY(dest) \
Z_PARAM_ARRAY_EX(dest, 0, 0)
/* old "A" */
-#define Z_PARAM_ARRAY_OR_OBJECT_EX(dest, check_null, separate) do { \
+#define Z_PARAM_ARRAY_OR_OBJECT_EX(dest, check_null, separate) \
Z_PARAM_PROLOGUE(separate); \
- if (!_z_param_array(_arg, &dest, check_null, 1)) { \
+ if (UNEXPECTED(!_z_param_array(_arg, &dest, check_null, 1))) { \
_expected_type = Z_EXPECTED_ARRAY; \
- goto zend_parse_params_wrong_arg; \
- } \
- } while (0);
+ error_code = ZPP_ERROR_WRONG_ARG; \
+ break; \
+ }
#define Z_PARAM_ARRAY_OR_OBJECT(dest, check_null, separate) \
Z_PARAM_ARRAY_OR_OBJECT_EX(dest, 0, 0)
/* old "b" */
-#define Z_PARAM_BOOL_EX(dest, is_null, check_null, separate) do { \
+#define Z_PARAM_BOOL_EX(dest, is_null, check_null, separate) \
Z_PARAM_PROLOGUE(separate); \
- if (!_z_param_bool(_arg, &dest, &is_null, check_null TSRMLS_CC)) { \
+ if (UNEXPECTED(!_z_param_bool(_arg, &dest, &is_null, check_null TSRMLS_CC))) { \
_expected_type = Z_EXPECTED_BOOL; \
- goto zend_parse_params_wrong_arg; \
- } \
- } while (0);
+ error_code = ZPP_ERROR_WRONG_ARG; \
+ break; \
+ }
#define Z_PARAM_BOOL(dest) \
Z_PARAM_BOOL_EX(dest, _dummy, 0, 0)
/* old "C" */
-#define Z_PARAM_CLASS_EX(dest, check_null, separate) do { \
+#define Z_PARAM_CLASS_EX(dest, check_null, separate) \
Z_PARAM_PROLOGUE(separate); \
- if (!_z_param_class(_arg, &dest, _i, check_null TSRMLS_CC)) { \
- goto zend_parse_params_failure; \
- } \
- } while (0);
+ if (UNEXPECTED(!_z_param_class(_arg, &dest, _i, check_null TSRMLS_CC))) { \
+ error_code = ZPP_ERROR_FAILURE; \
+ break; \
+ }
#define Z_PARAM_CLASS(dest) \
Z_PARAM_CLASS_EX(dest, 0, 0)
/* old "d" */
-#define Z_PARAM_DOUBLE_EX(dest, is_null, check_null, separate) do { \
+#define Z_PARAM_DOUBLE_EX(dest, is_null, check_null, separate) \
Z_PARAM_PROLOGUE(separate); \
- if (!_z_param_double(_arg, &dest, &is_null, check_null)) { \
+ if (UNEXPECTED(!_z_param_double(_arg, &dest, &is_null, check_null))) { \
_expected_type = Z_EXPECTED_DOUBLE; \
- goto zend_parse_params_wrong_arg; \
- } \
- } while (0);
+ error_code = ZPP_ERROR_WRONG_ARG; \
+ break; \
+ }
#define Z_PARAM_DOUBLE(dest) \
Z_PARAM_DOUBLE_EX(dest, _dummy, 0, 0)
/* old "f" */
-#define Z_PARAM_FUNC_EX(dest_fci, dest_fcc, check_null, separate) do { \
+#define Z_PARAM_FUNC_EX(dest_fci, dest_fcc, check_null, separate) \
Z_PARAM_PROLOGUE(separate); \
- if (!_z_param_func(_arg, &dest_fci, &dest_fcc, check_null, &_error TSRMLS_CC)) { \
+ if (UNEXPECTED(!_z_param_func(_arg, &dest_fci, &dest_fcc, check_null, &_error TSRMLS_CC))) { \
if (!_error) { \
_expected_type = Z_EXPECTED_FUNC; \
- goto zend_parse_params_wrong_arg; \
+ error_code = ZPP_ERROR_WRONG_ARG; \
+ break; \
} else { \
- goto zend_parse_params_wrong_callback; \
+ error_code = ZPP_ERROR_WRONG_CALLBACK; \
+ break; \
} \
- } else if (_error) { \
+ } else if (UNEXPECTED(_error != NULL)) { \
zend_wrong_callback_error(E_STRICT, _i, _error TSRMLS_CC); \
- } \
- } while (0);
+ }
#define Z_PARAM_FUNC(dest_fci, dest_fcc) \
Z_PARAM_FUNC_EX(dest_fci, dest_fcc, 0, 0)
/* old "h" */
-#define Z_PARAM_ARRAY_HT_EX(dest, check_null, separate) do { \
+#define Z_PARAM_ARRAY_HT_EX(dest, check_null, separate) \
Z_PARAM_PROLOGUE(separate); \
- if (!_z_param_array_ht(_arg, &dest, check_null, 0 TSRMLS_CC)) { \
+ if (UNEXPECTED(!_z_param_array_ht(_arg, &dest, check_null, 0 TSRMLS_CC))) { \
_expected_type = Z_EXPECTED_ARRAY; \
- goto zend_parse_params_wrong_arg; \
- } \
- } while (0);
+ error_code = ZPP_ERROR_WRONG_ARG; \
+ break; \
+ }
#define Z_PARAM_ARRAY_HT(dest) \
Z_PARAM_ARRAY_HT_EX(dest, 0, 0)
/* old "H" */
-#define Z_PARAM_ARRAY_OR_OBJECT_HT_EX(dest, check_null, separate) do { \
+#define Z_PARAM_ARRAY_OR_OBJECT_HT_EX(dest, check_null, separate) \
Z_PARAM_PROLOGUE(separate); \
- if (!_z_param_array_ht(_arg, &dest, check_null, 1 TSRMLS_CC)) { \
+ if (UNEXPECTED(!_z_param_array_ht(_arg, &dest, check_null, 1 TSRMLS_CC))) { \
_expected_type = Z_EXPECTED_ARRAY; \
- goto zend_parse_params_wrong_arg; \
- } \
- } while (0);
+ error_code = ZPP_ERROR_WRONG_ARG; \
+ break; \
+ }
#define Z_PARAM_ARRAY_OR_OBJECT_HT(dest) \
Z_PARAM_ARRAY_OR_OBJECT_HT_EX(dest, 0, 0)
/* old "l" */
-#define Z_PARAM_LONG_EX(dest, is_null, check_null, separate) do { \
+#define Z_PARAM_LONG_EX(dest, is_null, check_null, separate) \
Z_PARAM_PROLOGUE(separate); \
- if (!_z_param_long(_arg, &dest, &is_null, check_null, 0)) { \
+ if (UNEXPECTED(!_z_param_long(_arg, &dest, &is_null, check_null, 0))) { \
_expected_type = Z_EXPECTED_LONG; \
- goto zend_parse_params_wrong_arg; \
- } \
- } while (0);
+ error_code = ZPP_ERROR_WRONG_ARG; \
+ break; \
+ }
#define Z_PARAM_LONG(dest) \
Z_PARAM_LONG_EX(dest, _dummy, 0, 0)
/* old "L" */
-#define Z_PARAM_STRICT_LONG_EX(dest, is_null, check_null, separate) do { \
+#define Z_PARAM_STRICT_LONG_EX(dest, is_null, check_null, separate) \
Z_PARAM_PROLOGUE(separate); \
- if (!_z_param_long(_arg, &dest, &is_null, check_null, 1)) { \
+ if (UNEXPECTED(!_z_param_long(_arg, &dest, &is_null, check_null, 1))) { \
_expected_type = Z_EXPECTED_LONG; \
- goto zend_parse_params_wrong_arg; \
- } \
- } while (0);
+ error_code = ZPP_ERROR_WRONG_ARG; \
+ break; \
+ }
#define Z_PARAM_STRICT_LONG(dest) \
Z_PARAM_STRICT_LONG_EX(dest, _dummy, 0, 0)
/* old "o" */
-#define Z_PARAM_OBJECT_EX(dest, check_null, separate) do { \
+#define Z_PARAM_OBJECT_EX(dest, check_null, separate) \
Z_PARAM_PROLOGUE(separate); \
- if (!_z_param_object(_arg, &dest, NULL, check_null TSRMLS_CC)) { \
+ if (UNEXPECTED(!_z_param_object(_arg, &dest, NULL, check_null TSRMLS_CC))) { \
_expected_type = Z_EXPECTED_OBJECT; \
- goto zend_parse_params_wrong_arg; \
- } \
- } while (0);
+ error_code = ZPP_ERROR_WRONG_ARG; \
+ break; \
+ }
#define Z_PARAM_OBJECT(dest) \
Z_PARAM_OBJECT_EX(dest, 0, 0)
/* old "O" */
-#define Z_PARAM_OBJECT_OF_CLASS_EX(dest, _ce, check_null, separate) do { \
+#define Z_PARAM_OBJECT_OF_CLASS_EX(dest, _ce, check_null, separate) \
Z_PARAM_PROLOGUE(separate); \
- if (!_z_param_object(_arg, &dest, _ce, check_null TSRMLS_CC)) { \
+ if (UNEXPECTED(!_z_param_object(_arg, &dest, _ce, check_null TSRMLS_CC))) { \
if (_ce) { \
_error = (_ce)->name->val; \
- goto zend_parse_params_wrong_class; \
+ error_code = ZPP_ERROR_WRONG_CLASS; \
+ break; \
} else { \
_expected_type = Z_EXPECTED_OBJECT; \
- goto zend_parse_params_wrong_arg; \
+ error_code = ZPP_ERROR_WRONG_ARG; \
+ break; \
} \
- } \
- } while (0);
+ }
#define Z_PARAM_OBJECT_OF_CLASS(dest, _ce) \
Z_PARAM_OBJECT_OF_CLASS_EX(dest, _ce, 0, 0)
/* old "p" */
-#define Z_PARAM_PATH_EX(dest, dest_len, check_null, separate) do { \
+#define Z_PARAM_PATH_EX(dest, dest_len, check_null, separate) \
Z_PARAM_PROLOGUE(separate); \
- if (!_z_param_path(_arg, &dest, &dest_len, check_null TSRMLS_CC)) { \
+ if (UNEXPECTED(!_z_param_path(_arg, &dest, &dest_len, check_null TSRMLS_CC))) { \
_expected_type = Z_EXPECTED_PATH; \
- goto zend_parse_params_wrong_arg; \
- } \
- } while (0);
+ error_code = ZPP_ERROR_WRONG_ARG; \
+ break; \
+ }
#define Z_PARAM_PATH(dest, dest_len) \
Z_PARAM_PATH_EX(dest, dest_len, 0, 0)
/* old "P" */
-#define Z_PARAM_PATH_STR_EX(dest, check_null, separate) do { \
+#define Z_PARAM_PATH_STR_EX(dest, check_null, separate) \
Z_PARAM_PROLOGUE(separate); \
- if (!_z_param_path_str(_arg, &dest, check_null TSRMLS_CC)) { \
+ if (UNEXPECTED(!_z_param_path_str(_arg, &dest, check_null TSRMLS_CC))) { \
_expected_type = Z_EXPECTED_PATH; \
- goto zend_parse_params_wrong_arg; \
- } \
- } while (0);
+ error_code = ZPP_ERROR_WRONG_ARG; \
+ break; \
+ }
#define Z_PARAM_PATH_STR(dest) \
Z_PARAM_PATH_STR_EX(dest, 0, 0)
/* old "r" */
-#define Z_PARAM_RESOURCE_EX(dest, check_null, separate) do { \
+#define Z_PARAM_RESOURCE_EX(dest, check_null, separate) \
Z_PARAM_PROLOGUE(separate); \
- if (!_z_param_resource(_arg, &dest, check_null)) { \
+ if (UNEXPECTED(!_z_param_resource(_arg, &dest, check_null))) { \
_expected_type = Z_EXPECTED_RESOURCE; \
- goto zend_parse_params_wrong_arg; \
- } \
- } while (0);
+ error_code = ZPP_ERROR_WRONG_ARG; \
+ break; \
+ }
#define Z_PARAM_RESOURCE(dest) \
Z_PARAM_RESOURCE_EX(dest, 0, 0)
/* old "s" */
-#define Z_PARAM_STRING_EX(dest, dest_len, check_null, separate) do { \
+#define Z_PARAM_STRING_EX(dest, dest_len, check_null, separate) \
Z_PARAM_PROLOGUE(separate); \
- if (!_z_param_string(_arg, &dest, &dest_len, check_null TSRMLS_CC)) { \
+ if (UNEXPECTED(!_z_param_string(_arg, &dest, &dest_len, check_null TSRMLS_CC))) { \
_expected_type = Z_EXPECTED_STRING; \
- goto zend_parse_params_wrong_arg; \
- } \
- } while (0);
+ error_code = ZPP_ERROR_WRONG_ARG; \
+ break; \
+ }
#define Z_PARAM_STRING(dest, dest_len) \
Z_PARAM_STRING_EX(dest, dest_len, 0, 0)
/* old "S" */
-#define Z_PARAM_STR_EX(dest, check_null, separate) do { \
+#define Z_PARAM_STR_EX(dest, check_null, separate) \
Z_PARAM_PROLOGUE(separate); \
- if (!_z_param_str(_arg, &dest, check_null TSRMLS_CC)) { \
+ if (UNEXPECTED(!_z_param_str(_arg, &dest, check_null TSRMLS_CC))) { \
_expected_type = Z_EXPECTED_STRING; \
- goto zend_parse_params_wrong_arg; \
- } \
- } while (0);
+ error_code = ZPP_ERROR_WRONG_ARG; \
+ break; \
+ }
#define Z_PARAM_STR(dest) \
Z_PARAM_STR_EX(dest, 0, 0)
/* old "z" */
-#define Z_PARAM_ZVAL_EX(dest, check_null, separate) do { \
+#define Z_PARAM_ZVAL_EX(dest, check_null, separate) \
if (separate) { \
Z_PARAM_PROLOGUE(separate); \
_z_param_zval_deref(_arg, &dest, check_null); \
@@ -1005,17 +1020,15 @@ zend_parse_params_failure: ZEND_ATTRIBUTE_UNUSED_LABEL \
if (UNEXPECTED(++_i >_num_args)) break; \
_real_arg++; \
_z_param_zval(_real_arg, &dest, check_null); \
- } \
- } while (0);
+ }
#define Z_PARAM_ZVAL(dest) \
Z_PARAM_ZVAL_EX(dest, 0, 0)
/* old "z" (with dereference) */
-#define Z_PARAM_ZVAL_DEREF_EX(dest, check_null, separate) do { \
+#define Z_PARAM_ZVAL_DEREF_EX(dest, check_null, separate) \
Z_PARAM_PROLOGUE(separate); \
- _z_param_zval_deref(_arg, &dest, check_null); \
- } while (0);
+ _z_param_zval_deref(_arg, &dest, check_null);
#define Z_PARAM_ZVAL_DEREF(dest) \
Z_PARAM_ZVAL_DEREF_EX(dest, 0, 0)
@@ -1023,7 +1036,7 @@ zend_parse_params_failure: ZEND_ATTRIBUTE_UNUSED_LABEL \
/* old "+" and "*" */
#define Z_PARAM_VARIADIC_EX(spec, dest, dest_num, post_varargs) do { \
int _num_varargs = _num_args - _i - (post_varargs); \
- if (_num_varargs > 0) { \
+ if (EXPECTED(_num_varargs > 0)) { \
dest = _real_arg + 1; \
dest_num = _num_varargs; \
_i += _num_varargs; \
diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c
index 2dd5b16f44..8e1d970c41 100644
--- a/Zend/zend_ast.c
+++ b/Zend/zend_ast.c
@@ -173,7 +173,6 @@ static void zend_ast_add_array_element(zval *result, zval *offset, zval *expr TS
break;
case IS_STRING:
zend_symtable_update(Z_ARRVAL_P(result), Z_STR_P(offset), expr);
-//???
zval_dtor(offset);
break;
case IS_NULL:
@@ -234,11 +233,22 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *s
break;
}
case ZEND_AST_ZVAL:
- ZVAL_DUP(result, zend_ast_get_zval(ast));
- if (Z_OPT_CONSTANT_P(result)) {
- zval_update_constant_ex(result, 1, scope TSRMLS_CC);
+ {
+ zval *zv = zend_ast_get_zval(ast);
+ if (scope) {
+ /* class constants may be updated in-place */
+ if (Z_OPT_CONSTANT_P(zv)) {
+ zval_update_constant_ex(zv, 1, scope TSRMLS_CC);
+ }
+ ZVAL_DUP(result, zv);
+ } else {
+ ZVAL_DUP(result, zv);
+ if (Z_OPT_CONSTANT_P(result)) {
+ zval_update_constant_ex(result, 1, scope TSRMLS_CC);
+ }
}
break;
+ }
case ZEND_AST_AND:
zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC);
if (zend_is_true(&op1 TSRMLS_CC)) {
@@ -304,20 +314,17 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *s
}
}
break;
-//???
-#if 0
case ZEND_FETCH_DIM_R:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
- zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
+ zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->child[1], scope TSRMLS_CC);
{
- zval *tmp;
+ zval tmp;
zend_fetch_dimension_by_zval(&tmp, &op1, &op2 TSRMLS_CC);
- ZVAL_ZVAL(result, tmp, 1, 1);
+ ZVAL_ZVAL(result, &tmp, 1, 1);
}
zval_dtor(&op1);
zval_dtor(&op2);
break;
-#endif
default:
zend_error(E_ERROR, "Unsupported constant expression");
}
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 5a3359efa7..5e0ed6cf7b 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -3149,44 +3149,6 @@ void zend_do_end_compilation(TSRMLS_D) /* {{{ */
}
/* }}} */
-ZEND_API void zend_make_immutable_array(zval *zv TSRMLS_DC) /* {{{ */
-{
- zend_constant *c;
-
- if (Z_IMMUTABLE_P(zv)) {
- return;
- }
-
- Z_TYPE_FLAGS_P(zv) = IS_TYPE_IMMUTABLE;
- GC_REFCOUNT(Z_COUNTED_P(zv)) = 2;
- Z_ARRVAL_P(zv)->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
-
- /* store as an anonymous constant */
- c = emalloc(sizeof(zend_constant));
- ZVAL_COPY_VALUE(&c->value, zv);
- c->flags = 0;
- c->name = NULL;
- c->module_number = PHP_USER_CONSTANT;
- zend_hash_next_index_insert_ptr(EG(zend_constants), c);
-}
-/* }}} */
-
-void zend_make_immutable_array_r(zval *zv TSRMLS_DC) /* {{{ */
-{
- zval *el;
-
- if (Z_IMMUTABLE_P(zv)) {
- return;
- }
- zend_make_immutable_array(zv TSRMLS_CC);
- ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(zv), el) {
- if (Z_TYPE_P(el) == IS_ARRAY) {
- zend_make_immutable_array_r(el TSRMLS_CC);
- }
- } ZEND_HASH_FOREACH_END();
-}
-/* }}} */
-
/* {{{ zend_dirname
Returns directory name component of path */
ZEND_API size_t zend_dirname(char *path, size_t len)
@@ -6542,7 +6504,6 @@ static zend_bool zend_try_ct_eval_array(zval *result, zend_ast *ast TSRMLS_DC) {
}
}
- zend_make_immutable_array(result TSRMLS_CC);
return 1;
}
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index d3d81d04d0..0d343f0b39 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -450,7 +450,6 @@ typedef int (*unary_op_type)(zval *, zval * TSRMLS_DC);
typedef int (*binary_op_type)(zval *, zval *, zval * TSRMLS_DC);
ZEND_API unary_op_type get_unary_op(int opcode);
ZEND_API binary_op_type get_binary_op(int opcode);
-ZEND_API void zend_make_immutable_array(zval *zv TSRMLS_DC);
void zend_stop_lexing(TSRMLS_D);
void zend_emit_final_return(zval *zv TSRMLS_DC);
@@ -562,12 +561,10 @@ int zend_add_literal(zend_op_array *op_array, zval *zv TSRMLS_DC);
#define ZEND_FETCH_CLASS_DEFAULT 0
#define ZEND_FETCH_CLASS_SELF 1
#define ZEND_FETCH_CLASS_PARENT 2
-#define ZEND_FETCH_CLASS_MAIN 3 /* unused ??? */
-#define ZEND_FETCH_CLASS_GLOBAL 4 /* unused ??? */
-#define ZEND_FETCH_CLASS_AUTO 5
-#define ZEND_FETCH_CLASS_INTERFACE 6
-#define ZEND_FETCH_CLASS_STATIC 7
-#define ZEND_FETCH_CLASS_TRAIT 14
+#define ZEND_FETCH_CLASS_STATIC 3
+#define ZEND_FETCH_CLASS_AUTO 4
+#define ZEND_FETCH_CLASS_INTERFACE 5
+#define ZEND_FETCH_CLASS_TRAIT 6
#define ZEND_FETCH_CLASS_MASK 0x0f
#define ZEND_FETCH_CLASS_NO_AUTOLOAD 0x80
#define ZEND_FETCH_CLASS_SILENT 0x0100
diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c
index 650a566159..64ea7060fa 100644
--- a/Zend/zend_constants.c
+++ b/Zend/zend_constants.c
@@ -32,9 +32,7 @@ void free_zend_constant(zval *zv)
zend_constant *c = Z_PTR_P(zv);
if (!(c->flags & CONST_PERSISTENT)) {
- if (Z_REFCOUNTED(c->value) || Z_IMMUTABLE(c->value)) {
- _zval_dtor_func(Z_COUNTED(c->value) ZEND_FILE_LINE_CC);
- }
+ zval_dtor(&c->value);
} else {
zval_internal_dtor(&c->value);
}
@@ -398,7 +396,7 @@ ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope,
ret_constant = Z_REFVAL_P(ret_constant);
}
}
- STR_FREE(class_name);
+ STR_RELEASE(class_name);
STR_FREE(constant_name);
if (ret_constant && Z_CONSTANT_P(ret_constant)) {
zval_update_constant_ex(ret_constant, 1, ce TSRMLS_CC);
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 7fca796137..f3e97d71d0 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -133,8 +133,7 @@ static const zend_internal_function zend_pass_function = {
/* End of zend_execute_locks.h */
-// TODO: avoid global variable usage ???
-#define CV_DEF_OF(i) (EG(current_execute_data)->func->op_array.vars[i])
+#define CV_DEF_OF(i) (EX(func)->op_array.vars[i])
#define CTOR_CALL_BIT 0x1
#define CTOR_USED_BIT 0x2
@@ -182,7 +181,7 @@ static zend_always_inline zval *_get_zval_ptr_var_deref(zend_uint var, const zen
return ret;
}
-static zend_never_inline zval *_get_zval_cv_lookup(zval *ptr, zend_uint var, int type TSRMLS_DC)
+static zend_never_inline zval *_get_zval_cv_lookup(zval *ptr, zend_uint var, int type, const zend_execute_data *execute_data TSRMLS_DC)
{
zend_string *cv;
@@ -206,7 +205,7 @@ static zend_never_inline zval *_get_zval_cv_lookup(zval *ptr, zend_uint var, int
return ptr;
}
-static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_R(zval *ptr, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_R(zval *ptr, zend_uint var, const zend_execute_data *execute_data TSRMLS_DC)
{
zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
@@ -214,7 +213,7 @@ static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_R(zval *ptr, zend_uin
return &EG(uninitialized_zval);
}
-static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_UNSET(zval *ptr, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_UNSET(zval *ptr, zend_uint var, const zend_execute_data *execute_data TSRMLS_DC)
{
zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
@@ -222,12 +221,12 @@ static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_UNSET(zval *ptr, zend
return &EG(uninitialized_zval);
}
-static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_IS(zval *ptr, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_IS(zval *ptr, zend_uint var, const zend_execute_data *execute_data TSRMLS_DC)
{
return &EG(uninitialized_zval);
}
-static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_RW(zval *ptr, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_RW(zval *ptr, zend_uint var, const zend_execute_data *execute_data TSRMLS_DC)
{
zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
@@ -236,7 +235,7 @@ static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_RW(zval *ptr, zend_ui
return ptr;
}
-static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_W(zval *ptr, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_W(zval *ptr, zend_uint var, const zend_execute_data *execute_data TSRMLS_DC)
{
ZVAL_NULL(ptr);
return ptr;
@@ -247,7 +246,7 @@ static zend_always_inline zval *_get_zval_ptr_cv(const zend_execute_data *execut
zval *ret = EX_VAR(var);
if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
- return _get_zval_cv_lookup(ret, var, type TSRMLS_CC);
+ return _get_zval_cv_lookup(ret, var, type, execute_data TSRMLS_CC);
}
return ret;
}
@@ -257,7 +256,7 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref(const zend_execute_data *
zval *ret = EX_VAR(var);
if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
- return _get_zval_cv_lookup(ret, var, type TSRMLS_CC);
+ return _get_zval_cv_lookup(ret, var, type, execute_data TSRMLS_CC);
}
ZVAL_DEREF(ret);
return ret;
@@ -268,7 +267,7 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(const zend_execute_dat
zval *ret = EX_VAR(var);
if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
- return _get_zval_cv_lookup_BP_VAR_R(ret, var TSRMLS_CC);
+ return _get_zval_cv_lookup_BP_VAR_R(ret, var, execute_data TSRMLS_CC);
}
return ret;
}
@@ -278,7 +277,7 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_R(const zend_execu
zval *ret = EX_VAR(var);
if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
- return _get_zval_cv_lookup_BP_VAR_R(ret, var TSRMLS_CC);
+ return _get_zval_cv_lookup_BP_VAR_R(ret, var, execute_data TSRMLS_CC);
}
ZVAL_DEREF(ret);
return ret;
@@ -289,7 +288,7 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_UNSET(const zend_execute
zval *ret = EX_VAR(var);
if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
- return _get_zval_cv_lookup_BP_VAR_UNSET(ret, var TSRMLS_CC);
+ return _get_zval_cv_lookup_BP_VAR_UNSET(ret, var, execute_data TSRMLS_CC);
}
return ret;
}
@@ -299,7 +298,7 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_UNSET(const zend_e
zval *ret = EX_VAR(var);
if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
- return _get_zval_cv_lookup_BP_VAR_UNSET(ret, var TSRMLS_CC);
+ return _get_zval_cv_lookup_BP_VAR_UNSET(ret, var, execute_data TSRMLS_CC);
}
ZVAL_DEREF(ret);
return ret;
@@ -310,7 +309,7 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_IS(const zend_execute_da
zval *ret = EX_VAR(var);
if (Z_TYPE_P(ret) == IS_UNDEF) {
- return _get_zval_cv_lookup_BP_VAR_IS(ret, var TSRMLS_CC);
+ return _get_zval_cv_lookup_BP_VAR_IS(ret, var, execute_data TSRMLS_CC);
}
return ret;
}
@@ -320,7 +319,7 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_IS(const zend_exec
zval *ret = EX_VAR(var);
if (Z_TYPE_P(ret) == IS_UNDEF) {
- return _get_zval_cv_lookup_BP_VAR_IS(ret, var TSRMLS_CC);
+ return _get_zval_cv_lookup_BP_VAR_IS(ret, var, execute_data TSRMLS_CC);
}
ZVAL_DEREF(ret);
return ret;
@@ -331,7 +330,7 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(const zend_execute_da
zval *ret = EX_VAR(var);
if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
- return _get_zval_cv_lookup_BP_VAR_RW(ret, var TSRMLS_CC);
+ return _get_zval_cv_lookup_BP_VAR_RW(ret, var, execute_data TSRMLS_CC);
}
return ret;
}
@@ -341,7 +340,7 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_RW(const zend_exec
zval *ret = EX_VAR(var);
if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
- return _get_zval_cv_lookup_BP_VAR_RW(ret, var TSRMLS_CC);
+ return _get_zval_cv_lookup_BP_VAR_RW(ret, var, execute_data TSRMLS_CC);
}
ZVAL_DEREF(ret);
return ret;
@@ -352,7 +351,7 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(const zend_execute_dat
zval *ret = EX_VAR(var);
if (Z_TYPE_P(ret) == IS_UNDEF) {
- return _get_zval_cv_lookup_BP_VAR_W(ret, var TSRMLS_CC);
+ return _get_zval_cv_lookup_BP_VAR_W(ret, var, execute_data TSRMLS_CC);
}
return ret;
}
@@ -367,7 +366,7 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_W(const zend_execu
zval *ret = EX_VAR(var);
if (Z_TYPE_P(ret) == IS_UNDEF) {
- return _get_zval_cv_lookup_BP_VAR_W(ret, var TSRMLS_CC);
+ return _get_zval_cv_lookup_BP_VAR_W(ret, var, execute_data TSRMLS_CC);
}
ZVAL_DEREF(ret);
return ret;
@@ -697,34 +696,23 @@ static inline void zend_assign_to_object(zval *retval, zval *object_ptr, zval *p
if (Z_TYPE_P(object) == IS_NULL ||
Z_TYPE_P(object) == IS_FALSE ||
(Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0)) {
-//??? The following block may handle only non-interned empty string,
-//??? but it doesn't work anyway
-//??? see: Zend/tests/bug54265.phpt
-#if 0
- if (Z_REFCOUNTED_P(object)) {
- if (!Z_ISREF_P(object_ptr)) {
- SEPARATE_ZVAL(object);
- }
- Z_ADDREF_P(object);
- zend_error(E_WARNING, "Creating default object from empty value");
- if (Z_REFCOUNT_P(object) == 1) {
- /* object was removed by error handler, nothing to assign to */
- zval_ptr_dtor(object);
- if (retval) {
- ZVAL_NULL(retval);
- }
- FREE_OP(free_value);
- return;
+ zend_object *obj;
+
+ zval_ptr_dtor(object);
+ object_init(object);
+ Z_ADDREF_P(object);
+ obj = Z_OBJ_P(object);
+ zend_error(E_WARNING, "Creating default object from empty value");
+ if (GC_REFCOUNT(obj) == 1) {
+ /* the enclosing container was deleted, obj is unreferenced */
+ if (retval) {
+ ZVAL_NULL(retval);
}
- Z_DELREF_P(object);
- } else {
- zend_error(E_WARNING, "Creating default object from empty value");
+ FREE_OP(free_value);
+ OBJ_RELEASE(obj);
+ return;
}
-#else
- zend_error(E_WARNING, "Creating default object from empty value");
-#endif
- zval_dtor(object);
- object_init(object);
+ Z_DELREF_P(object);
} else {
zend_error(E_WARNING, "Attempt to assign property of non-object");
if (retval) {
@@ -945,6 +933,9 @@ static inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value TSRM
value = Z_REFVAL_P(value);
}
if (Z_REFCOUNTED_P(value)) {
+ if (UNEXPECTED(variable_ptr == value)) {
+ return variable_ptr;
+ }
Z_ADDREF_P(value);
}
}
@@ -1364,6 +1355,11 @@ static zend_never_inline void zend_fetch_dimension_address_read_IS(zval *result,
zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_IS TSRMLS_CC);
}
+ZEND_API void zend_fetch_dimension_by_zval(zval *result, zval *container, zval *dim TSRMLS_DC)
+{
+ zend_fetch_dimension_address_read_R(result, container, dim, IS_TMP_VAR TSRMLS_CC);
+}
+
static void zend_fetch_property_address(zval *result, zval *container_ptr, zval *prop_ptr, void **cache_slot, int type, int is_ref TSRMLS_DC)
{
zval *container = container_ptr;
diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h
index 812d4141b4..cb7ca70ef3 100644
--- a/Zend/zend_execute.h
+++ b/Zend/zend_execute.h
@@ -115,9 +115,6 @@ again:
result = Z_TYPE(tmp) == IS_TRUE;
break;
}
-
- // TODO: do we really need this warning ???
- // Nikita, add your comments here.
zend_error(E_RECOVERABLE_ERROR, "Object of class %s could not be converted to boolean", Z_OBJ_P(op)->ce->name->val);
} else if (Z_OBJ_HT_P(op)->get) {
zval rv;
@@ -289,6 +286,8 @@ ZEND_API zend_class_entry *zend_fetch_class(zend_string *class_name, int fetch_t
ZEND_API zend_class_entry *zend_fetch_class_by_name(zend_string *class_name, const zval *key, int fetch_type TSRMLS_DC);
void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC);
+ZEND_API void zend_fetch_dimension_by_zval(zval *result, zval *container, zval *dim TSRMLS_DC);
+
#ifdef ZEND_WIN32
void zend_init_timeout_thread(void);
void zend_shutdown_timeout_thread(void);
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index bdf87bd440..947d051ddd 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -859,6 +859,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
EG(scope) = func->common.scope;
}
call->prev_execute_data = EG(current_execute_data);
+ call->return_value = NULL; /* this is not a constructor call */
EG(current_execute_data) = call;
if (EXPECTED(zend_execute_internal == NULL)) {
/* saves one function call if zend_execute_internal is not used */
diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c
index eea4de8653..adc02a3eb0 100644
--- a/Zend/zend_gc.c
+++ b/Zend/zend_gc.c
@@ -472,7 +472,7 @@ static int gc_collect_white(zend_refcounted *ref TSRMLS_DC)
Bucket *p;
tail_call:
- if (GC_INFO(ref) == GC_WHITE) {
+ if (GC_GET_COLOR(GC_INFO(ref)) == GC_WHITE) {
ht = NULL;
GC_SET_BLACK(GC_INFO(ref));
@@ -481,6 +481,30 @@ tail_call:
count++;
}
+#if 1
+ if ((GC_TYPE(ref) == IS_OBJECT || GC_TYPE(ref) == IS_ARRAY) &&
+ !GC_ADDRESS(GC_INFO(ref))) {
+ /* add garbage into list */
+ gc_root_buffer *buf = GC_G(unused);
+
+ if (buf) {
+ GC_G(unused) = buf->prev;
+ } else if (GC_G(first_unused) != GC_G(last_unused)) {
+ buf = GC_G(first_unused);
+ GC_G(first_unused)++;
+ }
+ /* TODO: what should we do if we don't have room ??? */
+ if (buf) {
+ buf->ref = ref;
+ buf->next = GC_G(roots).next;
+ buf->prev = &GC_G(roots);
+ GC_G(roots).next->prev = buf;
+ GC_G(roots).next = buf;
+ GC_SET_ADDRESS(GC_INFO(ref), buf - GC_G(buf));
+ }
+ }
+#endif
+
if (GC_TYPE(ref) == IS_OBJECT && EG(objects_store).object_buckets) {
zend_object_get_gc_t get_gc;
zend_object *obj = (zend_object*)ref;
@@ -568,16 +592,23 @@ static int gc_collect_roots(TSRMLS_D)
int count = 0;
gc_root_buffer *current = GC_G(roots).next;
+ /* remove non-garbage from the list */
while (current != &GC_G(roots)) {
- GC_SET_ADDRESS(GC_INFO(current->ref), 0);
- if (GC_INFO(current->ref) == GC_WHITE) {
- count += gc_collect_white(current->ref TSRMLS_CC);
- GC_SET_ADDRESS(GC_INFO(current->ref), current - GC_G(buf));
- } else {
+ if (GC_GET_COLOR(GC_INFO(current->ref)) != GC_WHITE) {
+ GC_SET_ADDRESS(GC_INFO(current->ref), 0);
GC_REMOVE_FROM_ROOTS(current);
}
current = current->next;
}
+
+ current = GC_G(roots).next;
+ while (current != &GC_G(roots)) {
+ if (GC_GET_COLOR(GC_INFO(current->ref)) == GC_WHITE) {
+ GC_REFCOUNT(current->ref)++;
+ count += gc_collect_white(current->ref TSRMLS_CC);
+ }
+ current = current->next;
+ }
/* relink remaining roots into list to free */
if (GC_G(roots).next != &GC_G(roots)) {
if (GC_G(to_free).next == &GC_G(to_free)) {
@@ -600,6 +631,73 @@ static int gc_collect_roots(TSRMLS_D)
return count;
}
+static void gc_remove_nested_data_from_buffer(zend_refcounted *ref TSRMLS_DC)
+{
+ HashTable *ht;
+ uint idx;
+ Bucket *p;
+
+tail_call:
+ if (GC_ADDRESS(GC_INFO(ref)) != 0) {
+ GC_REMOVE_FROM_BUFFER(ref);
+
+ if (GC_TYPE(ref) == IS_OBJECT && EG(objects_store).object_buckets) {
+ zend_object_get_gc_t get_gc;
+ zend_object *obj = (zend_object*)ref;
+
+ if (EXPECTED(IS_OBJ_VALID(EG(objects_store).object_buckets[obj->handle]) &&
+ (get_gc = obj->handlers->get_gc) != NULL)) {
+ int i, n;
+ zval *table;
+ zval tmp;
+ HashTable *props;
+
+ ZVAL_OBJ(&tmp, obj);
+ props = get_gc(&tmp, &table, &n TSRMLS_CC);
+
+ while (n > 0 && !Z_REFCOUNTED(table[n-1])) n--;
+ for (i = 0; i < n; i++) {
+ if (Z_REFCOUNTED(table[i])) {
+ ref = Z_COUNTED(table[i]);
+ if (!props && i == n - 1) {
+ goto tail_call;
+ } else {
+ gc_remove_nested_data_from_buffer(ref TSRMLS_CC);
+ }
+ }
+ }
+ if (!props) {
+ return;
+ }
+ ht = props;
+ }
+ } else if (GC_TYPE(ref) == IS_ARRAY) {
+ ht = &((zend_array*)ref)->ht;
+ } else if (GC_TYPE(ref) == IS_REFERENCE) {
+ if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
+ if (UNEXPECTED(!EG(objects_store).object_buckets) &&
+ Z_TYPE(((zend_reference*)ref)->val) == IS_OBJECT) {
+ return;
+ }
+ ref = Z_COUNTED(((zend_reference*)ref)->val);
+ goto tail_call;
+ }
+ return;
+ }
+ if (!ht) return;
+ for (idx = 0; idx < ht->nNumUsed; idx++) {
+ p = ht->arData + idx;
+ if (!Z_REFCOUNTED(p->val)) continue;
+ ref = Z_COUNTED(p->val);
+ if (idx == ht->nNumUsed-1) {
+ goto tail_call;
+ } else {
+ gc_remove_nested_data_from_buffer(ref TSRMLS_CC);
+ }
+ }
+ }
+}
+
ZEND_API int gc_collect_cycles(TSRMLS_D)
{
int count = 0;
@@ -636,7 +734,14 @@ ZEND_API int gc_collect_cycles(TSRMLS_D)
orig_next_to_free = GC_G(next_to_free);
- /* First call destructors */
+ /* Remember reference counters before calling destructors */
+ current = to_free.next;
+ while (current != &to_free) {
+ current->refcount = GC_REFCOUNT(current->ref);
+ current = current->next;
+ }
+
+ /* Call destructors */
current = to_free.next;
while (current != &to_free) {
p = current->ref;
@@ -659,6 +764,16 @@ ZEND_API int gc_collect_cycles(TSRMLS_D)
current = GC_G(next_to_free);
}
+ /* Remove values captured in destructors */
+ current = to_free.next;
+ while (current != &to_free) {
+ GC_G(next_to_free) = current->next;
+ if (GC_REFCOUNT(current->ref) > current->refcount) {
+ gc_remove_nested_data_from_buffer(current->ref TSRMLS_CC);
+ }
+ current = GC_G(next_to_free);
+ }
+
/* Destroy zvals */
current = to_free.next;
while (current != &to_free) {
diff --git a/Zend/zend_gc.h b/Zend/zend_gc.h
index d060fae9dd..8d619f2e5e 100644
--- a/Zend/zend_gc.h
+++ b/Zend/zend_gc.h
@@ -74,9 +74,10 @@
GC_SET_PURPLE(Z_GC_INFO_P(v))
typedef struct _gc_root_buffer {
- struct _gc_root_buffer *prev; /* double-linked list */
- struct _gc_root_buffer *next;
zend_refcounted *ref;
+ struct _gc_root_buffer *next; /* double-linked list */
+ struct _gc_root_buffer *prev;
+ zend_uint refcount;
} gc_root_buffer;
typedef struct _zend_gc_globals {
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index e7aa255d78..78b38f7ea2 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -214,6 +214,7 @@ static zend_always_inline Bucket *zend_hash_str_find_bucket(const HashTable *ht,
nIndex = h & ht->nTableMask;
idx = ht->arHash[nIndex];
while (idx != INVALID_IDX) {
+ ZEND_ASSERT(idx < ht->nTableSize);
p = ht->arData + idx;
if ((p->h == h)
&& p->key
@@ -235,6 +236,7 @@ static zend_always_inline Bucket *zend_hash_index_find_bucket(const HashTable *h
nIndex = h & ht->nTableMask;
idx = ht->arHash[nIndex];
while (idx != INVALID_IDX) {
+ ZEND_ASSERT(idx < ht->nTableSize);
p = ht->arData + idx;
if (p->h == h && !p->key) {
return p;
@@ -579,6 +581,9 @@ ZEND_API int zend_hash_rehash(HashTable *ht)
IS_CONSISTENT(ht);
if (UNEXPECTED(ht->nNumOfElements == 0)) {
+ if (ht->nTableMask) {
+ memset(ht->arHash, INVALID_IDX, ht->nTableSize * sizeof(zend_uint));
+ }
return SUCCESS;
}
diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h
index c196134657..d7b419225e 100644
--- a/Zend/zend_hash.h
+++ b/Zend/zend_hash.h
@@ -628,6 +628,17 @@ static inline void *zend_hash_index_find_ptr(const HashTable *ht, ulong h)
return zv ? Z_PTR_P(zv) : NULL;
}
+static inline void *zend_symtable_str_find_ptr(HashTable *ht, const char *str, int len)
+{
+ ulong idx;
+
+ if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
+ return zend_hash_index_find_ptr(ht, idx);
+ } else {
+ return zend_hash_str_find_ptr(ht, str, len);
+ }
+}
+
static inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht, HashPosition *pos)
{
zval *zv;
diff --git a/Zend/zend_ini.c b/Zend/zend_ini.c
index 6232b8e2f1..c3a02d53a3 100644
--- a/Zend/zend_ini.c
+++ b/Zend/zend_ini.c
@@ -231,9 +231,11 @@ ZEND_API void zend_unregister_ini_entries(int module_number TSRMLS_DC) /* {{{ */
/* }}} */
#ifdef ZTS
-static int zend_ini_refresh_cache(zval *el, int stage TSRMLS_DC) /* {{{ */
+static int zend_ini_refresh_cache(zval *el, void *arg TSRMLS_DC) /* {{{ */
{
zend_ini_entry *p = (zend_ini_entry *)Z_PTR_P(el);
+ int stage = (int)(zend_intptr_t)arg;
+
if (p->on_modify) {
p->on_modify(p, p->value, p->value_length, p->mh_arg1, p->mh_arg2, p->mh_arg3, stage TSRMLS_CC);
}
diff --git a/Zend/zend_multibyte.c b/Zend/zend_multibyte.c
index 08251dfa5e..49056cfad4 100644
--- a/Zend/zend_multibyte.c
+++ b/Zend/zend_multibyte.c
@@ -168,7 +168,7 @@ ZEND_API const zend_encoding *zend_multibyte_get_script_encoding(TSRMLS_D)
ZEND_API int zend_multibyte_set_script_encoding(const zend_encoding **encoding_list, size_t encoding_list_size TSRMLS_DC)
{
if (CG(script_encoding_list)) {
- free(CG(script_encoding_list));
+ free((char*)CG(script_encoding_list));
}
CG(script_encoding_list) = encoding_list;
CG(script_encoding_list_size) = encoding_list_size;
@@ -195,7 +195,7 @@ ZEND_API int zend_multibyte_set_script_encoding_by_string(const char *new_value,
}
if (size == 0) {
- pefree(list, 1);
+ pefree((void*)list, 1);
return FAILURE;
}
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index 30794a3054..d7d8bf0a52 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -593,11 +593,25 @@ found:
ZVAL_COPY_VALUE(&garbage, Z_REFVAL_P(variable_ptr)); /* old value should be destroyed */
/* To check: can't *variable_ptr be some system variable like error_zval here? */
- ZVAL_COPY_VALUE(Z_REFVAL_P(variable_ptr), value);
- if (Z_REFCOUNTED_P(value) && Z_REFCOUNT_P(value) > 0) {
- zval_copy_ctor(Z_REFVAL_P(variable_ptr));
+ if (UNEXPECTED(Z_REFCOUNTED_P(value))) {
+ if (EXPECTED(!Z_ISREF_P(value))) {
+ Z_ADDREF_P(value);
+ } else {
+ if (Z_REFCOUNT_P(value) == 1) {
+ ZVAL_UNREF(value);
+ } else {
+ value = Z_REFVAL_P(value);
+ }
+ if (Z_REFCOUNTED_P(value)) {
+ if (UNEXPECTED(Z_REFVAL_P(variable_ptr) == value)) {
+ goto exit;
+ }
+ Z_ADDREF_P(value);
+ }
+ }
}
- zval_dtor(&garbage);
+ ZVAL_COPY_VALUE(Z_REFVAL_P(variable_ptr), value);
+ zval_ptr_dtor(&garbage);
} else {
zval garbage;
@@ -1455,6 +1469,7 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists,
found:
switch (has_set_exists) {
case 0:
+ ZVAL_DEREF(value);
result = (Z_TYPE_P(value) != IS_NULL);
break;
default:
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index dc2756fe09..921d71b685 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -819,6 +819,7 @@ try_again:
goto try_again;
EMPTY_SWITCH_DEFAULT_CASE()
}
+ return 0;
}
/* }}} */
@@ -859,6 +860,7 @@ try_again:
goto try_again;
EMPTY_SWITCH_DEFAULT_CASE()
}
+ return 0.0;
}
/* }}} */
@@ -912,6 +914,7 @@ try_again:
goto try_again;
EMPTY_SWITCH_DEFAULT_CASE()
}
+ return NULL;
}
/* }}} */
@@ -1552,10 +1555,10 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_CONCAT);
if (Z_TYPE_P(op1) != IS_STRING) {
- use_copy1 = zend_make_printable_zval(op1, &op1_copy);
+ use_copy1 = zend_make_printable_zval(op1, &op1_copy TSRMLS_CC);
}
if (Z_TYPE_P(op2) != IS_STRING) {
- use_copy2 = zend_make_printable_zval(op2, &op2_copy);
+ use_copy2 = zend_make_printable_zval(op2, &op2_copy TSRMLS_CC);
}
}
@@ -1783,6 +1786,14 @@ ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {
return SUCCESS;
default:
+ if (Z_ISREF_P(op1)) {
+ op1 = Z_REFVAL_P(op1);
+ continue;
+ } else if (Z_ISREF_P(op2)) {
+ op2 = Z_REFVAL_P(op2);
+ continue;
+ }
+
if (Z_TYPE_P(op1) == IS_OBJECT && Z_OBJ_HANDLER_P(op1, compare)) {
return Z_OBJ_HANDLER_P(op1, compare)(result, op1, op2 TSRMLS_CC);
} else if (Z_TYPE_P(op2) == IS_OBJECT && Z_OBJ_HANDLER_P(op2, compare)) {
@@ -1841,11 +1852,7 @@ ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {
return SUCCESS;
}
}
- if (Z_ISREF_P(op1)) {
- op1 = Z_REFVAL_P(op1);
- } else if (Z_ISREF_P(op2)) {
- op2 = Z_REFVAL_P(op2);
- } else if (!converted) {
+ if (!converted) {
if (Z_TYPE_P(op1) == IS_NULL || Z_TYPE_P(op1) == IS_FALSE) {
zendi_convert_to_boolean(op2, op2_copy, result);
ZVAL_LONG(result, (Z_TYPE_P(op2) == IS_TRUE) ? -1 : 0);
@@ -1888,10 +1895,9 @@ ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {
}
/* }}} */
-static int hash_zval_identical_function(zval *z1, zval *z2) /* {{{ */
+static int hash_zval_identical_function(zval *z1, zval *z2 TSRMLS_DC) /* {{{ */
{
zval result;
- TSRMLS_FETCH();
/* is_identical_function() returns 1 in case of identity and 0 in case
* of a difference;
diff --git a/Zend/zend_ts_hash.c b/Zend/zend_ts_hash.c
index 92cd62128e..f6523574ae 100644
--- a/Zend/zend_ts_hash.c
+++ b/Zend/zend_ts_hash.c
@@ -333,6 +333,39 @@ ZEND_API int zend_ts_hash_rehash(TsHashTable *ht)
return retval;
}
+ZEND_API zval *zend_ts_hash_str_find(TsHashTable *ht, const char *key, int len)
+{
+ zval *retval;
+
+ begin_read(ht);
+ retval = zend_hash_str_find(TS_HASH(ht), key, len);
+ end_read(ht);
+
+ return retval;
+}
+
+ZEND_API zval *_zend_ts_hash_str_update(TsHashTable *ht, const char *key, int len, zval *pData ZEND_FILE_LINE_DC)
+{
+ zval *retval;
+
+ begin_write(ht);
+ retval = zend_hash_str_update(TS_HASH(ht), key, len, pData);
+ end_write(ht);
+
+ return retval;
+}
+
+ZEND_API zval *_zend_ts_hash_str_add(TsHashTable *ht, const char *key, int len, zval *pData ZEND_FILE_LINE_DC)
+{
+ zval *retval;
+
+ begin_write(ht);
+ retval = zend_hash_str_add(TS_HASH(ht), key, len, pData);
+ end_write(ht);
+
+ return retval;
+}
+
/*
* Local variables:
* tab-width: 4
diff --git a/Zend/zend_ts_hash.h b/Zend/zend_ts_hash.h
index 4b0a507368..fcf8c3cda1 100644
--- a/Zend/zend_ts_hash.h
+++ b/Zend/zend_ts_hash.h
@@ -102,6 +102,41 @@ void zend_ts_hash_display_pListTail(TsHashTable *ht);
void zend_ts_hash_display(TsHashTable *ht);
#endif
+ZEND_API zval *zend_ts_hash_str_find(TsHashTable *ht, const char *key, int len);
+ZEND_API zval *_zend_ts_hash_str_update(TsHashTable *ht, const char *key, int len, zval *pData ZEND_FILE_LINE_DC);
+ZEND_API zval *_zend_ts_hash_str_add(TsHashTable *ht, const char *key, int len, zval *pData ZEND_FILE_LINE_DC);
+
+#define zend_ts_hash_str_update(ht, key, len, pData) \
+ _zend_ts_hash_str_update(ht, key, len, pData ZEND_FILE_LINE_CC)
+#define zend_ts_hash_str_add(ht, key, len, pData) \
+ _zend_ts_hash_str_add(ht, key, len, pData ZEND_FILE_LINE_CC)
+
+static inline void *zend_ts_hash_str_find_ptr(TsHashTable *ht, const char *str, int len)
+{
+ zval *zv;
+
+ zv = zend_ts_hash_str_find(ht, str, len);
+ return zv ? Z_PTR_P(zv) : NULL;
+}
+
+static inline void *zend_ts_hash_str_update_ptr(TsHashTable *ht, const char *str, int len, void *pData)
+{
+ zval tmp, *zv;
+
+ ZVAL_PTR(&tmp, pData);
+ zv = zend_ts_hash_str_update(ht, str, len, &tmp);
+ return zv ? Z_PTR_P(zv) : NULL;
+}
+
+static inline void *zend_ts_hash_str_add_ptr(TsHashTable *ht, const char *str, int len, void *pData)
+{
+ zval tmp, *zv;
+
+ ZVAL_PTR(&tmp, pData);
+ zv = zend_ts_hash_str_add(ht, str, len, &tmp);
+ return zv ? Z_PTR_P(zv) : NULL;
+}
+
END_EXTERN_C()
#define ZEND_TS_INIT_SYMTABLE(ht) \
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index f45882e52f..3122119998 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -1203,6 +1203,9 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, UNUSED|CONST|
ZEND_ASSERT(retval != NULL);
if (type == BP_VAR_R || type == BP_VAR_IS) {
+ if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
+ ZVAL_UNREF(retval);
+ }
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
@@ -2127,7 +2130,7 @@ ZEND_VM_HANDLER(56, ZEND_ADD_VAR, TMP|UNUSED, TMP|VAR|CV)
if (Z_TYPE_P(var) != IS_STRING) {
ZVAL_DEREF(var);
if (Z_TYPE_P(var) != IS_STRING) {
- use_copy = zend_make_printable_zval(var, &var_copy);
+ use_copy = zend_make_printable_zval(var, &var_copy TSRMLS_CC);
if (use_copy) {
var = &var_copy;
@@ -3477,7 +3480,7 @@ ZEND_VM_HANDLER(120, ZEND_SEND_USER, VAR|CV, ANY)
// This solution breaks the following test (emit warning message) ???
// ext/pdo_sqlite/tests/pdo_005.phpt
#endif
- (!Z_ISREF_P(arg) && Z_REFCOUNT_P(arg) > 1)) {
+ (!Z_ISREF_P(arg) /*&& Z_REFCOUNT_P(arg) > 1???*/)) {
if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
@@ -3841,7 +3844,7 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
retval = EX_VAR(opline->result.var);
ZVAL_COPY_VALUE(retval, &c->value);
if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) {
- if (Z_OPT_COPYABLE_P(retval) && (c->flags & CONST_PERSISTENT)) {
+ if (Z_OPT_COPYABLE_P(retval)) {
zval_copy_ctor_func(retval);
} else {
Z_ADDREF_P(retval);
@@ -4484,6 +4487,8 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
}
} else if (Z_IMMUTABLE_P(array_ptr)) {
zval_copy_ctor(array_ptr);
+ } else {
+ SEPARATE_ZVAL_NOREF(array_ptr);
}
if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref);
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
@@ -4845,8 +4850,9 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
FREE_OP1();
}
- if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -4924,7 +4930,8 @@ ZEND_VM_C_LABEL(num_index_prop):
if (opline->extended_value & ZEND_ISSET) {
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
- result = (value != NULL && Z_TYPE_P(value) > IS_NULL);
+ result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value TSRMLS_CC));
}
@@ -4943,6 +4950,9 @@ ZEND_VM_C_LABEL(num_index_prop):
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 263f729962..8605333d05 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -3093,6 +3093,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
}
} else if (Z_IMMUTABLE_P(array_ptr)) {
zval_copy_ctor(array_ptr);
+ } else {
+ SEPARATE_ZVAL_NOREF(array_ptr);
}
if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref);
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
@@ -3844,6 +3846,9 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_CONST(int type
ZEND_ASSERT(retval != NULL);
if (type == BP_VAR_R || type == BP_VAR_IS) {
+ if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
+ ZVAL_UNREF(retval);
+ }
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
@@ -4286,7 +4291,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO
retval = EX_VAR(opline->result.var);
ZVAL_COPY_VALUE(retval, &c->value);
if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) {
- if (Z_OPT_COPYABLE_P(retval) && (c->flags & CONST_PERSISTENT)) {
+ if (Z_OPT_COPYABLE_P(retval)) {
zval_copy_ctor_func(retval);
} else {
Z_ADDREF_P(retval);
@@ -4603,7 +4608,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_CONST_HANDLER(ZEND_O
}
if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -6343,6 +6349,9 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_VAR(int type,
ZEND_ASSERT(retval != NULL);
if (type == BP_VAR_R || type == BP_VAR_IS) {
+ if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
+ ZVAL_UNREF(retval);
+ }
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
@@ -6987,7 +6996,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPC
}
if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -7395,6 +7405,9 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int typ
ZEND_ASSERT(retval != NULL);
if (type == BP_VAR_R || type == BP_VAR_IS) {
+ if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
+ ZVAL_UNREF(retval);
+ }
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
@@ -7846,7 +7859,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_
}
if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -9807,6 +9821,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
}
} else if (Z_IMMUTABLE_P(array_ptr)) {
zval_copy_ctor(array_ptr);
+ } else {
+ SEPARATE_ZVAL_NOREF(array_ptr);
}
if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref);
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
@@ -10587,6 +10603,9 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_CONST(int type,
ZEND_ASSERT(retval != NULL);
if (type == BP_VAR_R || type == BP_VAR_IS) {
+ if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
+ ZVAL_UNREF(retval);
+ }
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
@@ -11200,7 +11219,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPC
}
if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -11968,7 +11988,7 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_
if (Z_TYPE_P(var) != IS_STRING) {
ZVAL_DEREF(var);
if (Z_TYPE_P(var) != IS_STRING) {
- use_copy = zend_make_printable_zval(var, &var_copy);
+ use_copy = zend_make_printable_zval(var, &var_copy TSRMLS_CC);
if (use_copy) {
var = &var_copy;
@@ -12864,6 +12884,9 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_VAR(int type, ZE
ZEND_ASSERT(retval != NULL);
if (type == BP_VAR_R || type == BP_VAR_IS) {
+ if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
+ ZVAL_UNREF(retval);
+ }
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
@@ -13101,7 +13124,7 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_
if (Z_TYPE_P(var) != IS_STRING) {
ZVAL_DEREF(var);
if (Z_TYPE_P(var) != IS_STRING) {
- use_copy = zend_make_printable_zval(var, &var_copy);
+ use_copy = zend_make_printable_zval(var, &var_copy TSRMLS_CC);
if (use_copy) {
var = &var_copy;
@@ -13465,7 +13488,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD
}
if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -13873,6 +13897,9 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type,
ZEND_ASSERT(retval != NULL);
if (type == BP_VAR_R || type == BP_VAR_IS) {
+ if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
+ ZVAL_UNREF(retval);
+ }
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
@@ -14208,7 +14235,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OP
}
if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -14818,7 +14846,7 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_A
if (Z_TYPE_P(var) != IS_STRING) {
ZVAL_DEREF(var);
if (Z_TYPE_P(var) != IS_STRING) {
- use_copy = zend_make_printable_zval(var, &var_copy);
+ use_copy = zend_make_printable_zval(var, &var_copy TSRMLS_CC);
if (use_copy) {
var = &var_copy;
@@ -16048,7 +16076,7 @@ static int ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR
// This solution breaks the following test (emit warning message) ???
// ext/pdo_sqlite/tests/pdo_005.phpt
#endif
- (!Z_ISREF_P(arg) && Z_REFCOUNT_P(arg) > 1)) {
+ (!Z_ISREF_P(arg) /*&& Z_REFCOUNT_P(arg) > 1???*/)) {
if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
@@ -16444,6 +16472,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
}
} else if (Z_IMMUTABLE_P(array_ptr)) {
zval_copy_ctor(array_ptr);
+ } else {
+ SEPARATE_ZVAL_NOREF(array_ptr);
}
if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref);
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
@@ -17875,6 +17905,9 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_CONST(int type,
ZEND_ASSERT(retval != NULL);
if (type == BP_VAR_R || type == BP_VAR_IS) {
+ if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
+ ZVAL_UNREF(retval);
+ }
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
@@ -18593,7 +18626,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE
retval = EX_VAR(opline->result.var);
ZVAL_COPY_VALUE(retval, &c->value);
if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) {
- if (Z_OPT_COPYABLE_P(retval) && (c->flags & CONST_PERSISTENT)) {
+ if (Z_OPT_COPYABLE_P(retval)) {
zval_copy_ctor_func(retval);
} else {
Z_ADDREF_P(retval);
@@ -19038,7 +19071,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPC
}
if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -19116,7 +19150,8 @@ num_index_prop:
if (opline->extended_value & ZEND_ISSET) {
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
- result = (value != NULL && Z_TYPE_P(value) > IS_NULL);
+ result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value TSRMLS_CC));
}
@@ -19135,6 +19170,9 @@ num_index_prop:
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
@@ -21105,7 +21143,8 @@ num_index_prop:
if (opline->extended_value & ZEND_ISSET) {
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
- result = (value != NULL && Z_TYPE_P(value) > IS_NULL);
+ result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value TSRMLS_CC));
}
@@ -21124,6 +21163,9 @@ num_index_prop:
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
@@ -22248,6 +22290,9 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_VAR(int type, ZE
ZEND_ASSERT(retval != NULL);
if (type == BP_VAR_R || type == BP_VAR_IS) {
+ if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
+ ZVAL_UNREF(retval);
+ }
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
@@ -23383,7 +23428,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD
}
if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -23461,7 +23507,8 @@ num_index_prop:
if (opline->extended_value & ZEND_ISSET) {
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
- result = (value != NULL && Z_TYPE_P(value) > IS_NULL);
+ result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value TSRMLS_CC));
}
@@ -23480,6 +23527,9 @@ num_index_prop:
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
@@ -24148,6 +24198,9 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_UNUSED(int type,
ZEND_ASSERT(retval != NULL);
if (type == BP_VAR_R || type == BP_VAR_IS) {
+ if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
+ ZVAL_UNREF(retval);
+ }
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
@@ -24710,7 +24763,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OP
}
if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -26693,7 +26747,8 @@ num_index_prop:
if (opline->extended_value & ZEND_ISSET) {
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
- result = (value != NULL && Z_TYPE_P(value) > IS_NULL);
+ result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value TSRMLS_CC));
}
@@ -26712,6 +26767,9 @@ num_index_prop:
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
@@ -27869,7 +27927,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC
retval = EX_VAR(opline->result.var);
ZVAL_COPY_VALUE(retval, &c->value);
if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) {
- if (Z_OPT_COPYABLE_P(retval) && (c->flags & CONST_PERSISTENT)) {
+ if (Z_OPT_COPYABLE_P(retval)) {
zval_copy_ctor_func(retval);
} else {
Z_ADDREF_P(retval);
@@ -28153,7 +28211,8 @@ num_index_prop:
if (opline->extended_value & ZEND_ISSET) {
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
- result = (value != NULL && Z_TYPE_P(value) > IS_NULL);
+ result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value TSRMLS_CC));
}
@@ -28172,6 +28231,9 @@ num_index_prop:
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
@@ -29117,7 +29179,7 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDL
if (Z_TYPE_P(var) != IS_STRING) {
ZVAL_DEREF(var);
if (Z_TYPE_P(var) != IS_STRING) {
- use_copy = zend_make_printable_zval(var, &var_copy);
+ use_copy = zend_make_printable_zval(var, &var_copy TSRMLS_CC);
if (use_copy) {
var = &var_copy;
@@ -29432,7 +29494,8 @@ num_index_prop:
if (opline->extended_value & ZEND_ISSET) {
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
- result = (value != NULL && Z_TYPE_P(value) > IS_NULL);
+ result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value TSRMLS_CC));
}
@@ -29451,6 +29514,9 @@ num_index_prop:
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
@@ -30398,7 +30464,7 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDL
if (Z_TYPE_P(var) != IS_STRING) {
ZVAL_DEREF(var);
if (Z_TYPE_P(var) != IS_STRING) {
- use_copy = zend_make_printable_zval(var, &var_copy);
+ use_copy = zend_make_printable_zval(var, &var_copy TSRMLS_CC);
if (use_copy) {
var = &var_copy;
@@ -30713,7 +30779,8 @@ num_index_prop:
if (opline->extended_value & ZEND_ISSET) {
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
- result = (value != NULL && Z_TYPE_P(value) > IS_NULL);
+ result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value TSRMLS_CC));
}
@@ -30732,6 +30799,9 @@ num_index_prop:
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
@@ -32190,7 +32260,7 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLE
if (Z_TYPE_P(var) != IS_STRING) {
ZVAL_DEREF(var);
if (Z_TYPE_P(var) != IS_STRING) {
- use_copy = zend_make_printable_zval(var, &var_copy);
+ use_copy = zend_make_printable_zval(var, &var_copy TSRMLS_CC);
if (use_copy) {
var = &var_copy;
@@ -32503,7 +32573,8 @@ num_index_prop:
if (opline->extended_value & ZEND_ISSET) {
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
- result = (value != NULL && Z_TYPE_P(value) > IS_NULL);
+ result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value TSRMLS_CC));
}
@@ -32522,6 +32593,9 @@ num_index_prop:
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
@@ -33414,7 +33488,7 @@ static int ZEND_FASTCALL ZEND_SEND_USER_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG
// This solution breaks the following test (emit warning message) ???
// ext/pdo_sqlite/tests/pdo_005.phpt
#endif
- (!Z_ISREF_P(arg) && Z_REFCOUNT_P(arg) > 1)) {
+ (!Z_ISREF_P(arg) /*&& Z_REFCOUNT_P(arg) > 1???*/)) {
if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
@@ -33795,6 +33869,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
}
} else if (Z_IMMUTABLE_P(array_ptr)) {
zval_copy_ctor(array_ptr);
+ } else {
+ SEPARATE_ZVAL_NOREF(array_ptr);
}
if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref);
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
@@ -35075,6 +35151,9 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type, Z
ZEND_ASSERT(retval != NULL);
if (type == BP_VAR_R || type == BP_VAR_IS) {
+ if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
+ ZVAL_UNREF(retval);
+ }
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
@@ -36024,7 +36103,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCO
}
if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -36102,7 +36182,8 @@ num_index_prop:
if (opline->extended_value & ZEND_ISSET) {
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
- result = (value != NULL && Z_TYPE_P(value) > IS_NULL);
+ result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value TSRMLS_CC));
}
@@ -36121,6 +36202,9 @@ num_index_prop:
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_CV == IS_CV || IS_CV == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
@@ -38002,7 +38086,8 @@ num_index_prop:
if (opline->extended_value & ZEND_ISSET) {
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
- result = (value != NULL && Z_TYPE_P(value) > IS_NULL);
+ result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value TSRMLS_CC));
}
@@ -38021,6 +38106,9 @@ num_index_prop:
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_CV == IS_CV || IS_CV == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
@@ -39143,6 +39231,9 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEN
ZEND_ASSERT(retval != NULL);
if (type == BP_VAR_R || type == BP_VAR_IS) {
+ if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
+ ZVAL_UNREF(retval);
+ }
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
@@ -40160,7 +40251,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE
}
if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -40238,7 +40330,8 @@ num_index_prop:
if (opline->extended_value & ZEND_ISSET) {
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
- result = (value != NULL && Z_TYPE_P(value) > IS_NULL);
+ result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value TSRMLS_CC));
}
@@ -40257,6 +40350,9 @@ num_index_prop:
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_CV == IS_CV || IS_CV == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
@@ -40923,6 +41019,9 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type,
ZEND_ASSERT(retval != NULL);
if (type == BP_VAR_R || type == BP_VAR_IS) {
+ if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
+ ZVAL_UNREF(retval);
+ }
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
@@ -41369,7 +41468,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPC
}
if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -43214,7 +43314,8 @@ num_index_prop:
if (opline->extended_value & ZEND_ISSET) {
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
- result = (value != NULL && Z_TYPE_P(value) > IS_NULL);
+ result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value TSRMLS_CC));
}
@@ -43233,6 +43334,9 @@ num_index_prop:
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_CV == IS_CV || IS_CV == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {