From 8b4eb936dbd863191e75cb7d1567d75d13b1e231 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 29 Jul 2025 16:14:38 +0200 Subject: [PATCH] target: allow events to be modified inside an event handler The code in an event handler can use the command '$target_name configure' to add a new event or to remove or modify an existing event. Such operation impacts the list of event of the target and also modify the event itself, causing OpenOCD to access memory already deallocated or not anymore valid. Use the safe version of list_for_each_entry() to iterate on the list of events. Make a local copy of the current event, to avoid issues if it gets deallocated. Use Jim_IncrRefCount() to guarantee that the body of the event handler don't gets deallocated when the event is removed. Change-Id: I936e35adddc030ba7cec6e2fc0c7d3b1b5c4a863 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/9063 Reviewed-by: Evgeniy Naydanov Tested-by: jenkins --- src/target/target.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index 002fd7886..ca9b90133 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -4663,11 +4663,18 @@ COMMAND_HANDLER(handle_target_write_memory) */ void target_handle_event(struct target *target, enum target_event e) { - struct target_event_action *teap; + struct target_event_action *teap, *tmp; int retval; - list_for_each_entry(teap, &target->events_action, list) { + list_for_each_entry_safe(teap, tmp, &target->events_action, list) { if (teap->event == e) { + /* + * The event can be destroyed by its own handler. + * Make a local copy and use it in place of the original. + */ + struct target_event_action local_teap = *teap; + teap = &local_teap; + LOG_DEBUG("target: %s (%s) event: %d (%s) action: %s", target_name(target), target_type_name(target), @@ -4683,7 +4690,13 @@ void target_handle_event(struct target *target, enum target_event e) struct target *saved_target_override = cmd_ctx->current_target_override; cmd_ctx->current_target_override = target; + /* + * The event can be destroyed by its own handler. + * Prevent the body to get deallocated by Jim. + */ + Jim_IncrRefCount(teap->body); retval = Jim_EvalObj(teap->interp, teap->body); + Jim_DecrRefCount(teap->interp, teap->body); cmd_ctx->current_target_override = saved_target_override;