aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2013-07-12 17:24:38 -0700
committerPaul Eggert2013-07-12 17:24:38 -0700
commit5e301d7651c0691bb2bc7f3fbe711fdbe26ac471 (patch)
treeee4962eb5ebb86a5de385d554b854864b9a53f21 /src
parentc04bbd85c9b5a7db4b7fb62e741563aa848dce67 (diff)
downloademacs-5e301d7651c0691bb2bc7f3fbe711fdbe26ac471.tar.gz
emacs-5e301d7651c0691bb2bc7f3fbe711fdbe26ac471.zip
Don't lose top specpdl entry when memory is exhausted.
* eval.c (grow_specpdl): Increment specpdl top by 1 and check for specpdl overflow here, to simplify callers; all callers changed. Always reserve an unused entry at the stack top; this avoids losing the top entry's information when memory is exhausted.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog8
-rw-r--r--src/eval.c56
2 files changed, 41 insertions, 23 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 6e3a82c7c13..60e7e376729 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,11 @@
12013-07-13 Paul Eggert <eggert@cs.ucla.edu>
2
3 Don't lose top specpdl entry when memory is exhausted.
4 * eval.c (grow_specpdl): Increment specpdl top by 1 and check for
5 specpdl overflow here, to simplify callers; all callers changed.
6 Always reserve an unused entry at the stack top; this avoids
7 losing the top entry's information when memory is exhausted.
8
12013-07-12 Paul Eggert <eggert@cs.ucla.edu> 92013-07-12 Paul Eggert <eggert@cs.ucla.edu>
2 10
3 Clean up errno reporting and fix some errno-reporting bugs. 11 Clean up errno reporting and fix some errno-reporting bugs.
diff --git a/src/eval.c b/src/eval.c
index 31a774b9d27..0e231bdb285 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1996,38 +1996,52 @@ If LEXICAL is t, evaluate using lexical scoping. */)
1996 return unbind_to (count, eval_sub (form)); 1996 return unbind_to (count, eval_sub (form));
1997} 1997}
1998 1998
1999/* Grow the specpdl stack by one entry.
2000 The caller should have already initialized the entry.
2001 Signal an error on stack overflow.
2002
2003 Make sure that there is always one unused entry past the top of the
2004 stack, so that the just-initialized entry is safely unwound if
2005 memory exhausted and an error is signaled here. Also, allocate a
2006 never-used entry just before the bottom of the stack; sometimes its
2007 address is taken. */
2008
1999static void 2009static void
2000grow_specpdl (void) 2010grow_specpdl (void)
2001{ 2011{
2002 ptrdiff_t count = SPECPDL_INDEX (); 2012 specpdl_ptr++;
2003 ptrdiff_t max_size = min (max_specpdl_size, PTRDIFF_MAX - 1000); 2013
2004 union specbinding *pdlvec = specpdl - 1; 2014 if (specpdl_ptr == specpdl + specpdl_size)
2005 ptrdiff_t pdlvecsize = specpdl_size + 1;
2006 if (max_size <= specpdl_size)
2007 { 2015 {
2008 if (max_specpdl_size < 400) 2016 ptrdiff_t count = SPECPDL_INDEX ();
2009 max_size = max_specpdl_size = 400; 2017 ptrdiff_t max_size = min (max_specpdl_size, PTRDIFF_MAX - 1000);
2018 union specbinding *pdlvec = specpdl - 1;
2019 ptrdiff_t pdlvecsize = specpdl_size + 1;
2010 if (max_size <= specpdl_size) 2020 if (max_size <= specpdl_size)
2011 signal_error ("Variable binding depth exceeds max-specpdl-size", Qnil); 2021 {
2022 if (max_specpdl_size < 400)
2023 max_size = max_specpdl_size = 400;
2024 if (max_size <= specpdl_size)
2025 signal_error ("Variable binding depth exceeds max-specpdl-size",
2026 Qnil);
2027 }
2028 pdlvec = xpalloc (pdlvec, &pdlvecsize, 1, max_size + 1, sizeof *specpdl);
2029 specpdl = pdlvec + 1;
2030 specpdl_size = pdlvecsize - 1;
2031 specpdl_ptr = specpdl + count;
2012 } 2032 }
2013 pdlvec = xpalloc (pdlvec, &pdlvecsize, 1, max_size + 1, sizeof *specpdl);
2014 specpdl = pdlvec + 1;
2015 specpdl_size = pdlvecsize - 1;
2016 specpdl_ptr = specpdl + count;
2017} 2033}
2018 2034
2019void 2035void
2020record_in_backtrace (Lisp_Object function, Lisp_Object *args, ptrdiff_t nargs) 2036record_in_backtrace (Lisp_Object function, Lisp_Object *args, ptrdiff_t nargs)
2021{ 2037{
2022 eassert (nargs >= UNEVALLED); 2038 eassert (nargs >= UNEVALLED);
2023 if (specpdl_ptr == specpdl + specpdl_size)
2024 grow_specpdl ();
2025 specpdl_ptr->bt.kind = SPECPDL_BACKTRACE; 2039 specpdl_ptr->bt.kind = SPECPDL_BACKTRACE;
2026 specpdl_ptr->bt.debug_on_exit = false; 2040 specpdl_ptr->bt.debug_on_exit = false;
2027 specpdl_ptr->bt.function = function; 2041 specpdl_ptr->bt.function = function;
2028 specpdl_ptr->bt.args = args; 2042 specpdl_ptr->bt.args = args;
2029 specpdl_ptr->bt.nargs = nargs; 2043 specpdl_ptr->bt.nargs = nargs;
2030 specpdl_ptr++; 2044 grow_specpdl ();
2031} 2045}
2032 2046
2033/* Eval a sub-expression of the current expression (i.e. in the same 2047/* Eval a sub-expression of the current expression (i.e. in the same
@@ -3113,8 +3127,6 @@ specbind (Lisp_Object symbol, Lisp_Object value)
3113 3127
3114 CHECK_SYMBOL (symbol); 3128 CHECK_SYMBOL (symbol);
3115 sym = XSYMBOL (symbol); 3129 sym = XSYMBOL (symbol);
3116 if (specpdl_ptr == specpdl + specpdl_size)
3117 grow_specpdl ();
3118 3130
3119 start: 3131 start:
3120 switch (sym->redirect) 3132 switch (sym->redirect)
@@ -3127,7 +3139,7 @@ specbind (Lisp_Object symbol, Lisp_Object value)
3127 specpdl_ptr->let.kind = SPECPDL_LET; 3139 specpdl_ptr->let.kind = SPECPDL_LET;
3128 specpdl_ptr->let.symbol = symbol; 3140 specpdl_ptr->let.symbol = symbol;
3129 specpdl_ptr->let.old_value = SYMBOL_VAL (sym); 3141 specpdl_ptr->let.old_value = SYMBOL_VAL (sym);
3130 ++specpdl_ptr; 3142 grow_specpdl ();
3131 if (!sym->constant) 3143 if (!sym->constant)
3132 SET_SYMBOL_VAL (sym, value); 3144 SET_SYMBOL_VAL (sym, value);
3133 else 3145 else
@@ -3162,7 +3174,7 @@ specbind (Lisp_Object symbol, Lisp_Object value)
3162 if (NILP (Flocal_variable_p (symbol, Qnil))) 3174 if (NILP (Flocal_variable_p (symbol, Qnil)))
3163 { 3175 {
3164 specpdl_ptr->let.kind = SPECPDL_LET_DEFAULT; 3176 specpdl_ptr->let.kind = SPECPDL_LET_DEFAULT;
3165 ++specpdl_ptr; 3177 grow_specpdl ();
3166 Fset_default (symbol, value); 3178 Fset_default (symbol, value);
3167 return; 3179 return;
3168 } 3180 }
@@ -3170,7 +3182,7 @@ specbind (Lisp_Object symbol, Lisp_Object value)
3170 else 3182 else
3171 specpdl_ptr->let.kind = SPECPDL_LET; 3183 specpdl_ptr->let.kind = SPECPDL_LET;
3172 3184
3173 specpdl_ptr++; 3185 grow_specpdl ();
3174 set_internal (symbol, value, Qnil, 1); 3186 set_internal (symbol, value, Qnil, 1);
3175 break; 3187 break;
3176 } 3188 }
@@ -3181,12 +3193,10 @@ specbind (Lisp_Object symbol, Lisp_Object value)
3181void 3193void
3182record_unwind_protect (Lisp_Object (*function) (Lisp_Object), Lisp_Object arg) 3194record_unwind_protect (Lisp_Object (*function) (Lisp_Object), Lisp_Object arg)
3183{ 3195{
3184 if (specpdl_ptr == specpdl + specpdl_size)
3185 grow_specpdl ();
3186 specpdl_ptr->unwind.kind = SPECPDL_UNWIND; 3196 specpdl_ptr->unwind.kind = SPECPDL_UNWIND;
3187 specpdl_ptr->unwind.func = function; 3197 specpdl_ptr->unwind.func = function;
3188 specpdl_ptr->unwind.arg = arg; 3198 specpdl_ptr->unwind.arg = arg;
3189 specpdl_ptr++; 3199 grow_specpdl ();
3190} 3200}
3191 3201
3192Lisp_Object 3202Lisp_Object