fix(php): 修复PHP嵌入模式下的模块注册和字符串释放问题

- 在模块注册失败时返回错误码255而不是继续执行
- 在模块启动失败时返回错误码255而不是继续执行
- 添加注释解释PHP内部字符串处理的bug
- 在请求关闭时手动从模块表中删除内部字符串以防止重复释放
- 防止use-after-free内存安全问题的发生
pull/1/head
韩天峰 7 months ago
parent 0d5d91ec02
commit 3931d77ceb
  1. 21
      src/cpp/main.cc

@ -20,13 +20,15 @@ int main(int cpp_argc, char **cpp_argv) {
zend_throw_exception_hook = throw_exception;
zend_module_entry *module = php_embed_get_module();
if (zend_register_module_ex(module, MODULE_PERSISTENT) == NULL) {
if (zend_register_module_ex(module, MODULE_PERSISTENT) == NULL) {
zend_error(E_ERROR, "Failed to register module [%s]", module->name);
}
return 255;
}
if (zend_startup_module_ex(module) == FAILURE) {
if (zend_startup_module_ex(module) == FAILURE) {
zend_error(E_ERROR, "Failed to startup module [%s]", module->name);
}
return 255;
}
int rc = 0;
#if PPROF_ON
@ -50,10 +52,15 @@ int main(int cpp_argc, char **cpp_argv) {
php_app_clean();
php::request_shutdown();
/**
* There is a bug in PHP's handling of internal strings. All interned strings are released in the request shutdown
* function, but then released again in the php_embed_shutdown function, resulting in a use-after-free issue. These
* must be manually removed from the module table to prevent double release.
*/
auto name_len = strlen(module->name);
auto lcname = zend_string_alloc(name_len, module->type == MODULE_PERSISTENT);
zend_str_tolower_copy(ZSTR_VAL(lcname), module->name, name_len);
zend_hash_del(&module_registry, lcname);
auto lcname = zend_string_alloc(name_len, module->type == MODULE_PERSISTENT);
zend_str_tolower_copy(ZSTR_VAL(lcname), module->name, name_len);
zend_hash_del(&module_registry, lcname);
php_embed_shutdown();

Loading…
Cancel
Save