Coverage Report

Created: 2022-02-19 20:31

/src/php-src/Zend/zend_constants.c
Line
Count
Source (jump to first uncovered line)
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
1.13k
#define IS_CONSTANT_VISITED_MARK    0x80
31
32
424
#define IS_CONSTANT_VISITED(zv)     (Z_ACCESS_FLAGS_P(zv) & IS_CONSTANT_VISITED_MARK)
33
355
#define MARK_CONSTANT_VISITED(zv)   Z_ACCESS_FLAGS_P(zv) |= IS_CONSTANT_VISITED_MARK
34
355
#define RESET_CONSTANT_VISITED(zv)  Z_ACCESS_FLAGS_P(zv) &= ~IS_CONSTANT_VISITED_MARK
35
36
/* Use for special null/true/false constants. */
37
static zend_constant *null_const, *true_const, *false_const;
38
39
void free_zend_constant(zval *zv)
40
0
{
41
0
  zend_constant *c = Z_PTR_P(zv);
42
43
0
  if (!(ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT)) {
44
0
    zval_ptr_dtor_nogc(&c->value);
45
0
    if (c->name) {
46
0
      zend_string_release_ex(c->name, 0);
47
0
    }
48
0
    efree(c);
49
0
  } else {
50
0
    zval_internal_ptr_dtor(&c->value);
51
0
    if (c->name) {
52
0
      zend_string_release_ex(c->name, 1);
53
0
    }
54
0
    free(c);
55
0
  }
56
0
}
57
58
59
#ifdef ZTS
60
static void copy_zend_constant(zval *zv)
61
{
62
  zend_constant *c = Z_PTR_P(zv);
63
64
  ZEND_ASSERT(ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT);
65
  Z_PTR_P(zv) = pemalloc(sizeof(zend_constant), 1);
66
  memcpy(Z_PTR_P(zv), c, sizeof(zend_constant));
67
68
  c = Z_PTR_P(zv);
69
  c->name = zend_string_copy(c->name);
70
  if (Z_TYPE(c->value) == IS_STRING) {
71
    Z_STR(c->value) = zend_string_dup(Z_STR(c->value), 1);
72
  }
73
}
74
75
76
void zend_copy_constants(HashTable *target, HashTable *source)
77
{
78
  zend_hash_copy(target, source, copy_zend_constant);
79
}
80
#endif
81
82
83
static int clean_module_constant(zval *el, void *arg)
84
0
{
85
0
  zend_constant *c = (zend_constant *)Z_PTR_P(el);
86
0
  int module_number = *(int *)arg;
87
88
0
  if (ZEND_CONSTANT_MODULE_NUMBER(c) == module_number) {
89
0
    return ZEND_HASH_APPLY_REMOVE;
90
0
  } else {
91
0
    return ZEND_HASH_APPLY_KEEP;
92
0
  }
93
0
}
94
95
96
void clean_module_constants(int module_number)
97
0
{
98
0
  zend_hash_apply_with_argument(EG(zend_constants), clean_module_constant, (void *) &module_number);
99
0
}
100
101
void zend_startup_constants(void)
102
0
{
103
0
  EG(zend_constants) = (HashTable *) malloc(sizeof(HashTable));
104
0
  zend_hash_init(EG(zend_constants), 128, NULL, ZEND_CONSTANT_DTOR, 1);
105
0
}
106
107
108
109
void zend_register_standard_constants(void)
110
6.08k
{
111
6.08k
  REGISTER_MAIN_LONG_CONSTANT("E_ERROR", E_ERROR, CONST_PERSISTENT | CONST_CS);
112
6.08k
  REGISTER_MAIN_LONG_CONSTANT("E_RECOVERABLE_ERROR", E_RECOVERABLE_ERROR, CONST_PERSISTENT | CONST_CS);
113
6.08k
  REGISTER_MAIN_LONG_CONSTANT("E_WARNING", E_WARNING, CONST_PERSISTENT | CONST_CS);
114
6.08k
  REGISTER_MAIN_LONG_CONSTANT("E_PARSE", E_PARSE, CONST_PERSISTENT | CONST_CS);
115
6.08k
  REGISTER_MAIN_LONG_CONSTANT("E_NOTICE", E_NOTICE, CONST_PERSISTENT | CONST_CS);
116
6.08k
  REGISTER_MAIN_LONG_CONSTANT("E_STRICT", E_STRICT, CONST_PERSISTENT | CONST_CS);
117
6.08k
  REGISTER_MAIN_LONG_CONSTANT("E_DEPRECATED", E_DEPRECATED, CONST_PERSISTENT | CONST_CS);
118
6.08k
  REGISTER_MAIN_LONG_CONSTANT("E_CORE_ERROR", E_CORE_ERROR, CONST_PERSISTENT | CONST_CS);
119
6.08k
  REGISTER_MAIN_LONG_CONSTANT("E_CORE_WARNING", E_CORE_WARNING, CONST_PERSISTENT | CONST_CS);
120
6.08k
  REGISTER_MAIN_LONG_CONSTANT("E_COMPILE_ERROR", E_COMPILE_ERROR, CONST_PERSISTENT | CONST_CS);
121
6.08k
  REGISTER_MAIN_LONG_CONSTANT("E_COMPILE_WARNING", E_COMPILE_WARNING, CONST_PERSISTENT | CONST_CS);
122
6.08k
  REGISTER_MAIN_LONG_CONSTANT("E_USER_ERROR", E_USER_ERROR, CONST_PERSISTENT | CONST_CS);
123
6.08k
  REGISTER_MAIN_LONG_CONSTANT("E_USER_WARNING", E_USER_WARNING, CONST_PERSISTENT | CONST_CS);
124
6.08k
  REGISTER_MAIN_LONG_CONSTANT("E_USER_NOTICE", E_USER_NOTICE, CONST_PERSISTENT | CONST_CS);
125
6.08k
  REGISTER_MAIN_LONG_CONSTANT("E_USER_DEPRECATED", E_USER_DEPRECATED, CONST_PERSISTENT | CONST_CS);
126
127
6.08k
  REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL, CONST_PERSISTENT | CONST_CS);
