summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2010-10-13 23:29:09 +0000
committerobrien <obrien@FreeBSD.org>2010-10-13 23:29:09 +0000
commit04029327665ca3c97ae07cae698d5df760f2b68e (patch)
tree21a2e1390b3cbd0e8029830cf4195a75dba0d1e7
parent256615c9b37c8059eef0e130fbf813607a5396a8 (diff)
downloadFreeBSD-src-04029327665ca3c97ae07cae698d5df760f2b68e.zip
FreeBSD-src-04029327665ca3c97ae07cae698d5df760f2b68e.tar.gz
Do not assume in growstackstr() that a "precious" character will be
immediately written into the stack after the call. Instead let the caller manage the "space left". Previously, growstackstr()'s assumption causes problems with STACKSTRNUL() where we want to be able to turn a stack into a C string, and later pretend the NUL is not there. This fixes a bug in STACKSTRNUL() (that grew the stack) where: 1. STADJUST() called after a STACKSTRNUL() results in an improper adjust. This can be seen in ${var%pattern} and ${var%%pattern} evaluation. 2. Memory leak in STPUTC() called after a STACKSTRNUL(). Reviewed by: jilles
-rw-r--r--bin/sh/histedit.c2
-rw-r--r--bin/sh/memalloc.c17
-rw-r--r--bin/sh/memalloc.h9
-rw-r--r--tools/regression/bin/sh/expansion/trim4.015
4 files changed, 34 insertions, 9 deletions
diff --git a/bin/sh/histedit.c b/bin/sh/histedit.c
index 7773ad8..dab69f1 100644
--- a/bin/sh/histedit.c
+++ b/bin/sh/histedit.c
@@ -418,7 +418,7 @@ fc_replace(const char *s, char *p, char *r)
} else
STPUTC(*s++, dest);
}
- STACKSTRNUL(dest);
+ STPUTC('\0', dest);
dest = grabstackstr(dest);
return (dest);
diff --git a/bin/sh/memalloc.c b/bin/sh/memalloc.c
index 01bddb2..9158719 100644
--- a/bin/sh/memalloc.c
+++ b/bin/sh/memalloc.c
@@ -295,6 +295,13 @@ grabstackblock(int len)
* is space for at least one character.
*/
+static char *
+growstrstackblock(int n)
+{
+ growstackblock();
+ sstrnleft = stackblocksize() - n;
+ return stackblock() + n;
+}
char *
growstackstr(void)
@@ -304,12 +311,10 @@ growstackstr(void)
len = stackblocksize();
if (herefd >= 0 && len >= 1024) {
xwrite(herefd, stackblock(), len);
- sstrnleft = len - 1;
+ sstrnleft = len;
return stackblock();
}
- growstackblock();
- sstrnleft = stackblocksize() - len - 1;
- return stackblock() + len;
+ return growstrstackblock(len);
}
@@ -323,9 +328,7 @@ makestrspace(void)
int len;
len = stackblocksize() - sstrnleft;
- growstackblock();
- sstrnleft = stackblocksize() - len;
- return stackblock() + len;
+ return growstrstackblock(len);
}
diff --git a/bin/sh/memalloc.h b/bin/sh/memalloc.h
index 187d4c8..563927a 100644
--- a/bin/sh/memalloc.h
+++ b/bin/sh/memalloc.h
@@ -67,9 +67,16 @@ void ungrabstackstr(char *, char *);
#define stackblock() stacknxt
#define stackblocksize() stacknleft
#define STARTSTACKSTR(p) p = stackblock(), sstrnleft = stackblocksize()
-#define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
+#define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), --sstrnleft, *p++ = (c)))
#define CHECKSTRSPACE(n, p) { if (sstrnleft < n) p = makestrspace(); }
#define USTPUTC(c, p) (--sstrnleft, *p++ = (c))
+/*
+ * STACKSTRNUL's use is where we want to be able to turn a stack
+ * (non-sentinel, character counting string) into a C string,
+ * and later pretend the NUL is not there.
+ * Note: Because of STACKSTRNUL's semantics, STACKSTRNUL cannot be used
+ * on a stack that will grabstackstr()ed.
+ */
#define STACKSTRNUL(p) (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
#define STUNPUTC(p) (++sstrnleft, --p)
#define STTOPC(p) p[-1]
diff --git a/tools/regression/bin/sh/expansion/trim4.0 b/tools/regression/bin/sh/expansion/trim4.0
new file mode 100644
index 0000000..1000bd3
--- /dev/null
+++ b/tools/regression/bin/sh/expansion/trim4.0
@@ -0,0 +1,15 @@
+# $FreeBSD$
+
+v1=/homes/SOME_USER
+v2=
+v3=C123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+
+# Trigger bug in VSTRIMRIGHT processing STADJUST() call in expand.c:subevalvar()
+while [ ${#v2} -lt 2000 ]; do
+ v4="${v2} ${v1%/*} $v3"
+ if [ ${#v4} -ne $((${#v2} + ${#v3} + 8)) ]; then
+ echo bad: ${#v4} -ne $((${#v2} + ${#v3} + 8))
+ fi
+ v2=x$v2
+ v3=y$v3
+done
OpenPOWER on IntegriCloud