xref: /PHP-7.4/Zend/zend_constants.c (revision 07877c46)
1 /*
2    +----------------------------------------------------------------------+
3    | Zend Engine                                                          |
4    +----------------------------------------------------------------------+
5    | Copyright (c) Zend Technologies Ltd. (http://www.zend.com)           |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 2.00 of the Zend license,     |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.zend.com/license/2_00.txt.                                |
11    | If you did not receive a copy of the Zend license and are unable to  |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@zend.com so we can mail you a copy immediately.              |
14    +----------------------------------------------------------------------+
15    | Authors: Andi Gutmans <andi@php.net>                                 |
16    |          Zeev Suraski <zeev@php.net>                                 |
17    +----------------------------------------------------------------------+
18 */
19 
20 #include "zend.h"
21 #include "zend_constants.h"
22 #include "zend_exceptions.h"
23 #include "zend_execute.h"
24 #include "zend_variables.h"
25 #include "zend_operators.h"
26 #include "zend_globals.h"
27 #include "zend_API.h"
28 
29 /* Protection from recursive self-referencing class constants */
30 #define IS_CONSTANT_VISITED_MARK    0x80
31 
32 #define IS_CONSTANT_VISITED(zv)     (Z_ACCESS_FLAGS_P(zv) & IS_CONSTANT_VISITED_MARK)
33 #define MARK_CONSTANT_VISITED(zv)   Z_ACCESS_FLAGS_P(zv) |= IS_CONSTANT_VISITED_MARK
34 #define RESET_CONSTANT_VISITED(zv)  Z_ACCESS_FLAGS_P(zv) &= ~IS_CONSTANT_VISITED_MARK
35 
free_zend_constant(zval * zv)36 void free_zend_constant(zval *zv)
37 {
38 	zend_constant *c = Z_PTR_P(zv);
39 
40 	if (!(ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT)) {
41 		zval_ptr_dtor_nogc(&c->value);
42 		if (c->name) {
43 			zend_string_release_ex(c->name, 0);
44 		}
45 		efree(c);
46 	} else {
47 		zval_internal_ptr_dtor(&c->value);
48 		if (c->name) {
49 			zend_string_release_ex(c->name, 1);
50 		}
51 		free(c);
52 	}
53 }
54 
55 
56 #ifdef ZTS
copy_zend_constant(zval * zv)57 static void copy_zend_constant(zval *zv)
58 {
59 	zend_constant *c = Z_PTR_P(zv);
60 
61 	ZEND_ASSERT(ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT);
62 	Z_PTR_P(zv) = pemalloc(sizeof(zend_constant), 1);
63 	memcpy(Z_PTR_P(zv), c, sizeof(zend_constant));
64 
65 	c = Z_PTR_P(zv);
66 	c->name = zend_string_copy(c->name);
67 	if (Z_TYPE(c->value) == IS_STRING) {
68 		Z_STR(c->value) = zend_string_dup(Z_STR(c->value), 1);
69 	}
70 }
71 
72 
zend_copy_constants(HashTable * target,HashTable * source)73 void zend_copy_constants(HashTable *target, HashTable *source)
74 {
75 	zend_hash_copy(target, source, copy_zend_constant);
76 }
77 #endif
78 
79 
clean_module_constant(zval * el,void * arg)80 static int clean_module_constant(zval *el, void *arg)
81 {
82 	zend_constant *c = (zend_constant *)Z_PTR_P(el);
83 	int module_number = *(int *)arg;
84 
85 	if (ZEND_CONSTANT_MODULE_NUMBER(c) == module_number) {
86 		return ZEND_HASH_APPLY_REMOVE;
87 	} else {
88 		return ZEND_HASH_APPLY_KEEP;
89 	}
90 }
91 
92 
clean_module_constants(int module_number)93 void clean_module_constants(int module_number)
94 {
95 	zend_hash_apply_with_argument(EG(zend_constants), clean_module_constant, (void *) &module_number);
96 }
97 
98 
zend_startup_constants(void)99 int zend_startup_constants(void)
100 {
101 	EG(zend_constants) = (HashTable *) malloc(sizeof(HashTable));
102 
103 	zend_hash_init(EG(zend_constants), 128, NULL, ZEND_CONSTANT_DTOR, 1);
104 	return SUCCESS;
105 }
106 
107 
108 
zend_register_standard_constants(void)109 void zend_register_standard_constants(void)
110 {
111 	REGISTER_MAIN_LONG_CONSTANT("E_ERROR", E_ERROR, CONST_PERSISTENT | CONST_CS);
112 	REGISTER_MAIN_LONG_CONSTANT("E_RECOVERABLE_ERROR", E_RECOVERABLE_ERROR, CONST_PERSISTENT | CONST_CS);
113 	REGISTER_MAIN_LONG_CONSTANT("E_WARNING", E_WARNING, CONST_PERSISTENT | CONST_CS);
114 	REGISTER_MAIN_LONG_CONSTANT("E_PARSE", E_PARSE, CONST_PERSISTENT | CONST_CS);
115 	REGISTER_MAIN_LONG_CONSTANT("E_NOTICE", E_NOTICE, CONST_PERSISTENT | CONST_CS);
116 	REGISTER_MAIN_LONG_CONSTANT("E_STRICT", E_STRICT, CONST_PERSISTENT | CONST_CS);
117 	REGISTER_MAIN_LONG_CONSTANT("E_DEPRECATED", E_DEPRECATED, CONST_PERSISTENT | CONST_CS);
118 	REGISTER_MAIN_LONG_CONSTANT("E_CORE_ERROR", E_CORE_ERROR, CONST_PERSISTENT | CONST_CS);
119 	REGISTER_MAIN_LONG_CONSTANT("E_CORE_WARNING", E_CORE_WARNING, CONST_PERSISTENT | CONST_CS);
120 	REGISTER_MAIN_LONG_CONSTANT("E_COMPILE_ERROR", E_COMPILE_ERROR, CONST_PERSISTENT | CONST_CS);
121 	REGISTER_MAIN_LONG_CONSTANT("E_COMPILE_WARNING", E_COMPILE_WARNING, CONST_PERSISTENT | CONST_CS);
122 	REGISTER_MAIN_LONG_CONSTANT("E_USER_ERROR", E_USER_ERROR, CONST_PERSISTENT | CONST_CS);
123 	REGISTER_MAIN_LONG_CONSTANT("E_USER_WARNING", E_USER_WARNING, CONST_PERSISTENT | CONST_CS);
124 	REGISTER_MAIN_LONG_CONSTANT("E_USER_NOTICE", E_USER_NOTICE, CONST_PERSISTENT | CONST_CS);
125 	REGISTER_MAIN_LONG_CONSTANT("E_USER_DEPRECATED", E_USER_DEPRECATED, CONST_PERSISTENT | CONST_CS);
126 
127 	REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL, CONST_PERSISTENT | CONST_CS);
128 
129 	REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_PROVIDE_OBJECT", DEBUG_BACKTRACE_PROVIDE_OBJECT, CONST_PERSISTENT | CONST_CS);
130 	REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_IGNORE_ARGS", DEBUG_BACKTRACE_IGNORE_ARGS, CONST_PERSISTENT | CONST_CS);
131 	/* true/false constants */
132 	{
133 		REGISTER_MAIN_BOOL_CONSTANT("TRUE", 1, CONST_PERSISTENT | CONST_CT_SUBST);
134 		REGISTER_MAIN_BOOL_CONSTANT("FALSE", 0, CONST_PERSISTENT | CONST_CT_SUBST);
135 		REGISTER_MAIN_BOOL_CONSTANT("ZEND_THREAD_SAFE", ZTS_V, CONST_PERSISTENT | CONST_CS);
136 		REGISTER_MAIN_BOOL_CONSTANT("ZEND_DEBUG_BUILD", ZEND_DEBUG, CONST_PERSISTENT | CONST_CS);
137 	}
138 	REGISTER_MAIN_NULL_CONSTANT("NULL", CONST_PERSISTENT | CONST_CT_SUBST);
139 }
140 
141 
zend_shutdown_constants(void)142 int zend_shutdown_constants(void)
143 {
144 	zend_hash_destroy(EG(zend_constants));
145 	free(EG(zend_constants));
146 	return SUCCESS;
147 }
148 
zend_register_null_constant(const char * name,size_t name_len,int flags,int module_number)149 ZEND_API void zend_register_null_constant(const char *name, size_t name_len, int flags, int module_number)
150 {
151 	zend_constant c;
152 
153 	ZVAL_NULL(&c.value);
154 	ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
155 	c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
156 	zend_register_constant(&c);
157 }
158 
zend_register_bool_constant(const char * name,size_t name_len,zend_bool bval,int flags,int module_number)159 ZEND_API void zend_register_bool_constant(const char *name, size_t name_len, zend_bool bval, int flags, int module_number)
160 {
161 	zend_constant c;
162 
163 	ZVAL_BOOL(&c.value, bval);
164 	ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
165 	c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
166 	zend_register_constant(&c);
167 }
168 
zend_register_long_constant(const char * name,size_t name_len,zend_long lval,int flags,int module_number)169 ZEND_API void zend_register_long_constant(const char *name, size_t name_len, zend_long lval, int flags, int module_number)
170 {
171 	zend_constant c;
172 
173 	ZVAL_LONG(&c.value, lval);
174 	ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
175 	c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
176 	zend_register_constant(&c);
177 }
178 
179 
zend_register_double_constant(const char * name,size_t name_len,double dval,int flags,int module_number)180 ZEND_API void zend_register_double_constant(const char *name, size_t name_len, double dval, int flags, int module_number)
181 {
182 	zend_constant c;
183 
184 	ZVAL_DOUBLE(&c.value, dval);
185 	ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
186 	c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
187 	zend_register_constant(&c);
188 }
189 
190 
zend_register_stringl_constant(const char * name,size_t name_len,char * strval,size_t strlen,int flags,int module_number)191 ZEND_API void zend_register_stringl_constant(const char *name, size_t name_len, char *strval, size_t strlen, int flags, int module_number)
192 {
193 	zend_constant c;
194 
195 	ZVAL_STR(&c.value, zend_string_init_interned(strval, strlen, flags & CONST_PERSISTENT));
196 	ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
197 	c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
198 	zend_register_constant(&c);
199 }
200 
201 
zend_register_string_constant(const char * name,size_t name_len,char * strval,int flags,int module_number)202 ZEND_API void zend_register_string_constant(const char *name, size_t name_len, char *strval, int flags, int module_number)
203 {
204 	zend_register_stringl_constant(name, name_len, strval, strlen(strval), flags, module_number);
205 }
206 
zend_get_special_constant(const char * name,size_t name_len)207 static zend_constant *zend_get_special_constant(const char *name, size_t name_len)
208 {
209 	zend_constant *c;
210 	static const char haltoff[] = "__COMPILER_HALT_OFFSET__";
211 
212 	if (!EG(current_execute_data)) {
213 		return NULL;
214 	} else if (name_len == sizeof("__COMPILER_HALT_OFFSET__")-1 &&
215 	          !memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1)) {
216 		const char *cfilename;
217 		zend_string *haltname;
218 		size_t clen;
219 
220 		cfilename = zend_get_executed_filename();
221 		clen = strlen(cfilename);
222 		/* check for __COMPILER_HALT_OFFSET__ */
223 		haltname = zend_mangle_property_name(haltoff,
224 			sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename, clen, 0);
225 		c = zend_hash_find_ptr(EG(zend_constants), haltname);
226 		zend_string_efree(haltname);
227 		return c;
228 	} else {
229 		return NULL;
230 	}
231 }
232 
zend_verify_const_access(zend_class_constant * c,zend_class_entry * scope)233 ZEND_API int zend_verify_const_access(zend_class_constant *c, zend_class_entry *scope) /* {{{ */
234 {
235 	if (Z_ACCESS_FLAGS(c->value) & ZEND_ACC_PUBLIC) {
236 		return 1;
237 	} else if (Z_ACCESS_FLAGS(c->value) & ZEND_ACC_PRIVATE) {
238 		return (c->ce == scope);
239 	} else {
240 		ZEND_ASSERT(Z_ACCESS_FLAGS(c->value) & ZEND_ACC_PROTECTED);
241 		return zend_check_protected(c->ce, scope);
242 	}
243 }
244 /* }}} */
245 
zend_get_constant_str_impl(const char * name,size_t name_len)246 static inline zend_constant *zend_get_constant_str_impl(const char *name, size_t name_len)
247 {
248 	zend_constant *c;
249 	ALLOCA_FLAG(use_heap)
250 
251 	if ((c = zend_hash_str_find_ptr(EG(zend_constants), name, name_len)) == NULL) {
252 		char *lcname = do_alloca(name_len + 1, use_heap);
253 		zend_str_tolower_copy(lcname, name, name_len);
254 		if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, name_len)) != NULL) {
255 			if (ZEND_CONSTANT_FLAGS(c) & CONST_CS) {
256 				c = NULL;
257 			}
258 		} else {
259 			c = zend_get_special_constant(name, name_len);
260 		}
261 		free_alloca(lcname, use_heap);
262 	}
263 
264 	return c;
265 }
266 
zend_get_constant_str(const char * name,size_t name_len)267 ZEND_API zval *zend_get_constant_str(const char *name, size_t name_len)
268 {
269 	zend_constant *c = zend_get_constant_str_impl(name, name_len);
270 	return c ? &c->value : NULL;
271 }
272 
zend_get_constant_impl(zend_string * name)273 static inline zend_constant *zend_get_constant_impl(zend_string *name)
274 {
275     zval *zv;
276 	zend_constant *c;
277 	ALLOCA_FLAG(use_heap)
278 
279 	zv = zend_hash_find(EG(zend_constants), name);
280 	if (zv == NULL) {
281 		char *lcname = do_alloca(ZSTR_LEN(name) + 1, use_heap);
282 		zend_str_tolower_copy(lcname, ZSTR_VAL(name), ZSTR_LEN(name));
283 		zv = zend_hash_str_find(EG(zend_constants), lcname, ZSTR_LEN(name));
284 		if (zv != NULL) {
285 			c = Z_PTR_P(zv);
286 			if (ZEND_CONSTANT_FLAGS(c) & CONST_CS) {
287 				c = NULL;
288 			}
289 		} else {
290 			c = zend_get_special_constant(ZSTR_VAL(name), ZSTR_LEN(name));
291 		}
292 		free_alloca(lcname, use_heap);
293 		return c;
294 	} else {
295 		return (zend_constant *) Z_PTR_P(zv);
296 	}
297 }
298 
zend_get_constant(zend_string * name)299 ZEND_API zval *zend_get_constant(zend_string *name)
300 {
301 	zend_constant *c = zend_get_constant_impl(name);
302 	return c ? &c->value : NULL;
303 }
304 
is_access_deprecated(const zend_constant * c,const char * access_name)305 static zend_bool is_access_deprecated(const zend_constant *c, const char *access_name) {
306 	const char *ns_sep = zend_memrchr(ZSTR_VAL(c->name), '\\', ZSTR_LEN(c->name));
307 	if (ns_sep) {
308 		/* Namespaces are always case-insensitive. Only compare shortname. */
309 		size_t shortname_offset = ns_sep - ZSTR_VAL(c->name) + 1;
310 		size_t shortname_len = ZSTR_LEN(c->name) - shortname_offset;
311 		return memcmp(
312 			access_name + shortname_offset,
313 			ZSTR_VAL(c->name) + shortname_offset,
314 			shortname_len
315 		) != 0;
316 	} else {
317 		/* No namespace, compare whole name */
318 		return memcmp(access_name, ZSTR_VAL(c->name), ZSTR_LEN(c->name)) != 0;
319 	}
320 }
321 
zend_get_constant_ex(zend_string * cname,zend_class_entry * scope,uint32_t flags)322 ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, uint32_t flags)
323 {
324 	zend_constant *c;
325 	const char *colon;
326 	zend_class_entry *ce = NULL;
327 	const char *name = ZSTR_VAL(cname);
328 	size_t name_len = ZSTR_LEN(cname);
329 
330 	/* Skip leading \\ */
331 	if (name[0] == '\\') {
332 		name += 1;
333 		name_len -= 1;
334 		cname = NULL;
335 	}
336 
337 	if ((colon = zend_memrchr(name, ':', name_len)) &&
338 	    colon > name && (*(colon - 1) == ':')) {
339 		int class_name_len = colon - name - 1;
340 		size_t const_name_len = name_len - class_name_len - 2;
341 		zend_string *constant_name = zend_string_init(colon + 1, const_name_len, 0);
342 		zend_string *class_name = zend_string_init(name, class_name_len, 0);
343 		zend_class_constant *c = NULL;
344 		zval *ret_constant = NULL;
345 
346 		if (zend_string_equals_literal_ci(class_name, "self")) {
347 			if (UNEXPECTED(!scope)) {
348 				zend_throw_error(NULL, "Cannot access self:: when no class scope is active");
349 				goto failure;
350 			}
351 			ce = scope;
352 		} else if (zend_string_equals_literal_ci(class_name, "parent")) {
353 			if (UNEXPECTED(!scope)) {
354 				zend_throw_error(NULL, "Cannot access parent:: when no class scope is active");
355 				goto failure;
356 			} else if (UNEXPECTED(!scope->parent)) {
357 				zend_throw_error(NULL, "Cannot access parent:: when current class scope has no parent");
358 				goto failure;
359 			} else {
360 				ce = scope->parent;
361 			}
362 		} else if (zend_string_equals_literal_ci(class_name, "static")) {
363 			ce = zend_get_called_scope(EG(current_execute_data));
364 			if (UNEXPECTED(!ce)) {
365 				zend_throw_error(NULL, "Cannot access static:: when no class scope is active");
366 				goto failure;
367 			}
368 		} else {
369 			ce = zend_fetch_class(class_name, flags);
370 		}
371 		if (ce) {
372 			c = zend_hash_find_ptr(&ce->constants_table, constant_name);
373 			if (c == NULL) {
374 				if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) {
375 					zend_throw_error(NULL, "Undefined class constant '%s::%s'", ZSTR_VAL(class_name), ZSTR_VAL(constant_name));
376 					goto failure;
377 				}
378 				ret_constant = NULL;
379 			} else {
380 				if (!zend_verify_const_access(c, scope)) {
381 					if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) {
382 						zend_throw_error(NULL, "Cannot access %s const %s::%s", zend_visibility_string(Z_ACCESS_FLAGS(c->value)), ZSTR_VAL(class_name), ZSTR_VAL(constant_name));
383 					}
384 					goto failure;
385 				}
386 				ret_constant = &c->value;
387 			}
388 		}
389 
390 		if (ret_constant && Z_TYPE_P(ret_constant) == IS_CONSTANT_AST) {
391 			int ret;
392 
393 			if (IS_CONSTANT_VISITED(ret_constant)) {
394 				zend_throw_error(NULL, "Cannot declare self-referencing constant '%s::%s'", ZSTR_VAL(class_name), ZSTR_VAL(constant_name));
395 				ret_constant = NULL;
396 				goto failure;
397 			}
398 
399 			MARK_CONSTANT_VISITED(ret_constant);
400 			ret = zval_update_constant_ex(ret_constant, c->ce);
401 			RESET_CONSTANT_VISITED(ret_constant);
402 
403 			if (UNEXPECTED(ret != SUCCESS)) {
404 				ret_constant = NULL;
405 				goto failure;
406 			}
407 		}
408 failure:
409 		zend_string_release_ex(class_name, 0);
410 		zend_string_efree(constant_name);
411 		return ret_constant;
412 	}
413 
414 	/* non-class constant */
415 	if ((colon = zend_memrchr(name, '\\', name_len)) != NULL) {
416 		/* compound constant name */
417 		int prefix_len = colon - name;
418 		size_t const_name_len = name_len - prefix_len - 1;
419 		const char *constant_name = colon + 1;
420 		char *lcname;
421 		size_t lcname_len;
422 		ALLOCA_FLAG(use_heap)
423 
424 		lcname_len = prefix_len + 1 + const_name_len;
425 		lcname = do_alloca(lcname_len + 1, use_heap);
426 		zend_str_tolower_copy(lcname, name, prefix_len);
427 		/* Check for namespace constant */
428 
429 		lcname[prefix_len] = '\\';
430 		memcpy(lcname + prefix_len + 1, constant_name, const_name_len + 1);
431 
432 		if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, lcname_len)) == NULL) {
433 			/* try lowercase */
434 			zend_str_tolower(lcname + prefix_len + 1, const_name_len);
435 			if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, lcname_len)) != NULL) {
436 				if ((ZEND_CONSTANT_FLAGS(c) & CONST_CS) != 0) {
437 					c = NULL;
438 				}
439 			}
440 		}
441 		free_alloca(lcname, use_heap);
442 
443 		if (!c) {
444 			if (!(flags & IS_CONSTANT_UNQUALIFIED)) {
445 				return NULL;
446 			}
447 
448 			/* name requires runtime resolution, need to check non-namespaced name */
449 			c = zend_get_constant_str_impl(constant_name, const_name_len);
450 			name = constant_name;
451 		}
452 	} else {
453 		if (cname) {
454 			c = zend_get_constant_impl(cname);
455 		} else {
456 			c = zend_get_constant_str_impl(name, name_len);
457 		}
458 	}
459 
460 	if (!c) {
461 		return NULL;
462 	}
463 
464 	if (!(flags & ZEND_GET_CONSTANT_NO_DEPRECATION_CHECK)) {
465 		if (!(ZEND_CONSTANT_FLAGS(c) & (CONST_CS|CONST_CT_SUBST)) && is_access_deprecated(c, name)) {
466 			zend_error(E_DEPRECATED,
467 				"Case-insensitive constants are deprecated. "
468 				"The correct casing for this constant is \"%s\"",
469 				ZSTR_VAL(c->name));
470 		}
471 	}
472 
473 	return &c->value;
474 }
475 
zend_hash_add_constant(HashTable * ht,zend_string * key,zend_constant * c)476 static void* zend_hash_add_constant(HashTable *ht, zend_string *key, zend_constant *c)
477 {
478 	void *ret;
479 	zend_constant *copy = pemalloc(sizeof(zend_constant), ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT);
480 
481 	memcpy(copy, c, sizeof(zend_constant));
482 	ret = zend_hash_add_ptr(ht, key, copy);
483 	if (!ret) {
484 		pefree(copy, ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT);
485 	}
486 	return ret;
487 }
488 
zend_register_constant(zend_constant * c)489 ZEND_API int zend_register_constant(zend_constant *c)
490 {
491 	zend_string *lowercase_name = NULL;
492 	zend_string *name;
493 	int ret = SUCCESS;
494 
495 #if 0
496 	printf("Registering constant for module %d\n", c->module_number);
497 #endif
498 
499 	if (!(ZEND_CONSTANT_FLAGS(c) & CONST_CS)) {
500 		lowercase_name = zend_string_tolower_ex(c->name, ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT);
501 		lowercase_name = zend_new_interned_string(lowercase_name);
502 		name = lowercase_name;
503 	} else {
504 		char *slash = strrchr(ZSTR_VAL(c->name), '\\');
505 		if (slash) {
506 			lowercase_name = zend_string_init(ZSTR_VAL(c->name), ZSTR_LEN(c->name), ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT);
507 			zend_str_tolower(ZSTR_VAL(lowercase_name), slash - ZSTR_VAL(c->name));
508 			lowercase_name = zend_new_interned_string(lowercase_name);
509 			name = lowercase_name;
510 		} else {
511 			name = c->name;
512 		}
513 	}
514 
515 	/* Check if the user is trying to define the internal pseudo constant name __COMPILER_HALT_OFFSET__ */
516 	if (zend_string_equals_literal(name, "__COMPILER_HALT_OFFSET__")
517 		|| zend_hash_add_constant(EG(zend_constants), name, c) == NULL) {
518 
519 		/* The internal __COMPILER_HALT_OFFSET__ is prefixed by NULL byte */
520 		if (ZSTR_VAL(c->name)[0] == '\0' && ZSTR_LEN(c->name) > sizeof("\0__COMPILER_HALT_OFFSET__")-1
521 			&& memcmp(ZSTR_VAL(name), "\0__COMPILER_HALT_OFFSET__", sizeof("\0__COMPILER_HALT_OFFSET__")) == 0) {
522 		}
523 		zend_error(E_NOTICE,"Constant %s already defined", ZSTR_VAL(name));
524 		zend_string_release(c->name);
525 		if (!(ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT)) {
526 			zval_ptr_dtor_nogc(&c->value);
527 		}
528 		ret = FAILURE;
529 	}
530 	if (lowercase_name) {
531 		zend_string_release(lowercase_name);
532 	}
533 	return ret;
534 }
535