mirror of
https://github.com/php/php-src.git
synced 2024-11-23 18:04:36 +08:00
Fixed mem leaks, added tests and ternary operator
This commit is contained in:
parent
2361745806
commit
466c5dd1fe
13
Zend/tests/class_properties_dynamic.phpt
Normal file
13
Zend/tests/class_properties_dynamic.phpt
Normal file
@ -0,0 +1,13 @@
|
||||
--TEST--
|
||||
Class Property Expressions
|
||||
--FILE--
|
||||
<?php
|
||||
class Foo {
|
||||
const BAR = 1 << 0;
|
||||
const BAZ = 1 << 1;
|
||||
public $bar = self::BAR | self::BAZ;
|
||||
}
|
||||
echo (new Foo)->bar;
|
||||
?>
|
||||
--EXPECTF--
|
||||
3
|
20
Zend/tests/class_properties_static.phpt
Normal file
20
Zend/tests/class_properties_static.phpt
Normal file
@ -0,0 +1,20 @@
|
||||
--TEST--
|
||||
Static Class Property Expressions
|
||||
--FILE--
|
||||
<?php
|
||||
class Foo {
|
||||
public $b1 = 1 + 1;
|
||||
public $b2 = 1 << 2;
|
||||
public $b3 = "foo " . " bar " . " baz";
|
||||
}
|
||||
$f = new Foo;
|
||||
var_dump(
|
||||
$f->b1,
|
||||
$f->b2,
|
||||
$f->b3
|
||||
);
|
||||
?>
|
||||
--EXPECT--
|
||||
int(2)
|
||||
int(4)
|
||||
string(13) "foo bar baz"
|
49
Zend/tests/constant_expressions.phpt
Normal file
49
Zend/tests/constant_expressions.phpt
Normal file
@ -0,0 +1,49 @@
|
||||
--TEST--
|
||||
Constant Expressions
|
||||
--FILE--
|
||||
<?php
|
||||
const T_1 = 1 << 1;
|
||||
const T_2 = 1 / 2;
|
||||
const T_3 = 1.5 + 1.5;
|
||||
const T_4 = "foo" . "bar";
|
||||
const T_5 = (1.5 + 1.5) * 2;
|
||||
const T_6 = "foo" . 2 . 3 . 4.0;
|
||||
const T_7 = __LINE__;
|
||||
const T_8 = <<<ENDOFSTRING
|
||||
This is a test string
|
||||
ENDOFSTRING;
|
||||
const T_9 = ~-1;
|
||||
const T_10 = (-1?:1) + (0?2:3);
|
||||
|
||||
// Test order of operations
|
||||
const T_11 = 1 + 2 * 3;
|
||||
|
||||
// Test for memory leaks
|
||||
const T_12 = "1" + 2 + "3";
|
||||
|
||||
var_dump(T_1);
|
||||
var_dump(T_2);
|
||||
var_dump(T_3);
|
||||
var_dump(T_4);
|
||||
var_dump(T_5);
|
||||
var_dump(T_6);
|
||||
var_dump(T_7);
|
||||
var_dump(T_8);
|
||||
var_dump(T_9);
|
||||
var_dump(T_10);
|
||||
var_dump(T_11);
|
||||
var_dump(T_12);
|
||||
?>
|
||||
--EXPECT--
|
||||
int(2)
|
||||
float(0.5)
|
||||
float(3)
|
||||
string(6) "foobar"
|
||||
float(6)
|
||||
string(6) "foo234"
|
||||
int(8)
|
||||
string(21) "This is a test string"
|
||||
int(0)
|
||||
int(2)
|
||||
int(7)
|
||||
int(6)
|
11
Zend/tests/constant_expressions_dynamic.phpt
Normal file
11
Zend/tests/constant_expressions_dynamic.phpt
Normal file
@ -0,0 +1,11 @@
|
||||
--TEST--
|
||||
Dynamic Constant Expressions
|
||||
--FILE--
|
||||
<?php
|
||||
const FOO = 1;
|
||||
const BAR = FOO | 2;
|
||||
|
||||
echo BAR;
|
||||
?>
|
||||
--EXPECTF--
|
||||
3
|
17
Zend/tests/function_arguments_003.phpt
Normal file
17
Zend/tests/function_arguments_003.phpt
Normal file
@ -0,0 +1,17 @@
|
||||
--TEST--
|
||||
Function Argument Parsing #003
|
||||
--FILE--
|
||||
<?php
|
||||
const a = 10;
|
||||
|
||||
function t1($a = 1 + 1, $b = 1 << 2, $c = "foo" . "bar", $d = a * 10) {
|
||||
var_dump($a, $b, $c, $d);
|
||||
}
|
||||
|
||||
t1();
|
||||
?>
|
||||
--EXPECT--
|
||||
int(2)
|
||||
int(4)
|
||||
string(6) "foobar"
|
||||
int(100)
|
29
Zend/tests/static_variable.phpt
Normal file
29
Zend/tests/static_variable.phpt
Normal file
@ -0,0 +1,29 @@
|
||||
--TEST--
|
||||
Static Variable Expressions
|
||||
--FILE--
|
||||
<?php
|
||||
const bar = 2, baz = bar + 1;
|
||||
|
||||
function foo() {
|
||||
static $a = 1 + 1;
|
||||
static $b = [bar => 1 + 1, baz * 2 => 1 << 2];
|
||||
static $c = [1 => bar] + [3 => baz];
|
||||
var_dump($a, $b, $c);
|
||||
}
|
||||
|
||||
foo();
|
||||
?>
|
||||
--EXPECT--
|
||||
int(2)
|
||||
array(2) {
|
||||
[2]=>
|
||||
int(2)
|
||||
[6]=>
|
||||
int(4)
|
||||
}
|
||||
array(2) {
|
||||
[1]=>
|
||||
int(2)
|
||||
[3]=>
|
||||
int(3)
|
||||
}
|
@ -22,7 +22,8 @@
|
||||
#include "zend_execute.h"
|
||||
|
||||
#define OP_IS_CONST_THEN(op, do_code) \
|
||||
switch (Z_TYPE_P(op) & IS_CONSTANT_TYPE_MASK) { \
|
||||
switch (op?Z_TYPE_P(op) & IS_CONSTANT_TYPE_MASK:-1) { \
|
||||
case -1: \
|
||||
case IS_CONSTANT: \
|
||||
case IS_CONSTANT_ARRAY: \
|
||||
case IS_CONSTANT_AST: { \
|
||||
@ -31,20 +32,26 @@
|
||||
}
|
||||
|
||||
#define OP_IS_NOT_CONST_THEN(op, do_code) \
|
||||
switch (Z_TYPE_P(op) & IS_CONSTANT_TYPE_MASK) { \
|
||||
case IS_CONSTANT: \
|
||||
case IS_CONSTANT_ARRAY: \
|
||||
case IS_CONSTANT_AST: \
|
||||
break; \
|
||||
if (op) { \
|
||||
switch (Z_TYPE_P(op) & IS_CONSTANT_TYPE_MASK) { \
|
||||
case IS_CONSTANT: \
|
||||
case IS_CONSTANT_ARRAY: \
|
||||
case IS_CONSTANT_AST: \
|
||||
break; \
|
||||
\
|
||||
default: { \
|
||||
do_code \
|
||||
default: { \
|
||||
do_code \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define COPY_ZVAL_TO_OP(nr) \
|
||||
Z_AST_P(result)->ops[nr] = emalloc(sizeof(zval)); \
|
||||
*Z_AST_P(result)->ops[nr] = *op##nr;
|
||||
if (op##nr) { \
|
||||
Z_AST_P(result)->ops[nr] = emalloc(sizeof(zval)); \
|
||||
*Z_AST_P(result)->ops[nr] = *op##nr; \
|
||||
} else { \
|
||||
Z_AST_P(result)->ops[nr] = NULL; \
|
||||
}
|
||||
|
||||
void zend_ast_add(zval *result, intermediary_ast_function_type func, char op_count) {
|
||||
zend_ast *ast = emalloc(sizeof(zend_ast));
|
||||
@ -58,9 +65,10 @@ void zend_ast_add(zval *result, intermediary_ast_function_type func, char op_cou
|
||||
|
||||
/* Do operations on constant operators at compile time (AST building time) */
|
||||
|
||||
void zend_ast_add_unary(zval *result, unary_ast_func func, zval *op0) {
|
||||
void zend_ast_add_unary(zval *result, unary_ast_func func, zval *op0 TSRMLS_DC) {
|
||||
OP_IS_NOT_CONST_THEN(op0,
|
||||
func(result, op0);
|
||||
func(result, op0 TSRMLS_CC);
|
||||
zval_dtor(op0);
|
||||
return;
|
||||
)
|
||||
|
||||
@ -68,9 +76,11 @@ void zend_ast_add_unary(zval *result, unary_ast_func func, zval *op0) {
|
||||
COPY_ZVAL_TO_OP(0)
|
||||
}
|
||||
|
||||
void zend_ast_add_binary(zval *result, binary_ast_func func, zval *op0, zval *op1) {
|
||||
void zend_ast_add_binary(zval *result, binary_ast_func func, zval *op0, zval *op1 TSRMLS_DC) {
|
||||
OP_IS_NOT_CONST_THEN(op0, OP_IS_NOT_CONST_THEN(op1,
|
||||
func(result, op0, op1);
|
||||
func(result, op0, op1 TSRMLS_CC);
|
||||
zval_dtor(op0);
|
||||
zval_dtor(op1);
|
||||
return;
|
||||
))
|
||||
|
||||
@ -79,9 +89,12 @@ void zend_ast_add_binary(zval *result, binary_ast_func func, zval *op0, zval *op
|
||||
COPY_ZVAL_TO_OP(1)
|
||||
}
|
||||
|
||||
void zend_ast_add_ternary(zval *result, ternary_ast_func func, zval *op0, zval *op1, zval *op2) {
|
||||
void zend_ast_add_ternary(zval *result, ternary_ast_func func, zval *op0, zval *op1, zval *op2 TSRMLS_DC) {
|
||||
OP_IS_NOT_CONST_THEN(op0, OP_IS_NOT_CONST_THEN(op1, OP_IS_NOT_CONST_THEN(op2,
|
||||
func(result, op0, op1, op2);
|
||||
func(result, op0, op1, op2 TSRMLS_CC);
|
||||
zval_dtor(op0);
|
||||
zval_dtor(op1);
|
||||
zval_dtor(op2);
|
||||
return;
|
||||
)))
|
||||
|
||||
@ -95,20 +108,22 @@ void zend_ast_evaluate(zval *result, zend_ast *ast TSRMLS_DC) {
|
||||
int i;
|
||||
|
||||
for (i = ast->op_count; i--;) {
|
||||
OP_IS_CONST_THEN(ast->ops[i],
|
||||
zval_update_constant_ex(&ast->ops[i], (void *)1, NULL TSRMLS_CC);
|
||||
)
|
||||
if (ast->ops[i]) {
|
||||
OP_IS_CONST_THEN(ast->ops[i],
|
||||
zval_update_constant_ex(&ast->ops[i], (void *)1, NULL TSRMLS_CC);
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
switch (ast->op_count) {
|
||||
case 1:
|
||||
((unary_ast_func)ast->func)(result, ast->ops[0]);
|
||||
((unary_ast_func)ast->func)(result, ast->ops[0] TSRMLS_CC);
|
||||
break;
|
||||
case 2:
|
||||
((binary_ast_func)ast->func)(result, ast->ops[0], ast->ops[1]);
|
||||
((binary_ast_func)ast->func)(result, ast->ops[0], ast->ops[1] TSRMLS_CC);
|
||||
break;
|
||||
case 3:
|
||||
((ternary_ast_func)ast->func)(result, ast->ops[0], ast->ops[1], ast->ops[2]);
|
||||
((ternary_ast_func)ast->func)(result, ast->ops[0], ast->ops[1], ast->ops[2] TSRMLS_CC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -117,7 +132,7 @@ void zend_ast_destroy(zend_ast *ast TSRMLS_DC) {
|
||||
int i;
|
||||
|
||||
for (i = ast->op_count; i--;) {
|
||||
if (!Z_DELREF_P(ast->ops[i])) {
|
||||
if (ast->ops[i] && !Z_DELREF_P(ast->ops[i])) {
|
||||
zval_dtor(ast->ops[i]);
|
||||
efree(ast->ops[i]);
|
||||
}
|
||||
|
@ -26,9 +26,9 @@ typedef struct _zend_ast zend_ast;
|
||||
#include "zend.h"
|
||||
|
||||
typedef void(*intermediary_ast_function_type)(zval *, ...);
|
||||
typedef int(*unary_ast_func)(zval *result, zval *op0);
|
||||
typedef int(*binary_ast_func)(zval *result, zval *op0, zval *op1);
|
||||
typedef int(*ternary_ast_func)(zval *result, zval *op0, zval *op1, zval *op2);
|
||||
typedef int(*unary_ast_func)(zval *result, zval *op0 TSRMLS_DC);
|
||||
typedef int(*binary_ast_func)(zval *result, zval *op0, zval *op1 TSRMLS_DC);
|
||||
typedef int(*ternary_ast_func)(zval *result, zval *op0, zval *op1, zval *op2 TSRMLS_DC);
|
||||
|
||||
struct _zend_ast {
|
||||
char op_count;
|
||||
@ -37,9 +37,9 @@ struct _zend_ast {
|
||||
int refcount;
|
||||
};
|
||||
|
||||
void zend_ast_add_unary(zval *result, unary_ast_func func, zval *op0);
|
||||
void zend_ast_add_binary(zval *result, binary_ast_func func, zval *op0, zval *op1);
|
||||
void zend_ast_add_ternary(zval *result, ternary_ast_func func, zval *op0, zval *op1, zval *op2);
|
||||
void zend_ast_add_unary(zval *result, unary_ast_func func, zval *op0 TSRMLS_DC);
|
||||
void zend_ast_add_binary(zval *result, binary_ast_func func, zval *op0, zval *op1 TSRMLS_DC);
|
||||
void zend_ast_add_ternary(zval *result, ternary_ast_func func, zval *op0, zval *op1, zval *op2 TSRMLS_DC);
|
||||
|
||||
void zend_ast_evaluate(zval *result, zend_ast *ast TSRMLS_DC);
|
||||
|
||||
|
@ -599,7 +599,7 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
|
||||
continue;
|
||||
}
|
||||
if (str_index[str_index_len - 2] == IS_CONSTANT_AST) {
|
||||
zend_ast_evaluate(&const_value, *(zend_ast **)str_index);
|
||||
zend_ast_evaluate(&const_value, *(zend_ast **)str_index TSRMLS_CC);
|
||||
ZEND_AST_DEL_REF(*(zend_ast **)str_index);
|
||||
} else if (!zend_get_constant_ex(str_index, str_index_len - 3, &const_value, scope, str_index[str_index_len - 2] TSRMLS_CC)) {
|
||||
char *actual;
|
||||
|
@ -982,6 +982,8 @@ static_operation:
|
||||
| static_scalar_value T_SL static_scalar_value { zend_ast_add_binary(&$$.u.constant, shift_left_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
|
||||
| static_scalar_value T_SR static_scalar_value { zend_ast_add_binary(&$$.u.constant, shift_right_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
|
||||
| static_scalar_value '.' static_scalar_value { zend_ast_add_binary(&$$.u.constant, concat_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
|
||||
| static_scalar_value '?' ':' static_scalar_value { zend_ast_add_ternary(&$$.u.constant, ternary_function, &$1.u.constant, NULL, &$4.u.constant TSRMLS_CC); }
|
||||
| static_scalar_value '?' static_scalar_value ':' static_scalar_value { zend_ast_add_ternary(&$$.u.constant, ternary_function, &$1.u.constant, &$3.u.constant, &$5.u.constant TSRMLS_CC); }
|
||||
| '+' static_scalar_value { ZVAL_LONG(&$1.u.constant, 0); zend_ast_add_binary(&$$.u.constant, add_function, &$1.u.constant, &$2.u.constant TSRMLS_CC); }
|
||||
| '-' static_scalar_value { ZVAL_LONG(&$1.u.constant, 0); zend_ast_add_binary(&$$.u.constant, sub_function, &$1.u.constant, &$2.u.constant TSRMLS_CC); }
|
||||
| '(' static_scalar_value ')' { $$ = $2; }
|
||||
|
@ -2323,6 +2323,28 @@ ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
#define PREVENT_DTOR_IF_REFCOUNT_1_AND_ASSIGN_TO_RESULT(var) \
|
||||
*result = *var; \
|
||||
if (Z_REFCOUNT_P(var) == 1) { \
|
||||
Z_TYPE_P(var) = IS_NULL; \
|
||||
}
|
||||
|
||||
ZEND_API int ternary_function(zval *result, zval *condition, zval *then, zval *if_not TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
if (i_zend_is_true(condition)) {
|
||||
if (then) {
|
||||
PREVENT_DTOR_IF_REFCOUNT_1_AND_ASSIGN_TO_RESULT(then);
|
||||
} else {
|
||||
PREVENT_DTOR_IF_REFCOUNT_1_AND_ASSIGN_TO_RESULT(condition);
|
||||
}
|
||||
} else {
|
||||
PREVENT_DTOR_IF_REFCOUNT_1_AND_ASSIGN_TO_RESULT(if_not);
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
|
@ -376,6 +376,8 @@ ZEND_API int zend_atoi(const char *str, int str_len);
|
||||
ZEND_API long zend_atol(const char *str, int str_len);
|
||||
|
||||
ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC);
|
||||
|
||||
ZEND_API int ternary_function(zval *result, zval *condition, zval *then, zval *if_not TSRMLS_DC);
|
||||
END_EXTERN_C()
|
||||
|
||||
#define convert_to_ex_master(ppzv, lower_type, upper_type) \
|
||||
|
Loading…
Reference in New Issue
Block a user