1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Andi Gutmans <andi@php.net> |
14 | Rasmus Lerdorf <rasmus@lerdorf.on.ca> |
15 | Zeev Suraski <zeev@php.net> |
16 +----------------------------------------------------------------------+
17 */
18
19 /* {{{ includes */
20
21 #define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
22
23 #include "php.h"
24 #include <stdio.h>
25 #include <fcntl.h>
26 #ifdef PHP_WIN32
27 #include "win32/time.h"
28 #include "win32/signal.h"
29 #include "win32/php_win32_globals.h"
30 #include "win32/winutil.h"
31 #include <process.h>
32 #endif
33 #if HAVE_SYS_TIME_H
34 #include <sys/time.h>
35 #endif
36 #if HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39
40 #include <signal.h>
41 #include <locale.h>
42 #include "zend.h"
43 #include "zend_types.h"
44 #include "zend_extensions.h"
45 #include "php_ini.h"
46 #include "php_globals.h"
47 #include "php_main.h"
48 #include "php_syslog.h"
49 #include "fopen_wrappers.h"
50 #include "ext/standard/php_standard.h"
51 #include "ext/date/php_date.h"
52 #include "php_variables.h"
53 #include "ext/standard/credits.h"
54 #ifdef PHP_WIN32
55 #include <io.h>
56 #include "win32/php_registry.h"
57 #include "ext/standard/flock_compat.h"
58 #endif
59 #include "php_syslog.h"
60 #include "Zend/zend_exceptions.h"
61
62 #if PHP_SIGCHILD
63 #include <sys/types.h>
64 #include <sys/wait.h>
65 #endif
66
67 #include "zend_compile.h"
68 #include "zend_execute.h"
69 #include "zend_highlight.h"
70 #include "zend_extensions.h"
71 #include "zend_ini.h"
72 #include "zend_dtrace.h"
73 #include "zend_observer.h"
74 #include "zend_system_id.h"
75
76 #include "php_content_types.h"
77 #include "php_ticks.h"
78 #include "php_streams.h"
79 #include "php_open_temporary_file.h"
80
81 #include "SAPI.h"
82 #include "rfc1867.h"
83
84 #include "ext/standard/html_tables.h"
85 #include "main_arginfo.h"
86 /* }}} */
87
88 PHPAPI int (*php_register_internal_extensions_func)(void) = php_register_internal_extensions;
89
90 #ifndef ZTS
91 php_core_globals core_globals;
92 #else
93 PHPAPI int core_globals_id;
94 PHPAPI size_t core_globals_offset;
95 #endif
96
97 #define SAFE_FILENAME(f) ((f)?(f):"-")
98
php_version(void)99 PHPAPI const char *php_version(void)
100 {
101 return PHP_VERSION;
102 }
103
php_version_id(void)104 PHPAPI unsigned int php_version_id(void)
105 {
106 return PHP_VERSION_ID;
107 }
108
109 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnSetFacility)110 static PHP_INI_MH(OnSetFacility)
111 {
112 const zend_string *facility = new_value;
113
114 #ifdef LOG_AUTH
115 if (zend_string_equals_literal(facility, "LOG_AUTH") || zend_string_equals_literal(facility, "auth")
116 || zend_string_equals_literal(facility, "security")) {
117 PG(syslog_facility) = LOG_AUTH;
118 return SUCCESS;
119 }
120 #endif
121 #ifdef LOG_AUTHPRIV
122 if (zend_string_equals_literal(facility, "LOG_AUTHPRIV") || zend_string_equals_literal(facility, "authpriv")) {
123 PG(syslog_facility) = LOG_AUTHPRIV;
124 return SUCCESS;
125 }
126 #endif
127 #ifdef LOG_CRON
128 if (zend_string_equals_literal(facility, "LOG_CRON") || zend_string_equals_literal(facility, "cron")) {
129 PG(syslog_facility) = LOG_CRON;
130 return SUCCESS;
131 }
132 #endif
133 #ifdef LOG_DAEMON
134 if (zend_string_equals_literal(facility, "LOG_DAEMON") || zend_string_equals_literal(facility, "daemon")) {
135 PG(syslog_facility) = LOG_DAEMON;
136 return SUCCESS;
137 }
138 #endif
139 #ifdef LOG_FTP
140 if (zend_string_equals_literal(facility, "LOG_FTP") || zend_string_equals_literal(facility, "ftp")) {
141 PG(syslog_facility) = LOG_FTP;
142 return SUCCESS;
143 }
144 #endif
145 #ifdef LOG_KERN
146 if (zend_string_equals_literal(facility, "LOG_KERN") || zend_string_equals_literal(facility, "kern")) {
147 PG(syslog_facility) = LOG_KERN;
148 return SUCCESS;
149 }
150 #endif
151 #ifdef LOG_LPR
152 if (zend_string_equals_literal(facility, "LOG_LPR") || zend_string_equals_literal(facility, "lpr")) {
153 PG(syslog_facility) = LOG_LPR;
154 return SUCCESS;
155 }
156 #endif
157 #ifdef LOG_MAIL
158 if (zend_string_equals_literal(facility, "LOG_MAIL") || zend_string_equals_literal(facility, "mail")) {
159 PG(syslog_facility) = LOG_MAIL;
160 return SUCCESS;
161 }
162 #endif
163 #ifdef LOG_INTERNAL_MARK
164 if (zend_string_equals_literal(facility, "LOG_INTERNAL_MARK") || zend_string_equals_literal(facility, "mark")) {
165 PG(syslog_facility) = LOG_INTERNAL_MARK;
166 return SUCCESS;
167 }
168 #endif
169 #ifdef LOG_NEWS
170 if (zend_string_equals_literal(facility, "LOG_NEWS") || zend_string_equals_literal(facility, "news")) {
171 PG(syslog_facility) = LOG_NEWS;
172 return SUCCESS;
173 }
174 #endif
175 #ifdef LOG_SYSLOG
176 if (zend_string_equals_literal(facility, "LOG_SYSLOG") || zend_string_equals_literal(facility, "syslog")) {
177 PG(syslog_facility) = LOG_SYSLOG;
178 return SUCCESS;
179 }
180 #endif
181 #ifdef LOG_USER
182 if (zend_string_equals(facility, ZSTR_KNOWN(ZEND_STR_USER)) || zend_string_equals_literal(facility, "LOG_USER")) {
183 PG(syslog_facility) = LOG_USER;
184 return SUCCESS;
185 }
186 #endif
187 #ifdef LOG_UUCP
188 if (zend_string_equals_literal(facility, "LOG_UUCP") || zend_string_equals_literal(facility, "uucp")) {
189 PG(syslog_facility) = LOG_UUCP;
190 return SUCCESS;
191 }
192 #endif
193 #ifdef LOG_LOCAL0
194 if (zend_string_equals_literal(facility, "LOG_LOCAL0") || zend_string_equals_literal(facility, "local0")) {
195 PG(syslog_facility) = LOG_LOCAL0;
196 return SUCCESS;
197 }
198 #endif
199 #ifdef LOG_LOCAL1
200 if (zend_string_equals_literal(facility, "LOG_LOCAL1") || zend_string_equals_literal(facility, "local1")) {
201 PG(syslog_facility) = LOG_LOCAL1;
202 return SUCCESS;
203 }
204 #endif
205 #ifdef LOG_LOCAL2
206 if (zend_string_equals_literal(facility, "LOG_LOCAL2") || zend_string_equals_literal(facility, "local2")) {
207 PG(syslog_facility) = LOG_LOCAL2;
208 return SUCCESS;
209 }
210 #endif
211 #ifdef LOG_LOCAL3
212 if (zend_string_equals_literal(facility, "LOG_LOCAL3") || zend_string_equals_literal(facility, "local3")) {
213 PG(syslog_facility) = LOG_LOCAL3;
214 return SUCCESS;
215 }
216 #endif
217 #ifdef LOG_LOCAL4
218 if (zend_string_equals_literal(facility, "LOG_LOCAL4") || zend_string_equals_literal(facility, "local4")) {
219 PG(syslog_facility) = LOG_LOCAL4;
220 return SUCCESS;
221 }
222 #endif
223 #ifdef LOG_LOCAL5
224 if (zend_string_equals_literal(facility, "LOG_LOCAL5") || zend_string_equals_literal(facility, "local5")) {
225 PG(syslog_facility) = LOG_LOCAL5;
226 return SUCCESS;
227 }
228 #endif
229 #ifdef LOG_LOCAL6
230 if (zend_string_equals_literal(facility, "LOG_LOCAL6") || zend_string_equals_literal(facility, "local6")) {
231 PG(syslog_facility) = LOG_LOCAL6;
232 return SUCCESS;
233 }
234 #endif
235 #ifdef LOG_LOCAL7
236 if (zend_string_equals_literal(facility, "LOG_LOCAL7") || zend_string_equals_literal(facility, "local7")) {
237 PG(syslog_facility) = LOG_LOCAL7;
238 return SUCCESS;
239 }
240 #endif
241
242 return FAILURE;
243 }
244 /* }}} */
245
246 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnSetPrecision)247 static PHP_INI_MH(OnSetPrecision)
248 {
249 zend_long i = ZEND_ATOL(ZSTR_VAL(new_value));
250 if (i >= -1) {
251 EG(precision) = i;
252 return SUCCESS;
253 } else {
254 return FAILURE;
255 }
256 }
257 /* }}} */
258
259 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnSetSerializePrecision)260 static PHP_INI_MH(OnSetSerializePrecision)
261 {
262 zend_long i = ZEND_ATOL(ZSTR_VAL(new_value));
263 if (i >= -1) {
264 PG(serialize_precision) = i;
265 return SUCCESS;
266 } else {
267 return FAILURE;
268 }
269 }
270 /* }}} */
271
272 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnChangeMemoryLimit)273 static PHP_INI_MH(OnChangeMemoryLimit)
274 {
275 size_t value;
276 if (new_value) {
277 value = zend_ini_parse_uquantity_warn(new_value, entry->name);
278 } else {
279 value = Z_L(1)<<30; /* effectively, no limit */
280 }
281 if (zend_set_memory_limit(value) == FAILURE) {
282 /* When the memory limit is reset to the original level during deactivation, we may be
283 * using more memory than the original limit while shutdown is still in progress.
284 * Ignore a failure for now, and set the memory limit when the memory manager has been
285 * shut down and the minimal amount of memory is used. */
286 if (stage != ZEND_INI_STAGE_DEACTIVATE) {
287 zend_error(E_WARNING, "Failed to set memory limit to %zd bytes (Current memory usage is %zd bytes)", value, zend_memory_usage(true));
288 return FAILURE;
289 }
290 }
291 PG(memory_limit) = value;
292 return SUCCESS;
293 }
294 /* }}} */
295
296 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnSetLogFilter)297 static PHP_INI_MH(OnSetLogFilter)
298 {
299 const zend_string *filter = new_value;
300
301 if (zend_string_equals_literal(filter, "all")) {
302 PG(syslog_filter) = PHP_SYSLOG_FILTER_ALL;
303 return SUCCESS;
304 }
305 if (zend_string_equals_literal(filter, "no-ctrl")) {
306 PG(syslog_filter) = PHP_SYSLOG_FILTER_NO_CTRL;
307 return SUCCESS;
308 }
309 if (zend_string_equals_literal(filter, "ascii")) {
310 PG(syslog_filter) = PHP_SYSLOG_FILTER_ASCII;
311 return SUCCESS;
312 }
313 if (zend_string_equals_literal(filter, "raw")) {
314 PG(syslog_filter) = PHP_SYSLOG_FILTER_RAW;
315 return SUCCESS;
316 }
317
318 return FAILURE;
319 }
320 /* }}} */
321
322 /* {{{ php_disable_classes */
php_disable_classes(void)323 static void php_disable_classes(void)
324 {
325 char *s = NULL, *e;
326
327 if (!*(INI_STR("disable_classes"))) {
328 return;
329 }
330
331 e = PG(disable_classes) = strdup(INI_STR("disable_classes"));
332
333 while (*e) {
334 switch (*e) {
335 case ' ':
336 case ',':
337 if (s) {
338 *e = '\0';
339 zend_disable_class(s, e-s);
340 s = NULL;
341 }
342 break;
343 default:
344 if (!s) {
345 s = e;
346 }
347 break;
348 }
349 e++;
350 }
351 if (s) {
352 zend_disable_class(s, e-s);
353 }
354 }
355 /* }}} */
356
357 /* {{{ php_binary_init */
php_binary_init(void)358 static void php_binary_init(void)
359 {
360 char *binary_location = NULL;
361 #ifdef PHP_WIN32
362 binary_location = (char *)pemalloc(MAXPATHLEN, 1);
363 if (GetModuleFileName(0, binary_location, MAXPATHLEN) == 0) {
364 pefree(binary_location, 1);
365 binary_location = NULL;
366 }
367 #else
368 if (sapi_module.executable_location) {
369 binary_location = (char *)pemalloc(MAXPATHLEN, 1);
370 if (!strchr(sapi_module.executable_location, '/')) {
371 char *envpath, *path;
372 bool found = false;
373
374 if ((envpath = getenv("PATH")) != NULL) {
375 char *search_dir, search_path[MAXPATHLEN];
376 char *last = NULL;
377 zend_stat_t s = {0};
378
379 path = estrdup(envpath);
380 search_dir = php_strtok_r(path, ":", &last);
381
382 while (search_dir) {
383 snprintf(search_path, MAXPATHLEN, "%s/%s", search_dir, sapi_module.executable_location);
384 if (VCWD_REALPATH(search_path, binary_location) && !VCWD_ACCESS(binary_location, X_OK) && VCWD_STAT(binary_location, &s) == 0 && S_ISREG(s.st_mode)) {
385 found = true;
386 break;
387 }
388 search_dir = php_strtok_r(NULL, ":", &last);
389 }
390 efree(path);
391 }
392 if (!found) {
393 pefree(binary_location, 1);
394 binary_location = NULL;
395 }
396 } else if (!VCWD_REALPATH(sapi_module.executable_location, binary_location) || VCWD_ACCESS(binary_location, X_OK)) {
397 pefree(binary_location, 1);
398 binary_location = NULL;
399 }
400 }
401 #endif
402 PG(php_binary) = binary_location;
403 }
404 /* }}} */
405
406 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateTimeout)407 static PHP_INI_MH(OnUpdateTimeout)
408 {
409 if (stage==PHP_INI_STAGE_STARTUP) {
410 /* Don't set a timeout on startup, only per-request */
411 EG(timeout_seconds) = ZEND_ATOL(ZSTR_VAL(new_value));
412 return SUCCESS;
413 }
414 zend_unset_timeout();
415 EG(timeout_seconds) = ZEND_ATOL(ZSTR_VAL(new_value));
416 if (stage != PHP_INI_STAGE_DEACTIVATE) {
417 /*
418 * If we're restoring INI values, we shouldn't reset the timer.
419 * Otherwise, the timer is active when PHP is idle, such as the
420 * CLI web server or CGI. Running a script will re-activate
421 * the timeout, so it's not needed to do so at script end.
422 */
423 zend_set_timeout(EG(timeout_seconds), 0);
424 }
425 return SUCCESS;
426 }
427 /* }}} */
428
429 /* {{{ php_get_display_errors_mode() helper function */
php_get_display_errors_mode(zend_string * value)430 static uint8_t php_get_display_errors_mode(zend_string *value)
431 {
432 if (!value) {
433 return PHP_DISPLAY_ERRORS_STDOUT;
434 }
435
436 if (zend_string_equals_literal_ci(value, "on")) {
437 return PHP_DISPLAY_ERRORS_STDOUT;
438 }
439 if (zend_string_equals_literal_ci(value, "yes")) {
440 return PHP_DISPLAY_ERRORS_STDOUT;
441 }
442
443 if (zend_string_equals_literal_ci(value, "true")) {
444 return PHP_DISPLAY_ERRORS_STDOUT;
445 }
446 if (zend_string_equals_literal_ci(value, "stderr")) {
447 return PHP_DISPLAY_ERRORS_STDERR;
448 }
449 if (zend_string_equals_literal_ci(value, "stdout")) {
450 return PHP_DISPLAY_ERRORS_STDOUT;
451 }
452
453 uint8_t mode = ZEND_ATOL(ZSTR_VAL(value));
454 if (mode && mode != PHP_DISPLAY_ERRORS_STDOUT && mode != PHP_DISPLAY_ERRORS_STDERR) {
455 return PHP_DISPLAY_ERRORS_STDOUT;
456 }
457
458 return mode;
459 }
460 /* }}} */
461
462 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateDisplayErrors)463 static PHP_INI_MH(OnUpdateDisplayErrors)
464 {
465 PG(display_errors) = php_get_display_errors_mode(new_value);
466
467 return SUCCESS;
468 }
469 /* }}} */
470
471 /* {{{ PHP_INI_DISP */
PHP_INI_DISP(display_errors_mode)472 static PHP_INI_DISP(display_errors_mode)
473 {
474 uint8_t mode;
475 bool cgi_or_cli;
476 zend_string *temporary_value;
477
478 if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) {
479 temporary_value = (ini_entry->orig_value ? ini_entry->orig_value : NULL );
480 } else if (ini_entry->value) {
481 temporary_value = ini_entry->value;
482 } else {
483 temporary_value = NULL;
484 }
485
486 mode = php_get_display_errors_mode(temporary_value);
487
488 /* Display 'On' for other SAPIs instead of STDOUT or STDERR */
489 cgi_or_cli = (!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg"));
490
491 switch (mode) {
492 case PHP_DISPLAY_ERRORS_STDERR:
493 if (cgi_or_cli ) {
494 PUTS("STDERR");
495 } else {
496 PUTS("On");
497 }
498 break;
499
500 case PHP_DISPLAY_ERRORS_STDOUT:
501 if (cgi_or_cli ) {
502 PUTS("STDOUT");
503 } else {
504 PUTS("On");
505 }
506 break;
507
508 default:
509 PUTS("Off");
510 break;
511 }
512 }
513 /* }}} */
514
php_get_internal_encoding(void)515 PHPAPI const char *php_get_internal_encoding(void) {
516 if (PG(internal_encoding) && PG(internal_encoding)[0]) {
517 return PG(internal_encoding);
518 } else if (SG(default_charset) && SG(default_charset)[0]) {
519 return SG(default_charset);
520 }
521 return "UTF-8";
522 }
523
php_get_input_encoding(void)524 PHPAPI const char *php_get_input_encoding(void) {
525 if (PG(input_encoding) && PG(input_encoding)[0]) {
526 return PG(input_encoding);
527 } else if (SG(default_charset) && SG(default_charset)[0]) {
528 return SG(default_charset);
529 }
530 return "UTF-8";
531 }
532
php_get_output_encoding(void)533 PHPAPI const char *php_get_output_encoding(void) {
534 if (PG(output_encoding) && PG(output_encoding)[0]) {
535 return PG(output_encoding);
536 } else if (SG(default_charset) && SG(default_charset)[0]) {
537 return SG(default_charset);
538 }
539 return "UTF-8";
540 }
541
542 PHPAPI void (*php_internal_encoding_changed)(void) = NULL;
543
544 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateDefaultCharset)545 static PHP_INI_MH(OnUpdateDefaultCharset)
546 {
547 if (memchr(ZSTR_VAL(new_value), '\0', ZSTR_LEN(new_value))
548 || strpbrk(ZSTR_VAL(new_value), "\r\n")) {
549 return FAILURE;
550 }
551 OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
552 if (php_internal_encoding_changed) {
553 php_internal_encoding_changed();
554 }
555 if (new_value) {
556 #ifdef PHP_WIN32
557 php_win32_cp_do_update(ZSTR_VAL(new_value));
558 #endif
559 }
560 return SUCCESS;
561 }
562 /* }}} */
563
564 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateDefaultMimeTye)565 static PHP_INI_MH(OnUpdateDefaultMimeTye)
566 {
567 if (memchr(ZSTR_VAL(new_value), '\0', ZSTR_LEN(new_value))
568 || strpbrk(ZSTR_VAL(new_value), "\r\n")) {
569 return FAILURE;
570 }
571 return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
572 }
573 /* }}} */
574
575 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateInternalEncoding)576 static PHP_INI_MH(OnUpdateInternalEncoding)
577 {
578 OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
579 if (php_internal_encoding_changed) {
580 php_internal_encoding_changed();
581 }
582 if (new_value) {
583 #ifdef PHP_WIN32
584 php_win32_cp_do_update(ZSTR_VAL(new_value));
585 #endif
586 }
587 return SUCCESS;
588 }
589 /* }}} */
590
591 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateInputEncoding)592 static PHP_INI_MH(OnUpdateInputEncoding)
593 {
594 OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
595 if (php_internal_encoding_changed) {
596 php_internal_encoding_changed();
597 }
598 if (new_value) {
599 #ifdef PHP_WIN32
600 php_win32_cp_do_update(NULL);
601 #endif
602 }
603 return SUCCESS;
604 }
605 /* }}} */
606
607 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateOutputEncoding)608 static PHP_INI_MH(OnUpdateOutputEncoding)
609 {
610 OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
611 if (php_internal_encoding_changed) {
612 php_internal_encoding_changed();
613 }
614 if (new_value) {
615 #ifdef PHP_WIN32
616 php_win32_cp_do_update(NULL);
617 #endif
618 }
619 return SUCCESS;
620 }
621 /* }}} */
622
623 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateErrorLog)624 static PHP_INI_MH(OnUpdateErrorLog)
625 {
626 /* Only do the safemode/open_basedir check at runtime */
627 if ((stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) &&
628 new_value && zend_string_equals_literal(new_value, "syslog")) {
629 if (PG(open_basedir) && php_check_open_basedir(ZSTR_VAL(new_value))) {
630 return FAILURE;
631 }
632 }
633 OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
634 return SUCCESS;
635 }
636 /* }}} */
637
638 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateMailLog)639 static PHP_INI_MH(OnUpdateMailLog)
640 {
641 /* Only do the safemode/open_basedir check at runtime */
642 if ((stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) && new_value) {
643 if (PG(open_basedir) && php_check_open_basedir(ZSTR_VAL(new_value))) {
644 return FAILURE;
645 }
646 }
647 OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
648 return SUCCESS;
649 }
650 /* }}} */
651
652 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnChangeMailForceExtra)653 static PHP_INI_MH(OnChangeMailForceExtra)
654 {
655 /* Check that INI setting does not have any nul bytes */
656 if (new_value && ZSTR_LEN(new_value) != strlen(ZSTR_VAL(new_value))) {
657 /* TODO Emit warning? */
658 return FAILURE;
659 }
660 /* Don't allow changing it in htaccess */
661 if (stage == PHP_INI_STAGE_HTACCESS) {
662 return FAILURE;
663 }
664 return SUCCESS;
665 }
666 /* }}} */
667
668 /* defined in browscap.c */
669 PHP_INI_MH(OnChangeBrowscap);
670
671
672 /* Need to be read from the environment (?):
673 * PHP_AUTO_PREPEND_FILE
674 * PHP_AUTO_APPEND_FILE
675 * PHP_DOCUMENT_ROOT
676 * PHP_USER_DIR
677 * PHP_INCLUDE_PATH
678 */
679
680 /* Windows use the internal mail */
681 #if defined(PHP_WIN32)
682 # define DEFAULT_SENDMAIL_PATH NULL
683 #else
684 # define DEFAULT_SENDMAIL_PATH PHP_PROG_SENDMAIL " -t -i"
685 #endif
686
687 /* {{{ PHP_INI */
688 PHP_INI_BEGIN()
689 PHP_INI_ENTRY_EX("highlight.comment", HL_COMMENT_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
690 PHP_INI_ENTRY_EX("highlight.default", HL_DEFAULT_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
691 PHP_INI_ENTRY_EX("highlight.html", HL_HTML_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
692 PHP_INI_ENTRY_EX("highlight.keyword", HL_KEYWORD_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
693 PHP_INI_ENTRY_EX("highlight.string", HL_STRING_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
694
695 STD_PHP_INI_ENTRY_EX("display_errors", "1", PHP_INI_ALL, OnUpdateDisplayErrors, display_errors, php_core_globals, core_globals, display_errors_mode)
696 STD_PHP_INI_BOOLEAN("display_startup_errors", "1", PHP_INI_ALL, OnUpdateBool, display_startup_errors, php_core_globals, core_globals)
697 STD_PHP_INI_BOOLEAN("enable_dl", "1", PHP_INI_SYSTEM, OnUpdateBool, enable_dl, php_core_globals, core_globals)
698 STD_PHP_INI_BOOLEAN("expose_php", "1", PHP_INI_SYSTEM, OnUpdateBool, expose_php, php_core_globals, core_globals)
699 STD_PHP_INI_ENTRY("docref_root", "", PHP_INI_ALL, OnUpdateString, docref_root, php_core_globals, core_globals)
700 STD_PHP_INI_ENTRY("docref_ext", "", PHP_INI_ALL, OnUpdateString, docref_ext, php_core_globals, core_globals)
701 STD_PHP_INI_BOOLEAN("html_errors", "1", PHP_INI_ALL, OnUpdateBool, html_errors, php_core_globals, core_globals)
702 STD_PHP_INI_BOOLEAN("xmlrpc_errors", "0", PHP_INI_SYSTEM, OnUpdateBool, xmlrpc_errors, php_core_globals, core_globals)
703 STD_PHP_INI_ENTRY("xmlrpc_error_number", "0", PHP_INI_ALL, OnUpdateLong, xmlrpc_error_number, php_core_globals, core_globals)
704 STD_PHP_INI_ENTRY("max_input_time", "-1", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, max_input_time, php_core_globals, core_globals)
705 STD_PHP_INI_BOOLEAN("ignore_user_abort", "0", PHP_INI_ALL, OnUpdateBool, ignore_user_abort, php_core_globals, core_globals)
706 STD_PHP_INI_BOOLEAN("implicit_flush", "0", PHP_INI_ALL, OnUpdateBool, implicit_flush, php_core_globals, core_globals)
707 STD_PHP_INI_BOOLEAN("log_errors", "0", PHP_INI_ALL, OnUpdateBool, log_errors, php_core_globals, core_globals)
708 STD_PHP_INI_BOOLEAN("ignore_repeated_errors", "0", PHP_INI_ALL, OnUpdateBool, ignore_repeated_errors, php_core_globals, core_globals)
709 STD_PHP_INI_BOOLEAN("ignore_repeated_source", "0", PHP_INI_ALL, OnUpdateBool, ignore_repeated_source, php_core_globals, core_globals)
710 STD_PHP_INI_BOOLEAN("report_memleaks", "1", PHP_INI_ALL, OnUpdateBool, report_memleaks, php_core_globals, core_globals)
711 STD_PHP_INI_BOOLEAN("report_zend_debug", "0", PHP_INI_ALL, OnUpdateBool, report_zend_debug, php_core_globals, core_globals)
712 STD_PHP_INI_ENTRY("output_buffering", "0", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateLong, output_buffering, php_core_globals, core_globals)
713 STD_PHP_INI_ENTRY("output_handler", NULL, PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateString, output_handler, php_core_globals, core_globals)
714 STD_PHP_INI_BOOLEAN("register_argc_argv", "1", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, register_argc_argv, php_core_globals, core_globals)
715 STD_PHP_INI_BOOLEAN("auto_globals_jit", "1", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, auto_globals_jit, php_core_globals, core_globals)
716 STD_PHP_INI_BOOLEAN("short_open_tag", DEFAULT_SHORT_OPEN_TAG, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, short_tags, zend_compiler_globals, compiler_globals)
717
718 STD_PHP_INI_ENTRY("unserialize_callback_func", NULL, PHP_INI_ALL, OnUpdateString, unserialize_callback_func, php_core_globals, core_globals)
719 STD_PHP_INI_ENTRY("serialize_precision", "-1", PHP_INI_ALL, OnSetSerializePrecision, serialize_precision, php_core_globals, core_globals)
720 STD_PHP_INI_ENTRY("arg_separator.output", "&", PHP_INI_ALL, OnUpdateStringUnempty, arg_separator.output, php_core_globals, core_globals)
721 STD_PHP_INI_ENTRY("arg_separator.input", "&", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateStringUnempty, arg_separator.input, php_core_globals, core_globals)
722
723 STD_PHP_INI_ENTRY("auto_append_file", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateString, auto_append_file, php_core_globals, core_globals)
724 STD_PHP_INI_ENTRY("auto_prepend_file", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateString, auto_prepend_file, php_core_globals, core_globals)
725 STD_PHP_INI_ENTRY("doc_root", NULL, PHP_INI_SYSTEM, OnUpdateStringUnempty, doc_root, php_core_globals, core_globals)
726 STD_PHP_INI_ENTRY("default_charset", PHP_DEFAULT_CHARSET, PHP_INI_ALL, OnUpdateDefaultCharset, default_charset, sapi_globals_struct, sapi_globals)
727 STD_PHP_INI_ENTRY("default_mimetype", SAPI_DEFAULT_MIMETYPE, PHP_INI_ALL, OnUpdateDefaultMimeTye, default_mimetype, sapi_globals_struct, sapi_globals)
728 STD_PHP_INI_ENTRY("internal_encoding", NULL, PHP_INI_ALL, OnUpdateInternalEncoding, internal_encoding, php_core_globals, core_globals)
729 STD_PHP_INI_ENTRY("input_encoding", NULL, PHP_INI_ALL, OnUpdateInputEncoding, input_encoding, php_core_globals, core_globals)
730 STD_PHP_INI_ENTRY("output_encoding", NULL, PHP_INI_ALL, OnUpdateOutputEncoding, output_encoding, php_core_globals, core_globals)
731 STD_PHP_INI_ENTRY("error_log", NULL, PHP_INI_ALL, OnUpdateErrorLog, error_log, php_core_globals, core_globals)
732 STD_PHP_INI_ENTRY("error_log_mode", "0644", PHP_INI_ALL, OnUpdateLong, error_log_mode, php_core_globals, core_globals)
733 STD_PHP_INI_ENTRY("extension_dir", PHP_EXTENSION_DIR, PHP_INI_SYSTEM, OnUpdateStringUnempty, extension_dir, php_core_globals, core_globals)
734 STD_PHP_INI_ENTRY("sys_temp_dir", NULL, PHP_INI_SYSTEM, OnUpdateStringUnempty, sys_temp_dir, php_core_globals, core_globals)
735 STD_PHP_INI_ENTRY("include_path", PHP_INCLUDE_PATH, PHP_INI_ALL, OnUpdateStringUnempty, include_path, php_core_globals, core_globals)
736 PHP_INI_ENTRY("max_execution_time", "30", PHP_INI_ALL, OnUpdateTimeout)
737 STD_PHP_INI_ENTRY("open_basedir", NULL, PHP_INI_ALL, OnUpdateBaseDir, open_basedir, php_core_globals, core_globals)
738
739 STD_PHP_INI_BOOLEAN("file_uploads", "1", PHP_INI_SYSTEM, OnUpdateBool, file_uploads, php_core_globals, core_globals)
740 STD_PHP_INI_ENTRY("upload_max_filesize", "2M", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, upload_max_filesize, php_core_globals, core_globals)
741 STD_PHP_INI_ENTRY("post_max_size", "8M", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, post_max_size, sapi_globals_struct,sapi_globals)
742 STD_PHP_INI_ENTRY("upload_tmp_dir", NULL, PHP_INI_SYSTEM, OnUpdateStringUnempty, upload_tmp_dir, php_core_globals, core_globals)
743 STD_PHP_INI_ENTRY("max_input_nesting_level", "64", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLongGEZero, max_input_nesting_level, php_core_globals, core_globals)
744 STD_PHP_INI_ENTRY("max_input_vars", "1000", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLongGEZero, max_input_vars, php_core_globals, core_globals)
745
746 STD_PHP_INI_ENTRY("user_dir", NULL, PHP_INI_SYSTEM, OnUpdateString, user_dir, php_core_globals, core_globals)
747 STD_PHP_INI_ENTRY("variables_order", "EGPCS", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateStringUnempty, variables_order, php_core_globals, core_globals)
748 STD_PHP_INI_ENTRY("request_order", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateString, request_order, php_core_globals, core_globals)
749
750 STD_PHP_INI_ENTRY("error_append_string", NULL, PHP_INI_ALL, OnUpdateString, error_append_string, php_core_globals, core_globals)
751 STD_PHP_INI_ENTRY("error_prepend_string", NULL, PHP_INI_ALL, OnUpdateString, error_prepend_string, php_core_globals, core_globals)
752
753 PHP_INI_ENTRY("SMTP", "localhost",PHP_INI_ALL, NULL)
754 PHP_INI_ENTRY("smtp_port", "25", PHP_INI_ALL, NULL)
755 STD_PHP_INI_BOOLEAN("mail.add_x_header", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, mail_x_header, php_core_globals, core_globals)
756 STD_PHP_INI_BOOLEAN("mail.mixed_lf_and_crlf", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, mail_mixed_lf_and_crlf, php_core_globals, core_globals)
757 STD_PHP_INI_ENTRY("mail.log", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateMailLog, mail_log, php_core_globals, core_globals)
758 PHP_INI_ENTRY("browscap", NULL, PHP_INI_SYSTEM, OnChangeBrowscap)
759 PHP_INI_ENTRY("memory_limit", "128M", PHP_INI_ALL, OnChangeMemoryLimit)
760 PHP_INI_ENTRY("precision", "14", PHP_INI_ALL, OnSetPrecision)
761 PHP_INI_ENTRY("sendmail_from", NULL, PHP_INI_ALL, NULL)
762 PHP_INI_ENTRY("sendmail_path", DEFAULT_SENDMAIL_PATH, PHP_INI_SYSTEM, NULL)
763 PHP_INI_ENTRY("mail.force_extra_parameters",NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnChangeMailForceExtra)
764 PHP_INI_ENTRY("disable_functions", "", PHP_INI_SYSTEM, NULL)
765 PHP_INI_ENTRY("disable_classes", "", PHP_INI_SYSTEM, NULL)
766 PHP_INI_ENTRY("max_file_uploads", "20", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL)
767 PHP_INI_ENTRY("max_multipart_body_parts", "-1", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL)
768
769 STD_PHP_INI_BOOLEAN("allow_url_fopen", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_url_fopen, php_core_globals, core_globals)
770 STD_PHP_INI_BOOLEAN("allow_url_include", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_url_include, php_core_globals, core_globals)
771 STD_PHP_INI_BOOLEAN("enable_post_data_reading", "1", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, enable_post_data_reading, php_core_globals, core_globals)
772
773 STD_PHP_INI_ENTRY("realpath_cache_size", "4096K", PHP_INI_SYSTEM, OnUpdateLong, realpath_cache_size_limit, virtual_cwd_globals, cwd_globals)
774 STD_PHP_INI_ENTRY("realpath_cache_ttl", "120", PHP_INI_SYSTEM, OnUpdateLong, realpath_cache_ttl, virtual_cwd_globals, cwd_globals)
775
776 STD_PHP_INI_ENTRY("user_ini.filename", ".user.ini", PHP_INI_SYSTEM, OnUpdateString, user_ini_filename, php_core_globals, core_globals)
777 STD_PHP_INI_ENTRY("user_ini.cache_ttl", "300", PHP_INI_SYSTEM, OnUpdateLong, user_ini_cache_ttl, php_core_globals, core_globals)
778 STD_PHP_INI_ENTRY("hard_timeout", "2", PHP_INI_SYSTEM, OnUpdateLong, hard_timeout, zend_executor_globals, executor_globals)
779 #ifdef PHP_WIN32
780 STD_PHP_INI_BOOLEAN("windows.show_crt_warning", "0", PHP_INI_ALL, OnUpdateBool, windows_show_crt_warning, php_core_globals, core_globals)
781 #endif
782 STD_PHP_INI_ENTRY("syslog.facility", "LOG_USER", PHP_INI_SYSTEM, OnSetFacility, syslog_facility, php_core_globals, core_globals)
783 STD_PHP_INI_ENTRY("syslog.ident", "php", PHP_INI_SYSTEM, OnUpdateString, syslog_ident, php_core_globals, core_globals)
784 STD_PHP_INI_ENTRY("syslog.filter", "no-ctrl", PHP_INI_ALL, OnSetLogFilter, syslog_filter, php_core_globals, core_globals)
785 PHP_INI_END()
786 /* }}} */
787
788 /* True globals (no need for thread safety */
789 /* But don't make them a single int bitfield */
790 static bool module_initialized = false;
791 static bool module_startup = true;
792 static bool module_shutdown = false;
793
794 /* {{{ php_during_module_startup */
php_during_module_startup(void)795 PHPAPI bool php_during_module_startup(void)
796 {
797 return module_startup;
798 }
799 /* }}} */
800
801 /* {{{ php_during_module_shutdown */
php_during_module_shutdown(void)802 PHPAPI bool php_during_module_shutdown(void)
803 {
804 return module_shutdown;
805 }
806 /* }}} */
807
808 /* {{{ php_get_module_initialized */
php_get_module_initialized(void)809 PHPAPI bool php_get_module_initialized(void)
810 {
811 return module_initialized;
812 }
813 /* }}} */
814
815 /* {{{ php_log_err_with_severity */
php_log_err_with_severity(const char * log_message,int syslog_type_int)816 PHPAPI ZEND_COLD void php_log_err_with_severity(const char *log_message, int syslog_type_int)
817 {
818 int fd = -1;
819 time_t error_time;
820
821 if (PG(in_error_log)) {
822 /* prevent recursive invocation */
823 return;
824 }
825 PG(in_error_log) = 1;
826
827 /* Try to use the specified logging location. */
828 if (PG(error_log) != NULL) {
829 int error_log_mode;
830
831 #ifdef HAVE_SYSLOG_H
832 if (!strcmp(PG(error_log), "syslog")) {
833 php_syslog(syslog_type_int, "%s", log_message);
834 PG(in_error_log) = 0;
835 return;
836 }
837 #endif
838
839 error_log_mode = 0644;
840
841 if (PG(error_log_mode) > 0 && PG(error_log_mode) <= 0777) {
842 error_log_mode = PG(error_log_mode);
843 }
844
845 fd = VCWD_OPEN_MODE(PG(error_log), O_CREAT | O_APPEND | O_WRONLY, error_log_mode);
846 if (fd != -1) {
847 char *tmp;
848 size_t len;
849 zend_string *error_time_str;
850
851 time(&error_time);
852 #ifdef ZTS
853 if (!php_during_module_startup()) {
854 error_time_str = php_format_date("d-M-Y H:i:s e", 13, error_time, 1);
855 } else {
856 error_time_str = php_format_date("d-M-Y H:i:s e", 13, error_time, 0);
857 }
858 #else
859 error_time_str = php_format_date("d-M-Y H:i:s e", 13, error_time, 1);
860 #endif
861 len = spprintf(&tmp, 0, "[%s] %s%s", ZSTR_VAL(error_time_str), log_message, PHP_EOL);
862 #ifdef PHP_WIN32
863 php_flock(fd, LOCK_EX);
864 /* XXX should eventually write in a loop if len > UINT_MAX */
865 php_ignore_value(write(fd, tmp, (unsigned)len));
866 php_flock(fd, LOCK_UN);
867 #else
868 php_ignore_value(write(fd, tmp, len));
869 #endif
870 efree(tmp);
871 zend_string_free(error_time_str);
872 close(fd);
873 PG(in_error_log) = 0;
874 return;
875 }
876 }
877
878 /* Otherwise fall back to the default logging location, if we have one */
879
880 if (sapi_module.log_message) {
881 sapi_module.log_message(log_message, syslog_type_int);
882 }
883 PG(in_error_log) = 0;
884 }
885 /* }}} */
886
887 /* {{{ php_write
888 wrapper for modules to use PHPWRITE */
php_write(void * buf,size_t size)889 PHPAPI size_t php_write(void *buf, size_t size)
890 {
891 return PHPWRITE(buf, size);
892 }
893 /* }}} */
894
895 /* {{{ php_printf */
php_printf(const char * format,...)896 PHPAPI size_t php_printf(const char *format, ...)
897 {
898 va_list args;
899 size_t ret;
900 char *buffer;
901 size_t size;
902
903 va_start(args, format);
904 size = vspprintf(&buffer, 0, format, args);
905 ret = PHPWRITE(buffer, size);
906 efree(buffer);
907 va_end(args);
908
909 return ret;
910 }
911 /* }}} */
912
913 /* {{{ php_printf_unchecked */
php_printf_unchecked(const char * format,...)914 PHPAPI size_t php_printf_unchecked(const char *format, ...)
915 {
916 va_list args;
917 size_t ret;
918 char *buffer;
919 size_t size;
920
921 va_start(args, format);
922 size = vspprintf(&buffer, 0, format, args);
923 ret = PHPWRITE(buffer, size);
924 efree(buffer);
925 va_end(args);
926
927 return ret;
928 }
929 /* }}} */
930
escape_html(const char * buffer,size_t buffer_len)931 static zend_string *escape_html(const char *buffer, size_t buffer_len) {
932 zend_string *result = php_escape_html_entities_ex(
933 (const unsigned char *) buffer, buffer_len, 0, ENT_COMPAT,
934 /* charset_hint */ NULL, /* double_encode */ 1, /* quiet */ 1);
935 if (!result || ZSTR_LEN(result) == 0) {
936 /* Retry with substituting invalid chars on fail. */
937 result = php_escape_html_entities_ex(
938 (const unsigned char *) buffer, buffer_len, 0, ENT_COMPAT | ENT_HTML_SUBSTITUTE_ERRORS,
939 /* charset_hint */ NULL, /* double_encode */ 1, /* quiet */ 1);
940 }
941 return result;
942 }
943
944 /* {{{ php_verror */
945 /* php_verror is called from php_error_docref<n> functions.
946 * Its purpose is to unify error messages and automatically generate clickable
947 * html error messages if corresponding ini setting (html_errors) is activated.
948 * See: CODING_STANDARDS.md for details.
949 */
php_verror(const char * docref,const char * params,int type,const char * format,va_list args)950 PHPAPI ZEND_COLD void php_verror(const char *docref, const char *params, int type, const char *format, va_list args)
951 {
952 zend_string *replace_origin = NULL;
953 char *docref_buf = NULL, *target = NULL;
954 char *docref_target = "", *docref_root = "";
955 char *p;
956 const char *space = "";
957 const char *class_name = "";
958 const char *function;
959 int origin_len;
960 char *origin;
961 zend_string *message;
962 int is_function = 0;
963
964 /* get error text into buffer and escape for html if necessary */
965 zend_string *buffer = vstrpprintf(0, format, args);
966
967 if (PG(html_errors)) {
968 zend_string *replace_buffer = escape_html(ZSTR_VAL(buffer), ZSTR_LEN(buffer));
969 zend_string_free(buffer);
970
971 if (replace_buffer) {
972 buffer = replace_buffer;
973 } else {
974 buffer = zend_empty_string;
975 }
976 }
977
978 /* which function caused the problem if any at all */
979 if (php_during_module_startup()) {
980 function = "PHP Startup";
981 } else if (php_during_module_shutdown()) {
982 function = "PHP Shutdown";
983 } else if (PG(during_request_startup)) {
984 function = "PHP Request Startup";
985 } else if (EG(current_execute_data) &&
986 EG(current_execute_data)->func &&
987 ZEND_USER_CODE(EG(current_execute_data)->func->common.type) &&
988 EG(current_execute_data)->opline &&
989 EG(current_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL
990 ) {
991 switch (EG(current_execute_data)->opline->extended_value) {
992 case ZEND_EVAL:
993 function = "eval";
994 is_function = 1;
995 break;
996 case ZEND_INCLUDE:
997 function = "include";
998 is_function = 1;
999 break;
1000 case ZEND_INCLUDE_ONCE:
1001 function = "include_once";
1002 is_function = 1;
1003 break;
1004 case ZEND_REQUIRE:
1005 function = "require";
1006 is_function = 1;
1007 break;
1008 case ZEND_REQUIRE_ONCE:
1009 function = "require_once";
1010 is_function = 1;
1011 break;
1012 default:
1013 function = "Unknown";
1014 }
1015 } else if ((function = get_active_function_name()) && strlen(function)) {
1016 is_function = 1;
1017 class_name = get_active_class_name(&space);
1018 } else if (EG(flags) & EG_FLAGS_IN_SHUTDOWN) {
1019 function = "PHP Request Shutdown";
1020 } else {
1021 function = "Unknown";
1022 }
1023
1024 /* if we still have memory then format the origin */
1025 if (is_function) {
1026 origin_len = (int)spprintf(&origin, 0, "%s%s%s(%s)", class_name, space, function, params);
1027 } else {
1028 origin_len = (int)spprintf(&origin, 0, "%s", function);
1029 }
1030
1031 if (PG(html_errors)) {
1032 replace_origin = escape_html(origin, origin_len);
1033 efree(origin);
1034 origin = ZSTR_VAL(replace_origin);
1035 }
1036
1037 /* origin and buffer available, so let's come up with the error message */
1038 if (docref && docref[0] == '#') {
1039 docref_target = strchr(docref, '#');
1040 docref = NULL;
1041 }
1042
1043 /* no docref given but function is known (the default) */
1044 if (!docref && is_function) {
1045 int doclen;
1046 while (*function == '_') {
1047 function++;
1048 }
1049 if (space[0] == '\0') {
1050 doclen = (int)spprintf(&docref_buf, 0, "function.%s", function);
1051 } else {
1052 doclen = (int)spprintf(&docref_buf, 0, "%s.%s", class_name, function);
1053 }
1054 while((p = strchr(docref_buf, '_')) != NULL) {
1055 *p = '-';
1056 }
1057 zend_str_tolower(docref_buf, doclen);
1058 docref = docref_buf;
1059 }
1060
1061 /* we have a docref for a function AND
1062 * - we show errors in html mode AND
1063 * - the user wants to see the links
1064 */
1065 if (docref && is_function && PG(html_errors) && strlen(PG(docref_root))) {
1066 if (strncmp(docref, "http://", 7)) {
1067 /* We don't have 'http://' so we use docref_root */
1068
1069 char *ref; /* temp copy for duplicated docref */
1070
1071 docref_root = PG(docref_root);
1072
1073 ref = estrdup(docref);
1074 if (docref_buf) {
1075 efree(docref_buf);
1076 }
1077 docref_buf = ref;
1078 /* strip of the target if any */
1079 p = strrchr(ref, '#');
1080 if (p) {
1081 target = estrdup(p);
1082 if (target) {
1083 docref_target = target;
1084 *p = '\0';
1085 }
1086 }
1087 /* add the extension if it is set in ini */
1088 if (PG(docref_ext) && strlen(PG(docref_ext))) {
1089 spprintf(&docref_buf, 0, "%s%s", ref, PG(docref_ext));
1090 efree(ref);
1091 }
1092 docref = docref_buf;
1093 }
1094 /* display html formatted or only show the additional links */
1095 if (PG(html_errors)) {
1096 message = zend_strpprintf_unchecked(0, "%s [<a href='%s%s%s'>%s</a>]: %S", origin, docref_root, docref, docref_target, docref, buffer);
1097 } else {
1098 message = zend_strpprintf_unchecked(0, "%s [%s%s%s]: %S", origin, docref_root, docref, docref_target, buffer);
1099 }
1100 if (target) {
1101 efree(target);
1102 }
1103 } else {
1104 message = zend_strpprintf_unchecked(0, "%s: %S", origin, buffer);
1105 }
1106 if (replace_origin) {
1107 zend_string_free(replace_origin);
1108 } else {
1109 efree(origin);
1110 }
1111 if (docref_buf) {
1112 efree(docref_buf);
1113 }
1114
1115 zend_string_free(buffer);
1116
1117 zend_error_zstr(type, message);
1118 zend_string_release(message);
1119 }
1120 /* }}} */
1121
1122 /* {{{ php_error_docref */
1123 /* Generate an error which links to docref or the php.net documentation if docref is NULL */
1124 #define php_error_docref_impl(docref, type, format) do {\
1125 va_list args; \
1126 va_start(args, format); \
1127 php_verror(docref, "", type, format, args); \
1128 va_end(args); \
1129 } while (0)
1130
php_error_docref(const char * docref,int type,const char * format,...)1131 PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format, ...)
1132 {
1133 php_error_docref_impl(docref, type, format);
1134 }
1135
php_error_docref_unchecked(const char * docref,int type,const char * format,...)1136 PHPAPI ZEND_COLD void php_error_docref_unchecked(const char *docref, int type, const char *format, ...)
1137 {
1138 php_error_docref_impl(docref, type, format);
1139 }
1140 /* }}} */
1141
1142 /* {{{ php_error_docref1 */
1143 /* See: CODING_STANDARDS.md for details. */
php_error_docref1(const char * docref,const char * param1,int type,const char * format,...)1144 PHPAPI ZEND_COLD void php_error_docref1(const char *docref, const char *param1, int type, const char *format, ...)
1145 {
1146 va_list args;
1147
1148 va_start(args, format);
1149 php_verror(docref, param1, type, format, args);
1150 va_end(args);
1151 }
1152 /* }}} */
1153
1154 /* {{{ php_error_docref2 */
1155 /* See: CODING_STANDARDS.md for details. */
php_error_docref2(const char * docref,const char * param1,const char * param2,int type,const char * format,...)1156 PHPAPI ZEND_COLD void php_error_docref2(const char *docref, const char *param1, const char *param2, int type, const char *format, ...)
1157 {
1158 char *params;
1159 va_list args;
1160
1161 spprintf(¶ms, 0, "%s,%s", param1, param2);
1162 va_start(args, format);
1163 php_verror(docref, params ? params : "...", type, format, args);
1164 va_end(args);
1165 if (params) {
1166 efree(params);
1167 }
1168 }
1169 /* }}} */
1170
1171 #ifdef PHP_WIN32
php_win32_docref1_from_error(DWORD error,const char * param1)1172 PHPAPI ZEND_COLD void php_win32_docref1_from_error(DWORD error, const char *param1) {
1173 char *buf = php_win32_error_to_msg(error);
1174 size_t buf_len;
1175
1176 buf_len = strlen(buf);
1177 if (buf_len >= 2) {
1178 buf[buf_len - 1] = '\0';
1179 buf[buf_len - 2] = '\0';
1180 }
1181 php_error_docref1(NULL, param1, E_WARNING, "%s (code: %lu)", buf, error);
1182 php_win32_error_msg_free(buf);
1183 }
1184
php_win32_docref2_from_error(DWORD error,const char * param1,const char * param2)1185 PHPAPI ZEND_COLD void php_win32_docref2_from_error(DWORD error, const char *param1, const char *param2) {
1186 char *buf = php_win32_error_to_msg(error);
1187 php_error_docref2(NULL, param1, param2, E_WARNING, "%s (code: %lu)", buf, error);
1188 php_win32_error_msg_free(buf);
1189 }
1190 #endif
1191
1192 /* {{{ php_html_puts */
php_html_puts(const char * str,size_t size)1193 PHPAPI void php_html_puts(const char *str, size_t size)
1194 {
1195 zend_html_puts(str, size);
1196 }
1197 /* }}} */
1198
clear_last_error(void)1199 static void clear_last_error(void) {
1200 if (PG(last_error_message)) {
1201 zend_string_release(PG(last_error_message));
1202 PG(last_error_message) = NULL;
1203 }
1204 if (PG(last_error_file)) {
1205 zend_string_release(PG(last_error_file));
1206 PG(last_error_file) = NULL;
1207 }
1208 }
1209
1210 #if ZEND_DEBUG
1211 /* {{{ report_zend_debug_error_notify_cb */
report_zend_debug_error_notify_cb(int type,zend_string * error_filename,uint32_t error_lineno,zend_string * message)1212 static void report_zend_debug_error_notify_cb(int type, zend_string *error_filename, uint32_t error_lineno, zend_string *message)
1213 {
1214 if (PG(report_zend_debug)) {
1215 bool trigger_break;
1216
1217 switch (type) {
1218 case E_ERROR:
1219 case E_CORE_ERROR:
1220 case E_COMPILE_ERROR:
1221 case E_USER_ERROR:
1222 trigger_break=1;
1223 break;
1224 default:
1225 trigger_break=0;
1226 break;
1227 }
1228
1229 zend_output_debug_string(trigger_break, "%s(%" PRIu32 ") : %s", ZSTR_VAL(error_filename), error_lineno, ZSTR_VAL(message));
1230 }
1231 }
1232 /* }}} */
1233 #endif
1234
1235 /* {{{ php_error_cb
1236 extended error handling function */
php_error_cb(int orig_type,zend_string * error_filename,const uint32_t error_lineno,zend_string * message)1237 static ZEND_COLD void php_error_cb(int orig_type, zend_string *error_filename, const uint32_t error_lineno, zend_string *message)
1238 {
1239 bool display;
1240 int type = orig_type & E_ALL;
1241
1242 /* check for repeated errors to be ignored */
1243 if (PG(ignore_repeated_errors) && PG(last_error_message)) {
1244 /* no check for PG(last_error_file) is needed since it cannot
1245 * be NULL if PG(last_error_message) is not NULL */
1246 if (!zend_string_equals(PG(last_error_message), message)
1247 || (!PG(ignore_repeated_source)
1248 && ((PG(last_error_lineno) != (int)error_lineno)
1249 || !zend_string_equals(PG(last_error_file), error_filename)))) {
1250 display = 1;
1251 } else {
1252 display = 0;
1253 }
1254 } else {
1255 display = 1;
1256 }
1257
1258 /* according to error handling mode, throw exception or show it */
1259 if (EG(error_handling) == EH_THROW) {
1260 switch (type) {
1261 case E_WARNING:
1262 case E_CORE_WARNING:
1263 case E_COMPILE_WARNING:
1264 case E_USER_WARNING:
1265 /* throw an exception if we are in EH_THROW mode and the type is warning.
1266 * fatal errors are real errors and cannot be made exceptions.
1267 * exclude deprecated for the sake of BC to old damaged code.
1268 * notices are no errors and are not treated as such like E_WARNINGS.
1269 * DO NOT overwrite a pending exception.
1270 */
1271 if (!EG(exception)) {
1272 zend_throw_error_exception(EG(exception_class), message, 0, type);
1273 }
1274 return;
1275 default:
1276 break;
1277 }
1278 }
1279
1280 /* store the error if it has changed */
1281 if (display) {
1282 clear_last_error();
1283 if (!error_filename) {
1284 error_filename = ZSTR_KNOWN(ZEND_STR_UNKNOWN_CAPITALIZED);
1285 }
1286 PG(last_error_type) = type;
1287 PG(last_error_message) = zend_string_copy(message);
1288 PG(last_error_file) = zend_string_copy(error_filename);
1289 PG(last_error_lineno) = error_lineno;
1290 }
1291
1292 if (zend_alloc_in_memory_limit_error_reporting()) {
1293 php_output_discard_all();
1294 }
1295
1296 /* display/log the error if necessary */
1297 if (display && ((EG(error_reporting) & type) || (type & E_CORE))
1298 && (PG(log_errors) || PG(display_errors) || (!module_initialized))) {
1299 char *error_type_str;
1300 int syslog_type_int = LOG_NOTICE;
1301
1302 switch (type) {
1303 case E_ERROR:
1304 case E_CORE_ERROR:
1305 case E_COMPILE_ERROR:
1306 case E_USER_ERROR:
1307 error_type_str = "Fatal error";
1308 syslog_type_int = LOG_ERR;
1309 break;
1310 case E_RECOVERABLE_ERROR:
1311 error_type_str = "Recoverable fatal error";
1312 syslog_type_int = LOG_ERR;
1313 break;
1314 case E_WARNING:
1315 case E_CORE_WARNING:
1316 case E_COMPILE_WARNING:
1317 case E_USER_WARNING:
1318 error_type_str = "Warning";
1319 syslog_type_int = LOG_WARNING;
1320 break;
1321 case E_PARSE:
1322 error_type_str = "Parse error";
1323 syslog_type_int = LOG_ERR;
1324 break;
1325 case E_NOTICE:
1326 case E_USER_NOTICE:
1327 error_type_str = "Notice";
1328 syslog_type_int = LOG_NOTICE;
1329 break;
1330 case E_STRICT:
1331 error_type_str = "Strict Standards";
1332 syslog_type_int = LOG_INFO;
1333 break;
1334 case E_DEPRECATED:
1335 case E_USER_DEPRECATED:
1336 error_type_str = "Deprecated";
1337 syslog_type_int = LOG_INFO;
1338 break;
1339 default:
1340 error_type_str = "Unknown error";
1341 break;
1342 }
1343
1344 if (PG(log_errors)
1345 || (!module_initialized && (!PG(display_startup_errors) || !PG(display_errors)))) {
1346 char *log_buffer;
1347 #ifdef PHP_WIN32
1348 if (type == E_CORE_ERROR || type == E_CORE_WARNING) {
1349 syslog(LOG_ALERT, "PHP %s: %s (%s)", error_type_str, ZSTR_VAL(message), GetCommandLine());
1350 }
1351 #endif
1352 spprintf(&log_buffer, 0, "PHP %s: %s in %s on line %" PRIu32, error_type_str, ZSTR_VAL(message), ZSTR_VAL(error_filename), error_lineno);
1353 php_log_err_with_severity(log_buffer, syslog_type_int);
1354 efree(log_buffer);
1355 }
1356
1357 if (PG(display_errors) && ((module_initialized && !PG(during_request_startup)) || (PG(display_startup_errors)))) {
1358 if (PG(xmlrpc_errors)) {
1359 php_printf("<?xml version=\"1.0\"?><methodResponse><fault><value><struct><member><name>faultCode</name><value><int>" ZEND_LONG_FMT "</int></value></member><member><name>faultString</name><value><string>%s:%s in %s on line %" PRIu32 "</string></value></member></struct></value></fault></methodResponse>", PG(xmlrpc_error_number), error_type_str, ZSTR_VAL(message), ZSTR_VAL(error_filename), error_lineno);
1360 } else {
1361 char *prepend_string = INI_STR("error_prepend_string");
1362 char *append_string = INI_STR("error_append_string");
1363
1364 if (PG(html_errors)) {
1365 if (type == E_ERROR || type == E_PARSE) {
1366 zend_string *buf = escape_html(ZSTR_VAL(message), ZSTR_LEN(message));
1367 php_printf("%s<br />\n<b>%s</b>: %s in <b>%s</b> on line <b>%" PRIu32 "</b><br />\n%s", STR_PRINT(prepend_string), error_type_str, ZSTR_VAL(buf), ZSTR_VAL(error_filename), error_lineno, STR_PRINT(append_string));
1368 zend_string_free(buf);
1369 } else {
1370 php_printf_unchecked("%s<br />\n<b>%s</b>: %S in <b>%s</b> on line <b>%" PRIu32 "</b><br />\n%s", STR_PRINT(prepend_string), error_type_str, message, ZSTR_VAL(error_filename), error_lineno, STR_PRINT(append_string));
1371 }
1372 } else {
1373 /* Write CLI/CGI errors to stderr if display_errors = "stderr" */
1374 if ((!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg")) &&
1375 PG(display_errors) == PHP_DISPLAY_ERRORS_STDERR
1376 ) {
1377 fprintf(stderr, "%s: ", error_type_str);
1378 fwrite(ZSTR_VAL(message), sizeof(char), ZSTR_LEN(message), stderr);
1379 fprintf(stderr, " in %s on line %" PRIu32 "\n", ZSTR_VAL(error_filename), error_lineno);
1380 #ifdef PHP_WIN32
1381 fflush(stderr);
1382 #endif
1383 } else {
1384 php_printf_unchecked("%s\n%s: %S in %s on line %" PRIu32 "\n%s", STR_PRINT(prepend_string), error_type_str, message, ZSTR_VAL(error_filename), error_lineno, STR_PRINT(append_string));
1385 }
1386 }
1387 }
1388 }
1389 }
1390
1391 /* Bail out if we can't recover */
1392 switch (type) {
1393 case E_CORE_ERROR:
1394 if(!module_initialized) {
1395 /* bad error in module startup - no way we can live with this */
1396 exit(-2);
1397 }
1398 ZEND_FALLTHROUGH;
1399 case E_ERROR:
1400 case E_RECOVERABLE_ERROR:
1401 case E_PARSE:
1402 case E_COMPILE_ERROR:
1403 case E_USER_ERROR:
1404 EG(exit_status) = 255;
1405 if (module_initialized) {
1406 if (!PG(display_errors) &&
1407 !SG(headers_sent) &&
1408 SG(sapi_headers).http_response_code == 200
1409 ) {
1410 sapi_header_line ctr = {0};
1411
1412 ctr.line = "HTTP/1.0 500 Internal Server Error";
1413 ctr.line_len = sizeof("HTTP/1.0 500 Internal Server Error") - 1;
1414 sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
1415 }
1416 /* the parser would return 1 (failure), we can bail out nicely */
1417 if (!(orig_type & E_DONT_BAIL)) {
1418 /* restore memory limit */
1419 zend_set_memory_limit(PG(memory_limit));
1420 zend_objects_store_mark_destructed(&EG(objects_store));
1421 if (CG(in_compilation) && (type == E_COMPILE_ERROR || type == E_PARSE)) {
1422 /* We bailout during compilation which may for example leave stale entries in CG(loop_var_stack).
1423 * If code is compiled during shutdown, we need to make sure the compiler is reset to a clean state,
1424 * otherwise this will lead to incorrect compilation during shutdown.
1425 * We don't do a full re-initialization via init_compiler() because that will also reset streams and resources. */
1426 shutdown_compiler();
1427 zend_init_compiler_data_structures();
1428 }
1429 zend_bailout();
1430 return;
1431 }
1432 }
1433 break;
1434 }
1435 }
1436 /* }}} */
1437
1438 /* {{{ php_get_current_user */
php_get_current_user(void)1439 PHPAPI char *php_get_current_user(void)
1440 {
1441 zend_stat_t *pstat = NULL;
1442
1443 if (SG(request_info).current_user) {
1444 return SG(request_info).current_user;
1445 }
1446
1447 /* FIXME: I need to have this somehow handled if
1448 USE_SAPI is defined, because cgi will also be
1449 interfaced in USE_SAPI */
1450
1451 pstat = sapi_get_stat();
1452
1453 if (!pstat) {
1454 return "";
1455 } else {
1456 #ifdef PHP_WIN32
1457 char *name = php_win32_get_username();
1458 int len;
1459
1460 if (!name) {
1461 return "";
1462 }
1463 len = (int)strlen(name);
1464 name[len] = '\0';
1465 SG(request_info).current_user_length = len;
1466 SG(request_info).current_user = estrndup(name, len);
1467 free(name);
1468 return SG(request_info).current_user;
1469 #else
1470 struct passwd *pwd;
1471 #if defined(ZTS) && defined(HAVE_GETPWUID_R) && defined(_SC_GETPW_R_SIZE_MAX)
1472 struct passwd _pw;
1473 struct passwd *retpwptr = NULL;
1474 int pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
1475 char *pwbuf;
1476
1477 if (pwbuflen < 1) {
1478 return "";
1479 }
1480 pwbuf = emalloc(pwbuflen);
1481 if (getpwuid_r(pstat->st_uid, &_pw, pwbuf, pwbuflen, &retpwptr) != 0) {
1482 efree(pwbuf);
1483 return "";
1484 }
1485 if (retpwptr == NULL) {
1486 efree(pwbuf);
1487 return "";
1488 }
1489 pwd = &_pw;
1490 #else
1491 if ((pwd=getpwuid(pstat->st_uid))==NULL) {
1492 return "";
1493 }
1494 #endif
1495 SG(request_info).current_user_length = strlen(pwd->pw_name);
1496 SG(request_info).current_user = estrndup(pwd->pw_name, SG(request_info).current_user_length);
1497 #if defined(ZTS) && defined(HAVE_GETPWUID_R) && defined(_SC_GETPW_R_SIZE_MAX)
1498 efree(pwbuf);
1499 #endif
1500 return SG(request_info).current_user;
1501 #endif
1502 }
1503 }
1504 /* }}} */
1505
1506 /* {{{ Sets the maximum time a script can run */
PHP_FUNCTION(set_time_limit)1507 PHP_FUNCTION(set_time_limit)
1508 {
1509 zend_long new_timeout;
1510 char *new_timeout_str;
1511 size_t new_timeout_strlen;
1512 zend_string *key;
1513
1514 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &new_timeout) == FAILURE) {
1515 RETURN_THROWS();
1516 }
1517
1518 new_timeout_strlen = zend_spprintf(&new_timeout_str, 0, ZEND_LONG_FMT, new_timeout);
1519
1520 key = ZSTR_INIT_LITERAL("max_execution_time", 0);
1521 if (zend_alter_ini_entry_chars_ex(key, new_timeout_str, new_timeout_strlen, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0) == SUCCESS) {
1522 RETVAL_TRUE;
1523 } else {
1524 RETVAL_FALSE;
1525 }
1526 zend_string_release_ex(key, 0);
1527 efree(new_timeout_str);
1528 }
1529 /* }}} */
1530
1531 /* {{{ php_fopen_wrapper_for_zend */
php_fopen_wrapper_for_zend(zend_string * filename,zend_string ** opened_path)1532 static FILE *php_fopen_wrapper_for_zend(zend_string *filename, zend_string **opened_path)
1533 {
1534 *opened_path = filename;
1535 return php_stream_open_wrapper_as_file(ZSTR_VAL(filename), "rb", USE_PATH|REPORT_ERRORS|STREAM_OPEN_FOR_INCLUDE|STREAM_OPEN_FOR_ZEND_STREAM, opened_path);
1536 }
1537 /* }}} */
1538
php_zend_stream_closer(void * handle)1539 static void php_zend_stream_closer(void *handle) /* {{{ */
1540 {
1541 php_stream_close((php_stream*)handle);
1542 }
1543 /* }}} */
1544
php_zend_stream_fsizer(void * handle)1545 static size_t php_zend_stream_fsizer(void *handle) /* {{{ */
1546 {
1547 php_stream *stream = handle;
1548 php_stream_statbuf ssb;
1549
1550 /* File size reported by stat() may be inaccurate if stream filters are used.
1551 * TODO: Should stat() be generally disabled if filters are used? */
1552 if (stream->readfilters.head) {
1553 return 0;
1554 }
1555
1556 if (php_stream_stat(stream, &ssb) == 0) {
1557 return ssb.sb.st_size;
1558 }
1559 return 0;
1560 }
1561 /* }}} */
1562
php_stream_open_for_zend(zend_file_handle * handle)1563 static zend_result php_stream_open_for_zend(zend_file_handle *handle) /* {{{ */
1564 {
1565 return php_stream_open_for_zend_ex(handle, USE_PATH|REPORT_ERRORS|STREAM_OPEN_FOR_INCLUDE);
1566 }
1567 /* }}} */
1568
php_stream_open_for_zend_ex(zend_file_handle * handle,int mode)1569 PHPAPI zend_result php_stream_open_for_zend_ex(zend_file_handle *handle, int mode) /* {{{ */
1570 {
1571 zend_string *opened_path;
1572 zend_string *filename;
1573 php_stream *stream;
1574
1575 ZEND_ASSERT(handle->type == ZEND_HANDLE_FILENAME);
1576 opened_path = filename = handle->filename;
1577 stream = php_stream_open_wrapper((char *)ZSTR_VAL(filename), "rb", mode | STREAM_OPEN_FOR_ZEND_STREAM, &opened_path);
1578 if (stream) {
1579 memset(handle, 0, sizeof(zend_file_handle));
1580 handle->type = ZEND_HANDLE_STREAM;
1581 handle->filename = filename;
1582 handle->opened_path = opened_path;
1583 handle->handle.stream.handle = stream;
1584 handle->handle.stream.reader = (zend_stream_reader_t)_php_stream_read;
1585 handle->handle.stream.fsizer = php_zend_stream_fsizer;
1586 handle->handle.stream.isatty = 0;
1587 handle->handle.stream.closer = php_zend_stream_closer;
1588 /* suppress warning if this stream is not explicitly closed */
1589 php_stream_auto_cleanup(stream);
1590 /* Disable buffering to avoid double buffering between PHP and Zend streams. */
1591 php_stream_set_option(stream, PHP_STREAM_OPTION_READ_BUFFER, PHP_STREAM_BUFFER_NONE, NULL);
1592
1593 return SUCCESS;
1594 }
1595 return FAILURE;
1596 }
1597 /* }}} */
1598
php_resolve_path_for_zend(zend_string * filename)1599 static zend_string *php_resolve_path_for_zend(zend_string *filename) /* {{{ */
1600 {
1601 return php_resolve_path(ZSTR_VAL(filename), ZSTR_LEN(filename), PG(include_path));
1602 }
1603 /* }}} */
1604
1605 /* {{{ php_get_configuration_directive_for_zend */
php_get_configuration_directive_for_zend(zend_string * name)1606 static zval *php_get_configuration_directive_for_zend(zend_string *name)
1607 {
1608 return cfg_get_entry_ex(name);
1609 }
1610 /* }}} */
1611
1612 /* {{{ php_free_request_globals */
php_free_request_globals(void)1613 static void php_free_request_globals(void)
1614 {
1615 clear_last_error();
1616 if (PG(php_sys_temp_dir)) {
1617 efree(PG(php_sys_temp_dir));
1618 PG(php_sys_temp_dir) = NULL;
1619 }
1620
1621 EG(filename_override) = NULL;
1622 EG(lineno_override) = -1;
1623 }
1624 /* }}} */
1625
1626 /* {{{ php_message_handler_for_zend */
php_message_handler_for_zend(zend_long message,const void * data)1627 static ZEND_COLD void php_message_handler_for_zend(zend_long message, const void *data)
1628 {
1629 switch (message) {
1630 case ZMSG_FAILED_INCLUDE_FOPEN: {
1631 char *tmp = estrdup((char *) data);
1632 php_error_docref("function.include", E_WARNING, "Failed opening '%s' for inclusion (include_path='%s')", php_strip_url_passwd(tmp), STR_PRINT(PG(include_path)));
1633 efree(tmp);
1634 break;
1635 }
1636 case ZMSG_FAILED_REQUIRE_FOPEN: {
1637 char *tmp = estrdup((char *) data);
1638 zend_throw_error(NULL, "Failed opening required '%s' (include_path='%s')", php_strip_url_passwd(tmp), STR_PRINT(PG(include_path)));
1639 efree(tmp);
1640 break;
1641 }
1642 case ZMSG_FAILED_HIGHLIGHT_FOPEN: {
1643 char *tmp = estrdup((char *) data);
1644 php_error_docref(NULL, E_WARNING, "Failed opening '%s' for highlighting", php_strip_url_passwd(tmp));
1645 efree(tmp);
1646 break;
1647 }
1648 case ZMSG_MEMORY_LEAK_DETECTED:
1649 case ZMSG_MEMORY_LEAK_REPEATED:
1650 #if ZEND_DEBUG
1651 if (EG(error_reporting) & E_WARNING) {
1652 char memory_leak_buf[1024];
1653
1654 if (message==ZMSG_MEMORY_LEAK_DETECTED) {
1655 zend_leak_info *t = (zend_leak_info *) data;
1656
1657 snprintf(memory_leak_buf, 512, "%s(%" PRIu32 ") : Freeing " ZEND_ADDR_FMT " (%zu bytes), script=%s\n", t->filename, t->lineno, (size_t)t->addr, t->size, SAFE_FILENAME(SG(request_info).path_translated));
1658 if (t->orig_filename) {
1659 char relay_buf[512];
1660
1661 snprintf(relay_buf, 512, "%s(%" PRIu32 ") : Actual location (location was relayed)\n", t->orig_filename, t->orig_lineno);
1662 strlcat(memory_leak_buf, relay_buf, sizeof(memory_leak_buf));
1663 }
1664 } else {
1665 unsigned long leak_count = (uintptr_t) data;
1666
1667 snprintf(memory_leak_buf, 512, "Last leak repeated %lu time%s\n", leak_count, (leak_count>1?"s":""));
1668 }
1669 # if defined(PHP_WIN32)
1670 if (IsDebuggerPresent()) {
1671 OutputDebugString(memory_leak_buf);
1672 } else {
1673 fprintf(stderr, "%s", memory_leak_buf);
1674 }
1675 # else
1676 fprintf(stderr, "%s", memory_leak_buf);
1677 # endif
1678 }
1679 #endif
1680 break;
1681 case ZMSG_MEMORY_LEAKS_GRAND_TOTAL:
1682 #if ZEND_DEBUG
1683 if (EG(error_reporting) & E_WARNING) {
1684 char memory_leak_buf[512];
1685
1686 snprintf(memory_leak_buf, 512, "=== Total %d memory leaks detected ===\n", *((uint32_t *) data));
1687 # if defined(PHP_WIN32)
1688 if (IsDebuggerPresent()) {
1689 OutputDebugString(memory_leak_buf);
1690 } else {
1691 fprintf(stderr, "%s", memory_leak_buf);
1692 }
1693 # else
1694 fprintf(stderr, "%s", memory_leak_buf);
1695 # endif
1696 }
1697 #endif
1698 break;
1699 case ZMSG_LOG_SCRIPT_NAME: {
1700 struct tm *ta, tmbuf;
1701 time_t curtime;
1702 char *datetime_str, asctimebuf[52];
1703 char memory_leak_buf[4096];
1704
1705 time(&curtime);
1706 ta = php_localtime_r(&curtime, &tmbuf);
1707 datetime_str = php_asctime_r(ta, asctimebuf);
1708 if (datetime_str) {
1709 datetime_str[strlen(datetime_str)-1]=0; /* get rid of the trailing newline */
1710 snprintf(memory_leak_buf, sizeof(memory_leak_buf), "[%s] Script: '%s'\n", datetime_str, SAFE_FILENAME(SG(request_info).path_translated));
1711 } else {
1712 snprintf(memory_leak_buf, sizeof(memory_leak_buf), "[null] Script: '%s'\n", SAFE_FILENAME(SG(request_info).path_translated));
1713 }
1714 # if defined(PHP_WIN32)
1715 if (IsDebuggerPresent()) {
1716 OutputDebugString(memory_leak_buf);
1717 } else {
1718 fprintf(stderr, "%s", memory_leak_buf);
1719 }
1720 # else
1721 fprintf(stderr, "%s", memory_leak_buf);
1722 # endif
1723 }
1724 break;
1725 }
1726 }
1727 /* }}} */
1728
1729
php_on_timeout(int seconds)1730 void php_on_timeout(int seconds)
1731 {
1732 PG(connection_status) |= PHP_CONNECTION_TIMEOUT;
1733 }
1734
1735 #if PHP_SIGCHILD
1736 /* {{{ sigchld_handler */
sigchld_handler(int apar)1737 static void sigchld_handler(int apar)
1738 {
1739 int errno_save = errno;
1740
1741 while (waitpid(-1, NULL, WNOHANG) > 0);
1742 signal(SIGCHLD, sigchld_handler);
1743
1744 errno = errno_save;
1745 }
1746 /* }}} */
1747 #endif
1748
1749 /* {{{ php_request_startup */
php_request_startup(void)1750 zend_result php_request_startup(void)
1751 {
1752 zend_result retval = SUCCESS;
1753
1754 zend_interned_strings_activate();
1755
1756 #ifdef HAVE_DTRACE
1757 DTRACE_REQUEST_STARTUP(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), (char *)SAFE_FILENAME(SG(request_info).request_method));
1758 #endif /* HAVE_DTRACE */
1759
1760 #ifdef PHP_WIN32
1761 # if defined(ZTS)
1762 _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
1763 # endif
1764 PG(com_initialized) = 0;
1765 #endif
1766
1767 #if PHP_SIGCHILD
1768 signal(SIGCHLD, sigchld_handler);
1769 #endif
1770
1771 zend_try {
1772 PG(in_error_log) = 0;
1773 PG(during_request_startup) = 1;
1774
1775 php_output_activate();
1776
1777 /* initialize global variables */
1778 PG(modules_activated) = 0;
1779 PG(header_is_being_sent) = 0;
1780 PG(connection_status) = PHP_CONNECTION_NORMAL;
1781 PG(in_user_include) = 0;
1782
1783 zend_activate();
1784 sapi_activate();
1785
1786 #ifdef ZEND_SIGNALS
1787 zend_signal_activate();
1788 #endif
1789
1790 if (PG(max_input_time) == -1) {
1791 zend_set_timeout(EG(timeout_seconds), 1);
1792 } else {
1793 zend_set_timeout(PG(max_input_time), 1);
1794 }
1795
1796 /* Disable realpath cache if an open_basedir is set */
1797 if (PG(open_basedir) && *PG(open_basedir)) {
1798 CWDG(realpath_cache_size_limit) = 0;
1799 }
1800
1801 if (PG(expose_php) && !SG(headers_sent)) {
1802 sapi_add_header(SAPI_PHP_VERSION_HEADER, sizeof(SAPI_PHP_VERSION_HEADER)-1, 1);
1803 }
1804
1805 if (PG(output_handler) && PG(output_handler)[0]) {
1806 zval oh;
1807
1808 ZVAL_STRING(&oh, PG(output_handler));
1809 php_output_start_user(&oh, 0, PHP_OUTPUT_HANDLER_STDFLAGS);
1810 zval_ptr_dtor(&oh);
1811 } else if (PG(output_buffering)) {
1812 php_output_start_user(NULL, PG(output_buffering) > 1 ? PG(output_buffering) : 0, PHP_OUTPUT_HANDLER_STDFLAGS);
1813 } else if (PG(implicit_flush)) {
1814 php_output_set_implicit_flush(1);
1815 }
1816
1817 /* We turn this off in php_execute_script() */
1818 /* PG(during_request_startup) = 0; */
1819
1820 php_hash_environment();
1821 zend_activate_modules();
1822 PG(modules_activated)=1;
1823 } zend_catch {
1824 retval = FAILURE;
1825 } zend_end_try();
1826
1827 SG(sapi_started) = 1;
1828
1829 return retval;
1830 }
1831 /* }}} */
1832
1833 /* {{{ php_request_shutdown */
php_request_shutdown(void * dummy)1834 void php_request_shutdown(void *dummy)
1835 {
1836 bool report_memleaks;
1837
1838 EG(flags) |= EG_FLAGS_IN_SHUTDOWN;
1839
1840 report_memleaks = PG(report_memleaks);
1841
1842 /* EG(current_execute_data) points into nirvana and therefore cannot be safely accessed
1843 * inside zend_executor callback functions.
1844 */
1845 EG(current_execute_data) = NULL;
1846
1847 php_deactivate_ticks();
1848
1849 /* 0. Call any open observer end handlers that are still open after a zend_bailout */
1850 if (ZEND_OBSERVER_ENABLED) {
1851 zend_observer_fcall_end_all();
1852 }
1853
1854 /* 1. Call all possible shutdown functions registered with register_shutdown_function() */
1855 if (PG(modules_activated)) {
1856 php_call_shutdown_functions();
1857 }
1858
1859 /* 2. Call all possible __destruct() functions */
1860 zend_try {
1861 zend_call_destructors();
1862 } zend_end_try();
1863
1864 /* 3. Flush all output buffers */
1865 zend_try {
1866 php_output_end_all();
1867 } zend_end_try();
1868
1869 /* 4. Reset max_execution_time (no longer executing php code after response sent) */
1870 zend_try {
1871 zend_unset_timeout();
1872 } zend_end_try();
1873
1874 /* 5. Call all extensions RSHUTDOWN functions */
1875 if (PG(modules_activated)) {
1876 zend_deactivate_modules();
1877 }
1878
1879 /* 6. Shutdown output layer (send the set HTTP headers, cleanup output handlers, etc.) */
1880 zend_try {
1881 php_output_deactivate();
1882 } zend_end_try();
1883
1884 /* 7. Free shutdown functions */
1885 if (PG(modules_activated)) {
1886 php_free_shutdown_functions();
1887 }
1888
1889 /* 8. Destroy super-globals */
1890 zend_try {
1891 int i;
1892
1893 for (i=0; i<NUM_TRACK_VARS; i++) {
1894 zval_ptr_dtor(&PG(http_globals)[i]);
1895 }
1896 } zend_end_try();
1897
1898 /* 9. Shutdown scanner/executor/compiler and restore ini entries */
1899 zend_deactivate();
1900
1901 /* 10. free request-bound globals */
1902 php_free_request_globals();
1903
1904 /* 11. Call all extensions post-RSHUTDOWN functions */
1905 zend_try {
1906 zend_post_deactivate_modules();
1907 } zend_end_try();
1908
1909 /* 12. SAPI related shutdown*/
1910 zend_try {
1911 sapi_deactivate_module();
1912 } zend_end_try();
1913 /* free SAPI stuff */
1914 sapi_deactivate_destroy();
1915
1916 /* 13. free virtual CWD memory */
1917 virtual_cwd_deactivate();
1918
1919 /* 14. Destroy stream hashes */
1920 zend_try {
1921 php_shutdown_stream_hashes();
1922 } zend_end_try();
1923
1924 /* 15. Free Willy (here be crashes) */
1925 zend_arena_destroy(CG(arena));
1926 zend_interned_strings_deactivate();
1927 zend_try {
1928 shutdown_memory_manager(CG(unclean_shutdown) || !report_memleaks, 0);
1929 } zend_end_try();
1930
1931 /* Reset memory limit, as the reset during INI_STAGE_DEACTIVATE may have failed.
1932 * At this point, no memory beyond a single chunk should be in use. */
1933 zend_set_memory_limit(PG(memory_limit));
1934
1935 /* 16. Deactivate Zend signals */
1936 #ifdef ZEND_SIGNALS
1937 zend_signal_deactivate();
1938 #endif
1939
1940 #ifdef PHP_WIN32
1941 if (PG(com_initialized)) {
1942 CoUninitialize();
1943 PG(com_initialized) = 0;
1944 }
1945 #endif
1946
1947 #ifdef HAVE_DTRACE
1948 DTRACE_REQUEST_SHUTDOWN(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), (char *)SAFE_FILENAME(SG(request_info).request_method));
1949 #endif /* HAVE_DTRACE */
1950 }
1951 /* }}} */
1952
1953 /* {{{ php_com_initialize */
php_com_initialize(void)1954 PHPAPI void php_com_initialize(void)
1955 {
1956 #ifdef PHP_WIN32
1957 if (!PG(com_initialized)) {
1958 if (CoInitialize(NULL) == S_OK) {
1959 PG(com_initialized) = 1;
1960 }
1961 }
1962 #endif
1963 }
1964 /* }}} */
1965
1966 #ifdef ZTS
1967 /* {{{ core_globals_ctor */
core_globals_ctor(php_core_globals * core_globals)1968 static void core_globals_ctor(php_core_globals *core_globals)
1969 {
1970 memset(core_globals, 0, sizeof(*core_globals));
1971 php_startup_ticks();
1972 }
1973 /* }}} */
1974 #endif
1975
1976 /* {{{ core_globals_dtor */
core_globals_dtor(php_core_globals * core_globals)1977 static void core_globals_dtor(php_core_globals *core_globals)
1978 {
1979 /* These should have been freed earlier. */
1980 ZEND_ASSERT(!core_globals->last_error_message);
1981 ZEND_ASSERT(!core_globals->last_error_file);
1982
1983 if (core_globals->disable_classes) {
1984 free(core_globals->disable_classes);
1985 }
1986 if (core_globals->php_binary) {
1987 free(core_globals->php_binary);
1988 }
1989
1990 php_shutdown_ticks(core_globals);
1991 }
1992 /* }}} */
1993
PHP_MINFO_FUNCTION(php_core)1994 PHP_MINFO_FUNCTION(php_core) { /* {{{ */
1995 php_info_print_table_start();
1996 php_info_print_table_row(2, "PHP Version", PHP_VERSION);
1997 php_info_print_table_end();
1998 DISPLAY_INI_ENTRIES();
1999 }
2000 /* }}} */
2001
2002 /* {{{ php_register_extensions */
php_register_extensions(zend_module_entry * const * ptr,int count)2003 zend_result php_register_extensions(zend_module_entry * const * ptr, int count)
2004 {
2005 zend_module_entry * const * end = ptr + count;
2006
2007 while (ptr < end) {
2008 if (*ptr) {
2009 if (zend_register_internal_module(*ptr)==NULL) {
2010 return FAILURE;
2011 }
2012 }
2013 ptr++;
2014 }
2015 return SUCCESS;
2016 }
2017
2018 #ifdef PHP_WIN32
2019 static _invalid_parameter_handler old_invalid_parameter_handler;
2020
dummy_invalid_parameter_handler(const wchar_t * expression,const wchar_t * function,const wchar_t * file,unsigned int line,uintptr_t pReserved)2021 void dummy_invalid_parameter_handler(
2022 const wchar_t *expression,
2023 const wchar_t *function,
2024 const wchar_t *file,
2025 unsigned int line,
2026 uintptr_t pReserved)
2027 {
2028 static int called = 0;
2029 char buf[1024];
2030 int len;
2031
2032 if (!called) {
2033 if(PG(windows_show_crt_warning)) {
2034 called = 1;
2035 if (function) {
2036 if (file) {
2037 len = _snprintf(buf, sizeof(buf)-1, "Invalid parameter detected in CRT function '%ws' (%ws:%u)", function, file, line);
2038 } else {
2039 len = _snprintf(buf, sizeof(buf)-1, "Invalid parameter detected in CRT function '%ws'", function);
2040 }
2041 } else {
2042 len = _snprintf(buf, sizeof(buf)-1, "Invalid CRT parameter detected (function not known)");
2043 }
2044 zend_error(E_WARNING, "%s", buf);
2045 called = 0;
2046 }
2047 }
2048 }
2049 #endif
2050
2051 /* {{{ php_module_startup */
php_module_startup(sapi_module_struct * sf,zend_module_entry * additional_module)2052 zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_module)
2053 {
2054 zend_utility_functions zuf;
2055 zend_utility_values zuv;
2056 zend_result retval = SUCCESS;
2057 int module_number = 0;
2058 zend_module_entry *module;
2059
2060 #ifdef PHP_WIN32
2061 WORD wVersionRequested = MAKEWORD(2, 0);
2062 WSADATA wsaData;
2063
2064 old_invalid_parameter_handler =
2065 _set_invalid_parameter_handler(dummy_invalid_parameter_handler);
2066 if (old_invalid_parameter_handler != NULL) {
2067 _set_invalid_parameter_handler(old_invalid_parameter_handler);
2068 }
2069
2070 /* Disable the message box for assertions.*/
2071 _CrtSetReportMode(_CRT_ASSERT, 0);
2072 #endif
2073
2074 #ifdef ZTS
2075 (void)ts_resource(0);
2076 #endif
2077
2078 #ifdef PHP_WIN32
2079 if (!php_win32_init_random_bytes()) {
2080 fprintf(stderr, "\ncrypt algorithm provider initialization failed\n");
2081 return FAILURE;
2082 }
2083 #endif
2084
2085 module_shutdown = false;
2086 module_startup = true;
2087 sapi_initialize_empty_request();
2088 sapi_activate();
2089
2090 if (module_initialized) {
2091 return SUCCESS;
2092 }
2093
2094 sapi_module = *sf;
2095
2096 php_output_startup();
2097
2098 #ifdef ZTS
2099 ts_allocate_fast_id(&core_globals_id, &core_globals_offset, sizeof(php_core_globals), (ts_allocate_ctor) core_globals_ctor, (ts_allocate_dtor) core_globals_dtor);
2100 #ifdef PHP_WIN32
2101 ts_allocate_id(&php_win32_core_globals_id, sizeof(php_win32_core_globals), (ts_allocate_ctor) php_win32_core_globals_ctor, (ts_allocate_dtor) php_win32_core_globals_dtor);
2102 #endif
2103 #else
2104 memset(&core_globals, 0, sizeof(core_globals));
2105 php_startup_ticks();
2106 #endif
2107 gc_globals_ctor();
2108
2109 zuf.error_function = php_error_cb;
2110 zuf.printf_function = php_printf;
2111 zuf.write_function = php_output_write;
2112 zuf.fopen_function = php_fopen_wrapper_for_zend;
2113 zuf.message_handler = php_message_handler_for_zend;
2114 zuf.get_configuration_directive = php_get_configuration_directive_for_zend;
2115 zuf.ticks_function = php_run_ticks;
2116 zuf.on_timeout = php_on_timeout;
2117 zuf.stream_open_function = php_stream_open_for_zend;
2118 zuf.printf_to_smart_string_function = php_printf_to_smart_string;
2119 zuf.printf_to_smart_str_function = php_printf_to_smart_str;
2120 zuf.getenv_function = sapi_getenv;
2121 zuf.resolve_path_function = php_resolve_path_for_zend;
2122 zend_startup(&zuf);
2123 zend_reset_lc_ctype_locale();
2124 zend_update_current_locale();
2125
2126 zend_observer_startup();
2127 #if ZEND_DEBUG
2128 zend_observer_error_register(report_zend_debug_error_notify_cb);
2129 #endif
2130
2131 #if HAVE_TZSET
2132 tzset();
2133 #endif
2134
2135 #ifdef PHP_WIN32
2136 char *img_err;
2137 if (!php_win32_crt_compatible(&img_err)) {
2138 php_error(E_CORE_WARNING, img_err);
2139 efree(img_err);
2140 return FAILURE;
2141 }
2142
2143 /* start up winsock services */
2144 if (WSAStartup(wVersionRequested, &wsaData) != 0) {
2145 fprintf(stderr, "\nwinsock.dll unusable. %d\n", WSAGetLastError());
2146 return FAILURE;
2147 }
2148 php_win32_signal_ctrl_handler_init();
2149 #endif
2150
2151 le_index_ptr = zend_register_list_destructors_ex(NULL, NULL, "index pointer", 0);
2152
2153 php_binary_init();
2154 register_main_symbols(module_number);
2155
2156 /* this will read in php.ini, set up the configuration parameters,
2157 load zend extensions and register php function extensions
2158 to be loaded later */
2159 zend_stream_init();
2160 if (php_init_config() == FAILURE) {
2161 return FAILURE;
2162 }
2163 zend_stream_shutdown();
2164
2165 /* Register PHP core ini entries */
2166 zend_register_ini_entries_ex(ini_entries, module_number, MODULE_PERSISTENT);
2167
2168 /* Register Zend ini entries */
2169 zend_register_standard_ini_entries();
2170
2171 #ifdef ZEND_WIN32
2172 /* Until the current ini values was setup, the current cp is 65001.
2173 If the actual ini values are different, some stuff needs to be updated.
2174 It concerns at least main_cwd_state and there might be more. As we're
2175 still in the startup phase, lets use the chance and reinit the relevant
2176 item according to the current codepage. Still, if ini_set() is used
2177 later on, a more intelligent way to update such stuff is needed.
2178 Startup/shutdown routines could involve touching globals and thus
2179 can't always be used on demand. */
2180 if (!php_win32_cp_use_unicode()) {
2181 virtual_cwd_main_cwd_init(1);
2182 }
2183 #endif
2184
2185 /* Disable realpath cache if an open_basedir is set */
2186 if (PG(open_basedir) && *PG(open_basedir)) {
2187 CWDG(realpath_cache_size_limit) = 0;
2188 }
2189
2190 PG(have_called_openlog) = 0;
2191
2192 /* initialize stream wrappers registry
2193 * (this uses configuration parameters from php.ini)
2194 */
2195 if (php_init_stream_wrappers(module_number) == FAILURE) {
2196 fprintf(stderr, "PHP: Unable to initialize stream url wrappers.\n");
2197 return FAILURE;
2198 }
2199
2200 zuv.html_errors = 1;
2201 php_startup_auto_globals();
2202 zend_set_utility_values(&zuv);
2203 php_startup_sapi_content_types();
2204
2205 /* Begin to fingerprint the process state */
2206 zend_startup_system_id();
2207
2208 /* startup extensions statically compiled in */
2209 if (php_register_internal_extensions_func() == FAILURE) {
2210 fprintf(stderr, "Unable to start builtin modules\n");
2211 return FAILURE;
2212 }
2213
2214 /* start additional PHP extensions */
2215 if (additional_module && (zend_register_internal_module(additional_module) == NULL)) {
2216 return FAILURE;
2217 }
2218
2219 /* load and startup extensions compiled as shared objects (aka DLLs)
2220 as requested by php.ini entries
2221 these are loaded after initialization of internal extensions
2222 as extensions *might* rely on things from ext/standard
2223 which is always an internal extension and to be initialized
2224 ahead of all other internals
2225 */
2226 php_ini_register_extensions();
2227 zend_startup_modules();
2228
2229 /* start Zend extensions */
2230 zend_startup_extensions();
2231
2232 zend_collect_module_handlers();
2233
2234 /* register additional functions */
2235 if (sapi_module.additional_functions) {
2236 if ((module = zend_hash_str_find_ptr(&module_registry, "standard", sizeof("standard")-1)) != NULL) {
2237 EG(current_module) = module;
2238 zend_register_functions(NULL, sapi_module.additional_functions, NULL, MODULE_PERSISTENT);
2239 EG(current_module) = NULL;
2240 }
2241 }
2242
2243 /* disable certain classes and functions as requested by php.ini */
2244 zend_disable_functions(INI_STR("disable_functions"));
2245 php_disable_classes();
2246
2247 /* make core report what it should */
2248 if ((module = zend_hash_str_find_ptr(&module_registry, "core", sizeof("core")-1)) != NULL) {
2249 module->version = PHP_VERSION;
2250 module->info_func = PHP_MINFO(php_core);
2251 }
2252
2253 /* freeze the list of observer fcall_init handlers */
2254 zend_observer_post_startup();
2255
2256 /* Extensions that add engine hooks after this point do so at their own peril */
2257 zend_finalize_system_id();
2258
2259 module_initialized = true;
2260
2261 if (zend_post_startup() != SUCCESS) {
2262 return FAILURE;
2263 }
2264
2265 /* Check for deprecated directives */
2266 /* NOTE: If you add anything here, remember to add it to build/Makefile.global! */
2267 {
2268 struct {
2269 const long error_level;
2270 const char *phrase;
2271 const char *directives[18]; /* Remember to change this if the number of directives change */
2272 } directives[2] = {
2273 {
2274 E_DEPRECATED,
2275 "Directive '%s' is deprecated",
2276 {
2277 "allow_url_include",
2278 NULL
2279 }
2280 },
2281 {
2282 E_CORE_ERROR,
2283 "Directive '%s' is no longer available in PHP",
2284 {
2285 "allow_call_time_pass_reference",
2286 "asp_tags",
2287 "define_syslog_variables",
2288 "highlight.bg",
2289 "magic_quotes_gpc",
2290 "magic_quotes_runtime",
2291 "magic_quotes_sybase",
2292 "register_globals",
2293 "register_long_arrays",
2294 "safe_mode",
2295 "safe_mode_gid",
2296 "safe_mode_include_dir",
2297 "safe_mode_exec_dir",
2298 "safe_mode_allowed_env_vars",
2299 "safe_mode_protected_env_vars",
2300 "zend.ze1_compatibility_mode",
2301 "track_errors",
2302 NULL
2303 }
2304 }
2305 };
2306
2307 unsigned int i;
2308
2309 zend_try {
2310 /* 2 = Count of deprecation structs */
2311 for (i = 0; i < 2; i++) {
2312 const char **p = directives[i].directives;
2313
2314 while(*p) {
2315 zend_long value;
2316
2317 if (cfg_get_long((char*)*p, &value) == SUCCESS && value) {
2318 zend_error(directives[i].error_level, directives[i].phrase, *p);
2319 }
2320
2321 ++p;
2322 }
2323 }
2324 } zend_catch {
2325 retval = FAILURE;
2326 } zend_end_try();
2327 }
2328
2329 virtual_cwd_deactivate();
2330
2331 sapi_deactivate();
2332 module_startup = false;
2333
2334 /* Don't leak errors from startup into the per-request phase. */
2335 clear_last_error();
2336 shutdown_memory_manager(1, 0);
2337 virtual_cwd_activate();
2338
2339 zend_interned_strings_switch_storage(1);
2340
2341 #if ZEND_RC_DEBUG
2342 if (retval == SUCCESS) {
2343 zend_rc_debug = 1;
2344 }
2345 #endif
2346
2347 /* we're done */
2348 return retval;
2349 }
2350 /* }}} */
2351
2352 /* {{{ php_module_shutdown_wrapper */
php_module_shutdown_wrapper(sapi_module_struct * sapi_globals)2353 int php_module_shutdown_wrapper(sapi_module_struct *sapi_globals)
2354 {
2355 php_module_shutdown();
2356 return SUCCESS;
2357 }
2358 /* }}} */
2359
2360 /* {{{ php_module_shutdown */
php_module_shutdown(void)2361 void php_module_shutdown(void)
2362 {
2363 int module_number=0;
2364
2365 module_shutdown = true;
2366
2367 if (!module_initialized) {
2368 return;
2369 }
2370
2371 zend_interned_strings_switch_storage(0);
2372
2373 #if ZEND_RC_DEBUG
2374 zend_rc_debug = 0;
2375 #endif
2376
2377 #ifdef PHP_WIN32
2378 (void)php_win32_shutdown_random_bytes();
2379 php_win32_signal_ctrl_handler_shutdown();
2380 #endif
2381
2382 sapi_flush();
2383
2384 zend_shutdown();
2385
2386 #ifdef PHP_WIN32
2387 /*close winsock */
2388 WSACleanup();
2389 #endif
2390
2391 /* Destroys filter & transport registries too */
2392 php_shutdown_stream_wrappers(module_number);
2393
2394 zend_unregister_ini_entries_ex(module_number, MODULE_PERSISTENT);
2395
2396 /* close down the ini config */
2397 php_shutdown_config();
2398 clear_last_error();
2399
2400 #ifndef ZTS
2401 zend_ini_shutdown();
2402 shutdown_memory_manager(CG(unclean_shutdown), 1);
2403 #else
2404 zend_ini_global_shutdown();
2405 #endif
2406
2407 php_output_shutdown();
2408
2409 #ifndef ZTS
2410 zend_interned_strings_dtor();
2411 #endif
2412
2413 if (zend_post_shutdown_cb) {
2414 void (*cb)(void) = zend_post_shutdown_cb;
2415
2416 zend_post_shutdown_cb = NULL;
2417 cb();
2418 }
2419
2420 module_initialized = false;
2421
2422 #ifndef ZTS
2423 core_globals_dtor(&core_globals);
2424 gc_globals_dtor();
2425 #else
2426 ts_free_id(core_globals_id);
2427 #endif
2428
2429 #ifdef PHP_WIN32
2430 if (old_invalid_parameter_handler == NULL) {
2431 _set_invalid_parameter_handler(old_invalid_parameter_handler);
2432 }
2433 #endif
2434
2435 zend_observer_shutdown();
2436 }
2437 /* }}} */
2438
php_execute_script_ex(zend_file_handle * primary_file,zval * retval)2439 PHPAPI bool php_execute_script_ex(zend_file_handle *primary_file, zval *retval)
2440 {
2441 zend_file_handle *prepend_file_p = NULL, *append_file_p = NULL;
2442 zend_file_handle prepend_file, append_file;
2443 #ifdef HAVE_BROKEN_GETCWD
2444 volatile int old_cwd_fd = -1;
2445 #else
2446 char *old_cwd;
2447 ALLOCA_FLAG(use_heap)
2448 #endif
2449 bool result = true;
2450
2451 #ifndef HAVE_BROKEN_GETCWD
2452 # define OLD_CWD_SIZE 4096
2453 old_cwd = do_alloca(OLD_CWD_SIZE, use_heap);
2454 old_cwd[0] = '\0';
2455 #endif
2456
2457 zend_try {
2458 char realfile[MAXPATHLEN];
2459
2460 #ifdef PHP_WIN32
2461 if(primary_file->filename) {
2462 UpdateIniFromRegistry(ZSTR_VAL(primary_file->filename));
2463 }
2464 #endif
2465
2466 PG(during_request_startup) = 0;
2467
2468 if (primary_file->filename && !(SG(options) & SAPI_OPTION_NO_CHDIR)) {
2469 #ifdef HAVE_BROKEN_GETCWD
2470 /* this looks nasty to me */
2471 old_cwd_fd = open(".", 0);
2472 #else
2473 php_ignore_value(VCWD_GETCWD(old_cwd, OLD_CWD_SIZE-1));
2474 #endif
2475 VCWD_CHDIR_FILE(ZSTR_VAL(primary_file->filename));
2476 }
2477
2478 /* Only lookup the real file path and add it to the included_files list if already opened
2479 * otherwise it will get opened and added to the included_files list in zend_execute_scripts
2480 */
2481 if (primary_file->filename &&
2482 !zend_string_equals_literal(primary_file->filename, "Standard input code") &&
2483 primary_file->opened_path == NULL &&
2484 primary_file->type != ZEND_HANDLE_FILENAME
2485 ) {
2486 if (expand_filepath(ZSTR_VAL(primary_file->filename), realfile)) {
2487 primary_file->opened_path = zend_string_init(realfile, strlen(realfile), 0);
2488 zend_hash_add_empty_element(&EG(included_files), primary_file->opened_path);
2489 }
2490 }
2491
2492 if (PG(auto_prepend_file) && PG(auto_prepend_file)[0]) {
2493 zend_stream_init_filename(&prepend_file, PG(auto_prepend_file));
2494 prepend_file_p = &prepend_file;
2495 }
2496
2497 if (PG(auto_append_file) && PG(auto_append_file)[0]) {
2498 zend_stream_init_filename(&append_file, PG(auto_append_file));
2499 append_file_p = &append_file;
2500 }
2501 if (PG(max_input_time) != -1) {
2502 #ifdef PHP_WIN32
2503 zend_unset_timeout();
2504 #endif
2505 zend_set_timeout(INI_INT("max_execution_time"), 0);
2506 }
2507
2508 if (prepend_file_p && result) {
2509 result = zend_execute_script(ZEND_REQUIRE, NULL, prepend_file_p) == SUCCESS;
2510 }
2511 if (result) {
2512 result = zend_execute_script(ZEND_REQUIRE, retval, primary_file) == SUCCESS;
2513 }
2514 if (append_file_p && result) {
2515 result = zend_execute_script(ZEND_REQUIRE, NULL, append_file_p) == SUCCESS;
2516 }
2517 } zend_catch {
2518 result = false;
2519 } zend_end_try();
2520
2521 if (prepend_file_p) {
2522 zend_destroy_file_handle(prepend_file_p);
2523 }
2524
2525 if (append_file_p) {
2526 zend_destroy_file_handle(append_file_p);
2527 }
2528
2529 if (EG(exception)) {
2530 zend_try {
2531 zend_exception_error(EG(exception), E_ERROR);
2532 } zend_end_try();
2533 }
2534
2535 #ifdef HAVE_BROKEN_GETCWD
2536 if (old_cwd_fd != -1) {
2537 fchdir(old_cwd_fd);
2538 close(old_cwd_fd);
2539 }
2540 #else
2541 if (old_cwd[0] != '\0') {
2542 php_ignore_value(VCWD_CHDIR(old_cwd));
2543 }
2544 free_alloca(old_cwd, use_heap);
2545 #endif
2546 return result;
2547 }
2548
2549 /* {{{ php_execute_script */
php_execute_script(zend_file_handle * primary_file)2550 PHPAPI bool php_execute_script(zend_file_handle *primary_file)
2551 {
2552 return php_execute_script_ex(primary_file, NULL);
2553 }
2554 /* }}} */
2555
2556 /* {{{ php_execute_simple_script */
php_execute_simple_script(zend_file_handle * primary_file,zval * ret)2557 PHPAPI int php_execute_simple_script(zend_file_handle *primary_file, zval *ret)
2558 {
2559 char *old_cwd;
2560 ALLOCA_FLAG(use_heap)
2561
2562 EG(exit_status) = 0;
2563 #define OLD_CWD_SIZE 4096
2564 old_cwd = do_alloca(OLD_CWD_SIZE, use_heap);
2565 old_cwd[0] = '\0';
2566
2567 zend_try {
2568 #ifdef PHP_WIN32
2569 if(primary_file->filename) {
2570 UpdateIniFromRegistry(ZSTR_VAL(primary_file->filename));
2571 }
2572 #endif
2573
2574 PG(during_request_startup) = 0;
2575
2576 if (primary_file->filename && !(SG(options) & SAPI_OPTION_NO_CHDIR)) {
2577 php_ignore_value(VCWD_GETCWD(old_cwd, OLD_CWD_SIZE-1));
2578 VCWD_CHDIR_FILE(ZSTR_VAL(primary_file->filename));
2579 }
2580 zend_execute_scripts(ZEND_REQUIRE, ret, 1, primary_file);
2581 } zend_end_try();
2582
2583 if (old_cwd[0] != '\0') {
2584 php_ignore_value(VCWD_CHDIR(old_cwd));
2585 }
2586
2587 free_alloca(old_cwd, use_heap);
2588 return EG(exit_status);
2589 }
2590 /* }}} */
2591
2592 /* {{{ php_handle_aborted_connection */
php_handle_aborted_connection(void)2593 PHPAPI void php_handle_aborted_connection(void)
2594 {
2595
2596 PG(connection_status) = PHP_CONNECTION_ABORTED;
2597 php_output_set_status(PHP_OUTPUT_DISABLED);
2598
2599 if (!PG(ignore_user_abort)) {
2600 zend_bailout();
2601 }
2602 }
2603 /* }}} */
2604
2605 /* {{{ php_handle_auth_data */
php_handle_auth_data(const char * auth)2606 PHPAPI int php_handle_auth_data(const char *auth)
2607 {
2608 int ret = -1;
2609 size_t auth_len = auth != NULL ? strlen(auth) : 0;
2610
2611 if (auth && auth_len > 0 && zend_binary_strncasecmp(auth, auth_len, "Basic ", sizeof("Basic ")-1, sizeof("Basic ")-1) == 0) {
2612 char *pass;
2613 zend_string *user;
2614
2615 user = php_base64_decode((const unsigned char*)auth + 6, auth_len - 6);
2616 if (user) {
2617 pass = strchr(ZSTR_VAL(user), ':');
2618 if (pass) {
2619 *pass++ = '\0';
2620 SG(request_info).auth_user = estrndup(ZSTR_VAL(user), ZSTR_LEN(user));
2621 SG(request_info).auth_password = estrdup(pass);
2622 ret = 0;
2623 }
2624 zend_string_free(user);
2625 }
2626 }
2627
2628 if (ret == -1) {
2629 SG(request_info).auth_user = SG(request_info).auth_password = NULL;
2630 } else {
2631 SG(request_info).auth_digest = NULL;
2632 }
2633
2634 if (ret == -1 && auth && auth_len > 0 && zend_binary_strncasecmp(auth, auth_len, "Digest ", sizeof("Digest ")-1, sizeof("Digest ")-1) == 0) {
2635 SG(request_info).auth_digest = estrdup(auth + 7);
2636 ret = 0;
2637 }
2638
2639 if (ret == -1) {
2640 SG(request_info).auth_digest = NULL;
2641 }
2642
2643 return ret;
2644 }
2645 /* }}} */
2646
2647 /* {{{ php_lint_script */
php_lint_script(zend_file_handle * file)2648 PHPAPI zend_result php_lint_script(zend_file_handle *file)
2649 {
2650 zend_op_array *op_array;
2651 zend_result retval = FAILURE;
2652
2653 zend_try {
2654 op_array = zend_compile_file(file, ZEND_INCLUDE);
2655
2656 if (op_array) {
2657 destroy_op_array(op_array);
2658 efree(op_array);
2659 retval = SUCCESS;
2660 }
2661 } zend_end_try();
2662 if (EG(exception)) {
2663 zend_exception_error(EG(exception), E_ERROR);
2664 }
2665
2666 return retval;
2667 }
2668 /* }}} */
2669
2670 #ifdef ZTS
2671 /* {{{ php_reserve_tsrm_memory */
php_reserve_tsrm_memory(void)2672 PHPAPI void php_reserve_tsrm_memory(void)
2673 {
2674 tsrm_reserve(
2675 TSRM_ALIGNED_SIZE(sizeof(zend_compiler_globals)) +
2676 TSRM_ALIGNED_SIZE(sizeof(zend_executor_globals)) +
2677 TSRM_ALIGNED_SIZE(sizeof(zend_php_scanner_globals)) +
2678 TSRM_ALIGNED_SIZE(sizeof(zend_ini_scanner_globals)) +
2679 TSRM_ALIGNED_SIZE(sizeof(virtual_cwd_globals)) +
2680 #ifdef ZEND_SIGNALS
2681 TSRM_ALIGNED_SIZE(sizeof(zend_signal_globals_t)) +
2682 #endif
2683 TSRM_ALIGNED_SIZE(zend_mm_globals_size()) +
2684 TSRM_ALIGNED_SIZE(zend_gc_globals_size()) +
2685 TSRM_ALIGNED_SIZE(sizeof(php_core_globals)) +
2686 TSRM_ALIGNED_SIZE(sizeof(sapi_globals_struct))
2687 );
2688 }
2689 /* }}} */
2690
php_tsrm_startup_ex(int expected_threads)2691 PHPAPI bool php_tsrm_startup_ex(int expected_threads)
2692 {
2693 bool ret = tsrm_startup(expected_threads, 1, 0, NULL);
2694 php_reserve_tsrm_memory();
2695 (void)ts_resource(0);
2696 return ret;
2697 }
2698
2699 /* {{{ php_tsrm_startup */
php_tsrm_startup(void)2700 PHPAPI bool php_tsrm_startup(void)
2701 {
2702 return php_tsrm_startup_ex(1);
2703 }
2704 /* }}} */
2705 #endif
2706