128
129
6.08k
  REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_PROVIDE_OBJECT", DEBUG_BACKTRACE_PROVIDE_OBJECT, CONST_PERSISTENT | CONST_CS);
130
6.08k
  REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_IGNORE_ARGS", DEBUG_BACKTRACE_IGNORE_ARGS, CONST_PERSISTENT | CONST_CS);
131
6.08k
  REGISTER_MAIN_BOOL_CONSTANT("ZEND_THREAD_SAFE", ZTS_V, CONST_PERSISTENT | CONST_CS);
132
6.08k
  REGISTER_MAIN_BOOL_CONSTANT("ZEND_DEBUG_BUILD", ZEND_DEBUG, CONST_PERSISTENT | CONST_CS);
133
134
  /* Special constants true/false/null.  */
135
6.08k
  REGISTER_MAIN_BOOL_CONSTANT("TRUE", 1, CONST_PERSISTENT);
136
6.08k
  REGISTER_MAIN_BOOL_CONSTANT("FALSE", 0, CONST_PERSISTENT);
137
6.08k
  REGISTER_MAIN_NULL_CONSTANT("NULL", CONST_PERSISTENT);
138
139
6.08k
  true_const = zend_hash_str_find_ptr(EG(zend_constants), "TRUE", sizeof("TRUE")-1);
140
6.08k
  false_const = zend_hash_str_find_ptr(EG(zend_constants), "FALSE", sizeof("FALSE")-1);
141
6.08k
  null_const = zend_hash_str_find_ptr(EG(zend_constants), "NULL", sizeof("NULL")-1);
