hush: fix backslash and terminator handling in <<[-]["]heredoc["]
function old new delta parse_stream 2339 2395 +56 expand_pseudo_dquoted 104 118 +14 parse_stream_dquoted 296 300 +4 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/0 up/down: 74/0) Total: 74 bytes Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
This commit is contained in:
parent
c49d2d9793
commit
77b32ccbf2
16
shell/hush.c
16
shell/hush.c
@ -3162,17 +3162,20 @@ static int redirect_opt_num(o_string *o)
|
|||||||
static char *fetch_till_str(o_string *as_string,
|
static char *fetch_till_str(o_string *as_string,
|
||||||
struct in_str *input,
|
struct in_str *input,
|
||||||
const char *word,
|
const char *word,
|
||||||
int skip_tabs)
|
int heredoc_flags)
|
||||||
{
|
{
|
||||||
o_string heredoc = NULL_O_STRING;
|
o_string heredoc = NULL_O_STRING;
|
||||||
int past_EOL = 0;
|
int past_EOL = 0;
|
||||||
|
int prev = 0; /* not \ */
|
||||||
int ch;
|
int ch;
|
||||||
|
|
||||||
goto jump_in;
|
goto jump_in;
|
||||||
while (1) {
|
while (1) {
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
nommu_addchr(as_string, ch);
|
nommu_addchr(as_string, ch);
|
||||||
if (ch == '\n') {
|
if (ch == '\n'
|
||||||
|
&& ((heredoc_flags & HEREDOC_QUOTED) || prev != '\\')
|
||||||
|
) {
|
||||||
if (strcmp(heredoc.data + past_EOL, word) == 0) {
|
if (strcmp(heredoc.data + past_EOL, word) == 0) {
|
||||||
heredoc.data[past_EOL] = '\0';
|
heredoc.data[past_EOL] = '\0';
|
||||||
debug_printf_parse("parsed heredoc '%s'\n", heredoc.data);
|
debug_printf_parse("parsed heredoc '%s'\n", heredoc.data);
|
||||||
@ -3185,7 +3188,7 @@ static char *fetch_till_str(o_string *as_string,
|
|||||||
do {
|
do {
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
nommu_addchr(as_string, ch);
|
nommu_addchr(as_string, ch);
|
||||||
} while (skip_tabs && ch == '\t');
|
} while ((heredoc_flags & HEREDOC_SKIPTABS) && ch == '\t');
|
||||||
} while (ch == '\n');
|
} while (ch == '\n');
|
||||||
}
|
}
|
||||||
if (ch == EOF) {
|
if (ch == EOF) {
|
||||||
@ -3194,6 +3197,7 @@ static char *fetch_till_str(o_string *as_string,
|
|||||||
}
|
}
|
||||||
o_addchr(&heredoc, ch);
|
o_addchr(&heredoc, ch);
|
||||||
nommu_addchr(as_string, ch);
|
nommu_addchr(as_string, ch);
|
||||||
|
prev = ch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3223,7 +3227,7 @@ static int fetch_heredocs(int heredoc_cnt, struct parse_context *ctx, struct in_
|
|||||||
redir->rd_type = REDIRECT_HEREDOC2;
|
redir->rd_type = REDIRECT_HEREDOC2;
|
||||||
/* redir->rd_dup is (ab)used to indicate <<- */
|
/* redir->rd_dup is (ab)used to indicate <<- */
|
||||||
p = fetch_till_str(&ctx->as_string, input,
|
p = fetch_till_str(&ctx->as_string, input,
|
||||||
redir->rd_filename, redir->rd_dup & HEREDOC_SKIPTABS);
|
redir->rd_filename, redir->rd_dup);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
syntax_error("unexpected EOF in here document");
|
syntax_error("unexpected EOF in here document");
|
||||||
return 1;
|
return 1;
|
||||||
@ -3778,8 +3782,9 @@ static int parse_stream_dquoted(o_string *as_string,
|
|||||||
* only when followed by one of the following characters:
|
* only when followed by one of the following characters:
|
||||||
* $, `, ", \, or <newline>. A double quote may be quoted
|
* $, `, ", \, or <newline>. A double quote may be quoted
|
||||||
* within double quotes by preceding it with a backslash."
|
* within double quotes by preceding it with a backslash."
|
||||||
|
* NB: in (unquoted) heredoc, above does not apply to ".
|
||||||
*/
|
*/
|
||||||
if (strchr("$`\"\\\n", next) != NULL) {
|
if (next == dquote_end || strchr("$`\\\n", next) != NULL) {
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
if (ch != '\n') {
|
if (ch != '\n') {
|
||||||
o_addqchr(dest, ch);
|
o_addqchr(dest, ch);
|
||||||
@ -4412,6 +4417,7 @@ static char *expand_pseudo_dquoted(const char *str)
|
|||||||
o_string dest = NULL_O_STRING;
|
o_string dest = NULL_O_STRING;
|
||||||
|
|
||||||
if (!strchr(str, '$')
|
if (!strchr(str, '$')
|
||||||
|
&& !strchr(str, '\\')
|
||||||
#if ENABLE_HUSH_TICK
|
#if ENABLE_HUSH_TICK
|
||||||
&& !strchr(str, '`')
|
&& !strchr(str, '`')
|
||||||
#endif
|
#endif
|
||||||
|
27
shell/hush_test/hush-misc/heredoc_backslash1.right
Normal file
27
shell/hush_test/hush-misc/heredoc_backslash1.right
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
Quoted heredoc:
|
||||||
|
a\
|
||||||
|
b
|
||||||
|
123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?-
|
||||||
|
-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-
|
||||||
|
c\
|
||||||
|
|
||||||
|
Unquoted heredoc:
|
||||||
|
a b
|
||||||
|
123456 -qwerty-\t-\-\"-\'-`-\--\z-\*-\?-
|
||||||
|
-qwerty-\t-\-\"-\'-`-\--\z-\*-\?-
|
||||||
|
cEOF2
|
||||||
|
|
||||||
|
Quoted -heredoc:
|
||||||
|
a\
|
||||||
|
b
|
||||||
|
123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?-
|
||||||
|
-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-
|
||||||
|
c\
|
||||||
|
|
||||||
|
Unquoted -heredoc:
|
||||||
|
a b
|
||||||
|
123456 -qwerty-\t-\-\"-\'-`-\--\z-\*-\?-
|
||||||
|
-qwerty-\t-\-\"-\'-`-\--\z-\*-\?-
|
||||||
|
cEOF4
|
||||||
|
|
||||||
|
Done: 0
|
54
shell/hush_test/hush-misc/heredoc_backslash1.tests
Executable file
54
shell/hush_test/hush-misc/heredoc_backslash1.tests
Executable file
@ -0,0 +1,54 @@
|
|||||||
|
# Test for correct handling of backslashes.
|
||||||
|
# Note that some lines in each heredoc start with a tab.
|
||||||
|
|
||||||
|
a=qwerty
|
||||||
|
|
||||||
|
echo Quoted heredoc:
|
||||||
|
cat <<"EOF1"
|
||||||
|
a\
|
||||||
|
b
|
||||||
|
123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?-
|
||||||
|
-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-
|
||||||
|
c\
|
||||||
|
EOF1
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo Unquoted heredoc:
|
||||||
|
cat <<EOF2
|
||||||
|
a\
|
||||||
|
b
|
||||||
|
123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?-
|
||||||
|
-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-
|
||||||
|
c\
|
||||||
|
EOF2
|
||||||
|
EOF2
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo Quoted -heredoc:
|
||||||
|
cat <<-"EOF3"
|
||||||
|
a\
|
||||||
|
b
|
||||||
|
123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?-
|
||||||
|
-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-
|
||||||
|
c\
|
||||||
|
EOF3
|
||||||
|
# In -heredoc case the marker is detected even if it is indented.
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo Unquoted -heredoc:
|
||||||
|
cat <<-EOF4
|
||||||
|
a\
|
||||||
|
b
|
||||||
|
123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?-
|
||||||
|
-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-
|
||||||
|
c\
|
||||||
|
EOF4
|
||||||
|
EOF4
|
||||||
|
# The marker is not detected if preceding line ends in backslash.
|
||||||
|
# TODO: marker should be detected even if it is split by line continuation:
|
||||||
|
# EOF\
|
||||||
|
# 4
|
||||||
|
# but currently hush doesn't do it. (Tab before "4" is not allowed, though.)
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "Done: $?"
|
Loading…
Reference in New Issue
Block a user