From a86f3c04a52515cfd830ae740cc264b98be90e7a Mon Sep 17 00:00:00 2001
From: Philipp Hahn
Date: Mon, 24 Mar 2025 14:02:03 +0100
Subject: [PATCH] trace: fix SIGSEGV after pop
Calling `trace_pop_target()` invalidates the linked list of
`target_stack_node_t`s by `free()`ing the node and its `p_target`.
But `p_stack_top` may still points at that now freed node. Entering the
debugger will crash as it will start from `p_stack_top`.
1. Explicitly invalidate `p_target` by setting it to `NULL`.
2. Explicitly pop the top node from `p_stack_top` before calling
`trace_pop_target()`.
Closes: #158
Signed-off-by: Philipp Hahn
---
src/remake.c | 8 ++++++++
src/trace.c | 1 +
2 files changed, 9 insertions(+)
diff --git a/src/remake.c b/src/remake.c
index e5f6d0443..84cde9e20 100644
--- a/src/remake.c
+++ b/src/remake.c
@@ -456,6 +456,7 @@ update_file_1 (struct file *file, unsigned int depth,
}
DBF (DB_VERBOSE, _("File '%s' was considered already.\n"));
+ p_stack_top = p_stack_top->p_parent;
trace_pop_target(p_call_stack);
return 0;
}
@@ -467,10 +468,12 @@ update_file_1 (struct file *file, unsigned int depth,
break;
case cs_running:
DBF (DB_VERBOSE, _("Still updating file '%s'.\n"));
+ p_stack_top = p_stack_top->p_parent;
trace_pop_target(p_call_stack);
return 0;
case cs_finished:
DBF (DB_VERBOSE, _("Finished updating file '%s'.\n"));
+ p_stack_top = p_stack_top->p_parent;
trace_pop_target(p_call_stack);
return file->update_status;
default:
@@ -707,6 +710,7 @@ update_file_1 (struct file *file, unsigned int depth,
set_command_state (file, cs_deps_running);
--depth;
DBF (DB_VERBOSE, _("The prerequisites of '%s' are being made.\n"));
+ p_stack_top = p_stack_top->p_parent;
trace_pop_target(p_call_stack);
return 0;
}
@@ -728,6 +732,7 @@ update_file_1 (struct file *file, unsigned int depth,
OS (error, NILF,
_("Target '%s' not remade because of errors."), file->name);
+ p_stack_top = p_stack_top->p_parent;
trace_pop_target(p_call_stack);
return dep_status;
}
@@ -838,6 +843,7 @@ update_file_1 (struct file *file, unsigned int depth,
}
notice_finished_file (file);
+ p_stack_top = p_stack_top->p_parent;
trace_pop_target(p_call_stack);
/* Since we don't need to remake the file, convert it to use the
@@ -871,6 +877,7 @@ update_file_1 (struct file *file, unsigned int depth,
DBF (DB_VERBOSE, _("Recipe of '%s' is being run.\n"));
if ( file->tracing & BRK_AFTER_CMD || i_debugger_stepping )
enter_debugger(p_call_stack, file, 0, DEBUG_BRKPT_AFTER_CMD);
+ p_stack_top = p_stack_top->p_parent;
trace_pop_target(p_call_stack);
return 0;
}
@@ -894,6 +901,7 @@ update_file_1 (struct file *file, unsigned int depth,
if ( file->tracing & BRK_AFTER_CMD || i_debugger_stepping )
enter_debugger(p_call_stack, file, 0, DEBUG_BRKPT_AFTER_CMD);
+ p_stack_top = p_stack_top->p_parent;
trace_pop_target(p_call_stack);
return file->update_status;
}
diff --git a/src/trace.c b/src/trace.c
index 53b4622aa..921425080 100644
--- a/src/trace.c
+++ b/src/trace.c
@@ -91,6 +91,7 @@ trace_pop_target (target_stack_node_t *p)
}
free(p->p_target);
+ p->p_target = NULL;
free(p);
}