From 9013f866a8231f39f066fc9bd9638611da2c3962 Mon Sep 17 00:00:00 2001 From: "Rob Swindell (on ChromeOS)" <rob@synchro.net> Date: Sat, 30 Mar 2024 15:26:20 -0700 Subject: [PATCH] Save and restore the js.exec_path, exec_dir, and exec_file properties When invoking a nested JS script, these properties of the "js" object would be overwritten and not restored, as discovered/reported by Nightfox when his trivial game script would indirectly execute yesnobar.js, his subsequent use of js.exec_dir would point to the wrong location (the "exec" directory, parent of yesnobar.js, and not the direcctory where his game script was located). The exec_path and exec_file properties had the same problem as demonstrated by a simple test.js placed in (and executed from) a directory other than the "exec" dir: function f() { print("js.exec_path = " + js.exec_path); print("js.exec_dir = " + js.exec_dir); print("Js.exec_file = " + js.exec_file); } f(); console.yesno("test"); f(); This would only trigger the problem when executed from the BBS and whebn the YesNoQuestion text.dat string invokes the "yesnobar" module via EXEC @-code and yesnobar.js exists (in exec or mods dir), superceding yesnobar.bin which does not trigger this issue (not a JavaScript mod). --- src/sbbs3/exec.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/sbbs3/exec.cpp b/src/sbbs3/exec.cpp index 454d7031a4..1f28e7802d 100644 --- a/src/sbbs3/exec.cpp +++ b/src/sbbs3/exec.cpp @@ -541,6 +541,10 @@ int sbbs_t::js_execfile(const char *cmd, const char* startup_dir, JSObject* scop JSObject* js_script=NULL; jsval old_js_argv = JSVAL_VOID; jsval old_js_argc = JSVAL_VOID; + jsval old_js_exec_path = JSVAL_VOID; + jsval old_js_exec_file = JSVAL_VOID; + jsval old_js_exec_dir = JSVAL_VOID; + jsval val; jsval rval; int32 result=0; struct js_event_list *events; @@ -663,6 +667,17 @@ int sbbs_t::js_execfile(const char *cmd, const char* startup_dir, JSObject* scop js_callback.counter=0; // Reset loop counter } JS_SetOperationCallback(js_cx, js_OperationCallback); + if(JS_GetProperty(js_cx, js_glob, "js", &val) && JSVAL_IS_OBJECT(val)) { + JSObject* js = JSVAL_TO_OBJECT(val); + + if(JS_GetProperty(js_cx, js, "exec_path", &old_js_exec_path)) + JS_AddValueRoot(js_cx, &old_js_exec_path); + if(JS_GetProperty(js_cx, js, "exec_file", &old_js_exec_file)) + JS_AddValueRoot(js_cx, &old_js_exec_file); + if(JS_GetProperty(js_cx, js, "exec_dir", &old_js_exec_dir)) + JS_AddValueRoot(js_cx, &old_js_exec_dir); + } + js_PrepareToExecute(js_cx, js_glob, path, startup_dir, js_scope); events = js_callback.events; js_callback.events = NULL; @@ -702,6 +717,18 @@ int sbbs_t::js_execfile(const char *cmd, const char* startup_dir, JSObject* scop JS_RemoveValueRoot(js_cx, &old_js_argv); JS_RemoveValueRoot(js_cx, &old_js_argc); } + if(JS_GetProperty(js_cx, js_glob, "js", &val) && JSVAL_IS_OBJECT(val)) { + JSObject* js = JSVAL_TO_OBJECT(val); + JS_DefineProperty(js_cx, js, "exec_path", old_js_exec_path + ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY); + JS_RemoveValueRoot(js_cx, &old_js_exec_path); + JS_DefineProperty(js_cx, js, "exec_file", old_js_exec_file + ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY); + JS_RemoveValueRoot(js_cx, &old_js_exec_file); + JS_DefineProperty(js_cx, js, "exec_dir", old_js_exec_dir + ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY); + JS_RemoveValueRoot(js_cx, &old_js_exec_dir); + } JS_GC(js_cx); -- GitLab