From e3e3e691f817c2b37fbaec6f749cd4d7ce18d857 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Thu, 2 Jan 2020 13:27:23 +0100 Subject: [PATCH] Fix abort_to_prompt bug if dynwind leave thunk expands the stack * libguile/vm.c (scm_i_vm_emergency_abort, abort_to_prompt): Unwinding the dynwind stack can run dynwind leave thunks, which may expand the stack, which may invalidate previously calculated SP / FP values. (Re)calculate SP/FP after unwinding, to avoid writing to unmapped memory. Fixes compile errors seen on Ubuntu and some other ports. --- libguile/vm.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/libguile/vm.c b/libguile/vm.c index 5899fa98b..ab6a6295e 100644 --- a/libguile/vm.c +++ b/libguile/vm.c @@ -1,4 +1,4 @@ -/* Copyright 2001,2009-2015,2017-2019 +/* Copyright 2001,2009-2015,2017-2020 Free Software Foundation, Inc. This file is part of Guile. @@ -1360,9 +1360,6 @@ scm_i_vm_emergency_abort (SCM *tag_and_argv, size_t n) abort (); } - fp = vp->stack_top - fp_offset; - sp = vp->stack_top - sp_offset; - if (!(flags & SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY)) { fprintf (stderr, "guile: fatal: emergency abort to non-linear prompt\n"); @@ -1374,6 +1371,9 @@ scm_i_vm_emergency_abort (SCM *tag_and_argv, size_t n) /* Unwind. */ scm_dynstack_unwind (dynstack, prompt); + fp = vp->stack_top - fp_offset; + sp = vp->stack_top - sp_offset; + /* Continuation gets nargs+1 values: the one more is for the cont. */ sp = sp - nargs - 1; @@ -1422,7 +1422,6 @@ abort_to_prompt (scm_thread *thread, uint8_t *saved_mra) scm_misc_error ("abort", "Abort to unknown prompt", scm_list_1 (tag)); fp = vp->stack_top - fp_offset; - sp = vp->stack_top - sp_offset; /* Only reify if the continuation referenced in the handler. */ if (flags & SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY) @@ -1439,6 +1438,10 @@ abort_to_prompt (scm_thread *thread, uint8_t *saved_mra) /* Unwind. */ scm_dynstack_unwind (dynstack, prompt); + /* Recompute FP, as scm_dynstack_unwind may have expanded the stack. */ + fp = vp->stack_top - fp_offset; + sp = vp->stack_top - sp_offset; + /* Continuation gets nargs+1 values: the one more is for the cont. */ sp = sp - nargs - 1;