From 08a514c097f1451678940a3178a9565b9d65a193 Mon Sep 17 00:00:00 2001 From: Brian Foley Date: Tue, 1 Jan 2019 13:40:59 -0800 Subject: [PATCH] awk: Syntax error if delete isn't given an arg. Unlike exit and return, delete strictly requires an arg, and derefs a null pointer if executed without one. Signed-off-by: Brian Foley Signed-off-by: Denys Vlasenko --- editors/awk.c | 23 +++++++++++++++-------- testsuite/awk.tests | 7 +++++-- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/editors/awk.c b/editors/awk.c index f2b8b13eb..90edec82c 100644 --- a/editors/awk.c +++ b/editors/awk.c @@ -275,18 +275,21 @@ typedef struct tsplitter_s { | TC_STRING | TC_NUMBER | TC_UOPPOST) #define TC_CONCAT2 (TC_OPERAND | TC_UOPPRE) -#define OF_RES1 0x010000 -#define OF_RES2 0x020000 -#define OF_STR1 0x040000 -#define OF_STR2 0x080000 -#define OF_NUM1 0x100000 -#define OF_CHECKED 0x200000 +#define OF_RES1 0x010000 +#define OF_RES2 0x020000 +#define OF_STR1 0x040000 +#define OF_STR2 0x080000 +#define OF_NUM1 0x100000 +#define OF_CHECKED 0x200000 +#define OF_REQUIRED 0x400000 + /* combined operator flags */ #define xx 0 #define xV OF_RES2 #define xS (OF_RES2 | OF_STR2) #define Vx OF_RES1 +#define Rx (OF_RES1 | OF_NUM1 | OF_REQUIRED) #define VV (OF_RES1 | OF_RES2) #define Nx (OF_RES1 | OF_NUM1) #define NV (OF_RES1 | OF_NUM1 | OF_RES2) @@ -425,7 +428,7 @@ static const uint32_t tokeninfo[] = { 0, 0, /* \n */ ST_IF, ST_DO, ST_FOR, OC_BREAK, - OC_CONTINUE, OC_DELETE|Vx, OC_PRINT, + OC_CONTINUE, OC_DELETE|Rx, OC_PRINT, OC_PRINTF, OC_NEXT, OC_NEXTFILE, OC_RETURN|Vx, OC_EXIT|Nx, ST_WHILE, @@ -593,7 +596,7 @@ static const char EMSG_UNEXP_EOS[] ALIGN1 = "Unexpected end of string"; static const char EMSG_UNEXP_TOKEN[] ALIGN1 = "Unexpected token"; static const char EMSG_DIV_BY_ZERO[] ALIGN1 = "Division by zero"; static const char EMSG_INV_FMT[] ALIGN1 = "Invalid format specifier"; -static const char EMSG_TOO_FEW_ARGS[] ALIGN1 = "Too few arguments for builtin"; +static const char EMSG_TOO_FEW_ARGS[] ALIGN1 = "Too few arguments"; static const char EMSG_NOT_ARRAY[] ALIGN1 = "Not an array"; static const char EMSG_POSSIBLE_ERROR[] ALIGN1 = "Possible syntax error"; static const char EMSG_UNDEF_FUNC[] ALIGN1 = "Call to undefined function"; @@ -1426,7 +1429,11 @@ static void chain_expr(uint32_t info) node *n; n = chain_node(info); + n->l.n = parse_expr(TC_OPTERM | TC_GRPTERM); + if ((info & OF_REQUIRED) && !n->l.n) + syntax_error(EMSG_TOO_FEW_ARGS); + if (t_tclass & TC_GRPTERM) rollback_token(); } diff --git a/testsuite/awk.tests b/testsuite/awk.tests index 9f353fc10..03fedf771 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests @@ -336,10 +336,13 @@ testing "awk continue" \ 'BEGIN { if (1) continue; else a = 1 }' testing "awk handles invalid for loop" \ - "awk '{ for() }' 2>&1" "awk: cmd. line:1: Unexpected token\n" "" "" + "awk -e '{ for() }' 2>&1" "awk: cmd. line:1: Unexpected token\n" "" "" testing "awk handles colon not preceded by ternary" \ - "awk 'foo:bar:' 2>&1" "awk: cmd. line:1: Unexpected token\n" "" "" + "awk -e foo:bar: 2>&1" "awk: cmd. line:1: Unexpected token\n" "" "" + +testing "awk errors on missing delete arg" \ + "awk -e '{delete}' 2>&1" "awk: cmd. line:1: Too few arguments\n" "" "" # testing "description" "command" "result" "infile" "stdin" testing 'awk negative field access' \