summaryrefslogtreecommitdiffstats
path: root/generic/tkWindow.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tkWindow.c')
-rw-r--r--generic/tkWindow.c81
1 files changed, 77 insertions, 4 deletions
diff --git a/generic/tkWindow.c b/generic/tkWindow.c
index fc9060a..510842b 100644
--- a/generic/tkWindow.c
+++ b/generic/tkWindow.c
@@ -2624,12 +2624,85 @@ Initialize(interp)
rest = 0;
/*
- * If there is an "argv" variable, get its value, extract out
- * relevant arguments from it, and rewrite the variable without
- * the arguments that we used.
+ * We start by resetting the result because it might not be clean
*/
+ Tcl_ResetResult(interp);
+
+ if (Tcl_IsSafe(interp)) {
+ /*
+ * Get the clearance to start Tk and the "argv" parameters
+ * from the master.
+ */
+ Tcl_DString ds;
+
+ /*
+ * Step 1 : find the master and construct the interp name
+ * (could be a function if new APIs were ok).
+ * We could also construct the path while walking, but there
+ * is no API to get the name of an interp either.
+ */
+ Tcl_Interp *master = interp;
+
+ while (1) {
+ master = Tcl_GetMaster(master);
+ if (master == NULL) {
+ Tcl_DStringFree(&ds);
+ Tcl_AppendResult(interp, "NULL master", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (!Tcl_IsSafe(master)) {
+ /* Found the trusted master. */
+ break;
+ }
+ }
+ /*
+ * Construct the name (rewalk...)
+ */
+ if (Tcl_GetInterpPath(master, interp) != TCL_OK) {
+ Tcl_AppendResult(interp, "error in Tcl_GetInterpPath",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ /*
+ * Build the string to eval.
+ */
+ Tcl_DStringInit(&ds);
+ Tcl_DStringAppendElement(&ds, "::safe::TkInit");
+ Tcl_DStringAppendElement(&ds, Tcl_GetStringResult(master));
+
+ /*
+ * Step 2 : Eval in the master. The argument is the *reversed*
+ * interp path of the slave.
+ */
+
+ if (Tcl_Eval(master, Tcl_DStringValue(&ds)) != TCL_OK) {
+ /*
+ * We might want to transfer the error message or not.
+ * We don't. (no API to do it and maybe security reasons).
+ */
+ Tcl_DStringFree(&ds);
+ Tcl_AppendResult(interp,
+ "not allowed to start Tk by master's safe::TkInit",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ Tcl_DStringFree(&ds);
+ /*
+ * Use the master's result as argv.
+ * Note: We don't use the Obj interfaces to avoid dealing with
+ * cross interp refcounting and changing the code below.
+ */
- p = Tcl_GetVar2(interp, "argv", (char *) NULL, TCL_GLOBAL_ONLY);
+ p = Tcl_GetStringResult(master);
+ } else {
+ /*
+ * If there is an "argv" variable, get its value, extract out
+ * relevant arguments from it, and rewrite the variable without
+ * the arguments that we used.
+ */
+
+ p = Tcl_GetVar2(interp, "argv", (char *) NULL, TCL_GLOBAL_ONLY);
+ }
argv = NULL;
if (p != NULL) {
if (Tcl_SplitList(interp, p, &argc, &argv) != TCL_OK) {