Skip to content

Commit 4c48fd2

Browse files
authored
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.
1 parent 3eeeeeb commit 4c48fd2

File tree

2 files changed

+39
-18
lines changed

2 files changed

+39
-18
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
eval() constant resolution
3+
--FILE--
4+
<?php
5+
namespace foo {
6+
define('foo\true', 'test');
7+
echo "In eval\n";
8+
eval('namespace foo { var_dump(true); var_dump(TrUe); var_dump(namespace\true); var_dump(\true); }');
9+
echo "Outside eval\n";
10+
var_dump(true); var_dump(TrUe); var_dump(namespace\true); var_dump(\true);
11+
}
12+
?>
13+
--EXPECT--
14+
In eval
15+
bool(true)
16+
bool(true)
17+
string(4) "test"
18+
bool(true)
19+
Outside eval
20+
bool(true)
21+
bool(true)
22+
string(4) "test"
23+
bool(true)

Zend/zend_compile.c

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1475,28 +1475,26 @@ static bool can_ct_eval_const(zend_constant *c) {
14751475

14761476
static bool zend_try_ct_eval_const(zval *zv, zend_string *name, bool is_fully_qualified) /* {{{ */
14771477
{
1478-
zend_constant *c = zend_hash_find_ptr(EG(zend_constants), name);
1478+
/* Substitute true, false and null (including unqualified usage in namespaces)
1479+
* before looking up the possibly namespaced name. */
1480+
const char *lookup_name = ZSTR_VAL(name);
1481+
size_t lookup_len = ZSTR_LEN(name);
1482+
1483+
if (!is_fully_qualified) {
1484+
zend_get_unqualified_name(name, &lookup_name, &lookup_len);
1485+
}
1486+
1487+
zend_constant *c;
1488+
if ((c = zend_get_special_const(lookup_name, lookup_len))) {
1489+
ZVAL_COPY_VALUE(zv, &c->value);
1490+
return 1;
1491+
}
1492+
c = zend_hash_find_ptr(EG(zend_constants), name);
14791493
if (c && can_ct_eval_const(c)) {
14801494
ZVAL_COPY_OR_DUP(zv, &c->value);
14811495
return 1;
14821496
}
1483-
1484-
{
1485-
/* Substitute true, false and null (including unqualified usage in namespaces) */
1486-
const char *lookup_name = ZSTR_VAL(name);
1487-
size_t lookup_len = ZSTR_LEN(name);
1488-
1489-
if (!is_fully_qualified) {
1490-
zend_get_unqualified_name(name, &lookup_name, &lookup_len);
1491-
}
1492-
1493-
if ((c = zend_get_special_const(lookup_name, lookup_len))) {
1494-
ZVAL_COPY_VALUE(zv, &c->value);
1495-
return 1;
1496-
}
1497-
1498-
return 0;
1499-
}
1497+
return 0;
15001498
}
15011499
/* }}} */
15021500

0 commit comments

Comments
 (0)