shells: do not allow bare "read" in non-bash compat configs
No binary (build failed)
—
(log yok)
| @@ -89,6 +89,12 @@ getopt32(char **argv, const char *applet_opts, ...) | |
| root:x:0:0:root:/root:/bin/bash | |
| user:x:500:500::/home/user:/bin/bash | |
| + | "^" options string is "^optchars""\0""opt_complementary". |
| + | |
| + | "!" If the first character in the applet_opts string is a '!', |
| + | report bad options, missing required options, |
| + | inconsistent options with all-ones return value (instead of abort. |
| + | |
| "+" If the first character in the applet_opts string is a plus, | |
| then option processing will stop as soon as a non-option is | |
| encountered in the argv array. Useful for applets like env | |
| @@ -96,10 +102,7 @@ getopt32(char **argv, const char *applet_opts, ...) | |
| env -i ls -d / | |
| Here we want env to process just the '-i', not the '-d'. | |
| - | "!" Report bad options, missing required options, |
| - | inconsistent options with all-ones return value (instead of abort). |
| - | |
| - | "^" options string is "^optchars""\0""opt_complementary". |
| + | (The order of multiple prefixes must be "^!+...") |
| uint32_t | |
| getopt32long(char **argv, const char *applet_opts, const char *logopts...) | |
| @@ -14161,6 +14161,10 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |
| } | |
| } | |
| + | if (!ENABLE_ASH_BASH_COMPAT && !argptr) { |
| + | bb_simple_error_msg("read: need variable name"); |
| + | return 1; |
| + | } |
| params.argv = argptr; | |
| params.setvar = setvar0; | |
| params.ifs = bltinlookup("IFS"); /* can be NULL */ | |
| @@ -4251,7 +4251,7 @@ static int done_word(struct parse_context *ctx) | |
| || endofname(command->argv[0])[0] != '\0' | |
| ) { | |
| /* bash says just "not a valid identifier" */ | |
| - | syntax_error("not a valid identifier in for"); |
| + | syntax_error("bad variable name in for"); |
| return 1; | |
| } | |
| /* Force FOR to have just one word (variable name) */ | |
| @@ -10799,10 +10799,17 @@ static int FAST_FUNC builtin_read(char **argv) | |
| */ | |
| params.read_flags = getopt32(argv, | |
| # if BASH_READ_D | |
| - | "!srn:p:t:u:d:", ¶ms.opt_n, ¶ms.opt_p, ¶ms.opt_t, ¶ms.opt_u, ¶ms.opt_d |
| + | IF_NOT_HUSH_BASH_COMPAT("^") |
| + | "!srn:p:t:u:d:" IF_NOT_HUSH_BASH_COMPAT("\0" "-1"/*min 1 arg*/), |
| + | ¶ms.opt_n, ¶ms.opt_p, ¶ms.opt_t, ¶ms.opt_u, ¶ms.opt_d |
| # else | |
| - | "!srn:p:t:u:", ¶ms.opt_n, ¶ms.opt_p, ¶ms.opt_t, ¶ms.opt_u |
| + | IF_NOT_HUSH_BASH_COMPAT("^") |
| + | "!srn:p:t:u:" IF_NOT_HUSH_BASH_COMPAT("\0" "-1"/*min 1 arg*/), |
| + | ¶ms.opt_n, ¶ms.opt_p, ¶ms.opt_t, ¶ms.opt_u |
| # endif | |
| + | //TODO: print "read: need variable name" |
| + | //for the case of !BASH "read" with no args (now it fails silently) |
| + | //(or maybe extend getopt32() to emit a message if "-1" fails) |
| ); | |
| if ((uint32_t)params.read_flags == (uint32_t)-1) | |
| return EXIT_FAILURE; | |
| @@ -59,7 +59,7 @@ shell_builtin_read(struct builtin_read_params *params) | |
| while (*pp) { | |
| if (endofname(*pp)[0] != '\0') { | |
| /* Mimic bash message */ | |
| - | bb_error_msg("read: '%s': not a valid identifier", *pp); |
| + | bb_error_msg("read: '%s': bad variable name", *pp); |
| return (const char *)(uintptr_t)1; | |
| } | |
| pp++; | |