diff options
author | Brian Foley <bpfoley@google.com> | 2019-01-01 13:40:59 -0800 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2019-01-21 12:55:49 +0100 |
commit | 08a514c097f1451678940a3178a9565b9d65a193 (patch) | |
tree | f86e7566847b02108eb243ad79f25345e6ba58ec | |
parent | dac15a10accc6921d1559d254ceed9fe9d092ddf (diff) | |
download | busybox-w32-08a514c097f1451678940a3178a9565b9d65a193.tar.gz busybox-w32-08a514c097f1451678940a3178a9565b9d65a193.tar.bz2 busybox-w32-08a514c097f1451678940a3178a9565b9d65a193.zip |
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 <bpfoley@google.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/awk.c | 23 | ||||
-rwxr-xr-x | 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 { | |||
275 | | TC_STRING | TC_NUMBER | TC_UOPPOST) | 275 | | TC_STRING | TC_NUMBER | TC_UOPPOST) |
276 | #define TC_CONCAT2 (TC_OPERAND | TC_UOPPRE) | 276 | #define TC_CONCAT2 (TC_OPERAND | TC_UOPPRE) |
277 | 277 | ||
278 | #define OF_RES1 0x010000 | 278 | #define OF_RES1 0x010000 |
279 | #define OF_RES2 0x020000 | 279 | #define OF_RES2 0x020000 |
280 | #define OF_STR1 0x040000 | 280 | #define OF_STR1 0x040000 |
281 | #define OF_STR2 0x080000 | 281 | #define OF_STR2 0x080000 |
282 | #define OF_NUM1 0x100000 | 282 | #define OF_NUM1 0x100000 |
283 | #define OF_CHECKED 0x200000 | 283 | #define OF_CHECKED 0x200000 |
284 | #define OF_REQUIRED 0x400000 | ||
285 | |||
284 | 286 | ||
285 | /* combined operator flags */ | 287 | /* combined operator flags */ |
286 | #define xx 0 | 288 | #define xx 0 |
287 | #define xV OF_RES2 | 289 | #define xV OF_RES2 |
288 | #define xS (OF_RES2 | OF_STR2) | 290 | #define xS (OF_RES2 | OF_STR2) |
289 | #define Vx OF_RES1 | 291 | #define Vx OF_RES1 |
292 | #define Rx (OF_RES1 | OF_NUM1 | OF_REQUIRED) | ||
290 | #define VV (OF_RES1 | OF_RES2) | 293 | #define VV (OF_RES1 | OF_RES2) |
291 | #define Nx (OF_RES1 | OF_NUM1) | 294 | #define Nx (OF_RES1 | OF_NUM1) |
292 | #define NV (OF_RES1 | OF_NUM1 | OF_RES2) | 295 | #define NV (OF_RES1 | OF_NUM1 | OF_RES2) |
@@ -425,7 +428,7 @@ static const uint32_t tokeninfo[] = { | |||
425 | 0, | 428 | 0, |
426 | 0, /* \n */ | 429 | 0, /* \n */ |
427 | ST_IF, ST_DO, ST_FOR, OC_BREAK, | 430 | ST_IF, ST_DO, ST_FOR, OC_BREAK, |
428 | OC_CONTINUE, OC_DELETE|Vx, OC_PRINT, | 431 | OC_CONTINUE, OC_DELETE|Rx, OC_PRINT, |
429 | OC_PRINTF, OC_NEXT, OC_NEXTFILE, | 432 | OC_PRINTF, OC_NEXT, OC_NEXTFILE, |
430 | OC_RETURN|Vx, OC_EXIT|Nx, | 433 | OC_RETURN|Vx, OC_EXIT|Nx, |
431 | ST_WHILE, | 434 | ST_WHILE, |
@@ -593,7 +596,7 @@ static const char EMSG_UNEXP_EOS[] ALIGN1 = "Unexpected end of string"; | |||
593 | static const char EMSG_UNEXP_TOKEN[] ALIGN1 = "Unexpected token"; | 596 | static const char EMSG_UNEXP_TOKEN[] ALIGN1 = "Unexpected token"; |
594 | static const char EMSG_DIV_BY_ZERO[] ALIGN1 = "Division by zero"; | 597 | static const char EMSG_DIV_BY_ZERO[] ALIGN1 = "Division by zero"; |
595 | static const char EMSG_INV_FMT[] ALIGN1 = "Invalid format specifier"; | 598 | static const char EMSG_INV_FMT[] ALIGN1 = "Invalid format specifier"; |
596 | static const char EMSG_TOO_FEW_ARGS[] ALIGN1 = "Too few arguments for builtin"; | 599 | static const char EMSG_TOO_FEW_ARGS[] ALIGN1 = "Too few arguments"; |
597 | static const char EMSG_NOT_ARRAY[] ALIGN1 = "Not an array"; | 600 | static const char EMSG_NOT_ARRAY[] ALIGN1 = "Not an array"; |
598 | static const char EMSG_POSSIBLE_ERROR[] ALIGN1 = "Possible syntax error"; | 601 | static const char EMSG_POSSIBLE_ERROR[] ALIGN1 = "Possible syntax error"; |
599 | static const char EMSG_UNDEF_FUNC[] ALIGN1 = "Call to undefined function"; | 602 | static const char EMSG_UNDEF_FUNC[] ALIGN1 = "Call to undefined function"; |
@@ -1426,7 +1429,11 @@ static void chain_expr(uint32_t info) | |||
1426 | node *n; | 1429 | node *n; |
1427 | 1430 | ||
1428 | n = chain_node(info); | 1431 | n = chain_node(info); |
1432 | |||
1429 | n->l.n = parse_expr(TC_OPTERM | TC_GRPTERM); | 1433 | n->l.n = parse_expr(TC_OPTERM | TC_GRPTERM); |
1434 | if ((info & OF_REQUIRED) && !n->l.n) | ||
1435 | syntax_error(EMSG_TOO_FEW_ARGS); | ||
1436 | |||
1430 | if (t_tclass & TC_GRPTERM) | 1437 | if (t_tclass & TC_GRPTERM) |
1431 | rollback_token(); | 1438 | rollback_token(); |
1432 | } | 1439 | } |
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" \ | |||
336 | 'BEGIN { if (1) continue; else a = 1 }' | 336 | 'BEGIN { if (1) continue; else a = 1 }' |
337 | 337 | ||
338 | testing "awk handles invalid for loop" \ | 338 | testing "awk handles invalid for loop" \ |
339 | "awk '{ for() }' 2>&1" "awk: cmd. line:1: Unexpected token\n" "" "" | 339 | "awk -e '{ for() }' 2>&1" "awk: cmd. line:1: Unexpected token\n" "" "" |
340 | 340 | ||
341 | testing "awk handles colon not preceded by ternary" \ | 341 | testing "awk handles colon not preceded by ternary" \ |
342 | "awk 'foo:bar:' 2>&1" "awk: cmd. line:1: Unexpected token\n" "" "" | 342 | "awk -e foo:bar: 2>&1" "awk: cmd. line:1: Unexpected token\n" "" "" |
343 | |||
344 | testing "awk errors on missing delete arg" \ | ||
345 | "awk -e '{delete}' 2>&1" "awk: cmd. line:1: Too few arguments\n" "" "" | ||
343 | 346 | ||
344 | # testing "description" "command" "result" "infile" "stdin" | 347 | # testing "description" "command" "result" "infile" "stdin" |
345 | testing 'awk negative field access' \ | 348 | testing 'awk negative field access' \ |