dfilter: Handle null arguments in macros better

If a null argument is given to a macro, print an error saying that
is disallowed instead of substituting the null argument (i.e., an
unquoted empty string) into the macro.
The latter almost certainly still produces a grammatical error, but it
will be something mysterious that depends on the macro definition like

"==" was unexpected in this context

instead of a useful error string.

For macros that take strings as argument, substituting a null has
never worked either, "" has always needed to be used.

As a special case, accept a single empty argument as meaning
"a macro with 0 arguments" instead of how it is currently treated,
a "macro with 1 null argument", i.e. $mymacro() for the new
function-like syntax and ${mymacro:} for the original syntax.

See 7d87367e22
This commit is contained in:
John Thacker 2024-01-21 08:31:31 -05:00 committed by AndersBroman
parent c538dd9ff9
commit f274be5523
3 changed files with 63 additions and 4 deletions

View File

@ -301,6 +301,12 @@ static char* dfilter_macro_apply_recurse(const char* text, unsigned depth, df_er
goto on_error;
case ';':
case ',':
if (arg->len == 0) {
/* Null arguments aren't accepted */
if (error != NULL)
*error = df_error_new_msg("null argument in macro expression");
goto on_error;
}
g_ptr_array_add(args,g_string_free(arg,false));
arg = g_string_sized_new(32);
@ -323,10 +329,19 @@ static char* dfilter_macro_apply_recurse(const char* text, unsigned depth, df_er
break;
}
g_ptr_array_add(args,g_string_free(arg,false));
g_ptr_array_add(args,NULL);
arg = NULL;
if (arg->len == 0) {
/* Null arguments aren't accepted... */
if (args->len != 0) {
/* Except $macro() or ${macro:} means zero args, not one null arg */
if (error != NULL)
*error = df_error_new_msg("null argument in macro expression");
goto on_error;
}
} else {
g_ptr_array_add(args,g_string_free(arg,false));
g_ptr_array_add(args,NULL);
arg = NULL;
}
resolved = dfilter_macro_resolve(name->str, (char**)args->pdata, error);
if (resolved == NULL)

View File

@ -20,3 +20,45 @@ class TestDfilterMacro:
def test_macro_3(self, checkDFilterCount):
dfilter = "${private_ipv4;ip.src}"
checkDFilterCount(dfilter, 1)
class TestDfilterMacroZeroArg:
trace_file = "nfs.pcap"
def test_macro_1(self, checkDFilterCount):
dfilter = "$nfs()"
checkDFilterCount(dfilter, 2)
def test_macro_2(self, checkDFilterCount):
dfilter = "${nfs}"
checkDFilterCount(dfilter, 2)
def test_macro_3(self, checkDFilterCount):
dfilter = "${nfs:}"
checkDFilterCount(dfilter, 2)
def test_macro_wrong_count_1(self, checkDFilterFail):
dfilter = "${private_ipv4}"
checkDFilterFail(dfilter, "wrong number of arguments for macro")
def test_macro_wrong_count_2(self, checkDFilterFail):
dfilter = "${private_ipv4:}"
checkDFilterFail(dfilter, "wrong number of arguments for macro")
def test_macro_wrong_count_3(self, checkDFilterFail):
dfilter = "$private_ipv4()"
checkDFilterFail(dfilter, "wrong number of arguments for macro")
class TestDfilterMacroNullArg:
trace_file = "nfs.pcap"
def test_macro_works(self, checkDFilterCount):
dfilter = "$ip(198.95.230.20, 2049)"
checkDFilterCount(dfilter, 2)
def test_macro_null_1(self, checkDFilterFail):
dfilter = "$ip(198.95.230.20,)"
checkDFilterFail(dfilter, "null argument")
def test_macro_null_2(self, checkDFilterFail):
dfilter = "${ip:;2049}"
checkDFilterFail(dfilter, "null argument")

View File

@ -2,3 +2,5 @@
"private_ipv4" $1 == 192.168.0.0/16 or $1 == 172.16.0.0/12 or $1 == 10.0.0.0/8
"private_ethernet" $1[0] & 0x0F == 2
"private_ipv6" ipv6 && $1 == fc00::/7
"nfs" rpc.program == 100003
"ip" (ip.src == $1 and (tcp.srcport == $2 or udp.srcport == $2 or sctp.srcport == $2 or dccp.srcport == $2)) or (ip.dst == $1 and (tcp.dstport == $2 or udp.dstport == $2 or sctp.dstport == $2 or dccp.dstport == $2))