diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2021-06-18 16:35:27 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-06-18 16:35:27 +0200 |
commit | fd217c1cbf7a702ad632bb21f7757433de1755b7 (patch) | |
tree | 7774ed226da9a29f42c7e8f236f990b0fc99bc66 | |
parent | dc30f3dce27bdcccb8450a2418061b4bcdc0ea14 (diff) | |
download | busybox-w32-fd217c1cbf7a702ad632bb21f7757433de1755b7.tar.gz busybox-w32-fd217c1cbf7a702ad632bb21f7757433de1755b7.tar.bz2 busybox-w32-fd217c1cbf7a702ad632bb21f7757433de1755b7.zip |
awk: after preinc/dec, only allow variable, field ref, array ref, or another preinc/dec
Accepting nonsense like "--4", and even "-- -4" is confusing.
function old new delta
parse_expr 917 938 +21
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/awk.c | 87 |
1 files changed, 69 insertions, 18 deletions
diff --git a/editors/awk.c b/editors/awk.c index 48836298c..2563722f9 100644 --- a/editors/awk.c +++ b/editors/awk.c | |||
@@ -66,6 +66,8 @@ | |||
66 | #endif | 66 | #endif |
67 | #ifndef debug_printf_parse | 67 | #ifndef debug_printf_parse |
68 | # define debug_printf_parse(...) (fprintf(stderr, __VA_ARGS__)) | 68 | # define debug_printf_parse(...) (fprintf(stderr, __VA_ARGS__)) |
69 | #else | ||
70 | # define debug_parse_print_tc(...) ((void)0) | ||
69 | #endif | 71 | #endif |
70 | 72 | ||
71 | 73 | ||
@@ -210,13 +212,13 @@ typedef struct tsplitter_s { | |||
210 | #define TC_SEQTERM (1 << 1) /* ) */ | 212 | #define TC_SEQTERM (1 << 1) /* ) */ |
211 | #define TC_REGEXP (1 << 2) /* /.../ */ | 213 | #define TC_REGEXP (1 << 2) /* /.../ */ |
212 | #define TC_OUTRDR (1 << 3) /* | > >> */ | 214 | #define TC_OUTRDR (1 << 3) /* | > >> */ |
213 | #define TC_UOPPOST (1 << 4) /* unary postfix operator */ | 215 | #define TC_UOPPOST (1 << 4) /* unary postfix operator ++ -- */ |
214 | #define TC_UOPPRE1 (1 << 5) /* unary prefix operator */ | 216 | #define TC_UOPPRE1 (1 << 5) /* unary prefix operator ++ -- $ */ |
215 | #define TC_BINOPX (1 << 6) /* two-opnd operator */ | 217 | #define TC_BINOPX (1 << 6) /* two-opnd operator */ |
216 | #define TC_IN (1 << 7) | 218 | #define TC_IN (1 << 7) |
217 | #define TC_COMMA (1 << 8) | 219 | #define TC_COMMA (1 << 8) |
218 | #define TC_PIPE (1 << 9) /* input redirection pipe */ | 220 | #define TC_PIPE (1 << 9) /* input redirection pipe */ |
219 | #define TC_UOPPRE2 (1 << 10) /* unary prefix operator */ | 221 | #define TC_UOPPRE2 (1 << 10) /* unary prefix operator + - ! */ |
220 | #define TC_ARRTERM (1 << 11) /* ] */ | 222 | #define TC_ARRTERM (1 << 11) /* ] */ |
221 | #define TC_GRPSTART (1 << 12) /* { */ | 223 | #define TC_GRPSTART (1 << 12) /* { */ |
222 | #define TC_GRPTERM (1 << 13) /* } */ | 224 | #define TC_GRPTERM (1 << 13) /* } */ |
@@ -243,14 +245,51 @@ typedef struct tsplitter_s { | |||
243 | #define TC_STRING (1 << 29) | 245 | #define TC_STRING (1 << 29) |
244 | #define TC_NUMBER (1 << 30) | 246 | #define TC_NUMBER (1 << 30) |
245 | 247 | ||
246 | #define TC_UOPPRE (TC_UOPPRE1 | TC_UOPPRE2) | 248 | #ifndef debug_parse_print_tc |
249 | #define debug_parse_print_tc(n) do { \ | ||
250 | if ((n) & TC_SEQSTART) debug_printf_parse(" SEQSTART"); \ | ||
251 | if ((n) & TC_SEQTERM ) debug_printf_parse(" SEQTERM" ); \ | ||
252 | if ((n) & TC_REGEXP ) debug_printf_parse(" REGEXP" ); \ | ||
253 | if ((n) & TC_OUTRDR ) debug_printf_parse(" OUTRDR" ); \ | ||
254 | if ((n) & TC_UOPPOST ) debug_printf_parse(" UOPPOST" ); \ | ||
255 | if ((n) & TC_UOPPRE1 ) debug_printf_parse(" UOPPRE1" ); \ | ||
256 | if ((n) & TC_BINOPX ) debug_printf_parse(" BINOPX" ); \ | ||
257 | if ((n) & TC_IN ) debug_printf_parse(" IN" ); \ | ||
258 | if ((n) & TC_COMMA ) debug_printf_parse(" COMMA" ); \ | ||
259 | if ((n) & TC_PIPE ) debug_printf_parse(" PIPE" ); \ | ||
260 | if ((n) & TC_UOPPRE2 ) debug_printf_parse(" UOPPRE2" ); \ | ||
261 | if ((n) & TC_ARRTERM ) debug_printf_parse(" ARRTERM" ); \ | ||
262 | if ((n) & TC_GRPSTART) debug_printf_parse(" GRPSTART"); \ | ||
263 | if ((n) & TC_GRPTERM ) debug_printf_parse(" GRPTERM" ); \ | ||
264 | if ((n) & TC_SEMICOL ) debug_printf_parse(" SEMICOL" ); \ | ||
265 | if ((n) & TC_NEWLINE ) debug_printf_parse(" NEWLINE" ); \ | ||
266 | if ((n) & TC_STATX ) debug_printf_parse(" STATX" ); \ | ||
267 | if ((n) & TC_WHILE ) debug_printf_parse(" WHILE" ); \ | ||
268 | if ((n) & TC_ELSE ) debug_printf_parse(" ELSE" ); \ | ||
269 | if ((n) & TC_BUILTIN ) debug_printf_parse(" BUILTIN" ); \ | ||
270 | if ((n) & TC_LENGTH ) debug_printf_parse(" LENGTH" ); \ | ||
271 | if ((n) & TC_GETLINE ) debug_printf_parse(" GETLINE" ); \ | ||
272 | if ((n) & TC_FUNCDECL) debug_printf_parse(" FUNCDECL"); \ | ||
273 | if ((n) & TC_BEGIN ) debug_printf_parse(" BEGIN" ); \ | ||
274 | if ((n) & TC_END ) debug_printf_parse(" END" ); \ | ||
275 | if ((n) & TC_EOF ) debug_printf_parse(" EOF" ); \ | ||
276 | if ((n) & TC_VARIABLE) debug_printf_parse(" VARIABLE"); \ | ||
277 | if ((n) & TC_ARRAY ) debug_printf_parse(" ARRAY" ); \ | ||
278 | if ((n) & TC_FUNCTION) debug_printf_parse(" FUNCTION"); \ | ||
279 | if ((n) & TC_STRING ) debug_printf_parse(" STRING" ); \ | ||
280 | if ((n) & TC_NUMBER ) debug_printf_parse(" NUMBER" ); \ | ||
281 | } while (0) | ||
282 | #endif | ||
247 | 283 | ||
248 | /* combined token classes */ | 284 | /* combined token classes */ |
285 | #define TC_UOPPRE (TC_UOPPRE1 | TC_UOPPRE2) | ||
286 | |||
249 | #define TC_BINOP (TC_BINOPX | TC_COMMA | TC_PIPE | TC_IN) | 287 | #define TC_BINOP (TC_BINOPX | TC_COMMA | TC_PIPE | TC_IN) |
250 | //#define TC_UNARYOP (TC_UOPPRE | TC_UOPPOST) | 288 | //#define TC_UNARYOP (TC_UOPPRE | TC_UOPPOST) |
251 | #define TC_OPERAND (TC_VARIABLE | TC_ARRAY | TC_FUNCTION \ | 289 | #define TC_OPERAND (TC_VARIABLE | TC_ARRAY | TC_FUNCTION \ |
252 | | TC_BUILTIN | TC_LENGTH | TC_GETLINE \ | 290 | | TC_BUILTIN | TC_LENGTH | TC_GETLINE \ |
253 | | TC_SEQSTART | TC_STRING | TC_NUMBER) | 291 | | TC_SEQSTART | TC_STRING | TC_NUMBER) |
292 | #define TC_LVALUE (TC_VARIABLE | TC_ARRAY) | ||
254 | 293 | ||
255 | #define TC_STATEMNT (TC_STATX | TC_WHILE) | 294 | #define TC_STATEMNT (TC_STATX | TC_WHILE) |
256 | #define TC_OPTERM (TC_SEMICOL | TC_NEWLINE) | 295 | #define TC_OPTERM (TC_SEMICOL | TC_NEWLINE) |
@@ -284,7 +323,6 @@ typedef struct tsplitter_s { | |||
284 | #define OF_CHECKED 0x200000 | 323 | #define OF_CHECKED 0x200000 |
285 | #define OF_REQUIRED 0x400000 | 324 | #define OF_REQUIRED 0x400000 |
286 | 325 | ||
287 | |||
288 | /* combined operator flags */ | 326 | /* combined operator flags */ |
289 | #define xx 0 | 327 | #define xx 0 |
290 | #define xV OF_RES2 | 328 | #define xV OF_RES2 |
@@ -313,10 +351,8 @@ typedef struct tsplitter_s { | |||
313 | #define PRIMASK2 0x7E000000 | 351 | #define PRIMASK2 0x7E000000 |
314 | 352 | ||
315 | /* Operation classes */ | 353 | /* Operation classes */ |
316 | |||
317 | #define SHIFT_TIL_THIS 0x0600 | 354 | #define SHIFT_TIL_THIS 0x0600 |
318 | #define RECUR_FROM_THIS 0x1000 | 355 | #define RECUR_FROM_THIS 0x1000 |
319 | |||
320 | enum { | 356 | enum { |
321 | OC_DELETE = 0x0100, OC_EXEC = 0x0200, OC_NEWSOURCE = 0x0300, | 357 | OC_DELETE = 0x0100, OC_EXEC = 0x0200, OC_NEWSOURCE = 0x0300, |
322 | OC_PRINT = 0x0400, OC_PRINTF = 0x0500, OC_WALKINIT = 0x0600, | 358 | OC_PRINT = 0x0400, OC_PRINTF = 0x0500, OC_WALKINIT = 0x0600, |
@@ -411,7 +447,9 @@ static const uint32_t tokeninfo[] ALIGN4 = { | |||
411 | OC_REGEXP, | 447 | OC_REGEXP, |
412 | xS|'a', xS|'w', xS|'|', | 448 | xS|'a', xS|'w', xS|'|', |
413 | OC_UNARY|xV|P(9)|'p', OC_UNARY|xV|P(9)|'m', | 449 | OC_UNARY|xV|P(9)|'p', OC_UNARY|xV|P(9)|'m', |
414 | OC_UNARY|xV|P(9)|'P', OC_UNARY|xV|P(9)|'M', OC_FIELD|xV|P(5), | 450 | #define TI_PREINC (OC_UNARY|xV|P(9)|'P') |
451 | #define TI_PREDEC (OC_UNARY|xV|P(9)|'M') | ||
452 | TI_PREINC, TI_PREDEC, OC_FIELD|xV|P(5), | ||
415 | OC_COMPARE|VV|P(39)|5, OC_MOVE|VV|P(74), OC_REPLACE|NV|P(74)|'+', OC_REPLACE|NV|P(74)|'-', | 453 | OC_COMPARE|VV|P(39)|5, OC_MOVE|VV|P(74), OC_REPLACE|NV|P(74)|'+', OC_REPLACE|NV|P(74)|'-', |
416 | OC_REPLACE|NV|P(74)|'*', OC_REPLACE|NV|P(74)|'/', OC_REPLACE|NV|P(74)|'%', OC_REPLACE|NV|P(74)|'&', | 454 | OC_REPLACE|NV|P(74)|'*', OC_REPLACE|NV|P(74)|'/', OC_REPLACE|NV|P(74)|'%', OC_REPLACE|NV|P(74)|'&', |
417 | OC_BINARY|NV|P(29)|'+', OC_BINARY|NV|P(29)|'-', OC_REPLACE|NV|P(74)|'&', OC_BINARY|NV|P(15)|'&', | 455 | OC_BINARY|NV|P(29)|'+', OC_BINARY|NV|P(29)|'-', OC_REPLACE|NV|P(74)|'&', OC_BINARY|NV|P(15)|'&', |
@@ -1070,6 +1108,10 @@ static uint32_t next_token(uint32_t expected) | |||
1070 | uint32_t tc; | 1108 | uint32_t tc; |
1071 | const uint32_t *ti; | 1109 | const uint32_t *ti; |
1072 | 1110 | ||
1111 | debug_printf_parse("%s() expected(%x):", __func__, expected); | ||
1112 | debug_parse_print_tc(expected); | ||
1113 | debug_printf_parse("\n"); | ||
1114 | |||
1073 | if (t_rollback) { | 1115 | if (t_rollback) { |
1074 | debug_printf_parse("%s: using rolled-back token\n", __func__); | 1116 | debug_printf_parse("%s: using rolled-back token\n", __func__); |
1075 | t_rollback = FALSE; | 1117 | t_rollback = FALSE; |
@@ -1226,7 +1268,9 @@ static uint32_t next_token(uint32_t expected) | |||
1226 | EMSG_UNEXP_EOS : EMSG_UNEXP_TOKEN); | 1268 | EMSG_UNEXP_EOS : EMSG_UNEXP_TOKEN); |
1227 | } | 1269 | } |
1228 | 1270 | ||
1229 | debug_printf_parse("%s: returning, ltclass:%x t_double:%f\n", __func__, ltclass, t_double); | 1271 | debug_printf_parse("%s: returning, t_double:%f ltclass:", __func__, t_double); |
1272 | debug_parse_print_tc(ltclass); | ||
1273 | debug_printf_parse("\n"); | ||
1230 | return ltclass; | 1274 | return ltclass; |
1231 | #undef concat_inserted | 1275 | #undef concat_inserted |
1232 | #undef save_tclass | 1276 | #undef save_tclass |
@@ -1266,7 +1310,7 @@ static node *condition(void) | |||
1266 | 1310 | ||
1267 | /* parse expression terminated by given argument, return ptr | 1311 | /* parse expression terminated by given argument, return ptr |
1268 | * to built subtree. Terminator is eaten by parse_expr */ | 1312 | * to built subtree. Terminator is eaten by parse_expr */ |
1269 | static node *parse_expr(uint32_t iexp) | 1313 | static node *parse_expr(uint32_t term_tc) |
1270 | { | 1314 | { |
1271 | node sn; | 1315 | node sn; |
1272 | node *cn = &sn; | 1316 | node *cn = &sn; |
@@ -1274,13 +1318,15 @@ static node *parse_expr(uint32_t iexp) | |||
1274 | uint32_t tc, xtc; | 1318 | uint32_t tc, xtc; |
1275 | var *v; | 1319 | var *v; |
1276 | 1320 | ||
1277 | debug_printf_parse("%s(%x)\n", __func__, iexp); | 1321 | debug_printf_parse("%s() term_tc(%x):", __func__, term_tc); |
1322 | debug_parse_print_tc(term_tc); | ||
1323 | debug_printf_parse("\n"); | ||
1278 | 1324 | ||
1279 | sn.info = PRIMASK; | 1325 | sn.info = PRIMASK; |
1280 | sn.r.n = sn.a.n = glptr = NULL; | 1326 | sn.r.n = sn.a.n = glptr = NULL; |
1281 | xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP | iexp; | 1327 | xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP | term_tc; |
1282 | 1328 | ||
1283 | while (!((tc = next_token(xtc)) & iexp)) { | 1329 | while (!((tc = next_token(xtc)) & term_tc)) { |
1284 | 1330 | ||
1285 | if (glptr && (t_info == (OC_COMPARE | VV | P(39) | 2))) { | 1331 | if (glptr && (t_info == (OC_COMPARE | VV | P(39) | 2))) { |
1286 | /* input redirection (<) attached to glptr node */ | 1332 | /* input redirection (<) attached to glptr node */ |
@@ -1313,25 +1359,28 @@ static node *parse_expr(uint32_t iexp) | |||
1313 | next_token(TC_GETLINE); | 1359 | next_token(TC_GETLINE); |
1314 | /* give maximum priority to this pipe */ | 1360 | /* give maximum priority to this pipe */ |
1315 | cn->info &= ~PRIMASK; | 1361 | cn->info &= ~PRIMASK; |
1316 | xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | iexp; | 1362 | xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | term_tc; |
1317 | } | 1363 | } |
1318 | } else { | 1364 | } else { |
1319 | cn->r.n = vn; | 1365 | cn->r.n = vn; |
1320 | xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | iexp; | 1366 | xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | term_tc; |
1321 | } | 1367 | } |
1322 | vn->a.n = cn; | 1368 | vn->a.n = cn; |
1323 | 1369 | ||
1324 | } else { | 1370 | } else { |
1325 | debug_printf_parse("%s: other\n", __func__); | 1371 | debug_printf_parse("%s: other, t_info:%x\n", __func__, t_info); |
1326 | /* for operands and prefix-unary operators, attach them | 1372 | /* for operands and prefix-unary operators, attach them |
1327 | * to last node */ | 1373 | * to last node */ |
1328 | vn = cn; | 1374 | vn = cn; |
1329 | cn = vn->r.n = new_node(t_info); | 1375 | cn = vn->r.n = new_node(t_info); |
1330 | cn->a.n = vn; | 1376 | cn->a.n = vn; |
1377 | |||
1331 | xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP; | 1378 | xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP; |
1379 | if (t_info == TI_PREINC || t_info == TI_PREDEC) | ||
1380 | xtc = TC_LVALUE | TC_UOPPRE1; | ||
1332 | if (tc & (TC_OPERAND | TC_REGEXP)) { | 1381 | if (tc & (TC_OPERAND | TC_REGEXP)) { |
1333 | debug_printf_parse("%s: TC_OPERAND | TC_REGEXP\n", __func__); | 1382 | debug_printf_parse("%s: TC_OPERAND | TC_REGEXP\n", __func__); |
1334 | xtc = TC_UOPPRE | TC_UOPPOST | TC_BINOP | TC_OPERAND | iexp; | 1383 | xtc = TC_UOPPRE | TC_UOPPOST | TC_BINOP | TC_OPERAND | term_tc; |
1335 | /* one should be very careful with switch on tclass - | 1384 | /* one should be very careful with switch on tclass - |
1336 | * only simple tclasses should be used! */ | 1385 | * only simple tclasses should be used! */ |
1337 | switch (tc) { | 1386 | switch (tc) { |
@@ -1388,7 +1437,7 @@ static node *parse_expr(uint32_t iexp) | |||
1388 | case TC_GETLINE: | 1437 | case TC_GETLINE: |
1389 | debug_printf_parse("%s: TC_GETLINE\n", __func__); | 1438 | debug_printf_parse("%s: TC_GETLINE\n", __func__); |
1390 | glptr = cn; | 1439 | glptr = cn; |
1391 | xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | iexp; | 1440 | xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | term_tc; |
1392 | break; | 1441 | break; |
1393 | 1442 | ||
1394 | case TC_BUILTIN: | 1443 | case TC_BUILTIN: |
@@ -1603,6 +1652,8 @@ static void parse_program(char *p) | |||
1603 | func *f; | 1652 | func *f; |
1604 | var *v; | 1653 | var *v; |
1605 | 1654 | ||
1655 | debug_printf_parse("%s()\n", __func__); | ||
1656 | |||
1606 | g_pos = p; | 1657 | g_pos = p; |
1607 | t_lineno = 1; | 1658 | t_lineno = 1; |
1608 | while ((tclass = next_token(TC_EOF | TC_OPSEQ | TC_GRPSTART | | 1659 | while ((tclass = next_token(TC_EOF | TC_OPSEQ | TC_GRPSTART | |