From 3eb87f7d6ce1b5ffde9c74c9776e9b0d3dd29164 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 8 Sep 2023 22:27:34 +1000 Subject: [PATCH] Ensure we never call anything after "Close". The only valid commands on a close pane are "Close", "Close:mark", and "Notify:Close" and these are always pane_call. So blocks all other calls on DAMAGED_CLOSED panes, and block even these on DAMAGED_DEAD. Note that "Free" is also allowed, but will soon be gone. This requires that home_comm_call() must be supported so that a comm can be called with a recently-closed pane as the focus (assuming it won't be dereferenced). Signed-off-by: NeilBrown --- core-keymap.c | 2 +- core-pane.h | 10 ++++++++++ core.h | 25 +++++++++++++++---------- lib-libevent.c | 2 +- 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/core-keymap.c b/core-keymap.c index c2b6e492..d766953e 100644 --- a/core-keymap.c +++ b/core-keymap.c @@ -558,7 +558,7 @@ int key_handle(const struct cmd_info *ci safe) while (p) { int ret = Efallthrough; - if (p->handle && !(p->damaged & DAMAGED_DEAD)) { + if (p->handle && !(p->damaged & DAMAGED_CLOSED)) { vci->home = p; vci->comm = p->handle; /* Don't add this to the call stack as it diff --git a/core-pane.h b/core-pane.h index e1d1b99d..87f114ec 100644 --- a/core-pane.h +++ b/core-pane.h @@ -131,6 +131,14 @@ static inline int do_call_val(enum target_type type, struct pane *home, return Efail; if (home) ci.home = home; + if ((home->damaged & DAMAGED_CLOSED) && + strncmp(ci.key, "Close", 5) != 0 && + strcmp(ci.key, "Notify:Close") != 0 && + strcmp(ci.key, "Free") != 0) + /* This pane cannot accept anything but + * "Close" or "Close:mark" or "Free" + */ + return Efail; ci.comm = home->handle; ret = ci.comm->func(&ci); break; @@ -139,6 +147,8 @@ static inline int do_call_val(enum target_type type, struct pane *home, return Efail; if (home) ci.home = home; + if (ci.home->damaged & DAMAGED_CLOSED) + return Efail; ci.comm = comm2a; ci.comm2 = comm2b; ret = ci.comm->func(&ci); diff --git a/core.h b/core.h index 12a19116..a60b939f 100644 --- a/core.h +++ b/core.h @@ -685,39 +685,44 @@ char *do_call_strsave(enum target_type type, struct pane *home, #define _doCALL(...) VFUNC(CALL, __VA_ARGS__) #define CALL15(ret, t_type, target, key, comm2a, focus, num, mark, str, \ num2, mark2, str2, x, y, comm2) \ - do_call_##ret(TYPE_##t_type, CH(T_##t_type,target, NULL), CH(T_##t_type,comm2,target), \ + do_call_##ret(TYPE_##t_type, CH(T_##t_type, target, comm2a), CH(T_##t_type,comm2,target), \ key, focus, num, mark, str, num2, mark2, str2, x, y, comm2) #define CALL14(ret, t_type, target, key, comm2a, focus, num, mark, str, num2, mark2, str2, x, y) \ - do_call_##ret(TYPE_##t_type, CH(T_##t_type,target, NULL), CH(T_##t_type,comm2a,target), \ + do_call_##ret(TYPE_##t_type, CH(T_##t_type, target, comm2a), CH(T_##t_type,comm2a,target), \ key, focus, num, mark, str, num2, mark2, str2, x, y, NULL) #define CALL12(ret, t_type, target, key, comm2a, focus, num, mark, str, num2, mark2, str2) \ - do_call_##ret(TYPE_##t_type, CH(T_##t_type,target, NULL), CH(T_##t_type,comm2a,target), \ + do_call_##ret(TYPE_##t_type, CH(T_##t_type, target, comm2a), CH(T_##t_type,comm2a,target), \ key, focus, num, mark, str, num2, mark2, str2, 0, 0, NULL) #define CALL11(ret, t_type, target, key, comm2a, focus, num, mark, str, num2, mark2) \ - do_call_##ret(TYPE_##t_type, CH(T_##t_type,target, NULL), CH(T_##t_type,comm2a,target), \ + do_call_##ret(TYPE_##t_type, CH(T_##t_type, target, comm2a), CH(T_##t_type,comm2a,target), \ key, focus, num, mark, str, num2, mark2, NULL, 0, 0, NULL) #define CALL10(ret, t_type, target, key, comm2a, focus, num, mark, str, num2) \ - do_call_##ret(TYPE_##t_type, CH(T_##t_type,target, NULL), CH(T_##t_type,comm2a,target), \ + do_call_##ret(TYPE_##t_type, CH(T_##t_type, target, comm2a), CH(T_##t_type,comm2a,target), \ key, focus, num, mark, str, num2, NULL, NULL, 0, 0, NULL) #define CALL9(ret, t_type, target, key, comm2a, focus, num, mark, str) \ - do_call_##ret(TYPE_##t_type, CH(T_##t_type,target, NULL), CH(T_##t_type,comm2a,target), \ + do_call_##ret(TYPE_##t_type, CH(T_##t_type, target, comm2a), CH(T_##t_type,comm2a,target), \ key, focus, num, mark, str, 0, NULL, NULL, 0, 0, NULL) #define CALL8(ret, t_type, target, key, comm2a, focus, num, mark) \ - do_call_##ret(TYPE_##t_type, CH(T_##t_type,target, NULL), CH(T_##t_type,comm2a,target), \ + do_call_##ret(TYPE_##t_type, CH(T_##t_type, target, comm2a), CH(T_##t_type,comm2a,target), \ key, focus, num, mark, NULL, 0, NULL, NULL, 0, 0, NULL) #define CALL7(ret, t_type, target, key, comm2a, focus, num) \ - do_call_##ret(TYPE_##t_type, CH(T_##t_type,target, NULL), CH(T_##t_type,comm2a,target), \ + do_call_##ret(TYPE_##t_type, CH(T_##t_type, target, comm2a), CH(T_##t_type,comm2a,target), \ key, focus, num, NULL, NULL, 0, NULL, NULL, 0, 0, NULL) #define CALL6(ret, t_type, target, key, comm2a, focus) \ - do_call_##ret(TYPE_##t_type, CH(T_##t_type,target, NULL), CH(T_##t_type,comm2a,target), \ + do_call_##ret(TYPE_##t_type, CH(T_##t_type,target, comm2a), CH(T_##t_type,comm2a,target), \ key, focus, 0, NULL, NULL, 0, NULL, NULL, 0, 0, NULL) #define CALL(ret, t_type, target, key, ...) _doCALL(ret, t_type, target, key, NULL, __VA_ARGS__) #define call(key, _focus, ...) CALL(val, focus, _focus, key, _focus, ##__VA_ARGS__) -/* comm_call() is only for callbacks, is it doesn't allow a separate 'home' */ +/* comm_call() is only for callbacks + * home_comm_call must be used if the focus must be closed already. + */ #define comm_call(_comm, key, ...) CALL(val, comm, _comm, key, ##__VA_ARGS__) +#define home_comm_call(_home, _comm, key, ...) _doCALL(val, comm, _comm, key, _home, __VA_ARGS__) + #define comm_call_ret(_ret, _comm, key, ...) CALL(_ret, comm, _comm, key, ##__VA_ARGS__) +#define home_comm_call_ret(_ret, _comm, key, ...) _doCALL(_ret, comm, _comm, key, _home, ##__VA_ARGS__) /* pane_call() is used when a very specific pane must be informed, rather than * the first responder in a chain of panes. This mostly used for notifications, * both generic notification, and special things like a child appearing or disappearing diff --git a/lib-libevent.c b/lib-libevent.c index 6268f721..e13fd652 100644 --- a/lib-libevent.c +++ b/lib-libevent.c @@ -444,7 +444,7 @@ DEF_CMD(libevent_notify) { struct event_info *ei = ci->home->data; - comm_call(&ei->free, "free", ci->focus); + home_comm_call(ci->home, &ei->free, "free", ci->focus); return 1; } -- 2.39.5