142
6.08k
}
143
144
145
void zend_shutdown_constants(void)
146
0
{
147
0
  zend_hash_destroy(EG(zend_constants));
148
0
  free(EG(zend_constants));
149
0
}
150
151
ZEND_API void zend_register_null_constant(const char *name, size_t name_len, int flags, int module_number)
152
6.08k
{
153
6.08k
  zend_constant c;
154
155
6.08k
  ZVAL_NULL(&c.value);
156
6.08k
  ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
157
6.08k
  c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
158
6.08k
  zend_register_constant(&c);
159
6.08k
}
160
161
ZEND_API void zend_register_bool_constant(const char *name, size_t name_len, zend_bool bval, int flags, int module_number)
162
30.4k
{
163
30.4k
  zend_constant c;
164
165
30.4k
  ZVAL_BOOL(&c.value, bval);
166
30.4k
  ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
167
30.4k
  c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
168
30.4k
  zend_register_constant(&c);
169
30.4k
}
170
171
ZEND_API void zend_register_long_constant(const char *name, size_t name_len, zend_long lval, int flags, int module_number)
172
2.77M
{
173
2.77M
  zend_constant c;
174
175
2.77M
  ZVAL_LONG(&c.value, lval);
176
2.77M
  ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
177
2.77M
  c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
178
2.77M
  zend_register_constant(&c);
179
2.77M
}
180
181
182
ZEND_API void zend_register_double_constant(const char *name, size_t name_len, double dval, int flags, int module_number)
183
133k
{
184
133k
  zend_constant c;
185
186
133k
  ZVAL_DOUBLE(&c.value, dval);
187
133k
  ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
188
133k
  c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
189
133k
  zend_register_constant(&c);
190
133k
}
191
192
193
ZEND_API void zend_register_stringl_constant(const char *name, size_t name_len, const char *strval, size_t strlen, int flags, int module_number)
194
243k
{
195
243k
  zend_constant c;
196
197
243k
  ZVAL_STR(&c.value, zend_string_init_interned(strval, strlen, flags & CONST_PERSISTENT));
198
243k
  ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
199
243k
  c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
200
243k
  zend_register_constant(&c);
201
243k
}
202
203
204
ZEND_API void zend_register_string_constant(const char *name, size_t name_len, const char *strval, int flags, int module_number)
205
115k
{
206
115k
  zend_register_stringl_constant(name, name_len, strval, strlen(strval), flags, module_number);
207
115k
}
208
209
static zend_constant *zend_get_halt_offset_constant(const char *name, size_t name_len)
210
466k
{
211
466k
  zend_constant *c;
212
466k
  static const char haltoff[] = "__COMPILER_HALT_OFFSET__";
213
214
466k
  if (!EG(current_execute_data)) {
215
1
    return NULL;
216
466k
  } else if (name_len == sizeof("__COMPILER_HALT_OFFSET__")-1 &&
217
239
            !memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1)) {
218
0
    const char *cfilename;
219
0
    zend_string *haltname;
220
0
    size_t clen;
221
222
0
    cfilename = zend_get_executed_filename();
223
0
    clen = strlen(cfilename);
224
    /* check for __COMPILER_HALT_OFFSET__ */
225
0
    haltname = zend_mangle_property_name(haltoff,
226
0
      sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename, clen, 0);
227
0
    c = zend_hash_find_ptr(EG(zend_constants), haltname);
228
0
    zend_string_efree(haltname);
229
0
    return c;
230
466k
  } else {
231
466k
    return NULL;
232
466k
  }
