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 /* Don't allow changing it in htaccess */
656 if (stage == PHP_INI_STAGE_HTACCESS) {
657 return FAILURE;
658 }
659 return SUCCESS;
660 }
661 /* }}} */
662
663 /* defined in browscap.c */
664 PHP_INI_MH(OnChangeBrowscap);
665
666
667 /* Need to be read from the environment (?):
668 * PHP_AUTO_PREPEND_FILE
669 * PHP_AUTO_APPEND_FILE
670 * PHP_DOCUMENT_ROOT
671 * PHP_USER_DIR
672 * PHP_INCLUDE_PATH
673 */
674
675 /* Windows use the internal mail */
676 #if defined(PHP_WIN32)
677 # define DEFAULT_SENDMAIL_PATH NULL
678 #else
679 # define DEFAULT_SENDMAIL_PATH PHP_PROG_SENDMAIL " -t -i"
680 #endif
681
682 /* {{{ PHP_INI */
683 PHP_INI_BEGIN()
684 PHP_INI_ENTRY_EX("highlight.comment", HL_COMMENT_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
685 PHP_INI_ENTRY_EX("highlight.default", HL_DEFAULT_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
686 PHP_INI_ENTRY_EX("highlight.html", HL_HTML_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
687 PHP_INI_ENTRY_EX("highlight.keyword", HL_KEYWORD_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
688 PHP_INI_ENTRY_EX("highlight.string", HL_STRING_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
689
690 STD_PHP_INI_ENTRY_EX("display_errors", "1", PHP_INI_ALL, OnUpdateDisplayErrors, display_errors, php_core_globals, core_globals, display_errors_mode)
691 STD_PHP_INI_BOOLEAN("display_startup_errors", "1", PHP_INI_ALL, OnUpdateBool, display_startup_errors, php_core_globals, core_globals)
692 STD_PHP_INI_BOOLEAN("enable_dl", "1", PHP_INI_SYSTEM, OnUpdateBool, enable_dl, php_core_globals, core_globals)
693 STD_PHP_INI_BOOLEAN("expose_php", "1", PHP_INI_SYSTEM, OnUpdateBool, expose_php, php_core_globals, core_globals)
694 STD_PHP_INI_ENTRY("docref_root", "", PHP_INI_ALL, OnUpdateString, docref_root, php_core_globals, core_globals)
695 STD_PHP_INI_ENTRY("docref_ext", "", PHP_INI_ALL, OnUpdateString, docref_ext, php_core_globals, core_globals)
696 STD_PHP_INI_BOOLEAN("html_errors", "1", PHP_INI_ALL, OnUpdateBool, html_errors, php_core_globals, core_globals)
697 STD_PHP_INI_BOOLEAN("xmlrpc_errors", "0", PHP_INI_SYSTEM, OnUpdateBool, xmlrpc_errors, php_core_globals, core_globals)
698 STD_PHP_INI_ENTRY("xmlrpc_error_number", "0", PHP_INI_ALL, OnUpdateLong, xmlrpc_error_number, php_core_globals, core_globals)
699 STD_PHP_INI_ENTRY("max_input_time", "-1", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, max_input_time, php_core_globals, core_globals)
700 STD_PHP_INI_BOOLEAN("ignore_user_abort", "0", PHP_INI_ALL, OnUpdateBool, ignore_user_abort, php_core_globals, core_globals)
701 STD_PHP_INI_BOOLEAN("implicit_flush", "0", PHP_INI_ALL, OnUpdateBool, implicit_flush, php_core_globals, core_globals)
702 STD_PHP_INI_BOOLEAN("log_errors", "0", PHP_INI_ALL, OnUpdateBool, log_errors, php_core_globals, core_globals)
703 STD_PHP_INI_BOOLEAN("ignore_repeated_errors", "0", PHP_INI_ALL, OnUpdateBool, ignore_repeated_errors, php_core_globals, core_globals)
704 STD_PHP_INI_BOOLEAN("ignore_repeated_source", "0", PHP_INI_ALL, OnUpdateBool, ignore_repeated_source, php_core_globals, core_globals)
705 STD_PHP_INI_BOOLEAN("report_memleaks", "1", PHP_INI_ALL, OnUpdateBool, report_memleaks, php_core_globals, core_globals)
706 STD_PHP_INI_BOOLEAN("report_zend_debug", "0", PHP_INI_ALL, OnUpdateBool, report_zend_debug, php_core_globals, core_globals)
707 STD_PHP_INI_ENTRY("output_buffering", "0", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateLong, output_buffering, php_core_globals, core_globals)
708 STD_PHP_INI_ENTRY("output_handler", NULL, PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateString, output_handler, php_core_globals, core_globals)
709 STD_PHP_INI_BOOLEAN("register_argc_argv", "1", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, register_argc_argv, php_core_globals, core_globals)
710 STD_PHP_INI_BOOLEAN("auto_globals_jit", "1", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, auto_globals_jit, php_core_globals, core_globals)
711 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)
712
713 STD_PHP_INI_ENTRY("unserialize_callback_func", NULL, PHP_INI_ALL, OnUpdateString, unserialize_callback_func, php_core_globals, core_globals)
714 STD_PHP_INI_ENTRY("serialize_precision", "-1", PHP_INI_ALL, OnSetSerializePrecision, serialize_precision, php_core_globals, core_globals)
715 STD_PHP_INI_ENTRY("arg_separator.output", "&", PHP_INI_ALL, OnUpdateStringUnempty, arg_separator.output, php_core_globals, core_globals)
716 STD_PHP_INI_ENTRY("arg_separator.input", "&", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateStringUnempty, arg_separator.input, php_core_globals, core_globals)
717
718 STD_PHP_INI_ENTRY("auto_append_file", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateString, auto_append_file, php_core_globals, core_globals)
719 STD_PHP_INI_ENTRY("auto_prepend_file", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateString, auto_prepend_file, php_core_globals, core_globals)
720 STD_PHP_INI_ENTRY("doc_root", NULL, PHP_INI_SYSTEM, OnUpdateStringUnempty, doc_root, php_core_globals, core_globals)
721 STD_PHP_INI_ENTRY("default_charset", PHP_DEFAULT_CHARSET, PHP_INI_ALL, OnUpdateDefaultCharset, default_charset, sapi_globals_struct, sapi_globals)
722 STD_PHP_INI_ENTRY("default_mimetype", SAPI_DEFAULT_MIMETYPE, PHP_INI_ALL, OnUpdateDefaultMimeTye, default_mimetype, sapi_globals_struct, sapi_globals)
723 STD_PHP_INI_ENTRY("internal_encoding", NULL, PHP_INI_ALL, OnUpdateInternalEncoding, internal_encoding, php_core_globals, core_globals)
724 STD_PHP_INI_ENTRY("input_encoding", NULL, PHP_INI_ALL, OnUpdateInputEncoding, input_encoding, php_core_globals, core_globals)
725 STD_PHP_INI_ENTRY("output_encoding", NULL, PHP_INI_ALL, OnUpdateOutputEncoding, output_encoding, php_core_globals, core_globals)
726 STD_PHP_INI_ENTRY("error_log", NULL, PHP_INI_ALL, OnUpdateErrorLog, error_log, php_core_globals, core_globals)
727 STD_PHP_INI_ENTRY("error_log_mode", "0644", PHP_INI_ALL, OnUpdateLong, error_log_mode, php_core_globals, core_globals)
728 STD_PHP_INI_ENTRY("extension_dir", PHP_EXTENSION_DIR, PHP_INI_SYSTEM, OnUpdateStringUnempty, extension_dir, php_core_globals, core_globals)
729 STD_PHP_INI_ENTRY("sys_temp_dir", NULL, PHP_INI_SYSTEM, OnUpdateStringUnempty, sys_temp_dir, php_core_globals, core_globals)
730 STD_PHP_INI_ENTRY("include_path", PHP_INCLUDE_PATH, PHP_INI_ALL, OnUpdateStringUnempty, include_path, php_core_globals, core_globals)
731 PHP_INI_ENTRY("max_execution_time", "30", PHP_INI_ALL, OnUpdateTimeout)
732 STD_PHP_INI_ENTRY("open_basedir", NULL, PHP_INI_ALL, OnUpdateBaseDir, open_basedir, php_core_globals, core_globals)
733
734 STD_PHP_INI_BOOLEAN("file_uploads", "1", PHP_INI_SYSTEM, OnUpdateBool, file_uploads, php_core_globals, core_globals)
735 STD_PHP_INI_ENTRY("upload_max_filesize", "2M", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, upload_max_filesize, php_core_globals, core_globals)
736 STD_PHP_INI_ENTRY("post_max_size", "8M", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, post_max_size, sapi_globals_struct,sapi_globals)
737 STD_PHP_INI_ENTRY("upload_tmp_dir", NULL, PHP_INI_SYSTEM, OnUpdateStringUnempty, upload_tmp_dir, php_core_globals, core_globals)
738 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)
739 STD_PHP_INI_ENTRY("max_input_vars", "1000", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLongGEZero, max_input_vars, php_core_globals, core_globals)
740
741 STD_PHP_INI_ENTRY("user_dir", NULL, PHP_INI_SYSTEM, OnUpdateString, user_dir, php_core_globals, core_globals)
742 STD_PHP_INI_ENTRY("variables_order", "EGPCS", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateStringUnempty, variables_order, php_core_globals, core_globals)
743 STD_PHP_INI_ENTRY("request_order", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateString, request_order, php_core_globals, core_globals)
744
745 STD_PHP_INI_ENTRY("error_append_string", NULL, PHP_INI_ALL, OnUpdateString, error_append_string, php_core_globals, core_globals)
746 STD_PHP_INI_ENTRY("error_prepend_string", NULL, PHP_INI_ALL, OnUpdateString, error_prepend_string, php_core_globals, core_globals)
747
748 PHP_INI_ENTRY("SMTP", "localhost",PHP_INI_ALL, NULL)
749 PHP_INI_ENTRY("smtp_port", "25", PHP_INI_ALL, NULL)
750 STD_PHP_INI_BOOLEAN("mail.add_x_header", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, mail_x_header, php_core_globals, core_globals)
751 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)
752 STD_PHP_INI_ENTRY("mail.log", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateMailLog, mail_log, php_core_globals, core_globals)
753 PHP_INI_ENTRY("browscap", NULL, PHP_INI_SYSTEM, OnChangeBrowscap)
754 PHP_INI_ENTRY("memory_limit", "128M", PHP_INI_ALL, OnChangeMemoryLimit)
755 PHP_INI_ENTRY("precision", "14", PHP_INI_ALL, OnSetPrecision)
756 PHP_INI_ENTRY("sendmail_from", NULL, PHP_INI_ALL, NULL)
757 PHP_INI_ENTRY("sendmail_path", DEFAULT_SENDMAIL_PATH, PHP_INI_SYSTEM, NULL)
758 PHP_INI_ENTRY("mail.force_extra_parameters",NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnChangeMailForceExtra)
759 PHP_INI_ENTRY("disable_functions", "", PHP_INI_SYSTEM, NULL)
760 PHP_INI_ENTRY("disable_classes", "", PHP_INI_SYSTEM, NULL)
761 PHP_INI_ENTRY("max_file_uploads", "20", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL)
762 PHP_INI_ENTRY("max_multipart_body_parts", "-1", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL)
763
764 STD_PHP_INI_BOOLEAN("allow_url_fopen", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_url_fopen, php_core_globals, core_globals)
765 STD_PHP_INI_BOOLEAN("allow_url_include", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_url_include, php_core_globals, core_globals)
766 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)
767
768 STD_PHP_INI_ENTRY("realpath_cache_size", "4096K", PHP_INI_SYSTEM, OnUpdateLong, realpath_cache_size_limit, virtual_cwd_globals, cwd_globals)
769 STD_PHP_INI_ENTRY("realpath_cache_ttl", "120", PHP_INI_SYSTEM, OnUpdateLong, realpath_cache_ttl, virtual_cwd_globals, cwd_globals)
770
771 STD_PHP_INI_ENTRY("user_ini.filename", ".user.ini", PHP_INI_SYSTEM, OnUpdateString, user_ini_filename, php_core_globals, core_globals)
772 STD_PHP_INI_ENTRY("user_ini.cache_ttl", "300", PHP_INI_SYSTEM, OnUpdateLong, user_ini_cache_ttl, php_core_globals, core_globals)
773 STD_PHP_INI_ENTRY("hard_timeout", "2", PHP_INI_SYSTEM, OnUpdateLong, hard_timeout, zend_executor_globals, executor_globals)
774 #ifdef PHP_WIN32
775 STD_PHP_INI_BOOLEAN("windows.show_crt_warning", "0", PHP_INI_ALL, OnUpdateBool, windows_show_crt_warning, php_core_globals, core_globals)
776 #endif
777 STD_PHP_INI_ENTRY("syslog.facility", "LOG_USER", PHP_INI_SYSTEM, OnSetFacility, syslog_facility, php_core_globals, core_globals)
778 STD_PHP_INI_ENTRY("syslog.ident", "php", PHP_INI_SYSTEM, OnUpdateString, syslog_ident, php_core_globals, core_globals)
779 STD_PHP_INI_ENTRY("syslog.filter", "no-ctrl", PHP_INI_ALL, OnSetLogFilter, syslog_filter, php_core_globals, core_globals)
780 PHP_INI_END()
781 /* }}} */
782
783 /* True globals (no need for thread safety */
784 /* But don't make them a single int bitfield */
785 static bool module_initialized = false;
786 static bool module_startup = true;
787 static bool module_shutdown = false;
788
789 /* {{{ php_during_module_startup */
php_during_module_startup(void)790 PHPAPI bool php_during_module_startup(void)
791 {
792 return module_startup;
793 }
794 /* }}} */
795
796 /* {{{ php_during_module_shutdown */
php_during_module_shutdown(void)797 PHPAPI bool php_during_module_shutdown(void)
798 {
799 return module_shutdown;
800 }
801 /* }}} */
802
803 /* {{{ php_get_module_initialized */
php_get_module_initialized(void)804 PHPAPI bool php_get_module_initialized(void)
805 {
806 return module_initialized;
807 }
808 /* }}} */
809
810 /* {{{ php_log_err_with_severity */
php_log_err_with_severity(const char * log_message,int syslog_type_int)811 PHPAPI ZEND_COLD void php_log_err_with_severity(const char *log_message, int syslog_type_int)
812 {
813 int fd = -1;
814 time_t error_time;
815
816 if (PG(in_error_log)) {
817 /* prevent recursive invocation */
818 return;
819 }
820 PG(in_error_log) = 1;
821
822 /* Try to use the specified logging location. */
823 if (PG(error_log) != NULL) {
824 int error_log_mode;
825
826 #ifdef HAVE_SYSLOG_H
827 if (!strcmp(PG(error_log), "syslog")) {
828 php_syslog(syslog_type_int, "%s", log_message);
829 PG(in_error_log) = 0;
830 return;
831 }
832 #endif
833
834 error_log_mode = 0644;
835
836 if (PG(error_log_mode) > 0 && PG(error_log_mode) <= 0777) {
837 error_log_mode = PG(error_log_mode);
838 }
839
840 fd = VCWD_OPEN_MODE(PG(error_log), O_CREAT | O_APPEND | O_WRONLY, error_log_mode);
841 if (fd != -1) {
842 char *tmp;
843 size_t len;
844 zend_string *error_time_str;
845
846 time(&error_time);
847 #ifdef ZTS
848 if (!php_during_module_startup()) {
849 error_time_str = php_format_date("d-M-Y H:i:s e", 13, error_time, 1);
850 } else {
851 error_time_str = php_format_date("d-M-Y H:i:s e", 13, error_time, 0);
852 }
853 #else
854 error_time_str = php_format_date("d-M-Y H:i:s e", 13, error_time, 1);
855 #endif
856 len = spprintf(&tmp, 0, "[%s] %s%s", ZSTR_VAL(error_time_str), log_message, PHP_EOL);
857 #ifdef PHP_WIN32
858 php_flock(fd, LOCK_EX);
859 /* XXX should eventually write in a loop if len > UINT_MAX */
860 php_ignore_value(write(fd, tmp, (unsigned)len));
861 php_flock(fd, LOCK_UN);
862 #else
863 php_ignore_value(write(fd, tmp, len));
864 #endif
865 efree(tmp);
866 zend_string_free(error_time_str);
867 close(fd);
868 PG(in_error_log) = 0;
869 return;
870 }
871 }
872
873 /* Otherwise fall back to the default logging location, if we have one */
874
875 if (sapi_module.log_message) {
876 sapi_module.log_message(log_message, syslog_type_int);
877 }
878 PG(in_error_log) = 0;
879 }
880 /* }}} */
881
882 /* {{{ php_write
883 wrapper for modules to use PHPWRITE */
php_write(void * buf,size_t size)884 PHPAPI size_t php_write(void *buf, size_t size)
885 {
886 return PHPWRITE(buf, size);
887 }
888 /* }}} */
889
890 /* {{{ php_printf */
php_printf(const char * format,...)891 PHPAPI size_t php_printf(const char *format, ...)
892 {
893 va_list args;
894 size_t ret;
895 char *buffer;
896 size_t size;
897
898 va_start(args, format);
899 size = vspprintf(&buffer, 0, format, args);
900 ret = PHPWRITE(buffer, size);
901 efree(buffer);
902 va_end(args);
903
904 return ret;
905 }
906 /* }}} */
907
908 /* {{{ php_printf_unchecked */
php_printf_unchecked(const char * format,...)909 PHPAPI size_t php_printf_unchecked(const char *format, ...)
910 {
911 va_list args;
912 size_t ret;
913 char *buffer;
914 size_t size;
915
916 va_start(args, format);
917 size = vspprintf(&buffer, 0, format, args);
918 ret = PHPWRITE(buffer, size);
919 efree(buffer);
920 va_end(args);
921
922 return ret;
923 }
924 /* }}} */
925
escape_html(const char * buffer,size_t buffer_len)926 static zend_string *escape_html(const char *buffer, size_t buffer_len) {
927 zend_string *result = php_escape_html_entities_ex(
928 (const unsigned char *) buffer, buffer_len, 0, ENT_COMPAT,
929 /* charset_hint */ NULL, /* double_encode */ 1, /* quiet */ 1);
930 if (!result || ZSTR_LEN(result) == 0) {
931 /* Retry with substituting invalid chars on fail. */
932 result = php_escape_html_entities_ex(
933 (const unsigned char *) buffer, buffer_len, 0, ENT_COMPAT | ENT_HTML_SUBSTITUTE_ERRORS,
934 /* charset_hint */ NULL, /* double_encode */ 1, /* quiet */ 1);
935 }
936 return result;
937 }
938
939 /* {{{ php_verror */
940 /* php_verror is called from php_error_docref<n> functions.
941 * Its purpose is to unify error messages and automatically generate clickable
942 * html error messages if corresponding ini setting (html_errors) is activated.
943 * See: CODING_STANDARDS.md for details.
944 */
php_verror(const char * docref,const char * params,int type,const char * format,va_list args)945 PHPAPI ZEND_COLD void php_verror(const char *docref, const char *params, int type, const char *format, va_list args)
946 {
947 zend_string *replace_origin = NULL;
948 char *docref_buf = NULL, *target = NULL;
949 char *docref_target = "", *docref_root = "";
950 char *p;
951 const char *space = "";
952 const char *class_name = "";
953 const char *function;
954 int origin_len;
955 char *origin;
956 zend_string *message;
957 int is_function = 0;
958
959 /* get error text into buffer and escape for html if necessary */
960 zend_string *buffer = vstrpprintf(0, format, args);
961
962 if (PG(html_errors)) {
963 zend_string *replace_buffer = escape_html(ZSTR_VAL(buffer), ZSTR_LEN(buffer));
964 zend_string_free(buffer);
965
966 if (replace_buffer) {
967 buffer = replace_buffer;
968 } else {
969 buffer = zend_empty_string;
970 }
971 }
972
973 /* which function caused the problem if any at all */
974 if (php_during_module_startup()) {
975 function = "PHP Startup";
976 } else if (php_during_module_shutdown()) {
977 function = "PHP Shutdown";
978 } else if (PG(during_request_startup)) {
979 function = "PHP Request Startup";
980 } else if (EG(current_execute_data) &&
981 EG(current_execute_data)->func &&
982 ZEND_USER_CODE(EG(current_execute_data)->func->common.type) &&
983 EG(current_execute_data)->opline &&
984 EG(current_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL
985 ) {
986 switch (EG(current_execute_data)->opline->extended_value) {
987 case ZEND_EVAL:
988 function = "eval";
989 is_function = 1;
990 break;
991 case ZEND_INCLUDE:
992 function = "include";
993 is_function = 1;
994 break;
995 case ZEND_INCLUDE_ONCE:
996 function = "include_once";
997 is_function = 1;
998 break;
999 case ZEND_REQUIRE:
1000 function = "require";
1001 is_function = 1;
1002 break;
1003 case ZEND_REQUIRE_ONCE:
1004 function = "require_once";
1005 is_function = 1;
1006 break;
1007 default:
1008 function = "Unknown";
1009 }
1010 } else if ((function = get_active_function_name()) && strlen(function)) {
1011 is_function = 1;
1012 class_name = get_active_class_name(&space);
1013 } else if (EG(flags) & EG_FLAGS_IN_SHUTDOWN) {
1014 function = "PHP Request Shutdown";
1015 } else {
1016 function = "Unknown";
1017 }
1018
1019 /* if we still have memory then format the origin */
1020 if (is_function) {
1021 origin_len = (int)spprintf(&origin, 0, "%s%s%s(%s)", class_name, space, function, params);
1022 } else {
1023 origin_len = (int)spprintf(&origin, 0, "%s", function);
1024 }
1025
1026 if (PG(html_errors)) {
1027 replace_origin = escape_html(origin, origin_len);
1028 efree(origin);
1029 origin = ZSTR_VAL(replace_origin);
1030 }
1031
1032 /* origin and buffer available, so let's come up with the error message */
1033 if (docref && docref[0] == '#') {
1034 docref_target = strchr(docref, '#');
1035 docref = NULL;
1036 }
1037
1038 /* no docref given but function is known (the default) */
1039 if (!docref && is_function) {
1040 int doclen;
1041 while (*function == '_') {
1042 function++;
1043 }
1044 if (space[0] == '\0') {
1045 doclen = (int)spprintf(&docref_buf, 0, "function.%s", function);
1046 } else {
1047 doclen = (int)spprintf(&docref_buf, 0, "%s.%s", class_name, function);
1048 }
1049 while((p = strchr(docref_buf, '_')) != NULL) {
1050 *p = '-';
1051 }
1052 zend_str_tolower(docref_buf, doclen);
1053 docref = docref_buf;
1054 }
1055
1056 /* we have a docref for a function AND
1057 * - we show errors in html mode AND
1058 * - the user wants to see the links
1059 */
1060 if (docref && is_function && PG(html_errors) && strlen(PG(docref_root))) {
1061 if (strncmp(docref, "http://", 7)) {
1062 /* We don't have 'http://' so we use docref_root */
1063
1064 char *ref; /* temp copy for duplicated docref */
1065
1066 docref_root = PG(docref_root);
1067
1068 ref = estrdup(docref);
1069 if (docref_buf) {
1070 efree(docref_buf);
1071 }
1072 docref_buf = ref;
1073 /* strip of the target if any */
1074 p = strrchr(ref, '#');
1075 if (p) {
1076 target = estrdup(p);
1077 if (target) {
1078 docref_target = target;
1079 *p = '\0';
1080 }
1081 }
1082 /* add the extension if it is set in ini */
1083 if (PG(docref_ext) && strlen(PG(docref_ext))) {
1084 spprintf(&docref_buf, 0, "%s%s", ref, PG(docref_ext));
1085 efree(ref);
1086 }
1087 docref = docref_buf;
1088 }
1089 /* display html formatted or only show the additional links */
1090 if (PG(html_errors)) {
1091 message = zend_strpprintf_unchecked(0, "%s [<a href='%s%s%s'>%s</a>]: %S", origin, docref_root, docref, docref_target, docref, buffer);
1092 } else {
1093 message = zend_strpprintf_unchecked(0, "%s [%s%s%s]: %S", origin, docref_root, docref, docref_target, buffer);
1094 }
1095 if (target) {
1096 efree(target);
1097 }
1098 } else {
1099 message = zend_strpprintf_unchecked(0, "%s: %S", origin, buffer);
1100 }
1101 if (replace_origin) {
1102 zend_string_free(replace_origin);
1103 } else {
1104 efree(origin);
1105 }
1106 if (docref_buf) {
1107 efree(docref_buf);
1108 }
1109
1110 zend_string_free(buffer);
1111
1112 zend_error_zstr(type, message);
1113 zend_string_release(message);
1114 }
1115 /* }}} */
1116
1117 /* {{{ php_error_docref */
1118 /* Generate an error which links to docref or the php.net documentation if docref is NULL */
1119 #define php_error_docref_impl(docref, type, format) do {\
1120 va_list args; \
1121 va_start(args, format); \
1122 php_verror(docref, "", type, format, args); \
1123 va_end(args); \
1124 } while (0)
1125
php_error_docref(const char * docref,int type,const char * format,...)1126 PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format, ...)
1127 {
1128 php_error_docref_impl(docref, type, format);
1129 }
1130
php_error_docref_unchecked(const char * docref,int type,const char * format,...)1131 PHPAPI ZEND_COLD void php_error_docref_unchecked(const char *docref, int type, const char *format, ...)
1132 {
1133 php_error_docref_impl(docref, type, format);
1134 }
1135 /* }}} */
1136
1137 /* {{{ php_error_docref1 */
1138 /* See: CODING_STANDARDS.md for details. */
php_error_docref1(const char * docref,const char * param1,int type,const char * format,...)1139 PHPAPI ZEND_COLD void php_error_docref1(const char *docref, const char *param1, int type, const char *format, ...)
1140 {
1141 va_list args;
1142
1143 va_start(args, format);
1144 php_verror(docref, param1, type, format, args);
1145 va_end(args);
1146 }
1147 /* }}} */
1148
1149 /* {{{ php_error_docref2 */
1150 /* See: CODING_STANDARDS.md for details. */
php_error_docref2(const char * docref,const char * param1,const char * param2,int type,const char * format,...)1151 PHPAPI ZEND_COLD void php_error_docref2(const char *docref, const char *param1, const char *param2, int type, const char *format, ...)
1152 {
1153 char *params;
1154 va_list args;
1155
1156 spprintf(¶ms, 0, "%s,%s", param1, param2);
1157 va_start(args, format);
1158 php_verror(docref, params ? params : "...", type, format, args);
1159 va_end(args);
1160 if (params) {
1161 efree(params);
1162 }
1163 }
1164 /* }}} */
1165
1166 #ifdef PHP_WIN32
php_win32_docref1_from_error(DWORD error,const char * param1)1167 PHPAPI ZEND_COLD void php_win32_docref1_from_error(DWORD error, const char *param1) {
1168 char *buf = php_win32_error_to_msg(error);
1169 size_t buf_len;
1170
1171 buf_len = strlen(buf);
1172 if (buf_len >= 2) {
1173 buf[buf_len - 1] = '\0';
1174 buf[buf_len - 2] = '\0';
1175 }
1176 php_error_docref1(NULL, param1, E_WARNING, "%s (code: %lu)", buf, error);
1177 php_win32_error_msg_free(buf);
1178 }
1179
php_win32_docref2_from_error(DWORD error,const char * param1,const char * param2)1180 PHPAPI ZEND_COLD void php_win32_docref2_from_error(DWORD error, const char *param1, const char *param2) {
1181 char *buf = php_win32_error_to_msg(error);
1182 php_error_docref2(NULL, param1, param2, E_WARNING, "%s (code: %lu)", buf, error);
1183 php_win32_error_msg_free(buf);
1184 }
1185 #endif
1186
1187 /* {{{ php_html_puts */
php_html_puts(const char * str,size_t size)1188 PHPAPI void php_html_puts(const char *str, size_t size)
1189 {
1190 zend_html_puts(str, size);
1191 }
1192 /* }}} */
1193
clear_last_error(void)1194 static void clear_last_error(void) {
1195 if (PG(last_error_message)) {
1196 zend_string_release(PG(last_error_message));
1197 PG(last_error_message) = NULL;
1198 }
1199 if (PG(last_error_file)) {
1200 zend_string_release(PG(last_error_file));
1201 PG(last_error_file) = NULL;
1202 }
1203 }
1204
1205 #if ZEND_DEBUG
1206 /* {{{ 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)1207 static void report_zend_debug_error_notify_cb(int type, zend_string *error_filename, uint32_t error_lineno, zend_string *message)
1208 {
1209 if (PG(report_zend_debug)) {
1210 bool trigger_break;
1211
1212 switch (type) {
1213 case E_ERROR:
1214 case E_CORE_ERROR:
1215 case E_COMPILE_ERROR:
1216 case E_USER_ERROR:
1217 trigger_break=1;
1218 break;
1219 default:
1220 trigger_break=0;
1221 break;
1222 }
1223
1224 zend_output_debug_string(trigger_break, "%s(%" PRIu32 ") : %s", ZSTR_VAL(error_filename), error_lineno, ZSTR_VAL(message));
1225 }
1226 }
1227 /* }}} */
1228 #endif
1229
1230 /* {{{ php_error_cb
1231 extended error handling function */
php_error_cb(int orig_type,zend_string * error_filename,const uint32_t error_lineno,zend_string * message)1232 static ZEND_COLD void php_error_cb(int orig_type, zend_string *error_filename, const uint32_t error_lineno, zend_string *message)
1233 {
1234 bool display;
1235 int type = orig_type & E_ALL;
1236
1237 /* check for repeated errors to be ignored */
1238 if (PG(ignore_repeated_errors) && PG(last_error_message)) {
1239 /* no check for PG(last_error_file) is needed since it cannot
1240 * be NULL if PG(last_error_message) is not NULL */
1241 if (!zend_string_equals(PG(last_error_message), message)
1242 || (!PG(ignore_repeated_source)
1243 && ((PG(last_error_lineno) != (int)error_lineno)
1244 || !zend_string_equals(PG(last_error_file), error_filename)))) {
1245 display = 1;
1246 } else {
1247 display = 0;
1248 }
1249 } else {
1250 display = 1;
1251 }
1252
1253 /* according to error handling mode, throw exception or show it */
1254 if (EG(error_handling) == EH_THROW) {
1255 switch (type) {
1256 case E_WARNING:
1257 case E_CORE_WARNING:
1258 case E_COMPILE_WARNING:
1259 case E_USER_WARNING:
1260 /* throw an exception if we are in EH_THROW mode and the type is warning.
1261 * fatal errors are real errors and cannot be made exceptions.
1262 * exclude deprecated for the sake of BC to old damaged code.
1263 * notices are no errors and are not treated as such like E_WARNINGS.
1264 * DO NOT overwrite a pending exception.
1265 */
1266 if (!EG(exception)) {
1267 zend_throw_error_exception(EG(exception_class), message, 0, type);
1268 }
1269 return;
1270 default:
1271 break;
1272 }
1273 }
1274
1275 /* store the error if it has changed */
1276 if (display) {
1277 clear_last_error();
1278 if (!error_filename) {
1279 error_filename = ZSTR_KNOWN(ZEND_STR_UNKNOWN_CAPITALIZED);
1280 }
1281 PG(last_error_type) = type;
1282 PG(last_error_message) = zend_string_copy(message);
1283 PG(last_error_file) = zend_string_copy(error_filename);
1284 PG(last_error_lineno) = error_lineno;
1285 }
1286
1287 if (zend_alloc_in_memory_limit_error_reporting()) {
1288 php_output_discard_all();
1289 }
1290
1291 /* display/log the error if necessary */
1292 if (display && ((EG(error_reporting) & type) || (type & E_CORE))
1293 && (PG(log_errors) || PG(display_errors) || (!module_initialized))) {
1294 char *error_type_str;
1295 int syslog_type_int = LOG_NOTICE;
1296
1297 switch (type) {
1298 case E_ERROR:
1299 case E_CORE_ERROR:
1300 case E_COMPILE_ERROR:
1301 case E_USER_ERROR:
1302 error_type_str = "Fatal error";
1303 syslog_type_int = LOG_ERR;
1304 break;
1305 case E_RECOVERABLE_ERROR:
1306 error_type_str = "Recoverable fatal error";
1307 syslog_type_int = LOG_ERR;
1308 break;
1309 case E_WARNING:
1310 case E_CORE_WARNING:
1311 case E_COMPILE_WARNING:
1312 case E_USER_WARNING:
1313 error_type_str = "Warning";
1314 syslog_type_int = LOG_WARNING;
1315 break;
1316 case E_PARSE:
1317 error_type_str = "Parse error";
1318 syslog_type_int = LOG_ERR;
1319 break;
1320 case E_NOTICE:
1321 case E_USER_NOTICE:
1322 error_type_str = "Notice";
1323 syslog_type_int = LOG_NOTICE;
1324 break;
1325 case E_STRICT:
1326 error_type_str = "Strict Standards";
1327 syslog_type_int = LOG_INFO;
1328 break;
1329 case E_DEPRECATED:
1330 case E_USER_DEPRECATED:
1331 error_type_str = "Deprecated";
1332 syslog_type_int = LOG_INFO;
1333 break;
1334 default:
1335 error_type_str = "Unknown error";
1336 break;
1337 }
1338
1339 if (PG(log_errors)
1340 || (!module_initialized && (!PG(display_startup_errors) || !PG(display_errors)))) {
1341 char *log_buffer;
1342 #ifdef PHP_WIN32
1343 if (type == E_CORE_ERROR || type == E_CORE_WARNING) {
1344 syslog(LOG_ALERT, "PHP %s: %s (%s)", error_type_str, ZSTR_VAL(message), GetCommandLine());
1345 }
1346 #endif
1347 spprintf(&log_buffer, 0, "PHP %s: %s in %s on line %" PRIu32, error_type_str, ZSTR_VAL(message), ZSTR_VAL(error_filename), error_lineno);
1348 php_log_err_with_severity(log_buffer, syslog_type_int);
1349 efree(log_buffer);
1350 }
1351
1352 if (PG(display_errors) && ((module_initialized && !PG(during_request_startup)) || (PG(display_startup_errors)))) {
1353 if (PG(xmlrpc_errors)) {
1354 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);
1355 } else {
1356 char *prepend_string = INI_STR("error_prepend_string");
1357 char *append_string = INI_STR("error_append_string");
1358
1359 if (PG(html_errors)) {
1360 if (type == E_ERROR || type == E_PARSE) {
1361 zend_string *buf = escape_html(ZSTR_VAL(message), ZSTR_LEN(message));
1362 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));
1363 zend_string_free(buf);
1364 } else {
1365 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));
1366 }
1367 } else {
1368 /* Write CLI/CGI errors to stderr if display_errors = "stderr" */
1369 if ((!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg")) &&
1370 PG(display_errors) == PHP_DISPLAY_ERRORS_STDERR
1371 ) {
1372 fprintf(stderr, "%s: ", error_type_str);
1373 fwrite(ZSTR_VAL(message), sizeof(char), ZSTR_LEN(message), stderr);
1374 fprintf(stderr, " in %s on line %" PRIu32 "\n", ZSTR_VAL(error_filename), error_lineno);
1375 #ifdef PHP_WIN32
1376 fflush(stderr);
1377 #endif
1378 } else {
1379 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));
1380 }
1381 }
1382 }
1383 }
1384 }
1385
1386 /* Bail out if we can't recover */
1387 switch (type) {
1388 case E_CORE_ERROR:
1389 if(!module_initialized) {
1390 /* bad error in module startup - no way we can live with this */
1391 exit(-2);
1392 }
1393 ZEND_FALLTHROUGH;
1394 case E_ERROR:
1395 case E_RECOVERABLE_ERROR:
1396 case E_PARSE:
1397 case E_COMPILE_ERROR:
1398 case E_USER_ERROR:
1399 EG(exit_status) = 255;
1400 if (module_initialized) {
1401 if (!PG(display_errors) &&
1402 !SG(headers_sent) &&
1403 SG(sapi_headers).http_response_code == 200
1404 ) {
1405 sapi_header_line ctr = {0};
1406
1407 ctr.line = "HTTP/1.0 500 Internal Server Error";
1408 ctr.line_len = sizeof("HTTP/1.0 500 Internal Server Error") - 1;
1409 sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
1410 }
1411 /* the parser would return 1 (failure), we can bail out nicely */
1412 if (!(orig_type & E_DONT_BAIL)) {
1413 /* restore memory limit */
1414 zend_set_memory_limit(PG(memory_limit));
1415 zend_objects_store_mark_destructed(&EG(objects_store));
1416 if (CG(in_compilation) && (type == E_COMPILE_ERROR || type == E_PARSE)) {
1417 /* We bailout during compilation which may for example leave stale entries in CG(loop_var_stack).
1418 * If code is compiled during shutdown, we need to make sure the compiler is reset to a clean state,
1419 * otherwise this will lead to incorrect compilation during shutdown.
1420 * We don't do a full re-initialization via init_compiler() because that will also reset streams and resources. */
1421 shutdown_compiler();
1422 zend_init_compiler_data_structures();
1423 }
1424 zend_bailout();
1425 return;
1426 }
1427 }
1428 break;
1429 }
1430 }
1431 /* }}} */
1432
1433 /* {{{ php_get_current_user */
php_get_current_user(void)1434 PHPAPI char *php_get_current_user(void)
1435 {
1436 zend_stat_t *pstat = NULL;
1437
1438 if (SG(request_info).current_user) {
1439 return SG(request_info).current_user;
1440 }
1441
1442 /* FIXME: I need to have this somehow handled if
1443 USE_SAPI is defined, because cgi will also be
1444 interfaced in USE_SAPI */
1445
1446 pstat = sapi_get_stat();
1447
1448 if (!pstat) {
1449 return "";
1450 } else {
1451 #ifdef PHP_WIN32
1452 char *name = php_win32_get_username();
1453 int len;
1454
1455 if (!name) {
1456 return "";
1457 }
1458 len = (int)strlen(name);
1459 name[len] = '\0';
1460 SG(request_info).current_user_length = len;
1461 SG(request_info).current_user = estrndup(name, len);
1462 free(name);
1463 return SG(request_info).current_user;
1464 #else
1465 struct passwd *pwd;
1466 #if defined(ZTS) && defined(HAVE_GETPWUID_R) && defined(_SC_GETPW_R_SIZE_MAX)
1467 struct passwd _pw;
1468 struct passwd *retpwptr = NULL;
1469 int pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
1470 char *pwbuf;
1471
1472 if (pwbuflen < 1) {
1473 return "";
1474 }
1475 pwbuf = emalloc(pwbuflen);
1476 if (getpwuid_r(pstat->st_uid, &_pw, pwbuf, pwbuflen, &retpwptr) != 0) {
1477 efree(pwbuf);
1478 return "";
1479 }
1480 if (retpwptr == NULL) {
1481 efree(pwbuf);
1482 return "";
1483 }
1484 pwd = &_pw;
1485 #else
1486 if ((pwd=getpwuid(pstat->st_uid))==NULL) {
1487 return "";
1488 }
1489 #endif
1490 SG(request_info).current_user_length = strlen(pwd->pw_name);
1491 SG(request_info).current_user = estrndup(pwd->pw_name, SG(request_info).current_user_length);
1492 #if defined(ZTS) && defined(HAVE_GETPWUID_R) && defined(_SC_GETPW_R_SIZE_MAX)
1493 efree(pwbuf);
1494 #endif
1495 return SG(request_info).current_user;
1496 #endif
1497 }
1498 }
1499 /* }}} */
1500
1501 /* {{{ Sets the maximum time a script can run */
PHP_FUNCTION(set_time_limit)1502 PHP_FUNCTION(set_time_limit)
1503 {
1504 zend_long new_timeout;
1505 char *new_timeout_str;
1506 size_t new_timeout_strlen;
1507 zend_string *key;
1508
1509 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &new_timeout) == FAILURE) {
1510 RETURN_THROWS();
1511 }
1512
1513 new_timeout_strlen = zend_spprintf(&new_timeout_str, 0, ZEND_LONG_FMT, new_timeout);
1514
1515 key = ZSTR_INIT_LITERAL("max_execution_time", 0);
1516 if (zend_alter_ini_entry_chars_ex(key, new_timeout_str, new_timeout_strlen, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0) == SUCCESS) {
1517 RETVAL_TRUE;
1518 } else {
1519 RETVAL_FALSE;
1520 }
1521 zend_string_release_ex(key, 0);
1522 efree(new_timeout_str);
1523 }
1524 /* }}} */
1525
1526 /* {{{ php_fopen_wrapper_for_zend */
php_fopen_wrapper_for_zend(zend_string * filename,zend_string ** opened_path)1527 static FILE *php_fopen_wrapper_for_zend(zend_string *filename, zend_string **opened_path)
1528 {
1529 *opened_path = filename;
1530 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);
1531 }
1532 /* }}} */
1533
php_zend_stream_closer(void * handle)1534 static void php_zend_stream_closer(void *handle) /* {{{ */
1535 {
1536 php_stream_close((php_stream*)handle);
1537 }
1538 /* }}} */
1539
php_zend_stream_fsizer(void * handle)1540 static size_t php_zend_stream_fsizer(void *handle) /* {{{ */
1541 {
1542 php_stream *stream = handle;
1543 php_stream_statbuf ssb;
1544
1545 /* File size reported by stat() may be inaccurate if stream filters are used.
1546 * TODO: Should stat() be generally disabled if filters are used? */
1547 if (stream->readfilters.head) {
1548 return 0;
1549 }
1550
1551 if (php_stream_stat(stream, &ssb) == 0) {
1552 return ssb.sb.st_size;
1553 }
1554 return 0;
1555 }
1556 /* }}} */
1557
php_stream_open_for_zend(zend_file_handle * handle)1558 static zend_result php_stream_open_for_zend(zend_file_handle *handle) /* {{{ */
1559 {
1560 return php_stream_open_for_zend_ex(handle, USE_PATH|REPORT_ERRORS|STREAM_OPEN_FOR_INCLUDE);
1561 }
1562 /* }}} */
1563
php_stream_open_for_zend_ex(zend_file_handle * handle,int mode)1564 PHPAPI zend_result php_stream_open_for_zend_ex(zend_file_handle *handle, int mode) /* {{{ */
1565 {
1566 zend_string *opened_path;
1567 zend_string *filename;
1568 php_stream *stream;
1569
1570 ZEND_ASSERT(handle->type == ZEND_HANDLE_FILENAME);
1571 opened_path = filename = handle->filename;
1572 stream = php_stream_open_wrapper((char *)ZSTR_VAL(filename), "rb", mode | STREAM_OPEN_FOR_ZEND_STREAM, &opened_path);
1573 if (stream) {
1574 memset(handle, 0, sizeof(zend_file_handle));
1575 handle->type = ZEND_HANDLE_STREAM;
1576 handle->filename = filename;
1577 handle->opened_path = opened_path;
1578 handle->handle.stream.handle = stream;
1579 handle->handle.stream.reader = (zend_stream_reader_t)_php_stream_read;
1580 handle->handle.stream.fsizer = php_zend_stream_fsizer;
1581 handle->handle.stream.isatty = 0;
1582 handle->handle.stream.closer = php_zend_stream_closer;
1583 /* suppress warning if this stream is not explicitly closed */
1584 php_stream_auto_cleanup(stream);
1585 /* Disable buffering to avoid double buffering between PHP and Zend streams. */
1586 php_stream_set_option(stream, PHP_STREAM_OPTION_READ_BUFFER, PHP_STREAM_BUFFER_NONE, NULL);
1587
1588 return SUCCESS;
1589 }
1590 return FAILURE;
1591 }
1592 /* }}} */
1593
php_resolve_path_for_zend(zend_string * filename)1594 static zend_string *php_resolve_path_for_zend(zend_string *filename) /* {{{ */
1595 {
1596 return php_resolve_path(ZSTR_VAL(filename), ZSTR_LEN(filename), PG(include_path));
1597 }
1598 /* }}} */
1599
1600 /* {{{ php_get_configuration_directive_for_zend */
php_get_configuration_directive_for_zend(zend_string * name)1601 static zval *php_get_configuration_directive_for_zend(zend_string *name)
1602 {
1603 return cfg_get_entry_ex(name);
1604 }
1605 /* }}} */
1606
1607 /* {{{ php_free_request_globals */
php_free_request_globals(void)1608 static void php_free_request_globals(void)
1609 {
1610 clear_last_error();
1611 if (PG(php_sys_temp_dir)) {
1612 efree(PG(php_sys_temp_dir));
1613 PG(php_sys_temp_dir) = NULL;
1614 }
1615
1616 EG(filename_override) = NULL;
1617 EG(lineno_override) = -1;
1618 }
1619 /* }}} */
1620
1621 /* {{{ php_message_handler_for_zend */
php_message_handler_for_zend(zend_long message,const void * data)1622 static ZEND_COLD void php_message_handler_for_zend(zend_long message, const void *data)
1623 {
1624 switch (message) {
1625 case ZMSG_FAILED_INCLUDE_FOPEN: {
1626 char *tmp = estrdup((char *) data);
1627 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)));
1628 efree(tmp);
1629 break;
1630 }
1631 case ZMSG_FAILED_REQUIRE_FOPEN: {
1632 char *tmp = estrdup((char *) data);
1633 zend_throw_error(NULL, "Failed opening required '%s' (include_path='%s')", php_strip_url_passwd(tmp), STR_PRINT(PG(include_path)));
1634 efree(tmp);
1635 break;
1636 }
1637 case ZMSG_FAILED_HIGHLIGHT_FOPEN: {
1638 char *tmp = estrdup((char *) data);
1639 php_error_docref(NULL, E_WARNING, "Failed opening '%s' for highlighting", php_strip_url_passwd(tmp));
1640 efree(tmp);
1641 break;
1642 }
1643 case ZMSG_MEMORY_LEAK_DETECTED:
1644 case ZMSG_MEMORY_LEAK_REPEATED:
1645 #if ZEND_DEBUG
1646 if (EG(error_reporting) & E_WARNING) {
1647 char memory_leak_buf[1024];
1648
1649 if (message==ZMSG_MEMORY_LEAK_DETECTED) {
1650 zend_leak_info *t = (zend_leak_info *) data;
1651
1652 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));
1653 if (t->orig_filename) {
1654 char relay_buf[512];
1655
1656 snprintf(relay_buf, 512, "%s(%" PRIu32 ") : Actual location (location was relayed)\n", t->orig_filename, t->orig_lineno);
1657 strlcat(memory_leak_buf, relay_buf, sizeof(memory_leak_buf));
1658 }
1659 } else {
1660 unsigned long leak_count = (uintptr_t) data;
1661
1662 snprintf(memory_leak_buf, 512, "Last leak repeated %lu time%s\n", leak_count, (leak_count>1?"s":""));
1663 }
1664 # if defined(PHP_WIN32)
1665 if (IsDebuggerPresent()) {
1666 OutputDebugString(memory_leak_buf);
1667 } else {
1668 fprintf(stderr, "%s", memory_leak_buf);
1669 }
1670 # else
1671 fprintf(stderr, "%s", memory_leak_buf);
1672 # endif
1673 }
1674 #endif
1675 break;
1676 case ZMSG_MEMORY_LEAKS_GRAND_TOTAL:
1677 #if ZEND_DEBUG
1678 if (EG(error_reporting) & E_WARNING) {
1679 char memory_leak_buf[512];
1680
1681 snprintf(memory_leak_buf, 512, "=== Total %d memory leaks detected ===\n", *((uint32_t *) data));
1682 # if defined(PHP_WIN32)
1683 if (IsDebuggerPresent()) {
1684 OutputDebugString(memory_leak_buf);
1685 } else {
1686 fprintf(stderr, "%s", memory_leak_buf);
1687 }
1688 # else
1689 fprintf(stderr, "%s", memory_leak_buf);
1690 # endif
1691 }
1692 #endif
1693 break;
1694 case ZMSG_LOG_SCRIPT_NAME: {
1695 struct tm *ta, tmbuf;
1696 time_t curtime;
1697 char *datetime_str, asctimebuf[52];
1698 char memory_leak_buf[4096];
1699
1700 time(&curtime);
1701 ta = php_localtime_r(&curtime, &tmbuf);
1702 datetime_str = php_asctime_r(ta, asctimebuf);
1703 if (datetime_str) {
1704 datetime_str[strlen(datetime_str)-1]=0; /* get rid of the trailing newline */
1705 snprintf(memory_leak_buf, sizeof(memory_leak_buf), "[%s] Script: '%s'\n", datetime_str, SAFE_FILENAME(SG(request_info).path_translated));
1706 } else {
1707 snprintf(memory_leak_buf, sizeof(memory_leak_buf), "[null] Script: '%s'\n", SAFE_FILENAME(SG(request_info).path_translated));
1708 }
1709 # if defined(PHP_WIN32)
1710 if (IsDebuggerPresent()) {
1711 OutputDebugString(memory_leak_buf);
1712 } else {
1713 fprintf(stderr, "%s", memory_leak_buf);
1714 }
1715 # else
1716 fprintf(stderr, "%s", memory_leak_buf);
1717 # endif
1718 }
1719 break;
1720 }
1721 }
1722 /* }}} */
1723
1724
php_on_timeout(int seconds)1725 void php_on_timeout(int seconds)
1726 {
1727 PG(connection_status) |= PHP_CONNECTION_TIMEOUT;
1728 }
1729
1730 #if PHP_SIGCHILD
1731 /* {{{ sigchld_handler */
sigchld_handler(int apar)1732 static void sigchld_handler(int apar)
1733 {
1734 int errno_save = errno;
1735
1736 while (waitpid(-1, NULL, WNOHANG) > 0);
1737 signal(SIGCHLD, sigchld_handler);
1738
1739 errno = errno_save;
1740 }
1741 /* }}} */
1742 #endif
1743
1744 /* {{{ php_request_startup */
php_request_startup(void)1745 zend_result php_request_startup(void)
1746 {
1747 zend_result retval = SUCCESS;
1748
1749 zend_interned_strings_activate();
1750
1751 #ifdef HAVE_DTRACE
1752 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));
1753 #endif /* HAVE_DTRACE */
1754
1755 #ifdef PHP_WIN32
1756 # if defined(ZTS)
1757 _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
1758 # endif
1759 PG(com_initialized) = 0;
1760 #endif
1761
1762 #if PHP_SIGCHILD
1763 signal(SIGCHLD, sigchld_handler);
1764 #endif
1765
1766 zend_try {
1767 PG(in_error_log) = 0;
1768 PG(during_request_startup) = 1;
1769
1770 php_output_activate();
1771
1772 /* initialize global variables */
1773 PG(modules_activated) = 0;
1774 PG(header_is_being_sent) = 0;
1775 PG(connection_status) = PHP_CONNECTION_NORMAL;
1776 PG(in_user_include) = 0;
1777
1778 zend_activate();
1779 sapi_activate();
1780
1781 #ifdef ZEND_SIGNALS
1782 zend_signal_activate();
1783 #endif
1784
1785 if (PG(max_input_time) == -1) {
1786 zend_set_timeout(EG(timeout_seconds), 1);
1787 } else {
1788 zend_set_timeout(PG(max_input_time), 1);
1789 }
1790
1791 /* Disable realpath cache if an open_basedir is set */
1792 if (PG(open_basedir) && *PG(open_basedir)) {
1793 CWDG(realpath_cache_size_limit) = 0;
1794 }
1795
1796 if (PG(expose_php) && !SG(headers_sent)) {
1797 sapi_add_header(SAPI_PHP_VERSION_HEADER, sizeof(SAPI_PHP_VERSION_HEADER)-1, 1);
1798 }
1799
1800 if (PG(output_handler) && PG(output_handler)[0]) {
1801 zval oh;
1802
1803 ZVAL_STRING(&oh, PG(output_handler));
1804 php_output_start_user(&oh, 0, PHP_OUTPUT_HANDLER_STDFLAGS);
1805 zval_ptr_dtor(&oh);
1806 } else if (PG(output_buffering)) {
1807 php_output_start_user(NULL, PG(output_buffering) > 1 ? PG(output_buffering) : 0, PHP_OUTPUT_HANDLER_STDFLAGS);
1808 } else if (PG(implicit_flush)) {
1809 php_output_set_implicit_flush(1);
1810 }
1811
1812 /* We turn this off in php_execute_script() */
1813 /* PG(during_request_startup) = 0; */
1814
1815 php_hash_environment();
1816 zend_activate_modules();
1817 PG(modules_activated)=1;
1818 } zend_catch {
1819 retval = FAILURE;
1820 } zend_end_try();
1821
1822 SG(sapi_started) = 1;
1823
1824 return retval;
1825 }
1826 /* }}} */
1827
1828 /* {{{ php_request_shutdown */
php_request_shutdown(void * dummy)1829 void php_request_shutdown(void *dummy)
1830 {
1831 bool report_memleaks;
1832
1833 EG(flags) |= EG_FLAGS_IN_SHUTDOWN;
1834
1835 report_memleaks = PG(report_memleaks);
1836
1837 /* EG(current_execute_data) points into nirvana and therefore cannot be safely accessed
1838 * inside zend_executor callback functions.
1839 */
1840 EG(current_execute_data) = NULL;
1841
1842 php_deactivate_ticks();
1843
1844 /* 0. Call any open observer end handlers that are still open after a zend_bailout */
1845 if (ZEND_OBSERVER_ENABLED) {
1846 zend_observer_fcall_end_all();
1847 }
1848
1849 /* 1. Call all possible shutdown functions registered with register_shutdown_function() */
1850 if (PG(modules_activated)) {
1851 php_call_shutdown_functions();
1852 }
1853
1854 /* 2. Call all possible __destruct() functions */
1855 zend_try {
1856 zend_call_destructors();
1857 } zend_end_try();
1858
1859 /* 3. Flush all output buffers */
1860 zend_try {
1861 php_output_end_all();
1862 } zend_end_try();
1863
1864 /* 4. Reset max_execution_time (no longer executing php code after response sent) */
1865 zend_try {
1866 zend_unset_timeout();
1867 } zend_end_try();
1868
1869 /* 5. Call all extensions RSHUTDOWN functions */
1870 if (PG(modules_activated)) {
1871 zend_deactivate_modules();
1872 }
1873
1874 /* 6. Shutdown output layer (send the set HTTP headers, cleanup output handlers, etc.) */
1875 zend_try {
1876 php_output_deactivate();
1877 } zend_end_try();
1878
1879 /* 7. Free shutdown functions */
1880 if (PG(modules_activated)) {
1881 php_free_shutdown_functions();
1882 }
1883
1884 /* 8. Destroy super-globals */
1885 zend_try {
1886 int i;
1887
1888 for (i=0; i<NUM_TRACK_VARS; i++) {
1889 zval_ptr_dtor(&PG(http_globals)[i]);
1890 }
1891 } zend_end_try();
1892
1893 /* 9. Shutdown scanner/executor/compiler and restore ini entries */
1894 zend_deactivate();
1895
1896 /* 10. free request-bound globals */
1897 php_free_request_globals();
1898
1899 /* 11. Call all extensions post-RSHUTDOWN functions */
1900 zend_try {
1901 zend_post_deactivate_modules();
1902 } zend_end_try();
1903
1904 /* 12. SAPI related shutdown*/
1905 zend_try {
1906 sapi_deactivate_module();
1907 } zend_end_try();
1908 /* free SAPI stuff */
1909 sapi_deactivate_destroy();
1910
1911 /* 13. free virtual CWD memory */
1912 virtual_cwd_deactivate();
1913
1914 /* 14. Destroy stream hashes */
1915 zend_try {
1916 php_shutdown_stream_hashes();
1917 } zend_end_try();
1918
1919 /* 15. Free Willy (here be crashes) */
1920 zend_arena_destroy(CG(arena));
1921 zend_interned_strings_deactivate();
1922 zend_try {
1923 shutdown_memory_manager(CG(unclean_shutdown) || !report_memleaks, 0);
1924 } zend_end_try();
1925
1926 /* Reset memory limit, as the reset during INI_STAGE_DEACTIVATE may have failed.
1927 * At this point, no memory beyond a single chunk should be in use. */
1928 zend_set_memory_limit(PG(memory_limit));
1929
1930 /* 16. Deactivate Zend signals */
1931 #ifdef ZEND_SIGNALS
1932 zend_signal_deactivate();
1933 #endif
1934
1935 #ifdef PHP_WIN32
1936 if (PG(com_initialized)) {
1937 CoUninitialize();
1938 PG(com_initialized) = 0;
1939 }
1940 #endif
1941
1942 #ifdef HAVE_DTRACE
1943 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));
1944 #endif /* HAVE_DTRACE */
1945 }
1946 /* }}} */
1947
1948 /* {{{ php_com_initialize */
php_com_initialize(void)1949 PHPAPI void php_com_initialize(void)
1950 {
1951 #ifdef PHP_WIN32
1952 if (!PG(com_initialized)) {
1953 if (CoInitialize(NULL) == S_OK) {
1954 PG(com_initialized) = 1;
1955 }
1956 }
1957 #endif
1958 }
1959 /* }}} */
1960
1961 #ifdef ZTS
1962 /* {{{ core_globals_ctor */
core_globals_ctor(php_core_globals * core_globals)1963 static void core_globals_ctor(php_core_globals *core_globals)
1964 {
1965 memset(core_globals, 0, sizeof(*core_globals));
1966 php_startup_ticks();
1967 }
1968 /* }}} */
1969 #endif
1970
1971 /* {{{ core_globals_dtor */
core_globals_dtor(php_core_globals * core_globals)1972 static void core_globals_dtor(php_core_globals *core_globals)
1973 {
1974 /* These should have been freed earlier. */
1975 ZEND_ASSERT(!core_globals->last_error_message);
1976 ZEND_ASSERT(!core_globals->last_error_file);
1977
1978 if (core_globals->disable_classes) {
1979 free(core_globals->disable_classes);
1980 }
1981 if (core_globals->php_binary) {
1982 free(core_globals->php_binary);
1983 }
1984
1985 php_shutdown_ticks(core_globals);
1986 }
1987 /* }}} */
1988
PHP_MINFO_FUNCTION(php_core)1989 PHP_MINFO_FUNCTION(php_core) { /* {{{ */
1990 php_info_print_table_start();
1991 php_info_print_table_row(2, "PHP Version", PHP_VERSION);
1992 php_info_print_table_end();
1993 DISPLAY_INI_ENTRIES();
1994 }
1995 /* }}} */
1996
1997 /* {{{ php_register_extensions */
php_register_extensions(zend_module_entry * const * ptr,int count)1998 zend_result php_register_extensions(zend_module_entry * const * ptr, int count)
1999 {
2000 zend_module_entry * const * end = ptr + count;
2001
2002 while (ptr < end) {
2003 if (*ptr) {
2004 if (zend_register_internal_module(*ptr)==NULL) {
2005 return FAILURE;
2006 }
2007 }
2008 ptr++;
2009 }
2010 return SUCCESS;
2011 }
2012
2013 #ifdef PHP_WIN32
2014 static _invalid_parameter_handler old_invalid_parameter_handler;
2015
dummy_invalid_parameter_handler(const wchar_t * expression,const wchar_t * function,const wchar_t * file,unsigned int line,uintptr_t pReserved)2016 void dummy_invalid_parameter_handler(
2017 const wchar_t *expression,
2018 const wchar_t *function,
2019 const wchar_t *file,
2020 unsigned int line,
2021 uintptr_t pReserved)
2022 {
2023 static int called = 0;
2024 char buf[1024];
2025 int len;
2026
2027 if (!called) {
2028 if(PG(windows_show_crt_warning)) {
2029 called = 1;
2030 if (function) {
2031 if (file) {
2032 len = _snprintf(buf, sizeof(buf)-1, "Invalid parameter detected in CRT function '%ws' (%ws:%u)", function, file, line);
2033 } else {
2034 len = _snprintf(buf, sizeof(buf)-1, "Invalid parameter detected in CRT function '%ws'", function);
2035 }
2036 } else {
2037 len = _snprintf(buf, sizeof(buf)-1, "Invalid CRT parameter detected (function not known)");
2038 }
2039 zend_error(E_WARNING, "%s", buf);
2040 called = 0;
2041 }
2042 }
2043 }
2044 #endif
2045
2046 /* {{{ php_module_startup */
php_module_startup(sapi_module_struct * sf,zend_module_entry * additional_module)2047 zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_module)
2048 {
2049 zend_utility_functions zuf;
2050 zend_utility_values zuv;
2051 zend_result retval = SUCCESS;
2052 int module_number = 0;
2053 zend_module_entry *module;
2054
2055 #ifdef PHP_WIN32
2056 WORD wVersionRequested = MAKEWORD(2, 0);
2057 WSADATA wsaData;
2058
2059 old_invalid_parameter_handler =
2060 _set_invalid_parameter_handler(dummy_invalid_parameter_handler);
2061 if (old_invalid_parameter_handler != NULL) {
2062 _set_invalid_parameter_handler(old_invalid_parameter_handler);
2063 }
2064
2065 /* Disable the message box for assertions.*/
2066 _CrtSetReportMode(_CRT_ASSERT, 0);
2067 #endif
2068
2069 #ifdef ZTS
2070 (void)ts_resource(0);
2071 #endif
2072
2073 #ifdef PHP_WIN32
2074 if (!php_win32_init_random_bytes()) {
2075 fprintf(stderr, "\ncrypt algorithm provider initialization failed\n");
2076 return FAILURE;
2077 }
2078 #endif
2079
2080 module_shutdown = false;
2081 module_startup = true;
2082 sapi_initialize_empty_request();
2083 sapi_activate();
2084
2085 if (module_initialized) {
2086 return SUCCESS;
2087 }
2088
2089 sapi_module = *sf;
2090
2091 php_output_startup();
2092
2093 #ifdef ZTS
2094 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);
2095 #ifdef PHP_WIN32
2096 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);
2097 #endif
2098 #else
2099 memset(&core_globals, 0, sizeof(core_globals));
2100 php_startup_ticks();
2101 #endif
2102 gc_globals_ctor();
2103
2104 zuf.error_function = php_error_cb;
2105 zuf.printf_function = php_printf;
2106 zuf.write_function = php_output_write;
2107 zuf.fopen_function = php_fopen_wrapper_for_zend;
2108 zuf.message_handler = php_message_handler_for_zend;
2109 zuf.get_configuration_directive = php_get_configuration_directive_for_zend;
2110 zuf.ticks_function = php_run_ticks;
2111 zuf.on_timeout = php_on_timeout;
2112 zuf.stream_open_function = php_stream_open_for_zend;
2113 zuf.printf_to_smart_string_function = php_printf_to_smart_string;
2114 zuf.printf_to_smart_str_function = php_printf_to_smart_str;
2115 zuf.getenv_function = sapi_getenv;
2116 zuf.resolve_path_function = php_resolve_path_for_zend;
2117 zend_startup(&zuf);
2118 zend_reset_lc_ctype_locale();
2119 zend_update_current_locale();
2120
2121 zend_observer_startup();
2122 #if ZEND_DEBUG
2123 zend_observer_error_register(report_zend_debug_error_notify_cb);
2124 #endif
2125
2126 #if HAVE_TZSET
2127 tzset();
2128 #endif
2129
2130 #ifdef PHP_WIN32
2131 char *img_err;
2132 if (!php_win32_crt_compatible(&img_err)) {
2133 php_error(E_CORE_WARNING, img_err);
2134 efree(img_err);
2135 return FAILURE;
2136 }
2137
2138 /* start up winsock services */
2139 if (WSAStartup(wVersionRequested, &wsaData) != 0) {
2140 fprintf(stderr, "\nwinsock.dll unusable. %d\n", WSAGetLastError());
2141 return FAILURE;
2142 }
2143 php_win32_signal_ctrl_handler_init();
2144 #endif
2145
2146 le_index_ptr = zend_register_list_destructors_ex(NULL, NULL, "index pointer", 0);
2147
2148 php_binary_init();
2149 register_main_symbols(module_number);
2150
2151 /* this will read in php.ini, set up the configuration parameters,
2152 load zend extensions and register php function extensions
2153 to be loaded later */
2154 zend_stream_init();
2155 if (php_init_config() == FAILURE) {
2156 return FAILURE;
2157 }
2158 zend_stream_shutdown();
2159
2160 /* Register PHP core ini entries */
2161 zend_register_ini_entries_ex(ini_entries, module_number, MODULE_PERSISTENT);
2162
2163 /* Register Zend ini entries */
2164 zend_register_standard_ini_entries();
2165
2166 #ifdef ZEND_WIN32
2167 /* Until the current ini values was setup, the current cp is 65001.
2168 If the actual ini values are different, some stuff needs to be updated.
2169 It concerns at least main_cwd_state and there might be more. As we're
2170 still in the startup phase, lets use the chance and reinit the relevant
2171 item according to the current codepage. Still, if ini_set() is used
2172 later on, a more intelligent way to update such stuff is needed.
2173 Startup/shutdown routines could involve touching globals and thus
2174 can't always be used on demand. */
2175 if (!php_win32_cp_use_unicode()) {
2176 virtual_cwd_main_cwd_init(1);
2177 }
2178 #endif
2179
2180 /* Disable realpath cache if an open_basedir is set */
2181 if (PG(open_basedir) && *PG(open_basedir)) {
2182 CWDG(realpath_cache_size_limit) = 0;
2183 }
2184
2185 PG(have_called_openlog) = 0;
2186
2187 /* initialize stream wrappers registry
2188 * (this uses configuration parameters from php.ini)
2189 */
2190 if (php_init_stream_wrappers(module_number) == FAILURE) {
2191 fprintf(stderr, "PHP: Unable to initialize stream url wrappers.\n");
2192 return FAILURE;
2193 }
2194
2195 zuv.html_errors = 1;
2196 php_startup_auto_globals();
2197 zend_set_utility_values(&zuv);
2198 php_startup_sapi_content_types();
2199
2200 /* Begin to fingerprint the process state */
2201 zend_startup_system_id();
2202
2203 /* startup extensions statically compiled in */
2204 if (php_register_internal_extensions_func() == FAILURE) {
2205 fprintf(stderr, "Unable to start builtin modules\n");
2206 return FAILURE;
2207 }
2208
2209 /* start additional PHP extensions */
2210 if (additional_module && (zend_register_internal_module(additional_module) == NULL)) {
2211 return FAILURE;
2212 }
2213
2214 /* load and startup extensions compiled as shared objects (aka DLLs)
2215 as requested by php.ini entries
2216 these are loaded after initialization of internal extensions
2217 as extensions *might* rely on things from ext/standard
2218 which is always an internal extension and to be initialized
2219 ahead of all other internals
2220 */
2221 php_ini_register_extensions();
2222 zend_startup_modules();
2223
2224 /* start Zend extensions */
2225 zend_startup_extensions();
2226
2227 zend_collect_module_handlers();
2228
2229 /* register additional functions */
2230 if (sapi_module.additional_functions) {
2231 if ((module = zend_hash_str_find_ptr(&module_registry, "standard", sizeof("standard")-1)) != NULL) {
2232 EG(current_module) = module;
2233 zend_register_functions(NULL, sapi_module.additional_functions, NULL, MODULE_PERSISTENT);
2234 EG(current_module) = NULL;
2235 }
2236 }
2237
2238 /* disable certain classes and functions as requested by php.ini */
2239 zend_disable_functions(INI_STR("disable_functions"));
2240 php_disable_classes();
2241
2242 /* make core report what it should */
2243 if ((module = zend_hash_str_find_ptr(&module_registry, "core", sizeof("core")-1)) != NULL) {
2244 module->version = PHP_VERSION;
2245 module->info_func = PHP_MINFO(php_core);
2246 }
2247
2248 /* freeze the list of observer fcall_init handlers */
2249 zend_observer_post_startup();
2250
2251 /* Extensions that add engine hooks after this point do so at their own peril */
2252 zend_finalize_system_id();
2253
2254 module_initialized = true;
2255
2256 if (zend_post_startup() != SUCCESS) {
2257 return FAILURE;
2258 }
2259
2260 /* Check for deprecated directives */
2261 /* NOTE: If you add anything here, remember to add it to build/Makefile.global! */
2262 {
2263 struct {
2264 const long error_level;
2265 const char *phrase;
2266 const char *directives[18]; /* Remember to change this if the number of directives change */
2267 } directives[2] = {
2268 {
2269 E_DEPRECATED,
2270 "Directive '%s' is deprecated",
2271 {
2272 "allow_url_include",
2273 NULL
2274 }
2275 },
2276 {
2277 E_CORE_ERROR,
2278 "Directive '%s' is no longer available in PHP",
2279 {
2280 "allow_call_time_pass_reference",
2281 "asp_tags",
2282 "define_syslog_variables",
2283 "highlight.bg",
2284 "magic_quotes_gpc",
2285 "magic_quotes_runtime",
2286 "magic_quotes_sybase",
2287 "register_globals",
2288 "register_long_arrays",
2289 "safe_mode",
2290 "safe_mode_gid",
2291 "safe_mode_include_dir",
2292 "safe_mode_exec_dir",
2293 "safe_mode_allowed_env_vars",
2294 "safe_mode_protected_env_vars",
2295 "zend.ze1_compatibility_mode",
2296 "track_errors",
2297 NULL
2298 }
2299 }
2300 };
2301
2302 unsigned int i;
2303
2304 zend_try {
2305 /* 2 = Count of deprecation structs */
2306 for (i = 0; i < 2; i++) {
2307 const char **p = directives[i].directives;
2308
2309 while(*p) {
2310 zend_long value;
2311
2312 if (cfg_get_long((char*)*p, &value) == SUCCESS && value) {
2313 zend_error(directives[i].error_level, directives[i].phrase, *p);
2314 }
2315
2316 ++p;
2317 }
2318 }
2319 } zend_catch {
2320 retval = FAILURE;
2321 } zend_end_try();
2322 }
2323
2324 virtual_cwd_deactivate();
2325
2326 sapi_deactivate();
2327 module_startup = false;
2328
2329 /* Don't leak errors from startup into the per-request phase. */
2330 clear_last_error();
2331 shutdown_memory_manager(1, 0);
2332 virtual_cwd_activate();
2333
2334 zend_interned_strings_switch_storage(1);
2335
2336 #if ZEND_RC_DEBUG
2337 if (retval == SUCCESS) {
2338 zend_rc_debug = 1;
2339 }
2340 #endif
2341
2342 /* we're done */
2343 return retval;
2344 }
2345 /* }}} */
2346
2347 /* {{{ php_module_shutdown_wrapper */
php_module_shutdown_wrapper(sapi_module_struct * sapi_globals)2348 int php_module_shutdown_wrapper(sapi_module_struct *sapi_globals)
2349 {
2350 php_module_shutdown();
2351 return SUCCESS;
2352 }
2353 /* }}} */
2354
2355 /* {{{ php_module_shutdown */
php_module_shutdown(void)2356 void php_module_shutdown(void)
2357 {
2358 int module_number=0;
2359
2360 module_shutdown = true;
2361
2362 if (!module_initialized) {
2363 return;
2364 }
2365
2366 zend_interned_strings_switch_storage(0);
2367
2368 #if ZEND_RC_DEBUG
2369 zend_rc_debug = 0;
2370 #endif
2371
2372 #ifdef PHP_WIN32
2373 (void)php_win32_shutdown_random_bytes();
2374 php_win32_signal_ctrl_handler_shutdown();
2375 #endif
2376
2377 sapi_flush();
2378
2379 zend_shutdown();
2380
2381 #ifdef PHP_WIN32
2382 /*close winsock */
2383 WSACleanup();
2384 #endif
2385
2386 /* Destroys filter & transport registries too */
2387 php_shutdown_stream_wrappers(module_number);
2388
2389 zend_unregister_ini_entries_ex(module_number, MODULE_PERSISTENT);
2390
2391 /* close down the ini config */
2392 php_shutdown_config();
2393 clear_last_error();
2394
2395 #ifndef ZTS
2396 zend_ini_shutdown();
2397 shutdown_memory_manager(CG(unclean_shutdown), 1);
2398 #else
2399 zend_ini_global_shutdown();
2400 #endif
2401
2402 php_output_shutdown();
2403
2404 #ifndef ZTS
2405 zend_interned_strings_dtor();
2406 #endif
2407
2408 if (zend_post_shutdown_cb) {
2409 void (*cb)(void) = zend_post_shutdown_cb;
2410
2411 zend_post_shutdown_cb = NULL;
2412 cb();
2413 }
2414
2415 module_initialized = false;
2416
2417 #ifndef ZTS
2418 core_globals_dtor(&core_globals);
2419 gc_globals_dtor();
2420 #else
2421 ts_free_id(core_globals_id);
2422 #endif
2423
2424 #ifdef PHP_WIN32
2425 if (old_invalid_parameter_handler == NULL) {
2426 _set_invalid_parameter_handler(old_invalid_parameter_handler);
2427 }
2428 #endif
2429
2430 zend_observer_shutdown();
2431 }
2432 /* }}} */
2433
php_execute_script_ex(zend_file_handle * primary_file,zval * retval)2434 PHPAPI bool php_execute_script_ex(zend_file_handle *primary_file, zval *retval)
2435 {
2436 zend_file_handle *prepend_file_p = NULL, *append_file_p = NULL;
2437 zend_file_handle prepend_file, append_file;
2438 #ifdef HAVE_BROKEN_GETCWD
2439 volatile int old_cwd_fd = -1;
2440 #else
2441 char *old_cwd;
2442 ALLOCA_FLAG(use_heap)
2443 #endif
2444 bool result = true;
2445
2446 #ifndef HAVE_BROKEN_GETCWD
2447 # define OLD_CWD_SIZE 4096
2448 old_cwd = do_alloca(OLD_CWD_SIZE, use_heap);
2449 old_cwd[0] = '\0';
2450 #endif
2451
2452 zend_try {
2453 char realfile[MAXPATHLEN];
2454
2455 #ifdef PHP_WIN32
2456 if(primary_file->filename) {
2457 UpdateIniFromRegistry(ZSTR_VAL(primary_file->filename));
2458 }
2459 #endif
2460
2461 PG(during_request_startup) = 0;
2462
2463 if (primary_file->filename && !(SG(options) & SAPI_OPTION_NO_CHDIR)) {
2464 #ifdef HAVE_BROKEN_GETCWD
2465 /* this looks nasty to me */
2466 old_cwd_fd = open(".", 0);
2467 #else
2468 php_ignore_value(VCWD_GETCWD(old_cwd, OLD_CWD_SIZE-1));
2469 #endif
2470 VCWD_CHDIR_FILE(ZSTR_VAL(primary_file->filename));
2471 }
2472
2473 /* Only lookup the real file path and add it to the included_files list if already opened
2474 * otherwise it will get opened and added to the included_files list in zend_execute_scripts
2475 */
2476 if (primary_file->filename &&
2477 !zend_string_equals_literal(primary_file->filename, "Standard input code") &&
2478 primary_file->opened_path == NULL &&
2479 primary_file->type != ZEND_HANDLE_FILENAME
2480 ) {
2481 if (expand_filepath(ZSTR_VAL(primary_file->filename), realfile)) {
2482 primary_file->opened_path = zend_string_init(realfile, strlen(realfile), 0);
2483 zend_hash_add_empty_element(&EG(included_files), primary_file->opened_path);
2484 }
2485 }
2486
2487 if (PG(auto_prepend_file) && PG(auto_prepend_file)[0]) {
2488 zend_stream_init_filename(&prepend_file, PG(auto_prepend_file));
2489 prepend_file_p = &prepend_file;
2490 }
2491
2492 if (PG(auto_append_file) && PG(auto_append_file)[0]) {
2493 zend_stream_init_filename(&append_file, PG(auto_append_file));
2494 append_file_p = &append_file;
2495 }
2496 if (PG(max_input_time) != -1) {
2497 #ifdef PHP_WIN32
2498 zend_unset_timeout();
2499 #endif
2500 zend_set_timeout(INI_INT("max_execution_time"), 0);
2501 }
2502
2503 if (prepend_file_p && result) {
2504 result = zend_execute_script(ZEND_REQUIRE, NULL, prepend_file_p) == SUCCESS;
2505 }
2506 if (result) {
2507 result = zend_execute_script(ZEND_REQUIRE, retval, primary_file) == SUCCESS;
2508 }
2509 if (append_file_p && result) {
2510 result = zend_execute_script(ZEND_REQUIRE, NULL, append_file_p) == SUCCESS;
2511 }
2512 } zend_catch {
2513 result = false;
2514 } zend_end_try();
2515
2516 if (prepend_file_p) {
2517 zend_destroy_file_handle(prepend_file_p);
2518 }
2519
2520 if (append_file_p) {
2521 zend_destroy_file_handle(append_file_p);
2522 }
2523
2524 if (EG(exception)) {
2525 zend_try {
2526 zend_exception_error(EG(exception), E_ERROR);
2527 } zend_end_try();
2528 }
2529
2530 #ifdef HAVE_BROKEN_GETCWD
2531 if (old_cwd_fd != -1) {
2532 fchdir(old_cwd_fd);
2533 close(old_cwd_fd);
2534 }
2535 #else
2536 if (old_cwd[0] != '\0') {
2537 php_ignore_value(VCWD_CHDIR(old_cwd));
2538 }
2539 free_alloca(old_cwd, use_heap);
2540 #endif
2541 return result;
2542 }
2543
2544 /* {{{ php_execute_script */
php_execute_script(zend_file_handle * primary_file)2545 PHPAPI bool php_execute_script(zend_file_handle *primary_file)
2546 {
2547 return php_execute_script_ex(primary_file, NULL);
2548 }
2549 /* }}} */
2550
2551 /* {{{ php_execute_simple_script */
php_execute_simple_script(zend_file_handle * primary_file,zval * ret)2552 PHPAPI int php_execute_simple_script(zend_file_handle *primary_file, zval *ret)
2553 {
2554 char *old_cwd;
2555 ALLOCA_FLAG(use_heap)
2556
2557 EG(exit_status) = 0;
2558 #define OLD_CWD_SIZE 4096
2559 old_cwd = do_alloca(OLD_CWD_SIZE, use_heap);
2560 old_cwd[0] = '\0';
2561
2562 zend_try {
2563 #ifdef PHP_WIN32
2564 if(primary_file->filename) {
2565 UpdateIniFromRegistry(ZSTR_VAL(primary_file->filename));
2566 }
2567 #endif
2568
2569 PG(during_request_startup) = 0;
2570
2571 if (primary_file->filename && !(SG(options) & SAPI_OPTION_NO_CHDIR)) {
2572 php_ignore_value(VCWD_GETCWD(old_cwd, OLD_CWD_SIZE-1));
2573 VCWD_CHDIR_FILE(ZSTR_VAL(primary_file->filename));
2574 }
2575 zend_execute_scripts(ZEND_REQUIRE, ret, 1, primary_file);
2576 } zend_end_try();
2577
2578 if (old_cwd[0] != '\0') {
2579 php_ignore_value(VCWD_CHDIR(old_cwd));
2580 }
2581
2582 free_alloca(old_cwd, use_heap);
2583 return EG(exit_status);
2584 }
2585 /* }}} */
2586
2587 /* {{{ php_handle_aborted_connection */
php_handle_aborted_connection(void)2588 PHPAPI void php_handle_aborted_connection(void)
2589 {
2590
2591 PG(connection_status) = PHP_CONNECTION_ABORTED;
2592 php_output_set_status(PHP_OUTPUT_DISABLED);
2593
2594 if (!PG(ignore_user_abort)) {
2595 zend_bailout();
2596 }
2597 }
2598 /* }}} */
2599
2600 /* {{{ php_handle_auth_data */
php_handle_auth_data(const char * auth)2601 PHPAPI int php_handle_auth_data(const char *auth)
2602 {
2603 int ret = -1;
2604 size_t auth_len = auth != NULL ? strlen(auth) : 0;
2605
2606 if (auth && auth_len > 0 && zend_binary_strncasecmp(auth, auth_len, "Basic ", sizeof("Basic ")-1, sizeof("Basic ")-1) == 0) {
2607 char *pass;
2608 zend_string *user;
2609
2610 user = php_base64_decode((const unsigned char*)auth + 6, auth_len - 6);
2611 if (user) {
2612 pass = strchr(ZSTR_VAL(user), ':');
2613 if (pass) {
2614 *pass++ = '\0';
2615 SG(request_info).auth_user = estrndup(ZSTR_VAL(user), ZSTR_LEN(user));
2616 SG(request_info).auth_password = estrdup(pass);
2617 ret = 0;
2618 }
2619 zend_string_free(user);
2620 }
2621 }
2622
2623 if (ret == -1) {
2624 SG(request_info).auth_user = SG(request_info).auth_password = NULL;
2625 } else {
2626 SG(request_info).auth_digest = NULL;
2627 }
2628
2629 if (ret == -1 && auth && auth_len > 0 && zend_binary_strncasecmp(auth, auth_len, "Digest ", sizeof("Digest ")-1, sizeof("Digest ")-1) == 0) {
2630 SG(request_info).auth_digest = estrdup(auth + 7);
2631 ret = 0;
2632 }
2633
2634 if (ret == -1) {
2635 SG(request_info).auth_digest = NULL;
2636 }
2637
2638 return ret;
2639 }
2640 /* }}} */
2641
2642 /* {{{ php_lint_script */
php_lint_script(zend_file_handle * file)2643 PHPAPI zend_result php_lint_script(zend_file_handle *file)
2644 {
2645 zend_op_array *op_array;
2646 zend_result retval = FAILURE;
2647
2648 zend_try {
2649 op_array = zend_compile_file(file, ZEND_INCLUDE);
2650
2651 if (op_array) {
2652 destroy_op_array(op_array);
2653 efree(op_array);
2654 retval = SUCCESS;
2655 }
2656 } zend_end_try();
2657 if (EG(exception)) {
2658 zend_exception_error(EG(exception), E_ERROR);
2659 }
2660
2661 return retval;
2662 }
2663 /* }}} */
2664
2665 #ifdef ZTS
2666 /* {{{ php_reserve_tsrm_memory */
php_reserve_tsrm_memory(void)2667 PHPAPI void php_reserve_tsrm_memory(void)
2668 {
2669 tsrm_reserve(
2670 TSRM_ALIGNED_SIZE(sizeof(zend_compiler_globals)) +
2671 TSRM_ALIGNED_SIZE(sizeof(zend_executor_globals)) +
2672 TSRM_ALIGNED_SIZE(sizeof(zend_php_scanner_globals)) +
2673 TSRM_ALIGNED_SIZE(sizeof(zend_ini_scanner_globals)) +
2674 TSRM_ALIGNED_SIZE(sizeof(virtual_cwd_globals)) +
2675 #ifdef ZEND_SIGNALS
2676 TSRM_ALIGNED_SIZE(sizeof(zend_signal_globals_t)) +
2677 #endif
2678 TSRM_ALIGNED_SIZE(zend_mm_globals_size()) +
2679 TSRM_ALIGNED_SIZE(zend_gc_globals_size()) +
2680 TSRM_ALIGNED_SIZE(sizeof(php_core_globals)) +
2681 TSRM_ALIGNED_SIZE(sizeof(sapi_globals_struct))
2682 );
2683 }
2684 /* }}} */
2685
php_tsrm_startup_ex(int expected_threads)2686 PHPAPI bool php_tsrm_startup_ex(int expected_threads)
2687 {
2688 bool ret = tsrm_startup(expected_threads, 1, 0, NULL);
2689 php_reserve_tsrm_memory();
2690 (void)ts_resource(0);
2691 return ret;
2692 }
2693
2694 /* {{{ php_tsrm_startup */
php_tsrm_startup(void)2695 PHPAPI bool php_tsrm_startup(void)
2696 {
2697 return php_tsrm_startup_ex(1);
2698 }
2699 /* }}} */
2700 #endif
2701