aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2021-06-18 16:35:27 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2021-06-18 16:35:27 +0200
commitfd217c1cbf7a702ad632bb21f7757433de1755b7 (patch)
tree7774ed226da9a29f42c7e8f236f990b0fc99bc66
parentdc30f3dce27bdcccb8450a2418061b4bcdc0ea14 (diff)
downloadbusybox-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.c87
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 { \
250if ((n) & TC_SEQSTART) debug_printf_parse(" SEQSTART"); \
251if ((n) & TC_SEQTERM ) debug_printf_parse(" SEQTERM" ); \
252if ((n) & TC_REGEXP ) debug_printf_parse(" REGEXP" ); \
253if ((n) & TC_OUTRDR ) debug_printf_parse(" OUTRDR" ); \
254if ((n) & TC_UOPPOST ) debug_printf_parse(" UOPPOST" ); \
255if ((n) & TC_UOPPRE1 ) debug_printf_parse(" UOPPRE1" ); \
256if ((n) & TC_BINOPX ) debug_printf_parse(" BINOPX" ); \
257if ((n) & TC_IN ) debug_printf_parse(" IN" ); \
258if ((n) & TC_COMMA ) debug_printf_parse(" COMMA" ); \
259if ((n) & TC_PIPE ) debug_printf_parse(" PIPE" ); \
260if ((n) & TC_UOPPRE2 ) debug_printf_parse(" UOPPRE2" ); \
261if ((n) & TC_ARRTERM ) debug_printf_parse(" ARRTERM" ); \
262if ((n) & TC_GRPSTART) debug_printf_parse(" GRPSTART"); \
263if ((n) & TC_GRPTERM ) debug_printf_parse(" GRPTERM" ); \
264if ((n) & TC_SEMICOL ) debug_printf_parse(" SEMICOL" ); \
265if ((n) & TC_NEWLINE ) debug_printf_parse(" NEWLINE" ); \
266if ((n) & TC_STATX ) debug_printf_parse(" STATX" ); \
267if ((n) & TC_WHILE ) debug_printf_parse(" WHILE" ); \
268if ((n) & TC_ELSE ) debug_printf_parse(" ELSE" ); \
269if ((n) & TC_BUILTIN ) debug_printf_parse(" BUILTIN" ); \
270if ((n) & TC_LENGTH ) debug_printf_parse(" LENGTH" ); \
271if ((n) & TC_GETLINE ) debug_printf_parse(" GETLINE" ); \
272if ((n) & TC_FUNCDECL) debug_printf_parse(" FUNCDECL"); \
273if ((n) & TC_BEGIN ) debug_printf_parse(" BEGIN" ); \
274if ((n) & TC_END ) debug_printf_parse(" END" ); \
275if ((n) & TC_EOF ) debug_printf_parse(" EOF" ); \
276if ((n) & TC_VARIABLE) debug_printf_parse(" VARIABLE"); \
277if ((n) & TC_ARRAY ) debug_printf_parse(" ARRAY" ); \
278if ((n) & TC_FUNCTION) debug_printf_parse(" FUNCTION"); \
279if ((n) & TC_STRING ) debug_printf_parse(" STRING" ); \
280if ((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
320enum { 356enum {
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 */
1269static node *parse_expr(uint32_t iexp) 1313static 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 |