Fix inconsistency in true/false/null constant resolution when opcache is not used (#7441)

Strangely, uses of eval and 'php -a' (or loading a file without opcache after a namespaced constant was declared)
will not treat non-FQ true/false/null as magic keywords, while compiled php required from a file would do that.

This may confuse people learning the language, and result in code loaded with
eval() behaving differently from the same snippet in a file loaded by require.

```
Interactive shell

php > define('foo\true', 'test');
php > namespace foo { var_dump(true); }
string(4) "test"
```

This will make the same session instead properly emit `bool(true);` like it
already would if running those statements in files when opcache was used.
This commit is contained in:
Tyson Andre 2021-09-03 08:42:36 -04:00 committed by GitHub
parent 3eeeeeb104
commit 4c48fd22d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 18 deletions

View File

@ -0,0 +1,23 @@
--TEST--
eval() constant resolution
--FILE--
<?php
namespace foo {
define('foo\true', 'test');
echo "In eval\n";
eval('namespace foo { var_dump(true); var_dump(TrUe); var_dump(namespace\true); var_dump(\true); }');
echo "Outside eval\n";
var_dump(true); var_dump(TrUe); var_dump(namespace\true); var_dump(\true);
}
?>
--EXPECT--
In eval
bool(true)
bool(true)
string(4) "test"
bool(true)
Outside eval
bool(true)
bool(true)
string(4) "test"
bool(true)

View File

@ -1475,28 +1475,26 @@ static bool can_ct_eval_const(zend_constant *c) {
static bool zend_try_ct_eval_const(zval *zv, zend_string *name, bool is_fully_qualified) /* {{{ */
{
zend_constant *c = zend_hash_find_ptr(EG(zend_constants), name);
/* Substitute true, false and null (including unqualified usage in namespaces)
* before looking up the possibly namespaced name. */
const char *lookup_name = ZSTR_VAL(name);
size_t lookup_len = ZSTR_LEN(name);
if (!is_fully_qualified) {
zend_get_unqualified_name(name, &lookup_name, &lookup_len);
}
zend_constant *c;
if ((c = zend_get_special_const(lookup_name, lookup_len))) {
ZVAL_COPY_VALUE(zv, &c->value);
return 1;
}
c = zend_hash_find_ptr(EG(zend_constants), name);
if (c && can_ct_eval_const(c)) {
ZVAL_COPY_OR_DUP(zv, &c->value);
return 1;
}
{
/* Substitute true, false and null (including unqualified usage in namespaces) */
const char *lookup_name = ZSTR_VAL(name);
size_t lookup_len = ZSTR_LEN(name);
if (!is_fully_qualified) {
zend_get_unqualified_name(name, &lookup_name, &lookup_len);
}
if ((c = zend_get_special_const(lookup_name, lookup_len))) {
ZVAL_COPY_VALUE(zv, &c->value);
return 1;
}
return 0;
}
return 0;
}
/* }}} */