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 <borneo.antonio@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/9063
Reviewed-by: Evgeniy Naydanov <evgeniy.naydanov@syntacore.com>
Tested-by: jenkins
This commit is contained in:
Antonio Borneo
2025-07-29 16:14:38 +02:00
parent 93c565e7b4
commit 8b4eb936db

View File

@@ -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;