1 : /*
2 : +----------------------------------------------------------------------+
3 : | Zend Engine |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1998-2009 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@zend.com> |
16 : | Zeev Suraski <zeev@zend.com> |
17 : +----------------------------------------------------------------------+
18 : */
19 :
20 : /* $Id: zend_constants.c 273405 2009-01-12 21:54:37Z stas $ */
21 :
22 : #include "zend.h"
23 : #include "zend_constants.h"
24 : #include "zend_execute.h"
25 : #include "zend_variables.h"
26 : #include "zend_operators.h"
27 : #include "zend_globals.h"
28 :
29 :
30 : void free_zend_constant(zend_constant *c)
31 36956987 : {
32 36956987 : if (!(c->flags & CONST_PERSISTENT)) {
33 2404247 : zval_dtor(&c->value);
34 : }
35 36956987 : free(c->name);
36 36956987 : }
37 :
38 :
39 : void copy_zend_constant(zend_constant *c)
40 0 : {
41 0 : c->name = zend_strndup(c->name, c->name_len - 1);
42 0 : if (!(c->flags & CONST_PERSISTENT)) {
43 0 : zval_copy_ctor(&c->value);
44 : }
45 0 : }
46 :
47 :
48 : void zend_copy_constants(HashTable *target, HashTable *source)
49 0 : {
50 : zend_constant tmp_constant;
51 :
52 0 : zend_hash_copy(target, source, (copy_ctor_func_t) copy_zend_constant, &tmp_constant, sizeof(zend_constant));
53 0 : }
54 :
55 :
56 : static int clean_non_persistent_constant(const zend_constant *c TSRMLS_DC)
57 72275 : {
58 72275 : return (c->flags & CONST_PERSISTENT) ? ZEND_HASH_APPLY_STOP : ZEND_HASH_APPLY_REMOVE;
59 : }
60 :
61 :
62 : static int clean_non_persistent_constant_full(const zend_constant *c TSRMLS_DC)
63 0 : {
64 0 : return (c->flags & CONST_PERSISTENT) ? 0 : 1;
65 : }
66 :
67 :
68 : static int clean_module_constant(const zend_constant *c, int *module_number TSRMLS_DC)
69 0 : {
70 0 : if (c->module_number == *module_number) {
71 0 : return 1;
72 : } else {
73 0 : return 0;
74 : }
75 : }
76 :
77 :
78 : void clean_module_constants(int module_number TSRMLS_DC)
79 0 : {
80 0 : zend_hash_apply_with_argument(EG(zend_constants), (apply_func_arg_t) clean_module_constant, (void *) &module_number TSRMLS_CC);
81 0 : }
82 :
83 :
84 : int zend_startup_constants(TSRMLS_D)
85 0 : {
86 0 : EG(zend_constants) = (HashTable *) malloc(sizeof(HashTable));
87 :
88 0 : if (zend_hash_init(EG(zend_constants), 20, NULL, ZEND_CONSTANT_DTOR, 1)==FAILURE) {
89 0 : return FAILURE;
90 : }
91 0 : return SUCCESS;
92 : }
93 :
94 :
95 :
96 : void zend_register_standard_constants(TSRMLS_D)
97 17633 : {
98 17633 : REGISTER_MAIN_LONG_CONSTANT("E_ERROR", E_ERROR, CONST_PERSISTENT | CONST_CS);
99 17633 : REGISTER_MAIN_LONG_CONSTANT("E_RECOVERABLE_ERROR", E_RECOVERABLE_ERROR, CONST_PERSISTENT | CONST_CS);
100 17633 : REGISTER_MAIN_LONG_CONSTANT("E_WARNING", E_WARNING, CONST_PERSISTENT | CONST_CS);
101 17633 : REGISTER_MAIN_LONG_CONSTANT("E_PARSE", E_PARSE, CONST_PERSISTENT | CONST_CS);
102 17633 : REGISTER_MAIN_LONG_CONSTANT("E_NOTICE", E_NOTICE, CONST_PERSISTENT | CONST_CS);
103 17633 : REGISTER_MAIN_LONG_CONSTANT("E_STRICT", E_STRICT, CONST_PERSISTENT | CONST_CS);
104 17633 : REGISTER_MAIN_LONG_CONSTANT("E_DEPRECATED", E_DEPRECATED, CONST_PERSISTENT | CONST_CS);
105 17633 : REGISTER_MAIN_LONG_CONSTANT("E_CORE_ERROR", E_CORE_ERROR, CONST_PERSISTENT | CONST_CS);
106 17633 : REGISTER_MAIN_LONG_CONSTANT("E_CORE_WARNING", E_CORE_WARNING, CONST_PERSISTENT | CONST_CS);
107 17633 : REGISTER_MAIN_LONG_CONSTANT("E_COMPILE_ERROR", E_COMPILE_ERROR, CONST_PERSISTENT | CONST_CS);
108 17633 : REGISTER_MAIN_LONG_CONSTANT("E_COMPILE_WARNING", E_COMPILE_WARNING, CONST_PERSISTENT | CONST_CS);
109 17633 : REGISTER_MAIN_LONG_CONSTANT("E_USER_ERROR", E_USER_ERROR, CONST_PERSISTENT | CONST_CS);
110 17633 : REGISTER_MAIN_LONG_CONSTANT("E_USER_WARNING", E_USER_WARNING, CONST_PERSISTENT | CONST_CS);
111 17633 : REGISTER_MAIN_LONG_CONSTANT("E_USER_NOTICE", E_USER_NOTICE, CONST_PERSISTENT | CONST_CS);
112 17633 : REGISTER_MAIN_LONG_CONSTANT("E_USER_DEPRECATED", E_USER_DEPRECATED, CONST_PERSISTENT | CONST_CS);
113 :
114 17633 : REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL, CONST_PERSISTENT | CONST_CS);
115 :
116 : /* true/false constants */
117 : {
118 : zend_constant c;
119 :
120 17633 : c.flags = CONST_PERSISTENT | CONST_CT_SUBST;
121 17633 : c.module_number = 0;
122 :
123 17633 : c.name = zend_strndup(ZEND_STRL("TRUE"));
124 17633 : c.name_len = sizeof("TRUE");
125 17633 : c.value.value.lval = 1;
126 17633 : c.value.type = IS_BOOL;
127 17633 : zend_register_constant(&c TSRMLS_CC);
128 :
129 17633 : c.name = zend_strndup(ZEND_STRL("FALSE"));
130 17633 : c.name_len = sizeof("FALSE");
131 17633 : c.value.value.lval = 0;
132 17633 : c.value.type = IS_BOOL;
133 17633 : zend_register_constant(&c TSRMLS_CC);
134 :
135 17633 : c.name = zend_strndup(ZEND_STRL("NULL"));
136 17633 : c.name_len = sizeof("NULL");
137 17633 : c.value.type = IS_NULL;
138 17633 : zend_register_constant(&c TSRMLS_CC);
139 :
140 17633 : c.flags = CONST_PERSISTENT;
141 :
142 17633 : c.name = zend_strndup(ZEND_STRL("ZEND_THREAD_SAFE"));
143 17633 : c.name_len = sizeof("ZEND_THREAD_SAFE");
144 17633 : c.value.value.lval = ZTS_V;
145 17633 : c.value.type = IS_BOOL;
146 17633 : zend_register_constant(&c TSRMLS_CC);
147 :
148 17633 : c.name = zend_strndup(ZEND_STRL("ZEND_DEBUG_BUILD"));
149 17633 : c.name_len = sizeof("ZEND_DEBUG_BUILD");
150 17633 : c.value.value.lval = ZEND_DEBUG;
151 17633 : c.value.type = IS_BOOL;
152 17633 : zend_register_constant(&c TSRMLS_CC);
153 : }
154 17633 : }
155 :
156 :
157 : int zend_shutdown_constants(TSRMLS_D)
158 0 : {
159 0 : zend_hash_destroy(EG(zend_constants));
160 0 : free(EG(zend_constants));
161 0 : return SUCCESS;
162 : }
163 :
164 :
165 : void clean_non_persistent_constants(TSRMLS_D)
166 17651 : {
167 17651 : if (EG(full_tables_cleanup)) {
168 0 : zend_hash_apply(EG(zend_constants), (apply_func_t) clean_non_persistent_constant_full TSRMLS_CC);
169 : } else {
170 17651 : zend_hash_reverse_apply(EG(zend_constants), (apply_func_t) clean_non_persistent_constant TSRMLS_CC);
171 : }
172 17651 : }
173 :
174 :
175 : ZEND_API void zend_register_long_constant(const char *name, uint name_len, long lval, int flags, int module_number TSRMLS_DC)
176 34966510 : {
177 : zend_constant c;
178 :
179 34966510 : c.value.type = IS_LONG;
180 34966510 : c.value.value.lval = lval;
181 34966510 : c.flags = flags;
182 34966510 : c.name = zend_strndup(name, name_len-1);
183 34966510 : c.name_len = name_len;
184 34966510 : c.module_number = module_number;
185 34966510 : zend_register_constant(&c TSRMLS_CC);
186 34966510 : }
187 :
188 :
189 : ZEND_API void zend_register_double_constant(const char *name, uint name_len, double dval, int flags, int module_number TSRMLS_DC)
190 335027 : {
191 : zend_constant c;
192 :
193 335027 : c.value.type = IS_DOUBLE;
194 335027 : c.value.value.dval = dval;
195 335027 : c.flags = flags;
196 335027 : c.name = zend_strndup(name, name_len-1);
197 335027 : c.name_len = name_len;
198 335027 : c.module_number = module_number;
199 335027 : zend_register_constant(&c TSRMLS_CC);
200 335027 : }
201 :
202 :
203 : ZEND_API void zend_register_stringl_constant(const char *name, uint name_len, char *strval, uint strlen, int flags, int module_number TSRMLS_DC)
204 1446226 : {
205 : zend_constant c;
206 :
207 1446226 : c.value.type = IS_STRING;
208 1446226 : c.value.value.str.val = strval;
209 1446226 : c.value.value.str.len = strlen;
210 1446226 : c.flags = flags;
211 1446226 : c.name = zend_strndup(name, name_len-1);
212 1446226 : c.name_len = name_len;
213 1446226 : c.module_number = module_number;
214 1446226 : zend_register_constant(&c TSRMLS_CC);
215 1446226 : }
216 :
217 :
218 : ZEND_API void zend_register_string_constant(const char *name, uint name_len, char *strval, int flags, int module_number TSRMLS_DC)
219 1128512 : {
220 1128512 : zend_register_stringl_constant(name, name_len, strval, strlen(strval), flags, module_number TSRMLS_CC);
221 1128512 : }
222 :
223 :
224 : ZEND_API int zend_get_constant(const char *name, uint name_len, zval *result TSRMLS_DC)
225 50919 : {
226 : zend_constant *c;
227 50919 : int retval = 1;
228 : char *lookup_name;
229 :
230 50919 : if (zend_hash_find(EG(zend_constants), name, name_len+1, (void **) &c) == FAILURE) {
231 36084 : lookup_name = zend_str_tolower_dup(name, name_len);
232 :
233 36084 : if (zend_hash_find(EG(zend_constants), lookup_name, name_len+1, (void **) &c)==SUCCESS) {
234 251 : if (c->flags & CONST_CS) {
235 0 : retval=0;
236 : }
237 : } else {
238 : static char haltoff[] = "__COMPILER_HALT_OFFSET__";
239 :
240 35833 : if (!EG(in_execution)) {
241 35499 : retval = 0;
242 411 : } else if (name_len == sizeof("__COMPILER_HALT_OFFSET__")-1 &&
243 : !memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1)) {
244 : char *cfilename, *haltname;
245 : int len, clen;
246 :
247 77 : cfilename = zend_get_executed_filename(TSRMLS_C);
248 77 : clen = strlen(cfilename);
249 : /* check for __COMPILER_HALT_OFFSET__ */
250 77 : zend_mangle_property_name(&haltname, &len, haltoff,
251 : sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename, clen, 0);
252 77 : if (zend_hash_find(EG(zend_constants), haltname, len+1, (void **) &c) == SUCCESS) {
253 76 : retval = 1;
254 : } else {
255 1 : retval=0;
256 : }
257 77 : pefree(haltname, 0);
258 : } else {
259 257 : retval=0;
260 : }
261 : }
262 36084 : efree(lookup_name);
263 : }
264 :
265 50919 : if (retval) {
266 15162 : *result = c->value;
267 15162 : zval_copy_ctor(result);
268 15162 : Z_SET_REFCOUNT_P(result, 1);
269 15162 : Z_UNSET_ISREF_P(result);
270 : }
271 :
272 50919 : return retval;
273 : }
274 :
275 : ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result, zend_class_entry *scope, ulong flags TSRMLS_DC)
276 15281 : {
277 : zend_constant *c;
278 15281 : int retval = 1;
279 : char *colon;
280 15281 : zend_class_entry *ce = NULL;
281 : char *class_name;
282 : zval **ret_constant;
283 :
284 : /* Skip leading \\ */
285 15281 : if (name[0] == '\\') {
286 8 : name += 1;
287 8 : name_len -= 1;
288 : }
289 :
290 :
291 15281 : if ((colon = zend_memrchr(name, ':', name_len)) &&
292 : colon > name && (*(colon - 1) == ':')) {
293 248 : int class_name_len = colon - name - 1;
294 248 : int const_name_len = name_len - class_name_len - 2;
295 248 : char *constant_name = colon + 1;
296 : char *lcname;
297 :
298 248 : class_name = estrndup(name, class_name_len);
299 248 : lcname = zend_str_tolower_dup(class_name, class_name_len);
300 248 : if (!scope) {
301 234 : if (EG(in_execution)) {
302 234 : scope = EG(scope);
303 : } else {
304 0 : scope = CG(active_class_entry);
305 : }
306 : }
307 :
308 295 : if (class_name_len == sizeof("self")-1 &&
309 : !memcmp(lcname, "self", sizeof("self")-1)) {
310 47 : if (scope) {
311 47 : ce = scope;
312 : } else {
313 0 : zend_error(E_ERROR, "Cannot access self:: when no class scope is active");
314 0 : retval = 0;
315 : }
316 47 : efree(lcname);
317 207 : } else if (class_name_len == sizeof("parent")-1 &&
318 : !memcmp(lcname, "parent", sizeof("parent")-1)) {
319 6 : if (!scope) {
320 0 : zend_error(E_ERROR, "Cannot access parent:: when no class scope is active");
321 6 : } else if (!scope->parent) {
322 0 : zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent");
323 : } else {
324 6 : ce = scope->parent;
325 : }
326 6 : efree(lcname);
327 200 : } else if (class_name_len == sizeof("static")-1 &&
328 : !memcmp(lcname, "static", sizeof("static")-1)) {
329 5 : if (EG(called_scope)) {
330 5 : ce = EG(called_scope);
331 : } else {
332 0 : zend_error(E_ERROR, "Cannot access static:: when no class scope is active");
333 : }
334 5 : efree(lcname);
335 : } else {
336 190 : efree(lcname);
337 190 : ce = zend_fetch_class(class_name, class_name_len, flags TSRMLS_CC);
338 : }
339 479 : if (retval && ce) {
340 239 : if (zend_hash_find(&ce->constants_table, constant_name, const_name_len+1, (void **) &ret_constant) != SUCCESS) {
341 5 : retval = 0;
342 5 : if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) {
343 1 : zend_error(E_ERROR, "Undefined class constant '%s::%s'", class_name, constant_name);
344 : }
345 : }
346 2 : } else if (!ce) {
347 2 : retval = 0;
348 : }
349 240 : efree(class_name);
350 240 : goto finish;
351 : }
352 :
353 : /* non-class constant */
354 15033 : if ((colon = zend_memrchr(name, '\\', name_len)) != NULL) {
355 : /* compound constant name */
356 146 : int prefix_len = colon - name;
357 146 : int const_name_len = name_len - prefix_len - 1;
358 146 : char *constant_name = colon + 1;
359 : char *lcname;
360 146 : int found_const = 0;
361 :
362 146 : lcname = zend_str_tolower_dup(name, prefix_len);
363 : /* Check for namespace constant */
364 :
365 : /* Concatenate lowercase namespace name and constant name */
366 146 : lcname = erealloc(lcname, prefix_len + 1 + const_name_len + 1);
367 146 : lcname[prefix_len] = '\\';
368 146 : memcpy(lcname + prefix_len + 1, constant_name, const_name_len + 1);
369 :
370 146 : if (zend_hash_find(EG(zend_constants), lcname, prefix_len + 1 + const_name_len + 1, (void **) &c) == SUCCESS) {
371 97 : found_const = 1;
372 : } else {
373 : /* try lowercase */
374 49 : zend_str_tolower(lcname + prefix_len + 1, const_name_len);
375 49 : if (zend_hash_find(EG(zend_constants), lcname, prefix_len + 1 + const_name_len + 1, (void **) &c) == SUCCESS) {
376 4 : if ((c->flags & CONST_CS) == 0) {
377 3 : found_const = 1;
378 : }
379 : }
380 : }
381 146 : efree(lcname);
382 146 : if(found_const) {
383 100 : *result = c->value;
384 100 : zval_update_constant_ex(&result, (void*)1, NULL TSRMLS_CC);
385 100 : zval_copy_ctor(result);
386 100 : Z_SET_REFCOUNT_P(result, 1);
387 100 : Z_UNSET_ISREF_P(result);
388 100 : return 1;
389 : }
390 : /* name requires runtime resolution, need to check non-namespaced name */
391 46 : if ((flags & IS_CONSTANT_UNQUALIFIED) != 0) {
392 35 : name = constant_name;
393 35 : name_len = const_name_len;
394 35 : return zend_get_constant(name, name_len, result TSRMLS_CC);
395 : }
396 11 : retval = 0;
397 251 : finish:
398 251 : if (retval) {
399 234 : zval_update_constant_ex(ret_constant, (void*)1, ce TSRMLS_CC);
400 232 : *result = **ret_constant;
401 232 : zval_copy_ctor(result);
402 232 : INIT_PZVAL(result);
403 : }
404 :
405 249 : return retval;
406 : }
407 :
408 14887 : return zend_get_constant(name, name_len, result TSRMLS_CC);
409 : }
410 :
411 : ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
412 36890041 : {
413 36890041 : char *lowercase_name = NULL;
414 : char *name;
415 36890041 : int ret = SUCCESS;
416 :
417 : #if 0
418 : printf("Registering constant for module %d\n", c->module_number);
419 : #endif
420 :
421 36890041 : if (!(c->flags & CONST_CS)) {
422 : /* keep in mind that c->name_len already contains the '\0' */
423 811564 : lowercase_name = estrndup(c->name, c->name_len-1);
424 811564 : zend_str_tolower(lowercase_name, c->name_len-1);
425 811564 : name = lowercase_name;
426 : } else {
427 36078477 : char *slash = strrchr(c->name, '\\');
428 36078477 : if(slash) {
429 29 : lowercase_name = estrndup(c->name, c->name_len-1);
430 29 : zend_str_tolower(lowercase_name, slash-c->name);
431 29 : name = lowercase_name;
432 : } else {
433 36078448 : name = c->name;
434 : }
435 : }
436 :
437 36890041 : if ((strncmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1) == 0) ||
438 : zend_hash_add(EG(zend_constants), name, c->name_len, (void *) c, sizeof(zend_constant), NULL)==FAILURE) {
439 7 : zend_error(E_NOTICE,"Constant %s already defined", name);
440 7 : free(c->name);
441 7 : if (!(c->flags & CONST_PERSISTENT)) {
442 7 : zval_dtor(&c->value);
443 : }
444 7 : ret = FAILURE;
445 : }
446 36890041 : if (lowercase_name) {
447 811593 : efree(lowercase_name);
448 : }
449 36890041 : return ret;
450 : }
451 :
452 :
453 : /*
454 : * Local variables:
455 : * tab-width: 4
456 : * c-basic-offset: 4
457 : * indent-tabs-mode: t
458 : * End:
459 : */
|