From 1045066f329065a7eda6f34a8d06fd961a1c8cbd Mon Sep 17 00:00:00 2001 From: claudio Date: Tue, 16 Jan 2024 14:35:56 +0000 Subject: [PATCH] Handle variable names (things strating with $ or @) in yylex() this way the error handling of strange variable names can be better controlled. With and OK dv@ --- usr.sbin/btrace/bt_parse.y | 134 ++++++++++++++++++++++++++++--------- 1 file changed, 101 insertions(+), 33 deletions(-) diff --git a/usr.sbin/btrace/bt_parse.y b/usr.sbin/btrace/bt_parse.y index 1eb528013cd..b378b89a0cf 100644 --- a/usr.sbin/btrace/bt_parse.y +++ b/usr.sbin/btrace/bt_parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: bt_parse.y,v 1.56 2023/12/20 14:00:17 dv Exp $ */ +/* $OpenBSD: bt_parse.y,v 1.57 2024/01/16 14:35:56 claudio Exp $ */ /* * Copyright (c) 2019-2023 Martin Pieuchot @@ -123,15 +123,15 @@ static int beflag = 0; /* BEGIN/END parsing context flag */ /* Functions and Map operators */ %token F_DELETE F_PRINT %token MFUNC FUNC0 FUNC1 FUNCN OP1 OP2 OP4 MOP0 MOP1 -%token STRING CSTRING +%token STRING CSTRING GVAR LVAR +%token PVAR PNUM %token NUMBER -%type gvar lvar %type beginend %type plist probe pname %type filter %type action stmt stmtblck stmtlist block -%type vargs mentry mpat pargs staticv +%type vargs mentry mpat pargs %type expr term fterm variable factor func %% @@ -158,18 +158,7 @@ pname : STRING ':' STRING ':' STRING { $$ = bp_new($1, $3, $5, 0); } | STRING ':' HZ ':' NUMBER { $$ = bp_new($1, "hz", NULL, $5); } ; -staticv : '$' NUMBER { $$ = get_varg($2); } - | '$' '#' { $$ = get_nargs(); } - ; - -gvar : '@' STRING { $$ = $2; } - | '@' { $$ = UNNAMED_MAP; } - ; - -lvar : '$' STRING { $$ = $2; } - ; - -mentry : gvar '[' vargs ']' { $$ = bm_find($1, $3); } +mentry : GVAR '[' vargs ']' { $$ = bm_find($1, $3); } ; mpat : MOP0 '(' ')' { $$ = ba_new(NULL, $1); } @@ -212,8 +201,8 @@ fterm : fterm '*' factor { $$ = ba_op(B_AT_OP_MULT, $1, $3); } | factor ; -variable: lvar { $$ = bl_find($1); } - | gvar { $$ = bg_find($1); } +variable: LVAR { $$ = bl_find($1); } + | GVAR { $$ = bg_find($1); } | variable '.' NUMBER { $$ = bi_find($1, $3); } ; @@ -222,14 +211,15 @@ factor : '(' expr ')' { $$ = $2; } | NUMBER { $$ = ba_new($1, B_AT_LONG); } | BUILTIN { $$ = ba_new(NULL, $1); } | CSTRING { $$ = ba_new($1, B_AT_STR); } - | staticv + | PVAR + | PNUM | variable | mentry | func ; -func : STR '(' staticv ')' { $$ = ba_new($3, B_AT_FN_STR); } - | STR '(' staticv ',' expr ')' { $$ = ba_op(B_AT_FN_STR, $3, $5); } +func : STR '(' PVAR ')' { $$ = ba_new($3, B_AT_FN_STR); } + | STR '(' PVAR ',' expr ')' { $$ = ba_op(B_AT_FN_STR, $3, $5); } ; vargs : expr @@ -237,7 +227,7 @@ vargs : expr ; pargs : expr - | gvar ',' expr { $$ = ba_append(bg_find($1), $3); } + | GVAR ',' expr { $$ = ba_append(bg_find($1), $3); } ; NL : /* empty */ @@ -245,17 +235,17 @@ NL : /* empty */ ; stmt : ';' NL { $$ = NULL; } - | gvar '=' expr { $$ = bg_store($1, $3); } - | lvar '=' expr { $$ = bl_store($1, $3); } - | gvar '[' vargs ']' '=' mpat { $$ = bm_insert($1, $3, $6); } + | GVAR '=' expr { $$ = bg_store($1, $3); } + | LVAR '=' expr { $$ = bl_store($1, $3); } + | GVAR '[' vargs ']' '=' mpat { $$ = bm_insert($1, $3, $6); } | FUNCN '(' vargs ')' { $$ = bs_new($1, $3, NULL); } | FUNC1 '(' expr ')' { $$ = bs_new($1, $3, NULL); } | MFUNC '(' variable ')' { $$ = bs_new($1, $3, NULL); } | FUNC0 '(' ')' { $$ = bs_new($1, NULL, NULL); } | F_DELETE '(' mentry ')' { $$ = bm_op($1, $3, NULL); } | F_PRINT '(' pargs ')' { $$ = bs_new($1, $3, NULL); } - | gvar '=' OP1 '(' expr ')' { $$ = bh_inc($1, $5, NULL); } - | gvar '=' OP4 '(' expr ',' vargs ')' { $$ = bh_inc($1, $5, $7); } + | GVAR '=' OP1 '(' expr ')' { $$ = bh_inc($1, $5, NULL); } + | GVAR '=' OP4 '(' expr ',' vargs ')' { $$ = bh_inc($1, $5, $7); } ; stmtblck: IF '(' expr ')' block { $$ = bt_new($3, $5); } @@ -285,7 +275,7 @@ get_varg(int index) const char *errstr = NULL; long val; - if (0 < index && index <= nargs) { + if (1 <= index && index <= nargs) { val = (long)strtonum(vargs[index-1], LONG_MIN, LONG_MAX, &errstr); if (errstr == NULL) @@ -777,6 +767,19 @@ lungetc(void) } } +static inline int +allowed_to_end_number(int x) +{ + return (isspace(x) || x == ')' || x == '/' || x == '{' || x == ';' || + x == ']' || x == ',' || x == '='); +} + +static inline int +allowed_in_string(int x) +{ + return (isalnum(x) || x == '_'); +} + int yylex(void) { @@ -872,6 +875,76 @@ again: case ':': case ';': return c; + case '$': + c = lgetc(); + if (c == '#') { + yylval.v.arg = get_nargs(); + return PNUM; + } else if (isdigit(c)) { + do { + *p++ = c; + if (p == ebuf) { + yyerror("line too long"); + return ERROR; + } + } while ((c = lgetc()) != EOF && isdigit(c)); + lungetc(); + *p = '\0'; + if (c == EOF || allowed_to_end_number(c)) { + const char *errstr = NULL; + int num; + + num = strtonum(buf, 1, INT_MAX, &errstr); + if (errstr) { + yyerror("'$%s' is %s", buf, errstr); + return ERROR; + } + + yylval.v.arg = get_varg(num); + return PVAR; + } + } else if (isalpha(c)) { + do { + *p++ = c; + if (p == ebuf) { + yyerror("line too long"); + return ERROR; + } + } while ((c = lgetc()) != EOF && allowed_in_string(c)); + lungetc(); + *p = '\0'; + if ((yylval.v.string = strdup(buf)) == NULL) + err(1, "%s", __func__); + return LVAR; + } + yyerror("'$%s%c' is an invalid variable name", buf, c); + return ERROR; + break; + case '@': + c = lgetc(); + /* check for unnamed map '@' */ + if (isalpha(c)) { + do { + *p++ = c; + if (p == ebuf) { + yyerror("line too long"); + return ERROR; + } + } while ((c = lgetc()) != EOF && allowed_in_string(c)); + lungetc(); + *p = '\0'; + if ((yylval.v.string = strdup(buf)) == NULL) + err(1, "%s", __func__); + return GVAR; + } else if (allowed_to_end_number(c) || c == '[') { + lungetc(); + *p = '\0'; + yylval.v.string = UNNAMED_MAP; + return GVAR; + } + yyerror("'@%s%c' is an invalid variable name", buf, c); + return ERROR; + break; case EOF: return 0; case '"': @@ -915,9 +988,6 @@ again: break; } -#define allowed_to_end_number(x) \ - (isspace(x) || x == ')' || x == '/' || x == '{' || x == ';' || x == ']' || x == ',') - /* parsing number */ if (isdigit(c)) { do { @@ -952,8 +1022,6 @@ again: } } -#define allowed_in_string(x) (isalnum(c) || c == '_') - /* parsing next word */ if (allowed_in_string(c)) { struct keyword *kwp; -- 2.20.1