Subject: Re: bug#16999: calc crashes when computation limit is increased

From: Dmitry Antipov <[email-masked]>
Date: Thu, 13 Mar 2014 18:30:40 +0400

On 03/13/2014 06:06 PM, Florian Beck wrote:

> Sorry, this doesn't work for me. (I applied the patch and bootstrapped, but I still get the crash.)

Oops, the guard should be installed in Ffuncall too...

Dmitry

=== modified file 'src/eval.c'
--- src/eval.c	2014-02-10 09:48:17 +0000
+++ src/eval.c	2014-03-13 14:27:14 +0000
@@ -33,6 +33,10 @@
 #include "xterm.h"
 #endif
 
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
 /* Chain of condition and catch handlers currently in effect.  */
 
 struct handler *handlerlist;
@@ -240,6 +244,13 @@
 
 static struct handler handlerlist_sentinel;
 
+/* C stack overflow protection.  */
+
+#if defined (HAVE_GETRLIMIT) && defined (RLIMIT_STACK)
+/* Current C stack slimit.  */
+static struct rlimit stack_limit;
+#endif
+
 void
 init_eval (void)
 {
@@ -262,6 +273,10 @@
 #endif
   /* This is less than the initial value of num_nonmacro_input_events.  */
   when_entered_debugger = -1;
+#if defined (HAVE_GETRLIMIT) && defined (RLIMIT_STACK)
+  if (getrlimit (RLIMIT_STACK, &stack_limit))
+    emacs_abort ();
+#endif  
 }
 
 /* Unwind-protect function used by call_debugger.  */
@@ -2060,6 +2075,19 @@
   Lisp_Object funcar;
   struct gcpro gcpro1, gcpro2, gcpro3;
 
+#if defined (HAVE_GETRLIMIT) && defined (RLIMIT_STACK)
+  ptrdiff_t stack_size;
+  char stack_top_variable;
+  const ptrdiff_t stack_extra = 128 * 1024;
+
+  if (&stack_top_variable < stack_bottom)
+    stack_size = stack_bottom - &stack_top_variable;
+  else
+    stack_size = &stack_top_variable - stack_bottom;
+  if (stack_size + stack_extra > stack_limit.rlim_cur)
+    error ("Attempt to overflow C stack");
+#endif /* HAVE_GETRLIMIT && RLIMIT_STACK */
+  
   if (SYMBOLP (form))
     {
       /* Look up its binding in the lexical environment.
@@ -2749,6 +2777,19 @@
   register Lisp_Object *internal_args;
   ptrdiff_t i;
 
+#if defined (HAVE_GETRLIMIT) && defined (RLIMIT_STACK)
+  ptrdiff_t stack_size;
+  char stack_top_variable;
+  const ptrdiff_t stack_extra = 128 * 1024;
+
+  if (&stack_top_variable < stack_bottom)
+    stack_size = stack_bottom - &stack_top_variable;
+  else
+    stack_size = &stack_top_variable - stack_bottom;
+  if (stack_size + stack_extra > stack_limit.rlim_cur)
+    error ("Attempt to overflow C stack");
+#endif /* HAVE_GETRLIMIT && RLIMIT_STACK */
+
   QUIT;
 
   if (++lisp_eval_depth > max_lisp_eval_depth)