hush: fix handling of '' in ${var:+ARG}

This wasn't an ash bug in dollar_altvalue9, it was hush bug (and bash!)

function                                             old     new   delta
expand_one_var                                      2236    2254     +18
expand_vars_to_list                                 1097    1103      +6
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 24/0)               Total: 24 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2018-07-20 17:36:06 +02:00
parent 294eb4612c
commit 83e434d5b5
7 changed files with 217 additions and 3 deletions

View File

@ -0,0 +1,69 @@
Unquoted '':
start:
||
end
start:
||
end
start:
||
end
start:
||
end
start:
||
||
end
Unquoted "":
start:
||
end
start:
||
end
start:
||
end
start:
||
end
start:
||
||
end
Quoted '':
start:
|''|
end
start:
|'' |
end
start:
| ''|
end
start:
| '' |
end
start:
|'' ''|
end
Quoted "":
start:
||
end
start:
| |
end
start:
| |
end
start:
| |
end
start:
| |
end

View File

@ -0,0 +1,33 @@
f() { echo start:; for i; do echo "|$i|"; done; echo end; }
x=a
echo "Unquoted '':"
f ${x:+''}
f ${x:+'' }
f ${x:+ ''}
f ${x:+ '' }
f ${x:+'' ''}
echo
echo 'Unquoted "":'
f ${x:+""}
f ${x:+"" }
f ${x:+ ""}
f ${x:+ "" }
f ${x:+"" ""}
echo
echo "Quoted '':"
f "${x:+''}"
f "${x:+'' }"
f "${x:+ ''}"
f "${x:+ '' }"
f "${x:+'' ''}"
echo
echo 'Quoted "":'
f "${x:+""}"
f "${x:+"" }"
f "${x:+ ""}"
f "${x:+ "" }"
f "${x:+"" ""}"

View File

@ -3,6 +3,7 @@ Unquoted 1:
|x y| |x y|
|1| |1|
|2| |2|
||
|1 2| |1 2|
|A| |A|
|B| |B|
@ -14,6 +15,7 @@ Unquoted 2:
|ax y| |ax y|
|1| |1|
|2| |2|
||
|1 2| |1 2|
|A| |A|
|B| |B|

View File

@ -475,7 +475,6 @@
#endif #endif
#define SPECIAL_VAR_SYMBOL_STR "\3" #define SPECIAL_VAR_SYMBOL_STR "\3"
#define SPECIAL_VAR_SYMBOL_CHR '\3'
#define SPECIAL_VAR_SYMBOL 3 #define SPECIAL_VAR_SYMBOL 3
/* The "variable" with name "\1" emits string "\3". Testcase: "echo ^C" */ /* The "variable" with name "\1" emits string "\3". Testcase: "echo ^C" */
#define SPECIAL_VAR_QUOTED_SVS 1 #define SPECIAL_VAR_QUOTED_SVS 1
@ -5950,6 +5949,8 @@ static int encode_then_append_var_plusminus(o_string *output, int n,
break; break;
o_addqchr(&dest, ch); o_addqchr(&dest, ch);
} }
o_addchr(&dest, SPECIAL_VAR_SYMBOL);
o_addchr(&dest, SPECIAL_VAR_SYMBOL);
continue; continue;
} }
} }
@ -5959,6 +5960,10 @@ static int encode_then_append_var_plusminus(o_string *output, int n,
} }
if (ch == '"') { if (ch == '"') {
dest.o_expflags ^= EXP_FLAG_ESC_GLOB_CHARS; dest.o_expflags ^= EXP_FLAG_ESC_GLOB_CHARS;
if (dest.o_expflags) {
o_addchr(&dest, SPECIAL_VAR_SYMBOL);
o_addchr(&dest, SPECIAL_VAR_SYMBOL);
}
continue; continue;
} }
if (ch == '\\') { if (ch == '\\') {
@ -6565,7 +6570,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
case SPECIAL_VAR_QUOTED_SVS: case SPECIAL_VAR_QUOTED_SVS:
/* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_QUOTED_SVS><SPECIAL_VAR_SYMBOL> */ /* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_QUOTED_SVS><SPECIAL_VAR_SYMBOL> */
/* "^C variable", represents literal ^C char (possible in scripts) */ /* "^C variable", represents literal ^C char (possible in scripts) */
o_addchr(output, SPECIAL_VAR_SYMBOL_CHR); o_addchr(output, SPECIAL_VAR_SYMBOL);
arg++; arg++;
break; break;
#if ENABLE_HUSH_TICK #if ENABLE_HUSH_TICK
@ -6627,7 +6632,8 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
o_addstr(output, arg); o_addstr(output, arg);
debug_print_list("expand_vars_to_list[b]", output, n); debug_print_list("expand_vars_to_list[b]", output, n);
} else if (output->length == o_get_last_ptr(output, n) /* expansion is empty */ } else if (output->length == o_get_last_ptr(output, n) /* expansion is empty */
&& !(cant_be_null & 0x80) /* and all vars were not quoted. */ && !(cant_be_null & 0x80) /* and all vars were not quoted */
&& !output->has_quoted_part
) { ) {
n--; n--;
/* allow to reuse list[n] later without re-growth */ /* allow to reuse list[n] later without re-growth */

View File

@ -0,0 +1,69 @@
Unquoted '':
start:
||
end
start:
||
end
start:
||
end
start:
||
end
start:
||
||
end
Unquoted "":
start:
||
end
start:
||
end
start:
||
end
start:
||
end
start:
||
||
end
Quoted '':
start:
|''|
end
start:
|'' |
end
start:
| ''|
end
start:
| '' |
end
start:
|'' ''|
end
Quoted "":
start:
||
end
start:
| |
end
start:
| |
end
start:
| |
end
start:
| |
end

View File

@ -0,0 +1,33 @@
f() { echo start:; for i; do echo "|$i|"; done; echo end; }
x=a
echo "Unquoted '':"
f ${x:+''}
f ${x:+'' }
f ${x:+ ''}
f ${x:+ '' }
f ${x:+'' ''}
echo
echo 'Unquoted "":'
f ${x:+""}
f ${x:+"" }
f ${x:+ ""}
f ${x:+ "" }
f ${x:+"" ""}
echo
echo "Quoted '':"
f "${x:+''}"
f "${x:+'' }"
f "${x:+ ''}"
f "${x:+ '' }"
f "${x:+'' ''}"
echo
echo 'Quoted "":'
f "${x:+""}"
f "${x:+"" }"
f "${x:+ ""}"
f "${x:+ "" }"
f "${x:+"" ""}"

View File

@ -3,6 +3,7 @@ Unquoted 1:
|x y| |x y|
|1| |1|
|2| |2|
||
|1 2| |1 2|
|A| |A|
|B| |B|
@ -14,6 +15,7 @@ Unquoted 2:
|ax y| |ax y|
|1| |1|
|2| |2|
||
|1 2| |1 2|
|A| |A|
|B| |B|