1 /* 2 +----------------------------------------------------------------------+ 3 | Zend Engine | 4 +----------------------------------------------------------------------+ 5 | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) | 6 +----------------------------------------------------------------------+ 7 | This source file is subject to version 2.00 of the Zend license, | 8 | that is bundled with this package in the file LICENSE, and is | 9 | available through the world-wide-web at the following url: | 10 | http://www.zend.com/license/2_00.txt. | 11 | If you did not receive a copy of the Zend license and are unable to | 12 | obtain it through the world-wide-web, please send a note to | 13 | license@zend.com so we can mail you a copy immediately. | 14 +----------------------------------------------------------------------+ 15 | Authors: Arnaud Le Blanc <arnaud.lb@gmail.com> | 16 +----------------------------------------------------------------------+ 17 */ 18 19 #ifndef ZEND_CALL_STACK_H 20 #define ZEND_CALL_STACK_H 21 22 #include "zend.h" 23 #include "zend_portability.h" 24 #ifdef __APPLE__ 25 # include <pthread.h> 26 #endif 27 28 #ifdef ZEND_CHECK_STACK_LIMIT 29 30 typedef struct _zend_call_stack { 31 void *base; /* high address of the stack */ 32 size_t max_size; 33 } zend_call_stack; 34 35 ZEND_API void zend_call_stack_init(void); 36 37 ZEND_API bool zend_call_stack_get(zend_call_stack *stack); 38 39 /** Returns an approximation of the current stack position */ zend_call_stack_position(void)40static zend_always_inline void *zend_call_stack_position(void) { 41 #ifdef ZEND_WIN32 42 return _AddressOfReturnAddress(); 43 #elif defined(PHP_HAVE_BUILTIN_FRAME_ADDRESS) 44 return __builtin_frame_address(0); 45 #else 46 void *a; 47 void *pos = (void*)&a; 48 return pos; 49 #endif 50 } 51 zend_call_stack_overflowed(void * stack_limit)52static zend_always_inline bool zend_call_stack_overflowed(void *stack_limit) { 53 return (uintptr_t) zend_call_stack_position() <= (uintptr_t) stack_limit; 54 } 55 zend_call_stack_limit(void * base,size_t size,size_t reserved_size)56static inline void* zend_call_stack_limit(void *base, size_t size, size_t reserved_size) 57 { 58 if (UNEXPECTED(size > (uintptr_t)base)) { 59 return (void*)0; 60 } 61 62 base = (int8_t*)base - size; 63 64 if (UNEXPECTED(UINTPTR_MAX - (uintptr_t)base < reserved_size)) { 65 return (void*)UINTPTR_MAX; 66 } 67 68 return (int8_t*)base + reserved_size; 69 } 70 zend_call_stack_default_size(void)71static inline size_t zend_call_stack_default_size(void) 72 { 73 #ifdef __linux__ 74 return 8 * 1024 * 1024; 75 #endif 76 #if defined(__FreeBSD__) || defined(__NetBSD__) 77 return 4 * 1024 * 1024; 78 #endif 79 #if defined(__DragonFly__) 80 return 2 * 1024 * 1024; 81 #endif 82 #ifdef __OpenBSD__ 83 return 512 * 1024; 84 #endif 85 #ifdef __APPLE__ 86 // https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html 87 if (pthread_main_np()) { 88 return 8 * 1024 * 1024; 89 } 90 return 512 * 1024; 91 #endif 92 #ifdef __HAIKU__ 93 return 64 * 4096; 94 #endif 95 #ifdef __sun 96 return 8 * 4096; 97 #endif 98 99 return 2 * 1024 * 1024; 100 } 101 102 #endif /* ZEND_CHECK_STACK_LIMIT */ 103 #endif /* ZEND_CALL_STACK_H */ 104