From 16b9f196782281e2bb407f3217695205d8cb70ff Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 15 Sep 2020 15:06:56 +0200 Subject: [PATCH] Fix compile-time/run-time discrepancies with unary operators This addresses two issues: * ~ throws for a number of types, and we should not compile-time evaluate in that case. Add a check similar to what we do for binary ops. * Unary +/- may produce a different error message due to canonicalization of the constant operand to the RHS. To avoid this, put the constant operand on the RHS right away. Fixes oss-fuzz #25649. --- ...numeric_strings_must_generate_warning.phpt | 4 +- .../runtime_compile_time_binary_operands.phpt | 43 ++++++++++++++++--- Zend/zend_compile.c | 40 +++++++++++------ 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-- 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, "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: -- 2.40.0