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