Skip to content

Commit b830ed6

Browse files
committed
Fix conflicts
2 parents 3d7d0f9 + 743729d commit b830ed6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1730
-738
lines changed

Zend/tests/bug71221.phpt

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,14 @@ Bug #71221 (Null pointer deref (segfault) in get_defined_vars via ob_start)
33
--FILE--
44
<?php
55
ob_start("get_defined_vars");
6-
ob_end_clean();
6+
try {
7+
ob_end_clean();
8+
} catch (\Error $e) {
9+
echo $e->getMessage();
10+
}
711
?>
8-
okey
12+
13+
OKAY
914
--EXPECT--
10-
okey
15+
Cannot call get_defined_vars() dynamically
16+
OKAY

Zend/tests/bug72107.phpt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ set_error_handler('func_get_args');
66
function test($a) {
77
echo $undef;
88
}
9-
test(1);
9+
try {
10+
test(1);
11+
} catch (\Error $e) {
12+
echo $e->getMessage();
13+
}
1014
?>
11-
--EXPECTF--
12-
Warning: Cannot call func_get_args() dynamically in %s on line %d
13-
14-
Notice: Undefined variable: undef in %s on line %d
15+
--EXPECT--
16+
Cannot call func_get_args() dynamically

Zend/tests/closure_062.phpt

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
--TEST--
2+
Closure $this unbinding deprecation
3+
--FILE--
4+
<?php
5+
6+
class Test {
7+
public function method() {
8+
echo "instance scoped, non-static, \$this used\n";
9+
$fn = function() {
10+
var_dump($this);
11+
};
12+
$fn->bindTo(null);
13+
echo "instance scoped, static, \$this used\n";
14+
$fn = static function() {
15+
var_dump($this);
16+
};
17+
$fn->bindTo(null);
18+
echo "instance scoped, non-static, \$this not used\n";
19+
$fn = function() {
20+
var_dump($notThis);
21+
};
22+
$fn->bindTo(null);
23+
}
24+
25+
public static function staticMethod() {
26+
echo "static scoped, non-static, \$this used\n";
27+
$fn = function() {
28+
var_dump($this);
29+
};
30+
$fn->bindTo(null);
31+
echo "static scoped, static, \$this used\n";
32+
$fn = static function() {
33+
var_dump($this);
34+
};
35+
$fn->bindTo(null);
36+
echo "static scoped, static, \$this not used\n";
37+
$fn = function() {
38+
var_dump($notThis);
39+
};
40+
$fn->bindTo(null);
41+
}
42+
}
43+
44+
(new Test)->method();
45+
Test::staticMethod();
46+
47+
?>
48+
--EXPECTF--
49+
instance scoped, non-static, $this used
50+
51+
Deprecated: Unbinding $this of closure is deprecated in %s on line %d
52+
instance scoped, static, $this used
53+
instance scoped, non-static, $this not used
54+
static scoped, non-static, $this used
55+
static scoped, static, $this used
56+
static scoped, static, $this not used

Zend/tests/dynamic_call_005.phpt

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,31 @@ Dynamic calls to scope introspection functions are forbidden
66
function test_calls($func) {
77
$i = 1;
88

9-
array_map($func, [['i' => new stdClass]]);
10-
var_dump($i);
9+
try {
10+
array_map($func, [['i' => new stdClass]]);
11+
var_dump($i);
12+
} catch (\Error $e) {
13+
echo $e->getMessage() . "\n";
14+
}
1115

12-
$func(['i' => new stdClass]);
13-
var_dump($i);
16+
try {
17+
$func(['i' => new stdClass]);
18+
var_dump($i);
19+
} catch (\Error $e) {
20+
echo $e->getMessage() . "\n";
21+
}
1422

15-
call_user_func($func, ['i' => new stdClass]);
16-
var_dump($i);
23+
try {
24+
call_user_func($func, ['i' => new stdClass]);
25+
var_dump($i);
26+
} catch (\Error $e) {
27+
echo $e->getMessage() . "\n";
28+
}
1729
}
1830
test_calls('extract');
1931

2032
?>
21-
--EXPECTF--
22-
Warning: Cannot call extract() dynamically in %s on line %d
23-
int(1)
24-
25-
Warning: Cannot call extract() dynamically in %s on line %d
26-
int(1)
27-
28-
Warning: Cannot call extract() dynamically in %s on line %d
29-
int(1)
33+
--EXPECT--
34+
Cannot call extract() dynamically
35+
Cannot call extract() dynamically
36+
Cannot call extract() dynamically

Zend/tests/dynamic_call_006.phpt

