将 HashTable 数据从 php.ini 传递到扩展方法:损坏的值

Posted

技术标签:

【中文标题】将 HashTable 数据从 php.ini 传递到扩展方法:损坏的值【英文标题】:Passing HashTable data from php.ini to an extension method: corrupted values 【发布时间】:2021-01-03 03:44:59 【问题描述】:

我正在尝试使 php (7.4) 扩展在扩展方法中使用来自 php.ini(如 myext.map=key1=val1,key2=val2;)的设置被解析为关联数组。我希望解析发生在PHP_MINIT_FUNCTION(myext)

所以,我声明了一个 php 设置,在 PHP_MINIT_FUNCTION(myext) 中未注释 REGISTER_INI_ENTRIES();,声明:

ZEND_BEGIN_MODULE_GLOBALS(myext)
    HashTable map;
ZEND_END_MODULE_GLOBALS(myext)

并从php.ini 设置JR 填充MYEXT_G(map)

PHP_INI_MH(myext_update_map) 
// The part that parses new_value into (key => val) pairs is skipped. It works.
//...
// key = val assignments have been counted.
zend_hash_init(&MYEXT_G(map), count, NULL, NULL, 1); // 1 for "persistent".
// ...
// Iterating (key => value) pairs.
    // key, key_len, val, val_len have been successfully extracted from php.ini.
    zend_string * key_z = zend_string_init( key, key_len, 1 );
    zval val_z;
    ZVAL_STRINGL( &val_z, val, val_len );
    zend_hash_add_new( &MYEXT_G(map), key_z, &val_z );

然后,在 PHP 方法中,我尝试从 &MYEXT_G(map) 读取数据:

PHP_METHOD(MyExt, getMap) 
// ...
zend_string * key_z;
zval * val_z;
ZEND_HASH_FOREACH_STR_KEY_VAL(&MYEXT_G(map), key_z, val_z)
    php_error_docref( NULL TSRMLS_CC, E_WARNING, "ZSTR_VAL(key_z) = %s\n", ZSTR_VAL(key_z) );
    php_error_docref( NULL TSRMLS_CC, E_WARNING, "Z_STRVAL_P(val_z) = %s\n", Z_STRVAL_P(val_z) );
    php_error_docref( NULL TSRMLS_CC, E_WARNING, "Z_STRLEN_P(val_z) = %lu\n", Z_STRLEN_P(val_z) );
ZEND_HASH_FOREACH_END();

如果从命令行调用包含MyExt::getLibraries() 的PHP 脚本,PHP 警告会打印在php.ini 中设置的键和值。

但是,如果脚本是由 HTTP 请求调用的,在警告消息中,ZSTR_VAL(key_z) 是正确的,但 Z_STRVAL_P(val_z)Z_STRLEN_P(val_z) 都包含垃圾。

所有涉及的函数要么定义为 PHP 宏,要么接收TSRMLS_DC

似乎全局哈希表中的值(但不是键)在模块初始化和服务 HTTP 请求之间被释放。

我已确保 MYEXT_G 中的标量值从 PHP_MINIT_FUNCTION(myExt) 保留到从 HTTP 请求调用的 PHP 方法中。

那么,我怎样才能确保 HashTable 值真正持久?

【问题讨论】:

【参考方案1】:

正如我在 PHP 内部 (internals@lists.php.net) 中得到的建议,ZVAL_STRINGL 分配了一个每个请求的字符串;我需要ZVAL_STRZVAL_STR(&val_z, zend_string_init(val, val_len, 1));

然后我在全局哈希表中添加了val_zzend_hash_str_add_new( &MYEXT_G(map), key_z, key_len, &val_z );。在处理 HTTP 请求时,哈希表 &MYEXT_G(map) 是可读的(键和值)。

【讨论】:

以上是关于将 HashTable 数据从 php.ini 传递到扩展方法:损坏的值的主要内容,如果未能解决你的问题,请参考以下文章

怎么在php.ini 里面配置临时上传目录?

PHP中传值与传引用的区别 能举一个例子吗

如何从我的CPanel访问php.ini?

PHP如何增加session.gc_maxlifetime?更改 php.ini 不起作用

不同版本的php.ini默认文件可以自己下载吗?

即使更改了 php.ini 文件,文件也太大而无法上传到服务器