summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/tests/numeric_strings/invalid_numeric_strings_must_generate_warning.phpt4
-rw-r--r--Zend/tests/runtime_compile_time_binary_operands.phpt43
-rw-r--r--Zend/zend_compile.c40
3 files changed, 65 insertions, 22 deletions
diff --git a/Zend/tests/numeric_strings/invalid_numeric_strings_must_generate_warning.phpt b/Zend/tests/numeric_strings/invalid_numeric_strings_must_generate_warning.phpt
index 3ffe78a119..2b76f538f4 100644
--- a/Zend/tests/numeric_strings/invalid_numeric_strings_must_generate_warning.phpt
+++ b/Zend/tests/numeric_strings/invalid_numeric_strings_must_generate_warning.phpt
@@ -198,9 +198,9 @@ Unsupported operand types: int ^ string
Warning: A non-numeric value encountered in %s on line %d
int(149)
-Unsupported operand types: int * string
+Unsupported operand types: string * int
---
Warning: A non-numeric value encountered in %s on line %d
int(-151)
-Unsupported operand types: int * string
+Unsupported operand types: string * int
diff --git a/Zend/tests/runtime_compile_time_binary_operands.phpt b/Zend/tests/runtime_compile_time_binary_operands.phpt
index 9fe76b2efb..14195141b1 100644
--- a/Zend/tests/runtime_compile_time_binary_operands.phpt
+++ b/Zend/tests/runtime_compile_time_binary_operands.phpt
@@ -5,7 +5,7 @@ memory_limit=256M
--FILE--
<?php
-$operands = [
+$binaryOperators = [
"==",
"!=",
"===",
@@ -31,6 +31,12 @@ $operands = [
"||",
"&&",
];
+$unaryOperators = [
+ "~",
+ "-",
+ "+",
+ "!",
+];
$input = [
0,
@@ -100,8 +106,7 @@ function makeParam($param) {
$c = 0;
$f = 0;
-function prepareLine($op1, $op2, $cmp, $operator) {
-
+function prepareBinaryLine($op1, $op2, $cmp, $operator) {
$op1_p = makeParam($op1);
$op2_p = makeParam($op2);
@@ -118,6 +123,22 @@ function prepareLine($op1, $op2, $cmp, $operator) {
}
return $line;
}
+function prepareUnaryLine($op, $cmp, $operator) {
+ $op_p = makeParam($op);
+
+ $error = "echo '" . addcslashes("$operator $op_p", "\\'") . '\', "\n"; $f++;';
+
+ $compare = "@($operator $op_p)";
+ $line = "\$c++; ";
+ try {
+ $result = makeParam($cmp());
+ $line .= "if (" . ($result === "(NAN)" ? "!is_nan($compare)" : "$compare !== $result") . ") { $error }";
+ } catch (Error $e) {
+ $msg = makeParam($e->getMessage());
+ $line .= "try { $compare; $error } catch (Error \$e) { if (\$e->getMessage() !== $msg) { $error } }";
+ }
+ return $line;
+}
$filename = __DIR__ . DIRECTORY_SEPARATOR . 'compare_binary_operands_temp.php';
$file = fopen($filename, "w");
@@ -126,14 +147,22 @@ fwrite($file, "<?php\n");
foreach ($input as $left) {
foreach ($input as $right) {
- foreach ($operands as $operand) {
- $line = prepareLine($left, $right, function() use ($left, $right, $operand) {
- return eval("return @(\$left $operand \$right);");
- }, $operand);
+ foreach ($binaryOperators as $operator) {
+ $line = prepareBinaryLine($left, $right, function() use ($left, $right, $operator) {
+ return eval("return @(\$left $operator \$right);");
+ }, $operator);
fwrite($file, $line . "\n");
}
}
}
+foreach ($input as $right) {
+ foreach ($unaryOperators as $operator) {
+ $line = prepareUnaryLine($right, function() use ($right, $operator) {
+ return eval("return @($operator \$right);");
+ }, $operator);
+ fwrite($file, $line . "\n");
+ }
+}
fclose($file);
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 6d07abe3e0..719e7aaffe 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -7913,18 +7913,32 @@ static inline zend_bool zend_try_ct_eval_binary_op(zval *result, uint32_t opcode
}
/* }}} */
-static inline void zend_ct_eval_unary_op(zval *result, uint32_t opcode, zval *op) /* {{{ */
+zend_bool zend_unary_op_produces_error(uint32_t opcode, zval *op)
{
+ if (opcode == ZEND_BW_NOT) {
+ return Z_TYPE_P(op) <= IS_TRUE || Z_TYPE_P(op) == IS_ARRAY;
+ }
+
+ return 0;
+}
+
+static inline zend_bool zend_try_ct_eval_unary_op(zval *result, uint32_t opcode, zval *op) /* {{{ */
+{
+ if (zend_unary_op_produces_error(opcode, op)) {
+ return 0;
+ }
+
unary_op_type fn = get_unary_op(opcode);
fn(result, op);
+ return 1;
}
/* }}} */
static inline zend_bool zend_try_ct_eval_unary_pm(zval *result, zend_ast_kind kind, zval *op) /* {{{ */
{
- zval left;
- ZVAL_LONG(&left, (kind == ZEND_AST_UNARY_PLUS) ? 1 : -1);
- return zend_try_ct_eval_binary_op(result, ZEND_MUL, &left, op);
+ zval right;
+ ZVAL_LONG(&right, (kind == ZEND_AST_UNARY_PLUS) ? 1 : -1);
+ return zend_try_ct_eval_binary_op(result, ZEND_MUL, op, &right);
}
/* }}} */
@@ -8185,10 +8199,9 @@ void zend_compile_unary_op(znode *result, zend_ast *ast) /* {{{ */
znode expr_node;
zend_compile_expr(&expr_node, expr_ast);
- if (expr_node.op_type == IS_CONST) {
+ if (expr_node.op_type == IS_CONST
+ && zend_try_ct_eval_unary_op(&result->u.constant, opcode, &expr_node.u.constant)) {
result->op_type = IS_CONST;
- zend_ct_eval_unary_op(&result->u.constant, opcode,
- &expr_node.u.constant);
zval_ptr_dtor(&expr_node.u.constant);
return;
}
@@ -8200,8 +8213,7 @@ void zend_compile_unary_op(znode *result, zend_ast *ast) /* {{{ */
void zend_compile_unary_pm(znode *result, zend_ast *ast) /* {{{ */
{
zend_ast *expr_ast = ast->child[0];
- znode expr_node;
- znode lefthand_node;
+ znode expr_node, right_node;
ZEND_ASSERT(ast->kind == ZEND_AST_UNARY_PLUS || ast->kind == ZEND_AST_UNARY_MINUS);
@@ -8214,9 +8226,9 @@ void zend_compile_unary_pm(znode *result, zend_ast *ast) /* {{{ */
return;
}
- lefthand_node.op_type = IS_CONST;
- ZVAL_LONG(&lefthand_node.u.constant, (ast->kind == ZEND_AST_UNARY_PLUS) ? 1 : -1);
- zend_emit_op_tmp(result, ZEND_MUL, &lefthand_node, &expr_node);
+ right_node.op_type = IS_CONST;
+ ZVAL_LONG(&right_node.u.constant, (ast->kind == ZEND_AST_UNARY_PLUS) ? 1 : -1);
+ zend_emit_op_tmp(result, ZEND_MUL, &expr_node, &right_node);
}
/* }}} */
@@ -9752,7 +9764,9 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
return;
}
- zend_ct_eval_unary_op(&result, ast->attr, zend_ast_get_zval(ast->child[0]));
+ if (!zend_try_ct_eval_unary_op(&result, ast->attr, zend_ast_get_zval(ast->child[0]))) {
+ return;
+ }
break;
case ZEND_AST_UNARY_PLUS:
case ZEND_AST_UNARY_MINUS: