Skip to content

Commit e2ad4e0

Browse files
committed
fix #46304: Defining namespaced constant using define() uses case sensitive match for namespace
1 parent 47a8643 commit e2ad4e0

File tree

2 files changed

+86
-4
lines changed

2 files changed

+86
-4
lines changed

Zend/tests/bug46304.phpt

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
--TEST--
2+
Bug #46304 (defining namespaced constant using define())
3+
--FILE--
4+
<?php
5+
6+
define('NS1\ns2\const1','value1');
7+
define('ns1\ns2\const2','value2');
8+
define('ns1\NS2\coNSt3','value3');
9+
define('NS1\ns2\const4','value4', true);
10+
define('ns1\ns2\const5','value5', true);
11+
define('ns1\NS2\coNSt6','value6', true);
12+
13+
print NS1\ns2\const1 . "\n";
14+
print ns1\ns2\const1 . "\n";
15+
print ns1\NS2\const1 . "\n";
16+
17+
print NS1\ns2\const2 . "\n";
18+
print ns1\ns2\const2 . "\n";
19+
print ns1\NS2\const2 . "\n";
20+
21+
print NS1\ns2\coNSt3 . "\n";
22+
print ns1\ns2\coNSt3 . "\n";
23+
print ns1\ns2\coNSt3 . "\n";
24+
25+
print NS1\ns2\const4 . "\n";
26+
print ns1\ns2\const4 . "\n";
27+
print ns1\NS2\const4 . "\n";
28+
print ns1\ns2\coNSt4 . "\n";
29+
30+
print NS1\ns2\const5 . "\n";
31+
print ns1\ns2\const5 . "\n";
32+
print ns1\NS2\const5 . "\n";
33+
print ns1\ns2\coNSt5 . "\n";
34+
35+
print NS1\ns2\const6 . "\n";
36+
print ns1\ns2\const6 . "\n";
37+
print ns1\NS2\const6 . "\n";
38+
print ns1\ns2\coNSt6 . "\n";
39+
40+
print NS1\ns2\coNSt1 . "\n";
41+
?>
42+
--EXPECTF--
43+
value1
44+
value1
45+
value1
46+
value2
47+
value2
48+
value2
49+
value3
50+
value3
51+
value3
52+
value4
53+
value4
54+
value4
55+
value4
56+
value5
57+
value5
58+
value5
59+
value5
60+
value6
61+
value6
62+
value6
63+
value6
64+
65+
Fatal error: Undefined constant 'NS1\ns2\coNSt1' in %s\bug46304.php on line %d

Zend/zend_constants.c

+21-4
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result,
357357
int const_name_len = name_len - prefix_len - 1;
358358
char *constant_name = colon + 1;
359359
char *lcname;
360+
int found_const = 0;
360361

361362
lcname = zend_str_tolower_dup(name, prefix_len);
362363
/* Check for namespace constant */
@@ -367,16 +368,25 @@ ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result,
367368
memcpy(lcname + prefix_len + 1, constant_name, const_name_len + 1);
368369

369370
if (zend_hash_find(EG(zend_constants), lcname, prefix_len + 1 + const_name_len + 1, (void **) &c) == SUCCESS) {
370-
efree(lcname);
371+
found_const = 1;
372+
} else {
373+
/* try lowercase */
374+
zend_str_tolower(lcname + prefix_len + 1, const_name_len);
375+
if (zend_hash_find(EG(zend_constants), lcname, prefix_len + 1 + const_name_len + 1, (void **) &c) == SUCCESS) {
376+
if ((c->flags & CONST_CS) == 0) {
377+
found_const = 1;
378+
}
379+
}
380+
}
381+
efree(lcname);
382+
if(found_const) {
371383
*result = c->value;
372384
zval_update_constant_ex(&result, (void*)1, NULL TSRMLS_CC);
373385
zval_copy_ctor(result);
374386
Z_SET_REFCOUNT_P(result, 1);
375387
Z_UNSET_ISREF_P(result);
376388
return 1;
377389
}
378-
379-
efree(lcname);
380390
/* name requires runtime resolution, need to check non-namespaced name */
381391
if ((flags & IS_CONSTANT_UNQUALIFIED) != 0) {
382392
name = constant_name;
@@ -414,7 +424,14 @@ ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
414424
zend_str_tolower(lowercase_name, c->name_len-1);
415425
name = lowercase_name;
416426
} else {
417-
name = c->name;
427+
char *slash = strrchr(c->name, '\\');
428+
if(slash) {
429+
lowercase_name = estrndup(c->name, c->name_len-1);
430+
zend_str_tolower(lowercase_name, slash-c->name);
431+
name = lowercase_name;
432+
} else {
433+
name = c->name;
434+
}
418435
}
419436

420437
if ((strncmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1) == 0) ||

0 commit comments

Comments
 (0)