From: Anthony Ferrara Date: Thu, 19 Mar 2015 16:26:34 +0000 (-0400) Subject: Fix severity issues with callbacks, start work porting ZEND_STRLEN opcode to work... X-Git-Tag: PRE_PHP7_NSAPI_REMOVAL~573^2~11^2~6 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0ef80ac351960cd0fa474f960638abc8921841d8;p=php Fix severity issues with callbacks, start work porting ZEND_STRLEN opcode to work with strict mode, more refactoring to come --- diff --git a/Zend/tests/typehints/internal_function_strict_mode.phpt b/Zend/tests/typehints/internal_function_strict_mode.phpt new file mode 100644 index 0000000000..3e5629af95 --- /dev/null +++ b/Zend/tests/typehints/internal_function_strict_mode.phpt @@ -0,0 +1,35 @@ +--TEST-- +Scalar type hint - internal function strict mode +--FILE-- +getMessage() . PHP_EOL; +} + +echo "*** Trying Array Map With Invalid Callback" . PHP_EOL; +try { + array_map([null, "bar"], []); +} catch (TypeException $e) { + echo "*** Caught " . $e->getMessage() . PHP_EOL; +} + +echo "*** Trying Strlen With Float" . PHP_EOL; +try { + var_dump(strlen(1.5)); +} catch (TypeException $e) { + echo "*** Caught " . $e->getMessage() . PHP_EOL; +} + +?> +--EXPECTF-- +*** Trying Ord With Integer +*** Caught ord() expects parameter 1 to be string, integer given +*** Trying Array Map With Invalid Callback +*** Caught array_map() expects parameter 1 to be a valid callback, first array member is not a valid class name or object +*** Trying Strlen With Float +*** Caught strlen() expects parameter 1 to be string, float given \ No newline at end of file diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 32888f1f00..f86bb66c53 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -284,13 +284,18 @@ ZEND_API void zend_wrong_paramer_class_error(int num, char *name, zval *arg, zen } /* }}} */ -ZEND_API void zend_wrong_callback_error(int severity, int num, char *error) /* {{{ */ +ZEND_API void zend_wrong_callback_error(int severity, int num, char *error, zend_bool strict) /* {{{ */ { const char *space; const char *class_name = get_active_class_name(&space); - zend_error(severity, "%s%s%s() expects parameter %d to be a valid callback, %s", - class_name, space, get_active_function_name(), num, error); + if (severity == E_WARNING) { + zend_internal_type_error(strict, "%s%s%s() expects parameter %d to be a valid callback, %s", + class_name, space, get_active_function_name(), num, error); + } else { + zend_error(severity, "%s%s%s() expects parameter %d to be a valid callback, %s", + class_name, space, get_active_function_name(), num, error); + } efree(error); } /* }}} */ diff --git a/Zend/zend_API.h b/Zend/zend_API.h index a1989d1927..810e9b850f 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -710,7 +710,7 @@ typedef enum _zend_expected_type { ZEND_API void zend_wrong_paramers_count_error(int num_args, int min_num_args, int max_num_args, zend_bool strict); ZEND_API void zend_wrong_paramer_type_error(int num, zend_expected_type expected_type, zval *arg, zend_bool strict); ZEND_API void zend_wrong_paramer_class_error(int num, char *name, zval *arg, zend_bool strict); -ZEND_API void zend_wrong_callback_error(int severity, int num, char *error); +ZEND_API void zend_wrong_callback_error(int severity, int num, char *error, zend_bool strict); #define ZPP_ERROR_OK 0 #define ZPP_ERROR_FAILURE 1 @@ -761,7 +761,7 @@ ZEND_API void zend_wrong_callback_error(int severity, int num, char *error); if (UNEXPECTED(error_code != ZPP_ERROR_OK)) { \ if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \ if (error_code == ZPP_ERROR_WRONG_CALLBACK) { \ - zend_wrong_callback_error(_strict ? E_RECOVERABLE_ERROR : E_WARNING, _i, _error); \ + zend_wrong_callback_error(E_WARNING, _i, _error, _strict); \ } else if (error_code == ZPP_ERROR_WRONG_CLASS) { \ zend_wrong_paramer_class_error(_i, _error, _arg, _strict); \ } else if (error_code == ZPP_ERROR_WRONG_ARG) { \ @@ -863,7 +863,7 @@ ZEND_API void zend_wrong_callback_error(int severity, int num, char *error); break; \ } \ } else if (UNEXPECTED(_error != NULL)) { \ - zend_wrong_callback_error(E_STRICT, _i, _error); \ + zend_wrong_callback_error(E_STRICT, _i, _error, _strict); \ } #define Z_PARAM_FUNC(dest_fci, dest_fcc) \ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index d116c4f5d6..eb9f68e350 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -7269,7 +7269,7 @@ ZEND_VM_HANDLER(121, ZEND_STRLEN, CONST|TMPVAR|CV, ANY) ZEND_VM_C_LABEL(try_strlen): if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); - } else { + } else if (EXPECTED(0 == EX_USES_STRICT_TYPES())) { if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); ZEND_VM_C_GOTO(try_strlen); @@ -7296,6 +7296,8 @@ ZEND_VM_C_LABEL(strlen_error): zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); ZVAL_NULL(EX_VAR(opline->result.var)); } + } else { + zend_type_error("strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); } FREE_OP1(); CHECK_EXCEPTION(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index d535b41dca..8eb8bf8826 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3815,7 +3815,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CONST_HANDLER(ZEND try_strlen: if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); - } else { + } else if (EXPECTED(0 == EX_USES_STRICT_TYPES())) { if ((IS_CONST & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); goto try_strlen; @@ -3842,6 +3842,8 @@ strlen_error: zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); ZVAL_NULL(EX_VAR(opline->result.var)); } + } else { + zend_type_error("strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); } CHECK_EXCEPTION(); @@ -27300,7 +27302,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CV_HANDLER(ZEND_OP try_strlen: if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); - } else { + } else if (EXPECTED(0 == EX_USES_STRICT_TYPES())) { if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); goto try_strlen; @@ -27327,6 +27329,8 @@ strlen_error: zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); ZVAL_NULL(EX_VAR(opline->result.var)); } + } else { + zend_type_error("strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); } CHECK_EXCEPTION(); @@ -37559,7 +37563,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_TMPVAR_HANDLER(ZEN try_strlen: if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); - } else { + } else if (EXPECTED(0 == EX_USES_STRICT_TYPES())) { if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); goto try_strlen; @@ -37586,6 +37590,8 @@ strlen_error: zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); ZVAL_NULL(EX_VAR(opline->result.var)); } + } else { + zend_type_error("strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); } zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION();