Coverage Report

Created: 2024-08-16 12:10

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