summaryrefslogtreecommitdiffstats
path: root/bin/sh
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2010-12-26 13:25:47 +0000
committerjilles <jilles@FreeBSD.org>2010-12-26 13:25:47 +0000
commitde73f385a5709ba788137d94801ead1014f1c5f0 (patch)
tree02dc00ec14f40f9ed9b75e0e6b62988d28b2ba9f /bin/sh
parent290c1ef87ffbfdb591c830fd2874a87241390022 (diff)
downloadFreeBSD-src-de73f385a5709ba788137d94801ead1014f1c5f0.zip
FreeBSD-src-de73f385a5709ba788137d94801ead1014f1c5f0.tar.gz
sh: Allow arbitrary large numbers in CHECKSTRSPACE.
Reduce "stack string" API somewhat and simplify code. Add a check for integer overflow of the "stack string" length (probably incomplete).
Diffstat (limited to 'bin/sh')
-rw-r--r--bin/sh/exec.c5
-rw-r--r--bin/sh/expand.c7
-rw-r--r--bin/sh/memalloc.c35
-rw-r--r--bin/sh/memalloc.h5
-rw-r--r--bin/sh/parser.c3
5 files changed, 30 insertions, 25 deletions
diff --git a/bin/sh/exec.c b/bin/sh/exec.c
index e104b63..e916080 100644
--- a/bin/sh/exec.c
+++ b/bin/sh/exec.c
@@ -190,9 +190,8 @@ padvance(const char **path, const char *name)
for (p = start; *p && *p != ':' && *p != '%'; p++)
; /* nothing */
len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
- while (stackblocksize() < len)
- growstackblock();
- q = stackblock();
+ STARTSTACKSTR(q);
+ CHECKSTRSPACE(len, q);
if (p != start) {
memcpy(q, start, p - start);
q += p - start;
diff --git a/bin/sh/expand.c b/bin/sh/expand.c
index a0b172e..b03cc3b 100644
--- a/bin/sh/expand.c
+++ b/bin/sh/expand.c
@@ -502,13 +502,14 @@ expbackq(union node *cmd, int quoted, int flag)
if (lastc == '\n') {
nnl++;
} else {
+ CHECKSTRSPACE(nnl + 2, dest);
while (nnl > 0) {
nnl--;
- STPUTC('\n', dest);
+ USTPUTC('\n', dest);
}
if (quotes && syntax[(int)lastc] == CCTL)
- STPUTC(CTLESC, dest);
- STPUTC(lastc, dest);
+ USTPUTC(CTLESC, dest);
+ USTPUTC(lastc, dest);
}
}
}
diff --git a/bin/sh/memalloc.c b/bin/sh/memalloc.c
index 47b5b83..0567009 100644
--- a/bin/sh/memalloc.c
+++ b/bin/sh/memalloc.c
@@ -218,8 +218,8 @@ popstackmark(struct stackmark *mark)
* part of the block that has been used.
*/
-void
-growstackblock(void)
+static void
+growstackblock(int min)
{
char *p;
int newlen;
@@ -229,8 +229,15 @@ growstackblock(void)
struct stack_block *oldstackp;
struct stackmark *xmark;
- newlen = (stacknleft == 0) ? MINSIZE : stacknleft * 2 + 100;
- newlen = ALIGN(newlen);
+ if (min < stacknleft)
+ min = stacknleft;
+ if (newlen >= INT_MAX / 2 - ALIGN(sizeof(struct stack_block)))
+ error("Out of space");
+ min += stacknleft;
+ min += ALIGN(sizeof(struct stack_block));
+ newlen = 512;
+ while (newlen < min)
+ newlen <<= 1;
oldspace = stacknxt;
oldlen = stacknleft;
@@ -257,6 +264,7 @@ growstackblock(void)
}
INTON;
} else {
+ newlen -= ALIGN(sizeof(struct stack_block));
p = stalloc(newlen);
if (oldlen != 0)
memcpy(p, oldspace, oldlen);
@@ -295,9 +303,9 @@ grabstackblock(int len)
*/
static char *
-growstrstackblock(int n)
+growstrstackblock(int n, int min)
{
- growstackblock();
+ growstackblock(min);
sstrnleft = stackblocksize() - n;
return stackblock() + n;
}
@@ -308,7 +316,7 @@ growstackstr(void)
int len;
len = stackblocksize();
- return growstrstackblock(len);
+ return (growstrstackblock(len, 0));
}
@@ -317,12 +325,12 @@ growstackstr(void)
*/
char *
-makestrspace(void)
+makestrspace(int min)
{
int len;
len = stackblocksize() - sstrnleft;
- return growstrstackblock(len);
+ return (growstrstackblock(len, min));
}
@@ -339,11 +347,10 @@ ungrabstackstr(char *s, char *p)
char *
stputbin(const char *data, int len, char *p)
{
- int i;
-
- for (i = 0; i < len; i++)
- STPUTC(data[i], p);
- return (p);
+ CHECKSTRSPACE(len, p);
+ memcpy(p, data, len);
+ sstrnleft -= len;
+ return (p + len);
}
char *
diff --git a/bin/sh/memalloc.h b/bin/sh/memalloc.h
index da23a95..fcdd5ba 100644
--- a/bin/sh/memalloc.h
+++ b/bin/sh/memalloc.h
@@ -55,10 +55,9 @@ pointer stalloc(int);
void stunalloc(pointer);
void setstackmark(struct stackmark *);
void popstackmark(struct stackmark *);
-void growstackblock(void);
void grabstackblock(int);
char *growstackstr(void);
-char *makestrspace(void);
+char *makestrspace(int);
void ungrabstackstr(char *, char *);
char *stputbin(const char *data, int len, char *p);
char *stputs(const char *data, char *p);
@@ -69,7 +68,7 @@ char *stputs(const char *data, char *p);
#define stackblocksize() stacknleft
#define STARTSTACKSTR(p) p = stackblock(), sstrnleft = stackblocksize()
#define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), --sstrnleft, *p++ = (c)))
-#define CHECKSTRSPACE(n, p) { if (sstrnleft < n) p = makestrspace(); }
+#define CHECKSTRSPACE(n, p) { if (sstrnleft < n) p = makestrspace(n); }
#define USTPUTC(c, p) (--sstrnleft, *p++ = (c))
/*
* STACKSTRNUL's use is where we want to be able to turn a stack
diff --git a/bin/sh/parser.c b/bin/sh/parser.c
index e292ad0..4a2ffa4 100644
--- a/bin/sh/parser.c
+++ b/bin/sh/parser.c
@@ -1093,9 +1093,8 @@ done:
popfile();
tokpushback = 0;
}
- while (stackblocksize() <= savelen)
- growstackblock();
STARTSTACKSTR(out);
+ CHECKSTRSPACE(savelen + 1, out);
INTOFF;
if (str) {
memcpy(out, str, savelen);
OpenPOWER on IntegriCloud