Skip to content

Commit a98765f

Browse files
committed
Merge remote-tracking branch 'php/master' into win_mb_path_w_only
* php/master: fix typo hard_timeout ignored on TS fix hard_timeout support in shutdown functions fix broken skipif and add xfail for now missing return Fix VERIFY_RETURN_TYPE elision Fix bug71843.phpt Check SKIP_SLOW_TESTS in issue0140.phpt Fix SSA NOP removal Fix handling of parse_str() with unpack in optimizer Don't optimize special dynamic calls to non-dynamic Add new test for openssl_pkey_new Add test for openssl_error_string Remove openssl_x509_parse for OpenSSL 0.9.x Fixed bug #53432 Fix typo Forbid ?void More explicit errors for return; vs return null; Forbid "return;" for typed returns already at compile-time Small generator-related cleanups
2 parents 84a6920 + edf769c commit a98765f

31 files changed

+992
-935
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ PHP NEWS
1010
. Change statement and fcall extension handlers to accept frame. (Joe)
1111
. Implemented safe execution timeout handling, that prevents random crashes
1212
after "Maximum execution time exceeded" error. (Dmitry)
13+
. Fixed bug #53432 (Assignment via string index access on an empty string
14+
converts to array). (Nikita)
1315
. Fixed bug #62210 (Exceptions can leak temporary variables). (Dmitry, Bob)
1416
. Fixed bug #62814 (It is possible to stiffen child class members visibility).
1517
(Nikita)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Pull Requests
1010
=============
1111
PHP accepts pull requests via github. Discussions are done on github, but
1212
depending on the topic can also be relayed to the official PHP developer
13-
mailinglist internals@lists.php.net.
13+
mailing list internals@lists.php.net.
1414

1515
New features require an RFC and must be accepted by the developers.
1616
See https://wiki.php.net/rfc and https://wiki.php.net/rfc/voting for more

Zend/tests/bug53432.phpt

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
--TEST--
2+
Bug #53432: Assignment via string index access on an empty string converts to array
3+
--FILE--
4+
<?php
5+
6+
$str = '';
7+
var_dump($str[0] = 'a');
8+
var_dump($str);
9+
10+
$str = '';
11+
var_dump($str[5] = 'a');
12+
var_dump($str);
13+
14+
$str = '';
15+
var_dump($str[-1] = 'a');
16+
var_dump($str);
17+
18+
$str = '';
19+
var_dump($str['foo'] = 'a');
20+
var_dump($str);
21+
22+
$str = '';
23+
try {
24+
var_dump($str[] = 'a');
25+
} catch (Error $e) {
26+
echo "Error: {$e->getMessage()}\n";
27+
}
28+
var_dump($str);
29+
30+
?>
31+
--EXPECTF--
32+
string(1) "a"
33+
string(1) "a"
34+
string(1) "a"
35+
string(6) " a"
36+
37+
Warning: Illegal string offset: -1 in %s on line %d
38+
NULL
39+
string(0) ""
40+
41+
Warning: Illegal string offset 'foo' in %s on line %d
42+
string(1) "a"
43+
string(1) "a"
44+
Error: [] operator not supported for strings
45+
string(0) ""

Zend/tests/dynamic_call_008.phpt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
--TEST--
2+
Don't optimize dynamic call to non-dynamic one if it drops the warning
3+
--FILE--
4+
<?php
5+
6+
function test() {
7+
((string) 'extract')(['a' => 42]);
8+
}
9+
test();
10+
11+
?>
12+
--EXPECTF--
13+
Warning: Cannot call extract() dynamically in %s on line %d

Zend/tests/indexing_001.phpt

Lines changed: 9 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,23 @@ foreach ($testvalues as $testvalue) {
1212
}
1313
echo "\n*** Indexing - Testing reference assignment with key ***\n";
1414

15-
$testvalues=array(null, 0, 1, true, false,'',0.1,array());
15+
$testvalues=array(null, 0, 1, true, false,0.1,array());
1616

