From a6412a5e71f223498c83ac3e4fe8f9d35af3a68d Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 3 Sep 2009 14:33:11 +0000 Subject: [PATCH] Fixed bug #46074 (Bus error during running PHP CLI under IRIX 6.5.30) --- Zend/zend_alloc.c | 13 --------- Zend/zend_alloc.h | 14 +++++++++ Zend/zend_compile.c | 2 +- Zend/zend_execute.h | 61 ++++++++++++++++++++++++++++++++-------- Zend/zend_vm_def.h | 4 +-- Zend/zend_vm_execute.h | 14 ++++----- Zend/zend_vm_execute.skl | 10 +++---- 7 files changed, 78 insertions(+), 40 deletions(-) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index f7b6ffd8fb..057fdf1a41 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -532,20 +532,7 @@ static unsigned int _zend_mm_cookie = 0; /* optimized access */ #define ZEND_MM_FREE_BLOCK_SIZE(b) (b)->info._size -#ifndef ZEND_MM_ALIGNMENT -# define ZEND_MM_ALIGNMENT 8 -# define ZEND_MM_ALIGNMENT_LOG2 3 -#elif ZEND_MM_ALIGNMENT < 4 -# undef ZEND_MM_ALIGNMENT -# undef ZEND_MM_ALIGNMENT_LOG2 -# define ZEND_MM_ALIGNMENT 4 -# define ZEND_MM_ALIGNMENT_LOG2 2 -#endif - -#define ZEND_MM_ALIGNMENT_MASK ~(ZEND_MM_ALIGNMENT-1) - /* Aligned header size */ -#define ZEND_MM_ALIGNED_SIZE(size) ((size + ZEND_MM_ALIGNMENT - 1) & ZEND_MM_ALIGNMENT_MASK) #define ZEND_MM_ALIGNED_HEADER_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_block)) #define ZEND_MM_ALIGNED_FREE_HEADER_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_small_free_block)) #define ZEND_MM_MIN_ALLOC_BLOCK_SIZE ZEND_MM_ALIGNED_SIZE(ZEND_MM_ALIGNED_HEADER_SIZE + END_MAGIC_SIZE) diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h index dc258ad934..4689ca1c77 100644 --- a/Zend/zend_alloc.h +++ b/Zend/zend_alloc.h @@ -28,6 +28,20 @@ #include #include "zend.h" +#ifndef ZEND_MM_ALIGNMENT +# define ZEND_MM_ALIGNMENT 8 +# define ZEND_MM_ALIGNMENT_LOG2 3 +#elif ZEND_MM_ALIGNMENT < 4 +# undef ZEND_MM_ALIGNMENT +# undef ZEND_MM_ALIGNMENT_LOG2 +# define ZEND_MM_ALIGNMENT 4 +# define ZEND_MM_ALIGNMENT_LOG2 2 +#endif + +#define ZEND_MM_ALIGNMENT_MASK ~(ZEND_MM_ALIGNMENT-1) + +#define ZEND_MM_ALIGNED_SIZE(size) (((size) + ZEND_MM_ALIGNMENT - 1) & ZEND_MM_ALIGNMENT_MASK) + typedef struct _zend_leak_info { void *addr; size_t size; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index a081979b25..b18b9e8a8c 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -279,7 +279,7 @@ ZEND_API char *zend_get_compiled_script_encoding(TSRMLS_D) /* {{{ */ static zend_uint get_temporary_variable(zend_op_array *op_array) /* {{{ */ { - return (op_array->T)++ * sizeof(temp_variable); + return (op_array->T)++ * ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)); } /* }}} */ diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 09f0590c79..5465890c09 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -162,9 +162,11 @@ struct _zend_vm_stack { void **top; void **end; zend_vm_stack prev; - void *elements[1]; }; +#define ZEND_VM_STACK_ELEMETS(stack) \ + ((void**)(((char*)(stack)) + ZEND_MM_ALIGNED_SIZE(sizeof(struct _zend_vm_stack)))) + #define ZEND_VM_STACK_GROW_IF_NEEDED(count) \ do { \ if (UNEXPECTED((count) > \ @@ -174,10 +176,10 @@ struct _zend_vm_stack { } while (0) static inline zend_vm_stack zend_vm_stack_new_page(int count) { - zend_vm_stack page = (zend_vm_stack)emalloc(sizeof(*page)+sizeof(page->elements[0])*(count-1)); + zend_vm_stack page = (zend_vm_stack)emalloc(ZEND_MM_ALIGNED_SIZE(sizeof(*page)) + sizeof(void*) * count); - page->top = page->elements; - page->end = page->elements + count; + page->top = ZEND_VM_STACK_ELEMETS(page); + page->end = page->top + count; page->prev = NULL; return page; } @@ -225,7 +227,7 @@ static inline void *zend_vm_stack_pop(TSRMLS_D) { void *el = *(--EG(argument_stack)->top); - if (UNEXPECTED(EG(argument_stack)->top == EG(argument_stack)->elements)) { + if (UNEXPECTED(EG(argument_stack)->top == ZEND_VM_STACK_ELEMETS(EG(argument_stack)))) { zend_vm_stack p = EG(argument_stack); EG(argument_stack) = p->prev; efree(p); @@ -239,15 +241,32 @@ static inline void *zend_vm_stack_alloc(size_t size TSRMLS_DC) size = (size + (sizeof(void*) - 1)) / sizeof(void*); - ZEND_VM_STACK_GROW_IF_NEEDED((int)size); + /* the following comparison must be optimized out at compile time */ + if (ZEND_MM_ALIGNMENT > sizeof(void*)) { + int extra = (ZEND_MM_ALIGNMENT - ((zend_uintptr_t)EG(argument_stack)->top & (ZEND_MM_ALIGNMENT - 1))) / sizeof(void*); + + if (UNEXPECTED(size + extra + ZEND_MM_ALIGNED_SIZE(sizeof(void*)) / sizeof(void*) > + EG(argument_stack)->end - EG(argument_stack)->top)) { + zend_vm_stack_extend(size TSRMLS_CC); + } else { + void **old_top = EG(argument_stack)->top; + + EG(argument_stack)->top += extra; + /* store old top on the stack */ + *EG(argument_stack)->top = (void*)old_top; + EG(argument_stack)->top += ZEND_MM_ALIGNED_SIZE(sizeof(void*)) / sizeof(void*); + } + } else { + ZEND_VM_STACK_GROW_IF_NEEDED((int)size); + } ret = (void*)EG(argument_stack)->top; EG(argument_stack)->top += size; return ret; } -static inline void zend_vm_stack_free(void *ptr TSRMLS_DC) +static inline void zend_vm_stack_free_int(void *ptr TSRMLS_DC) { - if (UNEXPECTED(EG(argument_stack)->elements == (void**)ptr)) { + if (UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (void**)ptr)) { zend_vm_stack p = EG(argument_stack); EG(argument_stack) = p->prev; @@ -257,10 +276,28 @@ static inline void zend_vm_stack_free(void *ptr TSRMLS_DC) } } +static inline void zend_vm_stack_free(void *ptr TSRMLS_DC) +{ + if (UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (void**)ptr)) { + zend_vm_stack p = EG(argument_stack); + + EG(argument_stack) = p->prev; + efree(p); + } else { + /* the following comparison must be optimized out at compile time */ + if (ZEND_MM_ALIGNMENT > sizeof(void*)) { + ptr = (void*)(((char*)ptr) - ZEND_MM_ALIGNED_SIZE(sizeof(void*))); + EG(argument_stack)->top = *(void***)ptr; + } else { + EG(argument_stack)->top = (void**)ptr; + } + } +} + static inline void** zend_vm_stack_push_args(int count TSRMLS_DC) { - if (UNEXPECTED(EG(argument_stack)->top - EG(argument_stack)->elements < count) || + if (UNEXPECTED(EG(argument_stack)->top - ZEND_VM_STACK_ELEMETS(EG(argument_stack)) < count) || UNEXPECTED(EG(argument_stack)->top == EG(argument_stack)->end)) { zend_vm_stack p = EG(argument_stack); @@ -271,14 +308,14 @@ static inline void** zend_vm_stack_push_args(int count TSRMLS_DC) while (count-- > 0) { void *data = *(--p->top); - if (UNEXPECTED(p->top == p->elements)) { + if (UNEXPECTED(p->top == ZEND_VM_STACK_ELEMETS(p))) { zend_vm_stack r = p; EG(argument_stack)->prev = p->prev; p = p->prev; efree(r); } - *(EG(argument_stack)->elements + count) = data; + *(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + count) = data; } return EG(argument_stack)->top++; } @@ -296,7 +333,7 @@ static inline void zend_vm_stack_clear_multiple(TSRMLS_D) *p = NULL; zval_ptr_dtor(&q); } - zend_vm_stack_free(p TSRMLS_CC); + zend_vm_stack_free_int(p TSRMLS_CC); } static inline zval** zend_vm_stack_get_arg(int requested_arg TSRMLS_DC) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index da5ae97935..72167214ed 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4469,8 +4469,8 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) int catched = 0; zval restored_error_reporting; - void **stack_frame = (void**)EX(Ts) + - (sizeof(temp_variable) * EX(op_array)->T) / sizeof(void*); + void **stack_frame = (void**)(((char*)EX(Ts)) + + (ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * EX(op_array)->T)); while (zend_vm_stack_top(TSRMLS_C) != stack_frame) { zval *stack_zval_p = zend_vm_stack_pop(TSRMLS_C); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index ee032d1ec6..4b86568c4f 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -52,13 +52,13 @@ ZEND_API void execute(zend_op_array *op_array TSRMLS_DC) zend_vm_enter: /* Initialize execute_data */ execute_data = (zend_execute_data *)zend_vm_stack_alloc( - sizeof(zend_execute_data) + - sizeof(zval**) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2) + - sizeof(temp_variable) * op_array->T TSRMLS_CC); + ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data)) + + ZEND_MM_ALIGNED_SIZE(sizeof(zval**) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2)) + + ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T TSRMLS_CC); - EX(CVs) = (zval***)((char*)execute_data + sizeof(zend_execute_data)); + EX(CVs) = (zval***)((char*)execute_data + ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data))); memset(EX(CVs), 0, sizeof(zval**) * op_array->last_var); - EX(Ts) = (temp_variable *)(EX(CVs) + op_array->last_var * (EG(active_symbol_table) ? 1 : 2)); + EX(Ts) = (temp_variable *)(((char*)EX(CVs)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval**) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2))); EX(fbc) = NULL; EX(called_scope) = NULL; EX(object) = NULL; @@ -606,8 +606,8 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER int catched = 0; zval restored_error_reporting; - void **stack_frame = (void**)EX(Ts) + - (sizeof(temp_variable) * EX(op_array)->T) / sizeof(void*); + void **stack_frame = (void**)(((char*)EX(Ts)) + + (ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * EX(op_array)->T)); while (zend_vm_stack_top(TSRMLS_C) != stack_frame) { zval *stack_zval_p = zend_vm_stack_pop(TSRMLS_C); diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl index fbb5b074e2..2df20720d0 100644 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@ -18,13 +18,13 @@ ZEND_API void {%EXECUTOR_NAME%}(zend_op_array *op_array TSRMLS_DC) zend_vm_enter: /* Initialize execute_data */ execute_data = (zend_execute_data *)zend_vm_stack_alloc( - sizeof(zend_execute_data) + - sizeof(zval**) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2) + - sizeof(temp_variable) * op_array->T TSRMLS_CC); + ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data)) + + ZEND_MM_ALIGNED_SIZE(sizeof(zval**) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2)) + + ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T TSRMLS_CC); - EX(CVs) = (zval***)((char*)execute_data + sizeof(zend_execute_data)); + EX(CVs) = (zval***)((char*)execute_data + ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data))); memset(EX(CVs), 0, sizeof(zval**) * op_array->last_var); - EX(Ts) = (temp_variable *)(EX(CVs) + op_array->last_var * (EG(active_symbol_table) ? 1 : 2)); + EX(Ts) = (temp_variable *)(((char*)EX(CVs)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval**) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2))); EX(fbc) = NULL; EX(called_scope) = NULL; EX(object) = NULL; -- 2.50.1