233
466k
}
234
235
ZEND_API zend_constant *_zend_get_special_const(const char *name, size_t len) /* {{{ */
236
238k
{
237
238k
  if (len == 4) {
238
180k
    if ((name[0] == 'n' || name[0] == 'N') &&
239
85.4k
      (name[1] == 'u' || name[1] == 'U') &&
240
81.1k
      (name[2] == 'l' || name[2] == 'L') &&
241
80.1k
      (name[3] == 'l' || name[3] == 'L')
242
79.1k
    ) {
243
79.1k
      return null_const;
244
79.1k
    }
245
101k
    if ((name[0] == 't' || name[0] == 'T') &&
246
77.9k
      (name[1] == 'r' || name[1] == 'R') &&
247
41.2k
      (name[2] == 'u' || name[2] == 'U') &&
248
40.0k
      (name[3] == 'e' || name[3] == 'E')
249
37.5k
    ) {
250
37.5k
      return true_const;
251
37.5k
    }
252
57.6k
  } else {
253
57.6k
    if ((name[0] == 'f' || name[0] == 'F') &&
254
28.5k
      (name[1] == 'a' || name[1] == 'A') &&
255
25.9k
      (name[2] == 'l' || name[2] == 'L') &&
256
25.0k
      (name[3] == 's' || name[3] == 'S') &&
257
23.2k
      (name[4] == 'e' || name[4] == 'E')
258
22.5k
    ) {
259
22.5k
      return false_const;
260
22.5k
    }
261
98.7k
  }
262
98.7k
  return NULL;
263
98.7k
}
264
/* }}} */
265
266
ZEND_API bool zend_verify_const_access(zend_class_constant *c, zend_class_entry *scope) /* {{{ */
267
17.8k
{
268
17.8k
  if (Z_ACCESS_FLAGS(c->value) & ZEND_ACC_PUBLIC) {
269
16.8k
    return 1;
270
1.01k
  } else if (Z_ACCESS_FLAGS(c->value) & ZEND_ACC_PRIVATE) {
271
990
    return (c->ce == scope);
272
22
  } else {
273
22
    ZEND_ASSERT(Z_ACCESS_FLAGS(c->value) & ZEND_ACC_PROTECTED);
274
22
    return zend_check_protected(c->ce, scope);
275
22
  }
276
17.8k
}
277
/* }}} */
278
279
static zend_constant *zend_get_constant_str_impl(const char *name, size_t name_len)
280
575
{
281
575
  zend_constant *c = zend_hash_str_find_ptr(EG(zend_constants), name, name_len);
282
575
  if (c) {
283
472
    return c;
284
472
  }
285
286
103
  c = zend_get_halt_offset_constant(name, name_len);
287
103
  if (c) {
288
0
    return c;
289
0
  }
290
291
103
  return zend_get_special_const(name, name_len);
292
103
}
293
294
ZEND_API zval *zend_get_constant_str(const char *name, size_t name_len)
295
0
{
296
0
  zend_constant *c = zend_get_constant_str_impl(name, name_len);
297
0
  if (c) {
298
0
    return &c->value;
299
0
  }
300
0
  return NULL;
301
0
}
302
303
static zend_constant *zend_get_constant_impl(zend_string *name)
304
475k
{
305
475k
  zend_constant *c = zend_hash_find_ptr(EG(zend_constants), name);
306
475k
  if (c) {
307
9.07k
    return c;
308
9.07k
  }
309
310
466k
  c = zend_get_halt_offset_constant(ZSTR_VAL(name), ZSTR_LEN(name));
311
466k
  if (c) {
312
0
    return c;
313
0
  }
314
315
466k
  return zend_get_special_const(ZSTR_VAL(name), ZSTR_LEN(name));
316
466k
}
317
318
ZEND_API zval *zend_get_constant(zend_string *name)
319
464k
{
320
464k
  zend_constant *c = zend_get_constant_impl(name);
321
464k
  if (c) {
322
1.96k
    return &c->value;
323
1.96k
  }
324
463k
  return NULL;
325
463k
}
326
327
ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, uint32_t flags)
328
21.2k
{
329
21.2k
  zend_constant *c;
330
21.2k
  const char *colon;
331
21.2k
  zend_class_entry *ce = NULL;
332
21.2k
  const char *name = ZSTR_VAL(cname);
333
21.2k
  size_t name_len = ZSTR_LEN(cname);
334
335
  /* Skip leading \\ */
336
21.2k
  if (name[0] == '\\') {
337
319
    name += 1;
338
319
    name_len -= 1;
339
319
    cname = NULL;
340
319
  }
341
342
21.2k
  if ((colon = zend_memrchr(name, ':', name_len)) &&
343
8.28k
      colon > name && (*(colon - 1) == ':')) {
344
8.16k
    int class_name_len = colon - name - 1;
345
8.16k
    size_t const_name_len = name_len - class_name_len - 2;
346
8.16k
    zend_string *constant_name = zend_string_init(colon + 1, const_name_len, 0);
347
8.16k
    zend_string *class_name = zend_string_init(name, class_name_len, 0);
348
8.16k
    zend_class_constant *c = NULL;
349
8.16k
    zval *ret_constant = NULL;
350
351
8.16k
    if (zend_string_equals_literal_ci(class_name, "self")) {
352
2.66k
      if (UNEXPECTED(!scope)) {
353
4
        zend_throw_error(NULL, "Cannot access \"self\" when no class scope is active");
354
4
        goto failure;
355
4
      }
356
2.66k
      ce = scope;
357
5.50k
    } else if (zend_string_equals_literal_ci(class_name, "parent")) {
358
409
      if (UNEXPECTED(!scope)) {
359
0
        zend_throw_error(NULL, "Cannot access \"parent\" when no class scope is active");
360
0
        goto failure;
361
409
      } else if (UNEXPECTED(!scope->parent)) {
362
20
        zend_throw_error(NULL, "Cannot access \"parent\" when current class scope has no parent");
363
20
        goto failure;
364
389
      } else {
365
389
        ce = scope->parent;
366
389
      }
367
5.09k
    } else if (zend_string_equals_literal_ci(class_name, "static")) {
368
325
      ce = zend_get_called_scope(EG(current_execute_data));
369
325
      if (UNEXPECTED(!ce)) {
370
0
        zend_throw_error(NULL, "Cannot access \"static\" when no class scope is active");
371
0
        goto failure;
372
0
      }
373
4.76k
    } else {
374
4.76k
      ce = zend_fetch_class(class_name, flags);
375
4.76k
    }
376
8.14k
    if (ce) {
377
7.43k
      c = zend_hash_find_ptr(&ce->constants_table, constant_name);
378
7.43k
      if (c == NULL) {
379
523
        if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) {
380
270
          zend_throw_error(NULL, "Undefined constant %s::%s", ZSTR_VAL(class_name), ZSTR_VAL(constant_name));
381
270
          goto failure;
382
270
        }
383
253
        ret_constant = NULL;
384
6.91k
      } else {
385
6.91k
        if (!zend_verify_const_access(c, scope)) {
386
0
          if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) {
387
0
            zend_throw_error(NULL, "Cannot access %s constant %s::%s", zend_visibility_string(Z_ACCESS_FLAGS(c->value)), ZSTR_VAL(class_name), ZSTR_VAL(constant_name));
388
0
          }
389
0
          goto failure;
390
0
        }
391
6.91k
        ret_constant = &c->value;
392
6.91k
      }
393
7.43k
    }
