]> git.pld-linux.org Git - packages/php.git/blame - suhosin.patch
This commit was manufactured by cvs2git to create branch 'DEVEL'.
[packages/php.git] / suhosin.patch
CommitLineData
c0240cb1 1diff -Naurp php-5.3.6RC1/configure php-5.3.6RC1.oden/configure
2--- php-5.3.6RC1/configure 2011-02-16 21:30:40.000000000 +0100
3+++ php-5.3.6RC1.oden/configure 2011-02-20 11:50:19.294835319 +0100
4@@ -18979,6 +18979,9 @@ EOF
5
6 fi
7
8+cat >> confdefs.h <<\EOF
9+#define SUHOSIN_PATCH 1
10+EOF
11
12 echo $ac_n "checking for declared timezone""... $ac_c" 1>&6
13 echo "configure:18985: checking for declared timezone" >&5
14@@ -115340,7 +115343,7 @@ EOF
15 php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
16 strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \
17 network.c php_open_temporary_file.c php_logos.c \
18- output.c getopt.c; do
19+ output.c getopt.c suhosin_patch.c ; do
20
21 IFS=.
22 set $ac_src
23@@ -115544,7 +115547,7 @@ esac
24 zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
25 zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c zend_stream.c \
26 zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c zend_gc.c \
27- zend_closures.c zend_float.c; do
28+ zend_closures.c zend_float.c zend_canary.c zend_alloc_canary.c ; do
29
30 IFS=.
31 set $ac_src
32diff -Naurp php-5.3.6RC1/configure.in php-5.3.6RC1.oden/configure.in
33--- php-5.3.6RC1/configure.in 2011-02-20 11:45:04.157489906 +0100
34+++ php-5.3.6RC1.oden/configure.in 2011-02-20 11:50:19.295835459 +0100
35@@ -286,6 +286,7 @@ sinclude(Zend/Zend.m4)
36 sinclude(TSRM/threads.m4)
37 sinclude(TSRM/tsrm.m4)
38
39+sinclude(main/suhosin_patch.m4)
40
41 divert(2)
42
43@@ -1393,7 +1394,7 @@ PHP_ADD_SOURCES(main, main.c snprintf.c
44 php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
45 strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \
46 network.c php_open_temporary_file.c php_logos.c \
47- output.c getopt.c)
48+ output.c getopt.c suhosin_patch.c )
49
50 PHP_ADD_SOURCES(main/streams, streams.c cast.c memory.c filter.c \
51 plain_wrapper.c userspace.c transports.c xp_socket.c mmap.c \
52@@ -1421,7 +1422,7 @@ PHP_ADD_SOURCES(Zend, \
53 zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
54 zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c zend_stream.c \
55 zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c zend_gc.c \
56- zend_closures.c zend_float.c)
57+ zend_closures.c zend_float.c zend_canary.c zend_alloc_canary.c )
58
59 if test -r "$abs_srcdir/Zend/zend_objects.c"; then
60 PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c zend_default_classes.c)
61diff -Naurp php-5.3.6RC1/ext/standard/dl.c php-5.3.6RC1.oden/ext/standard/dl.c
62--- php-5.3.6RC1/ext/standard/dl.c 2011-01-01 03:19:59.000000000 +0100
63+++ php-5.3.6RC1.oden/ext/standard/dl.c 2011-02-20 11:50:19.296835599 +0100
64@@ -254,6 +254,23 @@ PHPAPI int php_load_extension(char *file
65 return FAILURE;
66 }
67 }
68+
69+#if SUHOSIN_PATCH
70+ if (strncmp("suhosin", module_entry->name, sizeof("suhosin")-1) == 0) {
71+ void *log_func;
72+ /* sucessfully loaded suhosin extension, now check for logging function replacement */
73+ log_func = (void *) DL_FETCH_SYMBOL(handle, "suhosin_log");
74+ if (log_func == NULL) {
75+ log_func = (void *) DL_FETCH_SYMBOL(handle, "_suhosin_log");
76+ }
77+ if (log_func != NULL) {
78+ zend_suhosin_log = log_func;
79+ } else {
80+ zend_suhosin_log(S_MISC, "could not replace logging function");
81+ }
82+ }
83+#endif
84+
85 return SUCCESS;
86 }
87 /* }}} */
88diff -Naurp php-5.3.6RC1/ext/standard/info.c php-5.3.6RC1.oden/ext/standard/info.c
89--- php-5.3.6RC1/ext/standard/info.c 2011-02-20 11:45:04.155489624 +0100
90+++ php-5.3.6RC1.oden/ext/standard/info.c 2011-02-20 11:50:19.297835740 +0100
91@@ -885,6 +885,33 @@ PHPAPI void php_print_info(int flag TSRM
92
93 php_info_print_table_end();
94
95+ /* Suhosin Patch */
96+ php_info_print_box_start(0);
97+ if (expose_php && !sapi_module.phpinfo_as_text) {
98+ PUTS("<a href=\"http://www.suhosin.org\"><img border=\"0\" src=\"");
99+ if (SG(request_info).request_uri) {
100+ char *elem_esc = php_info_html_esc(SG(request_info).request_uri TSRMLS_CC);
101+ PUTS(elem_esc);
102+ efree(elem_esc);
103+ }
104+ PUTS("?="SUHOSIN_LOGO_GUID"\" alt=\"Suhosin logo\" /></a>\n");
105+ }
106+ PUTS("This server is protected with the Suhosin Patch ");
107+ if (sapi_module.phpinfo_as_text) {
108+ PUTS(SUHOSIN_PATCH_VERSION);
109+ } else {
110+ zend_html_puts(SUHOSIN_PATCH_VERSION, strlen(SUHOSIN_PATCH_VERSION) TSRMLS_CC);
111+ }
112+ PUTS(!sapi_module.phpinfo_as_text?"<br />":"\n");
113+ if (sapi_module.phpinfo_as_text) {
114+ PUTS("Copyright (c) 2006-2007 Hardened-PHP Project\n");
115+ PUTS("Copyright (c) 2007-2009 SektionEins GmbH\n");
116+ } else {
117+ PUTS("Copyright (c) 2006-2007 <a href=\"http://www.hardened-php.net/\">Hardened-PHP Project</a>\n");
118+ PUTS("Copyright (c) 2007-2009 <a href=\"http://www.sektioneins.de/\">SektionEins GmbH</a>\n");
119+ }
120+ php_info_print_box_end();
121+
122 /* Zend Engine */
123 php_info_print_box_start(0);
124 if (expose_php && !sapi_module.phpinfo_as_text) {
125diff -Naurp php-5.3.6RC1/ext/standard/syslog.c php-5.3.6RC1.oden/ext/standard/syslog.c
126--- php-5.3.6RC1/ext/standard/syslog.c 2011-01-01 03:19:59.000000000 +0100
127+++ php-5.3.6RC1.oden/ext/standard/syslog.c 2011-02-20 11:50:19.299836022 +0100
128@@ -42,6 +42,7 @@ static void start_syslog(TSRMLS_D);
129 */
130 PHP_MINIT_FUNCTION(syslog)
131 {
132+#if !SUHOSIN_PATCH
133 /* error levels */
134 REGISTER_LONG_CONSTANT("LOG_EMERG", LOG_EMERG, CONST_CS | CONST_PERSISTENT); /* system unusable */
135 REGISTER_LONG_CONSTANT("LOG_ALERT", LOG_ALERT, CONST_CS | CONST_PERSISTENT); /* immediate action required */
136@@ -97,6 +98,7 @@ PHP_MINIT_FUNCTION(syslog)
137 /* AIX doesn't have LOG_PERROR */
138 REGISTER_LONG_CONSTANT("LOG_PERROR", LOG_PERROR, CONST_CS | CONST_PERSISTENT); /*log to stderr*/
139 #endif
140+#endif
141 BG(syslog_device)=NULL;
142
143 return SUCCESS;
144diff -Naurp php-5.3.6RC1/main/fopen_wrappers.c php-5.3.6RC1.oden/main/fopen_wrappers.c
145--- php-5.3.6RC1/main/fopen_wrappers.c 2011-01-18 23:20:09.000000000 +0100
146+++ php-5.3.6RC1.oden/main/fopen_wrappers.c 2011-02-20 11:50:19.299836022 +0100
147@@ -85,13 +85,8 @@ or a tightening during activation/runtim
148 PHPAPI ZEND_INI_MH(OnUpdateBaseDir)
149 {
150 char **p, *pathbuf, *ptr, *end;
151-#ifndef ZTS
152- char *base = (char *) mh_arg2;
153-#else
154- char *base = (char *) ts_resource(*((int *) mh_arg2));
155-#endif
156
157- p = (char **) (base + (size_t) mh_arg1);
158+ p = &PG(open_basedir);
159
160 if (stage == PHP_INI_STAGE_STARTUP || stage == PHP_INI_STAGE_SHUTDOWN || stage == PHP_INI_STAGE_ACTIVATE || stage == PHP_INI_STAGE_DEACTIVATE) {
161 /* We're in a PHP_INI_SYSTEM context, no restrictions */
162diff -Naurp php-5.3.6RC1/main/main.c php-5.3.6RC1.oden/main/main.c
163--- php-5.3.6RC1/main/main.c 2011-02-08 22:40:51.000000000 +0100
164+++ php-5.3.6RC1.oden/main/main.c 2011-02-20 11:50:19.301836304 +0100
165@@ -90,6 +90,9 @@
166
167 #include "SAPI.h"
168 #include "rfc1867.h"
169+#if SUHOSIN_PATCH
170+#include "suhosin_globals.h"
171+#endif
172
173 #if HAVE_SYS_MMAN_H
174 # include <sys/mman.h>
175@@ -490,7 +493,7 @@ PHP_INI_BEGIN()
176 STD_PHP_INI_ENTRY("extension_dir", PHP_EXTENSION_DIR, PHP_INI_SYSTEM, OnUpdateStringUnempty, extension_dir, php_core_globals, core_globals)
177 STD_PHP_INI_ENTRY("include_path", PHP_INCLUDE_PATH, PHP_INI_ALL, OnUpdateStringUnempty, include_path, php_core_globals, core_globals)
178 PHP_INI_ENTRY("max_execution_time", "30", PHP_INI_ALL, OnUpdateTimeout)
179- STD_PHP_INI_ENTRY("open_basedir", NULL, PHP_INI_ALL, OnUpdateBaseDir, open_basedir, php_core_globals, core_globals)
180+ PHP_INI_ENTRY("open_basedir", NULL, PHP_INI_ALL, OnUpdateBaseDir)
181 STD_PHP_INI_ENTRY("safe_mode_exec_dir", PHP_SAFE_MODE_EXEC_DIR, PHP_INI_SYSTEM, OnUpdateString, safe_mode_exec_dir, php_core_globals, core_globals)
182
183 STD_PHP_INI_BOOLEAN("file_uploads", "1", PHP_INI_SYSTEM, OnUpdateBool, file_uploads, php_core_globals, core_globals)
184@@ -1781,6 +1784,10 @@ void dummy_invalid_parameter_handler(
185 }
186 #endif
187
188+#if SUHOSIN_PATCH
189+PHPAPI void suhosin_startup();
190+#endif
191+
192 /* {{{ php_module_startup
193 */
194 int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_modules, uint num_additional_modules)
195@@ -1825,6 +1832,10 @@ int php_module_startup(sapi_module_struc
196 tsrm_ls = ts_resource(0);
197 #endif
198
199+#if SUHOSIN_PATCH
200+ suhosin_startup();
201+#endif
202+
203 module_shutdown = 0;
204 module_startup = 1;
205 sapi_initialize_empty_request(TSRMLS_C);
206@@ -1944,7 +1955,11 @@ int php_module_startup(sapi_module_struc
207 REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_SCAN_DIR", PHP_CONFIG_FILE_SCAN_DIR, sizeof(PHP_CONFIG_FILE_SCAN_DIR)-1, CONST_PERSISTENT | CONST_CS);
208 REGISTER_MAIN_STRINGL_CONSTANT("PHP_SHLIB_SUFFIX", PHP_SHLIB_SUFFIX, sizeof(PHP_SHLIB_SUFFIX)-1, CONST_PERSISTENT | CONST_CS);
209 REGISTER_MAIN_STRINGL_CONSTANT("PHP_EOL", PHP_EOL, sizeof(PHP_EOL)-1, CONST_PERSISTENT | CONST_CS);
210- REGISTER_MAIN_LONG_CONSTANT("PHP_MAXPATHLEN", MAXPATHLEN, CONST_PERSISTENT | CONST_CS);
211+#if SUHOSIN_PATCH
212+ REGISTER_MAIN_LONG_CONSTANT("SUHOSIN_PATCH", 1, CONST_PERSISTENT | CONST_CS);
213+ REGISTER_MAIN_STRINGL_CONSTANT("SUHOSIN_PATCH_VERSION", SUHOSIN_PATCH_VERSION, sizeof(SUHOSIN_PATCH_VERSION)-1, CONST_PERSISTENT | CONST_CS);
214+#endif
215+ REGISTER_MAIN_LONG_CONSTANT("PHP_MAXPATHLEN", MAXPATHLEN, CONST_PERSISTENT | CONST_CS);
216 REGISTER_MAIN_LONG_CONSTANT("PHP_INT_MAX", LONG_MAX, CONST_PERSISTENT | CONST_CS);
217 REGISTER_MAIN_LONG_CONSTANT("PHP_INT_SIZE", sizeof(long), CONST_PERSISTENT | CONST_CS);
218 #ifdef ZEND_MULTIBYTE
219diff -Naurp php-5.3.6RC1/main/php_config.h.in php-5.3.6RC1.oden/main/php_config.h.in
220--- php-5.3.6RC1/main/php_config.h.in 2011-02-16 21:30:44.000000000 +0100
221+++ php-5.3.6RC1.oden/main/php_config.h.in 2011-02-20 11:50:19.302836444 +0100
222@@ -851,6 +851,9 @@
223 /* Define if the target system has /dev/urandom device */
224 #undef HAVE_DEV_URANDOM
225
226+/* Suhosin-Patch for PHP */
227+#undef SUHOSIN_PATCH
228+
229 /* Whether you have AOLserver */
230 #undef HAVE_AOLSERVER
231
232diff -Naurp php-5.3.6RC1/main/php.h php-5.3.6RC1.oden/main/php.h
233--- php-5.3.6RC1/main/php.h 2011-01-01 03:19:59.000000000 +0100
234+++ php-5.3.6RC1.oden/main/php.h 2011-02-20 11:50:19.303836584 +0100
235@@ -453,6 +453,10 @@ END_EXTERN_C()
236 #endif
237 #endif /* !XtOffsetOf */
238
239+#if SUHOSIN_PATCH
240+#include "suhosin_patch.h"
241+#endif
242+
243 #endif
244
245 /*
246diff -Naurp php-5.3.6RC1/main/php_logos.c php-5.3.6RC1.oden/main/php_logos.c
247--- php-5.3.6RC1/main/php_logos.c 2011-01-01 03:19:59.000000000 +0100
248+++ php-5.3.6RC1.oden/main/php_logos.c 2011-02-20 11:50:19.303836584 +0100
249@@ -50,6 +50,10 @@ PHPAPI int php_unregister_info_logo(char
250 return zend_hash_del(&phpinfo_logo_hash, logo_string, strlen(logo_string));
251 }
252
253+#if SUHOSIN_PATCH
254+#include "suhosin_logo.h"
255+#endif
256+
257 int php_init_info_logos(void)
258 {
259 if(zend_hash_init(&phpinfo_logo_hash, 0, NULL, NULL, 1)==FAILURE)
260@@ -58,7 +62,9 @@ int php_init_info_logos(void)
261 php_register_info_logo(PHP_EGG_LOGO_GUID, "image/gif", php_egg_logo, sizeof(php_egg_logo));
262 php_register_info_logo(ZEND_LOGO_GUID , "image/gif", zend_logo , sizeof(zend_logo));
263 php_register_info_logo(PLD_LOGO_GUID , "image/png", pld_logo , sizeof(pld_logo));
264-
265+#if SUHOSIN_PATCH
266+ php_register_info_logo(SUHOSIN_LOGO_GUID, "image/jpeg", suhosin_logo , sizeof(suhosin_logo));
267+#endif
268 return SUCCESS;
269 }
270
271diff -Naurp php-5.3.6RC1/main/snprintf.c php-5.3.6RC1.oden/main/snprintf.c
272--- php-5.3.6RC1/main/snprintf.c 2011-01-01 03:19:59.000000000 +0100
273+++ php-5.3.6RC1.oden/main/snprintf.c 2011-02-20 11:50:19.304836724 +0100
274@@ -780,6 +780,10 @@ static int format_converter(register buf
275 */
276 switch (*fmt) {
277 case 'Z':
278+#if SUHOSIN_PATCH
279+ zend_suhosin_log(S_MISC, "'Z' specifier within format string");
280+ goto skip_output;
281+#else
282 zvp = (zval*) va_arg(ap, zval*);
283 zend_make_printable_zval(zvp, &zcopy, &free_zcopy);
284 if (free_zcopy) {
285@@ -790,6 +794,7 @@ static int format_converter(register buf
286 if (adjust_precision && precision < s_len) {
287 s_len = precision;
288 }
289+#endif
290 break;
291 case 'u':
292 switch(modifier) {
293@@ -1091,7 +1096,11 @@ static int format_converter(register buf
294
295
296 case 'n':
297+#if SUHOSIN_PATCH
298+ zend_suhosin_log(S_MISC, "'n' specifier within format string");
299+#else
300 *(va_arg(ap, int *)) = cc;
301+#endif
302 goto skip_output;
303
304 /*
305diff -Naurp php-5.3.6RC1/main/spprintf.c php-5.3.6RC1.oden/main/spprintf.c
306--- php-5.3.6RC1/main/spprintf.c 2011-01-01 03:19:59.000000000 +0100
307+++ php-5.3.6RC1.oden/main/spprintf.c 2011-02-20 11:50:19.305836865 +0100
308@@ -388,6 +388,10 @@ static void xbuf_format_converter(smart_
309 */
310 switch (*fmt) {
311 case 'Z':
312+#if SUHOSIN_PATCH
313+ zend_suhosin_log(S_MISC, "'Z' specifier within format string");
314+ goto skip_output;
315+#else
316 zvp = (zval*) va_arg(ap, zval*);
317 zend_make_printable_zval(zvp, &zcopy, &free_zcopy);
318 if (free_zcopy) {
319@@ -398,6 +402,7 @@ static void xbuf_format_converter(smart_
320 if (adjust_precision && precision < s_len) {
321 s_len = precision;
322 }
323+#endif
324 break;
325 case 'u':
326 switch(modifier) {
327@@ -698,7 +703,11 @@ static void xbuf_format_converter(smart_
328
329
330 case 'n':
331+#if SUHOSIN_PATCH
332+ zend_suhosin_log(S_MISC, "'n' specifier within format string");
333+#else
334 *(va_arg(ap, int *)) = xbuf->len;
335+#endif
336 goto skip_output;
337
338 /*
339diff -Naurp php-5.3.6RC1/main/suhosin_globals.h php-5.3.6RC1.oden/main/suhosin_globals.h
340--- php-5.3.6RC1/main/suhosin_globals.h 1970-01-01 01:00:00.000000000 +0100
341+++ php-5.3.6RC1.oden/main/suhosin_globals.h 2011-02-20 11:50:19.306837006 +0100
342@@ -0,0 +1,61 @@
343+/*
344+ +----------------------------------------------------------------------+
345+ | Suhosin-Patch for PHP |
346+ +----------------------------------------------------------------------+
347+ | Copyright (c) 2004-2009 Stefan Esser |
348+ +----------------------------------------------------------------------+
349+ | This source file is subject to version 2.02 of the PHP license, |
350+ | that is bundled with this package in the file LICENSE, and is |
351+ | available at through the world-wide-web at |
352+ | http://www.php.net/license/2_02.txt. |
353+ | If you did not receive a copy of the PHP license and are unable to |
354+ | obtain it through the world-wide-web, please send a note to |
355+ | license@php.net so we can mail you a copy immediately. |
356+ +----------------------------------------------------------------------+
357+ | Author: Stefan Esser <stefan.esser@sektioneins.de> |
358+ +----------------------------------------------------------------------+
359+ */
360+
361+#ifndef SUHOSIN_GLOBALS_H
362+#define SUHOSIN_GLOBALS_H
363+
364+typedef struct _suhosin_patch_globals suhosin_patch_globals_struct;
365+
366+#ifdef ZTS
367+# define SPG(v) TSRMG(suhosin_patch_globals_id, suhosin_patch_globals_struct *, v)
368+extern int suhosin_patch_globals_id;
369+#else
370+# define SPG(v) (suhosin_patch_globals.v)
371+extern struct _suhosin_patch_globals suhosin_patch_globals;
372+#endif
373+
374+
375+struct _suhosin_patch_globals {
376+ /* logging */
377+ int log_syslog;
378+ int log_syslog_facility;
379+ int log_syslog_priority;
380+ int log_sapi;
381+ int log_script;
382+ int log_phpscript;
383+ char *log_scriptname;
384+ char *log_phpscriptname;
385+ zend_bool log_phpscript_is_safe;
386+ zend_bool log_use_x_forwarded_for;
387+
388+ /* memory manager canary protection */
389+ unsigned int canary_1;
390+ unsigned int canary_2;
391+ unsigned int canary_3;
392+ unsigned int dummy;
393+};
394+
395+
396+#endif /* SUHOSIN_GLOBALS_H */
397+
398+/*
399+ * Local variables:
400+ * tab-width: 4
401+ * c-basic-offset: 4
402+ * End:
403+ */
404diff -Naurp php-5.3.6RC1/main/suhosin_logo.h php-5.3.6RC1.oden/main/suhosin_logo.h
405--- php-5.3.6RC1/main/suhosin_logo.h 1970-01-01 01:00:00.000000000 +0100
406+++ php-5.3.6RC1.oden/main/suhosin_logo.h 2011-02-20 11:50:19.306837006 +0100
407@@ -0,0 +1,178 @@
408+static unsigned char suhosin_logo[] =
409+ "\xff\xd8\xff\xe0\x00\x10\x4a\x46\x49\x46\x00\x01\x01\x01\x00\x48"
410+ "\x00\x48\x00\x00\xff\xe1\x00\x16\x45\x78\x69\x66\x00\x00\x4d\x4d"
411+ "\x00\x2a\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\xff\xdb\x00\x43"
412+ "\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
413+ "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
414+ "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
415+ "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
416+ "\x01\xff\xc0\x00\x0b\x08\x00\x27\x00\x71\x01\x01\x22\x00\xff\xc4"
417+ "\x00\x1e\x00\x00\x02\x02\x02\x03\x01\x01\x00\x00\x00\x00\x00\x00"
418+ "\x00\x00\x00\x00\x09\x06\x08\x05\x07\x02\x03\x0a\x01\x04\xff\xc4"
419+ "\x00\x32\x10\x00\x01\x04\x03\x00\x02\x00\x05\x01\x05\x09\x01\x00"
420+ "\x00\x00\x00\x05\x02\x03\x04\x06\x01\x07\x08\x00\x09\x11\x12\x13"
421+ "\x14\x21\x15\x0a\x16\x31\x56\x96\x17\x18\x19\x23\x32\x41\x58\x98"
422+ "\xd4\xd6\xff\xda\x00\x08\x01\x01\x00\x00\x3f\x00\xf4\xc1\xe1\xe5"
423+ "\x69\xe9\x3e\xb9\xd1\x7c\x8a\x2e\x9d\x66\xe8\x3b\x29\x4d\x7f\x46"
424+ "\xba\x58\x55\x54\x8d\xb1\x5f\xaa\xd9\x8d\x51\x2b\xb6\x27\x5a\x69"
425+ "\xd1\x43\xaf\x16\x1a\xf0\xb2\xb1\xe9\x6d\x9f\xc2\xa4\x36\x18\xb5"
426+ "\x85\x10\x41\xbe\xfc\x09\xac\x49\x29\x11\xd4\x32\x97\xec\x08\x13"
427+ "\xc1\x2d\x20\xc3\x59\xeb\x26\x05\xd8\x6b\x76\x31\x43\x8f\x57\xcf"
428+ "\x84\x9f\x14\xa8\x53\x81\x0b\xc3\x64\x80\xa3\x02\x0a\x41\x75\xf8"
429+ "\x44\x85\x93\x81\x22\x3c\xd8\x13\xe1\xbe\xf4\x59\x91\x1f\x6a\x44"
430+ "\x77\x5c\x69\xc4\x2f\x39\x5f\x0f\x2a\x8d\xeb\xba\xf8\xc3\x56\x6c"
431+ "\x3b\x36\xa7\xda\xbd\x4d\xa1\xb5\x4e\xc6\xa7\xa4\x3a\xec\x15\x2d"
432+ "\xa5\xb3\xea\x5a\xdc\xac\x46\xac\x01\x60\xd8\x43\xc8\x8e\x8b\xb1"
433+ "\x40\x4c\x95\x8b\x34\x41\x28\x52\x91\x28\x43\xd3\xa3\xb6\xa7\x55"
434+ "\x15\xe7\x5a\x96\xcb\xf1\xda\xe5\x55\xee\xfe\x1e\xbd\xd9\x41\xd3"
435+ "\x28\xfd\x97\xca\x57\x2b\x85\x9c\xa4\x30\x95\xaa\xa5\x57\xa2\x35"
436+ "\x15\x86\xcb\x61\x34\x41\xe4\xc7\x80\x20\x18\x21\x17\x09\x85\x0b"
437+ "\x14\x9d\x21\x68\x62\x1c\x08\x11\x64\x4b\x92\xf2\xd2\xd3\x2d\x2d"
438+ "\x6a\xc2\x73\x6b\x3c\x3c\x8b\x9e\xbc\x52\xaa\xa4\xab\x81\x6c\xf6"
439+ "\xfa\xbd\x70\xc5\xc6\x7b\xc2\xaa\x22\x4f\x58\x04\x87\x25\x6a\x27"
440+ "\x1d\xa4\x3d\x20\x75\x72\x01\x09\x71\xe5\x1c\x9e\xc3\x2e\x36\xf3"
441+ "\xd0\xc6\x35\x2a\x43\x4d\x2d\x0e\x2d\xb4\xa1\x49\xce\x65\x1e\x52"
442+ "\x9e\xa1\xf6\x09\xcc\xdc\x63\x66\xa8\x01\xe9\x3b\x0d\xd7\x5a\x85"
443+ "\xbb\xc5\x65\xc0\x7b\x2e\x46\xa9\xd9\x56\x1d\x4c\x92\x72\x26\x4e"
444+ "\x86\xd5\x68\xae\xc4\xaa\x55\xce\xd7\x83\x59\xb3\x81\xee\xce\x74"
445+ "\x39\x39\x31\x9f\x8a\x25\xe8\xa5\xa5\xe5\x81\xf2\x11\x23\xcb\xa1"
446+ "\x1e\x43\x12\xe3\xb1\x2a\x2b\xcd\xc8\x8d\x25\x96\xa4\x47\x7d\x95"
447+ "\xa5\xc6\x9f\x61\xe4\x25\xc6\x5e\x69\xc4\xe7\x29\x5b\x6e\xb6\xa4"
448+ "\xad\x0b\x4e\x72\x95\x25\x58\x56\x33\x9c\x67\xce\xef\x0f\x17\xbf"
449+ "\x4c\x7b\x2d\xe6\xfe\x76\x35\x27\x5a\x07\x97\x67\xe8\xae\x8d\x71"
450+ "\x0f\xb2\x13\x99\xb9\xbc\x14\xad\xb3\xb7\xe6\x11\x6f\xe0\xda\x58"
451+ "\xb1\x08\xac\xa6\x6c\x2d\x7f\x05\xb7\x56\xd2\xe6\xcf\xbb\x4d\x0c"
452+ "\xe3\x50\xb2\xec\x91\xf0\x4a\xb8\xd6\x22\xb8\xa7\xf6\x67\xaf\xcf"
453+ "\x63\x7e\xd7\xe7\x42\xd8\xbd\xc3\x71\xa1\xf2\x7e\x9b\xa8\x97\x83"
454+ "\x6e\xd1\xdc\x4b\x06\x11\x2d\xae\x26\x61\x98\x72\x10\xf4\x42\x5d"
455+ "\x20\x4a\xa3\x73\xd7\xf2\xcd\x3c\x48\x32\xe4\x03\x9f\x80\x37\x08"
456+ "\x36\x11\xd0\xcb\x97\x6c\x08\xed\x6d\x33\x24\xa2\x1b\xb4\x77\xdf"
457+ "\x61\x5d\x5f\xc1\x43\xc2\x82\xeb\x0f\x5d\x84\x08\x68\xaa\xa4\x01"
458+ "\xe1\x19\xdf\xbc\x31\x65\xfe\xd1\xf5\x7d\x7a\xb2\x2a\x33\x50\x21"
459+ "\x2a\x56\x9d\xb1\x81\xab\xdb\x35\x78\x30\x83\xd9\x89\x1d\x31\xac"
460+ "\x96\x14\x07\x61\xbc\x20\x68\x42\x85\x33\x19\xac\xbe\xdb\x34\x56"
461+ "\xf1\xd5\xfd\x29\xa9\x28\xdb\xcb\x4c\x5a\x23\xdc\xf5\x96\xc5\x10"
462+ "\xa3\x35\x5b\x14\x68\xd3\x61\x62\x64\x76\x26\xcb\x17\x3e\x34\x98"
463+ "\x04\xa3\xc4\x20\x38\x90\x92\xe3\xc8\x07\x2c\x36\x74\x66\x26\x0e"
464+ "\x29\x02\x64\x29\x2d\x21\xe6\x16\x9c\x6b\xce\xa3\x89\xd9\x4f\xd3"
465+ "\xc4\xbd\xc5\x87\x79\x9c\x65\xf6\x39\x45\x60\xe8\xce\x9e\xab\x6d"
466+ "\x13\x15\x22\xe1\x5e\x4b\x38\x42\xc4\x1e\xd5\x76\xe0\xc5\xeb\x85"
467+ "\x07\x2d\x0f\xb8\xb6\xa6\xd6\x6d\x71\x0d\xa2\x43\x4c\x25\xea\xfa"
468+ "\xa1\xae\x4c\xe4\x7d\xbd\x76\xa9\xfb\x06\xc2\x83\x42\xeb\xad\xe7"
469+ "\xe9\x5f\x68\x6f\xba\xfb\x2f\x07\xce\xb8\x13\xc1\x9b\xeb\xb0\x76"
470+ "\x45\x57\x28\x7b\xea\xbe\x0f\xf4\x30\x7b\xa0\xed\xe4\x22\x93\x21"
471+ "\xfc\xbc\xe0\xb9\x75\xc1\x4f\xfc\xef\xb6\xfa\xa1\xfc\x64\xa1\x4a"
472+ "\x82\xc7\x33\xad\x75\xed\x82\xbd\x3d\xdb\xf7\xa8\xbe\x5e\xbb\x36"
473+ "\x62\x04\x9a\x2e\xc5\xd9\x9e\x9c\x3a\x0b\x98\x0b\x57\xac\xf1\x24"
474+ "\x62\x58\x83\x15\x5b\xa6\xf2\xda\x34\x70\x03\xce\x0f\x93\x1b\x12"
475+ "\xc7\xce\x54\x87\x33\x15\xd6\x53\x25\x1f\x2a\x90\x87\x12\xe3\x78"
476+ "\xef\x55\x77\x4d\x4a\xd8\x7e\xef\xd2\xfd\xd1\xaf\x3a\xaf\x55\xdb"
477+ "\x6a\x2d\x3d\x42\xac\x51\x79\xee\x91\xab\xe1\x05\x2d\x3c\x80\xa2"
478+ "\x43\xad\x22\x2e\xd5\x33\x13\xa4\x9e\x00\xe0\x04\x10\x84\xc8\xf2"
479+ "\x19\x30\x92\x1f\xaa\xc3\x28\xc9\x76\x30\x3f\xe9\x10\x61\x5e\x79"
480+ "\xd5\xf7\xdf\xd0\x54\xdb\xae\xb6\xae\xfa\xe8\xa3\x57\xe0\x6c\x2d"
481+ "\xf7\xbd\x49\xd6\x6e\x76\x79\xcc\x54\x0c\x5f\xff\x00\xbb\x06\x98"
482+ "\xa6\x9e\x89\x61\xb4\x6f\xc3\xe3\x6a\xc2\x4f\x59\x03\xc9\x80\x2c"
483+ "\x59\x24\x44\x70\x38\xd5\x96\x6a\x9e\x8b\x81\x64\xe5\xbc\xa0\x3c"
484+ "\x33\xaf\x17\x9d\xff\x00\x71\x1a\xd1\x3a\x80\x66\xb3\xd9\x31\x77"
485+ "\x0d\x12\xbd\xae\x29\xb5\x6a\xd6\xcf\x8d\x68\x87\x75\xcd\xe8\x65"
486+ "\x5a\xbe\x3c\x04\x7b\x34\xdb\x54\x19\xa4\x63\x9c\x2a\x5d\x23\xbe"
487+ "\xf4\xb1\x1c\x4d\x90\xec\x92\x2f\x49\x71\xf7\x14\xf2\x97\x9f\x15"
488+ "\x57\xed\x13\x21\x2a\xf5\x33\xd1\x2a\x52\x52\xac\xb7\x62\xd1\xcb"
489+ "\x46\x73\x8c\x67\x28\x56\x77\x86\xbf\x6f\x2a\x4e\x73\xfe\x95\x65"
490+ "\x0b\x5a\x3e\x38\xfc\xfc\xaa\x56\x3f\x86\x73\xe3\xb9\x4a\x52\x84"
491+ "\xa5\x08\x4e\x12\x94\x27\x09\x4a\x53\x8c\x61\x29\x4a\x71\xf0\x4a"
492+ "\x53\x8c\x7e\x31\x8c\x63\x18\xc6\x31\x8f\xc6\x31\xf8\xc7\x9f\x7c"
493+ "\xd5\xbb\xae\x5e\xe2\x1f\xab\x6e\x24\x34\x00\x8a\x25\x83\x70\x40"
494+ "\x1c\xcc\xda\x45\x7f\x66\x4e\x30\x2e\x94\x7e\x74\x49\xf0\xe4\x4e"
495+ "\x06\x5c\xa8\x2f\x89\x21\x2e\x98\x0e\xd9\x21\xc2\x0b\x21\x0f\xc4"
496+ "\x16\x6e\x48\xd9\xe4\xe3\x4a\x19\x1e\x64\x67\x54\xff\x00\x3a\x6d"
497+ "\x4f\x62\xb5\x00\x4a\xaa\x51\xfd\x2d\xe8\x0e\x6c\xaf\xc6\x7d\x6d"
498+ "\xc8\x88\xc7\x67\xea\x8a\x58\x02\x73\xe3\x65\x4d\xc9\x24\xc0\x3d"
499+ "\x57\xa3\x2e\x53\x16\x99\x4f\xe5\xe7\x19\x97\x3e\x3b\xcf\xc9\x4b"
500+ "\x99\x7f\x33\x25\xa5\xdf\xba\x77\x2b\xd3\x3e\xc2\x7b\x8b\x94\x07"
501+ "\xe9\x52\x5b\x43\x87\x34\x14\x86\x37\xcf\x41\x6b\x8e\x6a\xa5\x22"
502+ "\xab\xdb\x96\xa2\xcf\x46\xd8\x9b\x45\x93\xef\xd6\xdf\x3e\x99\x9c"
503+ "\x7e\x29\x10\x6b\x6c\xa2\xb8\x43\x05\x09\x44\x70\x8c\xb8\xaa\x54"
504+ "\x7c\x30\x36\x5e\x1c\x5e\x5b\x9f\x6c\x0d\x81\xee\xa0\x93\x8d\x67"
505+ "\x55\xf3\x87\xaf\xaa\x6b\x58\xf9\xbe\xb2\x36\x07\x42\x6e\xbd\x96"
506+ "\xe3\x9f\x1f\x8f\xc9\xf4\x9d\xae\x6a\x7d\x4c\x96\xbe\x5f\xc7\xcd"
507+ "\xf3\xb2\xf7\xcd\xf0\xcf\xc3\xe4\xf8\xfe\x37\x4f\x1c\x4d\xf6\x40"
508+ "\xf1\x6b\x7c\x4e\xe0\xa6\x71\xad\x56\xa7\x1c\x5c\x15\x6b\xfc\xf3"
509+ "\x01\x5d\xac\xf1\x75\x9a\x72\x6b\xaa\x28\xc5\x88\x6d\xfb\x33\x85"
510+ "\xe0\x4e\x61\xab\xeb\x31\x2c\x71\x08\x73\x11\x3b\xfc\xb5\xc0\x96"
511+ "\xcc\x87\x24\x44\xb5\x9b\x9e\xb3\x71\xba\xe9\xed\xb1\x4e\xd7\x76"
512+ "\x6c\xd2\xb6\x05\xb7\x5a\xde\xeb\x34\x5b\x96\x16\xfb\x59\xa9\x5c"
513+ "\x4f\x55\xca\x8a\xac\x59\xb0\xe4\x54\x39\x25\xbc\x81\x37\x2a\x09"
514+ "\x5f\x9e\x3b\x6b\x7d\x1f\x69\xf3\x34\x85\x39\x84\xa7\x28\x0b\xd3"
515+ "\xfd\xfb\x4b\x7a\xea\xe7\xd2\x3c\xd3\xda\x15\x68\xbc\x73\xd3\x22"
516+ "\x6f\xd7\x72\x5b\x2b\x66\xee\xa8\x0d\x54\xe8\x5b\xf9\x92\x96\x92"
517+ "\x93\xea\x97\x4a\xc7\x43\x10\x46\x35\xc5\xc0\x60\x8a\xe4\xc1\xb5"
518+ "\x36\xc6\xae\xed\xf7\x70\xa5\x86\x99\x3d\x91\xf8\xfd\x4e\x53\xeb"
519+ "\xbb\xbd\x6d\xec\x8f\xd7\x89\x3d\x31\x7f\xd7\x78\xba\x50\xbb\x74"
520+ "\x9d\xf6\xac\x4e\xb9\x03\x9c\x79\xd5\xe1\xbd\x17\x68\xd9\x13\x0b"
521+ "\x45\x75\x88\x00\x1d\x1f\xae\x73\x6a\x1d\x5c\x6e\x44\x9f\xa6\xfa"
522+ "\x4e\xd8\x25\x8b\xc0\xbc\xb2\x99\xe3\x17\x24\xb3\x23\xe2\x48\x8b"
523+ "\xfa\x22\xe7\x7e\x8f\xe6\x3f\x5f\x55\x0d\x75\xd3\x51\x0b\xd7\xed"
524+ "\xd3\x6f\x97\x3b\x85\x42\x80\x7e\x5f\xdc\x1b\xd6\xba\xee\xc4\x80"
525+ "\xce\x06\xa9\x15\x8c\x97\x5f\x40\x69\xb2\x4d\xc5\xb2\x5c\x1e\x01"
526+ "\x87\x7e\xe0\x36\x6d\x78\x80\x4e\x3c\x02\xec\x90\x1d\x11\x81\x74"
527+ "\xa5\x8b\xa4\xa0\x56\x06\xd5\x79\x72\x85\x57\x3b\xb2\x2e\xae\x90"
528+ "\x18\x8d\x91\xb2\x0e\x44\x19\xaa\xb4\xcc\x08\xed\x46\xfa\xd7\x2b"
529+ "\x78\x58\x72\x5d\xbb\x5e\x49\xe7\xee\xf3\x8a\x9d\x22\xa4\x19\xc8"
530+ "\xe7\x08\xc3\x90\x9b\x35\x9a\xa4\x25\x8c\x4b\x9b\xa7\xf8\xbf\x81"
531+ "\xf5\xdf\x22\x66\xf1\x7e\x9f\x66\x3d\xbb\xfa\x73\x73\x4d\xfd\x67"
532+ "\x7b\xf4\xce\xc3\x62\x2e\x6f\xbb\x0c\xa2\xdc\x69\xfc\x8a\x17\x0e"
533+ "\x3a\x9e\x83\x46\xd7\xe3\x5e\x65\x86\xc0\x51\x00\xbb\x91\xe3\xe1"
534+ "\xc1\x16\xc4\xe9\x65\x5c\x14\x3e\x44\x6a\x6b\xd1\x1e\xb0\x36\xdd"
535+ "\x0b\x7d\x8a\xeb\xaf\x58\x5b\x64\x3f\x38\xed\x52\x76\xe8\x46\xf7"
536+ "\x86\x84\xb3\x93\xb1\x0b\xe5\xfd\xfd\x0d\xe9\x6d\xe4\xf1\x1b\x1d"
537+ "\x56\xb4\x34\xe4\x6a\xf5\xa4\x9c\x2c\xc9\x64\x94\xc1\xf5\x79\x6d"
538+ "\x12\x96\xf3\x47\xc5\x48\xa8\xdb\xd8\x95\x64\x29\xcf\xf6\x88\xf1"
539+ "\x95\x7a\x98\xe8\xbc\x27\x19\xce\x73\x61\xd1\xb8\xc6\x31\x8c\xe7"
540+ "\x39\xce\x77\x9e\xbc\xc6\x31\x8c\x63\xf3\x9c\xe7\x39\xc6\x31\x8f"
541+ "\xf7\xce\x7e\x1e\x3b\x7f\x0f\x0f\x0f\x13\x57\xb9\x0a\xe1\x0b\x64"
542+ "\x5f\x58\x40\xc6\xc7\x7a\x4b\xf2\x3d\xbc\x71\xf4\xa7\xd2\xca\x14"
543+ "\xe2\x98\x1a\x30\x1e\xe0\x26\x5a\x6a\xf0\x9c\x67\x38\x66\x00\xb8"
544+ "\x72\xe6\xbe\xac\xfe\x12\xd3\x0b\x56\x73\x8c\x63\xc7\x2b\xe1\xe2"
545+ "\xe8\xdd\x7b\xff\x00\xd8\xe5\x23\x6c\xce\xa8\x69\xcf\x5e\x3a\xef"
546+ "\x77\xea\xe5\xab\x0e\x82\xdb\xd9\xed\x7a\x9e\xb8\x6d\x51\x32\xdb"
547+ "\x79\xc3\x36\x9a\x2d\xa3\x50\x39\x65\x0a\x63\x0e\xe5\xd4\x39\x12"
548+ "\xbf\x8b\x98\xa4\xa1\x2d\xad\xb3\xcf\x65\x6a\x43\x78\xb3\x3b\x07"
549+ "\xd8\xd5\xea\xae\x76\xad\x6f\xf5\xff\x00\xca\x93\xab\x96\xb0\x64"
550+ "\xeb\xd6\x4a\xd5\x87\xba\xec\x24\x60\x97\x06\x76\x03\xe3\x4c\x07"
551+ "\x29\x11\x8e\x34\x25\x02\x64\x29\xf0\x25\x48\x85\x3a\x33\x8b\x7a"
552+ "\x3c\x86\x1e\x75\xa5\x61\xc6\x97\x9f\x8d\x25\xf5\xc9\xcd\xde\xc9"
553+ "\x7d\x77\xf2\xc8\x7e\x70\xaf\x73\x5f\x2d\xec\xa2\x51\x2d\x96\xfb"
554+ "\x89\xad\x80\x57\xb2\x36\x1d\x7d\x83\x45\xac\xf3\xdb\xcc\x6c\x31"
555+ "\x4f\xcf\x30\x58\xd0\x12\x28\x90\x50\x42\x86\xfb\x48\x16\x3c\xc5"
556+ "\x9c\xf8\xe7\xcc\x29\x88\xb3\x4a\x4b\x4e\x6c\xbc\xdb\xc7\xbb\xe9"
557+ "\xb6\xa0\x8b\x11\xa1\x7d\x73\xd7\xe9\xbf\x7e\xc2\x6c\x10\x8d\xee"
558+ "\x9d\xef\x63\x3a\xe0\xf5\xbe\x8c\x3e\xa1\xc7\xc5\xd1\x00\x44\x1e"
559+ "\xf3\x51\xf2\xe2\xb0\xe3\xb5\x13\x7f\x32\xf1\x8c\xa6\x22\xfe\x1f"
560+ "\x49\x4d\xbb\xcf\x3a\x5d\xed\x4c\xd2\xfc\x85\xed\x23\xd6\xc7\x50"
561+ "\xb6\x5b\x3a\x16\x83\xb8\x6f\xfd\x32\x3f\xaa\x36\x34\xbb\xf5\x96"
562+ "\xa9\xab\xcf\x9f\x8f\xac\xc3\xca\xd5\x8b\xd8\x48\x9e\x79\xaa\x30"
563+ "\x87\xca\x58\x4d\x59\x96\xb9\x4f\xc5\x1b\x1c\xd2\xda\x5b\xe6\x57"
564+ "\x29\xa1\x28\x7a\x2b\x5b\xff\x00\x12\x2f\x5e\x3f\xf3\xbb\x8e\x7f"
565+ "\xec\xc6\x98\xff\x00\xed\x3c\xa6\xdd\xa9\xdc\x7e\xa0\xf7\xd6\x99"
566+ "\x31\xa2\xf7\xaf\x6b\xe9\x82\x74\x4b\x3d\x8f\x5e\x58\x0b\x33\xab"
567+ "\xef\xc3\xaf\x84\x64\xb9\xae\xb6\x25\x5f\x62\x8f\x1c\xe3\xf4\x51"
568+ "\xb7\x96\xe3\x0e\x30\x42\xa9\x18\x39\xbf\x9e\x2a\x1f\x74\x19\x02"
569+ "\x2d\x43\x93\x06\x63\xb1\xa7\x47\x6a\xfa\x9b\x6c\xeb\xbd\xe9\xae"
570+ "\x6a\x7b\x6f\x53\x5a\x60\x5d\xb5\xcd\xe8\x67\xeb\x35\x3b\x48\xc6"
571+ "\xa6\xb3\x04\xc8\xdf\xb8\x7e\x26\x64\xb0\xc9\x18\xb0\xa7\x33\xf2"
572+ "\x4a\x8b\x22\x3b\x8d\x4b\x89\x1d\xf6\x9d\x65\xc4\x38\xd2\x54\x9c"
573+ "\xe3\xcd\x89\xe1\xe1\xe6\x3e\x70\x81\x45\x1d\x18\xf9\x31\x83\xc8"
574+ "\xbe\x14\x82\x4b\x87\x7a\x74\x28\xd2\xdd\x12\x55\x30\xe6\x0e\x49"
575+ "\x31\x8e\x48\x69\xc5\xc0\x20\x91\xe4\x48\x41\x4c\xd8\xb9\x6a\x4e"
576+ "\x21\xce\x99\x1b\x0e\xfd\x09\x4f\xa1\x79\x0f\x0f\x0f\x0f\x0f\x0f"
577+ "\x0f\x3f\x3c\xb8\x71\x27\xc7\x72\x24\xe8\xb1\xa6\xc5\x7b\x18\xc3"
578+ "\xb1\xa5\xb0\xd4\x98\xee\xe3\x19\xc6\x71\x87\x19\x79\x2b\x6d\x78"
579+ "\xc6\x71\x8c\xe3\x0a\x4e\x71\x8c\xe3\x19\xfe\x38\xf2\x3b\xfb\x8b"
580+ "\x48\xfe\x4e\xaa\xff\x00\x4f\x08\xff\x00\xc7\xe1\xfb\x8b\x48\xfe"
581+ "\x4e\xaa\xff\x00\x4f\x08\xff\x00\xc7\xe4\x95\x86\x18\x8a\xcb\x31"
582+ "\xa3\x32\xd4\x78\xf1\xdb\x43\x2c\x47\x61\xb4\x32\xcb\x2c\xb4\x9c"
583+ "\x21\xb6\x99\x69\xbc\x25\xb6\xdb\x6d\x18\xc2\x10\xda\x12\x94\xa1"
584+ "\x38\xc2\x53\x8c\x63\x18\xc7\x9d\xbe\x7f\xff\xd9"
585+ ;
586diff -Naurp php-5.3.6RC1/main/suhosin_patch.c php-5.3.6RC1.oden/main/suhosin_patch.c
587--- php-5.3.6RC1/main/suhosin_patch.c 1970-01-01 01:00:00.000000000 +0100
588+++ php-5.3.6RC1.oden/main/suhosin_patch.c 2011-02-20 11:50:19.307837147 +0100
589@@ -0,0 +1,470 @@
590+/*
591+ +----------------------------------------------------------------------+
592+ | Suhosin Patch for PHP |
593+ +----------------------------------------------------------------------+
594+ | Copyright (c) 2004-2010 Stefan Esser |
595+ +----------------------------------------------------------------------+
596+ | This source file is subject to version 2.02 of the PHP license, |
597+ | that is bundled with this package in the file LICENSE, and is |
598+ | available at through the world-wide-web at |
599+ | http://www.php.net/license/2_02.txt. |
600+ | If you did not receive a copy of the PHP license and are unable to |
601+ | obtain it through the world-wide-web, please send a note to |
602+ | license@php.net so we can mail you a copy immediately. |
603+ +----------------------------------------------------------------------+
604+ | Author: Stefan Esser <sesser@hardened-php.net> |
605+ +----------------------------------------------------------------------+
606+ */
607+/* $Id$ */
608+
609+#include "php.h"
610+
611+#include <stdio.h>
612+#include <stdlib.h>
613+#include <sys/mman.h>
614+
615+#if HAVE_UNISTD_H
616+#include <unistd.h>
617+#endif
618+#include "SAPI.h"
619+#include "php_globals.h"
620+
621+#if SUHOSIN_PATCH
622+
623+#ifdef HAVE_SYS_SOCKET_H
624+#include <sys/socket.h>
625+#endif
626+
627+#if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE)
628+#undef AF_UNIX
629+#endif
630+
631+#if defined(AF_UNIX)
632+#include <sys/un.h>
633+#endif
634+
635+#define SYSLOG_PATH "/dev/log"
636+
637+#ifdef PHP_WIN32
638+static HANDLE log_source = 0;
639+#endif
640+
641+#include "snprintf.h"
642+
643+#include "suhosin_patch.h"
644+
645+#ifdef ZTS
646+#include "suhosin_globals.h"
647+int suhosin_patch_globals_id;
648+#else
649+struct _suhosin_patch_globals suhosin_patch_globals;
650+#endif
651+
652+static char *suhosin_config = NULL;
653+
654+static zend_intptr_t SUHOSIN_POINTER_GUARD = 0;
655+
656+static void php_security_log(int loglevel, char *fmt, ...);
657+
658+static void suhosin_patch_globals_ctor(suhosin_patch_globals_struct *suhosin_patch_globals TSRMLS_DC)
659+{
660+ memset(suhosin_patch_globals, 0, sizeof(*suhosin_patch_globals));
661+}
662+
663+ZEND_API char suhosin_get_config(int element)
664+{
665+ return ((char *)SUHOSIN_MANGLE_PTR(suhosin_config))[element];
666+}
667+
668+static void suhosin_set_config(int element, char value)
669+{
670+ ((char *)SUHOSIN_MANGLE_PTR(suhosin_config))[element] = value;
671+}
672+
673+static void suhosin_read_configuration_from_environment()
674+{
675+ char *tmp;
676+
677+ /* check if canary protection should be activated or not */
678+ tmp = getenv("SUHOSIN_MM_USE_CANARY_PROTECTION");
679+ /* default to activated */
680+ suhosin_set_config(SUHOSIN_MM_USE_CANARY_PROTECTION, 1);
681+ if (tmp) {
682+ int flag = zend_atoi(tmp, 0);
683+ suhosin_set_config(SUHOSIN_MM_USE_CANARY_PROTECTION, flag);
684+ }
685+
686+ /* check if free memory should be overwritten with 0xFF or not */
687+ tmp = getenv("SUHOSIN_MM_DESTROY_FREE_MEMORY");
688+ /* default to deactivated */
689+ suhosin_set_config(SUHOSIN_MM_DESTROY_FREE_MEMORY, 0);
690+ if (tmp) {
691+ int flag = zend_atoi(tmp, 0);
692+ suhosin_set_config(SUHOSIN_MM_DESTROY_FREE_MEMORY, flag);
693+ }
694+
695+ /* check if canary violations should be ignored */
696+ tmp = getenv("SUHOSIN_MM_IGNORE_CANARY_VIOLATION");
697+ /* default to NOT ignore */
698+ suhosin_set_config(SUHOSIN_MM_IGNORE_CANARY_VIOLATION, 0);
699+ if (tmp) {
700+ int flag = zend_atoi(tmp, 0);
701+ suhosin_set_config(SUHOSIN_MM_IGNORE_CANARY_VIOLATION, flag);
702+ }
703+
704+ /* check if invalid hashtable destructors should be ignored */
705+ tmp = getenv("SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR");
706+ /* default to NOT ignore */
707+ suhosin_set_config(SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR, 0);
708+ if (tmp) {
709+ int flag = zend_atoi(tmp, 0);
710+ suhosin_set_config(SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR, flag);
711+ }
712+
713+ /* check if invalid linkedlist destructors should be ignored */
714+ tmp = getenv("SUHOSIN_LL_IGNORE_INVALID_DESTRUCTOR");
715+ /* default to NOT ignore */
716+ suhosin_set_config(SUHOSIN_LL_IGNORE_INVALID_DESTRUCTOR, 0);
717+ if (tmp) {
718+ int flag = zend_atoi(tmp, 0);
719+ suhosin_set_config(SUHOSIN_LL_IGNORE_INVALID_DESTRUCTOR, flag);
720+ }
721+
722+ suhosin_set_config(SUHOSIN_CONFIG_SET, 1);
723+}
724+
725+static void suhosin_write_protect_configuration()
726+{
727+ /* check return value of mprotect() to ensure memory is read only now */
728+ if (mprotect(SUHOSIN_MANGLE_PTR(suhosin_config), sysconf(_SC_PAGESIZE), PROT_READ) != 0) {
729+ perror("suhosin");
730+ _exit(1);
731+ }
732+}
733+
734+PHPAPI void suhosin_startup()
735+{
736+#ifdef ZTS
737+ ts_allocate_id(&suhosin_patch_globals_id, sizeof(suhosin_patch_globals_struct), (ts_allocate_ctor) suhosin_patch_globals_ctor, NULL);
738+#else
739+ suhosin_patch_globals_ctor(&suhosin_patch_globals TSRMLS_CC);
740+#endif
741+ zend_suhosin_log = php_security_log;
742+
743+ /* get the pointer guardian and ensure low 3 bits are 1 */
744+ if (SUHOSIN_POINTER_GUARD == 0) {
745+ zend_canary(&SUHOSIN_POINTER_GUARD, sizeof(SUHOSIN_POINTER_GUARD));
746+ SUHOSIN_POINTER_GUARD |= 7;
747+ }
748+
749+ if (!suhosin_config) {
750+#ifndef MAP_ANONYMOUS
751+#define MAP_ANONYMOUS MAP_ANON
752+#endif
753+ suhosin_config = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
754+ if (suhosin_config == MAP_FAILED) {
755+ perror("suhosin");
756+ _exit(1);
757+ }
758+ suhosin_config = SUHOSIN_MANGLE_PTR(suhosin_config);
759+ }
760+ if (!SUHOSIN_CONFIG(SUHOSIN_CONFIG_SET)) {
761+ suhosin_read_configuration_from_environment();
762+ suhosin_write_protect_configuration();
763+ }
764+}
765+
766+static char *loglevel2string(int loglevel)
767+{
768+ switch (loglevel) {
769+ case S_FILES:
770+ return "FILES";
771+ case S_INCLUDE:
772+ return "INCLUDE";
773+ case S_MEMORY:
774+ return "MEMORY";
775+ case S_MISC:
776+ return "MISC";
777+ case S_SESSION:
778+ return "SESSION";
779+ case S_SQL:
780+ return "SQL";
781+ case S_EXECUTOR:
782+ return "EXECUTOR";
783+ case S_VARS:
784+ return "VARS";
785+ default:
786+ return "UNKNOWN";
787+ }
788+}
789+
790+static void php_security_log(int loglevel, char *fmt, ...)
791+{
792+ int s, r, i=0;
793+#if defined(AF_UNIX)
794+ struct sockaddr_un saun;
795+#endif
796+#ifdef PHP_WIN32
797+ LPTSTR strs[2];
798+ unsigned short etype;
799+ DWORD evid;
800+#endif
801+ char buf[4096+64];
802+ char error[4096+100];
803+ char *ip_address;
804+ char *fname;
805+ char *alertstring;
806+ int lineno;
807+ va_list ap;
808+ TSRMLS_FETCH();
809+
810+ /*SDEBUG("(suhosin_log) loglevel: %d log_syslog: %u - log_sapi: %u - log_script: %u", loglevel, SPG(log_syslog), SPG(log_sapi), SPG(log_script));*/
811+
812+ if (SPG(log_use_x_forwarded_for)) {
813+ ip_address = sapi_getenv("HTTP_X_FORWARDED_FOR", 20 TSRMLS_CC);
814+ if (ip_address == NULL) {
815+ ip_address = "X-FORWARDED-FOR not set";
816+ }
817+ } else {
818+ ip_address = sapi_getenv("REMOTE_ADDR", 11 TSRMLS_CC);
819+ if (ip_address == NULL) {
820+ ip_address = "REMOTE_ADDR not set";
821+ }
822+ }
823+
824+
825+ va_start(ap, fmt);
826+ ap_php_vsnprintf(error, sizeof(error), fmt, ap);
827+ va_end(ap);
828+ while (error[i]) {
829+ if (error[i] < 32) error[i] = '.';
830+ i++;
831+ }
832+
833+/* if (SPG(simulation)) {
834+ alertstring = "ALERT-SIMULATION";
835+ } else { */
836+ alertstring = "ALERT";
837+/* }*/
838+
839+ if (zend_is_executing(TSRMLS_C)) {
840+ if (EG(current_execute_data)) {
841+ lineno = EG(current_execute_data)->opline->lineno;
842+ fname = EG(current_execute_data)->op_array->filename;
843+ } else {
844+ lineno = zend_get_executed_lineno(TSRMLS_C);
845+ fname = zend_get_executed_filename(TSRMLS_C);
846+ }
847+ ap_php_snprintf(buf, sizeof(buf), "%s - %s (attacker '%s', file '%s', line %u)", alertstring, error, ip_address, fname, lineno);
848+ } else {
849+ fname = sapi_getenv("SCRIPT_FILENAME", 15 TSRMLS_CC);
850+ if (fname==NULL) {
851+ fname = "unknown";
852+ }
853+ ap_php_snprintf(buf, sizeof(buf), "%s - %s (attacker '%s', file '%s')", alertstring, error, ip_address, fname);
854+ }
855+
856+ /* Syslog-Logging disabled? */
857+ if (((SPG(log_syslog)|S_INTERNAL) & loglevel)==0) {
858+ goto log_sapi;
859+ }
860+
861+#if defined(AF_UNIX)
862+ ap_php_snprintf(error, sizeof(error), "<%u>suhosin[%u]: %s\n", (unsigned int)(SPG(log_syslog_facility)|SPG(log_syslog_priority)),getpid(),buf);
863+
864+ s = socket(AF_UNIX, SOCK_DGRAM, 0);
865+ if (s == -1) {
866+ goto log_sapi;
867+ }
868+
869+ memset(&saun, 0, sizeof(saun));
870+ saun.sun_family = AF_UNIX;
871+ strcpy(saun.sun_path, SYSLOG_PATH);
872+ /*saun.sun_len = sizeof(saun);*/
873+
874+ r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
875+ if (r) {
876+ close(s);
877+ s = socket(AF_UNIX, SOCK_STREAM, 0);
878+ if (s == -1) {
879+ goto log_sapi;
880+ }
881+
882+ memset(&saun, 0, sizeof(saun));
883+ saun.sun_family = AF_UNIX;
884+ strcpy(saun.sun_path, SYSLOG_PATH);
885+ /*saun.sun_len = sizeof(saun);*/
886+
887+ r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
888+ if (r) {
889+ close(s);
890+ goto log_sapi;
891+ }
892+ }
893+ send(s, error, strlen(error), 0);
894+
895+ close(s);
896+#endif
897+#ifdef PHP_WIN32
898+ ap_php_snprintf(error, sizeof(error), "suhosin[%u]: %s", getpid(),buf);
899+
900+ switch (SPG(log_syslog_priority)) { /* translate UNIX type into NT type */
901+ case 1: /*LOG_ALERT:*/
902+ etype = EVENTLOG_ERROR_TYPE;
903+ break;
904+ case 6: /*LOG_INFO:*/
905+ etype = EVENTLOG_INFORMATION_TYPE;
906+ break;
907+ default:
908+ etype = EVENTLOG_WARNING_TYPE;
909+ }
910+ evid = loglevel;
911+ strs[0] = error;
912+ /* report the event */
913+ if (log_source == NULL) {
914+ log_source = RegisterEventSource(NULL, "Suhosin-Patch-" SUHOSIN_PATCH_VERSION);
915+ }
916+ ReportEvent(log_source, etype, (unsigned short) SPG(log_syslog_priority), evid, NULL, 1, 0, strs, NULL);
917+
918+#endif
919+log_sapi:
920+ /* SAPI Logging activated? */
921+ /*SDEBUG("(suhosin_log) log_syslog: %u - log_sapi: %u - log_script: %u - log_phpscript: %u", SPG(log_syslog), SPG(log_sapi), SPG(log_script), SPG(log_phpscript));*/
922+ if (((SPG(log_sapi)|S_INTERNAL) & loglevel)!=0) {
923+ sapi_module.log_message(buf);
924+ }
925+
926+/*log_script:*/
927+ /* script logging activaed? */
928+ if (((SPG(log_script) & loglevel)!=0) && SPG(log_scriptname)!=NULL) {
929+ char cmd[8192], *cmdpos, *bufpos;
930+ FILE *in;
931+ int space;
932+
933+ ap_php_snprintf(cmd, sizeof(cmd), "%s %s \'", SPG(log_scriptname), loglevel2string(loglevel));
934+ space = sizeof(cmd) - strlen(cmd);
935+ cmdpos = cmd + strlen(cmd);
936+ bufpos = buf;
937+ if (space <= 1) return;
938+ while (space > 2 && *bufpos) {
939+ if (*bufpos == '\'') {
940+ if (space<=5) break;
941+ *cmdpos++ = '\'';
942+ *cmdpos++ = '\\';
943+ *cmdpos++ = '\'';
944+ *cmdpos++ = '\'';
945+ bufpos++;
946+ space-=4;
947+ } else {
948+ *cmdpos++ = *bufpos++;
949+ space--;
950+ }
951+ }
952+ *cmdpos++ = '\'';
953+ *cmdpos = 0;
954+
955+ if ((in=VCWD_POPEN(cmd, "r"))==NULL) {
956+ php_security_log(S_INTERNAL, "Unable to execute logging shell script: %s", SPG(log_scriptname));
957+ return;
958+ }
959+ /* read and forget the result */
960+ while (1) {
961+ int readbytes = fread(cmd, 1, sizeof(cmd), in);
962+ if (readbytes<=0) {
963+ break;
964+ }
965+ }
966+ pclose(in);
967+ }
968+/*log_phpscript:*/
969+ if ((SPG(log_phpscript) & loglevel)!=0 && EG(in_execution) && SPG(log_phpscriptname) && SPG(log_phpscriptname)[0]) {
970+ zend_file_handle file_handle;
971+ zend_op_array *new_op_array;
972+ zval *result = NULL;
973+
974+ /*long orig_execution_depth = SPG(execution_depth);*/
975+ zend_bool orig_safe_mode = PG(safe_mode);
976+ char *orig_basedir = PG(open_basedir);
977+
978+ char *phpscript = SPG(log_phpscriptname);
979+/*SDEBUG("scriptname %s", SPG(log_phpscriptname));`*/
980+#ifdef ZEND_ENGINE_2
981+ if (zend_stream_open(phpscript, &file_handle TSRMLS_CC) == SUCCESS) {
982+#else
983+ if (zend_open(phpscript, &file_handle) == SUCCESS && ZEND_IS_VALID_FILE_HANDLE(&file_handle)) {
984+ file_handle.filename = phpscript;
985+ file_handle.free_filename = 0;
986+#endif
987+ if (!file_handle.opened_path) {
988+ file_handle.opened_path = estrndup(phpscript, strlen(phpscript));
989+ }
990+ new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE TSRMLS_CC);
991+ zend_destroy_file_handle(&file_handle TSRMLS_CC);
992+ if (new_op_array) {
993+ HashTable *active_symbol_table = EG(active_symbol_table);
994+ zval *zerror, *zerror_class;
995+
996+ if (active_symbol_table == NULL) {
997+ active_symbol_table = &EG(symbol_table);
998+ }
999+ EG(return_value_ptr_ptr) = &result;
1000+ EG(active_op_array) = new_op_array;
1001+
1002+ MAKE_STD_ZVAL(zerror);
1003+ MAKE_STD_ZVAL(zerror_class);
1004+ ZVAL_STRING(zerror, buf, 1);
1005+ ZVAL_LONG(zerror_class, loglevel);
1006+
1007+ zend_hash_update(active_symbol_table, "SUHOSIN_ERROR", sizeof("SUHOSIN_ERROR"), (void **)&zerror, sizeof(zval *), NULL);
1008+ zend_hash_update(active_symbol_table, "SUHOSIN_ERRORCLASS", sizeof("SUHOSIN_ERRORCLASS"), (void **)&zerror_class, sizeof(zval *), NULL);
1009+
1010+ /*SPG(execution_depth) = 0;*/
1011+ if (SPG(log_phpscript_is_safe)) {
1012+ PG(safe_mode) = 0;
1013+ PG(open_basedir) = NULL;
1014+ }
1015+
1016+ zend_execute(new_op_array TSRMLS_CC);
1017+
1018+ /*SPG(execution_depth) = orig_execution_depth;*/
1019+ PG(safe_mode) = orig_safe_mode;
1020+ PG(open_basedir) = orig_basedir;
1021+
1022+#ifdef ZEND_ENGINE_2
1023+ destroy_op_array(new_op_array TSRMLS_CC);
1024+#else
1025+ destroy_op_array(new_op_array);
1026+#endif
1027+ efree(new_op_array);
1028+#ifdef ZEND_ENGINE_2
1029+ if (!EG(exception))
1030+#endif
1031+ {
1032+ if (EG(return_value_ptr_ptr)) {
1033+ zval_ptr_dtor(EG(return_value_ptr_ptr));
1034+ EG(return_value_ptr_ptr) = NULL;
1035+ }
1036+ }
1037+ } else {
1038+ php_security_log(S_INTERNAL, "Unable to execute logging PHP script: %s", SPG(log_phpscriptname));
1039+ return;
1040+ }
1041+ } else {
1042+ php_security_log(S_INTERNAL, "Unable to execute logging PHP script: %s", SPG(log_phpscriptname));
1043+ return;
1044+ }
1045+ }
1046+
1047+}
1048+
1049+
1050+#endif
1051+
1052+/*
1053+ * Local variables:
1054+ * tab-width: 4
1055+ * c-basic-offset: 4
1056+ * End:
1057+ * vim600: sw=4 ts=4 fdm=marker
1058+ * vim<600: sw=4 ts=4
1059+ */
1060diff -Naurp php-5.3.6RC1/main/suhosin_patch.h php-5.3.6RC1.oden/main/suhosin_patch.h
1061--- php-5.3.6RC1/main/suhosin_patch.h 1970-01-01 01:00:00.000000000 +0100
1062+++ php-5.3.6RC1.oden/main/suhosin_patch.h 2011-02-20 11:50:19.308837288 +0100
1063@@ -0,0 +1,59 @@
1064+/*
1065+ +----------------------------------------------------------------------+
1066+ | Suhosin Patch for PHP |
1067+ +----------------------------------------------------------------------+
1068+ | Copyright (c) 2004-2010 Stefan Esser |
1069+ +----------------------------------------------------------------------+
1070+ | This source file is subject to version 2.02 of the PHP license, |
1071+ | that is bundled with this package in the file LICENSE, and is |
1072+ | available at through the world-wide-web at |
1073+ | http://www.php.net/license/2_02.txt. |
1074+ | If you did not receive a copy of the PHP license and are unable to |
1075+ | obtain it through the world-wide-web, please send a note to |
1076+ | license@php.net so we can mail you a copy immediately. |
1077+ +----------------------------------------------------------------------+
1078+ | Author: Stefan Esser <stefan.esser@sektioneins.de> |
1079+ +----------------------------------------------------------------------+
1080+ */
1081+
1082+#ifndef SUHOSIN_PATCH_H
1083+#define SUHOSIN_PATCH_H
1084+
1085+#if SUHOSIN_PATCH
1086+
1087+#include "zend.h"
1088+
1089+#define SUHOSIN_PATCH_VERSION "0.9.10"
1090+
1091+#define SUHOSIN_LOGO_GUID "SUHO8567F54-D428-14d2-A769-00DA302A5F18"
1092+
1093+#define SUHOSIN_CONFIG(idx) (suhosin_get_config(idx))
1094+
1095+#define SUHOSIN_MM_USE_CANARY_PROTECTION 0
1096+#define SUHOSIN_MM_DESTROY_FREE_MEMORY 1
1097+#define SUHOSIN_MM_IGNORE_CANARY_VIOLATION 2
1098+#define SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR 3
1099+#define SUHOSIN_LL_IGNORE_INVALID_DESTRUCTOR 4
1100+
1101+#define SUHOSIN_CONFIG_SET 100
1102+
1103+#include <sys/types.h>
1104+#include <sys/stat.h>
1105+#include <sys/mman.h>
1106+
1107+#if defined(DARWIN)
1108+#include <mach/vm_param.h>
1109+#endif
1110+
1111+#define SUHOSIN_MANGLE_PTR(ptr) (ptr==NULL?NULL:((void *)((zend_intptr_t)(ptr)^SUHOSIN_POINTER_GUARD)))
1112+
1113+#endif
1114+
1115+#endif /* SUHOSIN_PATCH_H */
1116+
1117+/*
1118+ * Local variables:
1119+ * tab-width: 4
1120+ * c-basic-offset: 4
1121+ * End:
1122+ */
1123diff -Naurp php-5.3.6RC1/main/suhosin_patch.m4 php-5.3.6RC1.oden/main/suhosin_patch.m4
1124--- php-5.3.6RC1/main/suhosin_patch.m4 1970-01-01 01:00:00.000000000 +0100
1125+++ php-5.3.6RC1.oden/main/suhosin_patch.m4 2011-02-20 11:50:19.308837288 +0100
1126@@ -0,0 +1,8 @@
1127+dnl
1128+dnl $Id$
1129+dnl
1130+dnl This file contains Suhosin Patch for PHP specific autoconf functions.
1131+dnl
1132+
1133+AC_DEFINE(SUHOSIN_PATCH, 1, [Suhosin Patch])
1134+
1135diff -Naurp php-5.3.6RC1/sapi/apache/mod_php5.c php-5.3.6RC1.oden/sapi/apache/mod_php5.c
1136--- php-5.3.6RC1/sapi/apache/mod_php5.c 2011-01-01 03:19:59.000000000 +0100
1137+++ php-5.3.6RC1.oden/sapi/apache/mod_php5.c 2011-02-20 11:50:19.309837429 +0100
1138@@ -969,7 +969,11 @@ static void php_init_handler(server_rec
1139 {
1140 TSRMLS_FETCH();
1141 if (PG(expose_php)) {
1142+#if SUHOSIN_PATCH
1143+ ap_add_version_component("PHP/" PHP_VERSION " with Suhosin-Patch");
1144+#else
1145 ap_add_version_component("PHP/" PHP_VERSION);
1146+#endif
1147 }
1148 }
1149 #endif
1150diff -Naurp php-5.3.6RC1/sapi/apache2filter/sapi_apache2.c php-5.3.6RC1.oden/sapi/apache2filter/sapi_apache2.c
1151--- php-5.3.6RC1/sapi/apache2filter/sapi_apache2.c 2011-01-01 03:19:59.000000000 +0100
1152+++ php-5.3.6RC1.oden/sapi/apache2filter/sapi_apache2.c 2011-02-20 11:50:19.309837429 +0100
1153@@ -583,7 +583,11 @@ static void php_apache_add_version(apr_p
1154 {
1155 TSRMLS_FETCH();
1156 if (PG(expose_php)) {
1157+#if SUHOSIN_PATCH
1158+ ap_add_version_component(p, "PHP/" PHP_VERSION " with Suhosin-Patch");
1159+#else
1160 ap_add_version_component(p, "PHP/" PHP_VERSION);
1161+#endif
1162 }
1163 }
1164
1165diff -Naurp php-5.3.6RC1/sapi/apache2handler/sapi_apache2.c php-5.3.6RC1.oden/sapi/apache2handler/sapi_apache2.c
1166--- php-5.3.6RC1/sapi/apache2handler/sapi_apache2.c 2011-02-20 11:45:04.141487654 +0100
1167+++ php-5.3.6RC1.oden/sapi/apache2handler/sapi_apache2.c 2011-02-20 11:50:19.310837570 +0100
1168@@ -407,7 +407,11 @@ static void php_apache_add_version(apr_p
1169 {
1170 TSRMLS_FETCH();
1171 if (PG(expose_php)) {
1172+#if SUHOSIN_PATCH
1173+ ap_add_version_component(p, "PHP/" PHP_VERSION " with Suhosin-Patch");
1174+#else
1175 ap_add_version_component(p, "PHP/" PHP_VERSION);
1176+#endif
1177 }
1178 }
1179
1180diff -Naurp php-5.3.6RC1/sapi/apache_hooks/mod_php5.c php-5.3.6RC1.oden/sapi/apache_hooks/mod_php5.c
1181--- php-5.3.6RC1/sapi/apache_hooks/mod_php5.c 2011-01-01 03:19:59.000000000 +0100
1182+++ php-5.3.6RC1.oden/sapi/apache_hooks/mod_php5.c 2011-02-20 11:50:19.311837711 +0100
1183@@ -1256,7 +1256,11 @@ static void php_init_handler(server_rec
1184 {
1185 TSRMLS_FETCH();
1186 if (PG(expose_php)) {
1187+#if SUHOSIN_PATCH
1188+ ap_add_version_component("PHP/" PHP_VERSION " with Suhosin-Patch");
1189+#else
1190 ap_add_version_component("PHP/" PHP_VERSION);
1191+#endif
1192 }
1193 }
1194 #endif
1195diff -Naurp php-5.3.6RC1/sapi/cgi/cgi_main.c php-5.3.6RC1.oden/sapi/cgi/cgi_main.c
1196--- php-5.3.6RC1/sapi/cgi/cgi_main.c 2011-01-01 03:19:59.000000000 +0100
1197+++ php-5.3.6RC1.oden/sapi/cgi/cgi_main.c 2011-02-20 11:57:02.864596378 +0100
1198@@ -1929,10 +1929,18 @@ consult the installation file that came
1199 SG(headers_sent) = 1;
1200 SG(request_info).no_headers = 1;
1201 }
1202+#if SUHOSIN_PATCH
1203 #if ZEND_DEBUG
1204- php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2011 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
1205+ php_printf("PHP %s with Suhosin-Patch (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2011 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
1206 #else
1207- php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2011 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
1208+ php_printf("PHP %s with Suhosin-Patch (%s) (built: %s %s)\nCopyright (c) 1997-2011 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
1209+#endif
1210+#else
1211+ #if ZEND_DEBUG
1212+ php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2011 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
1213+ #else
1214+ php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2011 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
1215+ #endif
1216 #endif
1217 php_request_shutdown((void *) 0);
1218 fcgi_shutdown();
1219diff -Naurp php-5.3.6RC1/sapi/cli/php_cli.c php-5.3.6RC1.oden/sapi/cli/php_cli.c
1220--- php-5.3.6RC1/sapi/cli/php_cli.c 2011-01-01 03:19:59.000000000 +0100
1221+++ php-5.3.6RC1.oden/sapi/cli/php_cli.c 2011-02-20 11:58:39.473179737 +0100
1222@@ -832,7 +832,11 @@ int main(int argc, char *argv[])
1223 }
1224
1225 request_started = 1;
1226- php_printf("PHP %s (%s) (built: %s %s) %s\nCopyright (c) 1997-2011 The PHP Group\n%s",
1227+ php_printf("PHP %s "
1228+#if SUHOSIN_PATCH
1229+ "with Suhosin-Patch "
1230+#endif
1231+ "(%s) (built: %s %s) %s\nCopyright (c) 1997-2011 The PHP Group\n%s",
1232 PHP_VERSION, sapi_module.name, __DATE__, __TIME__,
1233 #if ZEND_DEBUG && defined(HAVE_GCOV)
1234 "(DEBUG GCOV)",
1235diff -Naurp php-5.3.6RC1/Zend/Makefile.am php-5.3.6RC1.oden/Zend/Makefile.am
1236--- php-5.3.6RC1/Zend/Makefile.am 2009-03-18 11:18:10.000000000 +0100
1237+++ php-5.3.6RC1.oden/Zend/Makefile.am 2011-02-20 11:50:19.316838414 +0100
1238@@ -17,7 +17,7 @@ libZend_la_SOURCES=\
1239 zend_objects_API.c zend_ts_hash.c zend_stream.c \
1240 zend_default_classes.c \
1241 zend_iterators.c zend_interfaces.c zend_exceptions.c \
1242- zend_strtod.c zend_closures.c zend_float.c
1243+ zend_strtod.c zend_closures.c zend_float.c zend_canary.c zend_alloc_canary.c
1244
1245 libZend_la_LDFLAGS =
1246 libZend_la_LIBADD = @ZEND_EXTRA_LIBS@
1247diff -Naurp php-5.3.6RC1/Zend/zend_alloc.c php-5.3.6RC1.oden/Zend/zend_alloc.c
1248--- php-5.3.6RC1/Zend/zend_alloc.c 2011-02-07 11:25:34.000000000 +0100
1249+++ php-5.3.6RC1.oden/Zend/zend_alloc.c 2011-02-20 11:50:19.318838696 +0100
1250@@ -32,6 +32,10 @@
1251 # include <unistd.h>
1252 #endif
1253
1254+#if SUHOSIN_PATCH
1255+#include "suhosin_patch.h"
1256+#endif
1257+
1258 #ifdef ZEND_WIN32
1259 # include <wincrypt.h>
1260 # include <process.h>
1261@@ -59,6 +63,7 @@
1262 # define PTR_FMT "0x%0.8lx"
1263 #endif
1264
1265+#ifndef SUHOSIN_MM_CLONE_FILE
1266 #if ZEND_DEBUG
1267 void zend_debug_alloc_output(char *format, ...)
1268 {
1269@@ -76,6 +81,7 @@ void zend_debug_alloc_output(char *forma
1270 #endif
1271 }
1272 #endif
1273+#endif
1274
1275 #if (defined (__GNUC__) && __GNUC__ > 2 ) && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX)
1276 static void zend_mm_panic(const char *message) __attribute__ ((noreturn));
1277@@ -134,6 +140,8 @@ static void zend_mm_panic(const char *me
1278 # endif
1279 #endif
1280
1281+static zend_intptr_t SUHOSIN_POINTER_GUARD = 0;
1282+
1283 static zend_mm_storage* zend_mm_mem_dummy_init(void *params)
1284 {
1285 return malloc(sizeof(zend_mm_storage));
1286@@ -332,13 +340,28 @@ static const zend_mm_mem_handlers mem_ha
1287 #define MEM_BLOCK_GUARD 0x2A8FCC84
1288 #define MEM_BLOCK_LEAK 0x6C5E8F2D
1289
1290+#if SUHOSIN_MM_WITH_CANARY_PROTECTION
1291+# define CANARY_SIZE sizeof(size_t)
1292+#else
1293+# define CANARY_SIZE 0
1294+#endif
1295+
1296 /* mm block type */
1297 typedef struct _zend_mm_block_info {
1298 #if ZEND_MM_COOKIES
1299 size_t _cookie;
1300 #endif
1301- size_t _size;
1302- size_t _prev;
1303+#if SUHOSIN_MM_WITH_CANARY_PROTECTION
1304+ size_t canary_1;
1305+#endif
1306+ size_t _size;
1307+ size_t _prev;
1308+#if SUHOSIN_PATCH
1309+ size_t size;
1310+#if SUHOSIN_MM_WITH_CANARY_PROTECTION
1311+ size_t canary_2;
1312+#endif
1313+#endif
1314 } zend_mm_block_info;
1315
1316 #if ZEND_DEBUG
1317@@ -412,7 +435,7 @@ typedef struct _zend_mm_free_block {
1318 # define ZEND_MM_CACHE_STAT 0
1319 #endif
1320
1321-struct _zend_mm_heap {
1322+typedef struct _zend_mm_heap {
1323 int use_zend_alloc;
1324 void *(*_malloc)(size_t);
1325 void (*_free)(void*);
1326@@ -447,6 +470,9 @@ struct _zend_mm_heap {
1327 int miss;
1328 } cache_stat[ZEND_MM_NUM_BUCKETS+1];
1329 #endif
1330+#if SUHOSIN_PATCH
1331+ size_t canary_1,canary_2,canary_3;
1332+#endif
1333 };
1334
1335 #define ZEND_MM_SMALL_FREE_BUCKET(heap, index) \
1336@@ -520,18 +546,31 @@ static unsigned int _zend_mm_cookie = 0;
1337 /* optimized access */
1338 #define ZEND_MM_FREE_BLOCK_SIZE(b) (b)->info._size
1339
1340+#ifndef ZEND_MM_ALIGNMENT
1341+# define ZEND_MM_ALIGNMENT 8
1342+# define ZEND_MM_ALIGNMENT_LOG2 3
1343+#elif ZEND_MM_ALIGNMENT < 4
1344+# undef ZEND_MM_ALIGNMENT
1345+# undef ZEND_MM_ALIGNMENT_LOG2
1346+# define ZEND_MM_ALIGNMENT 4
1347+# define ZEND_MM_ALIGNMENT_LOG2 2
1348+#endif
1349+
1350+#define ZEND_MM_ALIGNMENT_MASK ~(ZEND_MM_ALIGNMENT-1)
1351+
1352 /* Aligned header size */
1353+#define ZEND_MM_ALIGNED_SIZE(size) ((size + ZEND_MM_ALIGNMENT - 1) & ZEND_MM_ALIGNMENT_MASK)
1354 #define ZEND_MM_ALIGNED_HEADER_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_block))
1355 #define ZEND_MM_ALIGNED_FREE_HEADER_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_small_free_block))
1356-#define ZEND_MM_MIN_ALLOC_BLOCK_SIZE ZEND_MM_ALIGNED_SIZE(ZEND_MM_ALIGNED_HEADER_SIZE + END_MAGIC_SIZE)
1357+#define ZEND_MM_MIN_ALLOC_BLOCK_SIZE ZEND_MM_ALIGNED_SIZE(ZEND_MM_ALIGNED_HEADER_SIZE + END_MAGIC_SIZE + CANARY_SIZE)
1358 #define ZEND_MM_ALIGNED_MIN_HEADER_SIZE (ZEND_MM_MIN_ALLOC_BLOCK_SIZE>ZEND_MM_ALIGNED_FREE_HEADER_SIZE?ZEND_MM_MIN_ALLOC_BLOCK_SIZE:ZEND_MM_ALIGNED_FREE_HEADER_SIZE)
1359 #define ZEND_MM_ALIGNED_SEGMENT_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_segment))
1360
1361-#define ZEND_MM_MIN_SIZE ((ZEND_MM_ALIGNED_MIN_HEADER_SIZE>(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE))?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE-(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE)):0)
1362+#define ZEND_MM_MIN_SIZE ((ZEND_MM_ALIGNED_MIN_HEADER_SIZE>(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE+CANARY_SIZE))?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE-(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE+CANARY_SIZE)):0)
1363
1364 #define ZEND_MM_MAX_SMALL_SIZE ((ZEND_MM_NUM_BUCKETS<<ZEND_MM_ALIGNMENT_LOG2)+ZEND_MM_ALIGNED_MIN_HEADER_SIZE)
1365
1366-#define ZEND_MM_TRUE_SIZE(size) ((size<ZEND_MM_MIN_SIZE)?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE):(ZEND_MM_ALIGNED_SIZE(size+ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE)))
1367+#define ZEND_MM_TRUE_SIZE(size) ((size<ZEND_MM_MIN_SIZE)?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE):(ZEND_MM_ALIGNED_SIZE(size+ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE+CANARY_SIZE)))
1368
1369 #define ZEND_MM_BUCKET_INDEX(true_size) ((true_size>>ZEND_MM_ALIGNMENT_LOG2)-(ZEND_MM_ALIGNED_MIN_HEADER_SIZE>>ZEND_MM_ALIGNMENT_LOG2))
1370
1371@@ -593,6 +632,44 @@ static unsigned int _zend_mm_cookie = 0;
1372
1373 #endif
1374
1375+#if SUHOSIN_MM_WITH_CANARY_PROTECTION
1376+
1377+# define SUHOSIN_MM_CHECK_CANARIES(block, MFUNCTION) do { \
1378+ char *p = SUHOSIN_MM_END_CANARY_PTR(block); size_t check; \
1379+ if (((block)->info.canary_1 != heap->canary_1) || ((block)->info.canary_2 != heap->canary_2)) { \
1380+ canary_mismatch: \
1381+ zend_suhosin_log(S_MEMORY, "canary mismatch on " MFUNCTION " - heap overflow detected at %p", (block)); \
1382+ if (SUHOSIN_CONFIG(SUHOSIN_MM_IGNORE_CANARY_VIOLATION) == 0) { _exit(1); } else { (block)->info.canary_1 = heap->canary_1; (block)->info.canary_2 = heap->canary_2; }\
1383+ } \
1384+ memcpy(&check, p, CANARY_SIZE); \
1385+ if (check != heap->canary_3) { \
1386+ zend_suhosin_log(S_MEMORY, "end canary mismatch on " MFUNCTION " - heap overflow detected at %p", (block)); \
1387+ if (SUHOSIN_CONFIG(SUHOSIN_MM_IGNORE_CANARY_VIOLATION) == 0) { _exit(1); } else { memcpy(p, heap->canary_3, CANARY_SIZE); } \
1388+ } \
1389+ } while (0)
1390+
1391+# define SUHOSIN_MM_SET_CANARIES(block) do { \
1392+ (block)->info.canary_1 = heap->canary_1; \
1393+ (block)->info.canary_2 = heap->canary_2; \
1394+ } while (0)
1395+
1396+# define SUHOSIN_MM_END_CANARY_PTR(block) \
1397+ (char *)(((char*)(ZEND_MM_DATA_OF(block))) + ((zend_mm_block*)(block))->info.size + END_MAGIC_SIZE)
1398+
1399+# define SUHOSIN_MM_SET_END_CANARY(block) do { \
1400+ char *p = SUHOSIN_MM_END_CANARY_PTR(block); \
1401+ memcpy(p, &heap->canary_3, CANARY_SIZE); \
1402+ } while (0)
1403+
1404+#else
1405+
1406+# define SUHOSIN_MM_CHECK_CANARIES(block, MFUNCTION)
1407+# define SUHOSIN_MM_SET_CANARIES(block)
1408+# define SUHOSIN_MM_END_CANARY_PTR(block)
1409+# define SUHOSIN_MM_SET_END_CANARY(block)
1410+
1411+#endif
1412+
1413
1414 #if ZEND_MM_HEAP_PROTECTION
1415
1416@@ -715,7 +792,7 @@ static inline unsigned int zend_mm_low_b
1417 #endif
1418 }
1419
1420-static inline void zend_mm_add_to_rest_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
1421+static void zend_mm_add_to_rest_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
1422 {
1423 zend_mm_free_block *prev, *next;
1424
1425@@ -725,14 +802,14 @@ static inline void zend_mm_add_to_rest_l
1426 mm_block->parent = NULL;
1427 }
1428
1429- prev = heap->rest_buckets[0];
1430- next = prev->next_free_block;
1431- mm_block->prev_free_block = prev;
1432- mm_block->next_free_block = next;
1433- prev->next_free_block = next->prev_free_block = mm_block;
1434+ prev = SUHOSIN_MANGLE_PTR(heap->rest_buckets[0]);
1435+ next = SUHOSIN_MANGLE_PTR(prev->next_free_block);
1436+ mm_block->prev_free_block = SUHOSIN_MANGLE_PTR(prev);
1437+ mm_block->next_free_block = SUHOSIN_MANGLE_PTR(next);
1438+ prev->next_free_block = next->prev_free_block = SUHOSIN_MANGLE_PTR(mm_block);
1439 }
1440
1441-static inline void zend_mm_add_to_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
1442+static void zend_mm_add_to_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
1443 {
1444 size_t size;
1445 size_t index;
1446@@ -749,7 +826,7 @@ static inline void zend_mm_add_to_free_l
1447 if (!*p) {
1448 *p = mm_block;
1449 mm_block->parent = p;
1450- mm_block->prev_free_block = mm_block->next_free_block = mm_block;
1451+ mm_block->prev_free_block = mm_block->next_free_block = SUHOSIN_MANGLE_PTR(mm_block);
1452 heap->large_free_bitmap |= (ZEND_MM_LONG_CONST(1) << index);
1453 } else {
1454 size_t m;
1455@@ -762,15 +839,15 @@ static inline void zend_mm_add_to_free_l
1456 if (!*p) {
1457 *p = mm_block;
1458 mm_block->parent = p;
1459- mm_block->prev_free_block = mm_block->next_free_block = mm_block;
1460+ mm_block->prev_free_block = mm_block->next_free_block = SUHOSIN_MANGLE_PTR(mm_block);
1461 break;
1462 }
1463 } else {
1464- zend_mm_free_block *next = prev->next_free_block;
1465+ zend_mm_free_block *next = SUHOSIN_MANGLE_PTR(prev->next_free_block);
1466
1467- prev->next_free_block = next->prev_free_block = mm_block;
1468- mm_block->next_free_block = next;
1469- mm_block->prev_free_block = prev;
1470+ prev->next_free_block = next->prev_free_block = SUHOSIN_MANGLE_PTR(mm_block);
1471+ mm_block->next_free_block = SUHOSIN_MANGLE_PTR(next);
1472+ mm_block->prev_free_block = SUHOSIN_MANGLE_PTR(prev);
1473 mm_block->parent = NULL;
1474 break;
1475 }
1476@@ -782,27 +859,33 @@ static inline void zend_mm_add_to_free_l
1477 index = ZEND_MM_BUCKET_INDEX(size);
1478
1479 prev = ZEND_MM_SMALL_FREE_BUCKET(heap, index);
1480- if (prev->prev_free_block == prev) {
1481+ if (SUHOSIN_MANGLE_PTR(prev->prev_free_block) == prev) {
1482 heap->free_bitmap |= (ZEND_MM_LONG_CONST(1) << index);
1483 }
1484- next = prev->next_free_block;
1485+ next = SUHOSIN_MANGLE_PTR(prev->next_free_block);
1486
1487- mm_block->prev_free_block = prev;
1488- mm_block->next_free_block = next;
1489- prev->next_free_block = next->prev_free_block = mm_block;
1490+ mm_block->prev_free_block = SUHOSIN_MANGLE_PTR(prev);
1491+ mm_block->next_free_block = SUHOSIN_MANGLE_PTR(next);
1492+ prev->next_free_block = next->prev_free_block = SUHOSIN_MANGLE_PTR(mm_block);
1493 }
1494 }
1495
1496-static inline void zend_mm_remove_from_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
1497+static void zend_mm_remove_from_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
1498 {
1499- zend_mm_free_block *prev = mm_block->prev_free_block;
1500- zend_mm_free_block *next = mm_block->next_free_block;
1501+ zend_mm_free_block *prev = SUHOSIN_MANGLE_PTR(mm_block->prev_free_block);
1502+ zend_mm_free_block *next = SUHOSIN_MANGLE_PTR(mm_block->next_free_block);
1503
1504 ZEND_MM_CHECK_MAGIC(mm_block, MEM_BLOCK_FREED);
1505
1506 if (EXPECTED(prev == mm_block)) {
1507 zend_mm_free_block **rp, **cp;
1508
1509+#if SUHOSIN_PATCH
1510+ if (next != mm_block) {
1511+ zend_suhosin_log(S_MEMORY, "zend_mm_heap corrupted at %p", mm_block);
1512+ _exit(1);
1513+ }
1514+#endif
1515 #if ZEND_MM_SAFE_UNLINKING
1516 if (UNEXPECTED(next != mm_block)) {
1517 zend_mm_panic("zend_mm_heap corrupted");
1518@@ -841,14 +924,21 @@ subst_block:
1519 }
1520 } else {
1521
1522+#if SUHOSIN_PATCH
1523+ if (SUHOSIN_MANGLE_PTR(prev->next_free_block) != mm_block || SUHOSIN_MANGLE_PTR(next->prev_free_block) != mm_block) {
1524+ zend_suhosin_log(S_MEMORY, "zend_mm_head corrupted at %p", mm_block);
1525+ _exit(1);
1526+ }
1527+#endif
1528+
1529 #if ZEND_MM_SAFE_UNLINKING
1530- if (UNEXPECTED(prev->next_free_block != mm_block) || UNEXPECTED(next->prev_free_block != mm_block)) {
1531+ if (UNEXPECTED(SUHOSIN_MANGLE_PTR(prev->next_free_block) != mm_block) || UNEXPECTED(SUHOSIN_MANGLE_PTR(next->prev_free_block) != mm_block)) {
1532 zend_mm_panic("zend_mm_heap corrupted");
1533 }
1534 #endif
1535
1536- prev->next_free_block = next;
1537- next->prev_free_block = prev;
1538+ prev->next_free_block = SUHOSIN_MANGLE_PTR(next);
1539+ next->prev_free_block = SUHOSIN_MANGLE_PTR(prev);
1540
1541 if (EXPECTED(ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(mm_block)))) {
1542 if (EXPECTED(prev == next)) {
1543@@ -864,7 +954,7 @@ subst_block:
1544 }
1545 }
1546
1547-static inline void zend_mm_init(zend_mm_heap *heap)
1548+static void zend_mm_init(zend_mm_heap *heap)
1549 {
1550 zend_mm_free_block* p;
1551 int i;
1552@@ -882,12 +972,19 @@ static inline void zend_mm_init(zend_mm_
1553 #endif
1554 p = ZEND_MM_SMALL_FREE_BUCKET(heap, 0);
1555 for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
1556- p->next_free_block = p;
1557- p->prev_free_block = p;
1558+ p->next_free_block = SUHOSIN_MANGLE_PTR(p);
1559+ p->prev_free_block = SUHOSIN_MANGLE_PTR(p);
1560 p = (zend_mm_free_block*)((char*)p + sizeof(zend_mm_free_block*) * 2);
1561 heap->large_free_buckets[i] = NULL;
1562 }
1563- heap->rest_buckets[0] = heap->rest_buckets[1] = ZEND_MM_REST_BUCKET(heap);
1564+ heap->rest_buckets[0] = heap->rest_buckets[1] = SUHOSIN_MANGLE_PTR(ZEND_MM_REST_BUCKET(heap));
1565+#if SUHOSIN_PATCH
1566+ if (SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION)) {
1567+ zend_canary(&heap->canary_1, sizeof(heap->canary_1));
1568+ zend_canary(&heap->canary_2, sizeof(heap->canary_2));
1569+ zend_canary(&heap->canary_3, sizeof(heap->canary_3));
1570+ }
1571+#endif
1572 }
1573
1574 static void zend_mm_del_segment(zend_mm_heap *heap, zend_mm_segment *segment)
1575@@ -908,12 +1005,13 @@ static void zend_mm_free_cache(zend_mm_h
1576 int i;
1577
1578 for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
1579+ /* NULL means NULL even MANGLED */
1580 if (heap->cache[i]) {
1581- zend_mm_free_block *mm_block = heap->cache[i];
1582+ zend_mm_free_block *mm_block = SUHOSIN_MANGLE_PTR(heap->cache[i]);
1583
1584 while (mm_block) {
1585 size_t size = ZEND_MM_BLOCK_SIZE(mm_block);
1586- zend_mm_free_block *q = mm_block->prev_free_block;
1587+ zend_mm_free_block *q = SUHOSIN_MANGLE_PTR(mm_block->prev_free_block);
1588 zend_mm_block *next_block = ZEND_MM_NEXT_BLOCK(mm_block);
1589
1590 heap->cached -= size;
1591@@ -1009,14 +1107,20 @@ static void zend_mm_random(unsigned char
1592 /* }}} */
1593 #endif
1594
1595+
1596 /* Notes:
1597 * - This function may alter the block_sizes values to match platform alignment
1598 * - This function does *not* perform sanity checks on the arguments
1599 */
1600-ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params)
1601+#if SUHOSIN_MM_WITH_CANARY_PROTECTION
1602+zend_mm_heap *__zend_mm_startup_canary_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params)
1603+#else
1604+static zend_mm_heap *__zend_mm_startup_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params)
1605+#endif
1606 {
1607 zend_mm_storage *storage;
1608 zend_mm_heap *heap;
1609+ zend_mm_free_block *tmp;
1610
1611 #if 0
1612 int i;
1613@@ -1050,6 +1154,12 @@ ZEND_API zend_mm_heap *zend_mm_startup_e
1614 }
1615 #endif
1616
1617+ /* get the pointer guardian and ensure low 3 bits are 1 */
1618+ if (SUHOSIN_POINTER_GUARD == 0) {
1619+ zend_canary(&SUHOSIN_POINTER_GUARD, sizeof(SUHOSIN_POINTER_GUARD));
1620+ SUHOSIN_POINTER_GUARD |= 7;
1621+ }
1622+
1623 if (zend_mm_low_bit(block_size) != zend_mm_high_bit(block_size)) {
1624 fprintf(stderr, "'block_size' must be a power of two\n");
1625 /* See http://support.microsoft.com/kb/190351 */
1626@@ -1097,12 +1207,12 @@ ZEND_API zend_mm_heap *zend_mm_startup_e
1627 heap->reserve = NULL;
1628 heap->reserve_size = reserve_size;
1629 if (reserve_size > 0) {
1630- heap->reserve = _zend_mm_alloc_int(heap, reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
1631+ heap->reserve = _zend_mm_alloc(heap, reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
1632 }
1633 if (internal) {
1634 int i;
1635 zend_mm_free_block *p, *q, *orig;
1636- zend_mm_heap *mm_heap = _zend_mm_alloc_int(heap, sizeof(zend_mm_heap) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
1637+ zend_mm_heap *mm_heap = _zend_mm_alloc(heap, sizeof(zend_mm_heap) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
1638
1639 *mm_heap = *heap;
1640
1641@@ -1110,22 +1220,22 @@ ZEND_API zend_mm_heap *zend_mm_startup_e
1642 orig = ZEND_MM_SMALL_FREE_BUCKET(heap, 0);
1643 for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
1644 q = p;
1645- while (q->prev_free_block != orig) {
1646- q = q->prev_free_block;
1647+ while (SUHOSIN_MANGLE_PTR(q->prev_free_block) != orig) {
1648+ q = SUHOSIN_MANGLE_PTR(q->prev_free_block);
1649 }
1650- q->prev_free_block = p;
1651+ q->prev_free_block = SUHOSIN_MANGLE_PTR(p);
1652 q = p;
1653- while (q->next_free_block != orig) {
1654- q = q->next_free_block;
1655+ while (SUHOSIN_MANGLE_PTR(q->next_free_block) != orig) {
1656+ q = SUHOSIN_MANGLE_PTR(q->next_free_block);
1657 }
1658- q->next_free_block = p;
1659+ q->next_free_block = SUHOSIN_MANGLE_PTR(p);
1660 p = (zend_mm_free_block*)((char*)p + sizeof(zend_mm_free_block*) * 2);
1661 orig = (zend_mm_free_block*)((char*)orig + sizeof(zend_mm_free_block*) * 2);
1662 if (mm_heap->large_free_buckets[i]) {
1663 mm_heap->large_free_buckets[i]->parent = &mm_heap->large_free_buckets[i];
1664 }
1665 }
1666- mm_heap->rest_buckets[0] = mm_heap->rest_buckets[1] = ZEND_MM_REST_BUCKET(mm_heap);
1667+ mm_heap->rest_buckets[0] = mm_heap->rest_buckets[1] = SUHOSIN_MANGLE_PTR(ZEND_MM_REST_BUCKET(mm_heap));
1668
1669 free(heap);
1670 heap = mm_heap;
1671@@ -1133,7 +1243,11 @@ ZEND_API zend_mm_heap *zend_mm_startup_e
1672 return heap;
1673 }
1674
1675-ZEND_API zend_mm_heap *zend_mm_startup(void)
1676+#if SUHOSIN_MM_WITH_CANARY_PROTECTION
1677+zend_mm_heap *__zend_mm_startup_canary(void)
1678+#else
1679+static zend_mm_heap *__zend_mm_startup(void)
1680+#endif
1681 {
1682 int i;
1683 size_t seg_size;
1684@@ -1203,6 +1317,27 @@ ZEND_API zend_mm_heap *zend_mm_startup(v
1685 return heap;
1686 }
1687
1688+#ifndef SUHOSIN_MM_CLONE_FILE
1689+zend_mm_heap_canary *__zend_mm_startup_canary_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params);
1690+zend_mm_heap_canary *__zend_mm_startup_canary(void);
1691+
1692+ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params)
1693+{
1694+ if (SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION)) {
1695+ return (zend_mm_heap *)__zend_mm_startup_canary_ex(handlers, block_size, reserve_size, internal, params);
1696+ }
1697+ return __zend_mm_startup_ex(handlers, block_size, reserve_size, internal, params);
1698+}
1699+ZEND_API zend_mm_heap *zend_mm_startup(void)
1700+{
1701+ if (SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION)) {
1702+ return (zend_mm_heap *)__zend_mm_startup_canary();
1703+ }
1704+ return __zend_mm_startup();
1705+}
1706+
1707+#endif
1708+
1709 #if ZEND_DEBUG
1710 static long zend_mm_find_leaks(zend_mm_segment *segment, zend_mm_block *b)
1711 {
1712@@ -1571,7 +1706,11 @@ static int zend_mm_check_heap(zend_mm_he
1713 }
1714 #endif
1715
1716-ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC)
1717+#if SUHOSIN_MM_WITH_CANARY_PROTECTION
1718+void __zend_mm_shutdown_canary(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC)
1719+#else
1720+static void __zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC)
1721+#endif
1722 {
1723 zend_mm_storage *storage;
1724 zend_mm_segment *segment;
1725@@ -1581,7 +1720,7 @@ ZEND_API void zend_mm_shutdown(zend_mm_h
1726 if (heap->reserve) {
1727 #if ZEND_DEBUG
1728 if (!silent) {
1729- _zend_mm_free_int(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
1730+ _zend_mm_free(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
1731 }
1732 #endif
1733 heap->reserve = NULL;
1734@@ -1664,12 +1803,23 @@ ZEND_API void zend_mm_shutdown(zend_mm_h
1735 heap->size = 0;
1736 heap->peak = 0;
1737 if (heap->reserve_size) {
1738- heap->reserve = _zend_mm_alloc_int(heap, heap->reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
1739+ heap->reserve = _zend_mm_alloc(heap, heap->reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
1740 }
1741 heap->overflow = 0;
1742 }
1743 }
1744
1745+#ifndef SUHOSIN_MM_CLONE_FILE
1746+ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC)
1747+{
1748+ if (SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION)) {
1749+ __zend_mm_shutdown_canary(heap, full_shutdown, silent TSRMLS_CC);
1750+ return;
1751+ }
1752+ __zend_mm_shutdown(heap, full_shutdown, silent TSRMLS_CC);
1753+}
1754+#endif
1755+
1756 static void zend_mm_safe_error(zend_mm_heap *heap,
1757 const char *format,
1758 size_t limit,
1759@@ -1680,7 +1830,11 @@ static void zend_mm_safe_error(zend_mm_h
1760 size_t size)
1761 {
1762 if (heap->reserve) {
1763+#if SUHOSIN_MM_WITH_CANARY_PROTECTION
1764+ _zend_mm_free_canary_int(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
1765+#else
1766 _zend_mm_free_int(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
1767+#endif
1768 heap->reserve = NULL;
1769 }
1770 if (heap->overflow == 0) {
1771@@ -1755,7 +1909,7 @@ static zend_mm_free_block *zend_mm_searc
1772 p = heap->large_free_buckets[index];
1773 for (m = true_size << (ZEND_MM_NUM_BUCKETS - index); ; m <<= 1) {
1774 if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) {
1775- return p->next_free_block;
1776+ return SUHOSIN_MANGLE_PTR(p->next_free_block);
1777 } else if (ZEND_MM_FREE_BLOCK_SIZE(p) >= true_size &&
1778 ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) {
1779 best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
1780@@ -1779,7 +1933,7 @@ static zend_mm_free_block *zend_mm_searc
1781
1782 for (p = rst; p; p = p->child[p->child[0] != NULL]) {
1783 if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) {
1784- return p->next_free_block;
1785+ return SUHOSIN_MANGLE_PTR(p->next_free_block);
1786 } else if (ZEND_MM_FREE_BLOCK_SIZE(p) > true_size &&
1787 ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) {
1788 best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
1789@@ -1788,7 +1942,7 @@ static zend_mm_free_block *zend_mm_searc
1790 }
1791
1792 if (best_fit) {
1793- return best_fit->next_free_block;
1794+ return SUHOSIN_MANGLE_PTR(best_fit->next_free_block);
1795 }
1796 bitmap = bitmap >> 1;
1797 if (!bitmap) {
1798@@ -1804,9 +1958,12 @@ static zend_mm_free_block *zend_mm_searc
1799 best_fit = p;
1800 }
1801 }
1802- return best_fit->next_free_block;
1803+ return SUHOSIN_MANGLE_PTR(best_fit->next_free_block);
1804 }
1805
1806+#if SUHOSIN_PATCH
1807+void *_zend_mm_alloc_canary_int(zend_mm_heap_canary *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
1808+#endif
1809 static void *_zend_mm_alloc_int(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
1810 {
1811 zend_mm_free_block *best_fit;
1812@@ -1816,7 +1973,7 @@ static void *_zend_mm_alloc_int(zend_mm_
1813 size_t segment_size;
1814 zend_mm_segment *segment;
1815 int keep_rest = 0;
1816-
1817+
1818 if (EXPECTED(ZEND_MM_SMALL_SIZE(true_size))) {
1819 size_t index = ZEND_MM_BUCKET_INDEX(true_size);
1820 size_t bitmap;
1821@@ -1831,9 +1988,14 @@ static void *_zend_mm_alloc_int(zend_mm_
1822 heap->cache_stat[index].count--;
1823 heap->cache_stat[index].hit++;
1824 #endif
1825- best_fit = heap->cache[index];
1826+ best_fit = SUHOSIN_MANGLE_PTR(heap->cache[index]);
1827 heap->cache[index] = best_fit->prev_free_block;
1828 heap->cached -= true_size;
1829+#if SUHOSIN_PATCH
1830+ SUHOSIN_MM_SET_CANARIES(best_fit);
1831+ ((zend_mm_block*)best_fit)->info.size = size;
1832+ SUHOSIN_MM_SET_END_CANARY(best_fit);
1833+#endif
1834 ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED);
1835 ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
1836 return ZEND_MM_DATA_OF(best_fit);
1837@@ -1847,7 +2009,7 @@ static void *_zend_mm_alloc_int(zend_mm_
1838 if (bitmap) {
1839 /* Found some "small" free block that can be used */
1840 index += zend_mm_low_bit(bitmap);
1841- best_fit = heap->free_buckets[index*2];
1842+ best_fit = SUHOSIN_MANGLE_PTR(heap->free_buckets[index*2]);
1843 #if ZEND_MM_CACHE_STAT
1844 heap->cache_stat[ZEND_MM_NUM_BUCKETS].hit++;
1845 #endif
1846@@ -1862,7 +2024,7 @@ static void *_zend_mm_alloc_int(zend_mm_
1847 best_fit = zend_mm_search_large_block(heap, true_size);
1848
1849 if (!best_fit && heap->real_size >= heap->limit - heap->block_size) {
1850- zend_mm_free_block *p = heap->rest_buckets[0];
1851+ zend_mm_free_block *p = SUHOSIN_MANGLE_PTR(heap->rest_buckets[0]);
1852 size_t best_size = -1;
1853
1854 while (p != ZEND_MM_REST_BUCKET(heap)) {
1855@@ -1874,7 +2036,7 @@ static void *_zend_mm_alloc_int(zend_mm_
1856 best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
1857 best_fit = p;
1858 }
1859- p = p->prev_free_block;
1860+ p = SUHOSIN_MANGLE_PTR(p->prev_free_block);
1861 }
1862 }
1863
1864@@ -1973,13 +2135,19 @@ zend_mm_finished_searching_for_block:
1865
1866 ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 1);
1867
1868+#if SUHOSIN_PATCH
1869+ SUHOSIN_MM_SET_CANARIES(best_fit);
1870+ ((zend_mm_block*)best_fit)->info.size = size;
1871+ SUHOSIN_MM_SET_END_CANARY(best_fit);
1872+#endif
1873+
1874 heap->size += true_size;
1875 if (heap->peak < heap->size) {
1876 heap->peak = heap->size;
1877 }
1878
1879 HANDLE_UNBLOCK_INTERRUPTIONS();
1880-
1881+
1882 return ZEND_MM_DATA_OF(best_fit);
1883 }
1884
1885@@ -1996,19 +2164,26 @@ static void _zend_mm_free_int(zend_mm_he
1886
1887 mm_block = ZEND_MM_HEADER_OF(p);
1888 size = ZEND_MM_BLOCK_SIZE(mm_block);
1889+#if SUHOSIN_PATCH
1890+ SUHOSIN_MM_CHECK_CANARIES(mm_block, "efree()");
1891+#endif
1892 ZEND_MM_CHECK_PROTECTION(mm_block);
1893
1894 #if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
1895 memset(ZEND_MM_DATA_OF(mm_block), 0x5a, mm_block->debug.size);
1896 #endif
1897-
1898+#if SUHOSIN_PATCH
1899+ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_DESTROY_FREE_MEMORY))) {
1900+ memset(ZEND_MM_DATA_OF(mm_block), 0x5a, mm_block->info.size);
1901+ }
1902+#endif
1903 #if ZEND_MM_CACHE
1904 if (EXPECTED(ZEND_MM_SMALL_SIZE(size)) && EXPECTED(heap->cached < ZEND_MM_CACHE_SIZE)) {
1905 size_t index = ZEND_MM_BUCKET_INDEX(size);
1906 zend_mm_free_block **cache = &heap->cache[index];
1907
1908 ((zend_mm_free_block*)mm_block)->prev_free_block = *cache;
1909- *cache = (zend_mm_free_block*)mm_block;
1910+ *cache = (zend_mm_free_block*)SUHOSIN_MANGLE_PTR(mm_block);
1911 heap->cached += size;
1912 ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_CACHED);
1913 #if ZEND_MM_CACHE_STAT
1914@@ -2044,6 +2219,9 @@ static void _zend_mm_free_int(zend_mm_he
1915 HANDLE_UNBLOCK_INTERRUPTIONS();
1916 }
1917
1918+#if SUHOSIN_PATCH
1919+void *_zend_mm_realloc_canary_int(zend_mm_heap_canary *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
1920+#endif
1921 static void *_zend_mm_realloc_int(zend_mm_heap *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
1922 {
1923 zend_mm_block *mm_block = ZEND_MM_HEADER_OF(p);
1924@@ -2053,11 +2231,18 @@ static void *_zend_mm_realloc_int(zend_m
1925 void *ptr;
1926
1927 if (UNEXPECTED(!p) || !ZEND_MM_VALID_PTR(p)) {
1928+#ifdef SUHOSIN_MM_WITH_CANARY_PROTECTION
1929+ return _zend_mm_alloc_canary_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
1930+#else
1931 return _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
1932+#endif
1933 }
1934 mm_block = ZEND_MM_HEADER_OF(p);
1935 true_size = ZEND_MM_TRUE_SIZE(size);
1936 orig_size = ZEND_MM_BLOCK_SIZE(mm_block);
1937+#if SUHOSIN_PATCH
1938+ SUHOSIN_MM_CHECK_CANARIES(mm_block, "erealloc()");
1939+#endif
1940 ZEND_MM_CHECK_PROTECTION(mm_block);
1941
1942 if (UNEXPECTED(true_size < size)) {
1943@@ -2089,6 +2274,11 @@ static void *_zend_mm_realloc_int(zend_m
1944 HANDLE_UNBLOCK_INTERRUPTIONS();
1945 }
1946 ZEND_MM_SET_DEBUG_INFO(mm_block, size, 0, 0);
1947+#if SUHOSIN_PATCH
1948+ SUHOSIN_MM_SET_CANARIES(mm_block);
1949+ ((zend_mm_block*)mm_block)->info.size = size;
1950+ SUHOSIN_MM_SET_END_CANARY(mm_block);
1951+#endif
1952 return p;
1953 }
1954
1955@@ -2104,17 +2294,22 @@ static void *_zend_mm_realloc_int(zend_m
1956 heap->cache_stat[index].count--;
1957 heap->cache_stat[index].hit++;
1958 #endif
1959- best_fit = heap->cache[index];
1960+ best_fit = SUHOSIN_MANGLE_PTR(heap->cache[index]);
1961 heap->cache[index] = best_fit->prev_free_block;
1962 ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED);
1963- ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
1964-
1965+ ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
1966+#if SUHOSIN_PATCH
1967+ SUHOSIN_MM_SET_CANARIES(best_fit);
1968+ ((zend_mm_block*)best_fit)->info.size = size;
1969+ SUHOSIN_MM_SET_END_CANARY(best_fit);
1970+#endif
1971+
1972 ptr = ZEND_MM_DATA_OF(best_fit);
1973
1974 #if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
1975 memcpy(ptr, p, mm_block->debug.size);
1976 #else
1977- memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE);
1978+ memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE - CANARY_SIZE);
1979 #endif
1980
1981 heap->cached -= true_size - orig_size;
1982@@ -2123,14 +2318,13 @@ static void *_zend_mm_realloc_int(zend_m
1983 cache = &heap->cache[index];
1984
1985 ((zend_mm_free_block*)mm_block)->prev_free_block = *cache;
1986- *cache = (zend_mm_free_block*)mm_block;
1987+ *cache = (zend_mm_free_block*)SUHOSIN_MANGLE_PTR(mm_block);
1988 ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_CACHED);
1989 #if ZEND_MM_CACHE_STAT
1990 if (++heap->cache_stat[index].count > heap->cache_stat[index].max_count) {
1991 heap->cache_stat[index].max_count = heap->cache_stat[index].count;
1992 }
1993 #endif
1994-
1995 return ptr;
1996 }
1997 }
1998@@ -2173,6 +2367,11 @@ static void *_zend_mm_realloc_int(zend_m
1999 heap->peak = heap->size;
2000 }
2001 HANDLE_UNBLOCK_INTERRUPTIONS();
2002+#if SUHOSIN_PATCH
2003+ SUHOSIN_MM_SET_CANARIES(mm_block);
2004+ ((zend_mm_block*)mm_block)->info.size = size;
2005+ SUHOSIN_MM_SET_END_CANARY(mm_block);
2006+#endif
2007 return p;
2008 } else if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
2009 ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(next_block, ZEND_MM_FREE_BLOCK_SIZE(next_block)))) {
2010@@ -2275,38 +2474,90 @@ out_of_memory:
2011 }
2012
2013 HANDLE_UNBLOCK_INTERRUPTIONS();
2014+#if SUHOSIN_PATCH
2015+ SUHOSIN_MM_SET_CANARIES(mm_block);
2016+ ((zend_mm_block*)mm_block)->info.size = size;
2017+ SUHOSIN_MM_SET_END_CANARY(mm_block);
2018+#endif
2019 return ZEND_MM_DATA_OF(mm_block);
2020 }
2021
2022+#ifdef SUHOSIN_MM_WITH_CANARY_PROTECTION
2023+ ptr = _zend_mm_alloc_canary_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2024+#else
2025 ptr = _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2026+#endif
2027 #if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
2028 memcpy(ptr, p, mm_block->debug.size);
2029 #else
2030- memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE);
2031+ memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE - CANARY_SIZE);
2032 #endif
2033+#ifdef SUHOSIN_MM_WITH_CANARY_PROTECTION
2034+ _zend_mm_free_canary_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2035+#else
2036 _zend_mm_free_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2037+#endif
2038 return ptr;
2039 }
2040
2041+#ifndef SUHOSIN_MM_CLONE_FILE
2042 ZEND_API void *_zend_mm_alloc(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
2043 {
2044- return _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2045+#if SUHOSIN_PATCH
2046+ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0))
2047+#endif
2048+ return _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2049+#if SUHOSIN_PATCH
2050+ return _zend_mm_alloc_canary_int((zend_mm_heap_canary *)heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2051+#endif
2052 }
2053
2054 ZEND_API void _zend_mm_free(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
2055 {
2056- _zend_mm_free_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2057+#if SUHOSIN_PATCH
2058+ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0))
2059+#endif
2060+ { _zend_mm_free_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); return; }
2061+#if SUHOSIN_PATCH
2062+ _zend_mm_free_canary_int((zend_mm_heap_canary *)heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2063+#endif
2064 }
2065
2066 ZEND_API void *_zend_mm_realloc(zend_mm_heap *heap, void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
2067 {
2068- return _zend_mm_realloc_int(heap, ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2069+#if SUHOSIN_PATCH
2070+ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0))
2071+#endif
2072+ return _zend_mm_realloc_int(heap, ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2073+#if SUHOSIN_PATCH
2074+ return _zend_mm_realloc_canary_int((zend_mm_heap_canary *)heap, ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2075+#endif
2076 }
2077
2078 ZEND_API size_t _zend_mm_block_size(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
2079 {
2080 zend_mm_block *mm_block;
2081
2082+ if (SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) != 0) {
2083+ return _zend_mm_block_size_canary((zend_mm_heap_canary *)heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2084+ }
2085+
2086+ if (!ZEND_MM_VALID_PTR(p)) {
2087+ return 0;
2088+ }
2089+ mm_block = ZEND_MM_HEADER_OF(p);
2090+ ZEND_MM_CHECK_PROTECTION(mm_block);
2091+#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
2092+ return mm_block->debug.size;
2093+#else
2094+ return ZEND_MM_BLOCK_SIZE(mm_block);
2095+#endif
2096+}
2097+#else
2098+ZEND_API size_t _zend_mm_block_size_canary(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
2099+{
2100+ zend_mm_block *mm_block;
2101+
2102 if (!ZEND_MM_VALID_PTR(p)) {
2103 return 0;
2104 }
2105@@ -2319,6 +2570,8 @@ ZEND_API size_t _zend_mm_block_size(zend
2106 #endif
2107 }
2108
2109+#endif
2110+
2111 /**********************/
2112 /* Allocation Manager */
2113 /**********************/
2114@@ -2335,6 +2588,7 @@ static int alloc_globals_id;
2115 static zend_alloc_globals alloc_globals;
2116 #endif
2117
2118+#ifndef SUHOSIN_MM_CLONE_FILE
2119 ZEND_API int is_zend_mm(TSRMLS_D)
2120 {
2121 return AG(mm_heap)->use_zend_alloc;
2122@@ -2347,7 +2601,13 @@ ZEND_API void *_emalloc(size_t size ZEND
2123 if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) {
2124 return AG(mm_heap)->_malloc(size);
2125 }
2126+#if SUHOSIN_PATCH
2127+ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0))
2128+#endif
2129 return _zend_mm_alloc_int(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2130+#if SUHOSIN_PATCH
2131+ return _zend_mm_alloc_canary_int((zend_mm_heap_canary *)AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2132+#endif
2133 }
2134
2135 ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
2136@@ -2358,7 +2618,13 @@ ZEND_API void _efree(void *ptr ZEND_FILE
2137 AG(mm_heap)->_free(ptr);
2138 return;
2139 }
2140- _zend_mm_free_int(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2141+#if SUHOSIN_PATCH
2142+ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0))
2143+#endif
2144+ { _zend_mm_free_int(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); return; }
2145+#if SUHOSIN_PATCH
2146+ _zend_mm_free_canary_int((zend_mm_heap_canary *)AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2147+#endif
2148 }
2149
2150 ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
2151@@ -2368,7 +2634,13 @@ ZEND_API void *_erealloc(void *ptr, size
2152 if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) {
2153 return AG(mm_heap)->_realloc(ptr, size);
2154 }
2155+#if SUHOSIN_PATCH
2156+ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0))
2157+#endif
2158 return _zend_mm_realloc_int(AG(mm_heap), ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2159+#if SUHOSIN_PATCH
2160+ return _zend_mm_realloc_canary_int((zend_mm_heap_canary *)AG(mm_heap), ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2161+#endif
2162 }
2163
2164 ZEND_API size_t _zend_mem_block_size(void *ptr TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
2165@@ -2376,8 +2648,15 @@ ZEND_API size_t _zend_mem_block_size(voi
2166 if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) {
2167 return 0;
2168 }
2169- return _zend_mm_block_size(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2170+#if SUHOSIN_PATCH
2171+ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0))
2172+#endif
2173+ return _zend_mm_block_size(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2174+#if SUHOSIN_PATCH
2175+ return _zend_mm_block_size_canary((zend_mm_heap_canary *)AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2176+#endif
2177 }
2178+#endif
2179
2180 #if defined(__GNUC__) && defined(i386)
2181
2182@@ -2448,7 +2727,7 @@ static inline size_t safe_address(size_t
2183 }
2184 #endif
2185
2186-
2187+#ifndef SUHOSIN_MM_CLONE_FILE
2188 ZEND_API void *_safe_emalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
2189 {
2190 return emalloc_rel(safe_address(nmemb, size, offset));
2191@@ -2561,6 +2840,7 @@ ZEND_API void shutdown_memory_manager(in
2192 {
2193 zend_mm_shutdown(AG(mm_heap), full_shutdown, silent TSRMLS_CC);
2194 }
2195+#endif
2196
2197 static void alloc_globals_ctor(zend_alloc_globals *alloc_globals TSRMLS_DC)
2198 {
2199@@ -2585,6 +2865,7 @@ static void alloc_globals_dtor(zend_allo
2200 }
2201 #endif
2202
2203+#ifndef SUHOSIN_MM_CLONE_FILE
2204 ZEND_API void start_memory_manager(TSRMLS_D)
2205 {
2206 #ifdef ZTS
2207@@ -2649,6 +2930,7 @@ ZEND_API void _full_mem_check(int silent
2208 zend_debug_alloc_output("------------------------------------------------\n");
2209 }
2210 #endif
2211+#endif
2212
2213 /*
2214 * Local variables:
2215diff -Naurp php-5.3.6RC1/Zend/zend_alloc_canary.c php-5.3.6RC1.oden/Zend/zend_alloc_canary.c
2216--- php-5.3.6RC1/Zend/zend_alloc_canary.c 1970-01-01 01:00:00.000000000 +0100
2217+++ php-5.3.6RC1.oden/Zend/zend_alloc_canary.c 2011-02-20 11:50:19.320838976 +0100
2218@@ -0,0 +1,2498 @@
2219+/*
2220+ +----------------------------------------------------------------------+
2221+ | Suhosin-Patch for PHP |
2222+ +----------------------------------------------------------------------+
2223+ | Copyright (c) 2004-2010 Stefan Esser |
2224+ +----------------------------------------------------------------------+
2225+ | This source file is subject to version 2.02 of the PHP license, |
2226+ | that is bundled with this package in the file LICENSE, and is |
2227+ | available at through the world-wide-web at |
2228+ | http://www.php.net/license/2_02.txt. |
2229+ | If you did not receive a copy of the PHP license and are unable to |
2230+ | obtain it through the world-wide-web, please send a note to |
2231+ | license@php.net so we can mail you a copy immediately. |
2232+ +----------------------------------------------------------------------+
2233+ | Author: Stefan Esser <stefan.esser@sektioneins.de> |
2234+ +----------------------------------------------------------------------+
2235+ */
2236+/* $Id$ */
2237+
2238+#include "zend.h"
2239+#include "zend_alloc.h"
2240+#include "zend_globals.h"
2241+#include "zend_operators.h"
2242+
2243+#ifdef HAVE_SIGNAL_H
2244+# include <signal.h>
2245+#endif
2246+#ifdef HAVE_UNISTD_H
2247+# include <unistd.h>
2248+#endif
2249+
2250+#if SUHOSIN_PATCH
2251+#include "suhosin_patch.h"
2252+#endif
2253+
2254+#ifdef ZEND_WIN32
2255+# include <wincrypt.h>
2256+# include <process.h>
2257+#endif
2258+
2259+#ifndef ZEND_MM_HEAP_PROTECTION
2260+# define ZEND_MM_HEAP_PROTECTION ZEND_DEBUG
2261+#endif
2262+
2263+#ifndef ZEND_MM_SAFE_UNLINKING
2264+# define ZEND_MM_SAFE_UNLINKING 1
2265+#endif
2266+
2267+#ifndef ZEND_MM_COOKIES
2268+# define ZEND_MM_COOKIES ZEND_DEBUG
2269+#endif
2270+
2271+#ifdef _WIN64
2272+# define PTR_FMT "0x%0.16I64x"
2273+/*
2274+#elif sizeof(long) == 8
2275+# define PTR_FMT "0x%0.16lx"
2276+*/
2277+#else
2278+# define PTR_FMT "0x%0.8lx"
2279+#endif
2280+
2281+#define SUHOSIN_MM_WITH_CANARY_PROTECTION 1
2282+
2283+#if (defined (__GNUC__) && __GNUC__ > 2 ) && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX)
2284+static void zend_mm_panic(const char *message) __attribute__ ((noreturn));
2285+#endif
2286+
2287+static void zend_mm_panic(const char *message)
2288+{
2289+ fprintf(stderr, "%s\n", message);
2290+/* See http://support.microsoft.com/kb/190351 */
2291+#ifdef PHP_WIN32
2292+ fflush(stderr);
2293+#endif
2294+#if ZEND_DEBUG && defined(HAVE_KILL) && defined(HAVE_GETPID)
2295+ kill(getpid(), SIGSEGV);
2296+#endif
2297+ exit(1);
2298+}
2299+
2300+/*******************/
2301+/* Storage Manager */
2302+/*******************/
2303+
2304+#ifdef ZEND_WIN32
2305+# define HAVE_MEM_WIN32 /* use VirtualAlloc() to allocate memory */
2306+#endif
2307+#define HAVE_MEM_MALLOC /* use malloc() to allocate segments */
2308+
2309+#include <sys/types.h>
2310+#include <sys/stat.h>
2311+#if HAVE_LIMITS_H
2312+#include <limits.h>
2313+#endif
2314+#include <fcntl.h>
2315+#include <errno.h>
2316+
2317+#if defined(HAVE_MEM_MMAP_ANON) || defined(HAVE_MEM_MMAP_ZERO)
2318+# ifdef HAVE_MREMAP
2319+# ifndef _GNU_SOURCE
2320+# define _GNU_SOURCE
2321+# endif
2322+# ifndef __USE_GNU
2323+# define __USE_GNU
2324+# endif
2325+# endif
2326+# include <sys/mman.h>
2327+# ifndef MAP_ANON
2328+# ifdef MAP_ANONYMOUS
2329+# define MAP_ANON MAP_ANONYMOUS
2330+# endif
2331+# endif
2332+# ifndef MREMAP_MAYMOVE
2333+# define MREMAP_MAYMOVE 0
2334+# endif
2335+# ifndef MAP_FAILED
2336+# define MAP_FAILED ((void*)-1)
2337+# endif
2338+#endif
2339+
2340+static zend_intptr_t SUHOSIN_POINTER_GUARD = 0;
2341+
2342+static zend_mm_storage* zend_mm_mem_dummy_init(void *params)
2343+{
2344+ return malloc(sizeof(zend_mm_storage));
2345+}
2346+
2347+static void zend_mm_mem_dummy_dtor(zend_mm_storage *storage)
2348+{
2349+ free(storage);
2350+}
2351+
2352+static void zend_mm_mem_dummy_compact(zend_mm_storage *storage)
2353+{
2354+}
2355+
2356+#if defined(HAVE_MEM_MMAP_ANON) || defined(HAVE_MEM_MMAP_ZERO)
2357+
2358+static zend_mm_segment* zend_mm_mem_mmap_realloc(zend_mm_storage *storage, zend_mm_segment* segment, size_t size)
2359+{
2360+ zend_mm_segment *ret;
2361+#ifdef HAVE_MREMAP
2362+#if defined(__NetBSD__)
2363+ /* NetBSD 5 supports mremap but takes an extra newp argument */
2364+ ret = (zend_mm_segment*)mremap(segment, segment->size, segment, size, MREMAP_MAYMOVE);
2365+#else
2366+ ret = (zend_mm_segment*)mremap(segment, segment->size, size, MREMAP_MAYMOVE);
2367+#endif
2368+ if (ret == MAP_FAILED) {
2369+#endif
2370+ ret = storage->handlers->_alloc(storage, size);
2371+ if (ret) {
2372+ memcpy(ret, segment, size > segment->size ? segment->size : size);
2373+ storage->handlers->_free(storage, segment);
2374+ }
2375+#ifdef HAVE_MREMAP
2376+ }
2377+#endif
2378+ return ret;
2379+}
2380+
2381+static void zend_mm_mem_mmap_free(zend_mm_storage *storage, zend_mm_segment* segment)
2382+{
2383+ munmap((void*)segment, segment->size);
2384+}
2385+
2386+#endif
2387+
2388+#ifdef HAVE_MEM_MMAP_ANON
2389+
2390+static zend_mm_segment* zend_mm_mem_mmap_anon_alloc(zend_mm_storage *storage, size_t size)
2391+{
2392+ zend_mm_segment *ret = (zend_mm_segment*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
2393+ if (ret == MAP_FAILED) {
2394+ ret = NULL;
2395+ }
2396+ return ret;
2397+}
2398+
2399+# define ZEND_MM_MEM_MMAP_ANON_DSC {"mmap_anon", zend_mm_mem_dummy_init, zend_mm_mem_dummy_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_mmap_anon_alloc, zend_mm_mem_mmap_realloc, zend_mm_mem_mmap_free}
2400+
2401+#endif
2402+
2403+#ifdef HAVE_MEM_MMAP_ZERO
2404+
2405+static int zend_mm_dev_zero_fd = -1;
2406+
2407+static zend_mm_storage* zend_mm_mem_mmap_zero_init(void *params)
2408+{
2409+ if (zend_mm_dev_zero_fd != -1) {
2410+ zend_mm_dev_zero_fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR);
2411+ }
2412+ if (zend_mm_dev_zero_fd >= 0) {
2413+ return malloc(sizeof(zend_mm_storage));
2414+ } else {
2415+ return NULL;
2416+ }
2417+}
2418+
2419+static void zend_mm_mem_mmap_zero_dtor(zend_mm_storage *storage)
2420+{
2421+ close(zend_mm_dev_zero_fd);
2422+ free(storage);
2423+}
2424+
2425+static zend_mm_segment* zend_mm_mem_mmap_zero_alloc(zend_mm_storage *storage, size_t size)
2426+{
2427+ zend_mm_segment *ret = (zend_mm_segment*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, zend_mm_dev_zero_fd, 0);
2428+ if (ret == MAP_FAILED) {
2429+ ret = NULL;
2430+ }
2431+ return ret;
2432+}
2433+
2434+# define ZEND_MM_MEM_MMAP_ZERO_DSC {"mmap_zero", zend_mm_mem_mmap_zero_init, zend_mm_mem_mmap_zero_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_mmap_zero_alloc, zend_mm_mem_mmap_realloc, zend_mm_mem_mmap_free}
2435+
2436+#endif
2437+
2438+#ifdef HAVE_MEM_WIN32
2439+
2440+static zend_mm_storage* zend_mm_mem_win32_init(void *params)
2441+{
2442+ HANDLE heap = HeapCreate(HEAP_NO_SERIALIZE, 0, 0);
2443+ zend_mm_storage* storage;
2444+
2445+ if (heap == NULL) {
2446+ return NULL;
2447+ }
2448+ storage = (zend_mm_storage*)malloc(sizeof(zend_mm_storage));
2449+ storage->data = (void*) heap;
2450+ return storage;
2451+}
2452+
2453+static void zend_mm_mem_win32_dtor(zend_mm_storage *storage)
2454+{
2455+ HeapDestroy((HANDLE)storage->data);
2456+ free(storage);
2457+}
2458+
2459+static void zend_mm_mem_win32_compact(zend_mm_storage *storage)
2460+{
2461+ HeapDestroy((HANDLE)storage->data);
2462+ storage->data = (void*)HeapCreate(HEAP_NO_SERIALIZE, 0, 0);
2463+}
2464+
2465+static zend_mm_segment* zend_mm_mem_win32_alloc(zend_mm_storage *storage, size_t size)
2466+{
2467+ return (zend_mm_segment*) HeapAlloc((HANDLE)storage->data, HEAP_NO_SERIALIZE, size);
2468+}
2469+
2470+static void zend_mm_mem_win32_free(zend_mm_storage *storage, zend_mm_segment* segment)
2471+{
2472+ HeapFree((HANDLE)storage->data, HEAP_NO_SERIALIZE, segment);
2473+}
2474+
2475+static zend_mm_segment* zend_mm_mem_win32_realloc(zend_mm_storage *storage, zend_mm_segment* segment, size_t size)
2476+{
2477+ return (zend_mm_segment*) HeapReAlloc((HANDLE)storage->data, HEAP_NO_SERIALIZE, segment, size);
2478+}
2479+
2480+# define ZEND_MM_MEM_WIN32_DSC {"win32", zend_mm_mem_win32_init, zend_mm_mem_win32_dtor, zend_mm_mem_win32_compact, zend_mm_mem_win32_alloc, zend_mm_mem_win32_realloc, zend_mm_mem_win32_free}
2481+
2482+#endif
2483+
2484+#ifdef HAVE_MEM_MALLOC
2485+
2486+static zend_mm_segment* zend_mm_mem_malloc_alloc(zend_mm_storage *storage, size_t size)
2487+{
2488+ return (zend_mm_segment*)malloc(size);
2489+}
2490+
2491+static zend_mm_segment* zend_mm_mem_malloc_realloc(zend_mm_storage *storage, zend_mm_segment *ptr, size_t size)
2492+{
2493+ return (zend_mm_segment*)realloc(ptr, size);
2494+}
2495+
2496+static void zend_mm_mem_malloc_free(zend_mm_storage *storage, zend_mm_segment *ptr)
2497+{
2498+ free(ptr);
2499+}
2500+
2501+# define ZEND_MM_MEM_MALLOC_DSC {"malloc", zend_mm_mem_dummy_init, zend_mm_mem_dummy_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_malloc_alloc, zend_mm_mem_malloc_realloc, zend_mm_mem_malloc_free}
2502+
2503+#endif
2504+
2505+static const zend_mm_mem_handlers mem_handlers[] = {
2506+#ifdef HAVE_MEM_WIN32
2507+ ZEND_MM_MEM_WIN32_DSC,
2508+#endif
2509+#ifdef HAVE_MEM_MALLOC
2510+ ZEND_MM_MEM_MALLOC_DSC,
2511+#endif
2512+#ifdef HAVE_MEM_MMAP_ANON
2513+ ZEND_MM_MEM_MMAP_ANON_DSC,
2514+#endif
2515+#ifdef HAVE_MEM_MMAP_ZERO
2516+ ZEND_MM_MEM_MMAP_ZERO_DSC,
2517+#endif
2518+ {NULL, NULL, NULL, NULL, NULL, NULL}
2519+};
2520+
2521+# define ZEND_MM_STORAGE_DTOR() heap->storage->handlers->dtor(heap->storage)
2522+# define ZEND_MM_STORAGE_ALLOC(size) heap->storage->handlers->_alloc(heap->storage, size)
2523+# define ZEND_MM_STORAGE_REALLOC(ptr, size) heap->storage->handlers->_realloc(heap->storage, ptr, size)
2524+# define ZEND_MM_STORAGE_FREE(ptr) heap->storage->handlers->_free(heap->storage, ptr)
2525+
2526+/****************/
2527+/* Heap Manager */
2528+/****************/
2529+
2530+#define MEM_BLOCK_VALID 0x7312F8DC
2531+#define MEM_BLOCK_FREED 0x99954317
2532+#define MEM_BLOCK_CACHED 0xFB8277DC
2533+#define MEM_BLOCK_GUARD 0x2A8FCC84
2534+#define MEM_BLOCK_LEAK 0x6C5E8F2D
2535+
2536+#if SUHOSIN_MM_WITH_CANARY_PROTECTION
2537+# define CANARY_SIZE sizeof(size_t)
2538+#else
2539+# define CANARY_SIZE 0
2540+#endif
2541+
2542+/* mm block type */
2543+typedef struct _zend_mm_block_info_canary {
2544+#if ZEND_MM_COOKIES
2545+ size_t _cookie;
2546+#endif
2547+#if SUHOSIN_MM_WITH_CANARY_PROTECTION
2548+ size_t canary_1;
2549+#endif
2550+ size_t _size;
2551+ size_t _prev;
2552+#if SUHOSIN_PATCH
2553+ size_t size;
2554+#if SUHOSIN_MM_WITH_CANARY_PROTECTION
2555+ size_t canary_2;
2556+#endif
2557+#endif
2558+} zend_mm_block_info_canary;
2559+
2560+#if ZEND_DEBUG
2561+
2562+typedef struct _zend_mm_debug_info_canary {
2563+ char *filename;
2564+ uint lineno;
2565+ char *orig_filename;
2566+ uint orig_lineno;
2567+ size_t size;
2568+#if ZEND_MM_HEAP_PROTECTION
2569+ unsigned int start_magic;
2570+#endif
2571+} zend_mm_debug_info_canary;
2572+
2573+#elif ZEND_MM_HEAP_PROTECTION
2574+
2575+typedef struct _zend_mm_debug_info_canary {
2576+ size_t size;
2577+ unsigned int start_magic;
2578+} zend_mm_debug_info_canary;
2579+
2580+#endif
2581+
2582+typedef struct _zend_mm_block_canary {
2583+ zend_mm_block_info_canary info;
2584+#if ZEND_DEBUG
2585+ unsigned int magic;
2586+# ifdef ZTS
2587+ THREAD_T thread_id;
2588+# endif
2589+ zend_mm_debug_info_canary debug;
2590+#elif ZEND_MM_HEAP_PROTECTION
2591+ zend_mm_debug_info_canary debug;
2592+#endif
2593+} zend_mm_block_canary;
2594+
2595+typedef struct _zend_mm_small_free_block_canary {
2596+ zend_mm_block_info_canary info;
2597+#if ZEND_DEBUG
2598+ unsigned int magic;
2599+# ifdef ZTS
2600+ THREAD_T thread_id;
2601+# endif
2602+#endif
2603+ struct _zend_mm_free_block_canary *prev_free_block;
2604+ struct _zend_mm_free_block_canary *next_free_block;
2605+} zend_mm_small_free_block_canary;
2606+
2607+typedef struct _zend_mm_free_block_canary {
2608+ zend_mm_block_info_canary info;
2609+#if ZEND_DEBUG
2610+ unsigned int magic;
2611+# ifdef ZTS
2612+ THREAD_T thread_id;
2613+# endif
2614+#endif
2615+ struct _zend_mm_free_block_canary *prev_free_block;
2616+ struct _zend_mm_free_block_canary *next_free_block;
2617+
2618+ struct _zend_mm_free_block_canary **parent;
2619+ struct _zend_mm_free_block_canary *child[2];
2620+} zend_mm_free_block_canary;
2621+
2622+#define ZEND_MM_NUM_BUCKETS (sizeof(size_t) << 3)
2623+
2624+#define ZEND_MM_CACHE 1
2625+#define ZEND_MM_CACHE_SIZE (ZEND_MM_NUM_BUCKETS * 4 * 1024)
2626+
2627+#ifndef ZEND_MM_CACHE_STAT
2628+# define ZEND_MM_CACHE_STAT 0
2629+#endif
2630+
2631+typedef struct _zend_mm_heap_canary {
2632+ int use_zend_alloc;
2633+ void *(*_malloc)(size_t);
2634+ void (*_free)(void*);
2635+ void *(*_realloc)(void*, size_t);
2636+ size_t free_bitmap;
2637+ size_t large_free_bitmap;
2638+ size_t block_size;
2639+ size_t compact_size;
2640+ zend_mm_segment *segments_list;
2641+ zend_mm_storage *storage;
2642+ size_t real_size;
2643+ size_t real_peak;
2644+ size_t limit;
2645+ size_t size;
2646+ size_t peak;
2647+ size_t reserve_size;
2648+ void *reserve;
2649+ int overflow;
2650+ int internal;
2651+#if ZEND_MM_CACHE
2652+ unsigned int cached;
2653+ zend_mm_free_block_canary *cache[ZEND_MM_NUM_BUCKETS];
2654+#endif
2655+ zend_mm_free_block_canary *free_buckets[ZEND_MM_NUM_BUCKETS*2];
2656+ zend_mm_free_block_canary *large_free_buckets[ZEND_MM_NUM_BUCKETS];
2657+ zend_mm_free_block_canary *rest_buckets[2];
2658+#if ZEND_MM_CACHE_STAT
2659+ struct {
2660+ int count;
2661+ int max_count;
2662+ int hit;
2663+ int miss;
2664+ } cache_stat[ZEND_MM_NUM_BUCKETS+1];
2665+#endif
2666+#if SUHOSIN_PATCH
2667+ size_t canary_1,canary_2,canary_3;
2668+#endif
2669+};
2670+
2671+#define ZEND_MM_SMALL_FREE_BUCKET(heap, index) \
2672+ (zend_mm_free_block_canary*) ((char*)&heap->free_buckets[index * 2] + \
2673+ sizeof(zend_mm_free_block_canary*) * 2 - \
2674+ sizeof(zend_mm_small_free_block_canary))
2675+
2676+#define ZEND_MM_REST_BUCKET(heap) \
2677+ (zend_mm_free_block_canary*)((char*)&heap->rest_buckets[0] + \
2678+ sizeof(zend_mm_free_block_canary*) * 2 - \
2679+ sizeof(zend_mm_small_free_block_canary))
2680+
2681+#if ZEND_MM_COOKIES
2682+
2683+static unsigned int _zend_mm_cookie = 0;
2684+
2685+# define ZEND_MM_COOKIE(block) \
2686+ (((size_t)(block)) ^ _zend_mm_cookie)
2687+# define ZEND_MM_SET_COOKIE(block) \
2688+ (block)->info._cookie = ZEND_MM_COOKIE(block)
2689+# define ZEND_MM_CHECK_COOKIE(block) \
2690+ if (UNEXPECTED((block)->info._cookie != ZEND_MM_COOKIE(block))) { \
2691+ zend_mm_panic("zend_mm_heap corrupted"); \
2692+ }
2693+#else
2694+# define ZEND_MM_SET_COOKIE(block)
2695+# define ZEND_MM_CHECK_COOKIE(block)
2696+#endif
2697+
2698+/* Default memory segment size */
2699+#define ZEND_MM_SEG_SIZE (256 * 1024)
2700+
2701+/* Reserved space for error reporting in case of memory overflow */
2702+#define ZEND_MM_RESERVE_SIZE (8*1024)
2703+
2704+#ifdef _WIN64
2705+# define ZEND_MM_LONG_CONST(x) (x##i64)
2706+#else
2707+# define ZEND_MM_LONG_CONST(x) (x##L)
2708+#endif
2709+
2710+#define ZEND_MM_TYPE_MASK ZEND_MM_LONG_CONST(0x3)
2711+
2712+#define ZEND_MM_FREE_BLOCK ZEND_MM_LONG_CONST(0x0)
2713+#define ZEND_MM_USED_BLOCK ZEND_MM_LONG_CONST(0x1)
2714+#define ZEND_MM_GUARD_BLOCK ZEND_MM_LONG_CONST(0x3)
2715+
2716+#define ZEND_MM_BLOCK(b, type, size) do { \
2717+ size_t _size = (size); \
2718+ (b)->info._size = (type) | _size; \
2719+ ZEND_MM_BLOCK_AT(b, _size)->info._prev = (type) | _size; \
2720+ ZEND_MM_SET_COOKIE(b); \
2721+ } while (0);
2722+#define ZEND_MM_LAST_BLOCK(b) do { \
2723+ (b)->info._size = ZEND_MM_GUARD_BLOCK | ZEND_MM_ALIGNED_HEADER_SIZE; \
2724+ ZEND_MM_SET_MAGIC(b, MEM_BLOCK_GUARD); \
2725+ } while (0);
2726+#define ZEND_MM_BLOCK_SIZE(b) ((b)->info._size & ~ZEND_MM_TYPE_MASK)
2727+#define ZEND_MM_IS_FREE_BLOCK(b) (!((b)->info._size & ZEND_MM_USED_BLOCK))
2728+#define ZEND_MM_IS_USED_BLOCK(b) ((b)->info._size & ZEND_MM_USED_BLOCK)
2729+#define ZEND_MM_IS_GUARD_BLOCK(b) (((b)->info._size & ZEND_MM_TYPE_MASK) == ZEND_MM_GUARD_BLOCK)
2730+
2731+#define ZEND_MM_NEXT_BLOCK(b) ZEND_MM_BLOCK_AT(b, ZEND_MM_BLOCK_SIZE(b))
2732+#define ZEND_MM_PREV_BLOCK(b) ZEND_MM_BLOCK_AT(b, -(int)((b)->info._prev & ~ZEND_MM_TYPE_MASK))
2733+
2734+#define ZEND_MM_PREV_BLOCK_IS_FREE(b) (!((b)->info._prev & ZEND_MM_USED_BLOCK))
2735+
2736+#define ZEND_MM_MARK_FIRST_BLOCK(b) ((b)->info._prev = ZEND_MM_GUARD_BLOCK)
2737+#define ZEND_MM_IS_FIRST_BLOCK(b) ((b)->info._prev == ZEND_MM_GUARD_BLOCK)
2738+
2739+/* optimized access */
2740+#define ZEND_MM_FREE_BLOCK_SIZE(b) (b)->info._size
2741+
2742+#ifndef ZEND_MM_ALIGNMENT
2743+# define ZEND_MM_ALIGNMENT 8
2744+# define ZEND_MM_ALIGNMENT_LOG2 3
2745+#elif ZEND_MM_ALIGNMENT < 4
2746+# undef ZEND_MM_ALIGNMENT
2747+# undef ZEND_MM_ALIGNMENT_LOG2
2748+# define ZEND_MM_ALIGNMENT 4
2749+# define ZEND_MM_ALIGNMENT_LOG2 2
2750+#endif
2751+
2752+#define ZEND_MM_ALIGNMENT_MASK ~(ZEND_MM_ALIGNMENT-1)
2753+
2754+/* Aligned header size */
2755+#define ZEND_MM_ALIGNED_SIZE(size) ((size + ZEND_MM_ALIGNMENT - 1) & ZEND_MM_ALIGNMENT_MASK)
2756+#define ZEND_MM_ALIGNED_HEADER_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_block_canary))
2757+#define ZEND_MM_ALIGNED_FREE_HEADER_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_small_free_block_canary))
2758+#define ZEND_MM_MIN_ALLOC_BLOCK_SIZE ZEND_MM_ALIGNED_SIZE(ZEND_MM_ALIGNED_HEADER_SIZE + END_MAGIC_SIZE + CANARY_SIZE)
2759+#define ZEND_MM_ALIGNED_MIN_HEADER_SIZE (ZEND_MM_MIN_ALLOC_BLOCK_SIZE>ZEND_MM_ALIGNED_FREE_HEADER_SIZE?ZEND_MM_MIN_ALLOC_BLOCK_SIZE:ZEND_MM_ALIGNED_FREE_HEADER_SIZE)
2760+#define ZEND_MM_ALIGNED_SEGMENT_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_segment))
2761+
2762+#define ZEND_MM_MIN_SIZE ((ZEND_MM_ALIGNED_MIN_HEADER_SIZE>(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE+CANARY_SIZE))?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE-(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE+CANARY_SIZE)):0)
2763+
2764+#define ZEND_MM_MAX_SMALL_SIZE ((ZEND_MM_NUM_BUCKETS<<ZEND_MM_ALIGNMENT_LOG2)+ZEND_MM_ALIGNED_MIN_HEADER_SIZE)
2765+
2766+#define ZEND_MM_TRUE_SIZE(size) ((size<ZEND_MM_MIN_SIZE)?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE):(ZEND_MM_ALIGNED_SIZE(size+ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE+CANARY_SIZE)))
2767+
2768+#define ZEND_MM_BUCKET_INDEX(true_size) ((true_size>>ZEND_MM_ALIGNMENT_LOG2)-(ZEND_MM_ALIGNED_MIN_HEADER_SIZE>>ZEND_MM_ALIGNMENT_LOG2))
2769+
2770+#define ZEND_MM_SMALL_SIZE(true_size) (true_size < ZEND_MM_MAX_SMALL_SIZE)
2771+
2772+/* Memory calculations */
2773+#define ZEND_MM_BLOCK_AT(blk, offset) ((zend_mm_block_canary *) (((char *) (blk))+(offset)))
2774+#define ZEND_MM_DATA_OF(p) ((void *) (((char *) (p))+ZEND_MM_ALIGNED_HEADER_SIZE))
2775+#define ZEND_MM_HEADER_OF(blk) ZEND_MM_BLOCK_AT(blk, -(int)ZEND_MM_ALIGNED_HEADER_SIZE)
2776+
2777+/* Debug output */
2778+#if ZEND_DEBUG
2779+
2780+# ifdef ZTS
2781+# define ZEND_MM_SET_THREAD_ID(block) \
2782+ ((zend_mm_block_canary*)(block))->thread_id = tsrm_thread_id()
2783+# define ZEND_MM_BAD_THREAD_ID(block) ((block)->thread_id != tsrm_thread_id())
2784+# else
2785+# define ZEND_MM_SET_THREAD_ID(block)
2786+# define ZEND_MM_BAD_THREAD_ID(block) 0
2787+# endif
2788+
2789+# define ZEND_MM_VALID_PTR(block) \
2790+ zend_mm_check_ptr(heap, block, 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC)
2791+
2792+# define ZEND_MM_SET_MAGIC(block, val) do { \
2793+ (block)->magic = (val); \
2794+ } while (0)
2795+
2796+# define ZEND_MM_CHECK_MAGIC(block, val) do { \
2797+ if ((block)->magic != (val)) { \
2798+ zend_mm_panic("zend_mm_heap corrupted"); \
2799+ } \
2800+ } while (0)
2801+
2802+# define ZEND_MM_SET_DEBUG_INFO(block, __size, set_valid, set_thread) do { \
2803+ ((zend_mm_block_canary*)(block))->debug.filename = __zend_filename; \
2804+ ((zend_mm_block_canary*)(block))->debug.lineno = __zend_lineno; \
2805+ ((zend_mm_block_canary*)(block))->debug.orig_filename = __zend_orig_filename; \
2806+ ((zend_mm_block_canary*)(block))->debug.orig_lineno = __zend_orig_lineno; \
2807+ ZEND_MM_SET_BLOCK_SIZE(block, __size); \
2808+ if (set_valid) { \
2809+ ZEND_MM_SET_MAGIC(block, MEM_BLOCK_VALID); \
2810+ } \
2811+ if (set_thread) { \
2812+ ZEND_MM_SET_THREAD_ID(block); \
2813+ } \
2814+ } while (0)
2815+
2816+#else
2817+
2818+# define ZEND_MM_VALID_PTR(ptr) EXPECTED(ptr != NULL)
2819+
2820+# define ZEND_MM_SET_MAGIC(block, val)
2821+
2822+# define ZEND_MM_CHECK_MAGIC(block, val)
2823+
2824+# define ZEND_MM_SET_DEBUG_INFO(block, __size, set_valid, set_thread) ZEND_MM_SET_BLOCK_SIZE(block, __size)
2825+
2826+#endif
2827+
2828+#if SUHOSIN_MM_WITH_CANARY_PROTECTION
2829+
2830+# define SUHOSIN_MM_CHECK_CANARIES(block, MFUNCTION) do { \
2831+ char *p = SUHOSIN_MM_END_CANARY_PTR(block); size_t check; \
2832+ if (((block)->info.canary_1 != heap->canary_1) || ((block)->info.canary_2 != heap->canary_2)) { \
2833+ canary_mismatch: \
2834+ zend_suhosin_log(S_MEMORY, "canary mismatch on " MFUNCTION " - heap overflow detected at %p", (block)); \
2835+ if (SUHOSIN_CONFIG(SUHOSIN_MM_IGNORE_CANARY_VIOLATION) == 0) { _exit(1); } else { (block)->info.canary_1 = heap->canary_1; (block)->info.canary_2 = heap->canary_2; }\
2836+ } \
2837+ memcpy(&check, p, CANARY_SIZE); \
2838+ if (check != heap->canary_3) { \
2839+ zend_suhosin_log(S_MEMORY, "end canary mismatch on " MFUNCTION " - heap overflow detected at %p", (block)); \
2840+ if (SUHOSIN_CONFIG(SUHOSIN_MM_IGNORE_CANARY_VIOLATION) == 0) { _exit(1); } else { memcpy(p, heap->canary_3, CANARY_SIZE); } \
2841+ } \
2842+ } while (0)
2843+
2844+# define SUHOSIN_MM_SET_CANARIES(block) do { \
2845+ (block)->info.canary_1 = heap->canary_1; \
2846+ (block)->info.canary_2 = heap->canary_2; \
2847+ } while (0)
2848+
2849+# define SUHOSIN_MM_END_CANARY_PTR(block) \
2850+ (char *)(((char*)(ZEND_MM_DATA_OF(block))) + ((zend_mm_block_canary*)(block))->info.size + END_MAGIC_SIZE)
2851+
2852+# define SUHOSIN_MM_SET_END_CANARY(block) do { \
2853+ char *p = SUHOSIN_MM_END_CANARY_PTR(block); \
2854+ memcpy(p, &heap->canary_3, CANARY_SIZE); \
2855+ } while (0)
2856+
2857+#else
2858+
2859+# define SUHOSIN_MM_CHECK_CANARIES(block, MFUNCTION)
2860+# define SUHOSIN_MM_SET_CANARIES(block)
2861+# define SUHOSIN_MM_END_CANARY_PTR(block)
2862+# define SUHOSIN_MM_SET_END_CANARY(block)
2863+
2864+#endif
2865+
2866+
2867+#if ZEND_MM_HEAP_PROTECTION
2868+
2869+# define ZEND_MM_CHECK_PROTECTION(block) \
2870+ do { \
2871+ if ((block)->debug.start_magic != _mem_block_start_magic || \
2872+ memcmp(ZEND_MM_END_MAGIC_PTR(block), &_mem_block_end_magic, END_MAGIC_SIZE) != 0) { \
2873+ zend_mm_panic("zend_mm_heap corrupted"); \
2874+ } \
2875+ } while (0)
2876+
2877+# define ZEND_MM_END_MAGIC_PTR(block) \
2878+ (((char*)(ZEND_MM_DATA_OF(block))) + ((zend_mm_block_canary*)(block))->debug.size)
2879+
2880+# define END_MAGIC_SIZE sizeof(unsigned int)
2881+
2882+# define ZEND_MM_SET_BLOCK_SIZE(block, __size) do { \
2883+ char *p; \
2884+ ((zend_mm_block_canary*)(block))->debug.size = (__size); \
2885+ p = ZEND_MM_END_MAGIC_PTR(block); \
2886+ ((zend_mm_block_canary*)(block))->debug.start_magic = _mem_block_start_magic; \
2887+ memcpy(p, &_mem_block_end_magic, END_MAGIC_SIZE); \
2888+ } while (0)
2889+
2890+static unsigned int _mem_block_start_magic = 0;
2891+static unsigned int _mem_block_end_magic = 0;
2892+
2893+#else
2894+
2895+# if ZEND_DEBUG
2896+# define ZEND_MM_SET_BLOCK_SIZE(block, _size) \
2897+ ((zend_mm_block_canary*)(block))->debug.size = (_size)
2898+# else
2899+# define ZEND_MM_SET_BLOCK_SIZE(block, _size)
2900+# endif
2901+
2902+# define ZEND_MM_CHECK_PROTECTION(block)
2903+
2904+# define END_MAGIC_SIZE 0
2905+
2906+#endif
2907+
2908+#if ZEND_MM_SAFE_UNLINKING
2909+# define ZEND_MM_CHECK_BLOCK_LINKAGE(block) \
2910+ if (UNEXPECTED((block)->info._size != ZEND_MM_BLOCK_AT(block, ZEND_MM_FREE_BLOCK_SIZE(block))->info._prev) || \
2911+ UNEXPECTED(!UNEXPECTED(ZEND_MM_IS_FIRST_BLOCK(block)) && \
2912+ UNEXPECTED(ZEND_MM_PREV_BLOCK(block)->info._size != (block)->info._prev))) { \
2913+ zend_mm_panic("zend_mm_heap corrupted"); \
2914+ }
2915+#define ZEND_MM_CHECK_TREE(block) \
2916+ if (UNEXPECTED(*((block)->parent) != (block))) { \
2917+ zend_mm_panic("zend_mm_heap corrupted"); \
2918+ }
2919+#else
2920+# define ZEND_MM_CHECK_BLOCK_LINKAGE(block)
2921+# define ZEND_MM_CHECK_TREE(block)
2922+#endif
2923+
2924+#define ZEND_MM_LARGE_BUCKET_INDEX(S) zend_mm_high_bit(S)
2925+
2926+void *_zend_mm_alloc_canary_int(zend_mm_heap_canary *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
2927+void _zend_mm_free_canary_int(zend_mm_heap_canary *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
2928+void *_zend_mm_realloc_canary_int(zend_mm_heap_canary *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
2929+
2930+
2931+static inline unsigned int zend_mm_high_bit(size_t _size)
2932+{
2933+#if defined(__GNUC__) && defined(i386)
2934+ unsigned int n;
2935+
2936+ __asm__("bsrl %1,%0\n\t" : "=r" (n) : "rm" (_size));
2937+ return n;
2938+#elif defined(__GNUC__) && defined(__x86_64__)
2939+ unsigned long n;
2940+
2941+ __asm__("bsrq %1,%0\n\t" : "=r" (n) : "rm" (_size));
2942+ return (unsigned int)n;
2943+#elif defined(_MSC_VER) && defined(_M_IX86)
2944+ __asm {
2945+ bsr eax, _size
2946+ }
2947+#else
2948+ unsigned int n = 0;
2949+ while (_size != 0) {
2950+ _size = _size >> 1;
2951+ n++;
2952+ }
2953+ return n-1;
2954+#endif
2955+}
2956+
2957+static inline unsigned int zend_mm_low_bit(size_t _size)
2958+{
2959+#if defined(__GNUC__) && defined(i386)
2960+ unsigned int n;
2961+
2962+ __asm__("bsfl %1,%0\n\t" : "=r" (n) : "rm" (_size));
2963+ return n;
2964+#elif defined(__GNUC__) && defined(__x86_64__)
2965+ unsigned long n;
2966+
2967+ __asm__("bsfq %1,%0\n\t" : "=r" (n) : "rm" (_size));
2968+ return (unsigned int)n;
2969+#elif defined(_MSC_VER) && defined(_M_IX86)
2970+ __asm {
2971+ bsf eax, _size
2972+ }
2973+#else
2974+ static const int offset[16] = {4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0};
2975+ unsigned int n;
2976+ unsigned int index = 0;
2977+
2978+ n = offset[_size & 15];
2979+ while (n == 4) {
2980+ _size >>= 4;
2981+ index += n;
2982+ n = offset[_size & 15];
2983+ }
2984+
2985+ return index + n;
2986+#endif
2987+}
2988+
2989+static void zend_mm_add_to_rest_list(zend_mm_heap_canary *heap, zend_mm_free_block_canary *mm_block)
2990+{
2991+ zend_mm_free_block_canary *prev, *next;
2992+
2993+ ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_FREED);
2994+
2995+ if (!ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(mm_block))) {
2996+ mm_block->parent = NULL;
2997+ }
2998+
2999+ prev = SUHOSIN_MANGLE_PTR(heap->rest_buckets[0]);
3000+ next = SUHOSIN_MANGLE_PTR(prev->next_free_block);
3001+ mm_block->prev_free_block = SUHOSIN_MANGLE_PTR(prev);
3002+ mm_block->next_free_block = SUHOSIN_MANGLE_PTR(next);
3003+ prev->next_free_block = next->prev_free_block = SUHOSIN_MANGLE_PTR(mm_block);
3004+}
3005+
3006+static void zend_mm_add_to_free_list(zend_mm_heap_canary *heap, zend_mm_free_block_canary *mm_block)
3007+{
3008+ size_t size;
3009+ size_t index;
3010+
3011+ ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_FREED);
3012+
3013+ size = ZEND_MM_FREE_BLOCK_SIZE(mm_block);
3014+ if (EXPECTED(!ZEND_MM_SMALL_SIZE(size))) {
3015+ zend_mm_free_block_canary **p;
3016+
3017+ index = ZEND_MM_LARGE_BUCKET_INDEX(size);
3018+ p = &heap->large_free_buckets[index];
3019+ mm_block->child[0] = mm_block->child[1] = NULL;
3020+ if (!*p) {
3021+ *p = mm_block;
3022+ mm_block->parent = p;
3023+ mm_block->prev_free_block = mm_block->next_free_block = SUHOSIN_MANGLE_PTR(mm_block);
3024+ heap->large_free_bitmap |= (ZEND_MM_LONG_CONST(1) << index);
3025+ } else {
3026+ size_t m;
3027+
3028+ for (m = size << (ZEND_MM_NUM_BUCKETS - index); ; m <<= 1) {
3029+ zend_mm_free_block_canary *prev = *p;
3030+
3031+ if (ZEND_MM_FREE_BLOCK_SIZE(prev) != size) {
3032+ p = &prev->child[(m >> (ZEND_MM_NUM_BUCKETS-1)) & 1];
3033+ if (!*p) {
3034+ *p = mm_block;
3035+ mm_block->parent = p;
3036+ mm_block->prev_free_block = mm_block->next_free_block = SUHOSIN_MANGLE_PTR(mm_block);
3037+ break;
3038+ }
3039+ } else {
3040+ zend_mm_free_block_canary *next = SUHOSIN_MANGLE_PTR(prev->next_free_block);
3041+
3042+ prev->next_free_block = next->prev_free_block = SUHOSIN_MANGLE_PTR(mm_block);
3043+ mm_block->next_free_block = SUHOSIN_MANGLE_PTR(next);
3044+ mm_block->prev_free_block = SUHOSIN_MANGLE_PTR(prev);
3045+ mm_block->parent = NULL;
3046+ break;
3047+ }
3048+ }
3049+ }
3050+ } else {
3051+ zend_mm_free_block_canary *prev, *next;
3052+
3053+ index = ZEND_MM_BUCKET_INDEX(size);
3054+
3055+ prev = ZEND_MM_SMALL_FREE_BUCKET(heap, index);
3056+ if (SUHOSIN_MANGLE_PTR(prev->prev_free_block) == prev) {
3057+ heap->free_bitmap |= (ZEND_MM_LONG_CONST(1) << index);
3058+ }
3059+ next = SUHOSIN_MANGLE_PTR(prev->next_free_block);
3060+
3061+ mm_block->prev_free_block = SUHOSIN_MANGLE_PTR(prev);
3062+ mm_block->next_free_block = SUHOSIN_MANGLE_PTR(next);
3063+ prev->next_free_block = next->prev_free_block = SUHOSIN_MANGLE_PTR(mm_block);
3064+ }
3065+}
3066+
3067+static void zend_mm_remove_from_free_list(zend_mm_heap_canary *heap, zend_mm_free_block_canary *mm_block)
3068+{
3069+ zend_mm_free_block_canary *prev = SUHOSIN_MANGLE_PTR(mm_block->prev_free_block);
3070+ zend_mm_free_block_canary *next = SUHOSIN_MANGLE_PTR(mm_block->next_free_block);
3071+
3072+ ZEND_MM_CHECK_MAGIC(mm_block, MEM_BLOCK_FREED);
3073+
3074+ if (EXPECTED(prev == mm_block)) {
3075+ zend_mm_free_block_canary **rp, **cp;
3076+
3077+#if SUHOSIN_PATCH
3078+ if (next != mm_block) {
3079+ zend_suhosin_log(S_MEMORY, "zend_mm_heap corrupted at %p", mm_block);
3080+ _exit(1);
3081+ }
3082+#endif
3083+#if ZEND_MM_SAFE_UNLINKING
3084+ if (UNEXPECTED(next != mm_block)) {
3085+ zend_mm_panic("zend_mm_heap corrupted");
3086+ }
3087+#endif
3088+
3089+ rp = &mm_block->child[mm_block->child[1] != NULL];
3090+ prev = *rp;
3091+ if (EXPECTED(prev == NULL)) {
3092+ size_t index = ZEND_MM_LARGE_BUCKET_INDEX(ZEND_MM_FREE_BLOCK_SIZE(mm_block));
3093+
3094+ ZEND_MM_CHECK_TREE(mm_block);
3095+ *mm_block->parent = NULL;
3096+ if (mm_block->parent == &heap->large_free_buckets[index]) {
3097+ heap->large_free_bitmap &= ~(ZEND_MM_LONG_CONST(1) << index);
3098+ }
3099+ } else {
3100+ while (*(cp = &(prev->child[prev->child[1] != NULL])) != NULL) {
3101+ prev = *cp;
3102+ rp = cp;
3103+ }
3104+ *rp = NULL;
3105+
3106+subst_block:
3107+ ZEND_MM_CHECK_TREE(mm_block);
3108+ *mm_block->parent = prev;
3109+ prev->parent = mm_block->parent;
3110+ if ((prev->child[0] = mm_block->child[0])) {
3111+ ZEND_MM_CHECK_TREE(prev->child[0]);
3112+ prev->child[0]->parent = &prev->child[0];
3113+ }
3114+ if ((prev->child[1] = mm_block->child[1])) {
3115+ ZEND_MM_CHECK_TREE(prev->child[1]);
3116+ prev->child[1]->parent = &prev->child[1];
3117+ }
3118+ }
3119+ } else {
3120+
3121+#if SUHOSIN_PATCH
3122+ if (SUHOSIN_MANGLE_PTR(prev->next_free_block) != mm_block || SUHOSIN_MANGLE_PTR(next->prev_free_block) != mm_block) {
3123+ zend_suhosin_log(S_MEMORY, "zend_mm_head corrupted at %p", mm_block);
3124+ _exit(1);
3125+ }
3126+#endif
3127+
3128+#if ZEND_MM_SAFE_UNLINKING
3129+ if (UNEXPECTED(SUHOSIN_MANGLE_PTR(prev->next_free_block) != mm_block) || UNEXPECTED(SUHOSIN_MANGLE_PTR(next->prev_free_block) != mm_block)) {
3130+ zend_mm_panic("zend_mm_heap corrupted");
3131+ }
3132+#endif
3133+
3134+ prev->next_free_block = SUHOSIN_MANGLE_PTR(next);
3135+ next->prev_free_block = SUHOSIN_MANGLE_PTR(prev);
3136+
3137+ if (EXPECTED(ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(mm_block)))) {
3138+ if (EXPECTED(prev == next)) {
3139+ size_t index = ZEND_MM_BUCKET_INDEX(ZEND_MM_FREE_BLOCK_SIZE(mm_block));
3140+
3141+ if (EXPECTED(heap->free_buckets[index*2] == heap->free_buckets[index*2+1])) {
3142+ heap->free_bitmap &= ~(ZEND_MM_LONG_CONST(1) << index);
3143+ }
3144+ }
3145+ } else if (UNEXPECTED(mm_block->parent != NULL)) {
3146+ goto subst_block;
3147+ }
3148+ }
3149+}
3150+
3151+static void zend_mm_init(zend_mm_heap_canary *heap)
3152+{
3153+ zend_mm_free_block_canary* p;
3154+ int i;
3155+
3156+ heap->free_bitmap = 0;
3157+ heap->large_free_bitmap = 0;
3158+#if ZEND_MM_CACHE
3159+ heap->cached = 0;
3160+ memset(heap->cache, 0, sizeof(heap->cache));
3161+#endif
3162+#if ZEND_MM_CACHE_STAT
3163+ for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
3164+ heap->cache_stat[i].count = 0;
3165+ }
3166+#endif
3167+ p = ZEND_MM_SMALL_FREE_BUCKET(heap, 0);
3168+ for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
3169+ p->next_free_block = SUHOSIN_MANGLE_PTR(p);
3170+ p->prev_free_block = SUHOSIN_MANGLE_PTR(p);
3171+ p = (zend_mm_free_block_canary*)((char*)p + sizeof(zend_mm_free_block_canary*) * 2);
3172+ heap->large_free_buckets[i] = NULL;
3173+ }
3174+ heap->rest_buckets[0] = heap->rest_buckets[1] = SUHOSIN_MANGLE_PTR(ZEND_MM_REST_BUCKET(heap));
3175+#if SUHOSIN_PATCH
3176+ if (SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION)) {
3177+ zend_canary(&heap->canary_1, sizeof(heap->canary_1));
3178+ zend_canary(&heap->canary_2, sizeof(heap->canary_2));
3179+ zend_canary(&heap->canary_3, sizeof(heap->canary_3));
3180+ }
3181+#endif
3182+}
3183+
3184+static void zend_mm_del_segment(zend_mm_heap_canary *heap, zend_mm_segment *segment)
3185+{
3186+ zend_mm_segment **p = &heap->segments_list;
3187+
3188+ while (*p != segment) {
3189+ p = &(*p)->next_segment;
3190+ }
3191+ *p = segment->next_segment;
3192+ heap->real_size -= segment->size;
3193+ ZEND_MM_STORAGE_FREE(segment);
3194+}
3195+
3196+#if ZEND_MM_CACHE
3197+static void zend_mm_free_cache(zend_mm_heap_canary *heap)
3198+{
3199+ int i;
3200+
3201+ for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
3202+ /* SUHOSIN_MANGLE_PTR should NOT affect NULL pointers */
3203+ if (heap->cache[i]) {
3204+ zend_mm_free_block_canary *mm_block = SUHOSIN_MANGLE_PTR(heap->cache[i]);
3205+
3206+ while (mm_block) {
3207+ size_t size = ZEND_MM_BLOCK_SIZE(mm_block);
3208+ zend_mm_free_block_canary *q = SUHOSIN_MANGLE_PTR(mm_block->prev_free_block);
3209+ zend_mm_block_canary *next_block = ZEND_MM_NEXT_BLOCK(mm_block);
3210+
3211+ heap->cached -= size;
3212+
3213+ if (ZEND_MM_PREV_BLOCK_IS_FREE(mm_block)) {
3214+ mm_block = (zend_mm_free_block_canary*)ZEND_MM_PREV_BLOCK(mm_block);
3215+ size += ZEND_MM_FREE_BLOCK_SIZE(mm_block);
3216+ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) mm_block);
3217+ }
3218+ if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
3219+ size += ZEND_MM_FREE_BLOCK_SIZE(next_block);
3220+ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) next_block);
3221+ }
3222+ ZEND_MM_BLOCK(mm_block, ZEND_MM_FREE_BLOCK, size);
3223+
3224+ if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
3225+ ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_NEXT_BLOCK(mm_block))) {
3226+ zend_mm_del_segment(heap, (zend_mm_segment *) ((char *)mm_block - ZEND_MM_ALIGNED_SEGMENT_SIZE));
3227+ } else {
3228+ zend_mm_add_to_free_list(heap, (zend_mm_free_block_canary *) mm_block);
3229+ }
3230+
3231+ mm_block = q;
3232+ }
3233+ heap->cache[i] = NULL;
3234+#if ZEND_MM_CACHE_STAT
3235+ heap->cache_stat[i].count = 0;
3236+#endif
3237+ }
3238+ }
3239+}
3240+#endif
3241+
3242+#if ZEND_MM_HEAP_PROTECTION || ZEND_MM_COOKIES
3243+static void zend_mm_random(unsigned char *buf, size_t size) /* {{{ */
3244+{
3245+ size_t i = 0;
3246+ unsigned char t;
3247+
3248+#ifdef ZEND_WIN32
3249+ HCRYPTPROV hCryptProv;
3250+ int has_context = 0;
3251+
3252+ if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) {
3253+ /* Could mean that the key container does not exist, let try
3254+ again by asking for a new one */
3255+ if (GetLastError() == NTE_BAD_KEYSET) {
3256+ if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
3257+ has_context = 1;
3258+ }
3259+ }
3260+ } else {
3261+ has_context = 1;
3262+ }
3263+ if (has_context) {
3264+ do {
3265+ BOOL ret = CryptGenRandom(hCryptProv, size, buf);
3266+ CryptReleaseContext(hCryptProv, 0);
3267+ if (ret) {
3268+ while (i < size && buf[i] != 0) {
3269+ i++;
3270+ }
3271+ if (i == size) {
3272+ return;
3273+ }
3274+ }
3275+ } while (0);
3276+ }
3277+#elif defined(HAVE_DEV_URANDOM)
3278+ int fd = open("/dev/urandom", 0);
3279+
3280+ if (fd >= 0) {
3281+ if (read(fd, buf, size) == size) {
3282+ while (i < size && buf[i] != 0) {
3283+ i++;
3284+ }
3285+ if (i == size) {
3286+ close(fd);
3287+ return;
3288+ }
3289+ }
3290+ close(fd);
3291+ }
3292+#endif
3293+ t = (unsigned char)getpid();
3294+ while (i < size) {
3295+ do {
3296+ buf[i] = ((unsigned char)rand()) ^ t;
3297+ } while (buf[i] == 0);
3298+ t = buf[i++] << 1;
3299+ }
3300+}
3301+/* }}} */
3302+#endif
3303+
3304+
3305+/* Notes:
3306+ * - This function may alter the block_sizes values to match platform alignment
3307+ * - This function does *not* perform sanity checks on the arguments
3308+ */
3309+zend_mm_heap_canary *__zend_mm_startup_canary_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params)
3310+{
3311+ zend_mm_storage *storage;
3312+ zend_mm_heap_canary *heap;
3313+ zend_mm_free_block_canary *tmp;
3314+
3315+#if 0
3316+ int i;
3317+
3318+ printf("ZEND_MM_ALIGNMENT=%d\n", ZEND_MM_ALIGNMENT);
3319+ printf("ZEND_MM_ALIGNMENT_LOG2=%d\n", ZEND_MM_ALIGNMENT_LOG2);
3320+ printf("ZEND_MM_MIN_SIZE=%d\n", ZEND_MM_MIN_SIZE);
3321+ printf("ZEND_MM_MAX_SMALL_SIZE=%d\n", ZEND_MM_MAX_SMALL_SIZE);
3322+ printf("ZEND_MM_ALIGNED_HEADER_SIZE=%d\n", ZEND_MM_ALIGNED_HEADER_SIZE);
3323+ printf("ZEND_MM_ALIGNED_FREE_HEADER_SIZE=%d\n", ZEND_MM_ALIGNED_FREE_HEADER_SIZE);
3324+ printf("ZEND_MM_MIN_ALLOC_BLOCK_SIZE=%d\n", ZEND_MM_MIN_ALLOC_BLOCK_SIZE);
3325+ printf("ZEND_MM_ALIGNED_MIN_HEADER_SIZE=%d\n", ZEND_MM_ALIGNED_MIN_HEADER_SIZE);
3326+ printf("ZEND_MM_ALIGNED_SEGMENT_SIZE=%d\n", ZEND_MM_ALIGNED_SEGMENT_SIZE);
3327+ for (i = 0; i < ZEND_MM_MAX_SMALL_SIZE; i++) {
3328+ printf("%3d%c: %3ld %d %2ld\n", i, (i == ZEND_MM_MIN_SIZE?'*':' '), (long)ZEND_MM_TRUE_SIZE(i), ZEND_MM_SMALL_SIZE(ZEND_MM_TRUE_SIZE(i)), (long)ZEND_MM_BUCKET_INDEX(ZEND_MM_TRUE_SIZE(i)));
3329+ }
3330+ exit(0);
3331+#endif
3332+
3333+#if ZEND_MM_HEAP_PROTECTION
3334+ if (_mem_block_start_magic == 0) {
3335+ zend_mm_random((unsigned char*)&_mem_block_start_magic, sizeof(_mem_block_start_magic));
3336+ }
3337+ if (_mem_block_end_magic == 0) {
3338+ zend_mm_random((unsigned char*)&_mem_block_end_magic, sizeof(_mem_block_end_magic));
3339+ }
3340+#endif
3341+#if ZEND_MM_COOKIES
3342+ if (_zend_mm_cookie == 0) {
3343+ zend_mm_random((unsigned char*)&_zend_mm_cookie, sizeof(_zend_mm_cookie));
3344+ }
3345+#endif
3346+
3347+ /* get the pointer guardian and ensure low 3 bits are 1 */
3348+ if (SUHOSIN_POINTER_GUARD == 0) {
3349+ zend_canary(&SUHOSIN_POINTER_GUARD, sizeof(SUHOSIN_POINTER_GUARD));
3350+ SUHOSIN_POINTER_GUARD |= 7;
3351+ }
3352+
3353+ if (zend_mm_low_bit(block_size) != zend_mm_high_bit(block_size)) {
3354+ fprintf(stderr, "'block_size' must be a power of two\n");
3355+/* See http://support.microsoft.com/kb/190351 */
3356+#ifdef PHP_WIN32
3357+ fflush(stderr);
3358+#endif
3359+ exit(255);
3360+ }
3361+ storage = handlers->init(params);
3362+ if (!storage) {
3363+ fprintf(stderr, "Cannot initialize zend_mm storage [%s]\n", handlers->name);
3364+/* See http://support.microsoft.com/kb/190351 */
3365+#ifdef PHP_WIN32
3366+ fflush(stderr);
3367+#endif
3368+ exit(255);
3369+ }
3370+ storage->handlers = handlers;
3371+
3372+ heap = malloc(sizeof(struct _zend_mm_heap_canary));
3373+
3374+ heap->storage = storage;
3375+ heap->block_size = block_size;
3376+ heap->compact_size = 0;
3377+ heap->segments_list = NULL;
3378+ zend_mm_init(heap);
3379+# if ZEND_MM_CACHE_STAT
3380+ memset(heap->cache_stat, 0, sizeof(heap->cache_stat));
3381+# endif
3382+
3383+ heap->use_zend_alloc = 1;
3384+ heap->real_size = 0;
3385+ heap->overflow = 0;
3386+ heap->real_peak = 0;
3387+ heap->limit = ZEND_MM_LONG_CONST(1)<<(ZEND_MM_NUM_BUCKETS-2);
3388+ heap->size = 0;
3389+ heap->peak = 0;
3390+ heap->internal = internal;
3391+ heap->reserve = NULL;
3392+ heap->reserve_size = reserve_size;
3393+ if (reserve_size > 0) {
3394+ heap->reserve = _zend_mm_alloc((zend_mm_heap *)heap, reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
3395+ }
3396+ if (internal) {
3397+ int i;
3398+ zend_mm_free_block_canary *p, *q, *orig;
3399+ zend_mm_heap_canary *mm_heap = _zend_mm_alloc((zend_mm_heap *)heap, sizeof(zend_mm_heap_canary) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
3400+
3401+ *mm_heap = *heap;
3402+
3403+ p = ZEND_MM_SMALL_FREE_BUCKET(mm_heap, 0);
3404+ orig = ZEND_MM_SMALL_FREE_BUCKET(heap, 0);
3405+ for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
3406+ q = p;
3407+ while (SUHOSIN_MANGLE_PTR(q->prev_free_block) != orig) {
3408+ q = SUHOSIN_MANGLE_PTR(q->prev_free_block);
3409+ }
3410+ q->prev_free_block = SUHOSIN_MANGLE_PTR(p);
3411+ q = p;
3412+ while (SUHOSIN_MANGLE_PTR(q->next_free_block) != orig) {
3413+ q = SUHOSIN_MANGLE_PTR(q->next_free_block);
3414+ }
3415+ q->next_free_block = SUHOSIN_MANGLE_PTR(p);
3416+ p = (zend_mm_free_block_canary*)((char*)p + sizeof(zend_mm_free_block_canary*) * 2);
3417+ orig = (zend_mm_free_block_canary*)((char*)orig + sizeof(zend_mm_free_block_canary*) * 2);
3418+ if (mm_heap->large_free_buckets[i]) {
3419+ mm_heap->large_free_buckets[i]->parent = &mm_heap->large_free_buckets[i];
3420+ }
3421+ }
3422+ mm_heap->rest_buckets[0] = mm_heap->rest_buckets[1] = SUHOSIN_MANGLE_PTR(ZEND_MM_REST_BUCKET(mm_heap));
3423+
3424+ free(heap);
3425+ heap = mm_heap;
3426+ }
3427+ return heap;
3428+}
3429+
3430+zend_mm_heap_canary *__zend_mm_startup_canary(void)
3431+{
3432+ int i;
3433+ size_t seg_size;
3434+ char *mem_type = getenv("ZEND_MM_MEM_TYPE");
3435+ char *tmp;
3436+ const zend_mm_mem_handlers *handlers;
3437+ zend_mm_heap_canary *heap;
3438+
3439+ if (mem_type == NULL) {
3440+ i = 0;
3441+ } else {
3442+ for (i = 0; mem_handlers[i].name; i++) {
3443+ if (strcmp(mem_handlers[i].name, mem_type) == 0) {
3444+ break;
3445+ }
3446+ }
3447+ if (!mem_handlers[i].name) {
3448+ fprintf(stderr, "Wrong or unsupported zend_mm storage type '%s'\n", mem_type);
3449+ fprintf(stderr, " supported types:\n");
3450+/* See http://support.microsoft.com/kb/190351 */
3451+#ifdef PHP_WIN32
3452+ fflush(stderr);
3453+#endif
3454+ for (i = 0; mem_handlers[i].name; i++) {
3455+ fprintf(stderr, " '%s'\n", mem_handlers[i].name);
3456+ }
3457+/* See http://support.microsoft.com/kb/190351 */
3458+#ifdef PHP_WIN32
3459+ fflush(stderr);
3460+#endif
3461+ exit(255);
3462+ }
3463+ }
3464+ handlers = &mem_handlers[i];
3465+
3466+ tmp = getenv("ZEND_MM_SEG_SIZE");
3467+ if (tmp) {
3468+ seg_size = zend_atoi(tmp, 0);
3469+ if (zend_mm_low_bit(seg_size) != zend_mm_high_bit(seg_size)) {
3470+ fprintf(stderr, "ZEND_MM_SEG_SIZE must be a power of two\n");
3471+/* See http://support.microsoft.com/kb/190351 */
3472+#ifdef PHP_WIN32
3473+ fflush(stderr);
3474+#endif
3475+ exit(255);
3476+ } else if (seg_size < ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE) {
3477+ fprintf(stderr, "ZEND_MM_SEG_SIZE is too small\n");
3478+/* See http://support.microsoft.com/kb/190351 */
3479+#ifdef PHP_WIN32
3480+ fflush(stderr);
3481+#endif
3482+ exit(255);
3483+ }
3484+ } else {
3485+ seg_size = ZEND_MM_SEG_SIZE;
3486+ }
3487+
3488+ heap = __zend_mm_startup_canary_ex(handlers, seg_size, ZEND_MM_RESERVE_SIZE, 0, NULL);
3489+ if (heap) {
3490+ tmp = getenv("ZEND_MM_COMPACT");
3491+ if (tmp) {
3492+ heap->compact_size = zend_atoi(tmp, 0);
3493+ } else {
3494+ heap->compact_size = 2 * 1024 * 1024;
3495+ }
3496+ }
3497+ return heap;
3498+}
3499+
3500+#if ZEND_DEBUG
3501+static long zend_mm_find_leaks(zend_mm_segment *segment, zend_mm_block_canary *b)
3502+{
3503+ long leaks = 0;
3504+ zend_mm_block_canary *p, *q;
3505+
3506+ p = ZEND_MM_NEXT_BLOCK(b);
3507+ while (1) {
3508+ if (ZEND_MM_IS_GUARD_BLOCK(p)) {
3509+ ZEND_MM_CHECK_MAGIC(p, MEM_BLOCK_GUARD);
3510+ segment = segment->next_segment;
3511+ if (!segment) {
3512+ break;
3513+ }
3514+ p = (zend_mm_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
3515+ continue;
3516+ }
3517+ q = ZEND_MM_NEXT_BLOCK(p);
3518+ if (q <= p ||
3519+ (char*)q > (char*)segment + segment->size ||
3520+ p->info._size != q->info._prev) {
3521+ zend_mm_panic("zend_mm_heap corrupted");
3522+ }
3523+ if (!ZEND_MM_IS_FREE_BLOCK(p)) {
3524+ if (p->magic == MEM_BLOCK_VALID) {
3525+ if (p->debug.filename==b->debug.filename && p->debug.lineno==b->debug.lineno) {
3526+ ZEND_MM_SET_MAGIC(p, MEM_BLOCK_LEAK);
3527+ leaks++;
3528+ }
3529+#if ZEND_MM_CACHE
3530+ } else if (p->magic == MEM_BLOCK_CACHED) {
3531+ /* skip it */
3532+#endif
3533+ } else if (p->magic != MEM_BLOCK_LEAK) {
3534+ zend_mm_panic("zend_mm_heap corrupted");
3535+ }
3536+ }
3537+ p = q;
3538+ }
3539+ return leaks;
3540+}
3541+
3542+static void zend_mm_check_leaks(zend_mm_heap_canary *heap TSRMLS_DC)
3543+{
3544+ zend_mm_segment *segment = heap->segments_list;
3545+ zend_mm_block_canary *p, *q;
3546+ zend_uint total = 0;
3547+
3548+ if (!segment) {
3549+ return;
3550+ }
3551+ p = (zend_mm_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
3552+ while (1) {
3553+ q = ZEND_MM_NEXT_BLOCK(p);
3554+ if (q <= p ||
3555+ (char*)q > (char*)segment + segment->size ||
3556+ p->info._size != q->info._prev) {
3557+ zend_mm_panic("zend_mm_heap corrupted");
3558+ }
3559+ if (!ZEND_MM_IS_FREE_BLOCK(p)) {
3560+ if (p->magic == MEM_BLOCK_VALID) {
3561+ long repeated;
3562+ zend_leak_info leak;
3563+
3564+ ZEND_MM_SET_MAGIC(p, MEM_BLOCK_LEAK);
3565+
3566+ leak.addr = ZEND_MM_DATA_OF(p);
3567+ leak.size = p->debug.size;
3568+ leak.filename = p->debug.filename;
3569+ leak.lineno = p->debug.lineno;
3570+ leak.orig_filename = p->debug.orig_filename;
3571+ leak.orig_lineno = p->debug.orig_lineno;
3572+
3573+ zend_message_dispatcher(ZMSG_LOG_SCRIPT_NAME, NULL TSRMLS_CC);
3574+ zend_message_dispatcher(ZMSG_MEMORY_LEAK_DETECTED, &leak TSRMLS_CC);
3575+ repeated = zend_mm_find_leaks(segment, p);
3576+ total += 1 + repeated;
3577+ if (repeated) {
3578+ zend_message_dispatcher(ZMSG_MEMORY_LEAK_REPEATED, (void *)(zend_uintptr_t)repeated TSRMLS_CC);
3579+ }
3580+#if ZEND_MM_CACHE
3581+ } else if (p->magic == MEM_BLOCK_CACHED) {
3582+ /* skip it */
3583+#endif
3584+ } else if (p->magic != MEM_BLOCK_LEAK) {
3585+ zend_mm_panic("zend_mm_heap corrupted");
3586+ }
3587+ }
3588+ if (ZEND_MM_IS_GUARD_BLOCK(q)) {
3589+ segment = segment->next_segment;
3590+ if (!segment) {
3591+ break;
3592+ }
3593+ q = (zend_mm_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
3594+ }
3595+ p = q;
3596+ }
3597+ if (total) {
3598+ zend_message_dispatcher(ZMSG_MEMORY_LEAKS_GRAND_TOTAL, &total TSRMLS_CC);
3599+ }
3600+}
3601+
3602+static int zend_mm_check_ptr(zend_mm_heap_canary *heap, void *ptr, int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
3603+{
3604+ zend_mm_block_canary *p;
3605+ int no_cache_notice = 0;
3606+ int had_problems = 0;
3607+ int valid_beginning = 1;
3608+
3609+ if (silent==2) {
3610+ silent = 1;
3611+ no_cache_notice = 1;
3612+ } else if (silent==3) {
3613+ silent = 0;
3614+ no_cache_notice = 1;
3615+ }
3616+ if (!silent) {
3617+ TSRMLS_FETCH();
3618+
3619+ zend_message_dispatcher(ZMSG_LOG_SCRIPT_NAME, NULL TSRMLS_CC);
3620+ zend_debug_alloc_output("---------------------------------------\n");
3621+ zend_debug_alloc_output("%s(%d) : Block "PTR_FMT" status:\n" ZEND_FILE_LINE_RELAY_CC, ptr);
3622+ if (__zend_orig_filename) {
3623+ zend_debug_alloc_output("%s(%d) : Actual location (location was relayed)\n" ZEND_FILE_LINE_ORIG_RELAY_CC);
3624+ }
3625+ if (!ptr) {
3626+ zend_debug_alloc_output("NULL\n");
3627+ zend_debug_alloc_output("---------------------------------------\n");
3628+ return 0;
3629+ }
3630+ }
3631+
3632+ if (!ptr) {
3633+ if (silent) {
3634+ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
3635+ }
3636+ }
3637+
3638+ p = ZEND_MM_HEADER_OF(ptr);
3639+
3640+#ifdef ZTS
3641+ if (ZEND_MM_BAD_THREAD_ID(p)) {
3642+ if (!silent) {
3643+ zend_debug_alloc_output("Invalid pointer: ((thread_id=0x%0.8X) != (expected=0x%0.8X))\n", (long)p->thread_id, (long)tsrm_thread_id());
3644+ had_problems = 1;
3645+ } else {
3646+ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
3647+ }
3648+ }
3649+#endif
3650+
3651+ if (p->info._size != ZEND_MM_NEXT_BLOCK(p)->info._prev) {
3652+ if (!silent) {
3653+ zend_debug_alloc_output("Invalid pointer: ((size="PTR_FMT") != (next.prev="PTR_FMT"))\n", p->info._size, ZEND_MM_NEXT_BLOCK(p)->info._prev);
3654+ had_problems = 1;
3655+ } else {
3656+ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
3657+ }
3658+ }
3659+ if (p->info._prev != ZEND_MM_GUARD_BLOCK &&
3660+ ZEND_MM_PREV_BLOCK(p)->info._size != p->info._prev) {
3661+ if (!silent) {
3662+ zend_debug_alloc_output("Invalid pointer: ((prev="PTR_FMT") != (prev.size="PTR_FMT"))\n", p->info._prev, ZEND_MM_PREV_BLOCK(p)->info._size);
3663+ had_problems = 1;
3664+ } else {
3665+ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
3666+ }
3667+ }
3668+
3669+ if (had_problems) {
3670+ zend_debug_alloc_output("---------------------------------------\n");
3671+ return 0;
3672+ }
3673+
3674+ if (!silent) {
3675+ zend_debug_alloc_output("%10s\t","Beginning: ");
3676+ }
3677+
3678+ if (!ZEND_MM_IS_USED_BLOCK(p)) {
3679+ if (!silent) {
3680+ if (p->magic != MEM_BLOCK_FREED) {
3681+ zend_debug_alloc_output("Freed (magic=0x%0.8X, expected=0x%0.8X)\n", p->magic, MEM_BLOCK_FREED);
3682+ } else {
3683+ zend_debug_alloc_output("Freed\n");
3684+ }
3685+ had_problems = 1;
3686+ } else {
3687+ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
3688+ }
3689+ } else if (ZEND_MM_IS_GUARD_BLOCK(p)) {
3690+ if (!silent) {
3691+ if (p->magic != MEM_BLOCK_FREED) {
3692+ zend_debug_alloc_output("Guard (magic=0x%0.8X, expected=0x%0.8X)\n", p->magic, MEM_BLOCK_FREED);
3693+ } else {
3694+ zend_debug_alloc_output("Guard\n");
3695+ }
3696+ had_problems = 1;
3697+ } else {
3698+ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
3699+ }
3700+ } else {
3701+ switch (p->magic) {
3702+ case MEM_BLOCK_VALID:
3703+ case MEM_BLOCK_LEAK:
3704+ if (!silent) {
3705+ zend_debug_alloc_output("OK (allocated on %s:%d, %d bytes)\n", p->debug.filename, p->debug.lineno, (int)p->debug.size);
3706+ }
3707+ break; /* ok */
3708+ case MEM_BLOCK_CACHED:
3709+ if (!no_cache_notice) {
3710+ if (!silent) {
3711+ zend_debug_alloc_output("Cached\n");
3712+ had_problems = 1;
3713+ } else {
3714+ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
3715+ }
3716+ }
3717+ case MEM_BLOCK_FREED:
3718+ if (!silent) {
3719+ zend_debug_alloc_output("Freed (invalid)\n");
3720+ had_problems = 1;
3721+ } else {
3722+ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
3723+ }
3724+ break;
3725+ case MEM_BLOCK_GUARD:
3726+ if (!silent) {
3727+ zend_debug_alloc_output("Guard (invalid)\n");
3728+ had_problems = 1;
3729+ } else {
3730+ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
3731+ }
3732+ break;
3733+ default:
3734+ if (!silent) {
3735+ zend_debug_alloc_output("Unknown (magic=0x%0.8X, expected=0x%0.8X)\n", p->magic, MEM_BLOCK_VALID);
3736+ had_problems = 1;
3737+ valid_beginning = 0;
3738+ } else {
3739+ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
3740+ }
3741+ break;
3742+ }
3743+ }
3744+
3745+#if ZEND_MM_HEAP_PROTECTION
3746+ if (!valid_beginning) {
3747+ if (!silent) {
3748+ zend_debug_alloc_output("%10s\t", "Start:");
3749+ zend_debug_alloc_output("Unknown\n");
3750+ zend_debug_alloc_output("%10s\t", "End:");
3751+ zend_debug_alloc_output("Unknown\n");
3752+ }
3753+ } else {
3754+ char *end_magic = ZEND_MM_END_MAGIC_PTR(p);
3755+
3756+ if (p->debug.start_magic == _mem_block_start_magic) {
3757+ if (!silent) {
3758+ zend_debug_alloc_output("%10s\t", "Start:");
3759+ zend_debug_alloc_output("OK\n");
3760+ }
3761+ } else {
3762+ char *overflow_ptr, *magic_ptr=(char *) &_mem_block_start_magic;
3763+ int overflows=0;
3764+ int i;
3765+
3766+ if (silent) {
3767+ return _mem_block_check(ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
3768+ }
3769+ had_problems = 1;
3770+ overflow_ptr = (char *) &p->debug.start_magic;
3771+ i = END_MAGIC_SIZE;
3772+ while (--i >= 0) {
3773+ if (overflow_ptr[i]!=magic_ptr[i]) {
3774+ overflows++;
3775+ }
3776+ }
3777+ zend_debug_alloc_output("%10s\t", "Start:");
3778+ zend_debug_alloc_output("Overflown (magic=0x%0.8X instead of 0x%0.8X)\n", p->debug.start_magic, _mem_block_start_magic);
3779+ zend_debug_alloc_output("%10s\t","");
3780+ if (overflows >= END_MAGIC_SIZE) {
3781+ zend_debug_alloc_output("At least %d bytes overflown\n", END_MAGIC_SIZE);
3782+ } else {
3783+ zend_debug_alloc_output("%d byte(s) overflown\n", overflows);
3784+ }
3785+ }
3786+ if (memcmp(end_magic, &_mem_block_end_magic, END_MAGIC_SIZE)==0) {
3787+ if (!silent) {
3788+ zend_debug_alloc_output("%10s\t", "End:");
3789+ zend_debug_alloc_output("OK\n");
3790+ }
3791+ } else {
3792+ char *overflow_ptr, *magic_ptr=(char *) &_mem_block_end_magic;
3793+ int overflows=0;
3794+ int i;
3795+
3796+ if (silent) {
3797+ return _mem_block_check(ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
3798+ }
3799+ had_problems = 1;
3800+ overflow_ptr = (char *) end_magic;
3801+
3802+ for (i=0; i < END_MAGIC_SIZE; i++) {
3803+ if (overflow_ptr[i]!=magic_ptr[i]) {
3804+ overflows++;
3805+ }
3806+ }
3807+
3808+ zend_debug_alloc_output("%10s\t", "End:");
3809+ zend_debug_alloc_output("Overflown (magic=0x%0.8X instead of 0x%0.8X)\n", *end_magic, _mem_block_end_magic);
3810+ zend_debug_alloc_output("%10s\t","");
3811+ if (overflows >= END_MAGIC_SIZE) {
3812+ zend_debug_alloc_output("At least %d bytes overflown\n", END_MAGIC_SIZE);
3813+ } else {
3814+ zend_debug_alloc_output("%d byte(s) overflown\n", overflows);
3815+ }
3816+ }
3817+ }
3818+#endif
3819+
3820+ if (!silent) {
3821+ zend_debug_alloc_output("---------------------------------------\n");
3822+ }
3823+ return ((!had_problems) ? 1 : 0);
3824+}
3825+
3826+static int zend_mm_check_heap(zend_mm_heap_canary *heap, int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
3827+{
3828+ zend_mm_segment *segment = heap->segments_list;
3829+ zend_mm_block_canary *p, *q;
3830+ int errors = 0;
3831+
3832+ if (!segment) {
3833+ return 0;
3834+ }
3835+ p = (zend_mm_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
3836+ while (1) {
3837+ q = ZEND_MM_NEXT_BLOCK(p);
3838+ if (q <= p ||
3839+ (char*)q > (char*)segment + segment->size ||
3840+ p->info._size != q->info._prev) {
3841+ zend_mm_panic("zend_mm_heap corrupted");
3842+ }
3843+ if (!ZEND_MM_IS_FREE_BLOCK(p)) {
3844+ if (p->magic == MEM_BLOCK_VALID || p->magic == MEM_BLOCK_LEAK) {
3845+ if (!zend_mm_check_ptr(heap, ZEND_MM_DATA_OF(p), (silent?2:3) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC)) {
3846+ errors++;
3847+ }
3848+#if ZEND_MM_CACHE
3849+ } else if (p->magic == MEM_BLOCK_CACHED) {
3850+ /* skip it */
3851+#endif
3852+ } else if (p->magic != MEM_BLOCK_LEAK) {
3853+ zend_mm_panic("zend_mm_heap corrupted");
3854+ }
3855+ }
3856+ if (ZEND_MM_IS_GUARD_BLOCK(q)) {
3857+ segment = segment->next_segment;
3858+ if (!segment) {
3859+ return errors;
3860+ }
3861+ q = (zend_mm_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
3862+ }
3863+ p = q;
3864+ }
3865+}
3866+#endif
3867+
3868+void __zend_mm_shutdown_canary(zend_mm_heap_canary *heap, int full_shutdown, int silent TSRMLS_DC)
3869+{
3870+ zend_mm_storage *storage;
3871+ zend_mm_segment *segment;
3872+ zend_mm_segment *prev;
3873+ int internal;
3874+
3875+ if (heap->reserve) {
3876+#if ZEND_DEBUG
3877+ if (!silent) {
3878+ _zend_mm_free(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
3879+ }
3880+#endif
3881+ heap->reserve = NULL;
3882+ }
3883+
3884+#if ZEND_MM_CACHE_STAT
3885+ if (full_shutdown) {
3886+ FILE *f;
3887+
3888+ f = fopen("zend_mm.log", "w");
3889+ if (f) {
3890+ int i,j;
3891+ size_t size, true_size, min_size, max_size;
3892+ int hit = 0, miss = 0;
3893+
3894+ fprintf(f, "\nidx min_size max_size true_size max_len hits misses\n");
3895+ size = 0;
3896+ while (1) {
3897+ true_size = ZEND_MM_TRUE_SIZE(size);
3898+ if (ZEND_MM_SMALL_SIZE(true_size)) {
3899+ min_size = size;
3900+ i = ZEND_MM_BUCKET_INDEX(true_size);
3901+ size++;
3902+ while (1) {
3903+ true_size = ZEND_MM_TRUE_SIZE(size);
3904+ if (ZEND_MM_SMALL_SIZE(true_size)) {
3905+ j = ZEND_MM_BUCKET_INDEX(true_size);
3906+ if (j > i) {
3907+ max_size = size-1;
3908+ break;
3909+ }
3910+ } else {
3911+ max_size = size-1;
3912+ break;
3913+ }
3914+ size++;
3915+ }
3916+ hit += heap->cache_stat[i].hit;
3917+ miss += heap->cache_stat[i].miss;
3918+ fprintf(f, "%2d %8d %8d %9d %8d %8d %8d\n", i, (int)min_size, (int)max_size, ZEND_MM_TRUE_SIZE(max_size), heap->cache_stat[i].max_count, heap->cache_stat[i].hit, heap->cache_stat[i].miss);
3919+ } else {
3920+ break;
3921+ }
3922+ }
3923+ fprintf(f, " %8d %8d\n", hit, miss);
3924+ fprintf(f, " %8d %8d\n", heap->cache_stat[ZEND_MM_NUM_BUCKETS].hit, heap->cache_stat[ZEND_MM_NUM_BUCKETS].miss);
3925+ fclose(f);
3926+ }
3927+ }
3928+#endif
3929+
3930+#if ZEND_DEBUG
3931+ if (!silent) {
3932+ zend_mm_check_leaks(heap TSRMLS_CC);
3933+ }
3934+#endif
3935+
3936+ internal = heap->internal;
3937+ storage = heap->storage;
3938+ segment = heap->segments_list;
3939+ while (segment) {
3940+ prev = segment;
3941+ segment = segment->next_segment;
3942+ ZEND_MM_STORAGE_FREE(prev);
3943+ }
3944+ if (full_shutdown) {
3945+ storage->handlers->dtor(storage);
3946+ if (!internal) {
3947+ free(heap);
3948+ }
3949+ } else {
3950+ if (heap->compact_size &&
3951+ heap->real_peak > heap->compact_size) {
3952+ storage->handlers->compact(storage);
3953+ }
3954+ heap->segments_list = NULL;
3955+ zend_mm_init(heap);
3956+ heap->real_size = 0;
3957+ heap->real_peak = 0;
3958+ heap->size = 0;
3959+ heap->peak = 0;
3960+ if (heap->reserve_size) {
3961+ heap->reserve = _zend_mm_alloc((zend_mm_heap *)heap, heap->reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
3962+ }
3963+ heap->overflow = 0;
3964+ }
3965+}
3966+
3967+static void zend_mm_safe_error(zend_mm_heap_canary *heap,
3968+ const char *format,
3969+ size_t limit,
3970+#if ZEND_DEBUG
3971+ const char *filename,
3972+ uint lineno,
3973+#endif
3974+ size_t size)
3975+{
3976+ if (heap->reserve) {
3977+ _zend_mm_free_canary_int(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
3978+ heap->reserve = NULL;
3979+ }
3980+ if (heap->overflow == 0) {
3981+ char *error_filename;
3982+ uint error_lineno;
3983+ TSRMLS_FETCH();
3984+ if (zend_is_compiling(TSRMLS_C)) {
3985+ error_filename = zend_get_compiled_filename(TSRMLS_C);
3986+ error_lineno = zend_get_compiled_lineno(TSRMLS_C);
3987+ } else if (EG(in_execution)) {
3988+ error_filename = EG(active_op_array)?EG(active_op_array)->filename:NULL;
3989+ error_lineno = EG(opline_ptr)?(*EG(opline_ptr))->lineno:0;
3990+ } else {
3991+ error_filename = NULL;
3992+ error_lineno = 0;
3993+ }
3994+ if (!error_filename) {
3995+ error_filename = "Unknown";
3996+ }
3997+ heap->overflow = 1;
3998+ zend_try {
3999+ zend_error_noreturn(E_ERROR,
4000+ format,
4001+ limit,
4002+#if ZEND_DEBUG
4003+ filename,
4004+ lineno,
4005+#endif
4006+ size);
4007+ } zend_catch {
4008+ if (heap->overflow == 2) {
4009+ fprintf(stderr, "\nFatal error: ");
4010+ fprintf(stderr,
4011+ format,
4012+ limit,
4013+#if ZEND_DEBUG
4014+ filename,
4015+ lineno,
4016+#endif
4017+ size);
4018+ fprintf(stderr, " in %s on line %d\n", error_filename, error_lineno);
4019+ }
4020+/* See http://support.microsoft.com/kb/190351 */
4021+#ifdef PHP_WIN32
4022+ fflush(stderr);
4023+#endif
4024+ } zend_end_try();
4025+ } else {
4026+ heap->overflow = 2;
4027+ }
4028+ zend_bailout();
4029+}
4030+
4031+static zend_mm_free_block_canary *zend_mm_search_large_block(zend_mm_heap_canary *heap, size_t true_size)
4032+{
4033+ zend_mm_free_block_canary *best_fit;
4034+ size_t index = ZEND_MM_LARGE_BUCKET_INDEX(true_size);
4035+ size_t bitmap = heap->large_free_bitmap >> index;
4036+ zend_mm_free_block_canary *p;
4037+
4038+ if (bitmap == 0) {
4039+ return NULL;
4040+ }
4041+
4042+ if (UNEXPECTED((bitmap & 1) != 0)) {
4043+ /* Search for best "large" free block */
4044+ zend_mm_free_block_canary *rst = NULL;
4045+ size_t m;
4046+ size_t best_size = -1;
4047+
4048+ best_fit = NULL;
4049+ p = heap->large_free_buckets[index];
4050+ for (m = true_size << (ZEND_MM_NUM_BUCKETS - index); ; m <<= 1) {
4051+ if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) {
4052+ return SUHOSIN_MANGLE_PTR(p->next_free_block);
4053+ } else if (ZEND_MM_FREE_BLOCK_SIZE(p) >= true_size &&
4054+ ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) {
4055+ best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
4056+ best_fit = p;
4057+ }
4058+ if ((m & (ZEND_MM_LONG_CONST(1) << (ZEND_MM_NUM_BUCKETS-1))) == 0) {
4059+ if (p->child[1]) {
4060+ rst = p->child[1];
4061+ }
4062+ if (p->child[0]) {
4063+ p = p->child[0];
4064+ } else {
4065+ break;
4066+ }
4067+ } else if (p->child[1]) {
4068+ p = p->child[1];
4069+ } else {
4070+ break;
4071+ }
4072+ }
4073+
4074+ for (p = rst; p; p = p->child[p->child[0] != NULL]) {
4075+ if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) {
4076+ return SUHOSIN_MANGLE_PTR(p->next_free_block);
4077+ } else if (ZEND_MM_FREE_BLOCK_SIZE(p) > true_size &&
4078+ ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) {
4079+ best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
4080+ best_fit = p;
4081+ }
4082+ }
4083+
4084+ if (best_fit) {
4085+ return SUHOSIN_MANGLE_PTR(best_fit->next_free_block);
4086+ }
4087+ bitmap = bitmap >> 1;
4088+ if (!bitmap) {
4089+ return NULL;
4090+ }
4091+ index++;
4092+ }
4093+
4094+ /* Search for smallest "large" free block */
4095+ best_fit = p = heap->large_free_buckets[index + zend_mm_low_bit(bitmap)];
4096+ while ((p = p->child[p->child[0] != NULL])) {
4097+ if (ZEND_MM_FREE_BLOCK_SIZE(p) < ZEND_MM_FREE_BLOCK_SIZE(best_fit)) {
4098+ best_fit = p;
4099+ }
4100+ }
4101+ return SUHOSIN_MANGLE_PTR(best_fit->next_free_block);
4102+}
4103+
4104+void *_zend_mm_alloc_canary_int(zend_mm_heap_canary *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
4105+{
4106+ zend_mm_free_block_canary *best_fit;
4107+ size_t true_size = ZEND_MM_TRUE_SIZE(size);
4108+ size_t block_size;
4109+ size_t remaining_size;
4110+ size_t segment_size;
4111+ zend_mm_segment *segment;
4112+ int keep_rest = 0;
4113+
4114+ if (EXPECTED(ZEND_MM_SMALL_SIZE(true_size))) {
4115+ size_t index = ZEND_MM_BUCKET_INDEX(true_size);
4116+ size_t bitmap;
4117+
4118+ if (UNEXPECTED(true_size < size)) {
4119+ goto out_of_memory;
4120+ }
4121+#if ZEND_MM_CACHE
4122+ if (EXPECTED(heap->cache[index] != NULL)) {
4123+ /* Get block from cache */
4124+#if ZEND_MM_CACHE_STAT
4125+ heap->cache_stat[index].count--;
4126+ heap->cache_stat[index].hit++;
4127+#endif
4128+ best_fit = SUHOSIN_MANGLE_PTR(heap->cache[index]);
4129+ heap->cache[index] = best_fit->prev_free_block;
4130+ heap->cached -= true_size;
4131+#if SUHOSIN_PATCH
4132+ SUHOSIN_MM_SET_CANARIES(best_fit);
4133+ ((zend_mm_block_canary*)best_fit)->info.size = size;
4134+ SUHOSIN_MM_SET_END_CANARY(best_fit);
4135+#endif
4136+ ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED);
4137+ ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
4138+ return ZEND_MM_DATA_OF(best_fit);
4139+ }
4140+#if ZEND_MM_CACHE_STAT
4141+ heap->cache_stat[index].miss++;
4142+#endif
4143+#endif
4144+
4145+ bitmap = heap->free_bitmap >> index;
4146+ if (bitmap) {
4147+ /* Found some "small" free block that can be used */
4148+ index += zend_mm_low_bit(bitmap);
4149+ best_fit = SUHOSIN_MANGLE_PTR(heap->free_buckets[index*2]);
4150+#if ZEND_MM_CACHE_STAT
4151+ heap->cache_stat[ZEND_MM_NUM_BUCKETS].hit++;
4152+#endif
4153+ goto zend_mm_finished_searching_for_block;
4154+ }
4155+ }
4156+
4157+#if ZEND_MM_CACHE_STAT
4158+ heap->cache_stat[ZEND_MM_NUM_BUCKETS].miss++;
4159+#endif
4160+
4161+ best_fit = zend_mm_search_large_block(heap, true_size);
4162+
4163+ if (!best_fit && heap->real_size >= heap->limit - heap->block_size) {
4164+ zend_mm_free_block_canary *p = SUHOSIN_MANGLE_PTR(heap->rest_buckets[0]);
4165+ size_t best_size = -1;
4166+
4167+ while (p != ZEND_MM_REST_BUCKET(heap)) {
4168+ if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) {
4169+ best_fit = p;
4170+ goto zend_mm_finished_searching_for_block;
4171+ } else if (ZEND_MM_FREE_BLOCK_SIZE(p) > true_size &&
4172+ ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) {
4173+ best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
4174+ best_fit = p;
4175+ }
4176+ p = SUHOSIN_MANGLE_PTR(p->prev_free_block);
4177+ }
4178+ }
4179+
4180+ if (!best_fit) {
4181+ if (true_size > heap->block_size - (ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE)) {
4182+ /* Make sure we add a memory block which is big enough,
4183+ segment must have header "size" and trailer "guard" block */
4184+ segment_size = true_size + ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE;
4185+ segment_size = (segment_size + (heap->block_size-1)) & ~(heap->block_size-1);
4186+ keep_rest = 1;
4187+ } else {
4188+ segment_size = heap->block_size;
4189+ }
4190+
4191+ HANDLE_BLOCK_INTERRUPTIONS();
4192+
4193+ if (segment_size < true_size ||
4194+ heap->real_size + segment_size > heap->limit) {
4195+ /* Memory limit overflow */
4196+#if ZEND_MM_CACHE
4197+ zend_mm_free_cache(heap);
4198+#endif
4199+ HANDLE_UNBLOCK_INTERRUPTIONS();
4200+#if ZEND_DEBUG
4201+ zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted at %s:%d (tried to allocate %lu bytes)", heap->limit, __zend_filename, __zend_lineno, size);
4202+#else
4203+ zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted (tried to allocate %lu bytes)", heap->limit, size);
4204+#endif
4205+ }
4206+
4207+ segment = (zend_mm_segment *) ZEND_MM_STORAGE_ALLOC(segment_size);
4208+
4209+ if (!segment) {
4210+ /* Storage manager cannot allocate memory */
4211+#if ZEND_MM_CACHE
4212+ zend_mm_free_cache(heap);
4213+#endif
4214+ HANDLE_UNBLOCK_INTERRUPTIONS();
4215+out_of_memory:
4216+#if ZEND_DEBUG
4217+ zend_mm_safe_error(heap, "Out of memory (allocated %ld) at %s:%d (tried to allocate %lu bytes)", heap->real_size, __zend_filename, __zend_lineno, size);
4218+#else
4219+ zend_mm_safe_error(heap, "Out of memory (allocated %ld) (tried to allocate %lu bytes)", heap->real_size, size);
4220+#endif
4221+ return NULL;
4222+ }
4223+
4224+ heap->real_size += segment_size;
4225+ if (heap->real_size > heap->real_peak) {
4226+ heap->real_peak = heap->real_size;
4227+ }
4228+
4229+ segment->size = segment_size;
4230+ segment->next_segment = heap->segments_list;
4231+ heap->segments_list = segment;
4232+
4233+ best_fit = (zend_mm_free_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
4234+ ZEND_MM_MARK_FIRST_BLOCK(best_fit);
4235+
4236+ block_size = segment_size - ZEND_MM_ALIGNED_SEGMENT_SIZE - ZEND_MM_ALIGNED_HEADER_SIZE;
4237+
4238+ ZEND_MM_LAST_BLOCK(ZEND_MM_BLOCK_AT(best_fit, block_size));
4239+
4240+ } else {
4241+zend_mm_finished_searching_for_block:
4242+ /* remove from free list */
4243+ HANDLE_BLOCK_INTERRUPTIONS();
4244+ ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_FREED);
4245+ ZEND_MM_CHECK_COOKIE(best_fit);
4246+ ZEND_MM_CHECK_BLOCK_LINKAGE(best_fit);
4247+ zend_mm_remove_from_free_list(heap, best_fit);
4248+
4249+ block_size = ZEND_MM_FREE_BLOCK_SIZE(best_fit);
4250+ }
4251+
4252+ remaining_size = block_size - true_size;
4253+
4254+ if (remaining_size < ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
4255+ true_size = block_size;
4256+ ZEND_MM_BLOCK(best_fit, ZEND_MM_USED_BLOCK, true_size);
4257+ } else {
4258+ zend_mm_free_block_canary *new_free_block;
4259+
4260+ /* prepare new free block */
4261+ ZEND_MM_BLOCK(best_fit, ZEND_MM_USED_BLOCK, true_size);
4262+ new_free_block = (zend_mm_free_block_canary *) ZEND_MM_BLOCK_AT(best_fit, true_size);
4263+ ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
4264+
4265+ /* add the new free block to the free list */
4266+ if (EXPECTED(!keep_rest)) {
4267+ zend_mm_add_to_free_list(heap, new_free_block);
4268+ } else {
4269+ zend_mm_add_to_rest_list(heap, new_free_block);
4270+ }
4271+ }
4272+
4273+ ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 1);
4274+
4275+#if SUHOSIN_PATCH
4276+ SUHOSIN_MM_SET_CANARIES(best_fit);
4277+ ((zend_mm_block_canary*)best_fit)->info.size = size;
4278+ SUHOSIN_MM_SET_END_CANARY(best_fit);
4279+#endif
4280+
4281+ heap->size += true_size;
4282+ if (heap->peak < heap->size) {
4283+ heap->peak = heap->size;
4284+ }
4285+
4286+ HANDLE_UNBLOCK_INTERRUPTIONS();
4287+ return ZEND_MM_DATA_OF(best_fit);
4288+}
4289+
4290+
4291+void _zend_mm_free_canary_int(zend_mm_heap_canary *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
4292+{
4293+ zend_mm_block_canary *mm_block;
4294+ zend_mm_block_canary *next_block;
4295+ size_t size;
4296+
4297+ if (!ZEND_MM_VALID_PTR(p)) {
4298+ return;
4299+ }
4300+
4301+ mm_block = ZEND_MM_HEADER_OF(p);
4302+ size = ZEND_MM_BLOCK_SIZE(mm_block);
4303+#if SUHOSIN_PATCH
4304+ SUHOSIN_MM_CHECK_CANARIES(mm_block, "efree()");
4305+#endif
4306+ ZEND_MM_CHECK_PROTECTION(mm_block);
4307+
4308+#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
4309+ memset(ZEND_MM_DATA_OF(mm_block), 0x5a, mm_block->debug.size);
4310+#endif
4311+#if SUHOSIN_PATCH
4312+ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_DESTROY_FREE_MEMORY))) {
4313+ memset(ZEND_MM_DATA_OF(mm_block), 0x5a, mm_block->info.size);
4314+ }
4315+#endif
4316+#if ZEND_MM_CACHE
4317+ if (EXPECTED(ZEND_MM_SMALL_SIZE(size)) && EXPECTED(heap->cached < ZEND_MM_CACHE_SIZE)) {
4318+ size_t index = ZEND_MM_BUCKET_INDEX(size);
4319+ zend_mm_free_block_canary **cache = &heap->cache[index];
4320+
4321+ ((zend_mm_free_block_canary*)mm_block)->prev_free_block = *cache;
4322+ *cache = (zend_mm_free_block_canary*)SUHOSIN_MANGLE_PTR(mm_block);
4323+ heap->cached += size;
4324+ ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_CACHED);
4325+#if ZEND_MM_CACHE_STAT
4326+ if (++heap->cache_stat[index].count > heap->cache_stat[index].max_count) {
4327+ heap->cache_stat[index].max_count = heap->cache_stat[index].count;
4328+ }
4329+#endif
4330+ return;
4331+ }
4332+#endif
4333+
4334+ HANDLE_BLOCK_INTERRUPTIONS();
4335+
4336+ heap->size -= size;
4337+
4338+ next_block = ZEND_MM_BLOCK_AT(mm_block, size);
4339+ if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
4340+ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) next_block);
4341+ size += ZEND_MM_FREE_BLOCK_SIZE(next_block);
4342+ }
4343+ if (ZEND_MM_PREV_BLOCK_IS_FREE(mm_block)) {
4344+ mm_block = ZEND_MM_PREV_BLOCK(mm_block);
4345+ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) mm_block);
4346+ size += ZEND_MM_FREE_BLOCK_SIZE(mm_block);
4347+ }
4348+ if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
4349+ ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(mm_block, size))) {
4350+ zend_mm_del_segment(heap, (zend_mm_segment *) ((char *)mm_block - ZEND_MM_ALIGNED_SEGMENT_SIZE));
4351+ } else {
4352+ ZEND_MM_BLOCK(mm_block, ZEND_MM_FREE_BLOCK, size);
4353+ zend_mm_add_to_free_list(heap, (zend_mm_free_block_canary *) mm_block);
4354+ }
4355+ HANDLE_UNBLOCK_INTERRUPTIONS();
4356+}
4357+
4358+void *_zend_mm_realloc_canary_int(zend_mm_heap_canary *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
4359+{
4360+ zend_mm_block_canary *mm_block = ZEND_MM_HEADER_OF(p);
4361+ zend_mm_block_canary *next_block;
4362+ size_t true_size;
4363+ size_t orig_size;
4364+ void *ptr;
4365+
4366+ if (UNEXPECTED(!p) || !ZEND_MM_VALID_PTR(p)) {
4367+ return _zend_mm_alloc_canary_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
4368+ }
4369+ mm_block = ZEND_MM_HEADER_OF(p);
4370+ true_size = ZEND_MM_TRUE_SIZE(size);
4371+ orig_size = ZEND_MM_BLOCK_SIZE(mm_block);
4372+#if SUHOSIN_PATCH
4373+ SUHOSIN_MM_CHECK_CANARIES(mm_block, "erealloc()");
4374+#endif
4375+ ZEND_MM_CHECK_PROTECTION(mm_block);
4376+
4377+ if (UNEXPECTED(true_size < size)) {
4378+ goto out_of_memory;
4379+ }
4380+
4381+ if (true_size <= orig_size) {
4382+ size_t remaining_size = orig_size - true_size;
4383+
4384+ if (remaining_size >= ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
4385+ zend_mm_free_block_canary *new_free_block;
4386+
4387+ HANDLE_BLOCK_INTERRUPTIONS();
4388+ next_block = ZEND_MM_BLOCK_AT(mm_block, orig_size);
4389+ if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
4390+ remaining_size += ZEND_MM_FREE_BLOCK_SIZE(next_block);
4391+ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) next_block);
4392+ }
4393+
4394+ /* prepare new free block */
4395+ ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
4396+ new_free_block = (zend_mm_free_block_canary *) ZEND_MM_BLOCK_AT(mm_block, true_size);
4397+
4398+ ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
4399+
4400+ /* add the new free block to the free list */
4401+ zend_mm_add_to_free_list(heap, new_free_block);
4402+ heap->size += (true_size - orig_size);
4403+ HANDLE_UNBLOCK_INTERRUPTIONS();
4404+ }
4405+ ZEND_MM_SET_DEBUG_INFO(mm_block, size, 0, 0);
4406+#if SUHOSIN_PATCH
4407+ SUHOSIN_MM_SET_CANARIES(mm_block);
4408+ ((zend_mm_block_canary*)mm_block)->info.size = size;
4409+ SUHOSIN_MM_SET_END_CANARY(mm_block);
4410+#endif
4411+ return p;
4412+ }
4413+
4414+#if ZEND_MM_CACHE
4415+ if (ZEND_MM_SMALL_SIZE(true_size)) {
4416+ size_t index = ZEND_MM_BUCKET_INDEX(true_size);
4417+
4418+ if (heap->cache[index] != NULL) {
4419+ zend_mm_free_block_canary *best_fit;
4420+ zend_mm_free_block_canary **cache;
4421+
4422+#if ZEND_MM_CACHE_STAT
4423+ heap->cache_stat[index].count--;
4424+ heap->cache_stat[index].hit++;
4425+#endif
4426+ best_fit = SUHOSIN_MANGLE_PTR(heap->cache[index]);
4427+ heap->cache[index] = best_fit->prev_free_block;
4428+ ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED);
4429+ ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
4430+#if SUHOSIN_PATCH
4431+ SUHOSIN_MM_SET_CANARIES(best_fit);
4432+ ((zend_mm_block_canary*)best_fit)->info.size = size;
4433+ SUHOSIN_MM_SET_END_CANARY(best_fit);
4434+#endif
4435+
4436+ ptr = ZEND_MM_DATA_OF(best_fit);
4437+
4438+#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
4439+ memcpy(ptr, p, mm_block->debug.size);
4440+#else
4441+ memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE - CANARY_SIZE);
4442+#endif
4443+
4444+ heap->cached -= true_size - orig_size;
4445+
4446+ index = ZEND_MM_BUCKET_INDEX(orig_size);
4447+ cache = &heap->cache[index];
4448+
4449+ ((zend_mm_free_block_canary*)mm_block)->prev_free_block = *cache;
4450+ *cache = (zend_mm_free_block_canary*)SUHOSIN_MANGLE_PTR(mm_block);
4451+ ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_CACHED);
4452+#if ZEND_MM_CACHE_STAT
4453+ if (++heap->cache_stat[index].count > heap->cache_stat[index].max_count) {
4454+ heap->cache_stat[index].max_count = heap->cache_stat[index].count;
4455+ }
4456+#endif
4457+ return ptr;
4458+ }
4459+ }
4460+#endif
4461+
4462+ next_block = ZEND_MM_BLOCK_AT(mm_block, orig_size);
4463+
4464+ if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
4465+ ZEND_MM_CHECK_COOKIE(next_block);
4466+ ZEND_MM_CHECK_BLOCK_LINKAGE(next_block);
4467+ if (orig_size + ZEND_MM_FREE_BLOCK_SIZE(next_block) >= true_size) {
4468+ size_t block_size = orig_size + ZEND_MM_FREE_BLOCK_SIZE(next_block);
4469+ size_t remaining_size = block_size - true_size;
4470+
4471+ HANDLE_BLOCK_INTERRUPTIONS();
4472+ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) next_block);
4473+
4474+ if (remaining_size < ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
4475+ true_size = block_size;
4476+ ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
4477+ } else {
4478+ zend_mm_free_block_canary *new_free_block;
4479+
4480+ /* prepare new free block */
4481+ ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
4482+ new_free_block = (zend_mm_free_block_canary *) ZEND_MM_BLOCK_AT(mm_block, true_size);
4483+ ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
4484+
4485+ /* add the new free block to the free list */
4486+ if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
4487+ ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(new_free_block, remaining_size))) {
4488+ zend_mm_add_to_rest_list(heap, new_free_block);
4489+ } else {
4490+ zend_mm_add_to_free_list(heap, new_free_block);
4491+ }
4492+ }
4493+ ZEND_MM_SET_DEBUG_INFO(mm_block, size, 0, 0);
4494+ heap->size = heap->size + true_size - orig_size;
4495+ if (heap->peak < heap->size) {
4496+ heap->peak = heap->size;
4497+ }
4498+ HANDLE_UNBLOCK_INTERRUPTIONS();
4499+#if SUHOSIN_PATCH
4500+ SUHOSIN_MM_SET_CANARIES(mm_block);
4501+ ((zend_mm_block_canary*)mm_block)->info.size = size;
4502+ SUHOSIN_MM_SET_END_CANARY(mm_block);
4503+#endif
4504+ return p;
4505+ } else if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
4506+ ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(next_block, ZEND_MM_FREE_BLOCK_SIZE(next_block)))) {
4507+ HANDLE_BLOCK_INTERRUPTIONS();
4508+ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) next_block);
4509+ goto realloc_segment;
4510+ }
4511+ } else if (ZEND_MM_IS_FIRST_BLOCK(mm_block) && ZEND_MM_IS_GUARD_BLOCK(next_block)) {
4512+ zend_mm_segment *segment;
4513+ zend_mm_segment *segment_copy;
4514+ size_t segment_size;
4515+ size_t block_size;
4516+ size_t remaining_size;
4517+
4518+ HANDLE_BLOCK_INTERRUPTIONS();
4519+realloc_segment:
4520+ /* segment size, size of block and size of guard block */
4521+ if (true_size > heap->block_size - (ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE)) {
4522+ segment_size = true_size+ZEND_MM_ALIGNED_SEGMENT_SIZE+ZEND_MM_ALIGNED_HEADER_SIZE;
4523+ segment_size = (segment_size + (heap->block_size-1)) & ~(heap->block_size-1);
4524+ } else {
4525+ segment_size = heap->block_size;
4526+ }
4527+
4528+ segment_copy = (zend_mm_segment *) ((char *)mm_block - ZEND_MM_ALIGNED_SEGMENT_SIZE);
4529+ if (segment_size < true_size ||
4530+ heap->real_size + segment_size - segment_copy->size > heap->limit) {
4531+ if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
4532+ zend_mm_add_to_free_list(heap, (zend_mm_free_block_canary *) next_block);
4533+ }
4534+#if ZEND_MM_CACHE
4535+ zend_mm_free_cache(heap);
4536+#endif
4537+ HANDLE_UNBLOCK_INTERRUPTIONS();
4538+#if ZEND_DEBUG
4539+ zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted at %s:%d (tried to allocate %ld bytes)", heap->limit, __zend_filename, __zend_lineno, size);
4540+#else
4541+ zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted (tried to allocate %ld bytes)", heap->limit, size);
4542+#endif
4543+ return NULL;
4544+ }
4545+
4546+ segment = ZEND_MM_STORAGE_REALLOC(segment_copy, segment_size);
4547+ if (!segment) {
4548+#if ZEND_MM_CACHE
4549+ zend_mm_free_cache(heap);
4550+#endif
4551+ HANDLE_UNBLOCK_INTERRUPTIONS();
4552+out_of_memory:
4553+#if ZEND_DEBUG
4554+ zend_mm_safe_error(heap, "Out of memory (allocated %ld) at %s:%d (tried to allocate %ld bytes)", heap->real_size, __zend_filename, __zend_lineno, size);
4555+#else
4556+ zend_mm_safe_error(heap, "Out of memory (allocated %ld) (tried to allocate %ld bytes)", heap->real_size, size);
4557+#endif
4558+ return NULL;
4559+ }
4560+ heap->real_size += segment_size - segment->size;
4561+ if (heap->real_size > heap->real_peak) {
4562+ heap->real_peak = heap->real_size;
4563+ }
4564+
4565+ segment->size = segment_size;
4566+
4567+ if (segment != segment_copy) {
4568+ zend_mm_segment **seg = &heap->segments_list;
4569+ while (*seg != segment_copy) {
4570+ seg = &(*seg)->next_segment;
4571+ }
4572+ *seg = segment;
4573+ mm_block = (zend_mm_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
4574+ ZEND_MM_MARK_FIRST_BLOCK(mm_block);
4575+ }
4576+
4577+ block_size = segment_size - ZEND_MM_ALIGNED_SEGMENT_SIZE - ZEND_MM_ALIGNED_HEADER_SIZE;
4578+ remaining_size = block_size - true_size;
4579+
4580+ /* setup guard block */
4581+ ZEND_MM_LAST_BLOCK(ZEND_MM_BLOCK_AT(mm_block, block_size));
4582+
4583+ if (remaining_size < ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
4584+ true_size = block_size;
4585+ ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
4586+ } else {
4587+ zend_mm_free_block_canary *new_free_block;
4588+
4589+ /* prepare new free block */
4590+ ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
4591+ new_free_block = (zend_mm_free_block_canary *) ZEND_MM_BLOCK_AT(mm_block, true_size);
4592+ ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
4593+
4594+ /* add the new free block to the free list */
4595+ zend_mm_add_to_rest_list(heap, new_free_block);
4596+ }
4597+
4598+ ZEND_MM_SET_DEBUG_INFO(mm_block, size, 1, 1);
4599+
4600+ heap->size = heap->size + true_size - orig_size;
4601+ if (heap->peak < heap->size) {
4602+ heap->peak = heap->size;
4603+ }
4604+
4605+ HANDLE_UNBLOCK_INTERRUPTIONS();
4606+#if SUHOSIN_PATCH
4607+ SUHOSIN_MM_SET_CANARIES(mm_block);
4608+ ((zend_mm_block_canary*)mm_block)->info.size = size;
4609+ SUHOSIN_MM_SET_END_CANARY(mm_block);
4610+#endif
4611+ return ZEND_MM_DATA_OF(mm_block);
4612+ }
4613+
4614+ ptr = _zend_mm_alloc_canary_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
4615+#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
4616+ memcpy(ptr, p, mm_block->debug.size);
4617+#else
4618+ memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE - CANARY_SIZE);
4619+#endif
4620+ _zend_mm_free_canary_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
4621+ return ptr;
4622+}
4623+
4624+ZEND_API size_t _zend_mm_block_size_canary(zend_mm_heap_canary *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
4625+{
4626+ zend_mm_block_canary *mm_block;
4627+
4628+ if (!ZEND_MM_VALID_PTR(p)) {
4629+ return 0;
4630+ }
4631+ mm_block = ZEND_MM_HEADER_OF(p);
4632+ ZEND_MM_CHECK_PROTECTION(mm_block);
4633+#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
4634+ return mm_block->debug.size;
4635+#else
4636+ return ZEND_MM_BLOCK_SIZE(mm_block);
4637+#endif
4638+}
4639+
4640+#if defined(__GNUC__) && defined(i386)
4641+
4642+static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
4643+{
4644+ size_t res = nmemb;
4645+ unsigned long overflow = 0;
4646+
4647+ __asm__ ("mull %3\n\taddl %4,%0\n\tadcl %1,%1"
4648+ : "=&a"(res), "=&d" (overflow)
4649+ : "%0"(res),
4650+ "rm"(size),
4651+ "rm"(offset));
4652+
4653+ if (UNEXPECTED(overflow)) {
4654+ zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
4655+ return 0;
4656+ }
4657+ return res;
4658+}
4659+
4660+#elif defined(__GNUC__) && defined(__x86_64__)
4661+
4662+static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
4663+{
4664+ size_t res = nmemb;
4665+ unsigned long overflow = 0;
4666+
4667+ __asm__ ("mulq %3\n\taddq %4,%0\n\tadcq %1,%1"
4668+ : "=&a"(res), "=&d" (overflow)
4669+ : "%0"(res),
4670+ "rm"(size),
4671+ "rm"(offset));
4672+
4673+ if (UNEXPECTED(overflow)) {
4674+ zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
4675+ return 0;
4676+ }
4677+ return res;
4678+}
4679+
4680+#elif SIZEOF_SIZE_T == 4 && defined(HAVE_ZEND_LONG64)
4681+
4682+static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
4683+{
4684+ zend_ulong64 res = (zend_ulong64)nmemb * (zend_ulong64)size + (zend_ulong64)offset;
4685+
4686+ if (UNEXPECTED(res > (zend_ulong64)0xFFFFFFFFL)) {
4687+ zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
4688+ return 0;
4689+ }
4690+ return (size_t) res;
4691+}
4692+
4693+#else
4694+
4695+static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
4696+{
4697+ size_t res = nmemb * size + offset;
4698+ double _d = (double)nmemb * (double)size + (double)offset;
4699+ double _delta = (double)res - _d;
4700+
4701+ if (UNEXPECTED((_d + _delta ) != _d)) {
4702+ zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
4703+ return 0;
4704+ }
4705+ return res;
4706+}
4707+#endif
4708+
4709+/*
4710+ * Local variables:
4711+ * tab-width: 4
4712+ * c-basic-offset: 4
4713+ * indent-tabs-mode: t
4714+ * End:
4715+ */
4716+
4717diff -Naurp php-5.3.6RC1/Zend/zend_alloc.h php-5.3.6RC1.oden/Zend/zend_alloc.h
4718--- php-5.3.6RC1/Zend/zend_alloc.h 2011-01-01 03:19:59.000000000 +0100
4719+++ php-5.3.6RC1.oden/Zend/zend_alloc.h 2011-02-20 11:50:19.320838976 +0100
4720@@ -203,6 +203,8 @@ END_EXTERN_C()
4721
4722 /* Heap functions */
4723 typedef struct _zend_mm_heap zend_mm_heap;
4724+typedef struct _zend_mm_heap_canary zend_mm_heap_canary;
4725+
4726
4727 ZEND_API zend_mm_heap *zend_mm_startup(void);
4728 ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC);
4729diff -Naurp php-5.3.6RC1/Zend/zend.c php-5.3.6RC1.oden/Zend/zend.c
4730--- php-5.3.6RC1/Zend/zend.c 2011-01-01 03:19:59.000000000 +0100
4731+++ php-5.3.6RC1.oden/Zend/zend.c 2011-02-20 11:50:19.321839116 +0100
4732@@ -60,6 +60,10 @@ int (*zend_vspprintf)(char **pbuf, size_
4733 ZEND_API char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC);
4734 ZEND_API char *(*zend_resolve_path)(const char *filename, int filename_len TSRMLS_DC);
4735
4736+#if SUHOSIN_PATCH
4737+ZEND_API void (*zend_suhosin_log)(int loglevel, char *fmt, ...);
4738+#endif
4739+
4740 void (*zend_on_timeout)(int seconds TSRMLS_DC);
4741
4742 static void (*zend_message_dispatcher_p)(long message, void *data TSRMLS_DC);
4743@@ -88,6 +92,74 @@ static ZEND_INI_MH(OnUpdateGCEnabled) /*
4744 }
4745 /* }}} */
4746
4747+#if SUHOSIN_PATCH
4748+static ZEND_INI_MH(OnUpdateSuhosin_log_syslog)
4749+{
4750+ if (!new_value) {
4751+ SPG(log_syslog) = S_ALL & ~S_SQL | S_MEMORY;
4752+ } else {
4753+ SPG(log_syslog) = atoi(new_value) | S_MEMORY;
4754+ }
4755+ return SUCCESS;
4756+}
4757+static ZEND_INI_MH(OnUpdateSuhosin_log_syslog_facility)
4758+{
4759+ if (!new_value) {
4760+ SPG(log_syslog_facility) = LOG_USER;
4761+ } else {
4762+ SPG(log_syslog_facility) = atoi(new_value);
4763+ }
4764+ return SUCCESS;
4765+}
4766+static ZEND_INI_MH(OnUpdateSuhosin_log_syslog_priority)
4767+{
4768+ if (!new_value) {
4769+ SPG(log_syslog_priority) = LOG_ALERT;
4770+ } else {
4771+ SPG(log_syslog_priority) = atoi(new_value);
4772+ }
4773+ return SUCCESS;
4774+}
4775+static ZEND_INI_MH(OnUpdateSuhosin_log_sapi)
4776+{
4777+ if (!new_value) {
4778+ SPG(log_sapi) = S_ALL & ~S_SQL;
4779+ } else {
4780+ SPG(log_sapi) = atoi(new_value);
4781+ }
4782+ return SUCCESS;
4783+}
4784+static ZEND_INI_MH(OnUpdateSuhosin_log_script)
4785+{
4786+ if (!new_value) {
4787+ SPG(log_script) = S_ALL & ~S_MEMORY;
4788+ } else {
4789+ SPG(log_script) = atoi(new_value) & (~S_MEMORY) & (~S_INTERNAL);
4790+ }
4791+ return SUCCESS;
4792+}
4793+static ZEND_INI_MH(OnUpdateSuhosin_log_scriptname)
4794+{
4795+ if (SPG(log_scriptname)) {
4796+ pefree(SPG(log_scriptname),1);
4797+ }
4798+ SPG(log_scriptname) = NULL;
4799+ if (new_value) {
4800+ SPG(log_scriptname) = pestrdup(new_value,1);
4801+ }
4802+ return SUCCESS;
4803+}
4804+static ZEND_INI_MH(OnUpdateSuhosin_log_phpscript)
4805+{
4806+ if (!new_value) {
4807+ SPG(log_phpscript) = S_ALL & ~S_MEMORY;
4808+ } else {
4809+ SPG(log_phpscript) = atoi(new_value) & (~S_MEMORY) & (~S_INTERNAL);
4810+ }
4811+ return SUCCESS;
4812+}
4813+#endif
4814+
4815 ZEND_INI_BEGIN()
4816 ZEND_INI_ENTRY("error_reporting", NULL, ZEND_INI_ALL, OnUpdateErrorReporting)
4817 STD_ZEND_INI_BOOLEAN("zend.enable_gc", "1", ZEND_INI_ALL, OnUpdateGCEnabled, gc_enabled, zend_gc_globals, gc_globals)
4818diff -Naurp php-5.3.6RC1/Zend/zend_canary.c php-5.3.6RC1.oden/Zend/zend_canary.c
4819--- php-5.3.6RC1/Zend/zend_canary.c 1970-01-01 01:00:00.000000000 +0100
4820+++ php-5.3.6RC1.oden/Zend/zend_canary.c 2011-02-20 11:50:19.322839257 +0100
4821@@ -0,0 +1,66 @@
4822+/*
4823+ +----------------------------------------------------------------------+
4824+ | Suhosin-Patch for PHP |
4825+ +----------------------------------------------------------------------+
4826+ | Copyright (c) 2004-2009 Stefan Esser |
4827+ +----------------------------------------------------------------------+
4828+ | This source file is subject to version 2.02 of the PHP license, |
4829+ | that is bundled with this package in the file LICENSE, and is |
4830+ | available at through the world-wide-web at |
4831+ | http://www.php.net/license/2_02.txt. |
4832+ | If you did not receive a copy of the PHP license and are unable to |
4833+ | obtain it through the world-wide-web, please send a note to |
4834+ | license@php.net so we can mail you a copy immediately. |
4835+ +----------------------------------------------------------------------+
4836+ | Author: Stefan Esser <stefan.esser@sektioneins.de> |
4837+ +----------------------------------------------------------------------+
4838+ */
4839+/* $Id$ */
4840+
4841+#include "zend.h"
4842+
4843+#include <stdio.h>
4844+#include <stdlib.h>
4845+
4846+
4847+#if SUHOSIN_PATCH
4848+
4849+static size_t last_canary = 0x73625123;
4850+
4851+/* will be replaced later with more compatible method */
4852+ZEND_API void zend_canary(void *buf, int len)
4853+{
4854+ time_t t;
4855+ size_t canary;
4856+ int fd;
4857+
4858+#ifndef PHP_WIN32
4859+ fd = open("/dev/urandom", 0);
4860+ if (fd != -1) {
4861+ int r = read(fd, buf, len);
4862+ close(fd);
4863+ if (r == len) {
4864+ return;
4865+ }
4866+ }
4867+#endif
4868+ /* not good but we never want to do this */
4869+ time(&t);
4870+ canary = *(unsigned int *)&t + getpid() << 16 + last_canary;
4871+ last_canary ^= (canary << 5) | (canary >> (32-5));
4872+ /* When we ensure full win32 compatibility in next version
4873+ we will replace this with the random number code from zend_alloc.c */
4874+ memcpy(buf, &canary, len);
4875+}
4876+
4877+#endif
4878+
4879+
4880+/*
4881+ * Local variables:
4882+ * tab-width: 4
4883+ * c-basic-offset: 4
4884+ * End:
4885+ * vim600: sw=4 ts=4 fdm=marker
4886+ * vim<600: sw=4 ts=4
4887+ */
4888diff -Naurp php-5.3.6RC1/Zend/zend_compile.c php-5.3.6RC1.oden/Zend/zend_compile.c
4889--- php-5.3.6RC1/Zend/zend_compile.c 2011-01-19 18:17:52.000000000 +0100
4890+++ php-5.3.6RC1.oden/Zend/zend_compile.c 2011-02-20 11:50:19.323839398 +0100
4891@@ -73,6 +73,11 @@ static void zend_destroy_property_info_i
4892 }
4893 /* }}} */
4894
4895+#if SUHOSIN_PATCH
4896+void *suhosin_zend_destroy_property_info_internal = zend_destroy_property_info_internal;
4897+void *suhosin_zend_destroy_property_info = zend_destroy_property_info;
4898+#endif
4899+
4900 static void build_runtime_defined_function_key(zval *result, const char *name, int name_length TSRMLS_DC) /* {{{ */
4901 {
4902 char char_pos_buf[32];
4903diff -Naurp php-5.3.6RC1/Zend/zend_compile.h php-5.3.6RC1.oden/Zend/zend_compile.h
4904--- php-5.3.6RC1/Zend/zend_compile.h 2011-01-01 03:19:59.000000000 +0100
4905+++ php-5.3.6RC1.oden/Zend/zend_compile.h 2011-02-20 11:50:19.324839539 +0100
4906@@ -606,6 +606,11 @@ ZEND_API zend_bool zend_is_auto_global(c
4907 ZEND_API int zend_auto_global_disable_jit(const char *varname, zend_uint varname_length TSRMLS_DC);
4908 ZEND_API size_t zend_dirname(char *path, size_t len);
4909
4910+#if SUHOSIN_PATCH
4911+extern void *suhosin_zend_destroy_property_info_internal;
4912+extern void *suhosin_zend_destroy_property_info;
4913+#endif
4914+
4915 int zendlex(znode *zendlval TSRMLS_DC);
4916
4917 /* BEGIN: OPCODES */
4918diff -Naurp php-5.3.6RC1/Zend/zend_constants.c php-5.3.6RC1.oden/Zend/zend_constants.c
4919--- php-5.3.6RC1/Zend/zend_constants.c 2011-01-16 21:39:22.000000000 +0100
4920+++ php-5.3.6RC1.oden/Zend/zend_constants.c 2011-02-20 11:52:28.887065479 +0100
4921@@ -115,6 +115,77 @@ void zend_register_standard_constants(TS
4922
4923 REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_PROVIDE_OBJECT", DEBUG_BACKTRACE_PROVIDE_OBJECT, CONST_PERSISTENT | CONST_CS);
4924 REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_IGNORE_ARGS", DEBUG_BACKTRACE_IGNORE_ARGS, CONST_PERSISTENT | CONST_CS);
4925+
4926+#if SUHOSIN_PATCH
4927+ REGISTER_MAIN_LONG_CONSTANT("S_MEMORY", S_MEMORY, CONST_PERSISTENT | CONST_CS);
4928+ REGISTER_MAIN_LONG_CONSTANT("S_VARS", S_VARS, CONST_PERSISTENT | CONST_CS);
4929+ REGISTER_MAIN_LONG_CONSTANT("S_FILES", S_FILES, CONST_PERSISTENT | CONST_CS);
4930+ REGISTER_MAIN_LONG_CONSTANT("S_INCLUDE", S_INCLUDE, CONST_PERSISTENT | CONST_CS);
4931+ REGISTER_MAIN_LONG_CONSTANT("S_SQL", S_SQL, CONST_PERSISTENT | CONST_CS);
4932+ REGISTER_MAIN_LONG_CONSTANT("S_EXECUTOR", S_EXECUTOR, CONST_PERSISTENT | CONST_CS);
4933+ REGISTER_MAIN_LONG_CONSTANT("S_MAIL", S_MAIL, CONST_PERSISTENT | CONST_CS);
4934+ REGISTER_MAIN_LONG_CONSTANT("S_SESSION", S_SESSION, CONST_PERSISTENT | CONST_CS);
4935+ REGISTER_MAIN_LONG_CONSTANT("S_MISC", S_MISC, CONST_PERSISTENT | CONST_CS);
4936+ REGISTER_MAIN_LONG_CONSTANT("S_INTERNAL", S_INTERNAL, CONST_PERSISTENT | CONST_CS);
4937+ REGISTER_MAIN_LONG_CONSTANT("S_ALL", S_ALL, CONST_PERSISTENT | CONST_CS);
4938+
4939+ /* error levels */
4940+ REGISTER_MAIN_LONG_CONSTANT("LOG_EMERG", LOG_EMERG, CONST_CS | CONST_PERSISTENT); /* system unusable */
4941+ REGISTER_MAIN_LONG_CONSTANT("LOG_ALERT", LOG_ALERT, CONST_CS | CONST_PERSISTENT); /* immediate action required */
4942+ REGISTER_MAIN_LONG_CONSTANT("LOG_CRIT", LOG_CRIT, CONST_CS | CONST_PERSISTENT); /* critical conditions */
4943+ REGISTER_MAIN_LONG_CONSTANT("LOG_ERR", LOG_ERR, CONST_CS | CONST_PERSISTENT);
4944+ REGISTER_MAIN_LONG_CONSTANT("LOG_WARNING", LOG_WARNING, CONST_CS | CONST_PERSISTENT);
4945+ REGISTER_MAIN_LONG_CONSTANT("LOG_NOTICE", LOG_NOTICE, CONST_CS | CONST_PERSISTENT);
4946+ REGISTER_MAIN_LONG_CONSTANT("LOG_INFO", LOG_INFO, CONST_CS | CONST_PERSISTENT);
4947+ REGISTER_MAIN_LONG_CONSTANT("LOG_DEBUG", LOG_DEBUG, CONST_CS | CONST_PERSISTENT);
4948+ /* facility: type of program logging the message */
4949+ REGISTER_MAIN_LONG_CONSTANT("LOG_KERN", LOG_KERN, CONST_CS | CONST_PERSISTENT);
4950+ REGISTER_MAIN_LONG_CONSTANT("LOG_USER", LOG_USER, CONST_CS | CONST_PERSISTENT); /* generic user level */
4951+ REGISTER_MAIN_LONG_CONSTANT("LOG_MAIL", LOG_MAIL, CONST_CS | CONST_PERSISTENT); /* log to email */
4952+ REGISTER_MAIN_LONG_CONSTANT("LOG_DAEMON", LOG_DAEMON, CONST_CS | CONST_PERSISTENT); /* other system daemons */
4953+ REGISTER_MAIN_LONG_CONSTANT("LOG_AUTH", LOG_AUTH, CONST_CS | CONST_PERSISTENT);
4954+ REGISTER_MAIN_LONG_CONSTANT("LOG_SYSLOG", LOG_SYSLOG, CONST_CS | CONST_PERSISTENT);
4955+ REGISTER_MAIN_LONG_CONSTANT("LOG_LPR", LOG_LPR, CONST_CS | CONST_PERSISTENT);
4956+#ifdef LOG_NEWS
4957+ /* No LOG_NEWS on HP-UX */
4958+ REGISTER_MAIN_LONG_CONSTANT("LOG_NEWS", LOG_NEWS, CONST_CS | CONST_PERSISTENT); /* usenet new */
4959+#endif
4960+#ifdef LOG_UUCP
4961+ /* No LOG_UUCP on HP-UX */
4962+ REGISTER_MAIN_LONG_CONSTANT("LOG_UUCP", LOG_UUCP, CONST_CS | CONST_PERSISTENT);
4963+#endif
4964+#ifdef LOG_CRON
4965+ /* apparently some systems don't have this one */
4966+ REGISTER_MAIN_LONG_CONSTANT("LOG_CRON", LOG_CRON, CONST_CS | CONST_PERSISTENT);
4967+#endif
4968+#ifdef LOG_AUTHPRIV
4969+ /* AIX doesn't have LOG_AUTHPRIV */
4970+ REGISTER_MAIN_LONG_CONSTANT("LOG_AUTHPRIV", LOG_AUTHPRIV, CONST_CS | CONST_PERSISTENT);
4971+#endif
4972+#ifndef PHP_WIN32
4973+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL0", LOG_LOCAL0, CONST_CS | CONST_PERSISTENT);
4974+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL1", LOG_LOCAL1, CONST_CS | CONST_PERSISTENT);
4975+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL2", LOG_LOCAL2, CONST_CS | CONST_PERSISTENT);
4976+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL3", LOG_LOCAL3, CONST_CS | CONST_PERSISTENT);
4977+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL4", LOG_LOCAL4, CONST_CS | CONST_PERSISTENT);
4978+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL5", LOG_LOCAL5, CONST_CS | CONST_PERSISTENT);
4979+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL6", LOG_LOCAL6, CONST_CS | CONST_PERSISTENT);
4980+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL7", LOG_LOCAL7, CONST_CS | CONST_PERSISTENT);
4981+#endif
4982+ /* options */
4983+ REGISTER_MAIN_LONG_CONSTANT("LOG_PID", LOG_PID, CONST_CS | CONST_PERSISTENT);
4984+ REGISTER_MAIN_LONG_CONSTANT("LOG_CONS", LOG_CONS, CONST_CS | CONST_PERSISTENT);
4985+ REGISTER_MAIN_LONG_CONSTANT("LOG_ODELAY", LOG_ODELAY, CONST_CS | CONST_PERSISTENT);
4986+ REGISTER_MAIN_LONG_CONSTANT("LOG_NDELAY", LOG_NDELAY, CONST_CS | CONST_PERSISTENT);
4987+#ifdef LOG_NOWAIT
4988+ REGISTER_MAIN_LONG_CONSTANT("LOG_NOWAIT", LOG_NOWAIT, CONST_CS | CONST_PERSISTENT);
4989+#endif
4990+#ifdef LOG_PERROR
4991+ /* AIX doesn't have LOG_PERROR */
4992+ REGISTER_MAIN_LONG_CONSTANT("LOG_PERROR", LOG_PERROR, CONST_CS | CONST_PERSISTENT); /*log to stderr*/
4993+#endif
4994+#endif
4995+
4996 /* true/false constants */
4997 {
4998 zend_constant c;
4999diff -Naurp php-5.3.6RC1/Zend/zend_errors.h php-5.3.6RC1.oden/Zend/zend_errors.h
5000--- php-5.3.6RC1/Zend/zend_errors.h 2011-01-01 03:19:59.000000000 +0100
5001+++ php-5.3.6RC1.oden/Zend/zend_errors.h 2011-02-20 11:50:19.326839821 +0100
5002@@ -41,6 +41,20 @@
5003 #define E_ALL (E_ERROR | E_WARNING | E_PARSE | E_NOTICE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE | E_RECOVERABLE_ERROR | E_DEPRECATED | E_USER_DEPRECATED)
5004 #define E_CORE (E_CORE_ERROR | E_CORE_WARNING)
5005
5006+#if SUHOSIN_PATCH
5007+#define S_MEMORY (1<<0L)
5008+#define S_MISC (1<<1L)
5009+#define S_VARS (1<<2L)
5010+#define S_FILES (1<<3L)
5011+#define S_INCLUDE (1<<4L)
5012+#define S_SQL (1<<5L)
5013+#define S_EXECUTOR (1<<6L)
5014+#define S_MAIL (1<<7L)
5015+#define S_SESSION (1<<8L)
5016+#define S_INTERNAL (1<<29L)
5017+#define S_ALL (S_MEMORY | S_VARS | S_INCLUDE | S_FILES | S_MAIL | S_SESSION | S_MISC | S_SQL | S_EXECUTOR)
5018+#endif
5019+
5020 #endif /* ZEND_ERRORS_H */
5021
5022 /*
5023diff -Naurp php-5.3.6RC1/Zend/zend.h php-5.3.6RC1.oden/Zend/zend.h
5024--- php-5.3.6RC1/Zend/zend.h 2011-02-20 11:45:04.146488357 +0100
5025+++ php-5.3.6RC1.oden/Zend/zend.h 2011-02-20 11:50:19.327839962 +0100
5026@@ -627,6 +627,9 @@ extern ZEND_API int (*zend_stream_open_f
5027 extern int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
5028 extern ZEND_API char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC);
5029 extern ZEND_API char *(*zend_resolve_path)(const char *filename, int filename_len TSRMLS_DC);
5030+#if SUHOSIN_PATCH
5031+extern ZEND_API void (*zend_suhosin_log)(int loglevel, char *fmt, ...);
5032+#endif
5033
5034 ZEND_API void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
5035
5036@@ -774,6 +777,16 @@ ZEND_API void zend_restore_error_handlin
5037 #define DEBUG_BACKTRACE_PROVIDE_OBJECT (1<<0)
5038 #define DEBUG_BACKTRACE_IGNORE_ARGS (1<<1)
5039
5040+#if SUHOSIN_PATCH
5041+#include "suhosin_globals.h"
5042+#include "suhosin_patch.h"
5043+#include "php_syslog.h"
5044+
5045+ZEND_API void zend_canary(void *buf, int len);
5046+ZEND_API char suhosin_get_config(int element);
5047+
5048+#endif
5049+
5050 #endif /* ZEND_H */
5051
5052 /*
5053diff -Naurp php-5.3.6RC1/Zend/zend_hash.c php-5.3.6RC1.oden/Zend/zend_hash.c
5054--- php-5.3.6RC1/Zend/zend_hash.c 2011-01-01 03:19:59.000000000 +0100
5055+++ php-5.3.6RC1.oden/Zend/zend_hash.c 2011-02-20 11:50:19.328840102 +0100
5056@@ -20,6 +20,7 @@
5057 /* $Id$ */
5058
5059 #include "zend.h"
5060+#include "zend_compile.h"
5061
5062 #define CONNECT_TO_BUCKET_DLLIST(element, list_head) \
5063 (element)->pNext = (list_head); \
5064@@ -136,6 +137,199 @@ ZEND_API ulong zend_hash_func(const char
5065 }
5066
5067
5068+#if SUHOSIN_PATCH
5069+#ifdef ZTS
5070+static MUTEX_T zend_hash_dprot_mx_reader;
5071+static MUTEX_T zend_hash_dprot_mx_writer;
5072+static unsigned int zend_hash_dprot_reader;
5073+#endif
5074+static unsigned int zend_hash_dprot_counter;
5075+static unsigned int zend_hash_dprot_curmax;
5076+static dtor_func_t *zend_hash_dprot_table = NULL;
5077+
5078+static void zend_hash_dprot_begin_read()
5079+{
5080+#ifdef ZTS
5081+ tsrm_mutex_lock(zend_hash_dprot_mx_reader);
5082+ if ((++(zend_hash_dprot_reader)) == 1) {
5083+ tsrm_mutex_lock(zend_hash_dprot_mx_writer);
5084+ }
5085+ tsrm_mutex_unlock(zend_hash_dprot_mx_reader);
5086+#endif
5087+}
5088+
5089+static void zend_hash_dprot_end_read()
5090+{
5091+#ifdef ZTS
5092+ tsrm_mutex_lock(zend_hash_dprot_mx_reader);
5093+ if ((--(zend_hash_dprot_reader)) == 0) {
5094+ tsrm_mutex_unlock(zend_hash_dprot_mx_writer);
5095+ }
5096+ tsrm_mutex_unlock(zend_hash_dprot_mx_reader);
5097+#endif
5098+}
5099+
5100+static void zend_hash_dprot_begin_write()
5101+{
5102+#ifdef ZTS
5103+ tsrm_mutex_lock(zend_hash_dprot_mx_writer);
5104+#endif
5105+}
5106+
5107+static void zend_hash_dprot_end_write()
5108+{
5109+#ifdef ZTS
5110+ tsrm_mutex_unlock(zend_hash_dprot_mx_writer);
5111+#endif
5112+}
5113+
5114+/*ZEND_API void zend_hash_dprot_dtor()
5115+{
5116+#ifdef ZTS
5117+ tsrm_mutex_free(zend_hash_dprot_mx_reader);
5118+ tsrm_mutex_free(zend_hash_dprot_mx_writer);
5119+#endif
5120+ free(zend_hash_dprot_table);
5121+}*/
5122+
5123+static void zend_hash_add_destructor(dtor_func_t pDestructor)
5124+{
5125+ int left, right, mid;
5126+ zend_bool found = 0;
5127+ unsigned long value;
5128+
5129+ if (pDestructor == NULL || pDestructor == ZVAL_PTR_DTOR || pDestructor == ZVAL_INTERNAL_PTR_DTOR
5130+ || pDestructor == ZEND_FUNCTION_DTOR || pDestructor == ZEND_CLASS_DTOR) {
5131+ return;
5132+ }
5133+
5134+ if (zend_hash_dprot_table == NULL) {
5135+#ifdef ZTS
5136+ zend_hash_dprot_mx_reader = tsrm_mutex_alloc();
5137+ zend_hash_dprot_mx_writer = tsrm_mutex_alloc();
5138+ zend_hash_dprot_reader = 0;
5139+#endif
5140+ zend_hash_dprot_counter = 0;
5141+ zend_hash_dprot_curmax = 256;
5142+ zend_hash_dprot_table = (dtor_func_t *) malloc(256 * sizeof(dtor_func_t));
5143+ }
5144+
5145+ zend_hash_dprot_begin_write();
5146+
5147+ if (zend_hash_dprot_counter == 0) {
5148+ zend_hash_dprot_counter++;
5149+ zend_hash_dprot_table[0] = pDestructor;
5150+ } else {
5151+ value = (unsigned long) pDestructor;
5152+ left = 0;
5153+ right = zend_hash_dprot_counter-1;
5154+ mid = 0;
5155+
5156+ while (left < right) {
5157+ mid = (right - left) >> 1;
5158+ mid += left;
5159+ if ((unsigned long)zend_hash_dprot_table[mid] == value) {
5160+ found = 1;
5161+ break;
5162+ }
5163+ if (value < (unsigned long)zend_hash_dprot_table[mid]) {
5164+ right = mid-1;
5165+ } else {
5166+ left = mid+1;
5167+ }
5168+ }
5169+ if ((unsigned long)zend_hash_dprot_table[left] == value) {
5170+ found = 1;
5171+ }
5172+
5173+ if (!found) {
5174+
5175+ if (zend_hash_dprot_counter >= zend_hash_dprot_curmax) {
5176+ zend_hash_dprot_curmax += 256;
5177+ zend_hash_dprot_table = (dtor_func_t *) realloc(zend_hash_dprot_table, zend_hash_dprot_curmax * sizeof(dtor_func_t));
5178+ }
5179+
5180+ if ((unsigned long)zend_hash_dprot_table[left] < value) {
5181+ memmove(zend_hash_dprot_table+left+2, zend_hash_dprot_table+left+1, (zend_hash_dprot_counter-left-1)*sizeof(dtor_func_t));
5182+ zend_hash_dprot_table[left+1] = pDestructor;
5183+ } else {
5184+ memmove(zend_hash_dprot_table+left+1, zend_hash_dprot_table+left, (zend_hash_dprot_counter-left)*sizeof(dtor_func_t));
5185+ zend_hash_dprot_table[left] = pDestructor;
5186+ }
5187+
5188+ zend_hash_dprot_counter++;
5189+ }
5190+ }
5191+
5192+ zend_hash_dprot_end_write();
5193+}
5194+
5195+static void zend_hash_check_destructor(dtor_func_t pDestructor)
5196+{
5197+ unsigned long value;
5198+
5199+ if (pDestructor == NULL || pDestructor == ZVAL_PTR_DTOR || pDestructor == ZVAL_INTERNAL_PTR_DTOR
5200+#ifdef ZEND_ENGINE_2
5201+ || pDestructor == suhosin_zend_destroy_property_info_internal || pDestructor == suhosin_zend_destroy_property_info
5202+#endif
5203+ || pDestructor == ZEND_FUNCTION_DTOR || pDestructor == ZEND_CLASS_DTOR) {
5204+ return;
5205+ }
5206+
5207+ zend_hash_dprot_begin_read();
5208+
5209+ if (zend_hash_dprot_counter > 0) {
5210+ int left, right, mid;
5211+ zend_bool found = 0;
5212+
5213+ value = (unsigned long) pDestructor;
5214+ left = 0;
5215+ right = zend_hash_dprot_counter-1;
5216+
5217+ while (left < right) {
5218+ mid = (right - left) >> 1;
5219+ mid += left;
5220+ if ((unsigned long)zend_hash_dprot_table[mid] == value) {
5221+ found = 1;
5222+ break;
5223+ }
5224+ if (value < (unsigned long)zend_hash_dprot_table[mid]) {
5225+ right = mid-1;
5226+ } else {
5227+ left = mid+1;
5228+ }
5229+ }
5230+ if ((unsigned long)zend_hash_dprot_table[left] == value) {
5231+ found = 1;
5232+ }
5233+
5234+ if (!found) {
5235+ zend_hash_dprot_end_read();
5236+
5237+ zend_suhosin_log(S_MEMORY, "possible memory corruption detected - unknown Hashtable destructor");
5238+ if (SUHOSIN_CONFIG(SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR) == 0) {
5239+ _exit(1);
5240+ }
5241+ return;
5242+ }
5243+
5244+ } else {
5245+ zend_hash_dprot_end_read();
5246+
5247+ zend_suhosin_log(S_MEMORY, "possible memory corruption detected - unknown Hashtable destructor");
5248+ if (SUHOSIN_CONFIG(SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR) == 0) {
5249+ _exit(1);
5250+ }
5251+ return;
5252+ }
5253+
5254+ zend_hash_dprot_end_read();
5255+}
5256+
5257+#else
5258+#define zend_hash_add_destructor(pDestructor) do {} while(0)
5259+#define zend_hash_check_destructor(pDestructor) do {} while(0)
5260+#endif
5261
5262 ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
5263 {
5264@@ -156,6 +350,7 @@ ZEND_API int _zend_hash_init(HashTable *
5265
5266 ht->nTableMask = ht->nTableSize - 1;
5267 ht->pDestructor = pDestructor;
5268+ zend_hash_add_destructor(pDestructor);
5269 ht->arBuckets = NULL;
5270 ht->pListHead = NULL;
5271 ht->pListTail = NULL;
5272@@ -233,6 +428,7 @@ ZEND_API int _zend_hash_add_or_update(Ha
5273 return FAILURE;
5274 }
5275 #endif
5276+ zend_hash_check_destructor(ht->pDestructor);
5277 if (ht->pDestructor) {
5278 ht->pDestructor(p->pData);
5279 }
5280@@ -298,6 +494,7 @@ ZEND_API int _zend_hash_quick_add_or_upd
5281 return FAILURE;
5282 }
5283 #endif
5284+ zend_hash_check_destructor(ht->pDestructor);
5285 if (ht->pDestructor) {
5286 ht->pDestructor(p->pData);
5287 }
5288@@ -373,6 +570,7 @@ ZEND_API int _zend_hash_index_update_or_
5289 return FAILURE;
5290 }
5291 #endif
5292+ zend_hash_check_destructor(ht->pDestructor);
5293 if (ht->pDestructor) {
5294 ht->pDestructor(p->pData);
5295 }
5296@@ -496,6 +694,7 @@ ZEND_API int zend_hash_del_key_or_index(
5297 if (ht->pInternalPointer == p) {
5298 ht->pInternalPointer = p->pListNext;
5299 }
5300+ zend_hash_check_destructor(ht->pDestructor);
5301 if (ht->pDestructor) {
5302 ht->pDestructor(p->pData);
5303 }
5304@@ -522,6 +721,7 @@ ZEND_API void zend_hash_destroy(HashTabl
5305 SET_INCONSISTENT(HT_IS_DESTROYING);
5306
5307 p = ht->pListHead;
5308+ zend_hash_check_destructor(ht->pDestructor);
5309 while (p != NULL) {
5310 q = p;
5311 p = p->pListNext;
5312@@ -548,6 +748,7 @@ ZEND_API void zend_hash_clean(HashTable
5313 SET_INCONSISTENT(HT_CLEANING);
5314
5315 p = ht->pListHead;
5316+ zend_hash_check_destructor(ht->pDestructor);
5317 while (p != NULL) {
5318 q = p;
5319 p = p->pListNext;
5320@@ -610,6 +811,7 @@ static Bucket *zend_hash_apply_deleter(H
5321 ht->nNumOfElements--;
5322 HANDLE_UNBLOCK_INTERRUPTIONS();
5323
5324+ zend_hash_check_destructor(ht->pDestructor);
5325 if (ht->pDestructor) {
5326 ht->pDestructor(p->pData);
5327 }
5328diff -Naurp php-5.3.6RC1/Zend/zend_llist.c php-5.3.6RC1.oden/Zend/zend_llist.c
5329--- php-5.3.6RC1/Zend/zend_llist.c 2011-01-01 03:19:59.000000000 +0100
5330+++ php-5.3.6RC1.oden/Zend/zend_llist.c 2011-02-20 11:50:19.329840242 +0100
5331@@ -23,6 +23,194 @@
5332 #include "zend_llist.h"
5333 #include "zend_qsort.h"
5334
5335+#if SUHOSIN_PATCH
5336+#ifdef ZTS
5337+static MUTEX_T zend_llist_dprot_mx_reader;
5338+static MUTEX_T zend_llist_dprot_mx_writer;
5339+static unsigned int zend_llist_dprot_reader;
5340+#endif
5341+static unsigned int zend_llist_dprot_counter;
5342+static unsigned int zend_llist_dprot_curmax;
5343+static llist_dtor_func_t *zend_llist_dprot_table = NULL;
5344+
5345+static void zend_llist_dprot_begin_read()
5346+{
5347+#ifdef ZTS
5348+ tsrm_mutex_lock(zend_llist_dprot_mx_reader);
5349+ if ((++(zend_llist_dprot_reader)) == 1) {
5350+ tsrm_mutex_lock(zend_llist_dprot_mx_writer);
5351+ }
5352+ tsrm_mutex_unlock(zend_llist_dprot_mx_reader);
5353+#endif
5354+}
5355+
5356+static void zend_llist_dprot_end_read()
5357+{
5358+#ifdef ZTS
5359+ tsrm_mutex_lock(zend_llist_dprot_mx_reader);
5360+ if ((--(zend_llist_dprot_reader)) == 0) {
5361+ tsrm_mutex_unlock(zend_llist_dprot_mx_writer);
5362+ }
5363+ tsrm_mutex_unlock(zend_llist_dprot_mx_reader);
5364+#endif
5365+}
5366+
5367+static void zend_llist_dprot_begin_write()
5368+{
5369+#ifdef ZTS
5370+ tsrm_mutex_lock(zend_llist_dprot_mx_writer);
5371+#endif
5372+}
5373+
5374+static void zend_llist_dprot_end_write()
5375+{
5376+#ifdef ZTS
5377+ tsrm_mutex_unlock(zend_llist_dprot_mx_writer);
5378+#endif
5379+}
5380+
5381+/*ZEND_API void zend_llist_dprot_dtor()
5382+{
5383+#ifdef ZTS
5384+ tsrm_mutex_free(zend_llist_dprot_mx_reader);
5385+ tsrm_mutex_free(zend_llist_dprot_mx_writer);
5386+#endif
5387+ free(zend_llist_dprot_table);
5388+}*/
5389+
5390+static void zend_llist_add_destructor(llist_dtor_func_t pDestructor)
5391+{
5392+ int left, right, mid;
5393+ zend_bool found = 0;
5394+ unsigned long value;
5395+
5396+ if (pDestructor == NULL || pDestructor == ZVAL_PTR_DTOR) {
5397+ return;
5398+ }
5399+
5400+ if (zend_llist_dprot_table == NULL) {
5401+#ifdef ZTS
5402+ zend_llist_dprot_mx_reader = tsrm_mutex_alloc();
5403+ zend_llist_dprot_mx_writer = tsrm_mutex_alloc();
5404+ zend_llist_dprot_reader = 0;
5405+#endif
5406+ zend_llist_dprot_counter = 0;
5407+ zend_llist_dprot_curmax = 256;
5408+ zend_llist_dprot_table = (llist_dtor_func_t *) malloc(256 * sizeof(llist_dtor_func_t));
5409+ }
5410+
5411+ zend_llist_dprot_begin_write();
5412+
5413+ if (zend_llist_dprot_counter == 0) {
5414+ zend_llist_dprot_counter++;
5415+ zend_llist_dprot_table[0] = pDestructor;
5416+ } else {
5417+ value = (unsigned long) pDestructor;
5418+ left = 0;
5419+ right = zend_llist_dprot_counter-1;
5420+ mid = 0;
5421+
5422+ while (left < right) {
5423+ mid = (right - left) >> 1;
5424+ mid += left;
5425+ if ((unsigned long)zend_llist_dprot_table[mid] == value) {
5426+ found = 1;
5427+ break;
5428+ }
5429+ if (value < (unsigned long)zend_llist_dprot_table[mid]) {
5430+ right = mid-1;
5431+ } else {
5432+ left = mid+1;
5433+ }
5434+ }
5435+ if ((unsigned long)zend_llist_dprot_table[left] == value) {
5436+ found = 1;
5437+ }
5438+
5439+ if (!found) {
5440+
5441+ if (zend_llist_dprot_counter >= zend_llist_dprot_curmax) {
5442+ zend_llist_dprot_curmax += 256;
5443+ zend_llist_dprot_table = (llist_dtor_func_t *) realloc(zend_llist_dprot_table, zend_llist_dprot_curmax * sizeof(llist_dtor_func_t));
5444+ }
5445+
5446+ if ((unsigned long)zend_llist_dprot_table[left] < value) {
5447+ memmove(zend_llist_dprot_table+left+2, zend_llist_dprot_table+left+1, (zend_llist_dprot_counter-left-1)*sizeof(llist_dtor_func_t));
5448+ zend_llist_dprot_table[left+1] = pDestructor;
5449+ } else {
5450+ memmove(zend_llist_dprot_table+left+1, zend_llist_dprot_table+left, (zend_llist_dprot_counter-left)*sizeof(llist_dtor_func_t));
5451+ zend_llist_dprot_table[left] = pDestructor;
5452+ }
5453+
5454+ zend_llist_dprot_counter++;
5455+ }
5456+ }
5457+
5458+ zend_llist_dprot_end_write();
5459+}
5460+
5461+static void zend_llist_check_destructor(llist_dtor_func_t pDestructor)
5462+{
5463+ unsigned long value;
5464+
5465+ if (pDestructor == NULL || pDestructor == ZVAL_PTR_DTOR) {
5466+ return;
5467+ }
5468+
5469+ zend_llist_dprot_begin_read();
5470+
5471+ if (zend_llist_dprot_counter > 0) {
5472+ int left, right, mid;
5473+ zend_bool found = 0;
5474+
5475+ value = (unsigned long) pDestructor;
5476+ left = 0;
5477+ right = zend_llist_dprot_counter-1;
5478+
5479+ while (left < right) {
5480+ mid = (right - left) >> 1;
5481+ mid += left;
5482+ if ((unsigned long)zend_llist_dprot_table[mid] == value) {
5483+ found = 1;
5484+ break;
5485+ }
5486+ if (value < (unsigned long)zend_llist_dprot_table[mid]) {
5487+ right = mid-1;
5488+ } else {
5489+ left = mid+1;
5490+ }
5491+ }
5492+ if ((unsigned long)zend_llist_dprot_table[left] == value) {
5493+ found = 1;
5494+ }
5495+
5496+ if (!found) {
5497+ zend_llist_dprot_end_read();
5498+
5499+ zend_suhosin_log(S_MEMORY, "possible memory corruption detected - unknown llist destructor");
5500+ if (SUHOSIN_CONFIG(SUHOSIN_LL_IGNORE_INVALID_DESTRUCTOR) == 0) {
5501+ _exit(1);
5502+ }
5503+ return;
5504+ }
5505+
5506+ } else {
5507+ zend_llist_dprot_end_read();
5508+
5509+ zend_suhosin_log(S_MEMORY, "possible memory corruption detected - unknown llist destructor");
5510+ if (SUHOSIN_CONFIG(SUHOSIN_LL_IGNORE_INVALID_DESTRUCTOR) == 0) {
5511+ _exit(1);
5512+ }
5513+ return;
5514+ }
5515+
5516+ zend_llist_dprot_end_read();
5517+}
5518+#else
5519+#define zend_llist_add_destructor(pDestructor) do {} while(0)
5520+#define zend_llist_check_destructor(pDestructor) do {} while(0)
5521+#endif
5522+
5523 ZEND_API void zend_llist_init(zend_llist *l, size_t size, llist_dtor_func_t dtor, unsigned char persistent)
5524 {
5525 l->head = NULL;
5526@@ -30,6 +218,7 @@ ZEND_API void zend_llist_init(zend_llist
5527 l->count = 0;
5528 l->size = size;
5529 l->dtor = dtor;
5530+ zend_llist_add_destructor(dtor);
5531 l->persistent = persistent;
5532 }
5533
5534@@ -81,6 +270,7 @@ ZEND_API void zend_llist_prepend_element
5535 } else {\
5536 (l)->tail = (current)->prev;\
5537 }\
5538+ zend_llist_check_destructor((l)->dtor); \
5539 if ((l)->dtor) {\
5540 (l)->dtor((current)->data);\
5541 }\
5542@@ -108,6 +298,7 @@ ZEND_API void zend_llist_destroy(zend_ll
5543 {
5544 zend_llist_element *current=l->head, *next;
5545
5546+ zend_llist_check_destructor(l->dtor);
5547 while (current) {
5548 next = current->next;
5549 if (l->dtor) {
5550@@ -133,6 +324,7 @@ ZEND_API void *zend_llist_remove_tail(ze
5551 zend_llist_element *old_tail;
5552 void *data;
5553
5554+ zend_llist_check_destructor((l)->dtor);
5555 if ((old_tail = l->tail)) {
5556 if (old_tail->prev) {
5557 old_tail->prev->next = NULL;
5558diff -Naurp php-5.3.6RC1/Zend/zend_operators.c php-5.3.6RC1.oden/Zend/zend_operators.c
5559--- php-5.3.6RC1/Zend/zend_operators.c 2011-01-01 03:19:59.000000000 +0100
5560+++ php-5.3.6RC1.oden/Zend/zend_operators.c 2011-02-20 11:50:19.330840383 +0100
5561@@ -153,9 +153,14 @@ ZEND_API void convert_scalar_to_number(z
5562 case IS_STRING:
5563 {
5564 char *strval;
5565+ int strl;
5566
5567 strval = Z_STRVAL_P(op);
5568- if ((Z_TYPE_P(op)=is_numeric_string(strval, Z_STRLEN_P(op), &Z_LVAL_P(op), &Z_DVAL_P(op), 1)) == 0) {
5569+ strl = Z_STRLEN_P(op);
5570+#if SUHOSIN_PATCH
5571+ Z_STRLEN_P(op) = 0;
5572+#endif
5573+ if ((Z_TYPE_P(op)=is_numeric_string(strval, strl, &Z_LVAL_P(op), &Z_DVAL_P(op), 1)) == 0) {
5574 ZVAL_LONG(op, 0);
5575 }
5576 STR_FREE(strval);
5577@@ -187,7 +192,8 @@ ZEND_API void convert_scalar_to_number(z
5578 } else { \
5579 switch (Z_TYPE_P(op)) { \
5580 case IS_STRING: \
5581- { \
5582+ { \
5583+ Z_STRLEN(holder) = 0; \
5584 if ((Z_TYPE(holder)=is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &Z_LVAL(holder), &Z_DVAL(holder), 1)) == 0) { \
5585 ZVAL_LONG(&(holder), 0); \
5586 } \
5587@@ -229,6 +235,7 @@ ZEND_API void convert_scalar_to_number(z
5588 Z_LVAL(holder) = zend_dval_to_lval(Z_DVAL_P(op)); \
5589 break; \
5590 case IS_STRING: \
5591+ Z_STRLEN(holder) = 0; \
5592 Z_LVAL(holder) = strtol(Z_STRVAL_P(op), NULL, 10); \
5593 break; \
5594 case IS_ARRAY: \
5595@@ -271,6 +278,7 @@ ZEND_API void convert_scalar_to_number(z
5596 Z_LVAL(holder) = (Z_DVAL_P(op) ? 1 : 0); \
5597 break; \
5598 case IS_STRING: \
5599+ Z_STRLEN(holder) = 0; \
5600 if (Z_STRLEN_P(op) == 0 \
5601 || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) { \
5602 Z_LVAL(holder) = 0; \
5603@@ -356,6 +364,9 @@ ZEND_API void convert_to_long_base(zval
5604 {
5605 char *strval = Z_STRVAL_P(op);
5606
5607+#if SUHOSIN_PATCH
5608+ Z_STRLEN_P(op) = 0;
5609+#endif
5610 Z_LVAL_P(op) = strtol(strval, NULL, base);
5611 STR_FREE(strval);
5612 }
5613@@ -416,6 +427,9 @@ ZEND_API void convert_to_double(zval *op
5614 {
5615 char *strval = Z_STRVAL_P(op);
5616
5617+#if SUHOSIN_PATCH
5618+ Z_STRLEN_P(op) = 0;
5619+#endif
5620 Z_DVAL_P(op) = zend_strtod(strval, NULL);
5621 STR_FREE(strval);
5622 }
5623@@ -502,8 +516,14 @@ ZEND_API void convert_to_boolean(zval *o
5624
5625 if (Z_STRLEN_P(op) == 0
5626 || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) {
5627+#if SUHOSIN_PATCH
5628+ Z_STRLEN_P(op) = 0;
5629+#endif
5630 Z_LVAL_P(op) = 0;
5631 } else {
5632+#if SUHOSIN_PATCH
5633+ Z_STRLEN_P(op) = 0;
5634+#endif
5635 Z_LVAL_P(op) = 1;
5636 }
5637 STR_FREE(strval);
5638@@ -617,6 +637,9 @@ static void convert_scalar_to_array(zval
5639 *entry = *op;
5640 INIT_PZVAL(entry);
5641
5642+#if SUHOSIN_PATCH
5643+ Z_STRLEN_P(op) = 0;
5644+#endif
5645 switch (type) {
5646 case IS_ARRAY:
5647 ALLOC_HASHTABLE(Z_ARRVAL_P(op));
5648diff -Naurp php-5.3.6RC1/Zend/zend_variables.c php-5.3.6RC1.oden/Zend/zend_variables.c
5649--- php-5.3.6RC1/Zend/zend_variables.c 2011-01-01 03:19:59.000000000 +0100
5650+++ php-5.3.6RC1.oden/Zend/zend_variables.c 2011-02-20 11:50:19.331840524 +0100
5651@@ -34,6 +34,9 @@ ZEND_API void _zval_dtor_func(zval *zval
5652 case IS_CONSTANT:
5653 CHECK_ZVAL_STRING_REL(zvalue);
5654 STR_FREE_REL(zvalue->value.str.val);
5655+#if SUHOSIN_PATCH
5656+ zvalue->value.str.len = 0;
5657+#endif
5658 break;
5659 case IS_ARRAY:
5660 case IS_CONSTANT_ARRAY: {
5661@@ -78,6 +81,9 @@ ZEND_API void _zval_internal_dtor(zval *
5662 case IS_CONSTANT:
5663 CHECK_ZVAL_STRING_REL(zvalue);
5664 free(zvalue->value.str.val);
5665+#if SUHOSIN_PATCH
5666+ zvalue->value.str.len = 0;
5667+#endif
5668 break;
5669 case IS_ARRAY:
5670 case IS_CONSTANT_ARRAY:
This page took 0.952619 seconds and 4 git commands to generate.