Skip to content

Commit

Permalink
Fix GH-12232: FPM: segfault dynamically loading extension without opc…
Browse files Browse the repository at this point in the history
…ache

Also fixes incorrect assertion in ini init that php_dl is always
temporary.

Closes GH-12277
  • Loading branch information
bukka committed Oct 14, 2023
1 parent d7de0ce commit 0217be4
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 1 deletion.
4 changes: 4 additions & 0 deletions NEWS
Expand Up @@ -8,6 +8,10 @@ PHP NEWS
- Fiber:
. Fixed bug GH-11121 (ReflectionFiber segfault). (danog, trowski, bwoebi)

- FPM:
. Fixed bug GH-12232 (FPM: segfault dynamically loading extension without
opcache). (Jakub Zelenka)

- Opcache:
. Added warning when JIT cannot be enabled. (danog)
. Fixed bug GH-8143 (Crashes in zend_accel_inheritance_cache_find since
Expand Down
1 change: 0 additions & 1 deletion Zend/zend_ini.c
Expand Up @@ -211,7 +211,6 @@ ZEND_API zend_result zend_register_ini_entries_ex(const zend_ini_entry_def *ini_
* lead to death.
*/
if (directives != EG(ini_directives)) {
ZEND_ASSERT(module_type == MODULE_TEMPORARY);
directives = EG(ini_directives);
} else {
ZEND_ASSERT(module_type == MODULE_PERSISTENT);
Expand Down
2 changes: 2 additions & 0 deletions sapi/fpm/fpm/fpm_php.c
Expand Up @@ -87,7 +87,9 @@ int fpm_php_apply_defines_ex(struct key_value_s *kv, int mode) /* {{{ */

if (!strcmp(name, "extension") && *value) {
zval zv;
zend_interned_strings_switch_storage(0);
php_dl(value, MODULE_PERSISTENT, &zv, 1);
zend_interned_strings_switch_storage(1);
return Z_TYPE(zv) == IS_TRUE;
}

Expand Down
51 changes: 51 additions & 0 deletions sapi/fpm/tests/gh12232-php-value-extension.phpt
@@ -0,0 +1,51 @@
--TEST--
FPM: gh12232 - loading shared ext in FPM config
--SKIPIF--
<?php
include "skipif.inc";
FPM\Tester::skipIfSharedExtensionNotFound('dl_test');
?>
--FILE--
<?php

require_once "tester.inc";

$cfg = <<<EOT
[global]
error_log = {{FILE:LOG}}
[unconfined]
listen = {{ADDR}}
pm = static
pm.max_children = 1
pm.status_path = /status
catch_workers_output = yes
php_admin_value[extension] = dl_test
EOT;

$code = <<<EOT
<?php
var_dump(extension_loaded('dl_test'));
var_dump(ini_get('dl_test.string'));
ini_set('dl_test.string', 'test');
var_dump(ini_get('dl_test.string'));
EOT;

$tester = new FPM\Tester($cfg, $code);
$tester->start();
$tester->expectLogStartNotices();
$tester->request()->expectBody(['bool(true)', 'string(5) "hello"', 'string(4) "test"']);
$tester->request()->expectBody(['bool(true)', 'string(5) "hello"', 'string(4) "test"']);
$tester->terminate();
$tester->expectLogTerminatingNotices();
$tester->close();

?>
Done
--EXPECT--
Done
--CLEAN--
<?php
require_once "tester.inc";
FPM\Tester::clean();
?>
<?php
11 changes: 11 additions & 0 deletions sapi/fpm/tests/tester.inc
Expand Up @@ -319,6 +319,17 @@ class Tester
}
}

/**
* Skip if shared extension is not available in extension directory.
*/
static public function skipIfSharedExtensionNotFound($extensionName)
{
$soPath = ini_get('extension_dir') . '/' . $extensionName . '.so';
if ( ! file_exists($soPath)) {
die("skip $extensionName extension not present in extension_dir");
}
}

/**
* Tester constructor.
*
Expand Down

0 comments on commit 0217be4

Please sign in to comment.