diff options
| author | Noam Postavsky | 2018-02-15 22:13:51 -0500 |
|---|---|---|
| committer | Noam Postavsky | 2018-02-16 22:13:34 -0500 |
| commit | c352434ab89617b48c7c1f29342a22e5a5685504 (patch) | |
| tree | 0a6e535935d8f9a4a2691b30f7324573d48068d3 /src | |
| parent | 593bbdaf0b890924e9d10918ba6de206bddc2eb6 (diff) | |
| download | emacs-c352434ab89617b48c7c1f29342a22e5a5685504.tar.gz emacs-c352434ab89617b48c7c1f29342a22e5a5685504.zip | |
Avoid memory corruption with specpdl overflow + edebug (Bug#30481)
If grow_specpdl fails due to outgrowing max_specpdl_size, it will
signal an error *before* growing the specpdl array. Therefore, when
handling the signal, specpdl_ptr points past the end of the specpdl
array and any further use of of specpdl before unwinding (e.g., if
edebug binds signal-hook-function) will cause memory corruption.
* src/eval.c (signal_or_quit): Don't call `signal-hook-function' if
the specpdl_ptr is already past the end of the specpdl array.
* test/src/eval-tests.el (eval-tests--exceed-specbind-limit)
(eval-exceed-specbind-with-signal-hook): New test & helper function.
Diffstat (limited to 'src')
| -rw-r--r-- | src/eval.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/src/eval.c b/src/eval.c index e05a17f7b4b..ca1eb84ff3f 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -1553,7 +1553,10 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit) | |||
| 1553 | 1553 | ||
| 1554 | /* This hook is used by edebug. */ | 1554 | /* This hook is used by edebug. */ |
| 1555 | if (! NILP (Vsignal_hook_function) | 1555 | if (! NILP (Vsignal_hook_function) |
| 1556 | && ! NILP (error_symbol)) | 1556 | && ! NILP (error_symbol) |
| 1557 | /* Don't try to call a lisp function if we've already overflowed | ||
| 1558 | the specpdl stack. */ | ||
| 1559 | && specpdl_ptr < specpdl + specpdl_size) | ||
| 1557 | { | 1560 | { |
| 1558 | /* Edebug takes care of restoring these variables when it exits. */ | 1561 | /* Edebug takes care of restoring these variables when it exits. */ |
| 1559 | if (lisp_eval_depth + 20 > max_lisp_eval_depth) | 1562 | if (lisp_eval_depth + 20 > max_lisp_eval_depth) |