diff options
author | jilles <jilles@FreeBSD.org> | 2010-12-26 13:25:47 +0000 |
---|---|---|
committer | jilles <jilles@FreeBSD.org> | 2010-12-26 13:25:47 +0000 |
commit | de73f385a5709ba788137d94801ead1014f1c5f0 (patch) | |
tree | 02dc00ec14f40f9ed9b75e0e6b62988d28b2ba9f | |
parent | 290c1ef87ffbfdb591c830fd2874a87241390022 (diff) | |
download | FreeBSD-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).
-rw-r--r-- | bin/sh/exec.c | 5 | ||||
-rw-r--r-- | bin/sh/expand.c | 7 | ||||
-rw-r--r-- | bin/sh/memalloc.c | 35 | ||||
-rw-r--r-- | bin/sh/memalloc.h | 5 | ||||
-rw-r--r-- | bin/sh/parser.c | 3 |
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); |