394
395
7.87k
    if (ret_constant && Z_TYPE_P(ret_constant) == IS_CONSTANT_AST) {
396
424
      zend_result ret;
397
398
424
      if (IS_CONSTANT_VISITED(ret_constant)) {
399
69
        zend_throw_error(NULL, "Cannot declare self-referencing constant %s::%s", ZSTR_VAL(class_name), ZSTR_VAL(constant_name));
400
69
        ret_constant = NULL;
401
69
        goto failure;
402
69
      }
403
404
355
      MARK_CONSTANT_VISITED(ret_constant);
405
355
      ret = zval_update_constant_ex(ret_constant, c->ce);
406
355
      RESET_CONSTANT_VISITED(ret_constant);
407
408
355
      if (UNEXPECTED(ret != SUCCESS)) {
409
169
        ret_constant = NULL;
410
169
        goto failure;
411
169
      }
412
8.12k
    }
413
8.12k
failure:
414
8.12k
    zend_string_release_ex(class_name, 0);
415
8.12k
    zend_string_efree(constant_name);
416
8.12k
    return ret_constant;
417
13.1k
  }
418
419
  /* non-class constant */
420
13.1k
  if ((colon = zend_memrchr(name, '\\', name_len)) != NULL) {
421
    /* compound constant name */
422
2.88k
    int prefix_len = colon - name;
423
2.88k
    size_t const_name_len = name_len - prefix_len - 1;
424
2.88k
    const char *constant_name = colon + 1;
425
2.88k
    char *lcname;
426
2.88k
    size_t lcname_len;
427
2.88k
    ALLOCA_FLAG(use_heap)
428
429
    /* Lowercase the namespace portion */
430
2.88k
    lcname_len = prefix_len + 1 + const_name_len;
431
2.88k
    lcname = do_alloca(lcname_len + 1, use_heap);
432
2.88k
    zend_str_tolower_copy(lcname, name, prefix_len);
433
434
2.88k
    lcname[prefix_len] = '\\';
435
2.88k
    memcpy(lcname + prefix_len + 1, constant_name, const_name_len + 1);
436
437
2.88k
    c = zend_hash_str_find_ptr(EG(zend_constants), lcname, lcname_len);
438
2.88k
    free_alloca(lcname, use_heap);
439
440
2.88k
    if (!c) {
441
871
      if (flags & IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE) {
442
        /* name requires runtime resolution, need to check non-namespaced name */
443
545
        c = zend_get_constant_str_impl(constant_name, const_name_len);
444
545
      }
445
871
    }
446
10.2k
  } else {
447
10.2k
    if (cname) {
448
10.1k
      c = zend_get_constant_impl(cname);
449
30
    } else {
450
30
      c = zend_get_constant_str_impl(name, name_len);
451
30
    }
452
10.2k
  }
