chicken-hackers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Chicken-hackers] [PATCH] fix stack-overflow check


From: Felix
Subject: [Chicken-hackers] [PATCH] fix stack-overflow check
Date: Mon, 13 Aug 2012 12:31:47 +0200 (CEST)

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 <address@hidden>
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


reply via email to

[Prev in Thread] Current Thread [Next in Thread]