Skip to content

Commit 6263f22

Browse files
committed
Handle case sensivity of constants (nikic)
1 parent 28fa089 commit 6263f22

File tree

4 files changed

+62
-25
lines changed

4 files changed

+62
-25
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
importing const with same name but different case
3+
--FILE--
4+
<?php
5+
6+
namespace {
7+
use const foo\bar;
8+
use const foo\BAR;
9+
}
10+
11+
?>
12+
--EXPECT--
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
--TEST--
2+
importing function with same name but different case should fail
3+
--FILE--
4+
<?php
5+
6+
namespace {
7+
use function foo\bar;
8+
use function foo\BAR;
9+
}
10+
11+
?>
12+
--EXPECTF--
13+
Fatal error: Cannot use foo\BAR as BAR because the name is already in use in %s on line %d

Zend/zend_compile.c

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2101,12 +2101,12 @@ void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRML
21012101
}
21022102
/* }}} */
21032103

2104-
void zend_resolve_non_class_name(znode *element_name, zend_bool check_namespace, HashTable *current_import_sub TSRMLS_DC) /* {{{ */
2104+
void zend_resolve_non_class_name(znode *element_name, zend_bool check_namespace, zend_bool case_sensitive, HashTable *current_import_sub TSRMLS_DC) /* {{{ */
21052105
{
21062106
znode tmp;
21072107
int len;
21082108
zval **ns;
2109-
char *lcname, *compound = memchr(Z_STRVAL(element_name->u.constant), '\\', Z_STRLEN(element_name->u.constant));
2109+
char *lookup_name, *compound = memchr(Z_STRVAL(element_name->u.constant), '\\', Z_STRLEN(element_name->u.constant));
21102110

21112111
if (Z_STRVAL(element_name->u.constant)[0] == '\\') {
21122112
/* name starts with \ so it is known and unambiguos, nothing to do here but shorten it */
@@ -2121,23 +2121,31 @@ void zend_resolve_non_class_name(znode *element_name, zend_bool check_namespace,
21212121

21222122
if (current_import_sub) {
21232123
len = Z_STRLEN(element_name->u.constant)+1;
2124-
lcname = zend_str_tolower_dup(Z_STRVAL(element_name->u.constant), len);
2124+
if (case_sensitive) {
2125+
lookup_name = estrndup(Z_STRVAL(element_name->u.constant), len);
2126+
} else {
2127+
lookup_name = zend_str_tolower_dup(Z_STRVAL(element_name->u.constant), len);
2128+
}
21252129
/* Check if function/const matches imported name */
2126-
if (zend_hash_find(current_import_sub, lcname, len, (void**)&ns) == SUCCESS) {
2130+
if (zend_hash_find(current_import_sub, lookup_name, len, (void**)&ns) == SUCCESS) {
21272131
zval_dtor(&element_name->u.constant);
21282132
element_name->u.constant = **ns;
21292133
zval_copy_ctor(&element_name->u.constant);
2130-
efree(lcname);
2134+
efree(lookup_name);
21312135
return;
21322136
}
2133-
efree(lcname);
2137+
efree(lookup_name);
21342138
}
21352139

21362140
if (compound && CG(current_import)) {
21372141
len = compound - Z_STRVAL(element_name->u.constant);
2138-
lcname = zend_str_tolower_dup(Z_STRVAL(element_name->u.constant), len);
2142+
if (case_sensitive) {
2143+
lookup_name = estrndup(Z_STRVAL(element_name->u.constant), len);
2144+
} else {
2145+
lookup_name = zend_str_tolower_dup(Z_STRVAL(element_name->u.constant), len);
2146+
}
21392147
/* Check if first part of compound name is an import name */
2140-
if (zend_hash_find(CG(current_import), lcname, len+1, (void**)&ns) == SUCCESS) {
2148+
if (zend_hash_find(CG(current_import), lookup_name, len+1, (void**)&ns) == SUCCESS) {
21412149
/* Substitute import name */
21422150
tmp.op_type = IS_CONST;
21432151
tmp.u.constant = **ns;
@@ -2147,10 +2155,10 @@ void zend_resolve_non_class_name(znode *element_name, zend_bool check_namespace,
21472155
memmove(Z_STRVAL(element_name->u.constant), Z_STRVAL(element_name->u.constant)+len, Z_STRLEN(element_name->u.constant)+1);
21482156
zend_do_build_namespace_name(&tmp, &tmp, element_name TSRMLS_CC);
21492157
*element_name = tmp;
2150-
efree(lcname);
2158+
efree(lookup_name);
21512159
return;
21522160
}
2153-
efree(lcname);
2161+
efree(lookup_name);
21542162
}
21552163

21562164
if (CG(current_namespace)) {
@@ -2168,13 +2176,13 @@ void zend_resolve_non_class_name(znode *element_name, zend_bool check_namespace,
21682176

21692177
void zend_resolve_function_name(znode *element_name, zend_bool check_namespace TSRMLS_DC) /* {{{ */
21702178
{
2171-
zend_resolve_non_class_name(element_name, check_namespace, CG(current_import_function) TSRMLS_CC);
2179+
zend_resolve_non_class_name(element_name, check_namespace, 0, CG(current_import_function) TSRMLS_CC);
21722180
}
21732181
/* }}} */
21742182

21752183
void zend_resolve_const_name(znode *element_name, zend_bool check_namespace TSRMLS_DC) /* {{{ */
21762184
{
2177-
zend_resolve_non_class_name(element_name, check_namespace, CG(current_import_const) TSRMLS_CC);
2185+
zend_resolve_non_class_name(element_name, check_namespace, 1, CG(current_import_const) TSRMLS_CC);
21782186
}
21792187
/* }}} */
21802188

@@ -7152,9 +7160,9 @@ void zend_do_use(znode *ns_name, znode *new_name, int is_global TSRMLS_DC) /* {{
71527160
}
71537161
/* }}} */
71547162

7155-
void zend_do_use_non_class(znode *ns_name, znode *new_name, int is_global, const char *type, HashTable *current_import_sub, HashTable *lookup_table TSRMLS_DC) /* {{{ */
7163+
void zend_do_use_non_class(znode *ns_name, znode *new_name, int is_global, const char *type, zend_bool case_sensitive, HashTable *current_import_sub, HashTable *lookup_table TSRMLS_DC) /* {{{ */
71567164
{
7157-
char *lcname;
7165+
char *lookup_name;
71587166
char *filename;
71597167
zval *name, *ns, tmp;
71607168
zend_bool warn = 0;
@@ -7179,15 +7187,19 @@ void zend_do_use_non_class(znode *ns_name, znode *new_name, int is_global, const
71797187
}
71807188
}
71817189

7182-
lcname = zend_str_tolower_dup(Z_STRVAL_P(name), Z_STRLEN_P(name));
7190+
if (case_sensitive) {
7191+
lookup_name = estrndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
7192+
} else {
7193+
lookup_name = zend_str_tolower_dup(Z_STRVAL_P(name), Z_STRLEN_P(name));
7194+
}
71837195

71847196
if (CG(current_namespace)) {
71857197
/* Prefix import name with current namespace name to avoid conflicts with functions/consts */
71867198
char *c_ns_name = emalloc(Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name) + 1);
71877199

71887200
zend_str_tolower_copy(c_ns_name, Z_STRVAL_P(CG(current_namespace)), Z_STRLEN_P(CG(current_namespace)));
71897201
c_ns_name[Z_STRLEN_P(CG(current_namespace))] = '\\';
7190-
memcpy(c_ns_name+Z_STRLEN_P(CG(current_namespace))+1, lcname, Z_STRLEN_P(name)+1);
7202+
memcpy(c_ns_name+Z_STRLEN_P(CG(current_namespace))+1, lookup_name, Z_STRLEN_P(name)+1);
71917203
if (zend_hash_exists(lookup_table, c_ns_name, Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name)+1)) {
71927204
char *tmp2 = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
71937205

@@ -7198,23 +7210,23 @@ void zend_do_use_non_class(znode *ns_name, znode *new_name, int is_global, const
71987210
efree(tmp2);
71997211
}
72007212
efree(c_ns_name);
7201-
} else if (zend_hash_find(lookup_table, lcname, Z_STRLEN_P(name)+1, (void **)&filename) == SUCCESS && strcmp(filename, CG(compiled_filename)) == 0) {
7213+
} else if (zend_hash_find(lookup_table, lookup_name, Z_STRLEN_P(name)+1, (void **)&filename) == SUCCESS && strcmp(filename, CG(compiled_filename)) == 0) {
72027214
char *c_tmp = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
72037215

72047216
if (Z_STRLEN_P(ns) != Z_STRLEN_P(name) ||
7205-
memcmp(c_tmp, lcname, Z_STRLEN_P(ns))) {
7217+
memcmp(c_tmp, lookup_name, Z_STRLEN_P(ns))) {
72067218
zend_error(E_COMPILE_ERROR, "Cannot use %s %s as %s because the name is already in use", type, Z_STRVAL_P(ns), Z_STRVAL_P(name));
72077219
}
72087220
efree(c_tmp);
72097221
}
72107222

7211-
if (zend_hash_add(current_import_sub, lcname, Z_STRLEN_P(name)+1, &ns, sizeof(zval*), NULL) != SUCCESS) {
7223+
if (zend_hash_add(current_import_sub, lookup_name, Z_STRLEN_P(name)+1, &ns, sizeof(zval*), NULL) != SUCCESS) {
72127224
zend_error(E_COMPILE_ERROR, "Cannot use %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
72137225
}
72147226
if (warn) {
72157227
zend_error(E_WARNING, "The use statement with non-compound name '%s' has no effect", Z_STRVAL_P(name));
72167228
}
7217-
efree(lcname);
7229+
efree(lookup_name);
72187230
zval_dtor(name);
72197231
}
72207232
/* }}} */
@@ -7226,7 +7238,7 @@ void zend_do_use_function(znode *ns_name, znode *new_name, int is_global TSRMLS_
72267238
zend_hash_init(CG(current_import_function), 0, NULL, ZVAL_PTR_DTOR, 0);
72277239
}
72287240

7229-
zend_do_use_non_class(ns_name, new_name, is_global, "function", CG(current_import_function), &CG(function_filenames) TSRMLS_CC);
7241+
zend_do_use_non_class(ns_name, new_name, is_global, "function", 0, CG(current_import_function), &CG(function_filenames) TSRMLS_CC);
72307242
}
72317243
/* }}} */
72327244

@@ -7237,7 +7249,7 @@ void zend_do_use_const(znode *ns_name, znode *new_name, int is_global TSRMLS_DC)
72377249
zend_hash_init(CG(current_import_const), 0, NULL, ZVAL_PTR_DTOR, 0);
72387250
}
72397251

7240-
zend_do_use_non_class(ns_name, new_name, is_global, "const", CG(current_import_const), &CG(const_filenames) TSRMLS_CC);
7252+
zend_do_use_non_class(ns_name, new_name, is_global, "const", 1, CG(current_import_const), &CG(const_filenames) TSRMLS_CC);
72417253
}
72427254
/* }}} */
72437255

@@ -7269,7 +7281,7 @@ void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC) /* {{{ */
72697281
if (CG(current_import_const) &&
72707282
zend_hash_find(CG(current_import_const), Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant)+1, (void**)&ns_name) == SUCCESS) {
72717283

7272-
char *tmp = zend_str_tolower_dup(Z_STRVAL_PP(ns_name), Z_STRLEN_PP(ns_name));
7284+
char *tmp = estrndup(Z_STRVAL_PP(ns_name), Z_STRLEN_PP(ns_name));
72737285

72747286
if (Z_STRLEN_PP(ns_name) != Z_STRLEN(name->u.constant) ||
72757287
memcmp(tmp, Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant))) {

Zend/zend_compile.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ ZEND_API char *zend_get_compiled_filename(TSRMLS_D);
437437
ZEND_API int zend_get_compiled_lineno(TSRMLS_D);
438438
ZEND_API size_t zend_get_scanned_file_offset(TSRMLS_D);
439439

440-
void zend_resolve_non_class_name(znode *element_name, zend_bool check_namespace, HashTable *current_import_sub TSRMLS_DC);
440+
void zend_resolve_non_class_name(znode *element_name, zend_bool check_namespace, zend_bool case_sensitive, HashTable *current_import_sub TSRMLS_DC);
441441
void zend_resolve_function_name(znode *element_name, zend_bool check_namespace TSRMLS_DC);
442442
void zend_resolve_const_name(znode *element_name, zend_bool check_namespace TSRMLS_DC);
443443
void zend_resolve_class_name(znode *class_name, ulong fetch_type, int check_ns_name TSRMLS_DC);
@@ -638,7 +638,7 @@ void zend_do_begin_namespace(const znode *name, zend_bool with_brackets TSRMLS_D
638638
void zend_do_end_namespace(TSRMLS_D);
639639
void zend_verify_namespace(TSRMLS_D);
640640
void zend_do_use(znode *name, znode *new_name, int is_global TSRMLS_DC);
641-
void zend_do_use_non_class(znode *ns_name, znode *new_name, int is_global, const char *type, HashTable *current_import_sub, HashTable *lookup_table TSRMLS_DC);
641+
void zend_do_use_non_class(znode *ns_name, znode *new_name, int is_global, const char *type, zend_bool case_sensitive, HashTable *current_import_sub, HashTable *lookup_table TSRMLS_DC);
642642
void zend_do_use_function(znode *name, znode *new_name, int is_global TSRMLS_DC);
643643
void zend_do_use_const(znode *name, znode *new_name, int is_global TSRMLS_DC);
644644
void zend_do_end_compilation(TSRMLS_D);

0 commit comments

Comments
 (0)