Module Name:    src
Committed By:   kre
Date:           Fri Jul 12 07:30:30 UTC 2024

Modified Files:
        src/bin/sh: exec.c exec.h histedit.c myhistedit.h options.c options.h
            var.c var.h

Log Message:
Improve safety in var imports from the environment.

Add a new var flag VUNSAFE - set on all vars imported from the environment.

Add setvareqsafe() (which is to setvareq() as setvarsafe() is to setvar())
and use that instead of setvareq() when processing the environment, so
errors don't cause the shell to abort.  Use VUNSAFE in that call.

Add flags arguments to all var callback functions which are used when setting
variables, and pass the flags given to the setvar*() functions to those
functions, so they can act differently in different situations (if desired).
Most of them just ignore the flags.

When unsetting a variable, call setvar() to clear things (and call the
callback function) both when the variable had a value which needs to be freed,
and when unsetting a variable which wasn't unset previously, so the VUNSET
flag can be seen by that callback func.

When setting HISTSIZE, use the flags passed to determine whether to ignore
bad values (if VUNSAFE) or treat them as an error.  This replaces the
earlier temporary hack to always ignore bad data there (histedit.c 1.68).

Miscellaneous associated minor changes.

These changes should largely be invisible in normal use.


To generate a diff of this commit:
cvs rdiff -u -r1.58 -r1.59 src/bin/sh/exec.c src/bin/sh/options.c
cvs rdiff -u -r1.27 -r1.28 src/bin/sh/exec.h src/bin/sh/options.h
cvs rdiff -u -r1.69 -r1.70 src/bin/sh/histedit.c
cvs rdiff -u -r1.14 -r1.15 src/bin/sh/myhistedit.h
cvs rdiff -u -r1.82 -r1.83 src/bin/sh/var.c
cvs rdiff -u -r1.39 -r1.40 src/bin/sh/var.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/bin/sh/exec.c
diff -u src/bin/sh/exec.c:1.58 src/bin/sh/exec.c:1.59
--- src/bin/sh/exec.c:1.58	Sun Mar 19 17:55:57 2023
+++ src/bin/sh/exec.c	Fri Jul 12 07:30:30 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: exec.c,v 1.58 2023/03/19 17:55:57 kre Exp $	*/
+/*	$NetBSD: exec.c,v 1.59 2024/07/12 07:30:30 kre Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)exec.c	8.4 (Berkeley) 6/8/95";
 #else
-__RCSID("$NetBSD: exec.c,v 1.58 2023/03/19 17:55:57 kre Exp $");
+__RCSID("$NetBSD: exec.c,v 1.59 2024/07/12 07:30:30 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -844,7 +844,7 @@ hashcd(void)
  */
 
 void
