简体   繁体   English

如何使用 PHP 扩展覆盖内部 Zend 函数?

[英]How can I overwrite an internal Zend function with a PHP extension?

Hope this isn't too silly a question to ask.希望这不是一个太愚蠢的问题。 I'm fairly new to C and PHP internals but looking to learn more about them.我对 C 和 PHP 内部结构相当陌生,但希望了解更多关于它们的信息。

I've recently began looking into development of PHP extensions.我最近开始研究 PHP 扩展的开发。 I'm trying to overwrite an internal function to perform some action, before it executes the original function.在执行原始函数之前,我试图覆盖内部函数以执行某些操作。

I found an example on http://www.phpinternalsbook.com/php7/extensions_design/hooks.html where they overwrite the var_dump() function.我在http://www.phpinternalsbook.com/php7/extensions_design/hooks.html上找到了一个例子,它们覆盖了 var_dump() 函数。 Though I tried to build on this and compile it but can't seem to get it working properly.虽然我试图在此基础上构建并编译它,但似乎无法使其正常工作。

Here's the code I currently have:这是我目前拥有的代码:

php_hook.c: php_hook.c:

// include the PHP API itself
#include <php.h>
// then include the header of your extension
#include "php_hook.h"

// register our function to the PHP API 
// so that PHP knows, which functions are in this module
zend_function_entry hook_php_functions[] = {
    ZEND_NAMED_FE(my_overwrite_var_dump, my_overwrite_var_dump, NULL)
    {NULL, NULL, NULL}
};

// some pieces of information about our module
zend_module_entry hook_php_module_entry = {
    STANDARD_MODULE_HEADER,
    PHP_HOOK_EXTNAME,
    hook_php_functions,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    PHP_HOOK_VERSION,
    STANDARD_MODULE_PROPERTIES
};

// use a macro to output additional C code, to make ext dynamically loadable
ZEND_GET_MODULE(hook_php)

#if PHP_VERSION_ID < 70200
typedef void (*zif_handler)(INTERNAL_FUNCTION_PARAMETERS);
#endif
zif_handler original_handler_var_dump;

ZEND_NAMED_FUNCTION(my_overwrite_var_dump)
{
    php_printf("hooked (var_dump))\n");
    // if we want to call the original function
    original_handler_var_dump(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}

PHP_MINIT_FUNCTION(hook_php)
{
    zend_function *original;

    original = zend_hash_str_find_ptr(EG(function_table), "var_dump", sizeof("var_dump")-1);

    if (original != NULL) {
        original_handler_var_dump = original->internal_function.handler;
        original->internal_function.handler = my_overwrite_var_dump;
    }
}

config.m4:配置.m4:

PHP_ARG_ENABLE(php_hook, Whether to enable the HelloWorldPHP extension, [ --enable-hook-php Enable HelloWorldPHP])

if test "$PHP_HOOK" != "no"; then
    PHP_NEW_EXTENSION(php_hook, php_hook.c, $ext_shared)
fi

php_hook.h: php_hook.h:

// we define Module constants
#define PHP_HOOK_EXTNAME "php_hook"
#define PHP_HOOK_VERSION "0.0.1"

// then we declare the function to be exported
ZEND_NAMED_FUNCTION(my_overwrite_var_dump);

When I call var_dump(1) it just returns int(1) still.当我调用var_dump(1)它仍然只返回int(1) I'm on PHP 7.3 currently.我目前使用的是 PHP 7.3。

I haven´t tested it but I think something like this should work:我还没有测试过,但我认为这样的事情应该可行:

...

PHP_FUNCTION(my_overwrite_var_dump)
{
    php_printf("hooked (var_dump))\n");
    // if we want to call the original function
    original_handler_var_dump(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}


PHP_MINIT_FUNCTION(hook_php)
{
    zend_function *original;

    original = zend_hash_str_find_ptr(CG(function_table), "var_dump", sizeof("var_dump")-1);

    if (original != NULL) {
        original_handler_var_dump = original->internal_function.handler;
        original->internal_function.handler = PHP_FN(my_overwrite_var_dump);
    }
}

Things I changed:我改变的事情:

  • Instead of ZEND_NAMED_FUNCTION I used PHP_FUNCTION取而代之的ZEND_NAMED_FUNCTION我用PHP_FUNCTION
  • Instead of EG() I used CG()我使用CG()而不是EG() CG()
  • The last thing is that in order to overwrite the handler you have to use PHP_FN(my_overwrite_var_dump)最后一件事是,为了覆盖处理程序,您必须使用PHP_FN(my_overwrite_var_dump)

Let me know how it goes!让我知道事情的后续!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM