dfilter: Try to resolve field reference instead of using a heuristic
Instead of using a heuristic to decide whether the form ${...} is a macro or not, try to resolve the name to a registered protocol field and use that instead. This increases somewhat the surface for clobbering existing macro names with new field registrations but we'll cross that bridge when we get to it. Rejecting protocol field types reduces this probability again but it may not be intuitive to the user trying to mistakenly use a reference to a protocol why it is parsed as a macro. The reasons for rejecting FT_PROTOCOL types as not interesting field references are not very strong but it seems reasonable. $ dftest 'frame.number != ${frame.number}' Filter: frame.number != ${frame.number} Instructions: 00000 READ_TREE frame.number -> reg#0 00001 IF_FALSE_GOTO 5 00002 READ_REFERENCE ${frame.number} -> reg#1 00003 IF_FALSE_GOTO 5 00004 ALL_NE reg#0 != reg#1 00005 RETURN $ dftest 'frame != ${frame}' dftest: macro 'frame' does not exist
This commit is contained in:
parent
8355e96858
commit
8746eea297
|
@ -9,6 +9,7 @@
|
|||
|
||||
|
||||
#include "config.h"
|
||||
#define WS_LOG_DOMAIN LOG_DOMAIN_DFILTER
|
||||
|
||||
#ifdef DUMP_DFILTER_MACRO
|
||||
#include <stdio.h>
|
||||
|
@ -93,6 +94,37 @@ static gchar* dfilter_macro_resolve(gchar* name, gchar** args, gchar** error) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Start points to the first character after "${" */
|
||||
static gboolean start_is_field_reference(const char *start)
|
||||
{
|
||||
const char *end;
|
||||
char saved_c;
|
||||
const header_field_info *hfinfo;
|
||||
|
||||
end = strchr(start, '}');
|
||||
if (end == NULL)
|
||||
return FALSE;
|
||||
|
||||
saved_c = *end;
|
||||
/* This violates constness but we will restore the original string. */
|
||||
*(char *)end = '\0';
|
||||
/* Search for name in registered fields. */
|
||||
hfinfo = dfilter_resolve_unparsed(NULL, start);
|
||||
/* Restore mangled string. */
|
||||
*(char *)end = saved_c;
|
||||
|
||||
if (hfinfo == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
|
||||
/* Ignore these? */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* It's a field reference so ignore it as a macro. */
|
||||
ws_noisy("Ignore field reference ${%s}", start);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gchar* dfilter_macro_apply_recurse(const gchar* text, guint depth, gchar** error) {
|
||||
enum { OUTSIDE, STARTING, NAME, ARGS } state = OUTSIDE;
|
||||
|
@ -147,22 +179,14 @@ static gchar* dfilter_macro_apply_recurse(const gchar* text, guint depth, gchar*
|
|||
} case STARTING: {
|
||||
switch (c) {
|
||||
case '{': {
|
||||
/* If the name has a dot it's a field reference,
|
||||
* and conversely if it doesn't have a dot it's a macro. */
|
||||
const char *sep = r;
|
||||
char cc;
|
||||
while ((cc = *sep++) != '\0') {
|
||||
if (cc == '.' || cc == ':' || cc == '}') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cc == '.') {
|
||||
/* Field reference, preserve */
|
||||
if (start_is_field_reference(r)) {
|
||||
/* We have a field reference, preserve the name with ${} and bail. */
|
||||
g_string_append(out,"${");
|
||||
state = OUTSIDE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* We have a macro, continue. */
|
||||
args = g_ptr_array_new();
|
||||
arg = g_string_sized_new(32);
|
||||
name = g_string_sized_new(32);
|
||||
|
|
|
@ -113,7 +113,8 @@ dfilter_resolve_unparsed(dfwork_t *dfw, const char *name)
|
|||
hfinfo = proto_registrar_get_byalias(name);
|
||||
if (hfinfo != NULL) {
|
||||
/* It's an aliased field name */
|
||||
add_deprecated_token(dfw, name);
|
||||
if (dfw)
|
||||
add_deprecated_token(dfw, name);
|
||||
return hfinfo;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue