summaryrefslogtreecommitdiffstats
path: root/generic/tclMain.c
diff options
context:
space:
mode:
authorbch <brad.harder@gmail.com>2022-01-28 08:29:14 (GMT)
committerbch <brad.harder@gmail.com>2022-01-28 08:29:14 (GMT)
commit60f5d30e4406df3a2d80e61d7d9972dce3293133 (patch)
tree43d2950292d741dd24544d58ee96b4bb365c9f95 /generic/tclMain.c
parentaf3e9b9825f98a98907966cdd71286c1f00c8bcf (diff)
downloadtcl-60f5d30e4406df3a2d80e61d7d9972dce3293133.zip
tcl-60f5d30e4406df3a2d80e61d7d9972dce3293133.tar.gz
tcl-60f5d30e4406df3a2d80e61d7d9972dce3293133.tar.bz2
rejig argv/argc Tcl_MainEx() handling, prompted by outside discussion re: current [https://arstechnica.com/information-technology/2022/01/a-bug-lurking-for-12-years-gives-attackers-root-on-every-major-linux-distro/|polkit] issues, and comparisons of execve(2) abuse/mitigation (esp wrt OpenBSD); Probably most importantly, the access to argv has been limited to indexing, not swapping back/forth between indexing and advancing argv; pls review
Diffstat (limited to 'generic/tclMain.c')
-rw-r--r--generic/tclMain.c24
1 files changed, 15 insertions, 9 deletions
diff --git a/generic/tclMain.c b/generic/tclMain.c
index f175319..c2eee13 100644
--- a/generic/tclMain.c
+++ b/generic/tclMain.c
@@ -288,6 +288,7 @@ Tcl_MainEx(
* but before starting to execute commands. */
Tcl_Interp *interp)
{
+ int i=0; /* argv[i] index */
Tcl_Obj *path, *resultPtr, *argvPtr, *appName;
const char *encodingName = NULL;
int code, exitCode = 0;
@@ -296,7 +297,13 @@ Tcl_MainEx(
InteractiveState is;
TclpSetInitialEncodings();
- TclpFindExecutable((const char *)argv[0]);
+ if (0 < argc) {
+ --argc; /* consume argv[0] */
+ ++i;
+ }
+ TclpFindExecutable((const char *)argv[0]); /* nb: this could be NULL
+ * w/ (eg) a malformed
+ * execve() */
Tcl_InitMemory(interp);
@@ -318,36 +325,35 @@ Tcl_MainEx(
* FILENAME
*/
- if ((argc > 3) && (0 == _tcscmp(TEXT("-encoding"), argv[1]))
+ /* mind argc is being adjusted as we proceed */
+ if ((argc >= 3) && (0 == _tcscmp(TEXT("-encoding"), argv[1]))
&& ('-' != argv[3][0])) {
Tcl_Obj *value = NewNativeObj(argv[2]);
Tcl_SetStartupScript(NewNativeObj(argv[3]),
TclGetString(value));
Tcl_DecrRefCount(value);
argc -= 3;
- argv += 3;
- } else if ((argc > 1) && ('-' != argv[1][0])) {
+ i += 3;
+ } else if ((argc >= 1) && ('-' != argv[1][0])) {
Tcl_SetStartupScript(NewNativeObj(argv[1]), NULL);
argc--;
- argv++;
+ i++;
}
}
path = Tcl_GetStartupScript(&encodingName);
if (path == NULL) {
- appName = NewNativeObj(argv[0]);
+ appName = NewNativeObj(argv[0]); // nb: argv is _not_ advanced here...
} else {
appName = path;
}
Tcl_SetVar2Ex(interp, "argv0", NULL, appName, TCL_GLOBAL_ONLY);
- argc--;
- argv++;
Tcl_SetVar2Ex(interp, "argc", NULL, Tcl_NewWideIntObj(argc), TCL_GLOBAL_ONLY);
argvPtr = Tcl_NewListObj(0, NULL);
while (argc--) {
- Tcl_ListObjAppendElement(NULL, argvPtr, NewNativeObj(*argv++));
+ Tcl_ListObjAppendElement(NULL, argvPtr, NewNativeObj(argv[i++]));
}
Tcl_SetVar2Ex(interp, "argv", NULL, argvPtr, TCL_GLOBAL_ONLY);