summaryrefslogtreecommitdiffstats
path: root/bin/sh
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2014-04-14 21:26:34 +0000
committerjilles <jilles@FreeBSD.org>2014-04-14 21:26:34 +0000
commit813864aadb85d56ff09c1dcac212be2307bba3ed (patch)
tree8263de031cf1c7ceb7cb3e0f527b28807f170218 /bin/sh
parent35cde107ba8c9d8dab202424e39a194305eb6524 (diff)
downloadFreeBSD-src-813864aadb85d56ff09c1dcac212be2307bba3ed.zip
FreeBSD-src-813864aadb85d56ff09c1dcac212be2307bba3ed.tar.gz
MFC r263777: sh: Fix possible memory leaks and double frees with unexpected
SIGINT.
Diffstat (limited to 'bin/sh')
-rw-r--r--bin/sh/alias.c7
-rw-r--r--bin/sh/exec.c1
-rw-r--r--bin/sh/expand.c3
-rw-r--r--bin/sh/redir.c21
-rw-r--r--bin/sh/var.c13
5 files changed, 31 insertions, 14 deletions
diff --git a/bin/sh/alias.c b/bin/sh/alias.c
index 9ebdcb5..21f3f44 100644
--- a/bin/sh/alias.c
+++ b/bin/sh/alias.c
@@ -180,6 +180,7 @@ printaliases(void)
int i, j;
struct alias **sorted, *ap;
+ INTOFF;
sorted = ckmalloc(aliases * sizeof(*sorted));
j = 0;
for (i = 0; i < ATABSIZE; i++)
@@ -187,9 +188,13 @@ printaliases(void)
if (*ap->name != '\0')
sorted[j++] = ap;
qsort(sorted, aliases, sizeof(*sorted), comparealiases);
- for (i = 0; i < aliases; i++)
+ for (i = 0; i < aliases; i++) {
printalias(sorted[i]);
+ if (int_pending())
+ break;
+ }
ckfree(sorted);
+ INTON;
}
int
diff --git a/bin/sh/exec.c b/bin/sh/exec.c
index 5f30ec6..e547e31 100644
--- a/bin/sh/exec.c
+++ b/bin/sh/exec.c
@@ -612,6 +612,7 @@ defun(const char *name, union node *func)
/*
* Delete a function if it exists.
+ * Called with interrupts off.
*/
int
diff --git a/bin/sh/expand.c b/bin/sh/expand.c
index 6c8b023..a126ca6 100644
--- a/bin/sh/expand.c
+++ b/bin/sh/expand.c
@@ -956,6 +956,7 @@ recordregion(int start, int end, int inquotes)
{
struct ifsregion *ifsp;
+ INTOFF;
if (ifslastp == NULL) {
ifsp = &ifsfirst;
} else {
@@ -963,6 +964,7 @@ recordregion(int start, int end, int inquotes)
&& ifslastp->inquotes == inquotes) {
/* extend previous area */
ifslastp->endoff = end;
+ INTON;
return;
}
ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
@@ -973,6 +975,7 @@ recordregion(int start, int end, int inquotes)
ifslastp->begoff = start;
ifslastp->endoff = end;
ifslastp->inquotes = inquotes;
+ INTON;
}
diff --git a/bin/sh/redir.c b/bin/sh/redir.c
index 647b10a..6127e86 100644
--- a/bin/sh/redir.c
+++ b/bin/sh/redir.c
@@ -92,6 +92,13 @@ static int openhere(union node *);
* undone by calling popredir. If the REDIR_BACKQ flag is set, then the
* standard output, and the standard error if it becomes a duplicate of
* stdout, is saved in memory.
+*
+ * We suppress interrupts so that we won't leave open file
+ * descriptors around. Because the signal handler remains
+ * installed and we do not use system call restart, interrupts
+ * will still abort blocking opens such as fifos (they will fail
+ * with EINTR). There is, however, a race condition if an interrupt
+ * arrives after INTOFF and before open blocks.
*/
void
@@ -103,6 +110,7 @@ redirect(union node *redir, int flags)
int fd;
char memory[10]; /* file descriptors to write to memory */
+ INTOFF;
for (i = 10 ; --i >= 0 ; )
memory[i] = 0;
memory[1] = flags & REDIR_BACKQ;
@@ -139,11 +147,14 @@ redirect(union node *redir, int flags)
INTON;
}
openredirect(n, memory);
+ INTON;
+ INTOFF;
}
if (memory[1])
out1 = &memout;
if (memory[2])
out2 = &memout;
+ INTON;
}
@@ -156,15 +167,6 @@ openredirect(union node *redir, char memory[10])
int f;
int e;
- /*
- * We suppress interrupts so that we won't leave open file
- * descriptors around. Because the signal handler remains
- * installed and we do not use system call restart, interrupts
- * will still abort blocking opens such as fifos (they will fail
- * with EINTR). There is, however, a race condition if an interrupt
- * arrives after INTOFF and before open blocks.
- */
- INTOFF;
memory[fd] = 0;
switch (redir->nfile.type) {
case NFROM:
@@ -237,7 +239,6 @@ movefd:
default:
abort();
}
- INTON;
}
diff --git a/bin/sh/var.c b/bin/sh/var.c
index 1fd8c77..6c0685f 100644
--- a/bin/sh/var.c
+++ b/bin/sh/var.c
@@ -249,6 +249,7 @@ setvar(const char *name, const char *val, int flags)
vallen = strlen(val);
len += vallen;
}
+ INTOFF;
nameeq = ckmalloc(len);
memcpy(nameeq, name, namelen);
nameeq[namelen] = '=';
@@ -257,6 +258,7 @@ setvar(const char *name, const char *val, int flags)
else
nameeq[namelen + 1] = '\0';
setvareq(nameeq, flags);
+ INTON;
}
static int
@@ -289,6 +291,7 @@ change_env(const char *s, int set)
char *eqp;
char *ss;
+ INTOFF;
ss = savestr(s);
if ((eqp = strchr(ss, '=')) != NULL)
*eqp = '\0';
@@ -297,6 +300,7 @@ change_env(const char *s, int set)
else
(void) unsetenv(ss);
ckfree(ss);
+ INTON;
return;
}
@@ -359,13 +363,13 @@ setvareq(char *s, int flags)
/* not found */
if (flags & VNOSET)
return;
+ INTOFF;
vp = ckmalloc(sizeof (*vp));
vp->flags = flags;
vp->text = s;
vp->name_len = nlen;
vp->next = *vpp;
vp->func = NULL;
- INTOFF;
*vpp = vp;
if ((vp->flags & VEXPORT) && localevar(s)) {
change_env(s, 1);
@@ -773,6 +777,7 @@ poplocalvars(void)
struct localvar *lvp;
struct var *vp;
+ INTOFF;
while ((lvp = localvars) != NULL) {
localvars = lvp->next;
vp = lvp->vp;
@@ -790,6 +795,7 @@ poplocalvars(void)
}
ckfree(lvp);
}
+ INTON;
}
@@ -828,18 +834,21 @@ unsetcmd(int argc __unused, char **argv __unused)
if (flg_func == 0 && flg_var == 0)
flg_var = 1;
+ INTOFF;
for (ap = argptr; *ap ; ap++) {
if (flg_func)
ret |= unsetfunc(*ap);
if (flg_var)
ret |= unsetvar(*ap);
}
+ INTON;
return ret;
}
/*
* Unset the specified variable.
+ * Called with interrupts off.
*/
int
@@ -853,7 +862,6 @@ unsetvar(const char *s)
return (0);
if (vp->flags & VREADONLY)
return (1);
- INTOFF;
if (vp->text[vp->name_len + 1] != '\0')
setvar(s, nullstr, 0);
if ((vp->flags & VEXPORT) && localevar(vp->text)) {
@@ -869,7 +877,6 @@ unsetvar(const char *s)
*vpp = vp->next;
ckfree(vp);
}
- INTON;
return (0);
}
OpenPOWER on IntegriCloud