gpt4 book ai didi

php - 在 PHP 7.4 异常的源代码中有 __wakeup 有什么意义?

转载 作者:太空宇宙 更新时间:2023-11-04 04:11:24 26 4
gpt4 key购买 nike

存在一种(相当新的)开发技术,称为 phar deserialisation由 PHP 的 file system functions 触发喜欢file_exists , unlink , ... 然后非序列化代码在实例化类中执行,该实例化类至少需要包含两个魔术方法之一 __wakeup__destruct .

我的想法是在 PHP 的源代码中搜索内置的 PHP 类,这些类可能有这样的魔术方法(__wakeup__destruct)作为这些类的一部分,并且可以在 的反序列化过程中以某种方式被利用异常 处理(这可能会触发一些释放后使用错误)。我确实找到了__wakeup在几个 Exception 类中(获取所有内置类并检查它们是否具有 __wakeup__destruct 方法的简单方法是使用 PHP 函数 get_declared_classes() )。但目前它似乎无法利用。

所以问题不在于利用事物。

问题:我不明白的是为什么例如__wakeup异常中实现?它只是一个占位符方法,用于扩展此类 Exception 类并稍后编写自己的 __wakeup/__destruct方法?

源代码: https://github.com/php/php-src/blob/master/Zend/zend_exceptions.c#L316

第 306-333 行(php-src/Zend/zend_exceptions.c,PHP 7.4):

/* }}} */

/* {{{ proto Exception::__wakeup()
Exception unserialize checks */
#define CHECK_EXC_TYPE(id, type) \
pvalue = zend_read_property_ex(i_get_exception_base(object), (object), ZSTR_KNOWN(id), 1, &value); \
if (Z_TYPE_P(pvalue) != IS_NULL && Z_TYPE_P(pvalue) != type) { \
zend_unset_property(i_get_exception_base(object), object, ZSTR_VAL(ZSTR_KNOWN(id)), ZSTR_LEN(ZSTR_KNOWN(id))); \
}

ZEND_METHOD(exception, __wakeup)
{
zval value, *pvalue;
zval *object = ZEND_THIS;
CHECK_EXC_TYPE(ZEND_STR_MESSAGE, IS_STRING);
CHECK_EXC_TYPE(ZEND_STR_STRING, IS_STRING);
CHECK_EXC_TYPE(ZEND_STR_CODE, IS_LONG);
CHECK_EXC_TYPE(ZEND_STR_FILE, IS_STRING);
CHECK_EXC_TYPE(ZEND_STR_LINE, IS_LONG);
CHECK_EXC_TYPE(ZEND_STR_TRACE, IS_ARRAY);
pvalue = zend_read_property(i_get_exception_base(object), object, "previous", sizeof("previous")-1, 1, &value);
if (pvalue && Z_TYPE_P(pvalue) != IS_NULL && (Z_TYPE_P(pvalue) != IS_OBJECT ||
!instanceof_function(Z_OBJCE_P(pvalue), zend_ce_throwable) ||
pvalue == object)) {
zend_unset_property(i_get_exception_base(object), object, "previous", sizeof("previous")-1);
}
}
/* }}} */

以及后面的第 788-801 行: https://github.com/php/php-src/blob/master/Zend/zend_exceptions.c#L788

static const zend_function_entry default_exception_functions[] = {
ZEND_ME(exception, __clone, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
ZEND_ME(exception, __construct, arginfo_exception___construct, ZEND_ACC_PUBLIC)
ZEND_ME(exception, __wakeup, NULL, ZEND_ACC_PUBLIC)
ZEND_ME(exception, getMessage, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
ZEND_ME(exception, getCode, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
ZEND_ME(exception, getFile, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
ZEND_ME(exception, getLine, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
ZEND_ME(exception, getTrace, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
ZEND_ME(exception, getPrevious, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
ZEND_ME(exception, getTraceAsString, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
ZEND_ME(exception, __toString, NULL, 0)
ZEND_FE_END
};

最佳答案

据我所知,这段代码正在验证异常属性的类型,如果类型不正确,则将它们设置为 null。例如:

CHECK_EXC_TYPE(ZEND_STR_MESSAGE,  IS_STRING);

大致相当于PHP代码:

if (!is_string($this->message))
$this->message = null;

类似地,最后的代码,以 pvalue = zend_read_property(...) 开始,检查 $this->previous 是一个实现了 的对象可抛出。在 PHP 中,它大致等同于:

if (!is_object($this->previous) || !($this->previous instanceof Throwable)
$this->previous = null;

至于为什么这段代码是PHP解释器的一部分?整个 Exception 类都在 C 代码中定义。没有一个内置类或方法是用 PHP 编写的——它们不可能是,因为该语言无法提供将方法的 PHP 实现安装到用 C 声明的类的方法。

关于php - 在 PHP 7.4 异常的源代码中有 __wakeup 有什么意义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56978005/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com