dfilter: Improve grammar to parse functions
A function is grammatically an identifier that is followed by '(' and ')' according to some rules. We should avoid assuming a token is a function just because it matches a registered function name. Before: Filter: foobar(http.user_agent) contains "UPDATE" dftest: Syntax error near "(". After: Filter: foobar(http.user_agent) contains "UPDATE" dftest: The function 'foobar' does not exist. This has the problem that a function cannot have the same name as a protocol but that limitation already existed before.
This commit is contained in:
parent
db85625af9
commit
92285e6258
|
@ -72,6 +72,9 @@ extern stnode_t *df_lval;
|
|||
void
|
||||
dfilter_fail(dfwork_t *dfw, const char *format, ...) G_GNUC_PRINTF(2, 3);
|
||||
|
||||
void
|
||||
dfilter_parse_fail(dfwork_t *dfw, const char *format, ...) G_GNUC_PRINTF(2, 3);
|
||||
|
||||
void
|
||||
add_deprecated_token(GPtrArray *deprecated, const char *token);
|
||||
|
||||
|
@ -81,6 +84,9 @@ free_deprecated(GPtrArray *deprecated);
|
|||
void
|
||||
DfilterTrace(FILE *TraceFILE, char *zTracePrompt);
|
||||
|
||||
stnode_t *
|
||||
dfilter_new_function(dfwork_t *dfw, const char *name);
|
||||
|
||||
const char *tokenstr(int token);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -37,18 +37,45 @@ static void* ParserObj = NULL;
|
|||
*/
|
||||
dfwork_t *global_dfw;
|
||||
|
||||
static void
|
||||
dfilter_vfail(dfwork_t *dfw, const char *format, va_list args)
|
||||
{
|
||||
/* If we've already reported one error, don't overwite it */
|
||||
if (dfw->error_message != NULL)
|
||||
return;
|
||||
|
||||
dfw->error_message = g_strdup_vprintf(format, args);
|
||||
}
|
||||
|
||||
void
|
||||
dfilter_fail(dfwork_t *dfw, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
/* If we've already reported one error, don't overwite it */
|
||||
if (dfw->error_message != NULL)
|
||||
return;
|
||||
va_start(args, format);
|
||||
dfilter_vfail(dfw, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void
|
||||
dfilter_parse_fail(dfwork_t *dfw, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
dfw->error_message = g_strdup_vprintf(format, args);
|
||||
dfilter_vfail(dfw, format, args);
|
||||
va_end(args);
|
||||
dfw->syntax_error = TRUE;
|
||||
}
|
||||
|
||||
stnode_t *
|
||||
dfilter_new_function(dfwork_t *dfw, const char *name)
|
||||
{
|
||||
df_func_def_t *def = df_func_lookup(name);
|
||||
if (!def) {
|
||||
dfilter_parse_fail(dfw, "Function '%s' does not exist", name);
|
||||
}
|
||||
return stnode_new(STTYPE_FUNCTION, def, name);
|
||||
}
|
||||
|
||||
/* Initialize the dfilter module */
|
||||
|
@ -228,7 +255,6 @@ const char *tokenstr(int token)
|
|||
case TOKEN_RBRACE: return "RBRACE";
|
||||
case TOKEN_WHITESPACE: return "WHITESPACE";
|
||||
case TOKEN_DOTDOT: return "DOTDOT";
|
||||
case TOKEN_FUNCTION: return "FUNCTION";
|
||||
case TOKEN_LPAREN: return "LPAREN";
|
||||
case TOKEN_RPAREN: return "RPAREN";
|
||||
default: return "<unknown>";
|
||||
|
|
|
@ -318,7 +318,7 @@ df_functions[] = {
|
|||
|
||||
/* Lookup a display filter function record by name */
|
||||
df_func_def_t*
|
||||
df_func_lookup(char *name)
|
||||
df_func_lookup(const char *name)
|
||||
{
|
||||
df_func_def_t *func_def;
|
||||
|
||||
|
|
|
@ -37,6 +37,6 @@ typedef struct {
|
|||
} df_func_def_t;
|
||||
|
||||
/* Return the function definition record for a function of named "name" */
|
||||
df_func_def_t* df_func_lookup(char *name);
|
||||
df_func_def_t* df_func_lookup(const char *name);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -104,14 +104,11 @@ any "error" symbols are shifted, if possible. */
|
|||
hfinfo = (header_field_info *)stnode_data(TOKEN);
|
||||
dfilter_fail(dfw, "Syntax error near \"%s\".", hfinfo->abbrev);
|
||||
break;
|
||||
case STTYPE_FUNCTION:
|
||||
dfilter_fail(dfw, "The function \"%s\" was unexpected in this context.",
|
||||
sttype_function_funcdef(TOKEN)->name);
|
||||
break;
|
||||
/* These aren't handed to use as terminal tokens from
|
||||
the scanner, so was can assert that we'll never
|
||||
see them here. */
|
||||
case STTYPE_NUM_TYPES:
|
||||
case STTYPE_FUNCTION:
|
||||
case STTYPE_RANGE:
|
||||
case STTYPE_FVALUE:
|
||||
case STTYPE_PCRE:
|
||||
|
@ -331,16 +328,18 @@ set_node_list(L) ::= set_node_list(P) WHITESPACE entity(X) DOTDOT entity(Y).
|
|||
/* Functions */
|
||||
|
||||
/* A function can have one or more parameters */
|
||||
function(G) ::= FUNCTION(F) LPAREN function_params(P) RPAREN.
|
||||
function(F) ::= UNPARSED(U) LPAREN function_params(P) RPAREN.
|
||||
{
|
||||
G = F;
|
||||
sttype_function_set_params(G, P);
|
||||
F = dfilter_new_function(dfw, stnode_token_value(U));
|
||||
stnode_free(U);
|
||||
sttype_function_set_params(F, P);
|
||||
}
|
||||
|
||||
/* A function can have zero parameters. */
|
||||
function(G) ::= FUNCTION(F) LPAREN RPAREN.
|
||||
function(F) ::= UNPARSED(U) LPAREN RPAREN.
|
||||
{
|
||||
G = F;
|
||||
F = dfilter_new_function(dfw, stnode_token_value(U));
|
||||
stnode_free(U);
|
||||
}
|
||||
|
||||
function_params(P) ::= entity(E).
|
||||
|
|
|
@ -86,7 +86,6 @@ DIAG_OFF_FLEX
|
|||
|
||||
static int set_lval_str(int token, const char *token_value);
|
||||
static int set_lval_field(int token, header_field_info *hfinfo, const char *token_value);
|
||||
static int set_lval_func(int token, df_func_def_t *func, const char *token_value);
|
||||
static int set_lval_int(dfwork_t *dfw, int token, const char *token_value);
|
||||
static int simple(int token, const char *token_value);
|
||||
#define SIMPLE(token) simple(token, yytext)
|
||||
|
@ -401,7 +400,6 @@ static gboolean str_to_gint32(dfwork_t *dfw, const char *s, gint32* pint);
|
|||
[-+[:alnum:]_:]+([.][-+[:alnum:]_:]+)*[.]{0,2} {
|
||||
/* Is it a field name or some other value (float, integer, bytes, ...)? */
|
||||
header_field_info *hfinfo;
|
||||
df_func_def_t *df_func_def;
|
||||
|
||||
/* Trailing dot is allowed for floats, but make sure that trailing ".."
|
||||
* is interpreted as a token on its own. */
|
||||
|
@ -422,11 +420,6 @@ static gboolean str_to_gint32(dfwork_t *dfw, const char *s, gint32* pint);
|
|||
return set_lval_field(TOKEN_FIELD, hfinfo, yytext);
|
||||
}
|
||||
|
||||
df_func_def = df_func_lookup(yytext);
|
||||
if (df_func_def) {
|
||||
/* Yes, it's a dfilter function */
|
||||
return set_lval_func(TOKEN_FUNCTION, df_func_def, yytext);
|
||||
}
|
||||
/* No match, so treat it as an unparsed string */
|
||||
return set_lval_str(TOKEN_UNPARSED, yytext);
|
||||
}
|
||||
|
@ -510,14 +503,6 @@ set_lval_field(int token, header_field_info *hfinfo, const char *token_value)
|
|||
return token;
|
||||
}
|
||||
|
||||
static int
|
||||
set_lval_func(int token, df_func_def_t *func, const char *token_value)
|
||||
{
|
||||
ws_assert(token == TOKEN_FUNCTION);
|
||||
stnode_init(df_lval, STTYPE_FUNCTION, func, token_value);
|
||||
return token;
|
||||
}
|
||||
|
||||
static int
|
||||
set_lval_int(dfwork_t *dfw, int token, const char *token_value)
|
||||
{
|
||||
|
|
|
@ -25,8 +25,6 @@ function_new(gpointer funcdef)
|
|||
{
|
||||
function_t *stfuncrec;
|
||||
|
||||
ws_assert(funcdef != NULL);
|
||||
|
||||
stfuncrec = g_new(function_t, 1);
|
||||
|
||||
stfuncrec->magic = FUNCTION_MAGIC;
|
||||
|
|
Loading…
Reference in New Issue