aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-07-29 19:57:28 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2017-07-29 19:57:28 +0200
commita732898fdd9748b966da228ee8bbbc148c3c10c9 (patch)
tree6a77b07cc830a0bec815b27927a4af85846d1666
parent170f93ef1bc49a9e4c68f85f5245416767c1916f (diff)
downloadbusybox-w32-a732898fdd9748b966da228ee8bbbc148c3c10c9.tar.gz
busybox-w32-a732898fdd9748b966da228ee8bbbc148c3c10c9.tar.bz2
busybox-w32-a732898fdd9748b966da228ee8bbbc148c3c10c9.zip
ash: [PARSER] Removed noexpand/length check on eofmark
Upstream comment: Date: Sun, 11 Nov 2007 14:21:23 +0800 [PARSER] Removed noexpand/length check on eofmark On Tue, Oct 30, 2007 at 04:23:35AM +0000, Oleg Verych wrote: > > } 8<<"" > ====================== Actually this (the empty delim) only works with dash by accident. I've tried bash and pdksh and they both terminate on the first empty line which is what you would expect rather than EOF. The real Korn shell does something completely different. I've fixed this in dash to conform to bash/pdksh. > In [0] it's stated, that delimiter isn't evaluated (expanded), only > quoiting must be checked. That if() seems to be completely bogus. OK I agree. The reason it was there is because the parser would have already replaced the dollar sign by an internal representation. I've fixed it properly with this patch. Test case: cat <<- $a OK $a cat <<- "" OK echo OK Old result: dash: Syntax error: Illegal eof marker for << redirection OK echo OK New result: OK OK OK function old new delta parsefname 227 152 -75 readtoken1 2819 2651 -168 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-243) Total: -243 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/ash.c111
-rw-r--r--shell/ash_test/ash-heredoc/heredoc_empty.right3
-rwxr-xr-xshell/ash_test/ash-heredoc/heredoc_empty.tests8
3 files changed, 52 insertions, 70 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 02b21510e..2bfec83e6 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -9991,6 +9991,7 @@ static smallint checkkwd;
9991#define CHKALIAS 0x1 9991#define CHKALIAS 0x1
9992#define CHKKWD 0x2 9992#define CHKKWD 0x2
9993#define CHKNL 0x4 9993#define CHKNL 0x4
9994#define CHKEOFMARK 0x8
9994 9995
9995/* 9996/*
9996 * Push a string back onto the input at this current parsefile level. 9997 * Push a string back onto the input at this current parsefile level.
@@ -10303,31 +10304,6 @@ pgetc_without_PEOA(void)
10303#endif 10304#endif
10304 10305
10305/* 10306/*
10306 * Read a line from the script.
10307 */
10308static char *
10309pfgets(char *line, int len)
10310{
10311 char *p = line;
10312 int nleft = len;
10313 int c;
10314
10315 while (--nleft > 0) {
10316 c = pgetc_without_PEOA();
10317 if (c == PEOF) {
10318 if (p == line)
10319 return NULL;
10320 break;
10321 }
10322 *p++ = c;
10323 if (c == '\n')
10324 break;
10325 }
10326 *p = '\0';
10327 return line;
10328}
10329
10330/*
10331 * Undo a call to pgetc. Only two characters may be pushed back. 10307 * Undo a call to pgetc. Only two characters may be pushed back.
10332 * PEOF may be pushed back. 10308 * PEOF may be pushed back.
10333 */ 10309 */
@@ -10960,8 +10936,6 @@ raise_error_unexpected_syntax(int token)
10960 /* NOTREACHED */ 10936 /* NOTREACHED */
10961} 10937}
10962 10938
10963#define EOFMARKLEN 79
10964
10965/* parsing is heavily cross-recursive, need these forward decls */ 10939/* parsing is heavily cross-recursive, need these forward decls */
10966static union node *andor(void); 10940static union node *andor(void);
10967static union node *pipeline(void); 10941static union node *pipeline(void);
@@ -11141,43 +11115,22 @@ fixredir(union node *n, const char *text, int err)
11141 } 11115 }
11142} 11116}
11143 11117
11144/*
11145 * Returns true if the text contains nothing to expand (no dollar signs
11146 * or backquotes).
11147 */
11148static int
11149noexpand(const char *text)
11150{
11151 unsigned char c;
11152
11153 while ((c = *text++) != '\0') {
11154 if (c == CTLQUOTEMARK)
11155 continue;
11156 if (c == CTLESC)
11157 text++;
11158 else if (SIT(c, BASESYNTAX) == CCTL)
11159 return 0;
11160 }
11161 return 1;
11162}
11163
11164static void 11118static void
11165parsefname(void) 11119parsefname(void)
11166{ 11120{
11167 union node *n = redirnode; 11121 union node *n = redirnode;
11168 11122
11123 if (n->type == NHERE)
11124 checkkwd = CHKEOFMARK;
11169 if (readtoken() != TWORD) 11125 if (readtoken() != TWORD)
11170 raise_error_unexpected_syntax(-1); 11126 raise_error_unexpected_syntax(-1);
11171 if (n->type == NHERE) { 11127 if (n->type == NHERE) {
11172 struct heredoc *here = heredoc; 11128 struct heredoc *here = heredoc;
11173 struct heredoc *p; 11129 struct heredoc *p;
11174 int i;
11175 11130
11176 if (quoteflag == 0) 11131 if (quoteflag == 0)
11177 n->type = NXHERE; 11132 n->type = NXHERE;
11178 TRACE(("Here document %d\n", n->type)); 11133 TRACE(("Here document %d\n", n->type));
11179 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
11180 raise_error_syntax("illegal eof marker for << redirection");
11181 rmescapes(wordtext, 0); 11134 rmescapes(wordtext, 0);
11182 here->eofmark = wordtext; 11135 here->eofmark = wordtext;
11183 here->next = NULL; 11136 here->next = NULL;
@@ -11593,7 +11546,6 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
11593 /* c parameter is an unsigned char or PEOF or PEOA */ 11546 /* c parameter is an unsigned char or PEOF or PEOA */
11594 char *out; 11547 char *out;
11595 size_t len; 11548 size_t len;
11596 char line[EOFMARKLEN + 1];
11597 struct nodelist *bqlist; 11549 struct nodelist *bqlist;
11598 smallint quotef; 11550 smallint quotef;
11599 smallint dblquote; 11551 smallint dblquote;
@@ -11816,6 +11768,9 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
11816 */ 11768 */
11817checkend: { 11769checkend: {
11818 if (eofmark) { 11770 if (eofmark) {
11771 int markloc;
11772 char *p;
11773
11819#if ENABLE_ASH_ALIAS 11774#if ENABLE_ASH_ALIAS
11820 if (c == PEOA) 11775 if (c == PEOA)
11821 c = pgetc_without_PEOA(); 11776 c = pgetc_without_PEOA();
@@ -11825,27 +11780,42 @@ checkend: {
11825 c = pgetc_without_PEOA(); 11780 c = pgetc_without_PEOA();
11826 } 11781 }
11827 } 11782 }
11828 if (c == *eofmark) { 11783
11829 if (pfgets(line, sizeof(line)) != NULL) { 11784 markloc = out - (char *)stackblock();
11830 char *p, *q; 11785 for (p = eofmark; STPUTC(c, out), *p; p++) {
11831 int cc; 11786 if (c != *p)
11832 11787 goto more_heredoc;
11833 p = line; 11788
11834 for (q = eofmark + 1;; p++, q++) { 11789 c = pgetc_without_PEOA();
11835 cc = *p; 11790 }
11836 if (cc == '\n') 11791
11837 cc = 0; 11792 if (c == '\n' || c == PEOF) {
11838 if (!*q || cc != *q) 11793 c = PEOF;
11839 break; 11794 g_parsefile->linno++;
11840 } 11795 needprompt = doprompt;
11841 if (cc == *q) { 11796 } else {
11842 c = PEOF; 11797 int len_here;
11843 nlnoprompt(); 11798
11844 } else { 11799 more_heredoc:
11845 pushstring(line, NULL); 11800 p = (char *)stackblock() + markloc + 1;
11801 len_here = out - p;
11802
11803 if (len_here) {
11804 len_here -= (c >= PEOF);
11805 c = p[-1];
11806
11807 if (len_here) {
11808 char *str;
11809
11810 str = alloca(len_here + 1);
11811 *(char *)mempcpy(str, p, len_here) = '\0';
11812
11813 pushstring(str, NULL);
11846 } 11814 }
11847 } 11815 }
11848 } 11816 }
11817
11818 STADJUST((char *)stackblock() + markloc - out, out);
11849 } 11819 }
11850 goto checkend_return; 11820 goto checkend_return;
11851} 11821}
@@ -11939,7 +11909,8 @@ parsesub: {
11939 int typeloc; 11909 int typeloc;
11940 11910
11941 c = pgetc_eatbnl(); 11911 c = pgetc_eatbnl();
11942 if (c > 255 /* PEOA or PEOF */ 11912 if ((checkkwd & CHKEOFMARK)
11913 || c > 255 /* PEOA or PEOF */
11943 || (c != '(' && c != '{' && !is_name(c) && !is_special(c)) 11914 || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11944 ) { 11915 ) {
11945#if BASH_DOLLAR_SQUOTE 11916#if BASH_DOLLAR_SQUOTE
diff --git a/shell/ash_test/ash-heredoc/heredoc_empty.right b/shell/ash_test/ash-heredoc/heredoc_empty.right
new file mode 100644
index 000000000..0eabe3671
--- /dev/null
+++ b/shell/ash_test/ash-heredoc/heredoc_empty.right
@@ -0,0 +1,3 @@
1OK
2OK
3OK
diff --git a/shell/ash_test/ash-heredoc/heredoc_empty.tests b/shell/ash_test/ash-heredoc/heredoc_empty.tests
new file mode 100755
index 000000000..3629bc6d1
--- /dev/null
+++ b/shell/ash_test/ash-heredoc/heredoc_empty.tests
@@ -0,0 +1,8 @@
1unset a
2cat <<- $a
3 OK
4$a
5cat <<- ""
6 OK
7
8echo OK