1717
foreach ($testvalues as $testvalue) {
1818
$testvalue['foo']=&$array;
1919
var_dump ($testvalue);
2020
}
2121
echo "*** Indexing - Testing value assignment no key ***\n";
2222
$array=array(1);
23-
$testvalues=array(null, 0, 1, true, false,'',0.1,array());
23+
$testvalues=array(null, 0, 1, true, false,0.1,array());
2424

2525
foreach ($testvalues as $testvalue) {
2626
$testvalue[]=$array;
2727
var_dump ($testvalue);
2828
}
2929
echo "\n*** Indexing - Testing reference assignment no key ***\n";
3030

31-
$testvalues=array(null, 0, 1, true, false,'',0.1,array());
31+
$testvalues=array(null, 0, 1, true, false,0.1,array());
3232

3333
foreach ($testvalues as $testvalue) {
3434
$testvalue[]=&$array;
@@ -63,13 +63,11 @@ array(1) {
6363
int(1)
6464
}
6565
}
66-
array(1) {
67-
["foo"]=>
68-
array(1) {
69-
[0]=>
70-
int(1)
71-
}
72-
}
66+
67+
Warning: Illegal string offset 'foo' in %s on line %d
68+
69+
Notice: Array to string conversion in %s on line %d
70+
string(1) "A"
7371

7472
Warning: Illegal string offset 'foo' in %s on line %d
7573

@@ -110,13 +108,6 @@ array(1) {
110108
int(1)
111109
}
112110
}
113-
array(1) {
114-
["foo"]=>
115-
&array(1) {
116-
[0]=>
117-
int(1)
118-
}
119-
}
120111

121112
Warning: Cannot use a scalar value as an array in %s on line %d
122113
float(0.1)
@@ -151,13 +142,6 @@ array(1) {
151142
int(1)
152143
}
153144
}
154-
array(1) {
155-
[0]=>
156-
array(1) {
157-
[0]=>
158-
int(1)
159-
}
160-
}
161145

162146
Warning: Cannot use a scalar value as an array in %s on line %d
163147
float(0.1)
@@ -193,13 +177,6 @@ array(1) {
193177
int(1)
194178
}
195179
}
196-
array(1) {
197-
[0]=>
198-
&array(1) {
199-
[0]=>
200-
int(1)
201-
}
202-
}
203180

204181
Warning: Cannot use a scalar value as an array in %s on line %d
205182
float(0.1)
@@ -211,4 +188,4 @@ array(1) {
211188
}
212189
}
213190

214-
Done
191+
Done

Zend/tests/parse_str_with_unpack.phpt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--TEST--
2+
Calling parse_str through argument unpacking
3+
--FILE--
4+
<?php
5+
6+
function test() {
7+
$i = 0;
8+
parse_str(...["i=41"]);
9+
var_dump($i + 1);
10+
}
11+
test();
12+
13+
?>
14+
--EXPECT--
15+
int(42)

Zend/tests/return_types/029.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ function foo() : array {
99
try {
1010
throw new Exception("xxxx");
1111
} finally {
12-
return ;
12+
return null;
1313
}
1414
}
1515

@@ -21,7 +21,7 @@ Stack trace:
2121
#0 %s(%d): foo()
2222
#1 {main}
2323

24-
Next TypeError: Return value of foo() must be of the type array, none returned in %s29.php:%d
24+
Next TypeError: Return value of foo() must be of the type array, null returned in %s29.php:%d
2525
Stack trace:
2626
#0 %s(%d): foo()
2727
#1 {main}

Zend/tests/return_types/bug71092.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ function boom(): array {
99
$data = [['id']];
1010
switch ($data[0]) {
1111
case ['id']:
12-
return;
12+
return null;
1313
}
1414
}
1515

