Skip to content

Commit 7aa5a01

Browse files
committed
Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4: ext/opcache: Mark dl()-created persistent strings as thread-local
2 parents ddc5a62 + 77dbc2c commit 7aa5a01

5 files changed

Lines changed: 71 additions & 7 deletions

File tree

‎ext/dl_test/dl_test.stub.php‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public function test(string $str = ""): string {}
2222

2323
class DlTestSuperClass {
2424
public int $a;
25+
public int $temporary = 0;
2526
public function test(string $str = ""): string {}
2627
}
2728

‎ext/dl_test/dl_test_arginfo.h‎

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
try {
3+
dl_test_test2([]);
4+
} catch (TypeError $e) {
5+
echo $e::class, ": ", $e->getMessage(), PHP_EOL;
6+
}
7+
8+
try {
9+
(new DlTest)->test([]);
10+
} catch (TypeError $e) {
11+
echo $e::class, ": ", $e->getMessage(), PHP_EOL;
12+
}
13+
14+
var_dump((new ReflectionFunction('dl_test_test2'))->getName());
15+
16+
var_dump(get_object_vars(new DlTestSubClass));
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
dl() under opcache: refcounting names declared by a temporary module
3+
--SKIPIF--
4+
<?php include __DIR__ . "/skip.inc"; ?>
5+
--EXTENSIONS--
6+
opcache
7+
--INI--
8+
enable_dl=1
9+
opcache.enable_cli=1
10+
--FILE--
11+
<?php
12+
dl(PHP_OS_FAMILY === 'Windows' ? 'php_dl_test.dll' : 'dl_test.so');
13+
include __DIR__ . '/opcache_temporary_strings.inc';
14+
?>
15+
--EXPECT--
16+
TypeError: dl_test_test2(): Argument #1 ($str) must be of type string, array given
17+
TypeError: DlTest::test(): Argument #1 ($str) must be of type string, array given
18+
string(13) "dl_test_test2"
19+
array(1) {
20+
["temporary"]=>
21+
int(0)
22+
}

‎ext/opcache/ZendAccelerator.c‎

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,13 @@ static zend_string* ZEND_FASTCALL accel_new_interned_string_for_php(zend_string
585585
return ret;
586586
}
587587
}
588+
#if ZEND_RC_DEBUG
589+
/* PHP shouldn't create persistent strings during request, but at least
590+
* dl() may do this. They belong to the temporary module and are not shared. */
591+
if (!zend_rc_debug && !ZSTR_IS_INTERNED(str) && (GC_FLAGS(str) & GC_PERSISTENT)) {
592+
GC_MAKE_PERSISTENT_LOCAL(str);
593+
}
594+
#endif
588595
return str;
589596
}
590597

@@ -609,19 +616,31 @@ static zend_always_inline zend_string *accel_find_interned_string_ex(zend_ulong
609616

610617
static zend_string* ZEND_FASTCALL accel_init_interned_string_for_php(const char *str, size_t size, bool permanent)
611618
{
619+
zend_string *ret;
620+
612621
if (ZCG(counted)) {
613622
zend_ulong h = zend_inline_hash_func(str, size);
614-
zend_string *ret = accel_find_interned_string_ex(h, str, size);
623+
ret = accel_find_interned_string_ex(h, str, size);
615624

616-
if (!ret) {
617-
ret = zend_string_init(str, size, permanent);
618-
ZSTR_H(ret) = h;
625+
if (ret) {
626+
return ret;
619627
}
620628

621-
return ret;
629+
ret = zend_string_init(str, size, permanent);
630+
ZSTR_H(ret) = h;
631+
} else {
632+
ret = zend_string_init(str, size, permanent);
622633
}
623634

624-
return zend_string_init(str, size, permanent);
635+
#if ZEND_RC_DEBUG
636+
/* PHP shouldn't create persistent strings during request, but at least
637+
* dl() may do this. They belong to the temporary module and are not shared. */
638+
if (!zend_rc_debug && permanent) {
639+
GC_MAKE_PERSISTENT_LOCAL(ret);
640+
}
641+
#endif
642+
643+
return ret;
625644
}
626645

627646
static inline void accel_copy_permanent_list_types(

0 commit comments

Comments
 (0)