Skip to content

Commit 359a21f

Browse files
committed
Fix RCN violations in array functions
When the array functions perform their operation in-place, the `@refcount 1` annotation is wrong and causes a failure under `ZEND_VERIFY_FUNC_INFO`. The test file tests all functions that have the in-place optimization, even those that didn't have the refcount annotation, just to prevent future regressions. Closes GH-18929.
1 parent dc79f4c commit 359a21f

File tree

5 files changed

+59
-15
lines changed

5 files changed

+59
-15
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ PHP NEWS
2828

2929
- Standard:
3030
. Fix misleading errors in printf(). (nielsdos)
31+
. Fix RCN violations in array functions. (nielsdos)
3132

3233
- Streams:
3334
. Fixed GH-13264 (fgets() and stream_get_line() do not return false on filter

Zend/Optimizer/zend_func_infos.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -450,8 +450,6 @@ static const func_info_t func_infos[] = {
450450
F1("compact", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF),
451451
FN("array_fill", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_ANY),
452452
F1("array_fill_keys", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF),
453-
F1("array_replace", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF),
454-
F1("array_replace_recursive", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF),
455453
FN("array_keys", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_STRING),
456454
FN("array_values", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF),
457455
F1("array_count_values", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG),
@@ -460,13 +458,8 @@ static const func_info_t func_infos[] = {
460458
F1("array_flip", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_STRING),
461459
F1("array_change_key_case", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF),
462460
F1("array_intersect_key", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF),
463-
F1("array_intersect_ukey", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF),
464-
F1("array_intersect", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF),
465-
F1("array_uintersect", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF),
466461
F1("array_intersect_assoc", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF),
467462
F1("array_uintersect_assoc", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF),
468-
F1("array_intersect_uassoc", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF),
469-
F1("array_uintersect_uassoc", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF),
470463
F1("array_diff_key", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF),
471464
F1("array_diff_ukey", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF),
472465
F1("array_udiff", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF),

ext/standard/basic_functions.stub.php

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1678,13 +1678,11 @@ function array_merge_recursive(array ...$arrays): array {}
16781678

16791679
/**
16801680
* @compile-time-eval
1681-
* @refcount 1
16821681
*/
16831682
function array_replace(array $array, array ...$replacements): array {}
16841683

16851684
/**
16861685
* @compile-time-eval
1687-
* @refcount 1
16881686
*/
16891687
function array_replace_recursive(array $array, array ...$replacements): array {}
16901688

@@ -1757,19 +1755,16 @@ function array_intersect_key(array $array, array ...$arrays): array {}
17571755

17581756
/**
17591757
* @param array|callable $rest
1760-
* @refcount 1
17611758
*/
17621759
function array_intersect_ukey(array $array, ...$rest): array {}
17631760

17641761
/**
17651762
* @compile-time-eval
1766-
* @refcount 1
17671763
*/
17681764
function array_intersect(array $array, array ...$arrays): array {}
17691765

17701766
/**
17711767
* @param array|callable $rest
1772-
* @refcount 1
17731768
*/
17741769
function array_uintersect(array $array, ...$rest): array {}
17751770

@@ -1787,13 +1782,11 @@ function array_uintersect_assoc(array $array, ...$rest): array {}
17871782

17881783
/**
17891784
* @param array|callable $rest
1790-
* @refcount 1
17911785
*/
17921786
function array_intersect_uassoc(array $array, ...$rest): array {}
17931787

17941788
/**
17951789
* @param array|callable $rest
1796-
* @refcount 1
17971790
*/
17981791
function array_uintersect_uassoc(array $array, ...$rest): array {}
17991792

ext/standard/basic_functions_arginfo.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
--TEST--
2+
RCN check for in-place array modifications
3+
--FILE--
4+
<?php
5+
// Important: do NOT replace range(0, 1) with a variable, these NEED to be TMPVARs!
6+
var_dump(array_replace(range(0, 1), []));
7+
var_dump(array_replace_recursive(range(0, 1), []));
8+
var_dump(array_merge(range(0, 1), []));
9+
var_dump(array_merge_recursive(range(0, 1), []));
10+
var_dump(array_unique(range(0, 1)));
11+
var_dump(array_intersect_ukey(range(0, 1), [], fn () => 0));
12+
var_dump(array_intersect(range(0, 1), []));
13+
var_dump(array_uintersect(range(0, 1), [], fn () => 0));
14+
var_dump(array_intersect_uassoc(range(0, 1), [], fn () => 0));
15+
var_dump(array_uintersect_uassoc(range(0, 1), [], fn () => 0, fn () => 0));
16+
?>
17+
--EXPECT--
18+
array(2) {
19+
[0]=>
20+
int(0)
21+
[1]=>
22+
int(1)
23+
}
24+
array(2) {
25+
[0]=>
26+
int(0)
27+
[1]=>
28+
int(1)
29+
}
30+
array(2) {
31+
[0]=>
32+
int(0)
33+
[1]=>
34+
int(1)
35+
}
36+
array(2) {
37+
[0]=>
38+
int(0)
39+
[1]=>
40+
int(1)
41+
}
42+
array(2) {
43+
[0]=>
44+
int(0)
45+
[1]=>
46+
int(1)
47+
}
48+
array(0) {
49+
}
50+
array(0) {
51+
}
52+
array(0) {
53+
}
54+
array(0) {
55+
}
56+
array(0) {
57+
}

0 commit comments

Comments
 (0)