dfilter: Remove commute argument from semantic check

Take a more conservative, less flexible, maybe more elegant,
approach to type inference for now.
This commit is contained in:
João Valverde 2022-12-28 17:18:59 +00:00
parent 2ff6139307
commit a17fb20550
3 changed files with 97 additions and 38 deletions

View File

@ -47,8 +47,7 @@ check_arithmetic_LHS(dfwork_t *dfw, stnode_op_t st_op,
static void
check_relation(dfwork_t *dfw, stnode_op_t st_op,
FtypeCanFunc can_func, gboolean allow_partial_value,
stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2,
int commute);
stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2);
static void
semcheck(dfwork_t *dfw, stnode_t *st_node);
@ -713,6 +712,80 @@ check_relation_LHS_FIELD(dfwork_t *dfw, stnode_op_t st_op,
}
}
static void
check_relation_LHS_FVALUE(dfwork_t *dfw, stnode_op_t st_op _U_,
FtypeCanFunc can_func, gboolean allow_partial_value,
stnode_t *st_node,
stnode_t *st_arg1, stnode_t *st_arg2)
{
sttype_id_t type1, type2;
header_field_info *hfinfo2 = NULL;
ftenum_t ftype2;
fvalue_t *fvalue;
LOG_NODE(st_node);
type2 = stnode_type_id(st_arg2);
if (IS_FIELD_ENTITY(type2)) {
hfinfo2 = sttype_field_hfinfo(st_arg2);
ftype2 = sttype_field_ftenum(st_arg2);
if (!can_func(ftype2)) {
FAIL(dfw, st_arg2, "%s (type=%s) cannot participate in specified comparison.",
stnode_todisplay(st_arg2), ftype_pretty_name(ftype2));
}
}
else if (type2 == STTYPE_STRING ||
type2 == STTYPE_LITERAL ||
type2 == STTYPE_CHARCONST ||
type2 == STTYPE_PCRE) {
FAIL(dfw, st_node, "Constant expression is invalid.");
}
else if (type2 == STTYPE_SLICE) {
ftype2 = check_slice(dfw, st_arg2, FT_NONE);
if (!can_func(ftype2)) {
FAIL(dfw, st_arg2, "%s (type=%s) cannot participate in specified comparison.",
stnode_todisplay(st_arg2), ftype_pretty_name(ftype2));
}
}
else if (type2 == STTYPE_FUNCTION) {
ftype2 = check_function(dfw, st_arg2, FT_NONE);
if (!can_func(ftype2)) {
FAIL(dfw, st_arg2, "return value of %s() (type=%s) cannot participate in specified comparison.",
sttype_function_name(st_arg2), ftype_pretty_name(ftype2));
}
}
else if (type2 == STTYPE_ARITHMETIC) {
ftype2 = check_arithmetic(dfw, st_arg2, FT_NONE);
if (!can_func(ftype2)) {
FAIL(dfw, st_arg2, "%s (type=%s) cannot participate in specified comparison.",
stnode_todisplay(st_arg2), ftype_pretty_name(ftype2));
}
}
else {
ws_assert_not_reached();
}
type1 = stnode_type_id(st_arg1);
if (type1 == STTYPE_STRING) {
fvalue = dfilter_fvalue_from_string(dfw, ftype2, st_arg1, hfinfo2);
}
else if (type1 == STTYPE_LITERAL) {
fvalue = dfilter_fvalue_from_literal(dfw, ftype2, st_arg1, allow_partial_value, hfinfo2);
}
else if (type1 == STTYPE_CHARCONST) {
fvalue = dfilter_fvalue_from_charconst(dfw, ftype2, st_arg1);
}
else {
ws_assert_not_reached();
}
stnode_replace(st_arg1, STTYPE_FVALUE, fvalue);
}
static void
check_relation_LHS_SLICE(dfwork_t *dfw, stnode_op_t st_op,
FtypeCanFunc can_func _U_,
@ -812,8 +885,7 @@ check_relation_LHS_SLICE(dfwork_t *dfw, stnode_op_t st_op,
static void
check_relation_LHS_FUNCTION(dfwork_t *dfw, stnode_op_t st_op,
FtypeCanFunc can_func, gboolean allow_partial_value,
stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2,
int commute)
stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2)
{
sttype_id_t type2;
ftenum_t ftype1, ftype2;
@ -823,9 +895,7 @@ check_relation_LHS_FUNCTION(dfwork_t *dfw, stnode_op_t st_op,
ftype1 = check_function(dfw, st_arg1, FT_NONE);
if (ftype1 == FT_NONE) {
check_relation(dfw, st_op, can_func, allow_partial_value,
st_node, st_arg2, st_arg1, commute - 1);
return;
FAIL(dfw, st_arg1, "Constant expression is invalid on the LHS.");
}
if (!can_func(ftype1)) {
FAIL(dfw, st_arg1, "Function %s (type=%s) cannot participate in %s comparison.",
@ -923,8 +993,7 @@ check_relation_LHS_FUNCTION(dfwork_t *dfw, stnode_op_t st_op,
static void
check_relation_LHS_ARITHMETIC(dfwork_t *dfw, stnode_op_t st_op,
FtypeCanFunc can_func, gboolean allow_partial_value,
stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2,
int commute)
stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2)
{
sttype_id_t type2;
ftenum_t ftype1, ftype2;
@ -934,11 +1003,8 @@ check_relation_LHS_ARITHMETIC(dfwork_t *dfw, stnode_op_t st_op,
ftype1 = check_arithmetic(dfw, st_arg1, FT_NONE);
if (ftype1 == FT_NONE) {
check_relation(dfw, st_op, can_func, allow_partial_value,
st_node, st_arg2, st_arg1, commute - 1);
return;
FAIL(dfw, st_arg1, "Constant expression is invalid on the LHS.");
}
if (!can_func(ftype1)) {
FAIL(dfw, st_arg1, "Result with type %s cannot participate in %s comparison.",
ftype_pretty_name(ftype1),
@ -1030,17 +1096,10 @@ check_relation_LHS_ARITHMETIC(dfwork_t *dfw, stnode_op_t st_op,
static void
check_relation(dfwork_t *dfw, stnode_op_t st_op,
FtypeCanFunc can_func, gboolean allow_partial_value,
stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2,
int commute)
stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2)
{
LOG_NODE(st_node);
if (commute < 0) {
/* We have already commuted the LHS with the RHS and still
cannot assign a field type to any side of the relation. */
FAIL(dfw, st_node, "Constant expression is invalid.");
}
switch (stnode_type_id(st_arg1)) {
case STTYPE_FIELD:
case STTYPE_REFERENCE:
@ -1053,20 +1112,17 @@ check_relation(dfwork_t *dfw, stnode_op_t st_op,
break;
case STTYPE_FUNCTION:
check_relation_LHS_FUNCTION(dfw, st_op, can_func,
allow_partial_value, st_node, st_arg1, st_arg2, commute);
allow_partial_value, st_node, st_arg1, st_arg2);
break;
case STTYPE_ARITHMETIC:
check_relation_LHS_ARITHMETIC(dfw, st_op, can_func,
allow_partial_value, st_node, st_arg1, st_arg2, commute);
allow_partial_value, st_node, st_arg1, st_arg2);
break;
case STTYPE_LITERAL:
case STTYPE_STRING:
case STTYPE_CHARCONST:
/* We cannot semantically check a relation with literals on the LHS because we
don't have a type to assign them. Commute the LHS with the RHS and retry
the relation semantic check. */
check_relation(dfw, st_op, can_func,
allow_partial_value,st_node, st_arg2, st_arg1, commute - 1);
check_relation_LHS_FVALUE(dfw, st_op, can_func,
allow_partial_value, st_node, st_arg1, st_arg2);
break;
default:
/* Should not happen. */
@ -1110,7 +1166,7 @@ check_relation_contains(dfwork_t *dfw, stnode_t *st_node,
break;
case STTYPE_FUNCTION:
check_relation_LHS_FUNCTION(dfw, STNODE_OP_CONTAINS, ftype_can_contains,
TRUE, st_node, st_arg1, st_arg2, 0);
TRUE, st_node, st_arg1, st_arg2);
break;
case STTYPE_SLICE:
check_relation_LHS_SLICE(dfw, STNODE_OP_CONTAINS, ftype_can_contains,
@ -1157,7 +1213,7 @@ check_relation_matches(dfwork_t *dfw, stnode_t *st_node,
break;
case STTYPE_FUNCTION:
check_relation_LHS_FUNCTION(dfw, STNODE_OP_MATCHES, ftype_can_matches,
TRUE, st_node, st_arg1, st_arg2, 0);
TRUE, st_node, st_arg1, st_arg2);
break;
case STTYPE_SLICE:
check_relation_LHS_SLICE(dfw, STNODE_OP_MATCHES, ftype_can_matches,
@ -1238,13 +1294,13 @@ check_test(dfwork_t *dfw, stnode_t *st_node)
case STNODE_OP_ANY_EQ:
case STNODE_OP_ALL_NE:
case STNODE_OP_ANY_NE:
check_relation(dfw, st_op, ftype_can_eq, FALSE, st_node, st_arg1, st_arg2, 1);
check_relation(dfw, st_op, ftype_can_eq, FALSE, st_node, st_arg1, st_arg2);
break;
case STNODE_OP_GT:
case STNODE_OP_GE:
case STNODE_OP_LT:
case STNODE_OP_LE:
check_relation(dfw, st_op, ftype_can_cmp, FALSE, st_node, st_arg1, st_arg2, 1);
check_relation(dfw, st_op, ftype_can_cmp, FALSE, st_node, st_arg1, st_arg2);
break;
case STNODE_OP_CONTAINS:
check_relation_contains(dfw, st_node, st_arg1, st_arg2);

View File

@ -70,9 +70,10 @@ class case_dfunction_maxmin(unittest.TestCase):
dfilter = 'max(5060, udp.dstport) == udp.srcport'
checkDFilterCount(dfilter, 2)
def test_max_5(self, checkDFilterCount):
def test_max_5(self, checkDFilterFail):
error = 'Constant expression is invalid on the LHS'
dfilter = 'max(5060, 5070) == udp.srcport'
checkDFilterCount(dfilter, 1)
checkDFilterFail(dfilter, error)
@fixtures.uses_fixtures
class case_dfunction_abs(unittest.TestCase):

View File

@ -237,9 +237,10 @@ class case_unary_minus(unittest.TestCase):
dfilter = "tcp.window_size_scalefactor == +tcp.dstport"
checkDFilterCount(dfilter, 0)
def test_unary_3(self, checkDFilterCount):
def test_unary_3(self, checkDFilterFail):
error = 'Constant expression is invalid on the LHS'
dfilter = "-2 == tcp.dstport"
checkDFilterCount(dfilter, 0)
checkDFilterFail(dfilter, error)
def test_unary_4(self, checkDFilterCount):
dfilter = "tcp.window_size_scalefactor == -{tcp.dstport * 20}"
@ -261,9 +262,10 @@ class case_arithmetic(unittest.TestCase):
dfilter = "udp.dstport == 66+1"
checkDFilterCount(dfilter, 2)
def test_add_4(self, checkDFilterCount):
def test_add_4(self, checkDFilterFail):
error = 'Constant expression is invalid on the LHS'
dfilter = "1 + 2 == frame.number"
checkDFilterCount(dfilter, 1)
checkDFilterFail(dfilter, error)
def test_add_5(self, checkDFilterFail):
error = 'Constant expression is invalid'