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