diff --git a/NEWS b/NEWS index f22f5b47017e7..d688ef5aad399 100644 --- a/NEWS +++ b/NEWS @@ -146,6 +146,8 @@ PHP NEWS (ndossche) . Add array size maximum to array_diff(). (ndossche) . Add enum SortDirection. (timwolla) + . pathinfo() raises a ValueError with an invalid $flags argument. + (David Carlier) - Streams: . Added so_keepalive, tcp_keepidle, tcp_keepintvl and tcp_keepcnt stream diff --git a/UPGRADING b/UPGRADING index 18f34eca1984f..a97ad00061a27 100644 --- a/UPGRADING +++ b/UPGRADING @@ -131,6 +131,10 @@ PHP 8.6 UPGRADE NOTES when not null, and on failure, gives the error code (one of the EAI_* constants). +- Standard: + . pathinfo() now raises a ValueError when an invalid $flag argument + value is passed. + - Zip: . ZipArchive::extractTo now raises a TypeError for the files argument if one or more of the entries is not diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 7667214861202..176dc40b05f11 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2971,7 +2971,6 @@ static zend_op *zend_compile_simple_var_no_cv(znode *result, const zend_ast *ast opline->extended_value = ZEND_FETCH_GLOBAL; } else { - // TODO: Have a test case for this? if (name_node.op_type == IS_CONST && type == BP_VAR_R && zend_string_equals_literal(Z_STR(name_node.u.constant), "http_response_header")) { @@ -7472,15 +7471,15 @@ static void zend_are_intersection_types_redundant(const zend_type left_type, con unsigned int sum = 0; const zend_type *outer_type; - ZEND_TYPE_LIST_FOREACH(smaller_type_list, outer_type) + ZEND_TYPE_LIST_FOREACH(smaller_type_list, outer_type) { const zend_type *inner_type; - ZEND_TYPE_LIST_FOREACH(larger_type_list, inner_type) + ZEND_TYPE_LIST_FOREACH(larger_type_list, inner_type) { if (zend_string_equals_ci(ZEND_TYPE_NAME(*inner_type), ZEND_TYPE_NAME(*outer_type))) { sum++; break; } - ZEND_TYPE_LIST_FOREACH_END(); - ZEND_TYPE_LIST_FOREACH_END(); + } ZEND_TYPE_LIST_FOREACH_END(); + } ZEND_TYPE_LIST_FOREACH_END(); if (sum == smaller_type_list->num_types) { zend_string *smaller_type_str; @@ -7508,14 +7507,14 @@ static void zend_is_intersection_type_redundant_by_single_type(const zend_type i ZEND_ASSERT(!ZEND_TYPE_IS_INTERSECTION(single_type)); const zend_type *single_intersection_type = NULL; - ZEND_TYPE_FOREACH(intersection_type, single_intersection_type) + ZEND_TYPE_FOREACH(intersection_type, single_intersection_type) { if (zend_string_equals_ci(ZEND_TYPE_NAME(*single_intersection_type), ZEND_TYPE_NAME(single_type))) { zend_string *single_type_str = zend_type_to_string(single_type); zend_string *complete_type = zend_type_to_string(intersection_type); zend_error_noreturn(E_COMPILE_ERROR, "Type %s is redundant as it is more restrictive than type %s", ZSTR_VAL(complete_type), ZSTR_VAL(single_type_str)); } - ZEND_TYPE_FOREACH_END(); + } ZEND_TYPE_FOREACH_END(); } /* Used by both intersection and union types prior to transforming the type list to a full zend_type */ @@ -8465,7 +8464,7 @@ static void compile_implicit_lexical_binds( op_array->static_variables = zend_new_array(8); } - ZEND_HASH_MAP_FOREACH_STR_KEY(&info->uses, var_name) + ZEND_HASH_MAP_FOREACH_STR_KEY(&info->uses, var_name) { zval *value = zend_hash_add( op_array->static_variables, var_name, &EG(uninitialized_zval)); uint32_t offset = (uint32_t)((char*)value - (char*)op_array->static_variables->arData); @@ -8474,7 +8473,7 @@ static void compile_implicit_lexical_binds( opline->op2_type = IS_CV; opline->op2.var = lookup_cv(var_name); opline->extended_value = offset | ZEND_BIND_IMPLICIT; - ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); } static void zend_compile_closure_uses(zend_ast *ast) /* {{{ */ @@ -8514,11 +8513,11 @@ static void zend_compile_closure_uses(zend_ast *ast) /* {{{ */ static void zend_compile_implicit_closure_uses(const closure_info *info) { zend_string *var_name; - ZEND_HASH_MAP_FOREACH_STR_KEY(&info->uses, var_name) + ZEND_HASH_MAP_FOREACH_STR_KEY(&info->uses, var_name) { zval zv; ZVAL_NULL(&zv); zend_compile_static_var_common(var_name, &zv, ZEND_BIND_IMPLICIT); - ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); } static void add_stringable_interface(zend_class_entry *ce) { diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 1a79bc1ba9969..66849c09cacc5 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -1025,8 +1025,10 @@ zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_ if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, fci->retval)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, fci->retval); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(fci->retval) : !Z_ISREF_P(fci->retval)); } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 9cffc64a0ff53..9d0f0f398b54d 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4154,8 +4154,10 @@ ZEND_VM_HOT_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL,OBSERVER)) if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); @@ -4283,8 +4285,10 @@ ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL,OBSERVER)) if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); @@ -4412,8 +4416,10 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL,OBSERVER)) if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); @@ -9119,8 +9125,10 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY, SPEC(OBSERVER)) if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 7359bcb793f23..2bfb82f421ebd 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1322,8 +1322,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_D if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); @@ -1388,8 +1390,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_D if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); @@ -1454,8 +1458,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); @@ -1636,8 +1642,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_D if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); @@ -1750,8 +1758,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_D if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); @@ -1863,8 +1873,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); @@ -1995,8 +2007,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_D if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); @@ -2126,8 +2140,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_D if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); @@ -2254,8 +2270,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); @@ -3639,8 +3657,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CALL_TRAMPOLI if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); @@ -3783,8 +3803,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CALL_TRAMPOLI if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); @@ -54046,8 +54068,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_ICA if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); @@ -54112,8 +54136,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_ICA if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); @@ -54178,8 +54204,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_IC if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); @@ -54360,8 +54388,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_FCA if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); @@ -54474,8 +54504,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_FCA if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); @@ -54587,8 +54619,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_FC if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); @@ -54719,8 +54753,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_FCA if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); @@ -54850,8 +54886,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_FCA if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); @@ -54978,8 +55016,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_FC if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); @@ -56247,8 +56287,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CALL_TRAMPOLINE_SP if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); @@ -56391,8 +56433,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CALL_TRAMPOLINE_SP if (should_throw) { zend_internal_call_arginfo_violation(call->func); } - ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + bool result = zend_verify_internal_return_type(call->func, ret); + ZEND_ASSERT(result); + } ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); zend_verify_internal_func_info(call->func, ret); diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c index 1daa51851fb66..6c219d376e53a 100644 --- a/ext/snmp/snmp.c +++ b/ext/snmp/snmp.c @@ -655,7 +655,8 @@ static void php_free_objid_query(struct objid_query *objid_query, HashTable* oid */ static bool php_snmp_parse_oid( zval *object, int st, struct objid_query *objid_query, zend_string *oid_str, HashTable *oid_ht, - zend_string *type_str, HashTable *type_ht, zend_string *value_str, HashTable *value_ht + zend_string *type_str, HashTable *type_ht, zend_string *value_str, HashTable *value_ht, + uint32_t oid_argument_offset, uint32_t type_argument_offset, uint32_t value_argument_offset ) { char *pptr; uint32_t idx_type = 0, idx_value = 0; @@ -682,7 +683,7 @@ static bool php_snmp_parse_oid( ZEND_ASSERT(type_str && value_str); if (ZSTR_LEN(type_str) != 1) { - zend_value_error("Type must be a single character"); + zend_argument_value_error(type_argument_offset, "must be a single character"); efree(objid_query->vars); return false; } @@ -693,7 +694,7 @@ static bool php_snmp_parse_oid( objid_query->count++; } else if (oid_ht) { /* we got objid array */ if (zend_hash_num_elements(oid_ht) == 0) { - zend_value_error("Array of object IDs must not be empty"); + zend_argument_value_error(oid_argument_offset, "must not be empty when passed as an array"); return false; } objid_query->vars = (snmpobjarg *)safe_emalloc(sizeof(snmpobjarg), zend_hash_num_elements(oid_ht), 0); @@ -738,14 +739,14 @@ static bool php_snmp_parse_oid( char ptype = *ZSTR_VAL(type); zend_string_release(type); if (len != 1) { - zend_value_error("Type must be a single character"); + zend_argument_value_error(type_argument_offset, "must be a single character"); php_free_objid_query(objid_query, oid_ht, value_ht, st); return false; } objid_query->vars[objid_query->count].type = ptype; idx_type++; } else { - php_error_docref(NULL, E_WARNING, "'%s': no type set", ZSTR_VAL(tmp)); + zend_argument_value_error(type_argument_offset, "must contain a type for object ID '%s'", ZSTR_VAL(tmp)); php_free_objid_query(objid_query, oid_ht, value_ht, st); return false; } @@ -780,7 +781,7 @@ static bool php_snmp_parse_oid( objid_query->vars[objid_query->count].value = ZSTR_VAL(tmp); idx_value++; } else { - php_error_docref(NULL, E_WARNING, "'%s': no value set", ZSTR_VAL(tmp)); + zend_argument_value_error(value_argument_offset, "must contain a value for object ID '%s'", ZSTR_VAL(tmp)); php_free_objid_query(objid_query, oid_ht, value_ht, st); return false; } @@ -827,7 +828,7 @@ static bool php_snmp_parse_oid( /* {{{ snmp_session_init allocates memory for session and session->peername, caller should free it manually using snmp_session_free() and efree() */ -static bool snmp_session_init(php_snmp_session **session_p, int version, zend_string *hostname, zend_string *community, zend_long timeout, zend_long retries, int timeout_argument_offset) +static bool snmp_session_init(php_snmp_session **session_p, int version, zend_string *hostname, zend_string *community, zend_long timeout, zend_long retries, int hostname_argument_offset, int timeout_argument_offset) { php_snmp_session *session; char *pptr, *host_ptr; @@ -841,23 +842,13 @@ static bool snmp_session_init(php_snmp_session **session_p, int version, zend_st ZEND_ASSERT(hostname != NULL); ZEND_ASSERT(community != NULL); - if (zend_str_has_nul_byte(hostname)) { - zend_argument_value_error(2, "must not contain any null bytes"); - return false; - } - if (ZSTR_LEN(hostname) >= MAX_NAME_LEN) { - zend_argument_value_error(2, "length must be lower than %d", MAX_NAME_LEN); - return false; - } - - if (zend_str_has_nul_byte(community)) { - zend_argument_value_error(3, "must not contain any null bytes"); + zend_argument_value_error(hostname_argument_offset, "length must be lower than %d", MAX_NAME_LEN); return false; } if (ZSTR_LEN(community) == 0) { - zend_argument_must_not_be_empty_error(3); + zend_argument_must_not_be_empty_error(hostname_argument_offset + 1); return false; } @@ -899,14 +890,14 @@ static bool snmp_session_init(php_snmp_session **session_p, int version, zend_st char *pport = pptr + 2; tmp_port = atoi(pport); if (tmp_port < 0 || tmp_port > USHRT_MAX) { - zend_argument_value_error(2, "remote port must be between 0 and %u", USHRT_MAX); + zend_argument_value_error(hostname_argument_offset, "remote port must be between 0 and %u", USHRT_MAX); return false; } remote_port = (unsigned short)tmp_port; } *pptr = '\0'; } else { - php_error_docref(NULL, E_WARNING, "Malformed IPv6 address, closing square bracket missing"); + zend_argument_value_error(hostname_argument_offset, "has a malformed IPv6 address, closing square bracket missing"); return false; } } else { /* IPv4 address */ @@ -914,7 +905,7 @@ static bool snmp_session_init(php_snmp_session **session_p, int version, zend_st char *pport = pptr + 1; tmp_port = atoi(pport); if (tmp_port < 0 || tmp_port > USHRT_MAX) { - zend_argument_value_error(2, "remote port must be between 0 and %u", USHRT_MAX); + zend_argument_value_error(hostname_argument_offset, "remote port must be between 0 and %u", USHRT_MAX); return false; } remote_port = (unsigned short)tmp_port; @@ -1123,14 +1114,13 @@ static ZEND_ATTRIBUTE_NONNULL bool snmp_session_gen_sec_key(struct snmp_session /* }}} */ /* {{{ Set context Engine Id in the snmpv3 session */ -static bool snmp_session_set_contextEngineID(struct snmp_session *s, zend_string * contextEngineID) +static bool snmp_session_set_contextEngineID(struct snmp_session *s, zend_string * contextEngineID, uint32_t contextEngineID_argument_offset) { size_t ebuf_len = 32, eout_len = 0; uint8_t *ebuf = (uint8_t *) emalloc(ebuf_len); if (!snmp_hex_to_binary(&ebuf, &ebuf_len, &eout_len, 1, ZSTR_VAL(contextEngineID))) { - // TODO Promote to Error? - php_error_docref(NULL, E_WARNING, "Bad engine ID value '%s'", ZSTR_VAL(contextEngineID)); + zend_argument_value_error(contextEngineID_argument_offset, "must be a valid context engine ID"); efree(ebuf); return false; } @@ -1145,11 +1135,14 @@ static bool snmp_session_set_contextEngineID(struct snmp_session *s, zend_string } /* }}} */ -/* {{{ Set all snmpv3-related security options */ +/* {{{ Set all snmpv3-related security options + * auth_protocol_argnum and contextEngineID_argument_offset are the userland + * argument numbers used for error reporting. + */ static ZEND_ATTRIBUTE_NONNULL_ARGS(2) bool snmp_session_set_security(struct snmp_session *session, zend_string *sec_level, zend_string *auth_protocol, zend_string *auth_passphrase, zend_string *priv_protocol, zend_string *priv_passphrase, zend_string *contextName, zend_string *contextEngineID, - uint32_t auth_protocol_argnum) + uint32_t auth_protocol_argnum, uint32_t contextEngineID_argument_offset) { /* Setting the security level. */ @@ -1215,7 +1208,7 @@ static ZEND_ATTRIBUTE_NONNULL_ARGS(2) bool snmp_session_set_security(struct snmp } /* Setting contextEngineIS if specified */ - if (contextEngineID && ZSTR_LEN(contextEngineID) && !snmp_session_set_contextEngineID(session, contextEngineID)) { + if (contextEngineID && ZSTR_LEN(contextEngineID) && !snmp_session_set_contextEngineID(session, contextEngineID, contextEngineID_argument_offset)) { /* Warning message sent already, just bail out */ return false; } @@ -1243,6 +1236,7 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version) php_snmp_session *session; int session_less_mode = (getThis() == NULL); int timeout_argument_offset = -1; + uint32_t oid_argument_offset = 1, type_argument_offset = 0, value_argument_offset = 0; php_snmp_object *snmp_object; php_snmp_object glob_snmp_object; @@ -1255,8 +1249,8 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version) if (version == SNMP_VERSION_3) { if (st & SNMP_CMD_SET) { ZEND_PARSE_PARAMETERS_START(10, 12) - Z_PARAM_STR(a1) - Z_PARAM_STR(a2) + Z_PARAM_PATH_STR(a1) + Z_PARAM_PATH_STR(a2) Z_PARAM_STR(a3) Z_PARAM_STR(a4) Z_PARAM_STR(a5) @@ -1271,14 +1265,17 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version) ZEND_PARSE_PARAMETERS_END(); timeout_argument_offset = 10; + oid_argument_offset = 8; + type_argument_offset = 9; + value_argument_offset = 10; } else { /* SNMP_CMD_GET * SNMP_CMD_GETNEXT * SNMP_CMD_WALK */ ZEND_PARSE_PARAMETERS_START(8, 10) - Z_PARAM_STR(a1) - Z_PARAM_STR(a2) + Z_PARAM_PATH_STR(a1) + Z_PARAM_PATH_STR(a2) Z_PARAM_STR(a3) Z_PARAM_STR(a4) Z_PARAM_STR(a5) @@ -1291,12 +1288,13 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version) ZEND_PARSE_PARAMETERS_END(); timeout_argument_offset = 9; + oid_argument_offset = 8; } } else { if (st & SNMP_CMD_SET) { ZEND_PARSE_PARAMETERS_START(5, 7) - Z_PARAM_STR(a1) - Z_PARAM_STR(a2) + Z_PARAM_PATH_STR(a1) + Z_PARAM_PATH_STR(a2) Z_PARAM_ARRAY_HT_OR_STR(oid_ht, oid_str) Z_PARAM_ARRAY_HT_OR_STR(type_ht, type_str) Z_PARAM_ARRAY_HT_OR_STR(value_ht, value_str) @@ -1306,14 +1304,17 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version) ZEND_PARSE_PARAMETERS_END(); timeout_argument_offset = 6; + oid_argument_offset = 3; + type_argument_offset = 4; + value_argument_offset = 5; } else { /* SNMP_CMD_GET * SNMP_CMD_GETNEXT * SNMP_CMD_WALK */ ZEND_PARSE_PARAMETERS_START(3, 5) - Z_PARAM_STR(a1) - Z_PARAM_STR(a2) + Z_PARAM_PATH_STR(a1) + Z_PARAM_PATH_STR(a2) Z_PARAM_ARRAY_HT_OR_STR(oid_ht, oid_str) Z_PARAM_OPTIONAL Z_PARAM_LONG(timeout) @@ -1321,6 +1322,7 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version) ZEND_PARSE_PARAMETERS_END(); timeout_argument_offset = 4; + oid_argument_offset = 3; } } } else { @@ -1330,6 +1332,8 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version) Z_PARAM_ARRAY_HT_OR_STR(type_ht, type_str) Z_PARAM_ARRAY_HT_OR_STR(value_ht, value_str) ZEND_PARSE_PARAMETERS_END(); + type_argument_offset = 2; + value_argument_offset = 3; } else if (st & SNMP_CMD_WALK) { ZEND_PARSE_PARAMETERS_START(1, 4) Z_PARAM_ARRAY_HT_OR_STR(oid_ht, oid_str) @@ -1359,20 +1363,21 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version) } } - if (!php_snmp_parse_oid(getThis(), st, &objid_query, oid_str, oid_ht, type_str, type_ht, value_str, value_ht)) { + if (!php_snmp_parse_oid(getThis(), st, &objid_query, oid_str, oid_ht, type_str, type_ht, value_str, value_ht, + oid_argument_offset, type_argument_offset, value_argument_offset)) { RETURN_FALSE; } if (session_less_mode) { - if (!snmp_session_init(&session, version, a1, a2, timeout, retries, timeout_argument_offset)) { + if (!snmp_session_init(&session, version, a1, a2, timeout, retries, 1, timeout_argument_offset)) { php_free_objid_query(&objid_query, oid_ht, value_ht, st); snmp_session_free(&session); RETURN_FALSE; } - if (version == SNMP_VERSION_3 && !snmp_session_set_security(session, a3, a4, a5, a6, a7, NULL, NULL, 4)) { + if (version == SNMP_VERSION_3 && !snmp_session_set_security(session, a3, a4, a5, a6, a7, NULL, NULL, 4, 0)) { php_free_objid_query(&objid_query, oid_ht, value_ht, st); snmp_session_free(&session); - /* Warning message sent already, just bail out */ + /* An error has already been emitted, just bail out. */ RETURN_FALSE; } } else { @@ -1645,7 +1650,7 @@ PHP_METHOD(SNMP, __construct) snmp_object = Z_SNMP_P(object); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "lSS|ll", &version, &a1, &a2, &timeout, &retries) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "lPP|ll", &version, &a1, &a2, &timeout, &retries) == FAILURE) { RETURN_THROWS(); } @@ -1664,7 +1669,7 @@ PHP_METHOD(SNMP, __construct) snmp_session_free(&(snmp_object->session)); } - if (!snmp_session_init(&(snmp_object->session), version, a1, a2, timeout, retries, 4)) { + if (!snmp_session_init(&(snmp_object->session), version, a1, a2, timeout, retries, 2, 4)) { return; } snmp_object->max_oids = 0; @@ -1738,8 +1743,9 @@ PHP_METHOD(SNMP, setSecurity) RETURN_THROWS(); } - if (!snmp_session_set_security(snmp_object->session, a1, a2, a3, a4, a5, a6, a7, 2)) { - /* Warning message sent already, just bail out */ + /* authProtocol is argument #2 and contextEngineId is argument #7. */ + if (!snmp_session_set_security(snmp_object->session, a1, a2, a3, a4, a5, a6, a7, 2, 7)) { + /* An error has already been emitted, just bail out. */ RETURN_FALSE; } RETURN_TRUE; diff --git a/ext/snmp/tests/gh16959.phpt b/ext/snmp/tests/gh16959.phpt index cabe0eb84b6cb..f76fa61e1f731 100644 --- a/ext/snmp/tests/gh16959.phpt +++ b/ext/snmp/tests/gh16959.phpt @@ -66,5 +66,5 @@ array(4) { } Object of class stdClass could not be converted to string Object of class stdClass could not be converted to string -Type must be a single character -Type must be a single character +snmp2_set(): Argument #4 ($type) must be a single character +snmp2_set(): Argument #4 ($type) must be a single character diff --git a/ext/snmp/tests/ipv6.phpt b/ext/snmp/tests/ipv6.phpt index c305fb15d4b8c..93274fd7054f1 100644 --- a/ext/snmp/tests/ipv6.phpt +++ b/ext/snmp/tests/ipv6.phpt @@ -22,10 +22,12 @@ snmp_set_quick_print(false); snmp_set_valueretrieval(SNMP_VALUE_PLAIN); var_dump(snmpget($hostname6_port, $community, '.1.3.6.1.2.1.1.1.0')); -var_dump(snmpget('[dead:beef::', $community, '.1.3.6.1.2.1.1.1.0')); +try { + var_dump(snmpget('[dead:beef::', $community, '.1.3.6.1.2.1.1.1.0')); +} catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; +} ?> --EXPECTF-- string(%d) "%s" - -Warning: snmpget(): Malformed IPv6 address, closing square bracket missing in %s on line %d -bool(false) +snmpget(): Argument #1 ($hostname) has a malformed IPv6 address, closing square bracket missing diff --git a/ext/snmp/tests/snmp-object-setSecurity_error.phpt b/ext/snmp/tests/snmp-object-setSecurity_error.phpt index cf4f928837773..576ec8380804f 100644 --- a/ext/snmp/tests/snmp-object-setSecurity_error.phpt +++ b/ext/snmp/tests/snmp-object-setSecurity_error.phpt @@ -53,7 +53,11 @@ try { var_dump($session->setSecurity('authPriv', 'MD5', $auth_pass, 'AES', '')); var_dump($session->setSecurity('authPriv', 'MD5', $auth_pass, 'AES', 'ty')); -var_dump($session->setSecurity('authPriv', 'MD5', $auth_pass, 'AES', 'test12345', 'context', 'dsa')); +try { + var_dump($session->setSecurity('authPriv', 'MD5', $auth_pass, 'AES', 'test12345', 'context', 'dsa')); +} catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; +} var_dump($session->close()); @@ -76,7 +80,5 @@ bool(false) Warning: SNMP::setSecurity(): Error generating a key for privacy pass phrase 'ty': Generic error (The supplied password length is too short.) in %s on line %d bool(false) - -Warning: SNMP::setSecurity(): Bad engine ID value 'dsa' in %s on line %d -bool(false) +SNMP::setSecurity(): Argument #7 ($contextEngineId) must be a valid context engine ID bool(true) diff --git a/ext/snmp/tests/snmp2_get.phpt b/ext/snmp/tests/snmp2_get.phpt index 30500eb5ca9b3..e2cd1ef1b459b 100644 --- a/ext/snmp/tests/snmp2_get.phpt +++ b/ext/snmp/tests/snmp2_get.phpt @@ -54,7 +54,7 @@ var_dump(snmp2_get($hostname, $community, array('.1.3.6.1.2.1.1.1.0', '.1.3.6.1. --EXPECTF-- Checking error handling Empty OID array -Array of object IDs must not be empty +snmp2_get(): Argument #3 ($object_id) must not be empty when passed as an array Checking working Single OID string(%d) "%s" diff --git a/ext/snmp/tests/snmp2_set.phpt b/ext/snmp/tests/snmp2_set.phpt index 11b1d94419f50..da94fe21f498b 100644 --- a/ext/snmp/tests/snmp2_set.phpt +++ b/ext/snmp/tests/snmp2_set.phpt @@ -128,14 +128,22 @@ var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $ol var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2)); echo "Multiple OID, single type in array, multiple value\n"; -$z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2), array('s'), array($newvalue1, $newvalue2), $timeout, $retries); -var_dump($z); +try { + $z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2), array('s'), array($newvalue1, $newvalue2), $timeout, $retries); + var_dump($z); +} catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; +} var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1)); var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2)); echo "Multiple OID & type, single value in array\n"; -$z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2), array('s', 's'), array($newvalue1), $timeout, $retries); -var_dump($z); +try { + $z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2), array('s', 's'), array($newvalue1), $timeout, $retries); + var_dump($z); +} catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; +} var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1)); var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2)); @@ -167,7 +175,7 @@ var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $ol --EXPECTF-- Check error handing No type & no value (timeout & retries instead) -Type must be a single character +snmp2_set(): Argument #4 ($type) must be a single character No value (timeout instead), retries instead of timeout Warning: snmp2_set(): Could not add variable: OID='%s' type='q' value='%i': Bad variable type ("q") in %s on line %d @@ -216,23 +224,19 @@ Value must be of type string when object ID is a string bool(true) bool(true) Multiple OID, 1st wrong type -Type must be a single character +snmp2_set(): Argument #4 ($type) must be a single character bool(true) bool(true) Multiple OID, 2nd wrong type -Type must be a single character +snmp2_set(): Argument #4 ($type) must be a single character bool(true) bool(true) Multiple OID, single type in array, multiple value - -Warning: snmp2_set(): '%s': no type set in %s on line %d -bool(false) +snmp2_set(): Argument #4 ($type) must contain a type for object ID 'SNMPv2-MIB::sysLocation.0' bool(true) bool(true) Multiple OID & type, single value in array - -Warning: snmp2_set(): '%s': no value set in %s on line %d -bool(false) +snmp2_set(): Argument #5 ($value) must contain a value for object ID 'SNMPv2-MIB::sysLocation.0' bool(true) bool(true) Multiple OID, 1st bogus, single type, multiple value diff --git a/ext/snmp/tests/snmpset.phpt b/ext/snmp/tests/snmpset.phpt index ca935cecf5ec3..a4f89e78da933 100644 --- a/ext/snmp/tests/snmpset.phpt +++ b/ext/snmp/tests/snmpset.phpt @@ -122,14 +122,22 @@ var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $ol var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2)); echo "Multiple OID, single type in array, multiple value\n"; -$z = snmpset($hostname, $communityWrite, array($oid1, $oid2), array('s'), array($newvalue1, $newvalue2), $timeout, $retries); -var_dump($z); +try { + $z = snmpset($hostname, $communityWrite, array($oid1, $oid2), array('s'), array($newvalue1, $newvalue2), $timeout, $retries); + var_dump($z); +} catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; +} var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1)); var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2)); echo "Multiple OID & type, single value in array\n"; -$z = snmpset($hostname, $communityWrite, array($oid1, $oid2), array('s', 's'), array($newvalue1), $timeout, $retries); -var_dump($z); +try { + $z = snmpset($hostname, $communityWrite, array($oid1, $oid2), array('s', 's'), array($newvalue1), $timeout, $retries); + var_dump($z); +} catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; +} var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1)); var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2)); @@ -161,7 +169,7 @@ var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $ol --EXPECTF-- Check error handing No type & no value (timeout & retries instead) -Type must be a single character +snmpset(): Argument #4 ($type) must be a single character No value (timeout instead), retries instead of timeout Warning: snmpset(): Could not add variable: OID='%s' type='q' value='%i': Bad variable type ("q") in %s on line %d @@ -207,23 +215,19 @@ Value must be of type string when object ID is a string bool(true) bool(true) Multiple OID, 1st wrong type -Type must be a single character +snmpset(): Argument #4 ($type) must be a single character bool(true) bool(true) Multiple OID, 2nd wrong type -Type must be a single character +snmpset(): Argument #4 ($type) must be a single character bool(true) bool(true) Multiple OID, single type in array, multiple value - -Warning: snmpset(): '%s': no type set in %s on line %d -bool(false) +snmpset(): Argument #4 ($type) must contain a type for object ID 'SNMPv2-MIB::sysLocation.0' bool(true) bool(true) Multiple OID & type, single value in array - -Warning: snmpset(): '%s': no value set in %s on line %d -bool(false) +snmpset(): Argument #5 ($value) must contain a value for object ID 'SNMPv2-MIB::sysLocation.0' bool(true) bool(true) Multiple OID, 1st bogus, single type, multiple value diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c index 68f132069a7c5..45d2eeb5bb67b 100644 --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@ -241,11 +241,25 @@ static zend_result spl_object_storage_detach(spl_SplObjectStorage *intern, zend_ return ret; } /* }}}*/ +/* TODO: make this an official Zend API? */ +#define SPL_SAFE_HASH_FOREACH_PTR(_ht, _ptr) do { \ + const HashTable *__ht = (_ht); \ + zval *_z = __ht->arPacked; \ + for (uint32_t _idx = 0; _idx < __ht->nNumUsed; _idx++, _z = ZEND_HASH_ELEMENT(__ht, _idx)) { \ + if (UNEXPECTED(Z_ISUNDEF_P(_z))) continue; \ + _ptr = Z_PTR_P(_z); + static void spl_object_storage_addall(spl_SplObjectStorage *intern, spl_SplObjectStorage *other) { /* {{{ */ spl_SplObjectStorageElement *element; - ZEND_HASH_FOREACH_PTR(&other->storage, element) { - spl_object_storage_attach(intern, element->obj, &element->inf); + SPL_SAFE_HASH_FOREACH_PTR(&other->storage, element) { + zval zv; + zend_object *obj = element->obj; + GC_ADDREF(obj); + ZVAL_COPY(&zv, &element->inf); + spl_object_storage_attach(intern, obj, &zv); + zval_ptr_dtor(&zv); + OBJ_RELEASE(obj); } ZEND_HASH_FOREACH_END(); intern->index = 0; @@ -626,10 +640,13 @@ PHP_METHOD(SplObjectStorage, removeAllExcept) other = Z_SPLOBJSTORAGE_P(obj); - ZEND_HASH_FOREACH_PTR(&intern->storage, element) { - if (!spl_object_storage_contains(other, element->obj)) { - spl_object_storage_detach(intern, element->obj); + SPL_SAFE_HASH_FOREACH_PTR(&intern->storage, element) { + zend_object *elem_obj = element->obj; + GC_ADDREF(elem_obj); + if (!spl_object_storage_contains(other, elem_obj)) { + spl_object_storage_detach(intern, elem_obj); } + OBJ_RELEASE(elem_obj); } ZEND_HASH_FOREACH_END(); zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); diff --git a/ext/spl/tests/SplObjectStorage/concurrent_deletion.phpt b/ext/spl/tests/SplObjectStorage/concurrent_deletion.phpt new file mode 100644 index 0000000000000..ae063f1c9b03a --- /dev/null +++ b/ext/spl/tests/SplObjectStorage/concurrent_deletion.phpt @@ -0,0 +1,46 @@ +--TEST-- +SplObjectStorage: Concurrent deletion during iteration +--CREDITS-- +cnitlrt +--FILE-- +removeAllExcept($other)); + +unset($victim, $other); +$victim = new SplObjectStorage(); +$other = new EvilStorage(); + +for ($i = 0; $i < 1024; $i++) { + $o = new stdClass(); + $victim[$o] = null; + $other[$o] = null; +} + +var_dump($other->addAll($victim)); +?> +--EXPECTF-- +int(%d) +int(1024) diff --git a/ext/spl/tests/SplObjectStorage/concurrent_deletion_addall.phpt b/ext/spl/tests/SplObjectStorage/concurrent_deletion_addall.phpt new file mode 100644 index 0000000000000..af3fc381b5622 --- /dev/null +++ b/ext/spl/tests/SplObjectStorage/concurrent_deletion_addall.phpt @@ -0,0 +1,43 @@ +--TEST-- +SplObjectStorage: Concurrent deletion during addAll +--CREDITS-- +cnitlrt +--FILE-- +addAll($storage); + +var_dump($evil, $storage); + +?> +--EXPECTF-- +object(EvilStorage)#%d (1) { + ["storage":"SplObjectStorage":private]=> + array(1) { + [0]=> + array(2) { + ["obj"]=> + object(stdClass)#%d (0) { + } + ["inf"]=> + string(3) "foo" + } + } +} +object(SplObjectStorage)#%d (1) { + ["storage":"SplObjectStorage":private]=> + array(0) { + } +} diff --git a/ext/spl/tests/SplObjectStorage/concurrent_deletion_removeexcept.phpt b/ext/spl/tests/SplObjectStorage/concurrent_deletion_removeexcept.phpt new file mode 100644 index 0000000000000..b2ed211b304af --- /dev/null +++ b/ext/spl/tests/SplObjectStorage/concurrent_deletion_removeexcept.phpt @@ -0,0 +1,35 @@ +--TEST-- +SplObjectStorage: Concurrent deletion during removeAllExcept +--CREDITS-- +cnitlrt +--FILE-- +removeAllExcept($evil); + +var_dump($evil, $storage); + +?> +--EXPECTF-- +object(EvilStorage)#%d (1) { + ["storage":"SplObjectStorage":private]=> + array(0) { + } +} +object(SplObjectStorage)#%d (1) { + ["storage":"SplObjectStorage":private]=> + array(0) { + } +} diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 04505db15833c..a611433af5374 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -1283,9 +1283,9 @@ static void add_config_entries(HashTable *hash, zval *return_value) /* {{{ */ zend_string *key; zval *zv; - ZEND_HASH_FOREACH_KEY_VAL(hash, h, key, zv) + ZEND_HASH_FOREACH_KEY_VAL(hash, h, key, zv) { add_config_entry(h, key, zv, return_value); - ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); } /* }}} */ diff --git a/ext/standard/string.c b/ext/standard/string.c index e479a9e7612e0..d7f76af633cf9 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1591,6 +1591,16 @@ PHP_FUNCTION(pathinfo) Z_PARAM_LONG(opt) ZEND_PARSE_PARAMETERS_END(); + if (opt < PHP_PATHINFO_DIRNAME || opt > PHP_PATHINFO_ALL) { + zend_argument_value_error(2, "must be one of the PATHINFO_* constants"); + RETURN_THROWS(); + } + + if (opt < PHP_PATHINFO_ALL && (opt & (opt - 1))) { + zend_argument_value_error(2, "must be only one of the PATHINFO_* constants"); + RETURN_THROWS(); + } + have_basename = (opt & PHP_PATHINFO_BASENAME); array_init(&tmp); diff --git a/ext/standard/tests/file/pathinfo_variation3.phpt b/ext/standard/tests/file/pathinfo_variation3.phpt index aa1494b57997f..86f88677d813c 100644 --- a/ext/standard/tests/file/pathinfo_variation3.phpt +++ b/ext/standard/tests/file/pathinfo_variation3.phpt @@ -15,15 +15,37 @@ var_dump(pathinfo($testfile, PATHINFO_BASENAME)); var_dump(pathinfo($testfile, PATHINFO_FILENAME)); var_dump(pathinfo($testfile, PATHINFO_EXTENSION)); var_dump(pathinfo($testfile, PATHINFO_DIRNAME)); -var_dump(pathinfo($testfile, PATHINFO_EXTENSION|PATHINFO_FILENAME|PATHINFO_DIRNAME)); -var_dump(pathinfo($testfile, PATHINFO_EXTENSION|PATHINFO_FILENAME|PATHINFO_BASENAME)); -var_dump(pathinfo($testfile, PATHINFO_EXTENSION|PATHINFO_FILENAME)); -var_dump(pathinfo($testfile, PATHINFO_EXTENSION|PATHINFO_BASENAME)); -var_dump(pathinfo($testfile, PATHINFO_FILENAME|PATHINFO_DIRNAME)); -var_dump(pathinfo($testfile, PATHINFO_FILENAME|PATHINFO_BASENAME)); -var_dump(pathinfo($testfile, PATHINFO_DIRNAME|PATHINFO_EXTENSION)); -var_dump(pathinfo($testfile, PATHINFO_DIRNAME|PATHINFO_BASENAME)); +try { + pathinfo($testfile, PATHINFO_EXTENSION|PATHINFO_FILENAME|PATHINFO_DIRNAME); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} +try { + pathinfo($testfile, PATHINFO_EXTENSION|PATHINFO_FILENAME); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} +try { + pathinfo($testfile, PATHINFO_EXTENSION|PATHINFO_DIRNAME); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} +try { + pathinfo($testfile, PATHINFO_FILENAME|PATHINFO_BASENAME); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} +try { + pathinfo($testfile, PATHINFO_DIRNAME|PATHINFO_EXTENSION); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} +try { + pathinfo($testfile, PATHINFO_DIRNAME|PATHINFO_BASENAME); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} ?> --EXPECTF-- @@ -62,11 +84,9 @@ string(6) "inet.h" string(4) "inet" string(1) "h" string(17) "/usr/include/arpa" -string(17) "/usr/include/arpa" -string(6) "inet.h" -string(1) "h" -string(6) "inet.h" -string(17) "/usr/include/arpa" -string(6) "inet.h" -string(17) "/usr/include/arpa" -string(17) "/usr/include/arpa" +pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants +pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants +pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants +pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants +pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants +pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants diff --git a/ext/standard/tests/http/http_response_header_deprecated_dynamic_fetch.phpt b/ext/standard/tests/http/http_response_header_deprecated_dynamic_fetch.phpt new file mode 100644 index 0000000000000..e6b90355a4c3b --- /dev/null +++ b/ext/standard/tests/http/http_response_header_deprecated_dynamic_fetch.phpt @@ -0,0 +1,16 @@ +--TEST-- +$http_response_header dynamic fetch should warn +--FILE-- + +--EXPECTF-- +Deprecated: The predefined locally scoped $http_response_header variable is deprecated, call http_get_last_response_headers() instead in %s on line %d +string(2) "OK" diff --git a/ext/standard/tests/strings/pathinfo.phpt b/ext/standard/tests/strings/pathinfo.phpt index 2bbea73588cb2..1ff42a66121cc 100644 --- a/ext/standard/tests/strings/pathinfo.phpt +++ b/ext/standard/tests/strings/pathinfo.phpt @@ -14,14 +14,48 @@ var_dump(pathinfo(__FILE__, PATHINFO_BASENAME)); var_dump(pathinfo(__FILE__, PATHINFO_FILENAME)); var_dump(pathinfo(__FILE__, PATHINFO_EXTENSION)); var_dump(pathinfo(__FILE__, PATHINFO_DIRNAME)); -var_dump(pathinfo(__FILE__, PATHINFO_EXTENSION|PATHINFO_FILENAME|PATHINFO_DIRNAME)); -var_dump(pathinfo(__FILE__, PATHINFO_EXTENSION|PATHINFO_FILENAME|PATHINFO_BASENAME)); -var_dump(pathinfo(__FILE__, PATHINFO_EXTENSION|PATHINFO_FILENAME)); -var_dump(pathinfo(__FILE__, PATHINFO_EXTENSION|PATHINFO_BASENAME)); -var_dump(pathinfo(__FILE__, PATHINFO_FILENAME|PATHINFO_DIRNAME)); -var_dump(pathinfo(__FILE__, PATHINFO_FILENAME|PATHINFO_BASENAME)); -var_dump(pathinfo(__FILE__, PATHINFO_DIRNAME|PATHINFO_EXTENSION)); -var_dump(pathinfo(__FILE__, PATHINFO_DIRNAME|PATHINFO_BASENAME)); + +try { + pathinfo(__FILE__, PATHINFO_EXTENSION|PATHINFO_FILENAME|PATHINFO_DIRNAME); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} +try { + pathinfo(__FILE__, PATHINFO_EXTENSION|PATHINFO_FILENAME); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} +try { + pathinfo(__FILE__, PATHINFO_EXTENSION|PATHINFO_DIRNAME); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} +try { + pathinfo(__FILE__, PATHINFO_FILENAME|PATHINFO_BASENAME); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} +try { + pathinfo(__FILE__, PATHINFO_DIRNAME|PATHINFO_EXTENSION); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} +try { + pathinfo(__FILE__, PATHINFO_DIRNAME|PATHINFO_BASENAME); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + pathinfo(__FILE__, PATHINFO_DIRNAME-1); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} +try { + pathinfo(__FILE__, PATHINFO_ALL+1); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} echo "Done\n"; ?> @@ -94,12 +128,12 @@ string(12) "pathinfo.php" string(8) "pathinfo" string(3) "php" string(%d) "%s%estrings" -string(%d) "%s%estrings" -string(12) "pathinfo.php" -string(3) "php" -string(12) "pathinfo.php" -string(%d) "%s%estrings" -string(12) "pathinfo.php" -string(%d) "%s%estrings" -string(%d) "%s%estrings" +pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants +pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants +pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants +pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants +pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants +pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants +pathinfo(): Argument #2 ($flags) must be one of the PATHINFO_* constants +pathinfo(): Argument #2 ($flags) must be one of the PATHINFO_* constants Done diff --git a/sapi/apache2handler/php_functions.c b/sapi/apache2handler/php_functions.c index c2b15af86a601..9427729584197 100644 --- a/sapi/apache2handler/php_functions.c +++ b/sapi/apache2handler/php_functions.c @@ -179,10 +179,10 @@ PHP_FUNCTION(apache_request_headers) ctx = SG(server_context); arr = apr_table_elts(ctx->r->headers_in); - APR_ARRAY_FOREACH_OPEN(arr, key, val) + APR_ARRAY_FOREACH_OPEN(arr, key, val) { if (!val) val = ""; add_assoc_string(return_value, key, val); - APR_ARRAY_FOREACH_CLOSE() + } APR_ARRAY_FOREACH_CLOSE(); } /* }}} */ @@ -200,10 +200,10 @@ PHP_FUNCTION(apache_response_headers) ctx = SG(server_context); arr = apr_table_elts(ctx->r->headers_out); - APR_ARRAY_FOREACH_OPEN(arr, key, val) + APR_ARRAY_FOREACH_OPEN(arr, key, val) { if (!val) val = ""; add_assoc_string(return_value, key, val); - APR_ARRAY_FOREACH_CLOSE() + } APR_ARRAY_FOREACH_CLOSE(); } /* }}} */ @@ -411,12 +411,12 @@ PHP_MINFO_FUNCTION(apache) SECTION("Apache Environment"); php_info_print_table_start(); php_info_print_table_header(2, "Variable", "Value"); - APR_ARRAY_FOREACH_OPEN(arr, key, val) + APR_ARRAY_FOREACH_OPEN(arr, key, val) { if (!val) { val = ""; } php_info_print_table_row(2, key, val); - APR_ARRAY_FOREACH_CLOSE() + } APR_ARRAY_FOREACH_CLOSE(); php_info_print_table_end(); @@ -426,21 +426,21 @@ PHP_MINFO_FUNCTION(apache) php_info_print_table_row(2, "HTTP Request", ((php_struct *) SG(server_context))->r->the_request); arr = apr_table_elts(((php_struct *) SG(server_context))->r->headers_in); - APR_ARRAY_FOREACH_OPEN(arr, key, val) + APR_ARRAY_FOREACH_OPEN(arr, key, val) { if (!val) { val = ""; } php_info_print_table_row(2, key, val); - APR_ARRAY_FOREACH_CLOSE() + } APR_ARRAY_FOREACH_CLOSE(); php_info_print_table_colspan_header(2, "HTTP Response Headers"); arr = apr_table_elts(((php_struct *) SG(server_context))->r->headers_out); - APR_ARRAY_FOREACH_OPEN(arr, key, val) + APR_ARRAY_FOREACH_OPEN(arr, key, val) { if (!val) { val = ""; } php_info_print_table_row(2, key, val); - APR_ARRAY_FOREACH_CLOSE() + } APR_ARRAY_FOREACH_CLOSE(); php_info_print_table_end(); } diff --git a/sapi/apache2handler/sapi_apache2.c b/sapi/apache2handler/sapi_apache2.c index 2387d24741a4b..36862c9e41fc9 100644 --- a/sapi/apache2handler/sapi_apache2.c +++ b/sapi/apache2handler/sapi_apache2.c @@ -269,14 +269,14 @@ php_apache_sapi_register_variables(zval *track_vars_array) char *key, *val; size_t new_val_len; - APR_ARRAY_FOREACH_OPEN(arr, key, val) + APR_ARRAY_FOREACH_OPEN(arr, key, val) { if (!val) { val = ""; } if (sapi_module.input_filter(PARSE_SERVER, key, &val, strlen(val), &new_val_len)) { php_register_variable_safe(key, val, new_val_len, track_vars_array); } - APR_ARRAY_FOREACH_CLOSE() + } APR_ARRAY_FOREACH_CLOSE(); if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &ctx->r->uri, strlen(ctx->r->uri), &new_val_len)) { php_register_variable_safe("PHP_SELF", ctx->r->uri, new_val_len, track_vars_array);