From 51dc3beee71e87bd254845591c95e378ba59970d Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Fri, 24 Jul 2009 16:41:30 +0300 Subject: [PATCH] Bug 943: Refuse user JS actions in unfocused tabs --- NEWS | 14 ++++++++++++++ doc/smjs-scripting.txt | 7 ++++--- src/scripting/smjs/action_object.c | 28 ++++++++++++++++++++++++++++ src/terminal/window.c | 22 ++++++++++++++++++++++ src/terminal/window.h | 4 ++++ 5 files changed, 72 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index c7e4025c..a3eb8815 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,20 @@ You can see the complete list of recent changes, bugfixes and new features in the http://repo.or.cz/w/elinks.git[gitweb interface]. See the ChangeLog file for details. +ELinks 0.12pre5.GIT now: +------------------------ + +To be released as 0.12pre6 or 0.12rc1. + +Bugs that should be removed from NEWS before the 0.12.0 release: + +* critical bug 943: Don't let user JavaScripts call any methods of + ``elinks.action'' in tabs that do not have the focus. If a tab was + closed with ``elinks.action.tab_close'' while it had pop-up windows, + ELinks could crash; as a precaution, don't allow other actions + either. ELinks 0.12pre1 was the first release that supported + ``elinks.action''. + ELinks 0.12pre5: ---------------- diff --git a/doc/smjs-scripting.txt b/doc/smjs-scripting.txt index 34221cd4..155136ad 100644 --- a/doc/smjs-scripting.txt +++ b/doc/smjs-scripting.txt @@ -234,9 +234,10 @@ A history item has these properties: *Compatibility:* ELinks 0.12pre1 NOTE: When you read an action function from this hash, ELinks binds it to the -current tab; any later calls to the function affect that tab. This may be -changed in a future version. It is safest to call the function right away, -rather than save it in a variable and call it later. +current tab; any later calls to the function throw errors if that tab no +longer has the focus (in its terminal). This may be changed in a future +version. It is safest to call the function right away, rather than save it +in a variable and call it later. -- [[smjs-elinks.keymaps]] elinks.keymaps (hash):: diff --git a/src/scripting/smjs/action_object.c b/src/scripting/smjs/action_object.c index d95564d2..f6ae68fd 100644 --- a/src/scripting/smjs/action_object.c +++ b/src/scripting/smjs/action_object.c @@ -8,9 +8,11 @@ #include "config/kbdbind.h" #include "ecmascript/spidermonkey-shared.h" +#include "intl/gettext/libintl.h" #include "scripting/smjs/core.h" #include "scripting/smjs/elinks_object.h" #include "session/session.h" +#include "terminal/window.h" #include "util/memory.h" #include "viewer/action.h" @@ -60,6 +62,32 @@ smjs_action_fn_callback(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, (JSClass *) &action_fn_class, NULL); if (!hop) return JS_TRUE; + if (!would_window_receive_keypresses(hop->ses->tab)) { + /* The user cannot run actions in this tab by pressing + * keys, and some actions could crash if run in this + * situation; so we don't let user scripts run actions + * either. + * + * In particular, this check should fix bug 943, where + * ::ACT_MAIN_TAB_CLOSE called destroy_session(), + * which freed struct type_query while BFU dialogs had + * pointers to it. That crash could be prevented in + * various ways but it seems other similar crashes are + * possible, e.g. if the link menu is open and has a + * pointer to a session that is then destroyed. + * Instead of thoroughly auditing the use of pointers + * to sessions and related structures, I'll just + * disable the feature, to bring the ELinks 0.12 + * release closer. + * + * The "%s" prevents interpretation of any percent + * signs in translations. */ + JS_ReportError(ctx, "%s", + _("Cannot run actions in a tab that doesn't " + "have the focus", hop->ses->tab->term)); + return JS_FALSE; /* make JS propagate the exception */ + } + if (argc >= 1) { int32 val; diff --git a/src/terminal/window.c b/src/terminal/window.c index d4cd6c1b..9ac71916 100644 --- a/src/terminal/window.c +++ b/src/terminal/window.c @@ -205,3 +205,25 @@ assert_window_stacking(struct terminal *term) } } #endif /* CONFIG_DEBUG */ + +#if CONFIG_SCRIPTING_SPIDERMONKEY +/** Check whether keypress events would be directed to @a win. */ +int +would_window_receive_keypresses(const struct window *win) +{ + struct terminal *const term = win->term; + const struct window *selected; + + /* At least @win must be in the list. */ + assert(!list_empty(term->windows)); + if_assert_failed return 0; + + selected = term->windows.next; + if (selected->type != WINDOW_TAB) return 0; + + selected = get_current_tab(term); + if (selected != win) return 0; + + return 1; +} +#endif /* CONFIG_SCRIPTING_SPIDERMONKEY */ diff --git a/src/terminal/window.h b/src/terminal/window.h index e94da64b..8bb329d4 100644 --- a/src/terminal/window.h +++ b/src/terminal/window.h @@ -83,4 +83,8 @@ void assert_window_stacking(struct terminal *); #define assert_window_stacking(t) ((void) (t)) #endif +#if CONFIG_SCRIPTING_SPIDERMONKEY +int would_window_receive_keypresses(const struct window *); +#endif + #endif -- 2.11.4.GIT