From 9cf87aa1965504b1cd9dc595a3c6af418a416cfc Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 24 Oct 2017 17:27:31 +0300 Subject: [PATCH] Avoid HashTable allocations for empty arrays (using zend_empty_array). --- Zend/zend_ast.c | 7 +- Zend/zend_builtin_functions.c | 8 +- Zend/zend_closures.c | 8 +- Zend/zend_compile.c | 5 + Zend/zend_hash.c | 14 ++ Zend/zend_hash.h | 9 ++ Zend/zend_operators.c | 2 + Zend/zend_vm_def.h | 35 +++-- Zend/zend_vm_execute.h | 250 ++++++++++++++----------------- ext/dom/xpath.c | 11 +- ext/libxml/libxml.c | 5 +- ext/mbstring/mbstring.c | 7 +- ext/mysqli/mysqli_nonapi.c | 14 +- ext/mysqli/mysqli_prop.c | 8 +- ext/reflection/php_reflection.c | 41 ++++- ext/simplexml/simplexml.c | 6 +- ext/spl/spl_fixedarray.c | 5 +- ext/sqlite3/sqlite3.c | 2 +- ext/standard/array.c | 10 +- ext/standard/var_unserializer.c | 35 +++-- ext/standard/var_unserializer.re | 5 +- ext/xsl/xsltprocessor.c | 4 +- 22 files changed, 282 insertions(+), 209 deletions(-) diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 96bedb7b42..9ace0790d5 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -408,10 +408,15 @@ ZEND_API int zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *sc } break; case ZEND_AST_ARRAY: - array_init(result); { uint32_t i; zend_ast_list *list = zend_ast_get_list(ast); + + if (!list->children) { + ZVAL_EMPTY_ARRAY(result); + break; + } + array_init(result); for (i = 0; i < list->children; i++) { zend_ast *elem = list->child[i]; if (elem->child[1]) { diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 5793ea3308..387e9f5e60 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -472,8 +472,8 @@ ZEND_FUNCTION(func_get_args) arg_count = ZEND_CALL_NUM_ARGS(ex); - array_init_size(return_value, arg_count); if (arg_count) { + array_init_size(return_value, arg_count); first_extra_arg = ex->func->op_array.num_args; zend_hash_real_init(Z_ARRVAL_P(return_value), 1); ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { @@ -512,6 +512,8 @@ ZEND_FUNCTION(func_get_args) } } ZEND_HASH_FILL_END(); Z_ARRVAL_P(return_value)->nNumOfElements = arg_count; + } else { + ZVAL_EMPTY_ARRAY(return_value); } } /* }}} */ @@ -2122,11 +2124,11 @@ static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) / { uint32_t num_args = ZEND_CALL_NUM_ARGS(call); - array_init_size(arg_array, num_args); if (num_args) { uint32_t i = 0; zval *p = ZEND_CALL_ARG(call, 1); + array_init_size(arg_array, num_args); zend_hash_real_init(Z_ARRVAL_P(arg_array), 1); ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(arg_array)) { if (call->func->type == ZEND_USER_FUNCTION) { @@ -2184,6 +2186,8 @@ static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) / } } ZEND_HASH_FILL_END(); Z_ARRVAL_P(arg_array)->nNumOfElements = num_args; + } else { + ZVAL_EMPTY_ARRAY(arg_array); } } /* }}} */ diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index eacd06ac4a..57d91c6635 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -251,8 +251,12 @@ static ZEND_NAMED_FUNCTION(zend_closure_call_magic) /* {{{ */ { fci.params = params; fci.param_count = 2; ZVAL_STR(&fci.params[0], EX(func)->common.function_name); - array_init(&fci.params[1]); - zend_copy_parameters_array(ZEND_NUM_ARGS(), &fci.params[1]); + if (ZEND_NUM_ARGS()) { + array_init_size(&fci.params[1], ZEND_NUM_ARGS()); + zend_copy_parameters_array(ZEND_NUM_ARGS(), &fci.params[1]); + } else { + ZVAL_EMPTY_ARRAY(&fci.params[1]); + } fci.object = Z_OBJ(EX(This)); fcc.object = Z_OBJ(EX(This)); diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 5e85a26957..96be2c60b2 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6949,6 +6949,11 @@ static zend_bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */ return 0; } + if (!list->children) { + ZVAL_EMPTY_ARRAY(result); + return 1; + } + array_init_size(result, list->children); for (i = 0; i < list->children; ++i) { zend_ast *elem_ast = list->child[i]; diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index d629c098dc..9f829ff994 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -157,6 +157,20 @@ static zend_always_inline void zend_hash_check_init(HashTable *ht, int packed) static const uint32_t uninitialized_bucket[-HT_MIN_MASK] = {HT_INVALID_IDX, HT_INVALID_IDX}; +ZEND_API const HashTable zend_empty_array = { + .gc.refcount = 2, + .gc.u.type_info = IS_ARRAY | (GC_IMMUTABLE << GC_FLAGS_SHIFT), + .u.flags = HASH_FLAG_STATIC_KEYS, + .nTableMask = HT_MIN_MASK, + .arData = (Bucket*)&uninitialized_bucket[2], + .nNumUsed = 0, + .nNumOfElements = 0, + .nTableSize = HT_MIN_SIZE, + .nInternalPointer = HT_INVALID_IDX, + .nNextFreeElement = 0, + .pDestructor = ZVAL_PTR_DTOR +}; + static zend_always_inline void _zend_hash_init_int(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent) { GC_REFCOUNT(ht) = 1; diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index e9518b8840..ca1be3b0d0 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -56,6 +56,15 @@ # define HT_ALLOW_COW_VIOLATION(ht) #endif +extern ZEND_API const HashTable zend_empty_array; + +#define ZVAL_EMPTY_ARRAY(z) do { \ + zval *__z = (z); \ + Z_ARR_P(__z) = (zend_array*)&zend_empty_array; \ + Z_TYPE_INFO_P(__z) = IS_ARRAY | (IS_TYPE_COPYABLE << Z_TYPE_FLAGS_SHIFT); \ + } while (0) + + typedef struct _zend_hash_key { zend_ulong h; zend_string *key; diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index fe6f97b12c..5270b6b39a 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -629,10 +629,12 @@ try_again: } zval_dtor(op); + /*ZVAL_EMPTY_ARRAY(op);*/ array_init(op); } break; case IS_NULL: + /*ZVAL_EMPTY_ARRAY(op);*/ array_init(op); break; case IS_REFERENCE: diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 76589f30af..0b36d2e725 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4782,7 +4782,7 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, NUM, ANY) } } ZEND_HASH_FILL_END(); } else { - array_init(params); + ZVAL_EMPTY_ARRAY(params); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -5263,19 +5263,16 @@ ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSED|NEXT| array = EX_VAR(opline->result.var); if (OP1_TYPE != IS_UNUSED) { size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_ARR(array, zend_new_array(size)); - - if (OP1_TYPE != IS_UNUSED) { + ZVAL_ARR(array, zend_new_array(size)); /* Explicitly initialize array as not-packed if flag is set */ if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { zend_hash_real_init(Z_ARRVAL_P(array), 0); } + ZEND_VM_DISPATCH_TO_HANDLER(ZEND_ADD_ARRAY_ELEMENT); + } else { + ZVAL_EMPTY_ARRAY(array); + ZEND_VM_NEXT_OPCODE(); } - - ZEND_VM_DISPATCH_TO_HANDLER(ZEND_ADD_ARRAY_ELEMENT); } ZEND_VM_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY, TYPE) @@ -5323,14 +5320,16 @@ ZEND_VM_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY, TYPE) if (opline->extended_value == IS_ARRAY) { if (Z_TYPE_P(expr) != IS_OBJECT) { - ZVAL_ARR(result, zend_new_array(8)); if (Z_TYPE_P(expr) != IS_NULL) { + ZVAL_ARR(result, zend_new_array(8)); expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr); if (OP1_TYPE == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr); } else { if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); } + } else { + ZVAL_EMPTY_ARRAY(result); } } else { ZVAL_COPY_VALUE(result, expr); @@ -7819,11 +7818,11 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY) SAVE_OPLINE(); - args = zend_new_array(num_args); if (num_args) { zval *p = ZEND_CALL_ARG(execute_data, 1); zval *end = p + num_args; + args = zend_new_array(num_args); zend_hash_real_init(args, 1); ZEND_HASH_FILL_PACKED(args) { do { @@ -7842,7 +7841,11 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY) ZEND_CALL_NUM_ARGS(call) = 2; ZVAL_STR(ZEND_CALL_ARG(call, 1), fbc->common.function_name); - ZVAL_ARR(ZEND_CALL_ARG(call, 2), args); + if (num_args) { + ZVAL_ARR(ZEND_CALL_ARG(call, 2), args); + } else { + ZVAL_EMPTY_ARRAY(ZEND_CALL_ARG(call, 2)); + } zend_free_trampoline(fbc); fbc = call->func; @@ -8316,11 +8319,11 @@ ZEND_VM_HANDLER(195, ZEND_FUNC_GET_ARGS, UNUSED|CONST, UNUSED) result_size = arg_count; } - ht = zend_new_array(result_size); - ZVAL_ARR(EX_VAR(opline->result.var), ht); - if (result_size) { uint32_t first_extra_arg = EX(func)->op_array.num_args; + + ht = zend_new_array(result_size); + ZVAL_ARR(EX_VAR(opline->result.var), ht); zend_hash_real_init(ht, 1); ZEND_HASH_FILL_PACKED(ht) { zval *p, *q; @@ -8364,6 +8367,8 @@ ZEND_VM_HANDLER(195, ZEND_FUNC_GET_ARGS, UNUSED|CONST, UNUSED) } } ZEND_HASH_FILL_END(); ht->nNumOfElements = result_size; + } else { + ZVAL_EMPTY_ARRAY(EX_VAR(opline->result.var)); } ZEND_VM_NEXT_OPCODE(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index bc846336fb..1a24762e36 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1501,7 +1501,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_HANDLER(ZEN } } ZEND_HASH_FILL_END(); } else { - array_init(params); + ZVAL_EMPTY_ARRAY(params); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -1967,11 +1967,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z SAVE_OPLINE(); - args = zend_new_array(num_args); if (num_args) { zval *p = ZEND_CALL_ARG(execute_data, 1); zval *end = p + num_args; + args = zend_new_array(num_args); zend_hash_real_init(args, 1); ZEND_HASH_FILL_PACKED(args) { do { @@ -1990,7 +1990,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z ZEND_CALL_NUM_ARGS(call) = 2; ZVAL_STR(ZEND_CALL_ARG(call, 1), fbc->common.function_name); - ZVAL_ARR(ZEND_CALL_ARG(call, 2), args); + if (num_args) { + ZVAL_ARR(ZEND_CALL_ARG(call, 2), args); + } else { + ZVAL_EMPTY_ARRAY(ZEND_CALL_ARG(call, 2)); + } zend_free_trampoline(fbc); fbc = call->func; @@ -3395,14 +3399,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CONST_HANDLER(ZEND_O if (opline->extended_value == IS_ARRAY) { if (Z_TYPE_P(expr) != IS_OBJECT) { - ZVAL_ARR(result, zend_new_array(8)); if (Z_TYPE_P(expr) != IS_NULL) { + ZVAL_ARR(result, zend_new_array(8)); expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr); if (IS_CONST == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr); } else { if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); } + } else { + ZVAL_EMPTY_ARRAY(result); } } else { ZVAL_COPY_VALUE(result, expr); @@ -5934,19 +5940,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CONST_HA array = EX_VAR(opline->result.var); if (IS_CONST != IS_UNUSED) { size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_ARR(array, zend_new_array(size)); - - if (IS_CONST != IS_UNUSED) { + ZVAL_ARR(array, zend_new_array(size)); /* Explicitly initialize array as not-packed if flag is set */ if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { zend_hash_real_init(Z_ARRVAL_P(array), 0); } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_EMPTY_ARRAY(array); + ZEND_VM_NEXT_OPCODE(); } - - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -7717,19 +7720,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_UNUSED_H array = EX_VAR(opline->result.var); if (IS_CONST != IS_UNUSED) { size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_ARR(array, zend_new_array(size)); - - if (IS_CONST != IS_UNUSED) { + ZVAL_ARR(array, zend_new_array(size)); /* Explicitly initialize array as not-packed if flag is set */ if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { zend_hash_real_init(Z_ARRVAL_P(array), 0); } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_EMPTY_ARRAY(array); + ZEND_VM_NEXT_OPCODE(); } - - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -8221,11 +8221,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FUNC_GET_ARGS_SPEC_CONST_UNUSE result_size = arg_count; } - ht = zend_new_array(result_size); - ZVAL_ARR(EX_VAR(opline->result.var), ht); - if (result_size) { uint32_t first_extra_arg = EX(func)->op_array.num_args; + + ht = zend_new_array(result_size); + ZVAL_ARR(EX_VAR(opline->result.var), ht); zend_hash_real_init(ht, 1); ZEND_HASH_FILL_PACKED(ht) { zval *p, *q; @@ -8269,6 +8269,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FUNC_GET_ARGS_SPEC_CONST_UNUSE } } ZEND_HASH_FILL_END(); ht->nNumOfElements = result_size; + } else { + ZVAL_EMPTY_ARRAY(EX_VAR(opline->result.var)); } ZEND_VM_NEXT_OPCODE(); } @@ -9998,19 +10000,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CV_HANDL array = EX_VAR(opline->result.var); if (IS_CONST != IS_UNUSED) { size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_ARR(array, zend_new_array(size)); - - if (IS_CONST != IS_UNUSED) { + ZVAL_ARR(array, zend_new_array(size)); /* Explicitly initialize array as not-packed if flag is set */ if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { zend_hash_real_init(Z_ARRVAL_P(array), 0); } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_EMPTY_ARRAY(array); + ZEND_VM_NEXT_OPCODE(); } - - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12013,19 +12012,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_TMPVAR_H array = EX_VAR(opline->result.var); if (IS_CONST != IS_UNUSED) { size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_ARR(array, zend_new_array(size)); - - if (IS_CONST != IS_UNUSED) { + ZVAL_ARR(array, zend_new_array(size)); /* Explicitly initialize array as not-packed if flag is set */ if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { zend_hash_real_init(Z_ARRVAL_P(array), 0); } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_EMPTY_ARRAY(array); + ZEND_VM_NEXT_OPCODE(); } - - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13038,14 +13034,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPC if (opline->extended_value == IS_ARRAY) { if (Z_TYPE_P(expr) != IS_OBJECT) { - ZVAL_ARR(result, zend_new_array(8)); if (Z_TYPE_P(expr) != IS_NULL) { + ZVAL_ARR(result, zend_new_array(8)); expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr); if (IS_TMP_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr); } else { if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); } + } else { + ZVAL_EMPTY_ARRAY(result); } } else { ZVAL_COPY_VALUE(result, expr); @@ -13982,19 +13980,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CONST_HAND array = EX_VAR(opline->result.var); if (IS_TMP_VAR != IS_UNUSED) { size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_ARR(array, zend_new_array(size)); - - if (IS_TMP_VAR != IS_UNUSED) { + ZVAL_ARR(array, zend_new_array(size)); /* Explicitly initialize array as not-packed if flag is set */ if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { zend_hash_real_init(Z_ARRVAL_P(array), 0); } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_EMPTY_ARRAY(array); + ZEND_VM_NEXT_OPCODE(); } - - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -14710,19 +14705,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_HAN array = EX_VAR(opline->result.var); if (IS_TMP_VAR != IS_UNUSED) { size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_ARR(array, zend_new_array(size)); - - if (IS_TMP_VAR != IS_UNUSED) { + ZVAL_ARR(array, zend_new_array(size)); /* Explicitly initialize array as not-packed if flag is set */ if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { zend_hash_real_init(Z_ARRVAL_P(array), 0); } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_EMPTY_ARRAY(array); + ZEND_VM_NEXT_OPCODE(); } - - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -15356,19 +15348,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER array = EX_VAR(opline->result.var); if (IS_TMP_VAR != IS_UNUSED) { size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_ARR(array, zend_new_array(size)); - - if (IS_TMP_VAR != IS_UNUSED) { + ZVAL_ARR(array, zend_new_array(size)); /* Explicitly initialize array as not-packed if flag is set */ if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { zend_hash_real_init(Z_ARRVAL_P(array), 0); } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_EMPTY_ARRAY(array); + ZEND_VM_NEXT_OPCODE(); } - - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -15902,19 +15891,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_HAN array = EX_VAR(opline->result.var); if (IS_TMP_VAR != IS_UNUSED) { size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_ARR(array, zend_new_array(size)); - - if (IS_TMP_VAR != IS_UNUSED) { + ZVAL_ARR(array, zend_new_array(size)); /* Explicitly initialize array as not-packed if flag is set */ if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { zend_hash_real_init(Z_ARRVAL_P(array), 0); } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_EMPTY_ARRAY(array); + ZEND_VM_NEXT_OPCODE(); } - - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -16757,14 +16743,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPC if (opline->extended_value == IS_ARRAY) { if (Z_TYPE_P(expr) != IS_OBJECT) { - ZVAL_ARR(result, zend_new_array(8)); if (Z_TYPE_P(expr) != IS_NULL) { + ZVAL_ARR(result, zend_new_array(8)); expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr); if (IS_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr); } else { if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); } + } else { + ZVAL_EMPTY_ARRAY(result); } } else { ZVAL_COPY_VALUE(result, expr); @@ -20009,19 +19997,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CONST_HAND array = EX_VAR(opline->result.var); if (IS_VAR != IS_UNUSED) { size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_ARR(array, zend_new_array(size)); - - if (IS_VAR != IS_UNUSED) { + ZVAL_ARR(array, zend_new_array(size)); /* Explicitly initialize array as not-packed if flag is set */ if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { zend_hash_real_init(Z_ARRVAL_P(array), 0); } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_EMPTY_ARRAY(array); + ZEND_VM_NEXT_OPCODE(); } - - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -21765,19 +21750,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_UNUSED_HAN array = EX_VAR(opline->result.var); if (IS_VAR != IS_UNUSED) { size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_ARR(array, zend_new_array(size)); - - if (IS_VAR != IS_UNUSED) { + ZVAL_ARR(array, zend_new_array(size)); /* Explicitly initialize array as not-packed if flag is set */ if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { zend_hash_real_init(Z_ARRVAL_P(array), 0); } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_EMPTY_ARRAY(array); + ZEND_VM_NEXT_OPCODE(); } - - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -24331,19 +24313,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CV_HANDLER array = EX_VAR(opline->result.var); if (IS_VAR != IS_UNUSED) { size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_ARR(array, zend_new_array(size)); - - if (IS_VAR != IS_UNUSED) { + ZVAL_ARR(array, zend_new_array(size)); /* Explicitly initialize array as not-packed if flag is set */ if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { zend_hash_real_init(Z_ARRVAL_P(array), 0); } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_EMPTY_ARRAY(array); + ZEND_VM_NEXT_OPCODE(); } - - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -26847,19 +26826,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_TMPVAR_HAN array = EX_VAR(opline->result.var); if (IS_VAR != IS_UNUSED) { size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_ARR(array, zend_new_array(size)); - - if (IS_VAR != IS_UNUSED) { + ZVAL_ARR(array, zend_new_array(size)); /* Explicitly initialize array as not-packed if flag is set */ if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { zend_hash_real_init(Z_ARRVAL_P(array), 0); } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_EMPTY_ARRAY(array); + ZEND_VM_NEXT_OPCODE(); } - - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -29775,11 +29751,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FUNC_GET_ARGS_SPEC_UNUSED_UNUS result_size = arg_count; } - ht = zend_new_array(result_size); - ZVAL_ARR(EX_VAR(opline->result.var), ht); - if (result_size) { uint32_t first_extra_arg = EX(func)->op_array.num_args; + + ht = zend_new_array(result_size); + ZVAL_ARR(EX_VAR(opline->result.var), ht); zend_hash_real_init(ht, 1); ZEND_HASH_FILL_PACKED(ht) { zval *p, *q; @@ -29823,6 +29799,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FUNC_GET_ARGS_SPEC_UNUSED_UNUS } } ZEND_HASH_FILL_END(); ht->nNumOfElements = result_size; + } else { + ZVAL_EMPTY_ARRAY(EX_VAR(opline->result.var)); } ZEND_VM_NEXT_OPCODE(); } @@ -34217,14 +34195,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCO if (opline->extended_value == IS_ARRAY) { if (Z_TYPE_P(expr) != IS_OBJECT) { - ZVAL_ARR(result, zend_new_array(8)); if (Z_TYPE_P(expr) != IS_NULL) { + ZVAL_ARR(result, zend_new_array(8)); expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr); if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr); } else { if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); } + } else { + ZVAL_EMPTY_ARRAY(result); } } else { ZVAL_COPY_VALUE(result, expr); @@ -38224,19 +38204,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CONST_HANDL array = EX_VAR(opline->result.var); if (IS_CV != IS_UNUSED) { size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_ARR(array, zend_new_array(size)); - - if (IS_CV != IS_UNUSED) { + ZVAL_ARR(array, zend_new_array(size)); /* Explicitly initialize array as not-packed if flag is set */ if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { zend_hash_real_init(Z_ARRVAL_P(array), 0); } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_EMPTY_ARRAY(array); + ZEND_VM_NEXT_OPCODE(); } - - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -40926,19 +40903,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_UNUSED_HAND array = EX_VAR(opline->result.var); if (IS_CV != IS_UNUSED) { size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_ARR(array, zend_new_array(size)); - - if (IS_CV != IS_UNUSED) { + ZVAL_ARR(array, zend_new_array(size)); /* Explicitly initialize array as not-packed if flag is set */ if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { zend_hash_real_init(Z_ARRVAL_P(array), 0); } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_EMPTY_ARRAY(array); + ZEND_VM_NEXT_OPCODE(); } - - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_CV_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -44766,19 +44740,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CV_HANDLER( array = EX_VAR(opline->result.var); if (IS_CV != IS_UNUSED) { size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_ARR(array, zend_new_array(size)); - - if (IS_CV != IS_UNUSED) { + ZVAL_ARR(array, zend_new_array(size)); /* Explicitly initialize array as not-packed if flag is set */ if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { zend_hash_real_init(Z_ARRVAL_P(array), 0); } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_EMPTY_ARRAY(array); + ZEND_VM_NEXT_OPCODE(); } - - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -48377,19 +48348,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_TMPVAR_HAND array = EX_VAR(opline->result.var); if (IS_CV != IS_UNUSED) { size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; - } else { - size = 0; - } - ZVAL_ARR(array, zend_new_array(size)); - - if (IS_CV != IS_UNUSED) { + ZVAL_ARR(array, zend_new_array(size)); /* Explicitly initialize array as not-packed if flag is set */ if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { zend_hash_real_init(Z_ARRVAL_P(array), 0); } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_EMPTY_ARRAY(array); + ZEND_VM_NEXT_OPCODE(); } - - ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) diff --git a/ext/dom/xpath.c b/ext/dom/xpath.c index 57d1c8796a..f0b908ccf3 100644 --- a/ext/dom/xpath.c +++ b/ext/dom/xpath.c @@ -134,8 +134,8 @@ static void dom_xpath_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, xmlFree(str); } else if (type == 2) { int j; - array_init(&fci.params[i]); if (obj->nodesetval && obj->nodesetval->nodeNr > 0) { + array_init(&fci.params[i]); for (j = 0; j < obj->nodesetval->nodeNr; j++) { xmlNodePtr node = obj->nodesetval->nodeTab[j]; zval child; @@ -161,6 +161,8 @@ static void dom_xpath_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, php_dom_create_object(node, &child, &intern->dom); add_next_index_zval(&fci.params[i], &child); } + } else { + ZVAL_EMPTY_ARRAY(&fci.params[i]); } } break; @@ -430,10 +432,9 @@ static void php_xpath_eval(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */ int i; xmlNodeSetPtr nodesetp; - array_init(&retval); - - if (xpathobjp->type == XPATH_NODESET && NULL != (nodesetp = xpathobjp->nodesetval)) { + if (xpathobjp->type == XPATH_NODESET && NULL != (nodesetp = xpathobjp->nodesetval) && nodesetp->nodeNr) { + array_init(&retval); for (i = 0; i < nodesetp->nodeNr; i++) { xmlNodePtr node = nodesetp->nodeTab[i]; zval child; @@ -459,6 +460,8 @@ static void php_xpath_eval(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */ php_dom_create_object(node, &child, &intern->dom); add_next_index_zval(&retval, &child); } + } else { + ZVAL_EMPTY_ARRAY(&retval); } php_dom_create_interator(return_value, DOM_NODELIST); nodeobj = Z_DOMOBJ_P(return_value); diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c index c355ae2ba4..74a1736894 100644 --- a/ext/libxml/libxml.c +++ b/ext/libxml/libxml.c @@ -1042,10 +1042,9 @@ static PHP_FUNCTION(libxml_get_errors) xmlErrorPtr error; - array_init(return_value); - if (LIBXML(error_list)) { + array_init(return_value); error = zend_llist_get_first(LIBXML(error_list)); while (error != NULL) { @@ -1070,6 +1069,8 @@ static PHP_FUNCTION(libxml_get_errors) error = zend_llist_get_next(LIBXML(error_list)); } + } else { + ZVAL_EMPTY_ARRAY(return_value); } } /* }}} */ diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 01fd345017..7bb4304aff 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -3136,10 +3136,11 @@ MBSTRING_API HashTable *php_mb_convert_encoding_recursive(HashTable *input, cons break; case IS_ARRAY: chash = php_mb_convert_encoding_recursive(HASH_OF(entry), _to_encoding, _from_encodings); - if (!chash) { - chash = zend_new_array(0); + if (chash) { + ZVAL_ARR(&entry_tmp, chash); + } else { + ZVAL_EMPTY_ARRAY(&entry_tmp); } - ZVAL_ARR(&entry_tmp, chash); break; case IS_OBJECT: default: diff --git a/ext/mysqli/mysqli_nonapi.c b/ext/mysqli/mysqli_nonapi.c index 3dba36317d..6d4f648a7f 100644 --- a/ext/mysqli/mysqli_nonapi.c +++ b/ext/mysqli/mysqli_nonapi.c @@ -423,11 +423,11 @@ PHP_FUNCTION(mysqli_error_list) return; } MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID); - array_init(return_value); #if defined(MYSQLI_USE_MYSQLND) if (mysql->mysql->data->error_info->error_list) { MYSQLND_ERROR_LIST_ELEMENT * message; zend_llist_position pos; + array_init(return_value); for (message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_first_ex(mysql->mysql->data->error_info->error_list, &pos); message; message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_next_ex(mysql->mysql->data->error_info->error_list, &pos)) @@ -439,15 +439,20 @@ PHP_FUNCTION(mysqli_error_list) add_assoc_string_ex(&single_error, "error", sizeof("error") - 1, message->error); add_next_index_zval(return_value, &single_error); } + } else { + ZVAL_EMPTY_ARRAY(return_value); } #else if (mysql_errno(mysql->mysql)) { zval single_error; + array_init(return_value); array_init(&single_error); add_assoc_long_ex(&single_error, "errno", sizeof("errno") - 1, mysql_errno(mysql->mysql)); add_assoc_string_ex(&single_error, "sqlstate", sizeof("sqlstate") - 1, mysql_sqlstate(mysql->mysql)); add_assoc_string_ex(&single_error, "error", sizeof("error") - 1, mysql_error(mysql->mysql)); add_next_index_zval(return_value, &single_error); + } else { + ZVAL_EMPTY_ARRAY(return_value); } #endif } @@ -464,11 +469,11 @@ PHP_FUNCTION(mysqli_stmt_error_list) return; } MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_INITIALIZED); - array_init(return_value); #if defined(MYSQLI_USE_MYSQLND) if (stmt->stmt && stmt->stmt->data && stmt->stmt->data->error_info->error_list) { MYSQLND_ERROR_LIST_ELEMENT * message; zend_llist_position pos; + array_init(return_value); for (message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_first_ex(stmt->stmt->data->error_info->error_list, &pos); message; message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_next_ex(stmt->stmt->data->error_info->error_list, &pos)) @@ -480,15 +485,20 @@ PHP_FUNCTION(mysqli_stmt_error_list) add_assoc_string_ex(&single_error, "error", sizeof("error") - 1, message->error); add_next_index_zval(return_value, &single_error); } + } else { + ZVAL_EMPTY_ARRAY(return_value); } #else if (mysql_stmt_errno(stmt->stmt)) { zval single_error; + array_init(return_value); array_init(&single_error); add_assoc_long_ex(&single_error, "errno", sizeof("errno") - 1, mysql_stmt_errno(stmt->stmt)); add_assoc_string_ex(&single_error, "sqlstate", sizeof("sqlstate") - 1, mysql_stmt_sqlstate(stmt->stmt)); add_assoc_string_ex(&single_error, "error", sizeof("error") - 1, mysql_stmt_error(stmt->stmt)); add_next_index_zval(return_value, &single_error); + } else { + ZVAL_EMPTY_ARRAY(return_value); } #endif } diff --git a/ext/mysqli/mysqli_prop.c b/ext/mysqli/mysqli_prop.c index 06a4736008..0b3858d1c3 100644 --- a/ext/mysqli/mysqli_prop.c +++ b/ext/mysqli/mysqli_prop.c @@ -184,8 +184,8 @@ static zval *link_error_list_read(mysqli_object *obj, zval *retval) mysql = (MY_MYSQL *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr; - array_init(retval); if (mysql) { + array_init(retval); #if defined(MYSQLI_USE_MYSQLND) if (mysql->mysql->data->error_info->error_list) { MYSQLND_ERROR_LIST_ELEMENT * message; @@ -212,6 +212,8 @@ static zval *link_error_list_read(mysqli_object *obj, zval *retval) add_next_index_zval(retval, &single_error); } #endif + } else { + ZVAL_EMPTY_ARRAY(retval); } return retval; @@ -374,8 +376,8 @@ static zval *stmt_error_list_read(mysqli_object *obj, zval *retval) CHECK_STATUS(MYSQLI_STATUS_INITIALIZED); stmt = (MY_STMT *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr; - array_init(retval); if (stmt && stmt->stmt) { + array_init(retval); #if defined(MYSQLI_USE_MYSQLND) if (stmt->stmt->data && stmt->stmt->data->error_info->error_list) { MYSQLND_ERROR_LIST_ELEMENT * message; @@ -402,6 +404,8 @@ static zval *stmt_error_list_read(mysqli_object *obj, zval *retval) add_next_index_zval(retval, &single_error); } #endif + } else { + ZVAL_EMPTY_ARRAY(retval); } return retval; } diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 6a19940686..f8073e9186 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -1846,8 +1846,8 @@ ZEND_METHOD(reflection_function, getStaticVariables) GET_REFLECTION_OBJECT_PTR(fptr); /* Return an empty array in case no static variables exist */ - array_init(return_value); if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.static_variables != NULL) { + array_init(return_value); if (GC_REFCOUNT(fptr->op_array.static_variables) > 1) { if (!(GC_FLAGS(fptr->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) { GC_REFCOUNT(fptr->op_array.static_variables)--; @@ -1860,6 +1860,8 @@ ZEND_METHOD(reflection_function, getStaticVariables) } } ZEND_HASH_FOREACH_END(); zend_hash_copy(Z_ARRVAL_P(return_value), fptr->op_array.static_variables, zval_add_ref); + } else { + ZVAL_EMPTY_ARRAY(return_value); } } /* }}} */ @@ -2046,6 +2048,11 @@ ZEND_METHOD(reflection_function, getParameters) num_args++; } + if (!num_args) { + ZVAL_EMPTY_ARRAY(return_value); + return; + } + array_init(return_value); for (i = 0; i < num_args; i++) { zval parameter; @@ -4917,17 +4924,17 @@ ZEND_METHOD(reflection_class, getInterfaces) } GET_REFLECTION_OBJECT_PTR(ce); - /* Return an empty array if this class implements no interfaces */ - array_init(return_value); - if (ce->num_interfaces) { uint32_t i; + array_init(return_value); for (i=0; i < ce->num_interfaces; i++) { zval interface; zend_reflection_class_factory(ce->interfaces[i], &interface); zend_hash_update(Z_ARRVAL_P(return_value), ce->interfaces[i]->name, &interface); } + } else { + ZVAL_EMPTY_ARRAY(return_value); } } /* }}} */ @@ -4945,7 +4952,12 @@ ZEND_METHOD(reflection_class, getInterfaceNames) } GET_REFLECTION_OBJECT_PTR(ce); - /* Return an empty array if this class implements no interfaces */ + if (!ce->num_interfaces) { + /* Return an empty array if this class implements no interfaces */ + ZVAL_EMPTY_ARRAY(return_value); + return; + } + array_init(return_value); for (i=0; i < ce->num_interfaces; i++) { @@ -4967,6 +4979,11 @@ ZEND_METHOD(reflection_class, getTraits) } GET_REFLECTION_OBJECT_PTR(ce); + if (!ce->num_traits) { + ZVAL_EMPTY_ARRAY(return_value); + return; + } + array_init(return_value); for (i=0; i < ce->num_traits; i++) { @@ -4990,6 +5007,11 @@ ZEND_METHOD(reflection_class, getTraitNames) } GET_REFLECTION_OBJECT_PTR(ce); + if (!ce->num_traits) { + ZVAL_EMPTY_ARRAY(return_value); + return; + } + array_init(return_value); for (i=0; i < ce->num_traits; i++) { @@ -5010,10 +5032,11 @@ ZEND_METHOD(reflection_class, getTraitAliases) } GET_REFLECTION_OBJECT_PTR(ce); - array_init(return_value); if (ce->trait_aliases) { uint32_t i = 0; + + array_init(return_value); while (ce->trait_aliases[i]) { zend_string *mname; zend_trait_method_reference *cur_ref = ce->trait_aliases[i]->trait_method; @@ -5026,6 +5049,8 @@ ZEND_METHOD(reflection_class, getTraitAliases) } i++; } + } else { + ZVAL_EMPTY_ARRAY(return_value); } } /* }}} */ @@ -5961,15 +5986,15 @@ ZEND_METHOD(reflection_extension, getDependencies) } GET_REFLECTION_OBJECT_PTR(module); - array_init(return_value); - dep = module->deps; if (!dep) { + ZVAL_EMPTY_ARRAY(return_value); return; } + array_init(return_value); while(dep->name) { zend_string *relation; char *rel_type; diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 92d180cf8b..748c5c5453 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -1350,9 +1350,9 @@ SXE_METHOD(xpath) result = retval->nodesetval; - array_init(return_value); - if (result != NULL) { + array_init(return_value); + for (i = 0; i < result->nodeNr; ++i) { nodeptr = result->nodeTab[i]; if (nodeptr->type == XML_TEXT_NODE || nodeptr->type == XML_ELEMENT_NODE || nodeptr->type == XML_ATTRIBUTE_NODE) { @@ -1372,6 +1372,8 @@ SXE_METHOD(xpath) add_next_index_zval(return_value, &value); } } + } else { + ZVAL_EMPTY_ARRAY(return_value); } xmlXPathFreeObject(retval); diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index 3dd5b0656f..46e627102b 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -637,9 +637,10 @@ SPL_METHOD(SplFixedArray, toArray) intern = Z_SPLFIXEDARRAY_P(getThis()); - array_init(return_value); if (intern->array.size > 0) { int i = 0; + + array_init(return_value); for (; i < intern->array.size; i++) { if (!Z_ISUNDEF(intern->array.elements[i])) { zend_hash_index_update(Z_ARRVAL_P(return_value), i, &intern->array.elements[i]); @@ -650,6 +651,8 @@ SPL_METHOD(SplFixedArray, toArray) zend_hash_index_update(Z_ARRVAL_P(return_value), i, &EG(uninitialized_zval)); } } + } else { + ZVAL_EMPTY_ARRAY(return_value); } } /* }}} */ diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c index cdd17bd159..1b8f8e6e5f 100644 --- a/ext/sqlite3/sqlite3.c +++ b/ext/sqlite3/sqlite3.c @@ -676,7 +676,7 @@ PHP_METHOD(sqlite3, querySingle) if (!entire_row) { RETVAL_NULL(); } else { - array_init(return_value); + ZVAL_EMPTY_ARRAY(return_value); } break; } diff --git a/ext/standard/array.c b/ext/standard/array.c index 3d4c153f12..2a0053ee8b 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -2689,7 +2689,7 @@ PHP_FUNCTION(array_fill) } } } else if (EXPECTED(num == 0)) { - array_init(return_value); + ZVAL_EMPTY_ARRAY(return_value); return; } else { php_error_docref(NULL, E_WARNING, "Number of elements can't be negative"); @@ -3545,7 +3545,7 @@ PHP_FUNCTION(array_slice) /* Clamp the offset.. */ if (offset > num_in) { - array_init(return_value); + ZVAL_EMPTY_ARRAY(return_value); return; } else if (offset < 0 && (offset = (num_in + offset)) < 0) { offset = 0; @@ -3559,7 +3559,7 @@ PHP_FUNCTION(array_slice) } if (length <= 0) { - array_init(return_value); + ZVAL_EMPTY_ARRAY(return_value); return; } @@ -6316,12 +6316,12 @@ PHP_FUNCTION(array_combine) RETURN_FALSE; } - array_init_size(return_value, num_keys); - if (!num_keys) { + ZVAL_EMPTY_ARRAY(return_value); return; } + array_init_size(return_value, num_keys); ZEND_HASH_FOREACH_VAL(keys, entry_keys) { while (1) { if (pos_values >= values->nNumUsed) { diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index b32379a064..d798b589fe 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -704,7 +704,7 @@ yy2: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy88; yy3: -#line 1036 "ext/standard/var_unserializer.re" +#line 1039 "ext/standard/var_unserializer.re" { return 0; } #line 710 "ext/standard/var_unserializer.c" yy4: @@ -749,7 +749,7 @@ yy13: goto yy3; yy14: ++YYCURSOR; -#line 1030 "ext/standard/var_unserializer.re" +#line 1033 "ext/standard/var_unserializer.re" { /* this is the case where we have less data than planned */ php_error_docref(NULL, E_NOTICE, "Unexpected end of serialized data"); @@ -779,7 +779,7 @@ yy19: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 878 "ext/standard/var_unserializer.re" +#line 881 "ext/standard/var_unserializer.re" { size_t len, len2, len3, maxlen; zend_long elements; @@ -946,7 +946,7 @@ yy25: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 867 "ext/standard/var_unserializer.re" +#line 870 "ext/standard/var_unserializer.re" { zend_long elements; if (!var_hash) return 0; @@ -983,11 +983,14 @@ yy31: return 0; } - array_init_size(rval, elements); if (elements) { + array_init_size(rval, elements); /* we can't convert from packed to hash during unserialization, because reference to some zvals might be keept in var_hash (to support references) */ zend_hash_real_init(Z_ARRVAL_P(rval), 0); + } else { + ZVAL_EMPTY_ARRAY(rval); + return finish_nested_data(UNSERIALIZE_PASSTHRU); } /* The array may contain references to itself, in which case we'll be modifying an @@ -1002,7 +1005,7 @@ yy31: return finish_nested_data(UNSERIALIZE_PASSTHRU); } -#line 1006 "ext/standard/var_unserializer.c" +#line 1009 "ext/standard/var_unserializer.c" yy36: yych = *++YYCURSOR; if (yych <= '/') goto yy18; @@ -1051,7 +1054,7 @@ yy37: ZVAL_STR(rval, str); return 1; } -#line 1055 "ext/standard/var_unserializer.c" +#line 1058 "ext/standard/var_unserializer.c" yy42: yych = *++YYCURSOR; if (yych <= '/') goto yy18; @@ -1104,7 +1107,7 @@ yy43: } return 1; } -#line 1108 "ext/standard/var_unserializer.c" +#line 1111 "ext/standard/var_unserializer.c" yy48: yych = *++YYCURSOR; if (yych <= '/') { @@ -1201,7 +1204,7 @@ use_double: ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL)); return 1; } -#line 1205 "ext/standard/var_unserializer.c" +#line 1208 "ext/standard/var_unserializer.c" yy60: yych = *++YYCURSOR; if (yych <= ',') { @@ -1265,7 +1268,7 @@ yy67: return 1; } -#line 1269 "ext/standard/var_unserializer.c" +#line 1272 "ext/standard/var_unserializer.c" yy70: yych = *++YYCURSOR; if (yych == 'N') goto yy67; @@ -1318,7 +1321,7 @@ yy73: ZVAL_LONG(rval, parse_iv(start + 2)); return 1; } -#line 1322 "ext/standard/var_unserializer.c" +#line 1325 "ext/standard/var_unserializer.c" yy77: yych = *++YYCURSOR; if (yych <= '/') goto yy18; @@ -1332,7 +1335,7 @@ yy77: ZVAL_BOOL(rval, parse_iv(start + 2)); return 1; } -#line 1336 "ext/standard/var_unserializer.c" +#line 1339 "ext/standard/var_unserializer.c" yy81: ++YYCURSOR; #line 702 "ext/standard/var_unserializer.re" @@ -1341,7 +1344,7 @@ yy81: ZVAL_NULL(rval); return 1; } -#line 1345 "ext/standard/var_unserializer.c" +#line 1348 "ext/standard/var_unserializer.c" yy83: yych = *++YYCURSOR; if (yych <= '/') goto yy18; @@ -1379,7 +1382,7 @@ yy84: return 1; } -#line 1383 "ext/standard/var_unserializer.c" +#line 1386 "ext/standard/var_unserializer.c" yy88: yych = *++YYCURSOR; if (yych <= '/') goto yy18; @@ -1417,9 +1420,9 @@ yy89: return 1; } -#line 1421 "ext/standard/var_unserializer.c" +#line 1424 "ext/standard/var_unserializer.c" } -#line 1038 "ext/standard/var_unserializer.re" +#line 1041 "ext/standard/var_unserializer.re" return 0; diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index 912d7be4c8..3cf82b1e7a 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -844,11 +844,14 @@ use_double: return 0; } - array_init_size(rval, elements); if (elements) { + array_init_size(rval, elements); /* we can't convert from packed to hash during unserialization, because reference to some zvals might be keept in var_hash (to support references) */ zend_hash_real_init(Z_ARRVAL_P(rval), 0); + } else { + ZVAL_EMPTY_ARRAY(rval); + return finish_nested_data(UNSERIALIZE_PASSTHRU); } /* The array may contain references to itself, in which case we'll be modifying an diff --git a/ext/xsl/xsltprocessor.c b/ext/xsl/xsltprocessor.c index 02c436e340..6fda147b5c 100644 --- a/ext/xsl/xsltprocessor.c +++ b/ext/xsl/xsltprocessor.c @@ -252,8 +252,8 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t } else if (type == 2) { int j; dom_object *domintern = (dom_object *)intern->doc; - array_init(&args[i]); if (obj->nodesetval && obj->nodesetval->nodeNr > 0) { + array_init(&args[i]); for (j = 0; j < obj->nodesetval->nodeNr; j++) { xmlNodePtr node = obj->nodesetval->nodeTab[j]; zval child; @@ -282,6 +282,8 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t php_dom_create_object(node, &child, domintern); add_next_index_zval(&args[i], &child); } + } else { + ZVAL_EMPTY_ARRAY(&args[i]); } } break; -- 2.40.0