Magellan Linux

Contents of /trunk/php5/patches/php5-5.3.0-suhosin-0.9.8.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 933 - (show annotations) (download)
Tue Nov 17 11:39:50 2009 UTC (14 years, 6 months ago) by niro
File size: 181916 byte(s)
suhosin for 5.3.0

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