Lines changed: 48 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,56 @@ Dynamic calls to scope introspection functions are forbidden (function variation
33
--FILE--
44
<?php
55
function test() {
6-
$func = 'extract';
7-
$func(['a' => 'b']);
86

9-
$func = 'compact';
10-
$func(['a']);
11-
12-
$func = 'get_defined_vars';
13-
$func();
14-
15-
$func = 'func_get_args';
16-
$func();
17-
18-
$func = 'func_get_arg';
19-
$func(1);
20-
21-
$func = 'func_num_args';
22-
$func();
7+
try {
8+
$func = 'extract';
9+
$func(['a' => 'b']);
10+
} catch (\Error $e) {
11+
echo $e->getMessage() . "\n";
12+
}
13+
14+
try {
15+
$func = 'compact';
16+
$func(['a']);
17+
} catch (\Error $e) {
18+
echo $e->getMessage() . "\n";
19+
}
20+
21+
try {
22+
$func = 'get_defined_vars';
23+
$func();
24+
} catch (\Error $e) {
25+
echo $e->getMessage() . "\n";
26+
}
27+
28+
try {
29+
$func = 'func_get_args';
30+
$func();
31+
} catch (\Error $e) {
32+
echo $e->getMessage() . "\n";
33+
}
34+
35+
try {
36+
$func = 'func_get_arg';
37+
$func(1);
38+
} catch (\Error $e) {
39+
echo $e->getMessage() . "\n";
40+
}
41+
42+
try {
43+
$func = 'func_num_args';
44+
$func();
45+
} catch (\Error $e) {
46+
echo $e->getMessage() . "\n";
47+
}
2348
}
2449
test();
2550

2651
?>
27-
--EXPECTF--
28-
Warning: Cannot call extract() dynamically in %s on line %d
29-
30-
Warning: Cannot call compact() dynamically in %s on line %d
31-
32-
Warning: Cannot call get_defined_vars() dynamically in %s on line %d
33-
34-
Warning: Cannot call func_get_args() dynamically in %s on line %d
35-
36-
Warning: Cannot call func_get_arg() dynamically in %s on line %d
37-
38-
Warning: Cannot call func_num_args() dynamically in %s on line %d
52+
--EXPECT--
53+
Cannot call extract() dynamically
54+
Cannot call compact() dynamically
55+
Cannot call get_defined_vars() dynamically
56+
Cannot call func_get_args() dynamically
57+
Cannot call func_get_arg() dynamically
58+
Cannot call func_num_args() dynamically

Zend/tests/dynamic_call_007.phpt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@ Dynamic calls to scope introspection functions are forbidden (misoptimization)
55

66
function test() {
77
$i = 1;
8-
array_map('extract', [['i' => new stdClass]]);
8+
try {
9+
array_map('extract', [['i' => new stdClass]]);
10+
} catch (\Error $e) {
11+
echo $e->getMessage() . "\n";
12+
}
913
$i += 1;
1014
var_dump($i);
1115
}
1216
test();
1317

1418
?>
15-
--EXPECTF--
16-
Warning: Cannot call extract() dynamically in %s on line %d
19+
--EXPECT--
20+
Cannot call extract() dynamically
1721
int(2)

Zend/tests/dynamic_call_008.phpt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@ Don't optimize dynamic call to non-dynamic one if it drops the warning
44
<?php
55

66
function test() {
7-
((string) 'extract')(['a' => 42]);
7+
try {
8+
((string) 'extract')(['a' => 42]);
9+
} catch (\Error $e) {
10+
echo $e->getMessage() . "\n";
11+
}
812
}
913
test();
1014

1115
?>
12-
--EXPECTF--
13-
Warning: Cannot call extract() dynamically in %s on line %d
16+
--EXPECT--
17+
Cannot call extract() dynamically

Zend/zend_API.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2701,6 +2701,7 @@ ZEND_API int zend_disable_class(char *class_name, size_t class_name_length) /* {
27012701
{
27022702
zend_class_entry *disabled_class;
27032703
zend_string *key;
2704+
zend_function *fn;
27042705

27052706
key = zend_string_alloc(class_name_length, 0);
27062707
zend_str_tolower_copy(ZSTR_VAL(key), class_name, class_name_length);
@@ -2709,8 +2710,16 @@ ZEND_API int zend_disable_class(char *class_name, size_t class_name_length) /* {
27092710
if (!disabled_class) {
27102711
return FAILURE;
27112712
}
2713+
27122714
INIT_CLASS_ENTRY_INIT_METHODS((*disabled_class), disabled_class_new);
27132715
disabled_class->create_object = display_disabled_class;
2716+
2717+
ZEND_HASH_FOREACH_PTR(&disabled_class->function_table, fn) {
2718+
if ((fn->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) &&
2719+
fn->common.scope == disabled_class) {
2720+
zend_free_internal_arg_info(&fn->internal_function);
2721+
}
2722+
} ZEND_HASH_FOREACH_END();
27142723
zend_hash_clean(&disabled_class->function_table);
27152724
return SUCCESS;
27162725
}

Zend/zend_API.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ static zend_always_inline int zend_forbid_dynamic_call(const char *func_name)
538538
ZEND_ASSERT(ex != NULL && ex->func != NULL);
539539

540540
if (ZEND_CALL_INFO(ex) & ZEND_CALL_DYNAMIC) {
541-
zend_error(E_WARNING, "Cannot call %s dynamically", func_name);
541+
zend_throw_error(NULL, "Cannot call %s dynamically", func_name);
542542
return FAILURE;
543543
}
544544

Zend/zend_closures.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ static zend_bool zend_valid_closure_binding(
8686
&& !(func->common.fn_flags & ZEND_ACC_STATIC)) {
8787
zend_error(E_WARNING, "Cannot unbind $this of method");
8888
return 0;
89-
} else if (!is_fake_closure && !Z_ISUNDEF(closure->this_ptr)) {
89+
} else if (!is_fake_closure && !Z_ISUNDEF(closure->this_ptr)
90+
&& (func->common.fn_flags & ZEND_ACC_USES_THIS)) {
9091
// TODO: Only deprecate if it had $this *originally*?
9192
zend_error(E_DEPRECATED, "Unbinding $this of closure is deprecated");
9293
}

Zend/zend_compile.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2357,6 +2357,7 @@ static zend_op *zend_compile_simple_var(znode *result, zend_ast *ast, uint32_t t
23572357
opline->result_type = IS_TMP_VAR;
23582358
result->op_type = IS_TMP_VAR;
23592359
}
2360+
CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;
23602361
return opline;
23612362
} else if (zend_try_compile_cv(result, ast) == FAILURE) {
23622363
return zend_compile_simple_var_no_cv(result, ast, type, delayed);
@@ -2451,6 +2452,7 @@ static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t
24512452

24522453
if (is_this_fetch(obj_ast)) {
24532454
obj_node.op_type = IS_UNUSED;
2455+
CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;
24542456
} else {
24552457
opline = zend_delayed_compile_var(&obj_node, obj_ast, type, 0);
24562458
if (opline && type == BP_VAR_W && (opline->opcode == ZEND_FETCH_STATIC_PROP_W || opline->opcode == ZEND_FETCH_OBJ_W)) {
@@ -2987,6 +2989,7 @@ uint32_t zend_compile_args(zend_ast *ast, zend_function *fbc) /* {{{ */
29872989
if (is_this_fetch(arg)) {
29882990
zend_emit_op(&arg_node, ZEND_FETCH_THIS, NULL, NULL);
29892991
opcode = ZEND_SEND_VAR_EX;
2992+
CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;
29902993
break;
29912994
} else if (zend_try_compile_cv(&arg_node, arg) == SUCCESS) {
29922995
opcode = ZEND_SEND_VAR_EX;
@@ -3846,6 +3849,7 @@ void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type) /* {{
38463849

38473850
if (is_this_fetch(obj_ast)) {
38483851
obj_node.op_type = IS_UNUSED;
3852+
CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;
38493853
} else {
38503854
zend_compile_expr(&obj_node, obj_ast);
38513855
}
@@ -7654,6 +7658,7 @@ void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */
76547658
case ZEND_AST_VAR:
76557659
if (is_this_fetch(var_ast)) {
76567660
opline = zend_emit_op(result, ZEND_ISSET_ISEMPTY_THIS, NULL, NULL);
7661+
CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;
76577662
} else if (zend_try_compile_cv(&var_node, var_ast) == SUCCESS) {
76587663
opline = zend_emit_op(result, ZEND_ISSET_ISEMPTY_CV, &var_node, NULL);
76597664
} else {

Zend/zend_compile.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,9 @@ typedef struct _zend_oparray_context {
333333
/* function is a destructor | | | */
334334
#define ZEND_ACC_DTOR (1 << 29) /* | X | | */
335335
/* | | | */
336+
/* closure uses $this | | | */
337+
#define ZEND_ACC_USES_THIS (1 << 30) /* | X | | */
338+
/* | | | */
336339
/* op_array uses strict mode types | | | */
337340
#define ZEND_ACC_STRICT_TYPES (1U << 31) /* | X | | */
338341

Zend/zend_opcode.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ ZEND_API void destroy_zend_function(zend_function *function)
104104

105105
void zend_free_internal_arg_info(zend_internal_function *function) {
106106
if ((function->fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) &&
107-
!function->scope && function->arg_info) {
107+
function->arg_info) {
108108

109109
uint32_t i;
110110
uint32_t num_args = function->num_args + 1;
@@ -135,7 +135,10 @@ ZEND_API void zend_function_dtor(zval *zv)
135135
ZEND_ASSERT(function->common.function_name);
136136
zend_string_release_ex(function->common.function_name, 1);
137137

138-
zend_free_internal_arg_info(&function->internal_function);
138+
/* For methods this will be called explicitly. */
139+
if (!function->common.scope) {
140+
zend_free_internal_arg_info(&function->internal_function);
141+
}
139142

140143
if (!(function->common.fn_flags & ZEND_ACC_ARENA_ALLOCATED)) {
141144
pefree(function, 1);
@@ -352,8 +355,7 @@ ZEND_API void destroy_zend_class(zval *zv)
352355
ZEND_HASH_FOREACH_PTR(&ce->function_table, fn) {
353356
if ((fn->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) &&
354357
fn->common.scope == ce) {
355-
/* reset function scope to allow arg_info removing */
356-
fn->common.scope = NULL;
358+
zend_free_internal_arg_info(&fn->internal_function);
357359
}
358360
} ZEND_HASH_FOREACH_END();
359361

0 commit comments

Comments
 (0)