php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
zend_ini.c
Go to the documentation of this file.
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 | Author: Zeev Suraski <zeev@php.net> |
16 +----------------------------------------------------------------------+
17*/
18
19#include "zend.h"
20#include "zend_sort.h"
21#include "zend_API.h"
22#include "zend_ini.h"
23#include "zend_alloc.h"
24#include "zend_operators.h"
25#include "zend_strtod.h"
26#include "zend_modules.h"
27#include "zend_smart_str.h"
28#include <ctype.h>
29
30static HashTable *registered_zend_ini_directives;
31
32#define NO_VALUE_PLAINTEXT "no value"
33#define NO_VALUE_HTML "<i>no value</i>"
34
35static inline bool zend_is_whitespace(char c) {
36 return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\v' || c == '\f';
37}
38
39/*
40 * hash_apply functions
41 */
42static int zend_remove_ini_entries(zval *el, void *arg) /* {{{ */
43{
44 zend_ini_entry *ini_entry = (zend_ini_entry *)Z_PTR_P(el);
45 int module_number = *(int *)arg;
46
47 return ini_entry->module_number == module_number;
48}
49/* }}} */
50
51static zend_result zend_restore_ini_entry_cb(zend_ini_entry *ini_entry, int stage) /* {{{ */
52{
54
55 if (ini_entry->modified) {
56 if (ini_entry->on_modify) {
57 zend_try {
58 /* even if on_modify bails out, we have to continue on with restoring,
59 since there can be allocated variables that would be freed on MM shutdown
60 and would lead to memory corruption later ini entry is modified again */
61 result = ini_entry->on_modify(ini_entry, ini_entry->orig_value, ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage);
62 } zend_end_try();
63 }
64 if (stage == ZEND_INI_STAGE_RUNTIME && result == FAILURE) {
65 /* runtime failure is OK */
66 return FAILURE;
67 }
68 if (ini_entry->value != ini_entry->orig_value) {
69 zend_string_release(ini_entry->value);
70 }
71 ini_entry->value = ini_entry->orig_value;
72 ini_entry->modifiable = ini_entry->orig_modifiable;
73 ini_entry->modified = 0;
74 ini_entry->orig_value = NULL;
75 ini_entry->orig_modifiable = 0;
76 }
77 return SUCCESS;
78}
79/* }}} */
80
81static void free_ini_entry(zval *zv) /* {{{ */
82{
84
86 if (entry->value) {
87 zend_string_release(entry->value);
88 }
89 if (entry->orig_value) {
91 }
92 free(entry);
93}
94/* }}} */
95
96/*
97 * Startup / shutdown
98 */
99ZEND_API void zend_ini_startup(void) /* {{{ */
100{
101 registered_zend_ini_directives = (HashTable *) malloc(sizeof(HashTable));
102
103 EG(ini_directives) = registered_zend_ini_directives;
104 EG(modified_ini_directives) = NULL;
105 EG(error_reporting_ini_entry) = NULL;
106 zend_hash_init(registered_zend_ini_directives, 128, NULL, free_ini_entry, 1);
107}
108/* }}} */
109
110ZEND_API void zend_ini_shutdown(void) /* {{{ */
111{
112 zend_ini_dtor(EG(ini_directives));
113}
114/* }}} */
115
116ZEND_API void zend_ini_dtor(HashTable *ini_directives) /* {{{ */
117{
118 zend_hash_destroy(ini_directives);
119 free(ini_directives);
120}
121/* }}} */
122
124{
125 zend_hash_destroy(registered_zend_ini_directives);
126 free(registered_zend_ini_directives);
127}
128/* }}} */
129
130ZEND_API void zend_ini_deactivate(void) /* {{{ */
131{
132 if (EG(modified_ini_directives)) {
133 zend_ini_entry *ini_entry;
134
135 ZEND_HASH_MAP_FOREACH_PTR(EG(modified_ini_directives), ini_entry) {
136 zend_restore_ini_entry_cb(ini_entry, ZEND_INI_STAGE_DEACTIVATE);
138 zend_hash_destroy(EG(modified_ini_directives));
139 FREE_HASHTABLE(EG(modified_ini_directives));
140 EG(modified_ini_directives) = NULL;
141 }
142}
143/* }}} */
144
145#ifdef ZTS
146static void copy_ini_entry(zval *zv) /* {{{ */
147{
148 zend_ini_entry *old_entry = (zend_ini_entry*)Z_PTR_P(zv);
149 zend_ini_entry *new_entry = pemalloc(sizeof(zend_ini_entry), 1);
150
151 Z_PTR_P(zv) = new_entry;
152 memcpy(new_entry, old_entry, sizeof(zend_ini_entry));
153 if (old_entry->name) {
154 new_entry->name = zend_string_dup(old_entry->name, 1);
155 }
156 if (old_entry->value) {
157 new_entry->value = zend_string_dup(old_entry->value, 1);
158 }
159 if (old_entry->orig_value) {
160 new_entry->orig_value = zend_string_dup(old_entry->orig_value, 1);
161 }
162}
163/* }}} */
164
165ZEND_API void zend_copy_ini_directives(void) /* {{{ */
166{
167 EG(modified_ini_directives) = NULL;
168 EG(error_reporting_ini_entry) = NULL;
169 EG(ini_directives) = (HashTable *) malloc(sizeof(HashTable));
170 zend_hash_init(EG(ini_directives), registered_zend_ini_directives->nNumOfElements, NULL, free_ini_entry, 1);
171 zend_hash_copy(EG(ini_directives), registered_zend_ini_directives, copy_ini_entry);
172}
173/* }}} */
174#endif
175
176static int ini_key_compare(Bucket *f, Bucket *s) /* {{{ */
177{
178 if (!f->key && !s->key) { /* both numeric */
179 if (f->h > s->h) {
180 return -1;
181 } else if (f->h < s->h) {
182 return 1;
183 }
184 return 0;
185 } else if (!f->key) { /* f is numeric, s is not */
186 return -1;
187 } else if (!s->key) { /* s is numeric, f is not */
188 return 1;
189 } else { /* both strings */
190 return zend_binary_strcasecmp(ZSTR_VAL(f->key), ZSTR_LEN(f->key), ZSTR_VAL(s->key), ZSTR_LEN(s->key));
191 }
192}
193/* }}} */
194
195ZEND_API void zend_ini_sort_entries(void) /* {{{ */
196{
197 zend_hash_sort(EG(ini_directives), ini_key_compare, 0);
198}
199/* }}} */
200
201/*
202 * Registration / unregistration
203 */
204ZEND_API zend_result zend_register_ini_entries_ex(const zend_ini_entry_def *ini_entry, int module_number, int module_type) /* {{{ */
205{
207 zval *default_value;
208 HashTable *directives = registered_zend_ini_directives;
209
210#ifdef ZTS
211 /* if we are called during the request, eg: from dl(),
212 * then we should not touch the global directives table,
213 * and should update the per-(request|thread) version instead.
214 * This solves two problems: one is that ini entries for dl()'d
215 * extensions will now work, and the second is that updating the
216 * global hash here from dl() is not mutex protected and can
217 * lead to death.
218 */
219 if (directives != EG(ini_directives)) {
220 directives = EG(ini_directives);
221 } else {
222 ZEND_ASSERT(module_type == MODULE_PERSISTENT);
223 }
224#endif
225
226 while (ini_entry->name) {
227 p = pemalloc(sizeof(zend_ini_entry), 1);
228 p->name = zend_string_init_interned(ini_entry->name, ini_entry->name_length, 1);
229 p->on_modify = ini_entry->on_modify;
230 p->mh_arg1 = ini_entry->mh_arg1;
231 p->mh_arg2 = ini_entry->mh_arg2;
232 p->mh_arg3 = ini_entry->mh_arg3;
233 p->value = NULL;
234 p->orig_value = NULL;
235 p->displayer = ini_entry->displayer;
236 p->modifiable = ini_entry->modifiable;
237
238 p->orig_modifiable = 0;
239 p->modified = 0;
240 p->module_number = module_number;
241
242 if (zend_hash_add_ptr(directives, p->name, (void*)p) == NULL) {
243 if (p->name) {
244 zend_string_release_ex(p->name, 1);
245 }
246 pefree(p, true);
247 zend_unregister_ini_entries_ex(module_number, module_type);
248 return FAILURE;
249 }
250 if (((default_value = zend_get_configuration_directive(p->name)) != NULL) &&
251 (!p->on_modify || p->on_modify(p, Z_STR_P(default_value), p->mh_arg1, p->mh_arg2, p->mh_arg3, ZEND_INI_STAGE_STARTUP) == SUCCESS)) {
252
253 p->value = zend_new_interned_string(zend_string_copy(Z_STR_P(default_value)));
254 } else {
255 p->value = ini_entry->value ?
256 zend_string_init_interned(ini_entry->value, ini_entry->value_length, 1) : NULL;
257
258 if (p->on_modify) {
259 p->on_modify(p, p->value, p->mh_arg1, p->mh_arg2, p->mh_arg3, ZEND_INI_STAGE_STARTUP);
260 }
261 }
262 ini_entry++;
263 }
264 return SUCCESS;
265}
266/* }}} */
267
268ZEND_API zend_result zend_register_ini_entries(const zend_ini_entry_def *ini_entry, int module_number) /* {{{ */
269{
270 zend_module_entry *module;
271
272 /* Module is likely to be the last one in the list */
274 if (module->module_number == module_number) {
275 return zend_register_ini_entries_ex(ini_entry, module_number, module->type);
276 }
278
279 return FAILURE;
280}
281/* }}} */
282
283ZEND_API void zend_unregister_ini_entries_ex(int module_number, int module_type) /* {{{ */
284{
285 static HashTable *ini_directives;
286
287 if (module_type == MODULE_TEMPORARY) {
288 ini_directives = EG(ini_directives);
289 } else {
290 ini_directives = registered_zend_ini_directives;
291 }
292
293 zend_hash_apply_with_argument(ini_directives, zend_remove_ini_entries, (void *) &module_number);
294}
295/* }}} */
296
297ZEND_API void zend_unregister_ini_entries(int module_number) /* {{{ */
298{
299 zend_module_entry *module;
300
301 /* Module is likely to be the last one in the list */
303 if (module->module_number == module_number) {
304 zend_unregister_ini_entries_ex(module_number, module->type);
305 return;
306 }
308}
309/* }}} */
310
311#ifdef ZTS
312ZEND_API void zend_ini_refresh_caches(int stage) /* {{{ */
313{
315
316 ZEND_HASH_MAP_FOREACH_PTR(EG(ini_directives), p) {
317 if (p->on_modify) {
318 p->on_modify(p, p->value, p->mh_arg1, p->mh_arg2, p->mh_arg3, stage);
319 }
321}
322/* }}} */
323#endif
324
325ZEND_API zend_result zend_alter_ini_entry(zend_string *name, zend_string *new_value, int modify_type, int stage) /* {{{ */
326{
327
328 return zend_alter_ini_entry_ex(name, new_value, modify_type, stage, 0);
329}
330/* }}} */
331
332ZEND_API zend_result zend_alter_ini_entry_chars(zend_string *name, const char *value, size_t value_length, int modify_type, int stage) /* {{{ */
333{
335 zend_string *new_value;
336
337 new_value = zend_string_init(value, value_length, !(stage & ZEND_INI_STAGE_IN_REQUEST));
338 ret = zend_alter_ini_entry_ex(name, new_value, modify_type, stage, 0);
339 zend_string_release(new_value);
340 return ret;
341}
342/* }}} */
343
344ZEND_API zend_result zend_alter_ini_entry_chars_ex(zend_string *name, const char *value, size_t value_length, int modify_type, int stage, int force_change) /* {{{ */
345{
347 zend_string *new_value;
348
349 new_value = zend_string_init(value, value_length, !(stage & ZEND_INI_STAGE_IN_REQUEST));
350 ret = zend_alter_ini_entry_ex(name, new_value, modify_type, stage, force_change);
351 zend_string_release(new_value);
352 return ret;
353}
354/* }}} */
355
356ZEND_API zend_result zend_alter_ini_entry_ex(zend_string *name, zend_string *new_value, int modify_type, int stage, bool force_change) /* {{{ */
357{
358 zend_ini_entry *ini_entry;
359 zend_string *duplicate;
360 uint8_t modifiable;
361 bool modified;
362
363 if ((ini_entry = zend_hash_find_ptr(EG(ini_directives), name)) == NULL) {
364 return FAILURE;
365 }
366
367 modifiable = ini_entry->modifiable;
368 modified = ini_entry->modified;
369
370 if (stage == ZEND_INI_STAGE_ACTIVATE && modify_type == ZEND_INI_SYSTEM) {
371 ini_entry->modifiable = ZEND_INI_SYSTEM;
372 }
373
374 if (!force_change) {
375 if (!(ini_entry->modifiable & modify_type)) {
376 return FAILURE;
377 }
378 }
379
380 if (!EG(modified_ini_directives)) {
381 ALLOC_HASHTABLE(EG(modified_ini_directives));
382 zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0);
383 }
384 if (!modified) {
385 ini_entry->orig_value = ini_entry->value;
386 ini_entry->orig_modifiable = modifiable;
387 ini_entry->modified = 1;
388 zend_hash_add_ptr(EG(modified_ini_directives), ini_entry->name, ini_entry);
389 }
390
391 duplicate = zend_string_copy(new_value);
392
393 if (!ini_entry->on_modify
394 || ini_entry->on_modify(ini_entry, duplicate, ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage) == SUCCESS) {
395 if (modified && ini_entry->orig_value != ini_entry->value) { /* we already changed the value, free the changed value */
396 zend_string_release(ini_entry->value);
397 }
398 ini_entry->value = duplicate;
399 } else {
400 zend_string_release(duplicate);
401 return FAILURE;
402 }
403
404 return SUCCESS;
405}
406/* }}} */
407
409{
410 zend_ini_entry *ini_entry;
411
412 if ((ini_entry = zend_hash_find_ptr(EG(ini_directives), name)) == NULL ||
413 (stage == ZEND_INI_STAGE_RUNTIME && (ini_entry->modifiable & ZEND_INI_USER) == 0)) {
414 return FAILURE;
415 }
416
417 if (EG(modified_ini_directives)) {
418 if (zend_restore_ini_entry_cb(ini_entry, stage) == 0) {
419 zend_hash_del(EG(modified_ini_directives), name);
420 } else {
421 return FAILURE;
422 }
423 }
424
425 return SUCCESS;
426}
427/* }}} */
428
429ZEND_API zend_result zend_ini_register_displayer(const char *name, uint32_t name_length, void (*displayer)(zend_ini_entry *ini_entry, int type)) /* {{{ */
430{
431 zend_ini_entry *ini_entry;
432
433 ini_entry = zend_hash_str_find_ptr(registered_zend_ini_directives, name, name_length);
434 if (ini_entry == NULL) {
435 return FAILURE;
436 }
437
438 ini_entry->displayer = displayer;
439 return SUCCESS;
440}
441/* }}} */
442
443/*
444 * Data retrieval
445 */
446
447ZEND_API zend_long zend_ini_long(const char *name, size_t name_length, int orig) /* {{{ */
448{
449 zend_ini_entry *ini_entry;
450
451 ini_entry = zend_hash_str_find_ptr(EG(ini_directives), name, name_length);
452 if (ini_entry) {
453 if (orig && ini_entry->modified) {
454 return (ini_entry->orig_value ? ZEND_STRTOL(ZSTR_VAL(ini_entry->orig_value), NULL, 0) : 0);
455 } else {
456 return (ini_entry->value ? ZEND_STRTOL(ZSTR_VAL(ini_entry->value), NULL, 0) : 0);
457 }
458 }
459
460 return 0;
461}
462/* }}} */
463
464ZEND_API double zend_ini_double(const char *name, size_t name_length, int orig) /* {{{ */
465{
466 zend_ini_entry *ini_entry;
467
468 ini_entry = zend_hash_str_find_ptr(EG(ini_directives), name, name_length);
469 if (ini_entry) {
470 if (orig && ini_entry->modified) {
471 return (double) (ini_entry->orig_value ? zend_strtod(ZSTR_VAL(ini_entry->orig_value), NULL) : 0.0);
472 } else {
473 return (double) (ini_entry->value ? zend_strtod(ZSTR_VAL(ini_entry->value), NULL) : 0.0);
474 }
475 }
476
477 return 0.0;
478}
479/* }}} */
480
481ZEND_API char *zend_ini_string_ex(const char *name, size_t name_length, int orig, bool *exists) /* {{{ */
482{
483 zend_ini_entry *ini_entry;
484
485 ini_entry = zend_hash_str_find_ptr(EG(ini_directives), name, name_length);
486 if (ini_entry) {
487 if (exists) {
488 *exists = 1;
489 }
490
491 if (orig && ini_entry->modified) {
492 return ini_entry->orig_value ? ZSTR_VAL(ini_entry->orig_value) : NULL;
493 } else {
494 return ini_entry->value ? ZSTR_VAL(ini_entry->value) : NULL;
495 }
496 } else {
497 if (exists) {
498 *exists = 0;
499 }
500 return NULL;
501 }
502}
503/* }}} */
504
505ZEND_API char *zend_ini_string(const char *name, size_t name_length, int orig) /* {{{ */
506{
507 bool exists = 1;
508 char *return_value;
509
510 return_value = zend_ini_string_ex(name, name_length, orig, &exists);
511 if (!exists) {
512 return NULL;
513 } else if (!return_value) {
514 return_value = "";
515 }
516 return return_value;
517}
518/* }}} */
519
520
521ZEND_API zend_string *zend_ini_str_ex(const char *name, size_t name_length, bool orig, bool *exists) /* {{{ */
522{
523 zend_ini_entry *ini_entry;
524
525 ini_entry = zend_hash_str_find_ptr(EG(ini_directives), name, name_length);
526 if (ini_entry) {
527 if (exists) {
528 *exists = 1;
529 }
530
531 if (orig && ini_entry->modified) {
532 return ini_entry->orig_value ? ini_entry->orig_value : NULL;
533 } else {
534 return ini_entry->value ? ini_entry->value : NULL;
535 }
536 } else {
537 if (exists) {
538 *exists = 0;
539 }
540 return NULL;
541 }
542}
543/* }}} */
544
545ZEND_API zend_string *zend_ini_str(const char *name, size_t name_length, bool orig) /* {{{ */
546{
547 bool exists = 1;
549
550 return_value = zend_ini_str_ex(name, name_length, orig, &exists);
551 if (!exists) {
552 return NULL;
553 } else if (!return_value) {
555 }
556 return return_value;
557}
558/* }}} */
559
561{
562 zend_ini_entry *ini_entry;
563
564 ini_entry = zend_hash_find_ptr(EG(ini_directives), name);
565 if (ini_entry) {
566 return ini_entry->value ? ini_entry->value : ZSTR_EMPTY_ALLOC();
567 } else {
568 return NULL;
569 }
570}
571/* }}} */
572
574{
575 if (zend_string_equals_literal_ci(str, "true")
576 || zend_string_equals_literal_ci(str, "yes")
578 ) {
579 return 1;
580 } else {
581 return atoi(ZSTR_VAL(str)) != 0;
582 }
583}
584
589
590static const char *zend_ini_consume_quantity_prefix(const char *const digits, const char *const str_end, int base) {
591 const char *digits_consumed = digits;
592 /* Ignore leading whitespace. */
593 while (digits_consumed < str_end && zend_is_whitespace(*digits_consumed)) {++digits_consumed;}
594 if (digits_consumed[0] == '+' || digits_consumed[0] == '-') {
595 ++digits_consumed;
596 }
597
598 if (digits_consumed[0] == '0' && !isdigit(digits_consumed[1])) {
599 /* Value is just 0 */
600 if ((digits_consumed+1) == str_end) {
601 return digits_consumed;
602 }
603
604 switch (digits_consumed[1]) {
605 case 'x':
606 case 'X':
607 case 'o':
608 case 'O':
609 digits_consumed += 2;
610 break;
611 case 'b':
612 case 'B':
613 if (base != 16) {
614 /* 0b or 0B is valid in base 16, but not in the other supported bases. */
615 digits_consumed += 2;
616 }
617 break;
618 }
619 }
620 return digits_consumed;
621}
622
623static zend_ulong zend_ini_parse_quantity_internal(zend_string *value, zend_ini_parse_quantity_signed_result_t signed_result, zend_string **errstr) /* {{{ */
624{
625 char *digits_end = NULL;
626 char *str = ZSTR_VAL(value);
627 char *str_end = &str[ZSTR_LEN(value)];
628 char *digits = str;
629 bool overflow = false;
630 zend_ulong factor;
631 smart_str invalid = {0};
632 smart_str interpreted = {0};
633 smart_str chr = {0};
634
635 /* Ignore leading whitespace. ZEND_STRTOL() also skips leading whitespaces,
636 * but we need the position of the first non-whitespace later. */
637 while (digits < str_end && zend_is_whitespace(*digits)) {++digits;}
638
639 /* Ignore trailing whitespace */
640 while (digits < str_end && zend_is_whitespace(*(str_end-1))) {--str_end;}
641
642 if (digits == str_end) {
643 *errstr = NULL;
644 return 0;
645 }
646
647 bool is_negative = false;
648 if (digits[0] == '+') {
649 ++digits;
650 } else if (digits[0] == '-') {
651 is_negative = true;
652 ++digits;
653 }
654
655 /* if there is no digit after +/- */
656 if (!isdigit(digits[0])) {
657 /* Escape the string to avoid null bytes and to make non-printable chars
658 * visible */
660 smart_str_0(&invalid);
661
662 *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": no valid leading digits, interpreting as \"0\" for backwards compatibility",
663 ZSTR_VAL(invalid.s));
664
665 smart_str_free(&invalid);
666 return 0;
667 }
668
669 int base = 0;
670 if (digits[0] == '0' && !isdigit(digits[1])) {
671 /* Value is just 0 */
672 if ((digits+1) == str_end) {
673 *errstr = NULL;
674 return 0;
675 }
676
677 switch (digits[1]) {
678 /* Multiplier suffixes */
679 case 'g':
680 case 'G':
681 case 'm':
682 case 'M':
683 case 'k':
684 case 'K':
685 goto evaluation;
686 case 'x':
687 case 'X':
688 base = 16;
689 break;
690 case 'o':
691 case 'O':
692 base = 8;
693 break;
694 case 'b':
695 case 'B':
696 base = 2;
697 break;
698 default:
699 *errstr = zend_strpprintf(0, "Invalid prefix \"0%c\", interpreting as \"0\" for backwards compatibility",
700 digits[1]);
701 return 0;
702 }
703 digits += 2;
704 /* STRTOULL may silently ignore a prefix of whitespace, sign, and base prefix, which would be invalid at this position */
705 if (UNEXPECTED(digits == str_end || digits != zend_ini_consume_quantity_prefix(digits, str_end, base))) {
706 /* Escape the string to avoid null bytes and to make non-printable chars
707 * visible */
709 smart_str_0(&invalid);
710
711 *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": no digits after base prefix, interpreting as \"0\" for backwards compatibility",
712 ZSTR_VAL(invalid.s));
713
714 smart_str_free(&invalid);
715 return 0;
716 }
717 }
718 evaluation:
719
720 errno = 0;
721 zend_ulong retval = ZEND_STRTOUL(digits, &digits_end, base);
722
723 if (errno == ERANGE) {
724 overflow = true;
725 } else if (signed_result == ZEND_INI_PARSE_QUANTITY_UNSIGNED) {
726 if (is_negative) {
727 /* Ignore "-1" as it is commonly used as max value, for instance in memory_limit=-1. */
728 if (retval == 1 && digits_end == str_end) {
729 retval = -1;
730 } else {
731 overflow = true;
732 }
733 }
734 } else if (signed_result == ZEND_INI_PARSE_QUANTITY_SIGNED) {
735 /* Handle PHP_INT_MIN case */
736 if (is_negative && retval == ((zend_ulong)ZEND_LONG_MAX +1)) {
737 retval = 0u - retval;
738 } else if ((zend_long) retval < 0) {
739 overflow = true;
740 } else if (is_negative) {
741 retval = 0u - retval;
742 }
743 }
744
745 if (UNEXPECTED(digits_end == digits)) {
746 /* No leading digits */
747
748 /* Escape the string to avoid null bytes and to make non-printable chars
749 * visible */
751 smart_str_0(&invalid);
752
753 *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": no valid leading digits, interpreting as \"0\" for backwards compatibility",
754 ZSTR_VAL(invalid.s));
755
756 smart_str_free(&invalid);
757 return 0;
758 }
759
760 /* Allow for whitespace between integer portion and any suffix character */
761 while (digits_end < str_end && zend_is_whitespace(*digits_end)) ++digits_end;
762
763 /* No exponent suffix. */
764 if (digits_end == str_end) {
765 goto end;
766 }
767
768 switch (*(str_end-1)) {
769 case 'g':
770 case 'G':
771 factor = 1<<30;
772 break;
773 case 'm':
774 case 'M':
775 factor = 1<<20;
776 break;
777 case 'k':
778 case 'K':
779 factor = 1<<10;
780 break;
781 default:
782 /* Unknown suffix */
784 smart_str_0(&invalid);
785 smart_str_append_escaped(&interpreted, str, digits_end - str);
786 smart_str_0(&interpreted);
787 smart_str_append_escaped(&chr, str_end-1, 1);
788 smart_str_0(&chr);
789
790 *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": unknown multiplier \"%s\", interpreting as \"%s\" for backwards compatibility",
791 ZSTR_VAL(invalid.s), ZSTR_VAL(chr.s), ZSTR_VAL(interpreted.s));
792
793 smart_str_free(&invalid);
794 smart_str_free(&interpreted);
795 smart_str_free(&chr);
796
797 return retval;
798 }
799
800 if (!overflow) {
801 if (signed_result == ZEND_INI_PARSE_QUANTITY_SIGNED) {
802 zend_long sretval = (zend_long)retval;
803 if (sretval > 0) {
804 overflow = (zend_long)retval > ZEND_LONG_MAX / (zend_long)factor;
805 } else {
806 overflow = (zend_long)retval < ZEND_LONG_MIN / (zend_long)factor;
807 }
808 } else {
809 overflow = retval > ZEND_ULONG_MAX / factor;
810 }
811 }
812
813 retval *= factor;
814
815 if (UNEXPECTED(digits_end != str_end-1)) {
816 /* More than one character in suffix */
818 smart_str_0(&invalid);
819 smart_str_append_escaped(&interpreted, str, digits_end - str);
820 smart_str_0(&interpreted);
821 smart_str_append_escaped(&chr, str_end-1, 1);
822 smart_str_0(&chr);
823
824 *errstr = zend_strpprintf(0, "Invalid quantity \"%s\", interpreting as \"%s%s\" for backwards compatibility",
825 ZSTR_VAL(invalid.s), ZSTR_VAL(interpreted.s), ZSTR_VAL(chr.s));
826
827 smart_str_free(&invalid);
828 smart_str_free(&interpreted);
829 smart_str_free(&chr);
830
831 return retval;
832 }
833
834end:
835 if (UNEXPECTED(overflow)) {
837 smart_str_0(&invalid);
838
839 /* Not specifying the resulting value here because the caller may make
840 * additional conversions. Not specifying the allowed range
841 * because the caller may do narrower range checks. */
842 *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": value is out of range, using overflow result for backwards compatibility",
843 ZSTR_VAL(invalid.s));
844
845 smart_str_free(&invalid);
846 smart_str_free(&interpreted);
847 smart_str_free(&chr);
848
849 return retval;
850 }
851
852 *errstr = NULL;
853 return retval;
854}
855/* }}} */
856
858{
859 return (zend_long) zend_ini_parse_quantity_internal(value, ZEND_INI_PARSE_QUANTITY_SIGNED, errstr);
860}
861/* }}} */
862
864{
865 return zend_ini_parse_quantity_internal(value, ZEND_INI_PARSE_QUANTITY_UNSIGNED, errstr);
866}
867/* }}} */
868
870{
871 zend_string *errstr;
873
874 if (errstr) {
875 zend_error(E_WARNING, "Invalid \"%s\" setting. %s", ZSTR_VAL(setting), ZSTR_VAL(errstr));
876 zend_string_release(errstr);
877 }
878
879 return retval;
880}
881/* }}} */
882
884{
885 zend_string *errstr;
887
888 if (errstr) {
889 zend_error(E_WARNING, "Invalid \"%s\" setting. %s", ZSTR_VAL(setting), ZSTR_VAL(errstr));
890 zend_string_release(errstr);
891 }
892
893 return retval;
894}
895/* }}} */
896
897ZEND_INI_DISP(zend_ini_boolean_displayer_cb) /* {{{ */
898{
899 int value;
901
902 if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) {
903 tmp_value = (ini_entry->orig_value ? ini_entry->orig_value : NULL );
904 } else if (ini_entry->value) {
905 tmp_value = ini_entry->value;
906 } else {
907 tmp_value = NULL;
908 }
909
912 } else {
913 value = 0;
914 }
915
916 if (value) {
917 ZEND_PUTS("On");
918 } else {
919 ZEND_PUTS("Off");
920 }
921}
922/* }}} */
923
924ZEND_INI_DISP(zend_ini_color_displayer_cb) /* {{{ */
925{
926 char *value;
927
928 if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) {
929 value = ZSTR_VAL(ini_entry->orig_value);
930 } else if (ini_entry->value) {
931 value = ZSTR_VAL(ini_entry->value);
932 } else {
933 value = NULL;
934 }
935 if (value) {
936 if (zend_uv.html_errors) {
937 zend_printf("<span style=\"color: %s\">%s</span>", value, value);
938 } else {
940 }
941 } else {
942 if (zend_uv.html_errors) {
944 } else {
946 }
947 }
948}
949/* }}} */
950
951ZEND_INI_DISP(display_link_numbers) /* {{{ */
952{
953 char *value;
954
955 if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) {
956 value = ZSTR_VAL(ini_entry->orig_value);
957 } else if (ini_entry->value) {
958 value = ZSTR_VAL(ini_entry->value);
959 } else {
960 value = NULL;
961 }
962
963 if (value) {
964 if (atoi(value) == -1) {
965 ZEND_PUTS("Unlimited");
966 } else {
967 zend_printf("%s", value);
968 }
969 }
970}
971/* }}} */
972
973/* Standard message handlers */
974ZEND_API ZEND_INI_MH(OnUpdateBool) /* {{{ */
975{
976 bool *p = (bool *) ZEND_INI_GET_ADDR();
977 *p = zend_ini_parse_bool(new_value);
978 return SUCCESS;
979}
980/* }}} */
981
982ZEND_API ZEND_INI_MH(OnUpdateLong) /* {{{ */
983{
985 *p = zend_ini_parse_quantity_warn(new_value, entry->name);
986 return SUCCESS;
987}
988/* }}} */
989
990ZEND_API ZEND_INI_MH(OnUpdateLongGEZero) /* {{{ */
991{
992 zend_long tmp = zend_ini_parse_quantity_warn(new_value, entry->name);
993 if (tmp < 0) {
994 return FAILURE;
995 }
996
998 *p = tmp;
999
1000 return SUCCESS;
1001}
1002/* }}} */
1003
1004ZEND_API ZEND_INI_MH(OnUpdateReal) /* {{{ */
1005{
1006 double *p = (double *) ZEND_INI_GET_ADDR();
1007 *p = zend_strtod(ZSTR_VAL(new_value), NULL);
1008 return SUCCESS;
1009}
1010/* }}} */
1011
1012ZEND_API ZEND_INI_MH(OnUpdateString) /* {{{ */
1013{
1014 char **p = (char **) ZEND_INI_GET_ADDR();
1015 *p = new_value ? ZSTR_VAL(new_value) : NULL;
1016 return SUCCESS;
1017}
1018/* }}} */
1019
1020ZEND_API ZEND_INI_MH(OnUpdateStringUnempty) /* {{{ */
1021{
1022 if (new_value && !ZSTR_VAL(new_value)[0]) {
1023 return FAILURE;
1024 }
1025
1026 char **p = (char **) ZEND_INI_GET_ADDR();
1027 *p = new_value ? ZSTR_VAL(new_value) : NULL;
1028 return SUCCESS;
1029}
1030/* }}} */
1031
1032ZEND_API ZEND_INI_MH(OnUpdateStr) /* {{{ */
1033{
1035 *p = new_value;
1036 return SUCCESS;
1037}
1038/* }}} */
1039
1040ZEND_API ZEND_INI_MH(OnUpdateStrNotEmpty) /* {{{ */
1041{
1042 if (new_value && ZSTR_LEN(new_value) == 0) {
1043 return FAILURE;
1044 }
1045
1047 *p = new_value;
1048 return SUCCESS;
1049}
1050/* }}} */
chr(int $codepoint)
char s[4]
Definition cdf.c:77
uint32_t u
Definition cdf.c:78
zend_ffi_type * type
Definition ffi.c:3812
zval * zv
Definition ffi.c:3975
memcpy(ptr1, ptr2, size)
zval * arg
Definition ffi.c:3975
#define NULL
Definition gdcache.h:45
#define SUCCESS
Definition hash_sha3.c:261
unsigned const char * end
Definition php_ffi.h:51
p
Definition session.c:1105
zend_ulong h
Definition zend_types.h:382
zend_string * key
Definition zend_types.h:383
uint8_t modifiable
Definition zend_ini.h:44
void(* displayer)(zend_ini_entry *ini_entry, int type)
Definition zend_ini.h:40
uint16_t name_length
Definition zend_ini.h:43
const char * value
Definition zend_ini.h:39
void * mh_arg1
Definition zend_ini.h:36
void * mh_arg2
Definition zend_ini.h:37
const char * name
Definition zend_ini.h:34
void * mh_arg3
Definition zend_ini.h:38
uint32_t value_length
Definition zend_ini.h:42
zend_string * value
Definition zend_ini.h:53
uint8_t modifiable
Definition zend_ini.h:59
zend_string * orig_value
Definition zend_ini.h:54
uint8_t orig_modifiable
Definition zend_ini.h:60
void * mh_arg3
Definition zend_ini.h:52
void(* displayer)(zend_ini_entry *ini_entry, int type)
Definition zend_ini.h:55
int module_number
Definition zend_ini.h:57
void * mh_arg2
Definition zend_ini.h:51
void * mh_arg1
Definition zend_ini.h:50
zend_string * name
Definition zend_ini.h:48
uint8_t modified
Definition zend_ini.h:61
zend_string * s
#define errno
ZEND_API zval * zend_get_configuration_directive(zend_string *name)
Definition zend.c:1401
ZEND_API zend_utility_values zend_uv
Definition zend.c:73
ZEND_API zend_string * zend_strpprintf(size_t max_len, const char *format,...)
Definition zend.c:353
ZEND_API ZEND_COLD void zend_error(int type, const char *format,...)
Definition zend.c:1666
ZEND_API size_t(* zend_printf)(const char *format,...)
Definition zend.c:84
#define ZEND_PUTS(str)
Definition zend.h:335
#define zend_try
Definition zend.h:270
#define zend_end_try()
Definition zend.h:280
ZEND_API HashTable module_registry
Definition zend_API.c:41
#define pefree(ptr, persistent)
Definition zend_alloc.h:191
#define pemalloc(size, persistent)
Definition zend_alloc.h:189
#define FREE_HASHTABLE(ht)
Definition zend_alloc.h:234
#define ALLOC_HASHTABLE(ht)
Definition zend_alloc.h:231
struct _zval_struct zval
zend_string_release_ex(func->internal_function.function_name, 0)
#define ZEND_API
#define E_WARNING
Definition zend_errors.h:24
struct _zend_ini_entry zend_ini_entry
#define EG(v)
ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht)
Definition zend_hash.c:1727
ZEND_API void ZEND_FASTCALL zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t apply_func, void *argument)
Definition zend_hash.c:2099
ZEND_API void ZEND_FASTCALL zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor)
Definition zend_hash.c:2240
ZEND_API zend_result ZEND_FASTCALL zend_hash_del(HashTable *ht, zend_string *key)
Definition zend_hash.c:1534
#define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent)
Definition zend_hash.h:108
#define ZEND_HASH_MAP_FOREACH_PTR(ht, _ptr)
Definition zend_hash.h:1326
#define ZEND_HASH_REVERSE_FOREACH_PTR(ht, _ptr)
Definition zend_hash.h:1126
#define ZEND_HASH_FOREACH_END()
Definition zend_hash.h:1086
zend_string * tmp_value
Definition zend_ini.c:900
ZEND_API zend_result zend_alter_ini_entry_ex(zend_string *name, zend_string *new_value, int modify_type, int stage, bool force_change)
Definition zend_ini.c:356
ZEND_API zend_ulong zend_ini_parse_uquantity(zend_string *value, zend_string **errstr)
Definition zend_ini.c:863
ZEND_API void zend_ini_dtor(HashTable *ini_directives)
Definition zend_ini.c:116
ZEND_API zend_result zend_alter_ini_entry_chars(zend_string *name, const char *value, size_t value_length, int modify_type, int stage)
Definition zend_ini.c:332
ZEND_API zend_string * zend_ini_get_value(zend_string *name)
Definition zend_ini.c:560
#define NO_VALUE_HTML
Definition zend_ini.c:33
ZEND_API void zend_ini_deactivate(void)
Definition zend_ini.c:130
ZEND_API zend_ulong zend_ini_parse_uquantity_warn(zend_string *value, zend_string *setting)
Definition zend_ini.c:883
ZEND_API zend_result zend_register_ini_entries(const zend_ini_entry_def *ini_entry, int module_number)
Definition zend_ini.c:268
ZEND_API zend_result zend_restore_ini_entry(zend_string *name, int stage)
Definition zend_ini.c:408
ZEND_API zend_string * zend_ini_str_ex(const char *name, size_t name_length, bool orig, bool *exists)
Definition zend_ini.c:521
ZEND_API char * zend_ini_string_ex(const char *name, size_t name_length, int orig, bool *exists)
Definition zend_ini.c:481
ZEND_API void zend_unregister_ini_entries_ex(int module_number, int module_type)
Definition zend_ini.c:283
ZEND_API zend_result zend_ini_register_displayer(const char *name, uint32_t name_length, void(*displayer)(zend_ini_entry *ini_entry, int type))
Definition zend_ini.c:429
ZEND_API bool zend_ini_parse_bool(zend_string *str)
Definition zend_ini.c:573
ZEND_API zend_result zend_register_ini_entries_ex(const zend_ini_entry_def *ini_entry, int module_number, int module_type)
Definition zend_ini.c:204
ZEND_API zend_long zend_ini_parse_quantity_warn(zend_string *value, zend_string *setting)
Definition zend_ini.c:869
ZEND_API char * zend_ini_string(const char *name, size_t name_length, int orig)
Definition zend_ini.c:505
ZEND_API zend_long zend_ini_long(const char *name, size_t name_length, int orig)
Definition zend_ini.c:447
ZEND_API zend_result zend_alter_ini_entry(zend_string *name, zend_string *new_value, int modify_type, int stage)
Definition zend_ini.c:325
ZEND_API zend_long zend_ini_parse_quantity(zend_string *value, zend_string **errstr)
Definition zend_ini.c:857
ZEND_API void zend_ini_shutdown(void)
Definition zend_ini.c:110
ZEND_API zend_result zend_alter_ini_entry_chars_ex(zend_string *name, const char *value, size_t value_length, int modify_type, int stage, int force_change)
Definition zend_ini.c:344
ZEND_API zend_string * zend_ini_str(const char *name, size_t name_length, bool orig)
Definition zend_ini.c:545
ZEND_API void zend_unregister_ini_entries(int module_number)
Definition zend_ini.c:297
ZEND_API void zend_ini_sort_entries(void)
Definition zend_ini.c:195
ZEND_API void zend_ini_global_shutdown(void)
Definition zend_ini.c:123
zend_ini_parse_quantity_signed_result_t
Definition zend_ini.c:585
@ ZEND_INI_PARSE_QUANTITY_SIGNED
Definition zend_ini.c:586
@ ZEND_INI_PARSE_QUANTITY_UNSIGNED
Definition zend_ini.c:587
ZEND_API double zend_ini_double(const char *name, size_t name_length, int orig)
Definition zend_ini.c:464
ZEND_API void zend_ini_startup(void)
Definition zend_ini.c:99
#define NO_VALUE_PLAINTEXT
Definition zend_ini.c:32
#define ZEND_INI_STAGE_ACTIVATE
Definition zend_ini.h:229
ZEND_API void zend_ini_refresh_caches(int stage)
struct _zend_ini_entry_def zend_ini_entry_def
#define ZEND_INI_SYSTEM
Definition zend_ini.h:26
ZEND_API void zend_copy_ini_directives(void)
#define ZEND_INI_STAGE_STARTUP
Definition zend_ini.h:227
#define ZEND_INI_DISPLAY_ORIG
Definition zend_ini.h:224
#define ZEND_INI_MH(name)
Definition zend_ini.h:30
#define ZEND_INI_DISP(name)
Definition zend_ini.h:31
#define ZEND_INI_STAGE_IN_REQUEST
Definition zend_ini.h:234
#define ZEND_INI_STAGE_DEACTIVATE
Definition zend_ini.h:230
#define ZEND_INI_GET_ADDR()
Definition zend_ini.h:259
#define ZEND_INI_STAGE_RUNTIME
Definition zend_ini.h:231
#define ZEND_INI_USER
Definition zend_ini.h:24
int32_t zend_long
Definition zend_long.h:42
#define ZEND_LONG_MIN
Definition zend_long.h:46
uint32_t zend_ulong
Definition zend_long.h:43
#define ZEND_ULONG_MAX
Definition zend_long.h:47
#define ZEND_STRTOL(s0, s1, base)
Definition zend_long.h:85
#define ZEND_STRTOUL(s0, s1, base)
Definition zend_long.h:86
#define ZEND_LONG_MAX
Definition zend_long.h:45
struct _zend_string zend_string
#define MODULE_TEMPORARY
struct _zend_module_entry zend_module_entry
#define MODULE_PERSISTENT
ZEND_API int ZEND_FASTCALL zend_binary_strcasecmp(const char *s1, size_t len1, const char *s2, size_t len2)
#define ZEND_ASSERT(c)
#define UNEXPECTED(condition)
ZEND_API void ZEND_FASTCALL smart_str_append_escaped(smart_str *str, const char *s, size_t l)
ZEND_API zend_string_init_interned_func_t zend_string_init_interned
Definition zend_string.c:31
ZEND_API zend_new_interned_string_func_t zend_new_interned_string
Definition zend_string.c:30
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_EMPTY_ALLOC()
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
#define zend_string_equals_literal_ci(str, c)
ZEND_API double zend_strtod(const char *s00, const char **se)
struct _zend_array HashTable
Definition zend_types.h:386
#define Z_STR_P(zval_p)
Definition zend_types.h:972
#define Z_PTR_P(zval_p)
@ FAILURE
Definition zend_types.h:61
struct _Bucket Bucket
ZEND_RESULT_CODE zend_result
Definition zend_types.h:64
zval retval
zval * return_value
zend_string * name
bool result
zval * ret
value