aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dfilter/semcheck.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dfilter/semcheck.c')
-rw-r--r--epan/dfilter/semcheck.c136
1 files changed, 114 insertions, 22 deletions
diff --git a/epan/dfilter/semcheck.c b/epan/dfilter/semcheck.c
index 123864b7ff..faba2942d4 100644
--- a/epan/dfilter/semcheck.c
+++ b/epan/dfilter/semcheck.c
@@ -1,5 +1,5 @@
/*
- * $Id: semcheck.c,v 1.17 2003/06/13 07:39:26 guy Exp $
+ * $Id: semcheck.c,v 1.18 2003/07/25 03:44:01 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@@ -47,15 +47,15 @@ compatible_ftypes(ftenum_t a, ftenum_t b)
switch (a) {
case FT_NONE:
case FT_PROTOCOL:
- case FT_FLOAT:
- case FT_DOUBLE:
+ case FT_FLOAT: /* XXX - should be able to compare with INT */
+ case FT_DOUBLE: /* XXX - should be able to compare with INT */
case FT_ABSOLUTE_TIME:
case FT_RELATIVE_TIME:
case FT_IPv4:
case FT_IPv6:
case FT_IPXNET:
- case FT_INT64:
- case FT_UINT64:
+ case FT_INT64: /* XXX - should be able to compare with INT */
+ case FT_UINT64: /* XXX - should be able to compare with INT */
return a == b;
case FT_ETHER:
@@ -187,7 +187,7 @@ mk_fvalue_from_val_string(header_field_info *hfinfo, char *s)
return mk_uint32_fvalue(FALSE);
}
else {
- dfilter_fail("\"%s\" cannot be found among the possible values for %s.",
+ dfilter_fail("\"%s\" cannot be found among the possible values for %s.",
s, hfinfo->abbrev);
return NULL;
}
@@ -256,9 +256,11 @@ is_bytes_type(enum ftenum type)
return FALSE;
}
+/* If the LHS of a relation test is a FIELD, run some checks
+ * and possibly some modifications of syntax tree nodes. */
static void
-check_relation_LHS_FIELD(FtypeCanFunc can_func, stnode_t *st_node,
- stnode_t *st_arg1, stnode_t *st_arg2)
+check_relation_LHS_FIELD(const char *relation_string, FtypeCanFunc can_func,
+ stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2)
{
stnode_t *new_st;
sttype_id_t type1, type2;
@@ -275,8 +277,9 @@ check_relation_LHS_FIELD(FtypeCanFunc can_func, stnode_t *st_node,
ftype1 = hfinfo1->type;
if (!can_func(ftype1)) {
- dfilter_fail("%s (type=%s) cannot participate in specified comparison.",
- hfinfo1->abbrev, ftype_pretty_name(ftype1));
+ dfilter_fail("%s (type=%s) cannot participate in '%s' comparison.",
+ hfinfo1->abbrev, ftype_pretty_name(ftype1),
+ relation_string);
THROW(TypeError);
}
@@ -313,6 +316,21 @@ check_relation_LHS_FIELD(FtypeCanFunc can_func, stnode_t *st_node,
sttype_test_set2_args(st_node, st_arg1, new_st);
stnode_free(st_arg2);
}
+ else if (type2 == STTYPE_UNPARSED) {
+ s = stnode_data(st_arg2);
+ fvalue = fvalue_from_unparsed(ftype1, s, dfilter_fail);
+ if (!fvalue) {
+ /* check value_string */
+ fvalue = mk_fvalue_from_val_string(hfinfo1, s);
+ if (!fvalue) {
+ THROW(TypeError);
+ }
+ }
+
+ new_st = stnode_new(STTYPE_FVALUE, fvalue);
+ sttype_test_set2_args(st_node, st_arg1, new_st);
+ stnode_free(st_arg2);
+ }
else if (type2 == STTYPE_RANGE) {
if (!is_bytes_type(ftype1)) {
if (!ftype_can_slice(ftype1)) {
@@ -393,6 +411,60 @@ check_relation_LHS_STRING(FtypeCanFunc can_func _U_, stnode_t *st_node,
}
}
+static void
+check_relation_LHS_UNPARSED(FtypeCanFunc can_func _U_, stnode_t *st_node,
+ stnode_t *st_arg1, stnode_t *st_arg2)
+{
+ stnode_t *new_st;
+ sttype_id_t type1, type2;
+ header_field_info *hfinfo2;
+ ftenum_t ftype2;
+ fvalue_t *fvalue;
+ char *s;
+
+ type1 = stnode_type_id(st_arg1);
+ type2 = stnode_type_id(st_arg2);
+
+ if (type2 == STTYPE_FIELD) {
+ hfinfo2 = stnode_data(st_arg2);
+ ftype2 = hfinfo2->type;
+
+ s = stnode_data(st_arg1);
+ fvalue = fvalue_from_unparsed(ftype2, s, dfilter_fail);
+ if (!fvalue) {
+ /* check value_string */
+ fvalue = mk_fvalue_from_val_string(hfinfo2, s);
+ if (!fvalue) {
+ THROW(TypeError);
+ }
+ }
+
+ new_st = stnode_new(STTYPE_FVALUE, fvalue);
+ sttype_test_set2_args(st_node, new_st, st_arg2);
+ stnode_free(st_arg1);
+ }
+ else if (type2 == STTYPE_STRING) {
+ /* Well now that's silly... */
+ dfilter_fail("Neither \"%s\" nor \"%s\" are field or protocol names.",
+ stnode_data(st_arg1),
+ stnode_data(st_arg2));
+ THROW(TypeError);
+ }
+ else if (type2 == STTYPE_RANGE) {
+ s = stnode_data(st_arg1);
+ fvalue = fvalue_from_unparsed(FT_BYTES, s, dfilter_fail);
+ if (!fvalue) {
+ THROW(TypeError);
+ }
+ new_st = stnode_new(STTYPE_FVALUE, fvalue);
+ sttype_test_set2_args(st_node, new_st, st_arg2);
+ stnode_free(st_arg1);
+ }
+ else {
+ g_assert_not_reached();
+ }
+}
+
struct check_drange_sanity_args {
drange_node* err_node;
};
@@ -515,6 +587,16 @@ check_relation_LHS_RANGE(FtypeCanFunc can_func _U_, stnode_t *st_node,
sttype_test_set2_args(st_node, st_arg1, new_st);
stnode_free(st_arg2);
}
+ else if (type2 == STTYPE_UNPARSED) {
+ s = stnode_data(st_arg2);
+ fvalue = fvalue_from_unparsed(FT_BYTES, s, dfilter_fail);
+ if (!fvalue) {
+ THROW(TypeError);
+ }
+ new_st = stnode_new(STTYPE_FVALUE, fvalue);
+ sttype_test_set2_args(st_node, st_arg1, new_st);
+ stnode_free(st_arg2);
+ }
else if (type2 == STTYPE_RANGE) {
check_drange_sanity(st_arg2);
/* XXX - check lengths of both ranges */
@@ -525,13 +607,14 @@ check_relation_LHS_RANGE(FtypeCanFunc can_func _U_, stnode_t *st_node,
}
+/* Check the semantics of any relational test. */
static void
-check_relation(FtypeCanFunc can_func, stnode_t *st_node,
+check_relation(const char *relation_string, FtypeCanFunc can_func, stnode_t *st_node,
stnode_t *st_arg1, stnode_t *st_arg2)
{
switch (stnode_type_id(st_arg1)) {
case STTYPE_FIELD:
- check_relation_LHS_FIELD(can_func, st_node, st_arg1, st_arg2);
+ check_relation_LHS_FIELD(relation_string, can_func, st_node, st_arg1, st_arg2);
break;
case STTYPE_STRING:
check_relation_LHS_STRING(can_func, st_node, st_arg1, st_arg2);
@@ -539,6 +622,9 @@ check_relation(FtypeCanFunc can_func, stnode_t *st_node,
case STTYPE_RANGE:
check_relation_LHS_RANGE(can_func, st_node, st_arg1, st_arg2);
break;
+ case STTYPE_UNPARSED:
+ check_relation_LHS_UNPARSED(can_func, st_node, st_arg1, st_arg2);
+ break;
case STTYPE_UNINITIALIZED:
case STTYPE_TEST:
@@ -549,6 +635,7 @@ check_relation(FtypeCanFunc can_func, stnode_t *st_node,
}
}
+/* Check the semantics of any type of TEST */
static void
check_test(stnode_t *st_node)
{
@@ -577,34 +664,33 @@ check_test(stnode_t *st_node)
break;
case TEST_OP_EQ:
- check_relation(ftype_can_eq, st_node, st_arg1, st_arg2);
+ check_relation("==", ftype_can_eq, st_node, st_arg1, st_arg2);
break;
case TEST_OP_NE:
- check_relation(ftype_can_ne, st_node, st_arg1, st_arg2);
+ check_relation("!=", ftype_can_ne, st_node, st_arg1, st_arg2);
break;
case TEST_OP_GT:
- check_relation(ftype_can_gt, st_node, st_arg1, st_arg2);
+ check_relation(">", ftype_can_gt, st_node, st_arg1, st_arg2);
break;
case TEST_OP_GE:
- check_relation(ftype_can_ge, st_node, st_arg1, st_arg2);
+ check_relation(">=", ftype_can_ge, st_node, st_arg1, st_arg2);
break;
case TEST_OP_LT:
- check_relation(ftype_can_lt, st_node, st_arg1, st_arg2);
+ check_relation("<", ftype_can_lt, st_node, st_arg1, st_arg2);
break;
case TEST_OP_LE:
- check_relation(ftype_can_le, st_node, st_arg1, st_arg2);
+ check_relation("<=", ftype_can_le, st_node, st_arg1, st_arg2);
break;
}
}
+/* Check the entire syntax tree. */
static void
semcheck(stnode_t *st_node)
{
- const char *name;
-
- name = stnode_type_name(st_node);
-
+ /* The parser assures that the top-most syntax-tree
+ * node will be a TEST node, no matter what. So assert that. */
switch (stnode_type_id(st_node)) {
case STTYPE_TEST:
check_test(st_node);
@@ -615,9 +701,15 @@ semcheck(stnode_t *st_node)
}
+/* Check the syntax tree for semantic errors, and convert
+ * some of the nodes into the form they need to be in order to
+ * later generate the DFVM bytecode. */
gboolean
dfw_semcheck(dfwork_t *dfw)
{
+ /* Instead of having to check for errors at every stage of
+ * the semantic-checking, the semantic-checking code will
+ * throw an exception if a problem is found. */
TRY {
semcheck(dfw->st_root);
}