1616
boom();
1717
?>
1818
--EXPECTF--
19-
Fatal error: Uncaught TypeError: Return value of boom() must be of the type array, none returned in %sbug71092.php:%d
19+
Fatal error: Uncaught TypeError: Return value of boom() must be of the type array, null returned in %sbug71092.php:%d
2020
Stack trace:
2121
#0 %s(%d): boom()
2222
#1 {main}

Zend/tests/return_types/void_disallowed1.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ function foo(): void {
99

1010
// Note the lack of function call: function validated at compile-time
1111
--EXPECTF--
12-
Fatal error: A void function must not return a value in %s on line %d
12+
Fatal error: A void function must not return a value (did you mean "return;" instead of "return null;"?) in %s on line %d
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
--TEST--
2+
Nullable typed return without value generates friendlier error message
3+
--FILE--
4+
<?php
5+
6+
function test() : ?int {
7+
return;
8+
}
9+
10+
test();
11+
12+
?>
13+
--EXPECTF--
14+
Fatal error: A function with return type must return a value (did you mean "return null;" instead of "return;"?) in %s on line %d
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
--TEST--
2+
Void cannot be nullable
3+
--FILE--
4+
<?php
5+
6+
function test() : ?void {
7+
}
8+
9+
?>
10+
--EXPECTF--
11+
Fatal error: Void type cannot be nullable in %s on line %d
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
--TEST--
2+
Typed return without value generates compile-time error
3+
--FILE--
4+
<?php
5+
6+
function test() : int {
7+
return;
8+
}
9+
10+
test();
11+
12+
?>
13+
--EXPECTF--
14+
Fatal error: A function with return type must return a value in %s on line %d

Zend/zend_compile.c

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2264,12 +2264,19 @@ static zend_op *zend_delayed_compile_end(uint32_t offset) /* {{{ */
22642264
}
22652265
/* }}} */
22662266

