PHP-致命错误:无法访问以'\0';

PHP-致命错误:无法访问以'\0';,php,Php,这一定是我在jsut中遇到的最奇怪的错误之一,因为在另外两个系统上完全相同的代码可以正常工作 让我解释一下我的设置,以及它是如何工作的,在哪里工作的。首先,我使用的是zend框架,错误被抛出到第300行的zend/View/Abstract类中 运行PHP5.3.3的Windows系统-在这里运行良好。 运行PHP5.3.3的Linux Centos 5.5系统在这里运行良好。 运行PHP5.3.6的Linux Centos 5.5系统-此系统给出了致命错误 PHP-致命错误:无法访问以“\0”

这一定是我在jsut中遇到的最奇怪的错误之一,因为在另外两个系统上完全相同的代码可以正常工作

让我解释一下我的设置,以及它是如何工作的,在哪里工作的。首先,我使用的是zend框架,错误被抛出到第300行的zend/View/Abstract类中

运行PHP5.3.3的Windows系统-在这里运行良好。 运行PHP5.3.3的Linux Centos 5.5系统在这里运行良好。 运行PHP5.3.6的Linux Centos 5.5系统-此系统给出了致命错误

PHP-致命错误:无法访问以“\0”开头的属性

在查看设置时,我首先认为这一定是PHP中的一个bug,但我不太确定。我首先安装了PHP5.3.5并升级到了5.3.6,但这没有帮助

抛出错误的代码也应该起作用,所以我完全搞不懂为什么我在这个系统上而不是在另外两个系统上得到错误

引发错误的代码是:

$this->$key = $val;
采用以下方法定位:

public function __set($key, $val)
{
        if ('_' != substr($key, 0, 1)) {
            $this->$key = $val;
            return;
        }

        require_once 'Zend/View/Exception.php';
        $e = new Zend_View_Exception('Setting private or protected class members is not allowed');
        $e->setView($this);
        throw $e;
}
任何帮助都将不胜感激


我做了一些进一步的调试,它不是导致错误的变量之一。我发现,当$key变量设置为Zend_View_useViewStream时,会抛出致命错误,因此我在字符串修剪之前和之后都转储了它

KEY string(25) "Zend_View_useViewStream" 
TRIMMED string(24) "Zend_View_useViewStream" 

正如您所看到的,当变量未被修剪时,字符串长度长1个字符,但它们对我来说似乎相同??我猜nul字节[“\0”(ASCII 0(0x00)),nul字节.]正在用trim剥离,但为什么它被添加到这个系统而不是其他系统上?

我不确定,但我假设
$key
是一个以
“\0”
是当您尝试设置不存在的属性时调用的。如果它在
Zend\u View\u Abstract
中抛出错误,则您的一个视图试图设置一个不存在的实例属性,并且实例属性以空字符开头

$this->$property = $value;
你可以试着去看看房子

$property = trim($property);
$this->$property = $value;

我感觉有东西试图错误地修改
$this
。你能在你的视图中找到代码吗?

我会再次说这是语言环境问题。但目前的PHP版本似乎已经强化了这一点:

    if (Z_STRVAL_P(member)[0] == '\0') {
            if (!silent) {
                    if (Z_STRLEN_P(member) == 0) {
                            zend_error(E_ERROR, "Cannot access empty property");
                    } else {
                            zend_error(E_ERROR, "Cannot access property started with '\\0'");
                    }
            }
            return NULL;
所以我们可以得出结论,这是在PHP5.3.3到5.3.6之间引入的。(我的版本是5.3.2,效果相同,但可能是一个后端口补丁)。在变更日志中找不到任何指示原因的内容

无论如何,如果不确保二进制属性名不以NUL开头,则不能使用二进制属性名

--

PHP 5.0.0和PHP 5.1.0之间已发生更改:

我怀疑这就是原因:

if (prop_info_name[0] == '\0' && prop_info_name[1] != '*' && !(property_info->flags & ZEND_ACC_PRIVATE)) {
    /* we we're looking for a private prop but found a non private one of the same name */
    return FAILURE;
}

我还没有仔细看过,但从那段代码中,我假设
\0
字节最初用于不同的用途,后来被禁止使用。

如何设置值?在将其用作属性名之前,如果尝试打印($key),会发生什么情况?显然,出于某种原因,它以\0开头。@RobertPitt:我不这么认为,这很可能是解决方案。它只是没有被说成一个。@soulmerge,他指出它在几个操作系统上工作,但问题是由Centos造成的,哪一个**显然**表示一个环境OK如果我修剪$key变量它会工作,但这不是最好的解决方案,因为我正在修改zend framework库中的代码。我仍然不知道为什么它在另外两个系统上工作,而在这个系统上不工作。@Ilan那么,
$key
来自哪里?您可能应该检查错误中的堆栈跟踪,以找出代码中的哪一位导致调用它。我做了一些进一步的调试,它不是导致错误的变量之一。我发现,当$key变量设置为Zend_View_useViewStream时,会抛出致命错误,因此我在字符串修剪之前和之后都转储了它。键字符串(25)“Zend_View_useViewStream”修剪字符串(24)“Zend_View_useViewStream”可以看到,当变量未修剪时,字符串长度长1个字符,但它们似乎与我相同??空字符
\0
是零宽度字符。看起来什么都不像!当我正确地记得它时,
\0
是在旧版本的PHP中将属性标记为私有的前缀。还有一个黑客使用这个前缀手动访问私有财产。但是由于反射类是可用的,因此不再需要这种攻击。