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