aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-08-02 19:44:05 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2017-08-02 19:46:14 +0200
commit39701204cfa0f261beb2dc056024634e4c3afd71 (patch)
treef756205f8872ed47dd06652c63fae8c83cbdeab5 /shell
parent84ea60ed65f6ea6fd3b2170e44bbff5de410a78b (diff)
downloadbusybox-w32-39701204cfa0f261beb2dc056024634e4c3afd71.tar.gz
busybox-w32-39701204cfa0f261beb2dc056024634e4c3afd71.tar.bz2
busybox-w32-39701204cfa0f261beb2dc056024634e4c3afd71.zip
hush: do not accept "if() { echo; }" function def
function old new delta parse_stream 2634 2692 +58 msg_and_die_if_script - 21 +21 syntax_error_unexpected_ch 41 46 +5 syntax_error_at 14 18 +4 die_if_script 31 28 -3 setup_redirects 319 308 -11 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 3/2 up/down: 88/-14) Total: 74 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r--shell/ash_test/ash-parsing/groups_and_keywords2.right3
-rwxr-xr-xshell/ash_test/ash-parsing/groups_and_keywords2.tests9
-rw-r--r--shell/hush.c53
-rw-r--r--shell/hush_test/hush-parsing/groups_and_keywords2.right3
-rwxr-xr-xshell/hush_test/hush-parsing/groups_and_keywords2.tests9
5 files changed, 60 insertions, 17 deletions
diff --git a/shell/ash_test/ash-parsing/groups_and_keywords2.right b/shell/ash_test/ash-parsing/groups_and_keywords2.right
new file mode 100644
index 000000000..3fcbeb662
--- /dev/null
+++ b/shell/ash_test/ash-parsing/groups_and_keywords2.right
@@ -0,0 +1,3 @@
1./groups_and_keywords2.tests: eval: line 1: syntax error: unexpected ")"
2Fail:2
3./groups_and_keywords2.tests: line 8: syntax error: unexpected ")"
diff --git a/shell/ash_test/ash-parsing/groups_and_keywords2.tests b/shell/ash_test/ash-parsing/groups_and_keywords2.tests
new file mode 100755
index 000000000..ab33b909f
--- /dev/null
+++ b/shell/ash_test/ash-parsing/groups_and_keywords2.tests
@@ -0,0 +1,9 @@
1# This is an error
2(eval 'if() { echo; }')
3echo Fail:$?
4# ^^^^^^ bash prints 1, but interactively it sets $? = 2
5# we print 2
6
7# This is an error, and it aborts in script
8if() { echo; }
9echo Not reached
diff --git a/shell/hush.c b/shell/hush.c
index 6fa4e1630..b04f793f1 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -1272,7 +1272,7 @@ static void xxfree(void *ptr)
1272 * HUSH_DEBUG >= 2 prints line number in this file where it was detected. 1272 * HUSH_DEBUG >= 2 prints line number in this file where it was detected.
1273 */ 1273 */
1274#if HUSH_DEBUG < 2 1274#if HUSH_DEBUG < 2
1275# define die_if_script(lineno, ...) die_if_script(__VA_ARGS__) 1275# define msg_and_die_if_script(lineno, ...) msg_and_die_if_script(__VA_ARGS__)
1276# define syntax_error(lineno, msg) syntax_error(msg) 1276# define syntax_error(lineno, msg) syntax_error(msg)
1277# define syntax_error_at(lineno, msg) syntax_error_at(msg) 1277# define syntax_error_at(lineno, msg) syntax_error_at(msg)
1278# define syntax_error_unterm_ch(lineno, ch) syntax_error_unterm_ch(ch) 1278# define syntax_error_unterm_ch(lineno, ch) syntax_error_unterm_ch(ch)
@@ -1280,7 +1280,16 @@ static void xxfree(void *ptr)
1280# define syntax_error_unexpected_ch(lineno, ch) syntax_error_unexpected_ch(ch) 1280# define syntax_error_unexpected_ch(lineno, ch) syntax_error_unexpected_ch(ch)
1281#endif 1281#endif
1282 1282
1283static void die_if_script(unsigned lineno, const char *fmt, ...) 1283static void die_if_script(void)
1284{
1285 if (!G_interactive_fd) {
1286 if (G.last_exitcode) /* sometines it's 2, not 1 (bash compat) */
1287 xfunc_error_retval = G.last_exitcode;
1288 xfunc_die();
1289 }
1290}
1291
1292static void msg_and_die_if_script(unsigned lineno, const char *fmt, ...)
1284{ 1293{
1285 va_list p; 1294 va_list p;
1286 1295
@@ -1290,8 +1299,7 @@ static void die_if_script(unsigned lineno, const char *fmt, ...)
1290 va_start(p, fmt); 1299 va_start(p, fmt);
1291 bb_verror_msg(fmt, p, NULL); 1300 bb_verror_msg(fmt, p, NULL);
1292 va_end(p); 1301 va_end(p);
1293 if (!G_interactive_fd) 1302 die_if_script();
1294 xfunc_die();
1295} 1303}
1296 1304
1297static void syntax_error(unsigned lineno UNUSED_PARAM, const char *msg) 1305static void syntax_error(unsigned lineno UNUSED_PARAM, const char *msg)
@@ -1300,16 +1308,20 @@ static void syntax_error(unsigned lineno UNUSED_PARAM, const char *msg)
1300 bb_error_msg("syntax error: %s", msg); 1308 bb_error_msg("syntax error: %s", msg);
1301 else 1309 else
1302 bb_error_msg("syntax error"); 1310 bb_error_msg("syntax error");
1311 die_if_script();
1303} 1312}
1304 1313
1305static void syntax_error_at(unsigned lineno UNUSED_PARAM, const char *msg) 1314static void syntax_error_at(unsigned lineno UNUSED_PARAM, const char *msg)
1306{ 1315{
1307 bb_error_msg("syntax error at '%s'", msg); 1316 bb_error_msg("syntax error at '%s'", msg);
1317 die_if_script();
1308} 1318}
1309 1319
1310static void syntax_error_unterm_str(unsigned lineno UNUSED_PARAM, const char *s) 1320static void syntax_error_unterm_str(unsigned lineno UNUSED_PARAM, const char *s)
1311{ 1321{
1312 bb_error_msg("syntax error: unterminated %s", s); 1322 bb_error_msg("syntax error: unterminated %s", s);
1323//? source4.tests fails: in bash, echo ${^} in script does not terminate the script
1324// die_if_script();
1313} 1325}
1314 1326
1315static void syntax_error_unterm_ch(unsigned lineno, char ch) 1327static void syntax_error_unterm_ch(unsigned lineno, char ch)
@@ -1327,17 +1339,18 @@ static void syntax_error_unexpected_ch(unsigned lineno UNUSED_PARAM, int ch)
1327 bb_error_msg("hush.c:%u", lineno); 1339 bb_error_msg("hush.c:%u", lineno);
1328#endif 1340#endif
1329 bb_error_msg("syntax error: unexpected %s", ch == EOF ? "EOF" : msg); 1341 bb_error_msg("syntax error: unexpected %s", ch == EOF ? "EOF" : msg);
1342 die_if_script();
1330} 1343}
1331 1344
1332#if HUSH_DEBUG < 2 1345#if HUSH_DEBUG < 2
1333# undef die_if_script 1346# undef msg_and_die_if_script
1334# undef syntax_error 1347# undef syntax_error
1335# undef syntax_error_at 1348# undef syntax_error_at
1336# undef syntax_error_unterm_ch 1349# undef syntax_error_unterm_ch
1337# undef syntax_error_unterm_str 1350# undef syntax_error_unterm_str
1338# undef syntax_error_unexpected_ch 1351# undef syntax_error_unexpected_ch
1339#else 1352#else
1340# define die_if_script(...) die_if_script(__LINE__, __VA_ARGS__) 1353# define msg_and_die_if_script(...) msg_and_die_if_script(__LINE__, __VA_ARGS__)
1341# define syntax_error(msg) syntax_error(__LINE__, msg) 1354# define syntax_error(msg) syntax_error(__LINE__, msg)
1342# define syntax_error_at(msg) syntax_error_at(__LINE__, msg) 1355# define syntax_error_at(msg) syntax_error_at(__LINE__, msg)
1343# define syntax_error_unterm_ch(ch) syntax_error_unterm_ch(__LINE__, ch) 1356# define syntax_error_unterm_ch(ch) syntax_error_unterm_ch(__LINE__, ch)
@@ -1800,7 +1813,7 @@ static void restore_ttypgrp_and__exit(void)
1800 * echo END_OF_SCRIPT 1813 * echo END_OF_SCRIPT
1801 * lseeks fd in input FILE object from EOF to "e" in "echo END_OF_SCRIPT". 1814 * lseeks fd in input FILE object from EOF to "e" in "echo END_OF_SCRIPT".
1802 * This makes "echo END_OF_SCRIPT" executed twice. 1815 * This makes "echo END_OF_SCRIPT" executed twice.
1803 * Similar problems can be seen with die_if_script() -> xfunc_die() 1816 * Similar problems can be seen with msg_and_die_if_script() -> xfunc_die()
1804 * and in `cmd` handling. 1817 * and in `cmd` handling.
1805 * If set as die_func(), this makes xfunc_die() exit via _exit(), not exit(): 1818 * If set as die_func(), this makes xfunc_die() exit via _exit(), not exit():
1806 */ 1819 */
@@ -3383,7 +3396,7 @@ static int done_command(struct parse_context *ctx)
3383#if 0 /* Instead we emit error message at run time */ 3396#if 0 /* Instead we emit error message at run time */
3384 if (ctx->pending_redirect) { 3397 if (ctx->pending_redirect) {
3385 /* For example, "cmd >" (no filename to redirect to) */ 3398 /* For example, "cmd >" (no filename to redirect to) */
3386 die_if_script("syntax error: %s", "invalid redirect"); 3399 syntax_error("invalid redirect");
3387 ctx->pending_redirect = NULL; 3400 ctx->pending_redirect = NULL;
3388 } 3401 }
3389#endif 3402#endif
@@ -3949,7 +3962,7 @@ static int parse_redirect(struct parse_context *ctx,
3949#if 0 /* Instead we emit error message at run time */ 3962#if 0 /* Instead we emit error message at run time */
3950 if (ctx->pending_redirect) { 3963 if (ctx->pending_redirect) {
3951 /* For example, "cmd > <file" */ 3964 /* For example, "cmd > <file" */
3952 die_if_script("syntax error: %s", "invalid redirect"); 3965 syntax_error("invalid redirect");
3953 } 3966 }
3954#endif 3967#endif
3955 /* Set ctx->pending_redirect, so we know what to do at the 3968 /* Set ctx->pending_redirect, so we know what to do at the
@@ -5021,10 +5034,16 @@ static struct pipe *parse_stream(char **pstring,
5021 else 5034 else
5022 o_free_unsafe(&ctx.as_string); 5035 o_free_unsafe(&ctx.as_string);
5023#endif 5036#endif
5024 debug_leave(); 5037 if (ch != ';' && IS_NULL_PIPE(ctx.list_head)) {
5038 /* Example: bare "{ }", "()" */
5039 G.last_exitcode = 2; /* bash compat */
5040 syntax_error_unexpected_ch(ch);
5041 goto parse_error2;
5042 }
5025 debug_printf_parse("parse_stream return %p: " 5043 debug_printf_parse("parse_stream return %p: "
5026 "end_trigger char found\n", 5044 "end_trigger char found\n",
5027 ctx.list_head); 5045 ctx.list_head);
5046 debug_leave();
5028 return ctx.list_head; 5047 return ctx.list_head;
5029 } 5048 }
5030 } 5049 }
@@ -5282,8 +5301,8 @@ static struct pipe *parse_stream(char **pstring,
5282 /* proper use of this character is caught by end_trigger: 5301 /* proper use of this character is caught by end_trigger:
5283 * if we see {, we call parse_group(..., end_trigger='}') 5302 * if we see {, we call parse_group(..., end_trigger='}')
5284 * and it will match } earlier (not here). */ 5303 * and it will match } earlier (not here). */
5285 syntax_error_unexpected_ch(ch);
5286 G.last_exitcode = 2; 5304 G.last_exitcode = 2;
5305 syntax_error_unexpected_ch(ch);
5287 goto parse_error2; 5306 goto parse_error2;
5288 default: 5307 default:
5289 if (HUSH_DEBUG) 5308 if (HUSH_DEBUG)
@@ -5513,7 +5532,7 @@ static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p)
5513 if (errmsg_p) 5532 if (errmsg_p)
5514 *errmsg_p = math_state.errmsg; 5533 *errmsg_p = math_state.errmsg;
5515 if (math_state.errmsg) 5534 if (math_state.errmsg)
5516 die_if_script(math_state.errmsg); 5535 msg_and_die_if_script(math_state.errmsg);
5517 return res; 5536 return res;
5518} 5537}
5519#endif 5538#endif
@@ -5780,7 +5799,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
5780 /* in bash, len=-n means strlen()-n */ 5799 /* in bash, len=-n means strlen()-n */
5781 len = (arith_t)strlen(val) - beg + len; 5800 len = (arith_t)strlen(val) - beg + len;
5782 if (len < 0) /* bash compat */ 5801 if (len < 0) /* bash compat */
5783 die_if_script("%s: substring expression < 0", var); 5802 msg_and_die_if_script("%s: substring expression < 0", var);
5784 } 5803 }
5785 if (len <= 0 || !val || beg >= strlen(val)) { 5804 if (len <= 0 || !val || beg >= strlen(val)) {
5786 arith_err: 5805 arith_err:
@@ -5794,7 +5813,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
5794 } 5813 }
5795 debug_printf_varexp("val:'%s'\n", val); 5814 debug_printf_varexp("val:'%s'\n", val);
5796#else /* not (HUSH_SUBSTR_EXPANSION && FEATURE_SH_MATH) */ 5815#else /* not (HUSH_SUBSTR_EXPANSION && FEATURE_SH_MATH) */
5797 die_if_script("malformed ${%s:...}", var); 5816 msg_and_die_if_script("malformed ${%s:...}", var);
5798 val = NULL; 5817 val = NULL;
5799#endif 5818#endif
5800 } else { /* one of "-=+?" */ 5819 } else { /* one of "-=+?" */
@@ -5831,7 +5850,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
5831 exp_word = to_be_freed; 5850 exp_word = to_be_freed;
5832 if (exp_op == '?') { 5851 if (exp_op == '?') {
5833 /* mimic bash message */ 5852 /* mimic bash message */
5834 die_if_script("%s: %s", 5853 msg_and_die_if_script("%s: %s",
5835 var, 5854 var,
5836 exp_word[0] 5855 exp_word[0]
5837 ? exp_word 5856 ? exp_word
@@ -5848,7 +5867,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
5848 /* ${var=[word]} or ${var:=[word]} */ 5867 /* ${var=[word]} or ${var:=[word]} */
5849 if (isdigit(var[0]) || var[0] == '#') { 5868 if (isdigit(var[0]) || var[0] == '#') {
5850 /* mimic bash message */ 5869 /* mimic bash message */
5851 die_if_script("$%s: cannot assign in this way", var); 5870 msg_and_die_if_script("$%s: cannot assign in this way", var);
5852 val = NULL; 5871 val = NULL;
5853 } else { 5872 } else {
5854 char *new_var = xasprintf("%s=%s", var, val); 5873 char *new_var = xasprintf("%s=%s", var, val);
@@ -6862,7 +6881,7 @@ static int setup_redirects(struct command *prog, struct squirrel **sqp)
6862 * "cmd >" (no filename) 6881 * "cmd >" (no filename)
6863 * "cmd > <file" (2nd redirect starts too early) 6882 * "cmd > <file" (2nd redirect starts too early)
6864 */ 6883 */
6865 die_if_script("syntax error: %s", "invalid redirect"); 6884 syntax_error("invalid redirect");
6866 continue; 6885 continue;
6867 } 6886 }
6868 mode = redir_table[redir->rd_type].mode; 6887 mode = redir_table[redir->rd_type].mode;
diff --git a/shell/hush_test/hush-parsing/groups_and_keywords2.right b/shell/hush_test/hush-parsing/groups_and_keywords2.right
new file mode 100644
index 000000000..ae74a5db9
--- /dev/null
+++ b/shell/hush_test/hush-parsing/groups_and_keywords2.right
@@ -0,0 +1,3 @@
1hush: syntax error: unexpected )
2Fail:2
3hush: syntax error: unexpected )
diff --git a/shell/hush_test/hush-parsing/groups_and_keywords2.tests b/shell/hush_test/hush-parsing/groups_and_keywords2.tests
new file mode 100755
index 000000000..ab33b909f
--- /dev/null
+++ b/shell/hush_test/hush-parsing/groups_and_keywords2.tests
@@ -0,0 +1,9 @@
1# This is an error
2(eval 'if() { echo; }')
3echo Fail:$?
4# ^^^^^^ bash prints 1, but interactively it sets $? = 2
5# we print 2
6
7# This is an error, and it aborts in script
8if() { echo; }
9echo Not reached