2267-
static void zend_emit_return_type_check(znode *expr, zend_arg_info *return_info) /* {{{ */
2267+
static void zend_emit_return_type_check(
2268+
znode *expr, zend_arg_info *return_info, zend_bool implicit) /* {{{ */
22682269
{
22692270
/* `return ...;` is illegal in a void function (but `return;` isn't) */
22702271
if (return_info->type_hint == IS_VOID) {
22712272
if (expr) {
2272-
zend_error_noreturn(E_COMPILE_ERROR, "A void function must not return a value");
2273+
if (expr->op_type == IS_CONST && Z_TYPE(expr->u.constant) == IS_NULL) {
2274+
zend_error_noreturn(E_COMPILE_ERROR,
2275+
"A void function must not return a value "
2276+
"(did you mean \"return;\" instead of \"return null;\"?)");
2277+
} else {
2278+
zend_error_noreturn(E_COMPILE_ERROR, "A void function must not return a value");
2279+
}
22732280
}
22742281
/* we don't need run-time check */
22752282
return;
@@ -2278,6 +2285,17 @@ static void zend_emit_return_type_check(znode *expr, zend_arg_info *return_info)
22782285
if (return_info->type_hint != IS_UNDEF) {
22792286
zend_op *opline;
22802287

2288+
if (!expr && !implicit) {
2289+
if (return_info->allow_null) {
2290+
zend_error_noreturn(E_COMPILE_ERROR,
2291+
"A function with return type must return a value "
2292+
"(did you mean \"return null;\" instead of \"return;\"?)");
2293+
} else {
2294+
zend_error_noreturn(E_COMPILE_ERROR,
2295+
"A function with return type must return a value");
2296+
}
2297+
}
2298+
22812299
if (expr && expr->op_type == IS_CONST) {
22822300
if ((return_info->type_hint == Z_TYPE(expr->u.constant))
22832301
||((return_info->type_hint == _IS_BOOL)
@@ -2312,7 +2330,7 @@ void zend_emit_final_return(int return_one) /* {{{ */
23122330
zend_bool returns_reference = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
23132331

23142332
if (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
2315-
zend_emit_return_type_check(NULL, CG(active_op_array)->arg_info - 1);
2333+
zend_emit_return_type_check(NULL, CG(active_op_array)->arg_info - 1, 1);
23162334
}
23172335

23182336
zn.op_type = IS_CONST;
@@ -3183,11 +3201,7 @@ ZEND_API zend_uchar zend_get_call_op(const zend_op *init_op, zend_function *fbc)
31833201
}
31843202
} else {
31853203
if (zend_execute_ex == execute_ex) {
3186-
if (!(fbc->common.fn_flags & ZEND_ACC_GENERATOR)) {
3187-
return ZEND_DO_UCALL;
3188-
} else {
3189-
return ZEND_DO_FCALL_BY_NAME;
3190-
}
3204+
return ZEND_DO_UCALL;
31913205
}
31923206
}
31933207
} else if (zend_execute_ex == execute_ex &&
@@ -4062,7 +4076,8 @@ void zend_compile_return(zend_ast *ast) /* {{{ */
40624076

40634077
/* Generator return types are handled separately */
40644078
if (!(CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) && CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
4065-
zend_emit_return_type_check(expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1);
4079+
zend_emit_return_type_check(
4080+
expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1, 0);
40664081
}
40674082

40684083
zend_handle_loops_and_finally();
@@ -4949,6 +4964,10 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
49494964

49504965
zend_compile_typename(return_type_ast, arg_infos);
49514966

4967+
if (arg_infos->type_hint == IS_VOID && arg_infos->allow_null) {
4968+
zend_error_noreturn(E_COMPILE_ERROR, "Void type cannot be nullable");
4969+
}
4970+
49524971
arg_infos++;
49534972
op_array->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
49544973
} else {

Zend/zend_execute_API.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,8 +1157,24 @@ static void zend_set_timeout_ex(zend_long seconds, int reset_signals);
11571157

11581158
ZEND_API ZEND_NORETURN void zend_timeout(int dummy) /* {{{ */
11591159
{
1160+
#if defined(PHP_WIN32)
1161+
# ifndef ZTS
1162+
/* No action is needed if we're timed out because zero seconds are
1163+
just ignored. Also, the hard timeout needs to be respected. If the
1164+
timer is not restarted properly, it could hang in the shutdown
1165+
function. */
1166+
if (EG(hard_timeout) > 0) {
1167+
EG(timed_out) = 0;
1168+
zend_set_timeout_ex(EG(hard_timeout), 1);
1169+
/* XXX Abused, introduce an additional flag if the value needs to be kept. */
1170+
EG(hard_timeout) = 0;
1171+
}
1172+
# endif
1173+
#else
11601174
EG(timed_out) = 0;
11611175
zend_set_timeout_ex(0, 1);
1176+
#endif
1177+
11621178
zend_error_noreturn(E_ERROR, "Maximum execution time of %pd second%s exceeded", EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s");
11631179
}
11641180
/* }}} */

Zend/zend_opcode.c

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -642,19 +642,6 @@ ZEND_API int pass_two(zend_op_array *op_array)
642642
/* absolute index to relative offset */
643643
opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value);
644644
break;
645-
case ZEND_VERIFY_RETURN_TYPE:
646-
if (op_array->fn_flags & ZEND_ACC_GENERATOR) {
647-
if (opline->op1_type != IS_UNUSED) {
648-
zend_op *ret = opline;
649-
do ret++; while (ret->opcode != ZEND_RETURN);
650-
651-
ret->op1 = opline->op1;
652-
ret->op1_type = opline->op1_type;
653-
}
654-
655-
MAKE_NOP(opline);
656-
}
657-
break;
658645
case ZEND_RETURN:
659646
case ZEND_RETURN_BY_REF:
660647
if (op_array->fn_flags & ZEND_ACC_GENERATOR) {

0 commit comments

Comments
 (0)