diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2025-08-07 01:30:57 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2025-08-07 01:30:57 +0200 |
| commit | 7648dc721e390bba5049e798d73e70c6180b366b (patch) | |
| tree | ce7f34a088ef10e5889c834ccedd4523f7e9541c /shell | |
| parent | 558ef4962dd3adb9e63b4c0787f8d4902fc909d4 (diff) | |
| download | busybox-w32-7648dc721e390bba5049e798d73e70c6180b366b.tar.gz busybox-w32-7648dc721e390bba5049e798d73e70c6180b366b.tar.bz2 busybox-w32-7648dc721e390bba5049e798d73e70c6180b366b.zip | |
ash,hush: fix corner cases with backslash-newlines in heredocs
function old new delta
fetch_heredocs 477 485 +8
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
14 files changed, 44 insertions, 5 deletions
diff --git a/shell/ash.c b/shell/ash.c index 9cacdff64..bfd9aa53e 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
| @@ -12735,21 +12735,22 @@ checkend: { | |||
| 12735 | 12735 | ||
| 12736 | if (striptabs) { | 12736 | if (striptabs) { |
| 12737 | while (c == '\t') | 12737 | while (c == '\t') |
| 12738 | c = pgetc(); | 12738 | c = pgetc_eatbnl(); /* dash does pgetc() */ |
| 12739 | /* (see heredoc_bkslash_newline3a.tests) */ | ||
| 12739 | } | 12740 | } |
| 12740 | 12741 | ||
| 12741 | markloc = out - (char *)stackblock(); | 12742 | markloc = out - (char *)stackblock(); |
| 12742 | for (p = eofmark; STPUTC(c, out), *p; p++) { | 12743 | for (p = eofmark; STPUTC(c, out), *p; p++) { |
| 12743 | if (c != *p) | 12744 | if (c != *p) |
| 12744 | goto more_heredoc; | 12745 | goto more_heredoc; |
| 12745 | /* FIXME: fails for backslash-newlined terminator: | 12746 | /* dash still has this not fixed (as of 2025-08) |
| 12746 | * cat <<EOF | 12747 | * cat <<EOF |
| 12747 | * ... | 12748 | * ... |
| 12748 | * EO\ | 12749 | * EO\ |
| 12749 | * F | 12750 | * F |
| 12750 | * (see heredoc_bkslash_newline2.tests) | 12751 | * (see heredoc_bkslash_newline2.tests) |
| 12751 | */ | 12752 | */ |
| 12752 | c = pgetc(); | 12753 | c = pgetc_eatbnl(); /* dash does pgetc() */ |
| 12753 | } | 12754 | } |
| 12754 | 12755 | ||
| 12755 | if (c == '\n' || c == PEOF) { | 12756 | if (c == '\n' || c == PEOF) { |
diff --git a/shell/ash_test/ash-heredoc/heredoc_bkslash_newline2a.right b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline2a.right new file mode 100644 index 000000000..3d79316d7 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline2a.right | |||
| @@ -0,0 +1 @@ | |||
| Ok1 | |||
diff --git a/shell/ash_test/ash-heredoc/heredoc_bkslash_newline2a.tests b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline2a.tests new file mode 100755 index 000000000..eb2223031 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline2a.tests | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | cat <<-EOF | ||
| 2 | Ok1 | ||
| 3 | EO\ | ||
| 4 | F | ||
diff --git a/shell/ash_test/ash-heredoc/heredoc_bkslash_newline3.right b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline3.right new file mode 100644 index 000000000..3d79316d7 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline3.right | |||
| @@ -0,0 +1 @@ | |||
| Ok1 | |||
diff --git a/shell/ash_test/ash-heredoc/heredoc_bkslash_newline3.tests b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline3.tests new file mode 100755 index 000000000..de21132d1 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline3.tests | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | cat <<EOF | ||
| 2 | Ok1 | ||
| 3 | \ | ||
| 4 | EOF | ||
diff --git a/shell/ash_test/ash-heredoc/heredoc_bkslash_newline3a.right b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline3a.right new file mode 100644 index 000000000..3d79316d7 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline3a.right | |||
| @@ -0,0 +1 @@ | |||
| Ok1 | |||
diff --git a/shell/ash_test/ash-heredoc/heredoc_bkslash_newline3a.tests b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline3a.tests new file mode 100755 index 000000000..da3860804 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline3a.tests | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | cat <<-EOF | ||
| 2 | Ok1 | ||
| 3 | \ | ||
| 4 | EOF | ||
diff --git a/shell/hush.c b/shell/hush.c index 6129a087b..0b8da5e2d 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
| @@ -4639,7 +4639,15 @@ static char *fetch_till_str(o_string *as_string, | |||
| 4639 | past_EOL = heredoc.length; | 4639 | past_EOL = heredoc.length; |
| 4640 | /* Get 1st char of next line, possibly skipping leading tabs */ | 4640 | /* Get 1st char of next line, possibly skipping leading tabs */ |
| 4641 | do { | 4641 | do { |
| 4642 | ch = i_getch(input); | 4642 | if (heredoc_flags & HEREDOC_QUOTED) |
| 4643 | ch = i_getch(input); | ||
| 4644 | else { /* see heredoc_bkslash_newline3a.tests: | ||
| 4645 | * cat <<-EOF | ||
| 4646 | * <tab>\ | ||
| 4647 | * <tab>EOF | ||
| 4648 | */ | ||
| 4649 | ch = i_getch_and_eat_bkslash_nl(input); | ||
| 4650 | } | ||
| 4643 | if (ch != EOF) | 4651 | if (ch != EOF) |
| 4644 | nommu_addchr(as_string, ch); | 4652 | nommu_addchr(as_string, ch); |
| 4645 | } while ((heredoc_flags & HEREDOC_SKIPTABS) && ch == '\t'); | 4653 | } while ((heredoc_flags & HEREDOC_SKIPTABS) && ch == '\t'); |
| @@ -4665,7 +4673,7 @@ static char *fetch_till_str(o_string *as_string, | |||
| 4665 | prev = 0; /* not '\' */ | 4673 | prev = 0; /* not '\' */ |
| 4666 | continue; | 4674 | continue; |
| 4667 | } | 4675 | } |
| 4668 | } | 4676 | } /* if (\n or EOF) */ |
| 4669 | if (ch == EOF) { | 4677 | if (ch == EOF) { |
| 4670 | o_free(&heredoc); | 4678 | o_free(&heredoc); |
| 4671 | return NULL; /* error */ | 4679 | return NULL; /* error */ |
diff --git a/shell/hush_test/hush-heredoc/heredoc_bkslash_newline2a.right b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline2a.right new file mode 100644 index 000000000..3d79316d7 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline2a.right | |||
| @@ -0,0 +1 @@ | |||
| Ok1 | |||
diff --git a/shell/hush_test/hush-heredoc/heredoc_bkslash_newline2a.tests b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline2a.tests new file mode 100755 index 000000000..eb2223031 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline2a.tests | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | cat <<-EOF | ||
| 2 | Ok1 | ||
| 3 | EO\ | ||
| 4 | F | ||
diff --git a/shell/hush_test/hush-heredoc/heredoc_bkslash_newline3.right b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline3.right new file mode 100644 index 000000000..3d79316d7 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline3.right | |||
| @@ -0,0 +1 @@ | |||
| Ok1 | |||
diff --git a/shell/hush_test/hush-heredoc/heredoc_bkslash_newline3.tests b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline3.tests new file mode 100755 index 000000000..de21132d1 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline3.tests | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | cat <<EOF | ||
| 2 | Ok1 | ||
| 3 | \ | ||
| 4 | EOF | ||
diff --git a/shell/hush_test/hush-heredoc/heredoc_bkslash_newline3a.right b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline3a.right new file mode 100644 index 000000000..3d79316d7 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline3a.right | |||
| @@ -0,0 +1 @@ | |||
| Ok1 | |||
diff --git a/shell/hush_test/hush-heredoc/heredoc_bkslash_newline3a.tests b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline3a.tests new file mode 100755 index 000000000..da3860804 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline3a.tests | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | cat <<-EOF | ||
| 2 | Ok1 | ||
| 3 | \ | ||
| 4 | EOF | ||
