The attached patch fixes the computation of stack depth beyond C_stack_limit. The old way of calculating the depth could overflow if the stack is located very high in memory. This was causing incorrect stack-overflow errors on some 64-bit systems (sparc64 and x86-64). The new method checks whether the stack-pointer is beyond the limit computed at startup, including a 64k "slack" area to allow (modestly) deep recursions in direct-call-optimized (simple, non-allocating, not externally visible) procedures, if the nursery is already mostly exhausted.
This patch fixes ticket #895. I recommend to include this fix in the upcoming 4.8.0 release (this will require a new release candidate). cheers, felix
>From 3882f6fbb265bbbb8224894163e0a3b6f8f54133 Mon Sep 17 00:00:00 2001 From: felix <[email protected]> Date: Mon, 13 Aug 2012 12:23:27 +0200 Subject: [PATCH] Fix computation of stack depth beyond C_stack_limit. The old way of calculating the depth could overflow if the stack is located very high in memory. This was causing incorrect stack-overflow errors on some 64-bit systems (sparc64 and x86-64). The new method checks whether the stack-pointer is beyond the limit computed at startup, including a 64k "slack" area to allow (modestly) deep recursions in direct-call-optimized (simple, non-allocating, not externally visible) procedures. --- c-backend.scm | 2 +- chicken.h | 25 +++++++++++++++++++++---- runtime.c | 3 +-- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/c-backend.scm b/c-backend.scm index a7b6afe..23bf331 100644 --- a/c-backend.scm +++ b/c-backend.scm @@ -855,7 +855,7 @@ [else (unless direct (gen #t "C_word *a;")) (when (and direct (not unsafe) (not disable-stack-overflow-checking)) - (gen #t "C_stack_check;") ) + (gen #t "C_stack_overflow_check;") ) (when looping (gen #t "loop:")) ] ) (when (and external (not unsafe) (not no-argc-checks) (not customizable)) ;; (not customizable) implies empty-closure diff --git a/chicken.h b/chicken.h index 6e9e009..f5ce0d9 100644 --- a/chicken.h +++ b/chicken.h @@ -1007,17 +1007,34 @@ extern double trunc(double); # define C_stress 1 #endif +#define C_stack_overflow_check C_stack_check1(C_stack_overflow()) + +/*XXX OBSOLETE */ +#define C_stack_check C_stack_overflow_check + #if C_STACK_GROWS_DOWNWARD # define C_demand(n) (C_stress && ((C_word)(C_stack_pointer - C_stack_limit) > (n))) # define C_stack_probe(p) (C_stress && ((C_word *)(p) >= C_stack_limit)) -# define C_stack_test (!C_disable_overflow_check && (C_byte*)(C_stack_pointer) + C_STACK_RESERVE < (C_byte *)C_stack_limit) + +# define C_stack_check1(err) if(!C_disable_overflow_check) { \ + do { C_byte *_sp = (C_byte*)(C_stack_pointer); \ + if(_sp < (C_byte *)C_stack_limit && \ + ((C_byte *)C_stack_limit - _sp) > C_STACK_RESERVE) \ + err; } \ + while(0);} + #else # define C_demand(n) (C_stress && ((C_word)(C_stack_limit - C_stack_pointer) > (n))) # define C_stack_probe(p) (C_stress && ((C_word *)(p) < C_stack_limit)) -# define C_stack_test (!C_disable_overflow_check && (C_byte*)(C_stack_pointer) - C_STACK_RESERVE > (C_byte *)C_stack_limit) -#endif -#define C_stack_check if(C_stack_test) C_stack_overflow() +# define C_stack_check1(err) if(!C_disable_overflow_check) { \ + do { C_byte *_sp = (C_byte*)(C_stack_pointer); \ + if(_sp > (C_byte *)C_stack_limit && \ + (_sp - (C_byte *)C_stack_limit) > C_STACK_RESERVE) \ + err; } \ + while(0);} + +#endif #define C_zero_length_p(x) C_mk_bool(C_header_size(x) == 0) #define C_boundp(x) C_mk_bool(((C_SCHEME_BLOCK *)(x))->data[ 0 ] != C_SCHEME_UNBOUND) diff --git a/runtime.c b/runtime.c index dd1c837..caf0e11 100644 --- a/runtime.c +++ b/runtime.c @@ -3843,8 +3843,7 @@ C_regparm C_word C_fcall C_equalp(C_word x, C_word y) C_header header; C_word bits, n, i; - if(C_stack_test) - barf(C_CIRCULAR_DATA_ERROR, "equal?"); + C_stack_check1(barf(C_CIRCULAR_DATA_ERROR, "equal?")); loop: if(x == y) return 1; -- 1.7.0.4
_______________________________________________ Chicken-hackers mailing list [email protected] https://lists.nongnu.org/mailman/listinfo/chicken-hackers
