From 8515248a9e3edc1d75cc0ae14645e8c22644aa46 Mon Sep 17 00:00:00 2001 From: Dreamszhu Date: Fri, 28 Jun 2019 22:56:53 +0800 Subject: [PATCH] Fix #1879 (#1881) --- ext/kernel/array.c | 92 +++++++++++++----------------------- ext/kernel/memory.c | 2 +- ext/kernel/object.c | 16 ++++++- ext/test/vars.zep.c | 70 ++++++++++++++++++++++----- ext/test/vars.zep.h | 2 +- kernels/ZendEngine3/array.c | 92 +++++++++++++----------------------- kernels/ZendEngine3/object.c | 16 ++++++- test/vars.zep | 9 ++-- 8 files changed, 162 insertions(+), 137 deletions(-) diff --git a/ext/kernel/array.c b/ext/kernel/array.c index 519aa5982e..ec4276bd48 100644 --- a/ext/kernel/array.c +++ b/ext/kernel/array.c @@ -832,16 +832,12 @@ int zephir_array_key_exists(zval *arr, zval *key) */ void zephir_array_update_multi_ex(zval *arr, zval *value, const char *types, int types_length, int types_count, va_list ap) { - long old_l[ZEPHIR_MAX_ARRAY_LEVELS], old_ll[ZEPHIR_MAX_ARRAY_LEVELS]; - char *s, *old_s[ZEPHIR_MAX_ARRAY_LEVELS], old_type[ZEPHIR_MAX_ARRAY_LEVELS]; - zval *item, *old_item[ZEPHIR_MAX_ARRAY_LEVELS]; + char *s; + zval *item; zval pzv; - zend_array *p, *old_p[ZEPHIR_MAX_ARRAY_LEVELS]; - zval tmp; + zend_array *p; int i, j, l, ll, re_update, must_continue, wrap_tmp; - assert(types_length < ZEPHIR_MAX_ARRAY_LEVELS); - ZVAL_UNDEF(&tmp); ZVAL_UNDEF(&pzv); if (Z_TYPE_P(arr) != IS_ARRAY) { @@ -851,6 +847,7 @@ void zephir_array_update_multi_ex(zval *arr, zval *value, const char *types, int p = Z_ARRVAL_P(arr); for (i = 0; i < types_length; ++i) { + zval tmp; zval fetched; ZVAL_UNDEF(&fetched); @@ -858,15 +855,12 @@ void zephir_array_update_multi_ex(zval *arr, zval *value, const char *types, int must_continue = 0; wrap_tmp = 0; - old_p[i] = p; ZVAL_ARR(&pzv, p); switch (types[i]) { case 's': s = va_arg(ap, char*); l = va_arg(ap, int); - old_s[i] = s; - old_l[i] = l; if (zephir_array_isset_string_fetch(&fetched, &pzv, s, l, 1)) { if (Z_TYPE(fetched) == IS_ARRAY) { if (i == (types_length - 1)) { @@ -874,8 +868,14 @@ void zephir_array_update_multi_ex(zval *arr, zval *value, const char *types, int zephir_array_update_string(&pzv, s, l, value, PH_COPY | PH_SEPARATE); p = Z_ARRVAL(pzv); } else { - p = Z_ARRVAL(fetched); - Z_TRY_ADDREF(fetched); + re_update = !Z_REFCOUNTED(fetched) || (Z_REFCOUNT(fetched) > 1 && !Z_ISREF(fetched)); + if (re_update) { + ZVAL_DUP(&tmp, &fetched); + zephir_array_update_string(&pzv, s, l, &tmp, 0); + p = Z_ARRVAL(tmp); + } else { + p = Z_ARRVAL(fetched); + } } must_continue = 1; } @@ -902,7 +902,6 @@ void zephir_array_update_multi_ex(zval *arr, zval *value, const char *types, int case 'l': ll = va_arg(ap, long); - old_ll[i] = ll; if (zephir_array_isset_long_fetch(&fetched, &pzv, ll, 1)) { if (Z_TYPE(fetched) == IS_ARRAY) { if (i == (types_length - 1)) { @@ -910,8 +909,14 @@ void zephir_array_update_multi_ex(zval *arr, zval *value, const char *types, int zephir_array_update_long(&pzv, ll, value, PH_COPY | PH_SEPARATE ZEPHIR_DEBUG_PARAMS_DUMMY); p = Z_ARRVAL(pzv); } else { - p = Z_ARRVAL(fetched); - Z_TRY_ADDREF(fetched); + re_update = !Z_REFCOUNTED(fetched) || (Z_REFCOUNT(fetched) > 1 && !Z_ISREF(fetched)); + if (re_update) { + ZVAL_DUP(&tmp, &fetched); + zephir_array_update_long(&pzv, ll, &tmp, 0 ZEPHIR_DEBUG_PARAMS_DUMMY); + p = Z_ARRVAL(tmp); + } else { + p = Z_ARRVAL(fetched); + } } must_continue = 1; } @@ -938,7 +943,6 @@ void zephir_array_update_multi_ex(zval *arr, zval *value, const char *types, int case 'z': item = va_arg(ap, zval*); - old_item[i] = item; if (zephir_array_isset_fetch(&fetched, &pzv, item, 1)) { if (Z_TYPE(fetched) == IS_ARRAY) { if (i == (types_length - 1)) { @@ -946,8 +950,14 @@ void zephir_array_update_multi_ex(zval *arr, zval *value, const char *types, int zephir_array_update_zval(&pzv, item, value, PH_COPY | PH_SEPARATE); p = Z_ARRVAL(pzv); } else { - p = Z_ARRVAL(fetched); - Z_TRY_ADDREF(fetched); + re_update = !Z_REFCOUNTED(fetched) || (Z_REFCOUNT(fetched) > 1 && !Z_ISREF(fetched)); + if (re_update) { + ZVAL_DUP(&tmp, &fetched); + zephir_array_update_zval(&pzv, item, &tmp, 0); + p = Z_ARRVAL(tmp); + } else { + p = Z_ARRVAL(fetched); + } } must_continue = 1; } @@ -974,50 +984,14 @@ void zephir_array_update_multi_ex(zval *arr, zval *value, const char *types, int case 'a': re_update = !Z_REFCOUNTED(pzv) || (Z_REFCOUNT(pzv) > 1 && !Z_ISREF(pzv)); - zephir_array_append(&pzv, value, PH_SEPARATE ZEPHIR_DEBUG_PARAMS_DUMMY); - p = Z_ARRVAL(pzv); - break; - } - - if (re_update) { - for (j = i - 1; j >= 0; j--) { - zval old_pzv; - - if (!re_update) { - break; - } - - ZVAL_ARR(&pzv, old_p[j]); - re_update = !Z_REFCOUNTED(pzv) || (Z_REFCOUNT(pzv) > 1 && !Z_ISREF(pzv)); - - if (j == i - 1) { - ZVAL_ARR(&old_pzv, p); + if (re_update) { + zephir_array_append(&pzv, value, PH_COPY | PH_SEPARATE ZEPHIR_DEBUG_PARAMS_DUMMY); } else { - ZVAL_ARR(&old_pzv, old_p[j + 1]); - } - - switch (old_type[j]) - { - case 's': - zephir_array_update_string(&pzv, old_s[j], old_l[j], &old_pzv, PH_SEPARATE); - break; - case 'l': - zephir_array_update_long(&pzv, old_ll[j], &old_pzv, PH_SEPARATE ZEPHIR_DEBUG_PARAMS_DUMMY); - break; - case 'z': - zephir_array_update_zval(&pzv, old_item[j], &old_pzv, PH_SEPARATE); - break; - } - old_p[j] = Z_ARRVAL(pzv); - if (wrap_tmp) { - p = Z_ARRVAL(tmp); - wrap_tmp = 0; + zephir_array_append(&pzv, value, PH_COPY ZEPHIR_DEBUG_PARAMS_DUMMY); } - } - } - if (i != (types_length - 1)) { - old_type[i] = types[i]; + p = Z_ARRVAL(pzv); + break; } } } diff --git a/ext/kernel/memory.c b/ext/kernel/memory.c index 3254b4d124..2f8b3b89e6 100644 --- a/ext/kernel/memory.c +++ b/ext/kernel/memory.c @@ -83,7 +83,7 @@ void ZEPHIR_FASTCALL zephir_memory_grow_stack(zephir_method_globals *g, const ch #endif } -void zephir_memory_restore_stack(zephir_method_globals *g, const char *func) +void ZEPHIR_FASTCALL zephir_memory_restore_stack(zephir_method_globals *g, const char *func) { size_t i; zephir_memory_entry *prev, *active_memory; diff --git a/ext/kernel/object.c b/ext/kernel/object.c index 8e90dae803..edba0045c6 100644 --- a/ext/kernel/object.c +++ b/ext/kernel/object.c @@ -369,6 +369,16 @@ int zephir_clone(zval *destination, zval *obj) int zephir_isset_property(zval *object, const char *property_name, unsigned int property_length) { if (Z_TYPE_P(object) == IS_OBJECT) { + /* + if (Z_OBJ_HANDLER_P(object, has_property)) { + zval member; + int retval; + ZVAL_STRINGL(&member, property_name, property_length); + retval = Z_OBJ_HT_P(object)->has_property(object, &member, 2, NULL); + zval_ptr_dtor(&member); + return retval; + } + */ if (EXPECTED(zend_hash_str_exists(&Z_OBJCE_P(object)->properties_info, property_name, property_length))) { return 1; } @@ -385,7 +395,11 @@ int zephir_isset_property_zval(zval *object, const zval *property) { if (Z_TYPE_P(object) == IS_OBJECT) { if (Z_TYPE_P(property) == IS_STRING) { - + /* + if (Z_OBJ_HANDLER_P(object, has_property)) { + return Z_OBJ_HT_P(object)->has_property(object, property, 2, NULL); + } + */ if (EXPECTED(zend_hash_str_exists(&Z_OBJCE_P(object)->properties_info, Z_STRVAL_P(property), Z_STRLEN_P(property)))) { return 1; } else { diff --git a/ext/test/vars.zep.c b/ext/test/vars.zep.c index bac6b8755d..bf9d9ff578 100644 --- a/ext/test/vars.zep.c +++ b/ext/test/vars.zep.c @@ -13,6 +13,7 @@ #include "kernel/main.h" #include "kernel/array.h" +#include "kernel/fcall.h" #include "kernel/memory.h" #include "ext/spl/spl_exceptions.h" #include "kernel/exception.h" @@ -31,24 +32,69 @@ ZEPHIR_INIT_CLASS(Test_Vars) { PHP_METHOD(Test_Vars, testParam) { + zend_string *_4; + zend_ulong _3; zephir_method_globals *ZEPHIR_METHOD_GLOBALS_PTR = NULL; - zval *arr_param = NULL, _0; - zval arr; + zephir_fcall_cache_entry *_6 = NULL; + zend_long ZEPHIR_LAST_CALL_STATUS; + zval *config_param = NULL, k, v, _0, *_1, _2, _5$$3, _7$$4; + zval config; zval *this_ptr = getThis(); - ZVAL_UNDEF(&arr); + ZVAL_UNDEF(&config); + ZVAL_UNDEF(&k); + ZVAL_UNDEF(&v); ZVAL_UNDEF(&_0); + ZVAL_UNDEF(&_2); + ZVAL_UNDEF(&_5$$3); + ZVAL_UNDEF(&_7$$4); ZEPHIR_MM_GROW(); - zephir_fetch_params(1, 1, 0, &arr_param); - - ZEPHIR_OBS_COPY_OR_DUP(&arr, arr_param); - - - ZEPHIR_INIT_VAR(&_0); - ZVAL_STRING(&_0, "test"); - zephir_array_update_multi(&arr, &_0 TSRMLS_CC, SL("ss"), 4, SL("test"), SL("test")); - RETURN_CTOR(&arr); + zephir_fetch_params(1, 1, 0, &config_param); + + ZEPHIR_OBS_COPY_OR_DUP(&config, config_param); + + + zephir_array_fetch_string(&_0, &config, SL("dir"), PH_NOISY | PH_READONLY, "test/vars.zep", 8 TSRMLS_CC); + zephir_is_iterable(&_0, 0, "test/vars.zep", 11); + if (Z_TYPE_P(&_0) == IS_ARRAY) { + ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(&_0), _3, _4, _1) + { + ZEPHIR_INIT_NVAR(&k); + if (_4 != NULL) { + ZVAL_STR_COPY(&k, _4); + } else { + ZVAL_LONG(&k, _3); + } + ZEPHIR_INIT_NVAR(&v); + ZVAL_COPY(&v, _1); + ZEPHIR_CALL_FUNCTION(&_5$$3, "realpath", &_6, 57, &v); + zephir_check_call_status(); + zephir_array_update_multi(&config, &_5$$3 TSRMLS_CC, SL("sz"), 3, SL("dir"), &k); + } ZEND_HASH_FOREACH_END(); + } else { + ZEPHIR_CALL_METHOD(NULL, &_0, "rewind", NULL, 0); + zephir_check_call_status(); + while (1) { + ZEPHIR_CALL_METHOD(&_2, &_0, "valid", NULL, 0); + zephir_check_call_status(); + if (!zend_is_true(&_2)) { + break; + } + ZEPHIR_CALL_METHOD(&k, &_0, "key", NULL, 0); + zephir_check_call_status(); + ZEPHIR_CALL_METHOD(&v, &_0, "current", NULL, 0); + zephir_check_call_status(); + ZEPHIR_CALL_FUNCTION(&_7$$4, "realpath", &_6, 57, &v); + zephir_check_call_status(); + zephir_array_update_multi(&config, &_7$$4 TSRMLS_CC, SL("sz"), 3, SL("dir"), &k); + ZEPHIR_CALL_METHOD(NULL, &_0, "next", NULL, 0); + zephir_check_call_status(); + } + } + ZEPHIR_INIT_NVAR(&v); + ZEPHIR_INIT_NVAR(&k); + RETURN_CTOR(&config); } diff --git a/ext/test/vars.zep.h b/ext/test/vars.zep.h index 287fbf6997..dc1c8cd5c0 100644 --- a/ext/test/vars.zep.h +++ b/ext/test/vars.zep.h @@ -19,7 +19,7 @@ PHP_METHOD(Test_Vars, testBoolVarDump); PHP_METHOD(Test_Vars, testGetDefinedVars); ZEND_BEGIN_ARG_INFO_EX(arginfo_test_vars_testparam, 0, 0, 1) - ZEND_ARG_ARRAY_INFO(0, arr, 0) + ZEND_ARG_ARRAY_INFO(0, config, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_test_vars_testvardump2, 0, 0, 1) diff --git a/kernels/ZendEngine3/array.c b/kernels/ZendEngine3/array.c index 519aa5982e..ec4276bd48 100644 --- a/kernels/ZendEngine3/array.c +++ b/kernels/ZendEngine3/array.c @@ -832,16 +832,12 @@ int zephir_array_key_exists(zval *arr, zval *key) */ void zephir_array_update_multi_ex(zval *arr, zval *value, const char *types, int types_length, int types_count, va_list ap) { - long old_l[ZEPHIR_MAX_ARRAY_LEVELS], old_ll[ZEPHIR_MAX_ARRAY_LEVELS]; - char *s, *old_s[ZEPHIR_MAX_ARRAY_LEVELS], old_type[ZEPHIR_MAX_ARRAY_LEVELS]; - zval *item, *old_item[ZEPHIR_MAX_ARRAY_LEVELS]; + char *s; + zval *item; zval pzv; - zend_array *p, *old_p[ZEPHIR_MAX_ARRAY_LEVELS]; - zval tmp; + zend_array *p; int i, j, l, ll, re_update, must_continue, wrap_tmp; - assert(types_length < ZEPHIR_MAX_ARRAY_LEVELS); - ZVAL_UNDEF(&tmp); ZVAL_UNDEF(&pzv); if (Z_TYPE_P(arr) != IS_ARRAY) { @@ -851,6 +847,7 @@ void zephir_array_update_multi_ex(zval *arr, zval *value, const char *types, int p = Z_ARRVAL_P(arr); for (i = 0; i < types_length; ++i) { + zval tmp; zval fetched; ZVAL_UNDEF(&fetched); @@ -858,15 +855,12 @@ void zephir_array_update_multi_ex(zval *arr, zval *value, const char *types, int must_continue = 0; wrap_tmp = 0; - old_p[i] = p; ZVAL_ARR(&pzv, p); switch (types[i]) { case 's': s = va_arg(ap, char*); l = va_arg(ap, int); - old_s[i] = s; - old_l[i] = l; if (zephir_array_isset_string_fetch(&fetched, &pzv, s, l, 1)) { if (Z_TYPE(fetched) == IS_ARRAY) { if (i == (types_length - 1)) { @@ -874,8 +868,14 @@ void zephir_array_update_multi_ex(zval *arr, zval *value, const char *types, int zephir_array_update_string(&pzv, s, l, value, PH_COPY | PH_SEPARATE); p = Z_ARRVAL(pzv); } else { - p = Z_ARRVAL(fetched); - Z_TRY_ADDREF(fetched); + re_update = !Z_REFCOUNTED(fetched) || (Z_REFCOUNT(fetched) > 1 && !Z_ISREF(fetched)); + if (re_update) { + ZVAL_DUP(&tmp, &fetched); + zephir_array_update_string(&pzv, s, l, &tmp, 0); + p = Z_ARRVAL(tmp); + } else { + p = Z_ARRVAL(fetched); + } } must_continue = 1; } @@ -902,7 +902,6 @@ void zephir_array_update_multi_ex(zval *arr, zval *value, const char *types, int case 'l': ll = va_arg(ap, long); - old_ll[i] = ll; if (zephir_array_isset_long_fetch(&fetched, &pzv, ll, 1)) { if (Z_TYPE(fetched) == IS_ARRAY) { if (i == (types_length - 1)) { @@ -910,8 +909,14 @@ void zephir_array_update_multi_ex(zval *arr, zval *value, const char *types, int zephir_array_update_long(&pzv, ll, value, PH_COPY | PH_SEPARATE ZEPHIR_DEBUG_PARAMS_DUMMY); p = Z_ARRVAL(pzv); } else { - p = Z_ARRVAL(fetched); - Z_TRY_ADDREF(fetched); + re_update = !Z_REFCOUNTED(fetched) || (Z_REFCOUNT(fetched) > 1 && !Z_ISREF(fetched)); + if (re_update) { + ZVAL_DUP(&tmp, &fetched); + zephir_array_update_long(&pzv, ll, &tmp, 0 ZEPHIR_DEBUG_PARAMS_DUMMY); + p = Z_ARRVAL(tmp); + } else { + p = Z_ARRVAL(fetched); + } } must_continue = 1; } @@ -938,7 +943,6 @@ void zephir_array_update_multi_ex(zval *arr, zval *value, const char *types, int case 'z': item = va_arg(ap, zval*); - old_item[i] = item; if (zephir_array_isset_fetch(&fetched, &pzv, item, 1)) { if (Z_TYPE(fetched) == IS_ARRAY) { if (i == (types_length - 1)) { @@ -946,8 +950,14 @@ void zephir_array_update_multi_ex(zval *arr, zval *value, const char *types, int zephir_array_update_zval(&pzv, item, value, PH_COPY | PH_SEPARATE); p = Z_ARRVAL(pzv); } else { - p = Z_ARRVAL(fetched); - Z_TRY_ADDREF(fetched); + re_update = !Z_REFCOUNTED(fetched) || (Z_REFCOUNT(fetched) > 1 && !Z_ISREF(fetched)); + if (re_update) { + ZVAL_DUP(&tmp, &fetched); + zephir_array_update_zval(&pzv, item, &tmp, 0); + p = Z_ARRVAL(tmp); + } else { + p = Z_ARRVAL(fetched); + } } must_continue = 1; } @@ -974,50 +984,14 @@ void zephir_array_update_multi_ex(zval *arr, zval *value, const char *types, int case 'a': re_update = !Z_REFCOUNTED(pzv) || (Z_REFCOUNT(pzv) > 1 && !Z_ISREF(pzv)); - zephir_array_append(&pzv, value, PH_SEPARATE ZEPHIR_DEBUG_PARAMS_DUMMY); - p = Z_ARRVAL(pzv); - break; - } - - if (re_update) { - for (j = i - 1; j >= 0; j--) { - zval old_pzv; - - if (!re_update) { - break; - } - - ZVAL_ARR(&pzv, old_p[j]); - re_update = !Z_REFCOUNTED(pzv) || (Z_REFCOUNT(pzv) > 1 && !Z_ISREF(pzv)); - - if (j == i - 1) { - ZVAL_ARR(&old_pzv, p); + if (re_update) { + zephir_array_append(&pzv, value, PH_COPY | PH_SEPARATE ZEPHIR_DEBUG_PARAMS_DUMMY); } else { - ZVAL_ARR(&old_pzv, old_p[j + 1]); - } - - switch (old_type[j]) - { - case 's': - zephir_array_update_string(&pzv, old_s[j], old_l[j], &old_pzv, PH_SEPARATE); - break; - case 'l': - zephir_array_update_long(&pzv, old_ll[j], &old_pzv, PH_SEPARATE ZEPHIR_DEBUG_PARAMS_DUMMY); - break; - case 'z': - zephir_array_update_zval(&pzv, old_item[j], &old_pzv, PH_SEPARATE); - break; - } - old_p[j] = Z_ARRVAL(pzv); - if (wrap_tmp) { - p = Z_ARRVAL(tmp); - wrap_tmp = 0; + zephir_array_append(&pzv, value, PH_COPY ZEPHIR_DEBUG_PARAMS_DUMMY); } - } - } - if (i != (types_length - 1)) { - old_type[i] = types[i]; + p = Z_ARRVAL(pzv); + break; } } } diff --git a/kernels/ZendEngine3/object.c b/kernels/ZendEngine3/object.c index 8e90dae803..edba0045c6 100644 --- a/kernels/ZendEngine3/object.c +++ b/kernels/ZendEngine3/object.c @@ -369,6 +369,16 @@ int zephir_clone(zval *destination, zval *obj) int zephir_isset_property(zval *object, const char *property_name, unsigned int property_length) { if (Z_TYPE_P(object) == IS_OBJECT) { + /* + if (Z_OBJ_HANDLER_P(object, has_property)) { + zval member; + int retval; + ZVAL_STRINGL(&member, property_name, property_length); + retval = Z_OBJ_HT_P(object)->has_property(object, &member, 2, NULL); + zval_ptr_dtor(&member); + return retval; + } + */ if (EXPECTED(zend_hash_str_exists(&Z_OBJCE_P(object)->properties_info, property_name, property_length))) { return 1; } @@ -385,7 +395,11 @@ int zephir_isset_property_zval(zval *object, const zval *property) { if (Z_TYPE_P(object) == IS_OBJECT) { if (Z_TYPE_P(property) == IS_STRING) { - + /* + if (Z_OBJ_HANDLER_P(object, has_property)) { + return Z_OBJ_HT_P(object)->has_property(object, property, 2, NULL); + } + */ if (EXPECTED(zend_hash_str_exists(&Z_OBJCE_P(object)->properties_info, Z_STRVAL_P(property), Z_STRLEN_P(property)))) { return 1; } else { diff --git a/test/vars.zep b/test/vars.zep index 7c66942689..5256a807b5 100644 --- a/test/vars.zep +++ b/test/vars.zep @@ -2,10 +2,13 @@ namespace Test; class Vars { - public function testParam(array! arr) + public function testParam(array! config) { - let arr["test"]["test"] = "test"; - return arr; + var k, v; + for k, v in config["dir"] { + let config["dir"][k] = realpath(v); + } + return config; } public function testVarDump()