453
454
13.1k
  if (!c) {
455
1.98k
    if (!(flags & ZEND_FETCH_CLASS_SILENT)) {
456
1.51k
      zend_throw_error(NULL, "Undefined constant \"%s\"", name);
457
1.51k
    }
458
1.98k
    return NULL;
459
1.98k
  }
460
461
11.1k
  if (!(flags & ZEND_FETCH_CLASS_SILENT) && (ZEND_CONSTANT_FLAGS(c) & CONST_DEPRECATED)) {
462
0
    zend_error(E_DEPRECATED, "Constant %s is deprecated", name);
463
0
  }
464
11.1k
  return &c->value;
465
11.1k
}
466
467
static void* zend_hash_add_constant(HashTable *ht, zend_string *key, zend_constant *c)
468
3.20M
{
469
3.20M
  void *ret;
470
3.20M
  zend_constant *copy = pemalloc(sizeof(zend_constant), ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT);
471
472
3.20M
  memcpy(copy, c, sizeof(zend_constant));
473
3.20M
  ret = zend_hash_add_ptr(ht, key, copy);
474
3.20M
  if (!ret) {
475
153
    pefree(copy, ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT);
476
153
  }
477
3.20M
  return ret;
478
3.20M
}
479
480
ZEND_API zend_result zend_register_constant(zend_constant *c)
481
3.20M
{
482
3.20M
  zend_string *lowercase_name = NULL;
483
3.20M
  zend_string *name;
484
3.20M
  zend_result ret = SUCCESS;
485
3.20M
  zend_bool persistent = (ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT) != 0;
486
487
#if 0
488
  printf("Registering constant for module %d\n", c->module_number);
489
#endif
490
491
3.20M
  char *slash = strrchr(ZSTR_VAL(c->name), '\\');
492
3.20M
  if (slash) {
493
1.57k
    lowercase_name = zend_string_init(ZSTR_VAL(c->name), ZSTR_LEN(c->name), persistent);
494
1.57k
    zend_str_tolower(ZSTR_VAL(lowercase_name), slash - ZSTR_VAL(c->name));
495
1.57k
    lowercase_name = zend_new_interned_string(lowercase_name);
496
1.57k
    name = lowercase_name;
497
3.20M
  } else {
498
3.20M
    name = c->name;
499
3.20M
  }
500
501
  /* Check if the user is trying to define any special constant */
502
3.20M
  if (zend_string_equals_literal(name, "__COMPILER_HALT_OFFSET__")
503
3.20M
    || (!persistent && zend_get_special_const(ZSTR_VAL(name), ZSTR_LEN(name)))
504
3.20M
    || zend_hash_add_constant(EG(zend_constants), name, c) == NULL
505
263
  ) {
506
263
    zend_error(E_NOTICE,"Constant %s already defined", ZSTR_VAL(name));
507
263
    zend_string_release(c->name);
508
263
    if (!persistent) {
509
263
      zval_ptr_dtor_nogc(&c->value);
510
263
    }
511
263
    ret = FAILURE;
512
263
  }
513
3.20M
  if (lowercase_name) {
514
1.57k
    zend_string_release(lowercase_name);
515
1.57k
  }
516
3.20M
  return ret;
517
3.20M
}