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