aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2011-03-11 11:07:42 +0800
committermaximilian attems <max@stro.at>2011-06-03 18:44:13 +0200
commit0760036ff9167812c9498ed5a519147ea952fa11 (patch)
tree582e1533aa5f698debacd5214c18bb112c66686e
parent0213c2371a01554a56d6c2a6c5f8a5f5be9b3a9c (diff)
downloadklibc-0760036ff9167812c9498ed5a519147ea952fa11.tar.gz
[klibc] [BUILTIN] Fix backslash handling in read(1)
The new read(1) implementation incorrectly assumes that ifsbreakup ignores characters escaped by CTLESC. As such it fails to handle backslashes except for escaping newlines. This patch makes it use recordregion for every part that isn't escaped by a backslash. Reported-by: Jilles Tjoelker <jilles@stack.nl> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> [ merge fixups -maks ] Signed-off-by: maximilian attems <max@stro.at>
-rw-r--r--usr/dash/expand.c1
-rw-r--r--usr/dash/miscbltin.c38
-rw-r--r--usr/dash/mystring.c1
-rw-r--r--usr/dash/mystring.h1
4 files changed, 28 insertions, 13 deletions
diff --git a/usr/dash/expand.c b/usr/dash/expand.c
index 900d8c7e6ae2b..e177ee6114a09 100644
--- a/usr/dash/expand.c
+++ b/usr/dash/expand.c
@@ -1597,7 +1597,6 @@ char *
_rmescapes(char *str, int flag)
{
char *p, *q, *r;
- static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
unsigned inquotes;
int notescaped;
int globbing;
diff --git a/usr/dash/miscbltin.c b/usr/dash/miscbltin.c
index f2acce8a03a94..ece66ced0220c 100644
--- a/usr/dash/miscbltin.c
+++ b/usr/dash/miscbltin.c
@@ -72,21 +72,22 @@
* @param len length of line including trailing '\0'
*/
static void
-readcmd_handle_line(char *line, char **ap, size_t len)
+readcmd_handle_line(char *s, char **ap)
{
struct arglist arglist;
struct strlist *sl;
- char *s, *backup;
+ char *backup;
+ char *line;
/* ifsbreakup will fiddle with stack region... */
- s = grabstackstr(line + len);
+ line = stackblock();
+ s = grabstackstr(s);
/* need a copy, so that delimiters aren't lost
* in case there are more fields than variables */
backup = sstrdup(line);
arglist.lastp = &arglist.list;
- recordregion(0, len - 1, 0);
ifsbreakup(s, &arglist);
*arglist.lastp = NULL;
@@ -138,11 +139,12 @@ int
readcmd(int argc, char **argv)
{
char **ap;
- int backslash;
char c;
int rflag;
char *prompt;
char *p;
+ int startloc;
+ int newloc;
int status;
int timeout;
int i;
@@ -180,8 +182,8 @@ readcmd(int argc, char **argv)
}
if (*(ap = argptr) == NULL)
sh_error("arg count");
+
status = 0;
- backslash = 0;
if (timeout) {
gettimeofday(&t0, NULL);
@@ -194,6 +196,9 @@ readcmd(int argc, char **argv)
ts.tv_sec += t0.tv_sec;
}
STARTSTACKSTR(p);
+
+ goto start;
+
for (;;) {
if (timeout) {
gettimeofday(&t1, NULL);
@@ -233,26 +238,35 @@ readcmd(int argc, char **argv)
}
if (c == '\0')
continue;
- if (backslash || c == CTLESC) {
+ if (newloc >= startloc) {
if (c == '\n')
goto resetbs;
- STPUTC(CTLESC, p);
goto put;
}
if (!rflag && c == '\\') {
- backslash++;
+ newloc = p - (char *)stackblock();
continue;
}
if (c == '\n')
break;
put:
- STPUTC(c, p);
+ CHECKSTRSPACE(2, p);
+ if (strchr(qchars, c))
+ USTPUTC(CTLESC, p);
+ USTPUTC(c, p);
+
+ if (newloc >= startloc) {
resetbs:
- backslash = 0;
+ recordregion(startloc, newloc, 0);
+start:
+ startloc = p - (char *)stackblock();
+ newloc = startloc - 1;
+ }
}
out:
+ recordregion(startloc, p - (char *)stackblock(), 0);
STACKSTRNUL(p);
- readcmd_handle_line(stackblock(), ap, p + 1 - (char *)stackblock());
+ readcmd_handle_line(p + 1, ap);
return status;
}
diff --git a/usr/dash/mystring.c b/usr/dash/mystring.c
index ce48c825c3e0b..bbb6b776ce996 100644
--- a/usr/dash/mystring.c
+++ b/usr/dash/mystring.c
@@ -62,6 +62,7 @@ const char spcstr[] = " ";
const char snlfmt[] = "%s\n";
const char dolatstr[] = { CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=',
CTLQUOTEMARK, '\0' };
+const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
const char illnum[] = "Illegal number: %s";
const char homestr[] = "HOME";
diff --git a/usr/dash/mystring.h b/usr/dash/mystring.h
index 2e0540a1b4763..352252376abfe 100644
--- a/usr/dash/mystring.h
+++ b/usr/dash/mystring.h
@@ -41,6 +41,7 @@ extern const char snlfmt[];
extern const char spcstr[];
extern const char dolatstr[];
#define DOLATSTRLEN 6
+extern const char qchars[];
extern const char illnum[];
extern const char homestr[];