From a6857c613efe6a0b54deb5daa0dc3234d5d86b57 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Tue, 6 Jul 2021 06:25:35 -0700 Subject: unwind: stop runaway recursion. Before uw_rthrow calls uw_unwind_to_exit_point, it decrements the reentry_count, so that function is not protected against re-entry. We could protect some of its internal code agains re-entry, like the use of a bad stderr stream, if we extend the scope of that variable. * unwind.c (reentry_count): New static variable, moved to file scope from uw_rthrow function. (uw_unwind_to_exit_point): Bump up the reentry count in two places where we print diagnostics and terminate. If the diagnostic code hits an exception, the uw_rthrow will see the positive reentry count and abort. --- unwind.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'unwind.c') diff --git a/unwind.c b/unwind.c index 60746003..9773d228 100644 --- a/unwind.c +++ b/unwind.c @@ -76,6 +76,8 @@ static val deferred_warnings, tentative_defs; static int uw_break_on_error; #endif +static int reentry_count; + static void uw_unwind_to_exit_point(void) { uw_frame_t *orig_stack = uw_stack; @@ -110,6 +112,7 @@ static void uw_unwind_to_exit_point(void) case UW_GUARD: if (uw_stack->gu.uw_ok) break; + ++reentry_count; format(top_stderr, lit("~a: cannot unwind across foreign stack frames\n"), prog_string, nao); abort(); @@ -123,6 +126,7 @@ static void uw_unwind_to_exit_point(void) val args = unhandled_ex.ca.args; gc_stack_limit = 0; + ++reentry_count; dyn_env = nil; @@ -670,7 +674,6 @@ static void invoke_handler(uw_frame_t *fr, struct args *args) val uw_rthrow(val sym, val args) { uw_frame_t *ex; - static int reentry_count = 0; if (++reentry_count > 1) { fprintf(stderr, "txr: invalid re-entry of exception handling logic\n"); -- cgit v1.2.3