From 0325c1ba659a2ecd18c5765437b37077cf40ad5c Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Wed, 26 Mar 2014 18:20:38 -0700 Subject: [PATCH] Teach parse_util_detect_errors to report invalid builtins, as found in issue #1252 --- builtin.cpp | 2 +- parse_constants.h | 3 +++ parse_util.cpp | 13 ++++++++++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/builtin.cpp b/builtin.cpp index 4469868bb..e5ecc8422 100644 --- a/builtin.cpp +++ b/builtin.cpp @@ -3760,7 +3760,7 @@ int builtin_run(parser_t &parser, const wchar_t * const *argv, const io_chain_t } else { - debug(0, _(L"Unknown builtin '%ls'"), argv[0]); + debug(0, UNKNOWN_BUILTIN_ERR_MSG, argv[0]); } return STATUS_BUILTIN_ERROR; } diff --git a/parse_constants.h b/parse_constants.h index 31f07f60b..8ed37acdf 100644 --- a/parse_constants.h +++ b/parse_constants.h @@ -183,6 +183,9 @@ void parse_error_offset_source_start(parse_error_list_t *errors, size_t amt); /** Error message when encountering an illegal command name */ #define ILLEGAL_CMD_ERR_MSG _( L"Illegal command name '%ls'") +/** Error message when encountering an unknown builtin name */ +#define UNKNOWN_BUILTIN_ERR_MSG _( L"Unknown builtin '%ls'") + /** Error message when encountering a failed expansion, e.g. for the variable name in for loops */ #define FAILED_EXPANSION_VARIABLE_NAME_ERR_MSG _( L"Unable to expand variable name '%ls'") diff --git a/parse_util.cpp b/parse_util.cpp index d1f7a4824..0d6261612 100644 --- a/parse_util.cpp +++ b/parse_util.cpp @@ -40,6 +40,7 @@ #include "wildcard.h" #include "parse_tree.h" #include "parser.h" +#include "builtin.h" /** Error message for improper use of the exec builtin @@ -1288,8 +1289,11 @@ parser_test_error_bits_t parse_util_detect_errors(const wcstring &buff_src, pars // In a few places below, we want to know if we are in a pipeline const bool is_in_pipeline = node_tree.statement_is_in_pipeline(node, true /* count first */); + // We need to know the decoration + const enum parse_statement_decoration_t decoration = node_tree.decoration_for_plain_statement(node); + // Check that we don't try to pipe through exec - if (is_in_pipeline && node_tree.decoration_for_plain_statement(node) == parse_statement_decoration_exec) + if (is_in_pipeline && decoration == parse_statement_decoration_exec) { errored = append_syntax_error(&parse_errors, node, EXEC_ERR_MSG, L"exec"); } @@ -1380,6 +1384,13 @@ parser_test_error_bits_t parse_util_detect_errors(const wcstring &buff_src, pars errored = append_syntax_error(&parse_errors, node, (command == L"break" ? INVALID_BREAK_ERR_MSG : INVALID_CONTINUE_ERR_MSG)); } } + + // Check that we don't do an invalid builtin (#1252) + if (! errored && decoration == parse_statement_decoration_builtin && ! builtin_exists(command)) + { + errored = append_syntax_error(&parse_errors, node, UNKNOWN_BUILTIN_ERR_MSG, command.c_str()); + } + } } }