-changepath(const char *newval)
+changepath(char *newval, int flags __unused)
 {
 	const char *old, *new;
 	int idx;
Index: src/bin/sh/options.c
diff -u src/bin/sh/options.c:1.58 src/bin/sh/options.c:1.59
--- src/bin/sh/options.c:1.58	Sun Sep 18 06:03:19 2022
+++ src/bin/sh/options.c	Fri Jul 12 07:30:30 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: options.c,v 1.58 2022/09/18 06:03:19 kre Exp $	*/
+/*	$NetBSD: options.c,v 1.59 2024/07/12 07:30:30 kre Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)options.c	8.2 (Berkeley) 5/4/95";
 #else
-__RCSID("$NetBSD: options.c,v 1.58 2022/09/18 06:03:19 kre Exp $");
+__RCSID("$NetBSD: options.c,v 1.59 2024/07/12 07:30:30 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -465,7 +465,7 @@ setcmd(int argc, char **argv)
 
 
 void
-getoptsreset(const char *value)
+getoptsreset(char *value, int flags __unused)
 {
 	/*
 	 * This is just to detect the case where OPTIND=1

Index: src/bin/sh/exec.h
diff -u src/bin/sh/exec.h:1.27 src/bin/sh/exec.h:1.28
--- src/bin/sh/exec.h:1.27	Fri Jun 22 11:04:55 2018
+++ src/bin/sh/exec.h	Fri Jul 12 07:30:30 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: exec.h,v 1.27 2018/06/22 11:04:55 kre Exp $	*/
+/*	$NetBSD: exec.h,v 1.28 2024/07/12 07:30:30 kre Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -69,7 +69,7 @@ void find_command(char *, struct cmdentr
 int (*find_builtin(char *))(int, char **);
 int (*find_splbltin(char *))(int, char **);
 void hashcd(void);
-void changepath(const char *);
+void changepath(char *, int);
 void deletefuncs(void);
 void getcmdentry(char *, struct cmdentry *);
 union node;
Index: src/bin/sh/options.h
diff -u src/bin/sh/options.h:1.27 src/bin/sh/options.h:1.28
--- src/bin/sh/options.h:1.27	Sun May 28 00:38:01 2017
+++ src/bin/sh/options.h	Fri Jul 12 07:30:30 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: options.h,v 1.27 2017/05/28 00:38:01 kre Exp $	*/
+/*	$NetBSD: options.h,v 1.28 2024/07/12 07:30:30 kre Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -69,4 +69,4 @@ void optschanged(void);
 void setparam(char **);
 void freeparam(volatile struct shparam *);
 int nextopt(const char *);
-void getoptsreset(const char *);
+void getoptsreset(char *, int);

Index: src/bin/sh/histedit.c
diff -u src/bin/sh/histedit.c:1.69 src/bin/sh/histedit.c:1.70
--- src/bin/sh/histedit.c:1.69	Fri Jul  5 04:07:26 2024
+++ src/bin/sh/histedit.c	Fri Jul 12 07:30:30 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: histedit.c,v 1.69 2024/07/05 04:07:26 kre Exp $	*/
+/*	$NetBSD: histedit.c,v 1.70 2024/07/12 07:30:30 kre Exp $	*/
 
 /*-
  * Copyright (c) 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)histedit.c	8.2 (Berkeley) 5/4/95";
 #else
-__RCSID("$NetBSD: histedit.c,v 1.69 2024/07/05 04:07:26 kre Exp $");
+__RCSID("$NetBSD: histedit.c,v 1.70 2024/07/12 07:30:30 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -113,7 +113,7 @@ histedit(void)
 			INTON;
 
 			if (hist != NULL)
-				sethistsize(histsizeval());
+				sethistsize(histsizeval(), histsizeflags());
 			else
 				out2str("sh: can't initialize history\n");
 		}
@@ -164,7 +164,7 @@ histedit(void)
 				if (hist)
 					el_set(el, EL_HIST, history, hist);
 
-				set_prompt_lit(lookupvar("PSlit"));
+				set_prompt_lit(lookupvar("PSlit"), 0);
 				el_set(el, EL_SIGNAL, 1);
 				el_set(el, EL_SAFEREAD, 1);
 				el_set(el, EL_ALIAS_TEXT, alias_text, NULL);
@@ -211,7 +211,7 @@ histedit(void)
 }
 
 void
-set_prompt_lit(const char *lit_ch)
+set_prompt_lit(char *lit_ch, int flags __unused)
 {
 	wchar_t wc;
 
@@ -234,24 +234,31 @@ set_prompt_lit(const char *lit_ch)
 }
 
 void
-set_editrc(const char *fname)
+set_editrc(char *fname, int flags)
 {
 	INTOFF;
-	if (iflag && editing && el)
+	if (iflag && editing && el && !(flags & VUNSET))
 		el_source(el, fname);
 	INTON;
 }
 
 void
-sethistsize(const char *hs)
+sethistsize(char *hs, int flags)
 {
 	int histsize;
 	HistEvent he;
 
+	CTRACE(DBG_HISTORY, ("Set HISTSIZE=%s [%x] %s\n",
+	    (hs == NULL ? "''" : hs), flags, "!hist" + (hist != NULL)));
+
+	if (hs != NULL && *hs != '\0' && (flags & VUNSAFE) && !is_number(hs))
+		hs = NULL;
+
+	if (hs == NULL || *hs == '\0' || (flags & VUNSET) ||
+	    (histsize = number(hs)) < 0)
+		histsize = 100;
+
 	if (hist != NULL) {
-		if (hs == NULL || *hs == '\0' || !is_number(hs) ||
-		   (histsize = number(hs)) < 0)
-			histsize = 100;
 		INTOFF;
 		history(hist, &he, H_SETSIZE, histsize);
 		history(hist, &he, H_SETUNIQUE, 1);
@@ -260,10 +267,10 @@ sethistsize(const char *hs)
 }
 
 void
-setterm(const char *term)
+setterm(char *term, int flags __unused)
 {
 	INTOFF;
-	if (el != NULL && term != NULL)
+	if (el != NULL && term != NULL && *term != '\0')
 		if (el_set(el, EL_TERMINAL, term) != 0) {
 			outfmt(out2, "sh: Can't set terminal type %s\n", term);
 			outfmt(out2, "sh: Using dumb terminal settings.\n");

Index: src/bin/sh/myhistedit.h
diff -u src/bin/sh/myhistedit.h:1.14 src/bin/sh/myhistedit.h:1.15
--- src/bin/sh/myhistedit.h:1.14	Sun Aug 15 10:17:55 2021
+++ src/bin/sh/myhistedit.h	Fri Jul 12 07:30:30 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: myhistedit.h,v 1.14 2021/08/15 10:17:55 christos Exp $	*/
+/*	$NetBSD: myhistedit.h,v 1.15 2024/07/12 07:30:30 kre Exp $	*/
 
 /*-
  * Copyright (c) 1993
@@ -40,8 +40,8 @@ extern int displayhist;
 #include <filecomplete.h>
 
 void histedit(void);
-void sethistsize(const char *);
-void setterm(const char *);
+void sethistsize(char *, int);
+void setterm(char *, int);
 int inputrc(int, char **);
-void set_editrc(const char *);
-void set_prompt_lit(const char *);
+void set_editrc(char *, int);
+void set_prompt_lit(char *, int);

Index: src/bin/sh/var.c
diff -u src/bin/sh/var.c:1.82 src/bin/sh/var.c:1.83
--- src/bin/sh/var.c:1.82	Sun Sep 18 17:11:33 2022
+++ src/bin/sh/var.c	Fri Jul 12 07:30:30 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: var.c,v 1.82 2022/09/18 17:11:33 kre Exp $	*/
+/*	$NetBSD: var.c,v 1.83 2024/07/12 07:30:30 kre Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)var.c	8.3 (Berkeley) 5/4/95";
 #else
-__RCSID("$NetBSD: var.c,v 1.82 2022/09/18 17:11:33 kre Exp $");
+__RCSID("$NetBSD: var.c,v 1.83 2024/07/12 07:30:30 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -207,6 +207,7 @@ INCLUDE <time.h>
 INCLUDE "var.h"
 INCLUDE "version.h"
 MKINIT char **environ;
+MKINIT void setvareqsafe(char *, int);
 INIT {
 	char **envp;
 	char buf[64];
@@ -221,11 +222,11 @@ INIT {
 
 	/*
 	 * Import variables from the environment, which will
-	 * override anything initialised just previously.
+	 * if permitted, override anything initialised just previously.
 	 */
 	for (envp = environ ; *envp ; envp++) {
 		if (strchr(*envp, '=')) {
-			setvareq(*envp, VEXPORT|VTEXTFIXED);
+			setvareqsafe(*envp, VEXPORT|VTEXTFIXED|VUNSAFE);
 		}
 	}
 
@@ -396,6 +397,22 @@ setvarsafe(const char *name, const char 
 	return err;
 }
 
+void
+setvareqsafe(char *s, int flags)
+{
+	struct jmploc jmploc;
+	struct jmploc * const savehandler = handler;
+	volatile int e_s = errors_suppressed;
+
+	if (!setjmp(jmploc.loc)) {
+		handler = &jmploc;
+		errors_suppressed = 1;
+		setvareq(s, flags);
+	}
+	handler = savehandler;
+	errors_suppressed = e_s;
+}
+
 /*
  * Set the value of a variable.  The flags argument is ored with the
  * flags of the variable.  If val is NULL, the variable is unset.
@@ -477,7 +494,7 @@ setvareq(char *s, int flags)
 		INTOFF;
 
 		if (vp->func && !(vp->flags & VFUNCREF) && !(flags & VNOFUNC))
-			(*vp->func)(s + vp->name_len + 1);
+			(*vp->func)(s + vp->name_len + 1, flags);
 
 		if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
 			ckfree(vp->text);
@@ -489,7 +506,7 @@ setvareq(char *s, int flags)
 		if (vp->rfunc && (vp->flags & (VFUNCREF|VSPECIAL)) == VFUNCREF)
 			vp->rfunc = NULL;
 
-		vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
+		vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET|VUNSAFE);
 		if (flags & VNOEXPORT)
 			vp->flags &= ~VEXPORT;
 		if (flags & VDOEXPORT)
@@ -1178,7 +1195,8 @@ poplocalvars(void)
 			(void)unsetvar(vp->text, 0);
 		} else {
 			if (lvp->func && (lvp->flags & (VNOFUNC|VFUNCREF)) == 0)
-				(*lvp->func)(lvp->text + vp->name_len + 1);
+				(*lvp->func)(lvp->text + vp->name_len + 1, 
+				    lvp->flags);
 			if ((vp->flags & VTEXTFIXED) == 0)
 				ckfree(vp->text);
 			vp->flags = lvp->flags;
@@ -1268,8 +1286,8 @@ unsetvar(const char *s, int unexport)
 	if (unexport & 1) {
 		vp->flags &= ~VEXPORT;
 	} else {
-		if (vp->text[vp->name_len + 1] != '\0')
-			setvar(s, nullstr, 0);
+		if (vp->text[vp->name_len + 1] != '\0' || !(vp->flags & VUNSET))
+			setvar(s, nullstr, VUNSET);
 		if (!(unexport & 2))
 			vp->flags &= ~VEXPORT;
 		vp->flags |= VUNSET;

Index: src/bin/sh/var.h
diff -u src/bin/sh/var.h:1.39 src/bin/sh/var.h:1.40
--- src/bin/sh/var.h:1.39	Sun Sep 18 06:03:19 2022
+++ src/bin/sh/var.h	Fri Jul 12 07:30:30 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: var.h,v 1.39 2022/09/18 06:03:19 kre Exp $	*/
+/*	$NetBSD: var.h,v 1.40 2024/07/12 07:30:30 kre Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -48,6 +48,9 @@
 #define VSTRFIXED	0x0010	/* variable struct is statically allocated */
 #define VTEXTFIXED	0x0020	/* text is statically allocated */
 #define VSTACK		0x0040	/* text is allocated on the stack */
+
+#define VUNSAFE		0x0080	/* variable value imported from environment */
+
 #define VNOFUNC		0x0100	/* don't call the callback function */
 #define VFUNCREF	0x0200	/* the function is called on ref, not set */
 
@@ -59,7 +62,7 @@
 struct var;
 
 union var_func_union {		/* function to be called when:  */
-	void (*set_func)(const char *);		/* variable gets set/unset */
+	void (*set_func)(char *, int);		/* variable gets set/unset */
 	char*(*ref_func)(struct var *);		/* variable is referenced */
 };
 
@@ -124,6 +127,7 @@ extern int funclineabs;
 #define optindval()	(voptind.text + 7)
 #ifndef SMALL
 #define histsizeval()	(vhistsize.text + 9)
+#define histsizeflags()	(vhistsize.flags)
 #define termval()	(vterm.text + 5)
 #endif
 
@@ -146,6 +150,7 @@ int unsetvar(const char *, int);
 void choose_ps1(void);
 void setvar_invocation(int, char **);
 int setvarsafe(const char *, const char *, int);
+void setvareqsafe(char *, int);
 void print_quoted(const char *);
 int validname(const char *, int, int *);
 

Reply via email to