Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,10 @@ PHP NEWS
. Fixed bug GH-23730 (use-after-free when XSLTProcessor::importStylesheet()
is called during a transformation). (David Carlier)

- Zend:
. Fixed use-after-free when a dl()-loaded extension declares a frameless
function and a later request calls it. (Ilia Alshanetsky)

- Zip:
. Fixed ZipArchive::extractTo() ignoring files given in a non-list array.
(David Carlier)
Expand Down
6 changes: 5 additions & 1 deletion Zend/zend_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -2976,7 +2976,11 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend
internal_function->prototype = NULL;
internal_function->prop_info = NULL;
internal_function->attributes = NULL;
internal_function->frameless_function_infos = ptr->frameless_function_infos;
if (type == MODULE_TEMPORARY) {
internal_function->frameless_function_infos = NULL;
} else {
internal_function->frameless_function_infos = ptr->frameless_function_infos;
}
if (EG(active)) { // at run-time: this ought to only happen if registered with dl() or somehow temporarily at runtime
ZEND_MAP_PTR_INIT(internal_function->run_time_cache, zend_arena_calloc(&CG(arena), 1, zend_internal_run_time_cache_reserved_size()));
} else {
Expand Down
22 changes: 22 additions & 0 deletions ext/dl_test/dl_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,28 @@ PHP_FUNCTION(dl_test_test2)
}
/* }}}*/

PHP_FUNCTION(dl_test_frameless)
{
zend_long value;

ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_LONG(value)
ZEND_PARSE_PARAMETERS_END();

RETURN_LONG(value);
}

ZEND_FRAMELESS_FUNCTION(dl_test_frameless, 1)
{
zend_long value;

Z_FLF_PARAM_LONG(1, value);

RETVAL_LONG(value);

flf_clean:;
}

/* {{{ PHP_DL_TEST_USE_REGISTER_FUNCTIONS_DIRECTLY */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_dl_test_use_register_functions_directly, 0, 0, IS_STRING, 0)
ZEND_END_ARG_INFO()
Expand Down
5 changes: 5 additions & 0 deletions ext/dl_test/dl_test.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ function dl_test_test1(): void {}

function dl_test_test2(string $str = ""): string {}

/**
* @frameless-function {"arity": 1}
*/
function dl_test_frameless(int $value): int {}

class DlTest {
public function test(string $str = ""): string {}
}
Expand Down
15 changes: 14 additions & 1 deletion ext/dl_test/dl_test_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions ext/dl_test/tests/frameless_temporary.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php
var_dump(dl_test_frameless(7));
try {
dl_test_frameless("nope");
echo "no throw\n";
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
53 changes: 53 additions & 0 deletions ext/dl_test/tests/frameless_temporary.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
--TEST--
dl() of a frameless function does not keep the freed function record
--SKIPIF--
<?php
if (PHP_OS_FAMILY === 'Windows') {
die('skip setarch -R is required so dl() remaps the extension at the stale handler address');
}
if (!getenv('TEST_PHP_CGI_EXECUTABLE')) {
die('skip php-cgi not available');
}
$setarch = trim((string) shell_exec('command -v setarch'));
if ($setarch === '') {
die('skip setarch -R is required so dl() remaps the extension at the stale handler address');
}
$arch = php_uname('m');
exec($setarch . ' ' . escapeshellarg($arch) . ' -R true', $setarch_out, $setarch_code);
if ($setarch_code !== 0) {
die('skip setarch -R cannot run on ' . $arch);
}
$so = ini_get('extension_dir') . DIRECTORY_SEPARATOR . 'dl_test.so';
if (!file_exists($so)) {
die('skip dl_test extension is not built (tried ' . $so . ')');
}
?>
--FILE--
<?php
$cmd = 'env -u SCRIPT_FILENAME -u PATH_TRANSLATED -u REDIRECT_STATUS -u REQUEST_METHOD -u QUERY_STRING'
. ' USE_ZEND_ALLOC=0 ASAN_OPTIONS=' . escapeshellarg('detect_leaks=0:halt_on_error=1:abort_on_error=1')
. ' setarch ' . escapeshellarg(php_uname('m')) . ' -R '
. escapeshellarg(getenv('TEST_PHP_CGI_EXECUTABLE'))
. ' -n -q -T 2 -d enable_dl=1 -d extension_dir=' . escapeshellarg(ini_get('extension_dir'))
. ' ' . escapeshellarg(__DIR__ . '/frameless_temporary_cgi.inc');
$proc = proc_open($cmd, [
0 => ['pipe', 'r'],
1 => ['pipe', 'w'],
2 => ['pipe', 'w'],
], $pipes);
fclose($pipes[0]);
$out = stream_get_contents($pipes[1]);
stream_get_contents($pipes[2]);
fclose($pipes[1]);
fclose($pipes[2]);
echo $out;
$code = proc_close($proc);
if ($code !== 0) {
echo "exit:$code\n";
}
?>
--EXPECT--
int(7)
dl_test_frameless(): Argument #1 ($value) must be of type int, string given
int(7)
dl_test_frameless(): Argument #1 ($value) must be of type int, string given
7 changes: 7 additions & 0 deletions ext/dl_test/tests/frameless_temporary_cgi.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php
$ext = PHP_OS_FAMILY === 'Windows' ? 'php_dl_test.dll' : 'dl_test.so';
if (!dl($ext)) {
echo "dl failed\n";
return;
}
include __DIR__ . '/frameless_temporary.inc';
19 changes: 19 additions & 0 deletions ext/dl_test/tests/frameless_temporary_opcache.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
--TEST--
dl() does not compile calls to a temporary module's function as frameless
--SKIPIF--
<?php include __DIR__ . "/skip.inc"; ?>
--EXTENSIONS--
opcache
--INI--
enable_dl=1
opcache.enable_cli=1
opcache.opt_debug_level=0x10000
--FILE--
<?php
dl(PHP_OS_FAMILY === 'Windows' ? 'php_dl_test.dll' : 'dl_test.so');
include __DIR__ . '/frameless_temporary.inc';
?>
--EXPECTF--
%A0001 INIT_FCALL 1 %d string("dl_test_frameless")
%Aint(7)
dl_test_frameless(): Argument #1 ($value) must be of type int, string given
Loading