aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-04-17 11:55:42 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-04-17 11:55:42 +0000
commitf8c1f02d2f7733619437581c2264828d3d160089 (patch)
treeaca561482419d64a6d36d649fc1f4f67d1ba9123 /shell
parent5ff9629b8fe7578dd0cefb31764365c89ca6328c (diff)
downloadbusybox-w32-f8c1f02d2f7733619437581c2264828d3d160089.tar.gz
busybox-w32-f8c1f02d2f7733619437581c2264828d3d160089.tar.bz2
busybox-w32-f8c1f02d2f7733619437581c2264828d3d160089.zip
hush: disallow "{echo hi; }" (require whitespace)
and "{ echo hi }" (require semicolon or &) function old new delta parse_stream 2098 2176 +78 done_command 98 84 -14 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 78/-14) Total: 64 bytes
Diffstat (limited to 'shell')
-rw-r--r--shell/hush.c55
1 files changed, 35 insertions, 20 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 61b6a7925..8dda988ee 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -319,6 +319,10 @@ struct command {
319 */ 319 */
320 struct redir_struct *redirects; /* I/O redirections */ 320 struct redir_struct *redirects; /* I/O redirections */
321}; 321};
322/* Is there anything in this command at all? */
323#define IS_NULL_CMD(cmd) \
324 (!(cmd)->group && !(cmd)->argv && !(cmd)->redirects)
325
322 326
323struct pipe { 327struct pipe {
324 struct pipe *next; 328 struct pipe *next;
@@ -341,6 +345,9 @@ typedef enum pipe_style {
341 PIPE_OR = 3, 345 PIPE_OR = 3,
342 PIPE_BG = 4, 346 PIPE_BG = 4,
343} pipe_style; 347} pipe_style;
348/* Is there anything in this pipe at all? */
349#define IS_NULL_PIPE(pi) \
350 ((pi)->num_cmds == 0 IF_HAS_KEYWORDS( && (pi)->res_word == RES_NONE))
344 351
345/* This holds pointers to the various results of parsing */ 352/* This holds pointers to the various results of parsing */
346struct parse_context { 353struct parse_context {
@@ -3971,8 +3978,10 @@ static struct pipe *new_pipe(void)
3971 return pi; 3978 return pi;
3972} 3979}
3973 3980
3974/* Command (member of a pipe) is complete. The only possible error here 3981/* Command (member of a pipe) is complete, or we start a new pipe
3975 * is out of memory, in which case xmalloc exits. */ 3982 * if ctx->command is NULL.
3983 * No errors possible here.
3984 */
3976static int done_command(struct parse_context *ctx) 3985static int done_command(struct parse_context *ctx)
3977{ 3986{
3978 /* The command is really already in the pipe structure, so 3987 /* The command is really already in the pipe structure, so
@@ -3981,13 +3990,9 @@ static int done_command(struct parse_context *ctx)
3981 struct command *command = ctx->command; 3990 struct command *command = ctx->command;
3982 3991
3983 if (command) { 3992 if (command) {
3984 if (command->group == NULL 3993 if (IS_NULL_CMD(command)) {
3985 && command->argv == NULL
3986 && command->redirects == NULL
3987 ) {
3988 debug_printf_parse("done_command: skipping null cmd, num_cmds=%d\n", pi->num_cmds); 3994 debug_printf_parse("done_command: skipping null cmd, num_cmds=%d\n", pi->num_cmds);
3989 memset(command, 0, sizeof(*command)); /* paranoia */ 3995 goto clear_and_ret;
3990 return pi->num_cmds;
3991 } 3996 }
3992 pi->num_cmds++; 3997 pi->num_cmds++;
3993 debug_printf_parse("done_command: ++num_cmds=%d\n", pi->num_cmds); 3998 debug_printf_parse("done_command: ++num_cmds=%d\n", pi->num_cmds);
@@ -3999,12 +4004,9 @@ static int done_command(struct parse_context *ctx)
3999 /* Only real trickiness here is that the uncommitted 4004 /* Only real trickiness here is that the uncommitted
4000 * command structure is not counted in pi->num_cmds. */ 4005 * command structure is not counted in pi->num_cmds. */
4001 pi->cmds = xrealloc(pi->cmds, sizeof(*pi->cmds) * (pi->num_cmds+1)); 4006 pi->cmds = xrealloc(pi->cmds, sizeof(*pi->cmds) * (pi->num_cmds+1));
4002 command = &pi->cmds[pi->num_cmds]; 4007 ctx->command = command = &pi->cmds[pi->num_cmds];
4008 clear_and_ret:
4003 memset(command, 0, sizeof(*command)); 4009 memset(command, 0, sizeof(*command));
4004
4005 ctx->command = command;
4006 /* but ctx->pipe and ctx->list_head remain unchanged */
4007
4008 return pi->num_cmds; /* used only for 0/nonzero check */ 4010 return pi->num_cmds; /* used only for 0/nonzero check */
4009} 4011}
4010 4012
@@ -4024,9 +4026,7 @@ static void done_pipe(struct parse_context *ctx, pipe_style type)
4024 4026
4025 /* Without this check, even just <enter> on command line generates 4027 /* Without this check, even just <enter> on command line generates
4026 * tree of three NOPs (!). Which is harmless but annoying. 4028 * tree of three NOPs (!). Which is harmless but annoying.
4027 * IOW: it is safe to do it unconditionally. 4029 * IOW: it is safe to do it unconditionally. */
4028 * RES_NONE case is for "for a in; do ..." (empty IN set)
4029 * and other cases to work. */
4030 if (not_null 4030 if (not_null
4031#if ENABLE_HUSH_IF 4031#if ENABLE_HUSH_IF
4032 || ctx->ctx_res_w == RES_FI 4032 || ctx->ctx_res_w == RES_FI
@@ -4048,7 +4048,7 @@ static void done_pipe(struct parse_context *ctx, pipe_style type)
4048 ctx->pipe->next = new_p; 4048 ctx->pipe->next = new_p;
4049 ctx->pipe = new_p; 4049 ctx->pipe = new_p;
4050 /* RES_THEN, RES_DO etc are "sticky" - 4050 /* RES_THEN, RES_DO etc are "sticky" -
4051 * they remain set for commands inside if/while. 4051 * they remain set for pipes inside if/while.
4052 * This is used to control execution. 4052 * This is used to control execution.
4053 * RES_FOR and RES_IN are NOT sticky (needed to support 4053 * RES_FOR and RES_IN are NOT sticky (needed to support
4054 * cases where variable or value happens to match a keyword): 4054 * cases where variable or value happens to match a keyword):
@@ -4304,7 +4304,7 @@ static int done_word(o_string *word, struct parse_context *ctx)
4304 && ctx->ctx_res_w != RES_IN 4304 && ctx->ctx_res_w != RES_IN
4305# endif 4305# endif
4306 ) { 4306 ) {
4307 debug_printf_parse(": checking '%s' for reserved-ness\n", word->data); 4307 debug_printf_parse("checking '%s' for reserved-ness\n", word->data);
4308 if (reserved_word(word, ctx)) { 4308 if (reserved_word(word, ctx)) {
4309 o_reset_to_empty_unquoted(word); 4309 o_reset_to_empty_unquoted(word);
4310 debug_printf_parse("done_word return %d\n", 4310 debug_printf_parse("done_word return %d\n",
@@ -4775,6 +4775,14 @@ static int parse_group(o_string *dest, struct parse_context *ctx,
4775 if (ch == '(') { 4775 if (ch == '(') {
4776 endch = ')'; 4776 endch = ')';
4777 command->grp_type = GRP_SUBSHELL; 4777 command->grp_type = GRP_SUBSHELL;
4778 } else {
4779 /* bash does not allow "{echo...", requires whitespace */
4780 ch = i_getch(input);
4781 if (ch != ' ' && ch != '\t' && ch != '\n') {
4782 syntax_error_unexpected_ch(ch);
4783 return 1;
4784 }
4785 nommu_addchr(&ctx->as_string, ch);
4778 } 4786 }
4779 4787
4780 { 4788 {
@@ -5352,13 +5360,11 @@ static struct pipe *parse_stream(char **pstring,
5352 if (end_trigger && end_trigger == ch 5360 if (end_trigger && end_trigger == ch
5353 && (heredoc_cnt == 0 || end_trigger != ';') 5361 && (heredoc_cnt == 0 || end_trigger != ';')
5354 ) { 5362 ) {
5355//TODO: disallow "{ cmd }" without semicolon
5356 if (heredoc_cnt) { 5363 if (heredoc_cnt) {
5357 /* This is technically valid: 5364 /* This is technically valid:
5358 * { cat <<HERE; }; echo Ok 5365 * { cat <<HERE; }; echo Ok
5359 * heredoc 5366 * heredoc
5360 * heredoc 5367 * heredoc
5361 * heredoc
5362 * HERE 5368 * HERE
5363 * but we don't support this. 5369 * but we don't support this.
5364 * We require heredoc to be in enclosing {}/(), 5370 * We require heredoc to be in enclosing {}/(),
@@ -5370,6 +5376,15 @@ static struct pipe *parse_stream(char **pstring,
5370 if (done_word(&dest, &ctx)) { 5376 if (done_word(&dest, &ctx)) {
5371 goto parse_error; 5377 goto parse_error;
5372 } 5378 }
5379 /* Disallow "{ cmd }" without semicolon or & */
5380 //debug_printf_parse("null pi %d\n", IS_NULL_PIPE(ctx.pipe))
5381 //debug_printf_parse("null cmd %d\n", IS_NULL_CMD(ctx.command))
5382 if (ch == '}'
5383 && !(IS_NULL_PIPE(ctx.pipe) && IS_NULL_CMD(ctx.command))
5384 ) {
5385 syntax_error_unexpected_ch(ch);
5386 goto parse_error;
5387 }
5373 done_pipe(&ctx, PIPE_SEQ); 5388 done_pipe(&ctx, PIPE_SEQ);
5374 dest.o_assignment = MAYBE_ASSIGNMENT; 5389 dest.o_assignment = MAYBE_ASSIGNMENT;
5375 /* Do we sit outside of any if's, loops or case's? */ 5390 /* Do we sit outside of any if's, loops or case's? */