dfilter: Add bitwise masking of bits

Add support for masking of bits. Before the bitwise operator
could only test bits, it did not support clearing bits.

This allows testing if any combination of bits are set/unset
more naturally with a single test. Previously this was only
possible by combining several bitwise predicates.

Bitwise is implemented as a test node, even though it is not.
Maybe the test node should be renamed to something else.

Fixes #17246.
pespin/osmux-wip
João Valverde 2022-02-25 19:37:53 +00:00 committed by A Wireshark GitLab Utility
parent 3e3db6cd3e
commit 16729be2c1
28 changed files with 675 additions and 160 deletions

View File

@ -378,8 +378,8 @@ following bit field operation is supported:
bitwise_and, & Bitwise AND
The bitwise AND operation allows testing to see if one or more bits are set.
Bitwise AND operates on integer protocol fields and slices.
The bitwise AND operation allows masking bits and testing to see if one or
more bits are set. Bitwise AND operates on integer protocol fields and slices.
When testing for TCP SYN packets, you can write:

View File

@ -63,6 +63,8 @@ They previously shipped with Npcap 1.55.
** Floats must be written with a leading and ending digit. For example the values ".7" and "7." are now invalid as floats.
It must be written "7.0" and "0.7" respectively.
** The operator "~=" is deprecated and will be removed in a future version. Use "!==" with the same meaning instead.
** The "bitwise and" operator is now a first-class bit operator, not a boolean operator. In particular this means
it is now possible to mask bits, e.g.: frame[0] & 0x0F == 3.
* text2pcap and "Import from Hex Dump":
** text2pcap supports writing the output file in all the capture file formats

View File

@ -102,6 +102,7 @@ dfilter_vfail(dfwork_t *dfw, const char *format, va_list args);
void
dfilter_fail(dfwork_t *dfw, const char *format, ...) G_GNUC_PRINTF(2, 3);
WS_NORETURN
void
dfilter_fail_throw(dfwork_t *dfw, long code, const char *format, ...) G_GNUC_PRINTF(3, 4);

View File

@ -259,7 +259,7 @@ const char *tokenstr(int token)
case TOKEN_TEST_GE: return "TEST_GE";
case TOKEN_TEST_CONTAINS: return "TEST_CONTAINS";
case TOKEN_TEST_MATCHES: return "TEST_MATCHES";
case TOKEN_TEST_BITWISE_AND: return "TEST_BITWISE_AND";
case TOKEN_BITWISE_AND: return "BITWISE_AND";
case TOKEN_TEST_NOT: return "TEST_NOT";
case TOKEN_STRING: return "STRING";
case TOKEN_CHARCONST: return "CHARCONST";

View File

@ -272,9 +272,14 @@ dfvm_dump(FILE *f, dfilter_t *df)
id, arg1_str, arg2_str);
break;
case ANY_BITWISE_AND:
fprintf(f, "%05d ANY_BITWISE_AND\t%s & %s\n",
id, arg1_str, arg2_str);
case MK_BITWISE_AND:
fprintf(f, "%05d MK_BITWISE_AND\t%s & %s -> %s\n",
id, arg1_str, arg2_str, arg3_str);
break;
case ANY_NOTZERO:
fprintf(f, "%05d ANY_NOTZERO\t%s\n",
id, arg1_str);
break;
case ANY_CONTAINS:
@ -380,6 +385,7 @@ enum match_how {
};
typedef gboolean (*DFVMCompareFunc)(const fvalue_t*, const fvalue_t*);
typedef gboolean (*DFVMTestFunc)(const fvalue_t*);
static gboolean
cmp_test(enum match_how how, DFVMCompareFunc match_func,
@ -410,6 +416,39 @@ cmp_test(enum match_how how, DFVMCompareFunc match_func,
return want_all;
}
static gboolean
cmp_test_unary(enum match_how how, DFVMTestFunc test_func, GSList *arg1)
{
GSList *list1;
gboolean want_all = (how == MATCH_ALL);
gboolean want_any = (how == MATCH_ANY);
gboolean have_match;
list1 = arg1;
while (list1) {
have_match = test_func(list1->data);
if (want_all && !have_match) {
return FALSE;
}
else if (want_any && have_match) {
return TRUE;
}
list1 = g_slist_next(list1);
}
/* want_all || !want_any */
return want_all;
}
/* cmp(A) <=> cmp(a1) OR cmp(a2) OR cmp(a3) OR ... */
static gboolean
any_test_unary(dfilter_t *df, DFVMTestFunc func, dfvm_value_t *arg1)
{
ws_assert(arg1->type == REGISTER);
GSList *list1 = df->registers[arg1->value.numeric];
return cmp_test_unary(MATCH_ANY, func, list1);
}
/* cmp(A) <=> cmp(a1) OR cmp(a2) OR cmp(a3) OR ... */
static gboolean
any_test(dfilter_t *df, DFVMCompareFunc cmp,
@ -562,6 +601,77 @@ call_function(dfilter_t *df, dfvm_value_t *arg1, dfvm_value_t *arg2,
return accum;
}
static void debug_op_error(fvalue_t *v1, fvalue_t *v2, const char *op, const char *msg)
{
char *s1 = fvalue_to_debug_repr(NULL, v1);
char *s2 = fvalue_to_debug_repr(NULL, v2);
ws_noisy("Error: %s %s %s: %s", s1, op, s2, msg);
g_free(s1);
g_free(s2);
}
typedef fvalue_t* (*DFVMBitwiseFunc)(const fvalue_t*, const fvalue_t*, char **);
static void
mk_bitwise_internal(DFVMBitwiseFunc func,
GSList *arg1, GSList *arg2, GSList **retval)
{
GSList *list1, *list2;
GSList *to_list = NULL;
fvalue_t *val1, *val2;
fvalue_t *result;
char *err_msg = NULL;
list1 = arg1;
while (list1) {
list2 = arg2;
while (list2) {
val1 = list1->data;
val2 = list2->data;
result = func(val1, val2, &err_msg);
if (result == NULL) {
debug_op_error(val1, val2, "&", err_msg);
g_free(err_msg);
err_msg = NULL;
}
else {
to_list = g_slist_prepend(to_list, result);
}
list2 = g_slist_next(list2);
}
list1 = g_slist_next(list1);
}
*retval = to_list;
}
static void
mk_bitwise(dfilter_t *df, DFVMBitwiseFunc func,
dfvm_value_t *arg1, dfvm_value_t *arg2, dfvm_value_t *to_arg)
{
ws_assert(arg1->type == REGISTER);
GSList *list1 = df->registers[arg1->value.numeric];
GSList *result = NULL;
if (arg2->type == REGISTER) {
GSList *list2 = df->registers[arg2->value.numeric];
mk_bitwise_internal(func, list1, list2, &result);
}
else if (arg2->type == FVALUE) {
GSList list2;
list2.data = arg2->value.fvalue;
list2.next = NULL;
mk_bitwise_internal(func, list1, &list2, &result);
}
else {
ws_assert_not_reached();
}
df->registers[to_arg->value.numeric] = result;
df->free_registers[to_arg->value.numeric] = (GDestroyNotify)fvalue_free;
}
gboolean
dfvm_apply(dfilter_t *df, proto_tree *tree)
{
@ -646,8 +756,12 @@ dfvm_apply(dfilter_t *df, proto_tree *tree)
accum = any_test(df, fvalue_le, arg1, arg2);
break;
case ANY_BITWISE_AND:
accum = any_test(df, fvalue_bitwise_and, arg1, arg2);
case MK_BITWISE_AND:
mk_bitwise(df, fvalue_bitwise_and, arg1, arg2, arg3);
break;
case ANY_NOTZERO:
accum = any_test_unary(df, fvalue_is_true, arg1);
break;
case ANY_CONTAINS:

View File

@ -61,10 +61,11 @@ typedef enum {
ANY_GE,
ANY_LT,
ANY_LE,
ANY_BITWISE_AND,
ANY_CONTAINS,
ANY_MATCHES,
ANY_NOTZERO,
MK_RANGE,
MK_BITWISE_AND,
CALL_FUNCTION,
ANY_IN_RANGE

View File

@ -279,6 +279,32 @@ gen_relation_in(dfwork_t *dfw, stnode_t *st_arg1, stnode_t *st_arg2)
set_nodelist_free(nodelist_head);
}
static dfvm_value_t *
gen_bitwise(dfwork_t *dfw, stnode_t *st_arg, GSList **jumps_ptr)
{
stnode_t *left, *right;
test_op_t st_op;
dfvm_value_t *reg_val, *val1, *val2;
dfvm_opcode_t op;
sttype_test_get(st_arg, &st_op, &left, &right);
switch (st_op) {
case OP_BITWISE_AND:
op = MK_BITWISE_AND;
break;
default:
ws_assert_not_reached();
break;
}
val1 = gen_entity(dfw, left, jumps_ptr);
val2 = gen_entity(dfw, right, jumps_ptr);
reg_val = dfvm_value_new_register(dfw->next_register++);
gen_relation_insn(dfw, op, val1, val2, reg_val, NULL);
return reg_val;
}
/* Parse an entity, returning the reg that it gets put into.
* p_jmp will be set if it has to be set by the calling code; it should
* be set to the place to jump to, to return to the calling code,
@ -314,6 +340,9 @@ gen_entity(dfwork_t *dfw, stnode_t *st_arg, GSList **jumps_ptr)
else if (e_type == STTYPE_PCRE) {
val = dfvm_value_new_pcre(stnode_steal_data(st_arg));
}
else if (e_type == STTYPE_BITWISE) {
val = gen_bitwise(dfw, st_arg, jumps_ptr);
}
else {
/* printf("sttype_id is %u\n", (unsigned)e_type); */
ws_assert_not_reached();
@ -328,7 +357,9 @@ gen_test(dfwork_t *dfw, stnode_t *st_node)
test_op_t st_op;
stnode_t *st_arg1, *st_arg2;
dfvm_insn_t *insn;
dfvm_value_t *jmp;
dfvm_value_t *jmp, *val1;
GSList *jumps = NULL;
header_field_info *hfinfo;
sttype_test_get(st_node, &st_op, &st_arg1, &st_arg2);
@ -359,6 +390,16 @@ gen_test(dfwork_t *dfw, stnode_t *st_node)
break;
case TEST_OP_NOTZERO:
val1 = gen_entity(dfw, st_arg1, &jumps);
insn = dfvm_insn_new(ANY_NOTZERO);
insn->arg1 = dfvm_value_ref(val1);
dfw_append_insn(dfw, insn);
g_slist_foreach(jumps, fixup_jumps, dfw);
g_slist_free(jumps);
jumps = NULL;
break;
case TEST_OP_NOT:
gencode(dfw, st_arg1);
insn = dfvm_insn_new(NOT);
@ -421,8 +462,8 @@ gen_test(dfwork_t *dfw, stnode_t *st_node)
gen_relation(dfw, ANY_LE, st_arg1, st_arg2);
break;
case TEST_OP_BITWISE_AND:
gen_relation(dfw, ANY_BITWISE_AND, st_arg1, st_arg2);
case OP_BITWISE_AND:
ws_assert_not_reached();
break;
case TEST_OP_CONTAINS:

View File

@ -127,30 +127,35 @@ logical_test(T) ::= entity(E).
sttype_test_set1_args(T, E);
}
logical_test(T) ::= bitwise_term(E).
{
T = new_test(dfw, TEST_OP_NOTZERO, NULL);
sttype_test_set1_args(T, E);
}
/* Entities, or things that can be compared/tested/checked */
entity(E) ::= STRING(S).
atom(E) ::= STRING(S).
{
E = stnode_new_string(df_lval_value(S), df_lval_value(S));
df_lval_free(S, FALSE);
}
entity(E) ::= CHARCONST(C).
atom(E) ::= CHARCONST(C).
{
E = stnode_new_charconst(df_lval_number(C), df_lval_value(C));
df_lval_free(C, FALSE);
}
entity(E) ::= UNPARSED(U).
atom(E) ::= UNPARSED(U).
{
E = stnode_new_unparsed(df_lval_value(U), df_lval_value(U));
df_lval_free(U, FALSE);
}
entity(E) ::= LITERAL(S).
atom(E) ::= LITERAL(S).
{
E = stnode_new_literal(df_lval_value(S), df_lval_value(S));
df_lval_free(S, FALSE);
}
entity(E) ::= IDENTIFIER(F).
atom(E) ::= IDENTIFIER(F).
{
char *name = df_lval_value(F);
header_field_info *hfinfo = dfilter_resolve_unparsed(dfw, name);
@ -160,9 +165,21 @@ entity(E) ::= IDENTIFIER(F).
E = stnode_new(STTYPE_FIELD, hfinfo, name);
df_lval_free(F, FALSE);
}
entity(E) ::= atom(A). { E = A; }
entity(E) ::= range(R). { E = R; }
entity(E) ::= function(F). { E = F; }
bitwise_term(T) ::= entity(F) BITWISE_AND(B) entity(M).
{
T = stnode_new(STTYPE_BITWISE, NULL, df_lval_value(B));
sttype_test_set2(T, OP_BITWISE_AND, F, M);
df_lval_free(B, FALSE);
}
term(T) ::= entity(E). { T = E; }
term(T) ::= bitwise_term(E). { T = E; }
/* Ranges */
range(R) ::= entity(E) LBRACKET range_node_list(L) RBRACKET.
@ -207,16 +224,15 @@ cmp_op(O) ::= TEST_GT(L). { O = new_test(dfw, TEST_OP_GT, L); }
cmp_op(O) ::= TEST_GE(L). { O = new_test(dfw, TEST_OP_GE, L); }
cmp_op(O) ::= TEST_LT(L). { O = new_test(dfw, TEST_OP_LT, L); }
cmp_op(O) ::= TEST_LE(L). { O = new_test(dfw, TEST_OP_LE, L); }
cmp_op(O) ::= TEST_BITWISE_AND(L). { O = new_test(dfw, TEST_OP_BITWISE_AND, L); }
comparison_test(T) ::= entity(E) cmp_op(O) entity(F).
comparison_test(T) ::= term(E) cmp_op(O) term(F).
{
T = O;
sttype_test_set2_args(O, E, F);
}
/* 'a == b == c' or 'a < b <= c <= d < e' */
comparison_test(T) ::= entity(E) cmp_op(O) comparison_test(R).
comparison_test(T) ::= term(E) cmp_op(O) comparison_test(R).
{
stnode_t *L, *F;
/* for now generate it like E O F TEST_OP_AND F P G, later it could be optimized

View File

@ -137,8 +137,6 @@ WORD_CHAR [][:alnum:]_:/+-]
"lt" return simple(TOKEN_TEST_LT);
"<=" return simple(TOKEN_TEST_LE);
"le" return simple(TOKEN_TEST_LE);
"bitwise_and" return simple(TOKEN_TEST_BITWISE_AND);
"&" return simple(TOKEN_TEST_BITWISE_AND);
"contains" return simple(TOKEN_TEST_CONTAINS);
"~" return simple(TOKEN_TEST_MATCHES);
"matches" return simple(TOKEN_TEST_MATCHES);
@ -150,6 +148,9 @@ WORD_CHAR [][:alnum:]_:/+-]
"or" return simple(TOKEN_TEST_OR);
"in" return simple(TOKEN_TEST_IN);
"&" return simple(TOKEN_BITWISE_AND);
"bitwise_and" return simple(TOKEN_BITWISE_AND);
"[" {
BEGIN(RANGE);
return simple(TOKEN_LBRACKET);

View File

@ -38,6 +38,12 @@ semcheck(dfwork_t *dfw, stnode_t *st_node);
static void
check_function(dfwork_t *dfw, stnode_t *st_node);
static ftenum_t
check_bitwise_entity(dfwork_t *dfw, stnode_t *st_node, stnode_t *st_arg, ftenum_t ftype);
static ftenum_t
check_bitwise_operation(dfwork_t *dfw, stnode_t *st_node);
static fvalue_t *
mk_fvalue_from_val_string(dfwork_t *dfw, header_field_info *hfinfo, const char *s);
@ -903,6 +909,36 @@ again:
}
}
static void
check_relation_LHS_BITWISE(dfwork_t *dfw, test_op_t st_op _U_,
FtypeCanFunc can_func _U_, gboolean allow_partial_value,
stnode_t *st_node _U_,
stnode_t *st_arg1, stnode_t *st_arg2)
{
stnode_t *bitwise_entity;
sttype_id_t bitwise_entity_type;
LOG_NODE(st_node);
/* (arg1: bitwise) <relop> (arg2: rhs) */
check_bitwise_operation(dfw, st_arg1);
sttype_test_get(st_arg1, NULL, &bitwise_entity, NULL);
bitwise_entity_type = stnode_type_id(bitwise_entity);
if (bitwise_entity_type == STTYPE_FIELD) {
check_relation_LHS_FIELD(dfw, st_op, can_func, allow_partial_value, st_node, bitwise_entity, st_arg2);
}
else if (bitwise_entity_type == STTYPE_RANGE) {
check_relation_LHS_RANGE(dfw, st_op, can_func, allow_partial_value, st_node, bitwise_entity, st_arg2);
}
else if (bitwise_entity_type == STTYPE_FUNCTION) {
check_relation_LHS_FUNCTION(dfw, st_op, can_func, allow_partial_value, st_node, bitwise_entity, st_arg2);
}
else {
ws_assert_not_reached();
}
}
/* Check the semantics of any relational test. */
static void
@ -927,6 +963,10 @@ check_relation(dfwork_t *dfw, test_op_t st_op,
check_relation_LHS_FUNCTION(dfw, st_op, can_func,
allow_partial_value, st_node, st_arg1, st_arg2);
break;
case STTYPE_BITWISE:
check_relation_LHS_BITWISE(dfw, st_op, can_func,
allow_partial_value, st_node, st_arg1, st_arg2);
break;
default:
FAIL(dfw, "Left side of %s expression must be a field or function, not %s.",
stnode_todisplay(st_node), stnode_todisplay(st_arg1));
@ -1075,6 +1115,11 @@ check_test(dfwork_t *dfw, stnode_t *st_node)
check_exists(dfw, st_arg1);
break;
case TEST_OP_NOTZERO:
ws_assert(stnode_type_id(st_arg1) == STTYPE_BITWISE);
check_bitwise_operation(dfw, st_arg1);
break;
case TEST_OP_NOT:
semcheck(dfw, st_arg1);
break;
@ -1113,9 +1158,6 @@ check_test(dfwork_t *dfw, stnode_t *st_node)
case TEST_OP_LE:
check_relation(dfw, st_op, ftype_can_cmp, FALSE, st_node, st_arg1, st_arg2);
break;
case TEST_OP_BITWISE_AND:
check_relation(dfw, st_op, ftype_can_bitwise_and, FALSE, st_node, st_arg1, st_arg2);
break;
case TEST_OP_CONTAINS:
check_relation_contains(dfw, st_node, st_arg1, st_arg2);
break;
@ -1131,6 +1173,95 @@ check_test(dfwork_t *dfw, stnode_t *st_node)
}
}
static ftenum_t
check_bitwise_entity(dfwork_t *dfw, stnode_t *st_node, stnode_t *st_arg, ftenum_t lhs_ftype)
{
header_field_info *hfinfo;
ftenum_t ftype;
fvalue_t *fvalue;
sttype_id_t type;
df_func_def_t *funcdef;
LOG_NODE(st_arg);
resolve_unparsed(dfw, st_arg);
type = stnode_type_id(st_arg);
if (type == STTYPE_FIELD) {
hfinfo = stnode_data(st_arg);
ftype = hfinfo->type;
if (!ftype_can_bitwise_and(ftype)) {
FAIL(dfw, "%s (type=%s) cannot participate in %s comparison.",
hfinfo->abbrev, ftype_pretty_name(ftype),
stnode_todisplay(st_node));
}
return ftype;
}
else if (type == STTYPE_FUNCTION) {
check_function(dfw, st_arg);
funcdef = sttype_function_funcdef(st_arg);
ftype = funcdef->retval_ftype;
if (!ftype_can_bitwise_and(ftype)) {
FAIL(dfw, "Function %s (type=%s) cannot participate in %s comparison.",
funcdef->name, ftype_pretty_name(ftype),
stnode_todisplay(st_node));
}
return ftype;
}
else if (type == STTYPE_RANGE) {
check_drange_sanity(dfw, st_arg);
ftype = FT_BYTES;
if (!ftype_can_bitwise_and(ftype)) {
FAIL(dfw, "Range %s (type=%s) cannot participate in %s comparison.",
stnode_todisplay(st_arg), ftype_pretty_name(ftype),
stnode_todisplay(st_node));
}
return ftype;
}
else if (lhs_ftype != FT_NONE) {
/* numeric constant */
ftype = lhs_ftype;
fvalue = dfilter_fvalue_from_literal(dfw, ftype, st_arg, FALSE, NULL);
stnode_replace(st_arg, STTYPE_FVALUE, fvalue);
}
else {
FAIL(dfw, "Invalid bitwise operand %s in comparison %s.",
stnode_todisplay(st_arg), stnode_todisplay(st_arg));
}
return ftype;
}
static ftenum_t
check_bitwise_operation(dfwork_t *dfw, stnode_t *st_node)
{
test_op_t st_op;
stnode_t *st_arg1, *st_arg2;
ftenum_t ftype1, ftype2;
LOG_NODE(st_node);
sttype_test_get(st_node, &st_op, &st_arg1, &st_arg2);
ftype1 = check_bitwise_entity(dfw, st_node, st_arg1, FT_NONE);
ftype2 = check_bitwise_entity(dfw, st_node, st_arg2, ftype1);
if (!ftype_can_is_true(ftype1)) {
FAIL(dfw, "Cannot test if %s is true", stnode_todisplay(st_arg1));
}
/* XXX This could be relaxed with type promotions. */
if (ftype1 != ftype2) {
FAIL(dfw, "%s %s %s: entities have different types",
stnode_todisplay(st_arg1),
stnode_todisplay(st_node),
stnode_todisplay(st_arg2));
}
return ftype1;
}
/* Check the entire syntax tree. */
static void

View File

@ -71,7 +71,7 @@ test_todisplay(test_op_t op)
switch(op) {
case TEST_OP_EXISTS:
s = "exists";
s = "<exists>";
break;
case TEST_OP_NOT:
s = "!";
@ -106,9 +106,12 @@ test_todisplay(test_op_t op)
case TEST_OP_LE:
s = "<=";
break;
case TEST_OP_BITWISE_AND:
case OP_BITWISE_AND:
s = "&";
break;
case TEST_OP_NOTZERO:
s = "<notzero>";
break;
case TEST_OP_CONTAINS:
s = "contains";
break;
@ -170,8 +173,11 @@ test_todebug(test_op_t op)
case TEST_OP_LE:
s = "TEST_LE";
break;
case TEST_OP_BITWISE_AND:
s = "TEST_BITAND";
case OP_BITWISE_AND:
s = "BITWISE_AND";
break;
case TEST_OP_NOTZERO:
s = "TEST_NOTZERO";
break;
case TEST_OP_CONTAINS:
s = "TEST_CONTAINS";
@ -214,6 +220,7 @@ num_operands(test_op_t op)
break;
case TEST_OP_EXISTS:
case TEST_OP_NOT:
case TEST_OP_NOTZERO:
return 1;
case TEST_OP_AND:
case TEST_OP_OR:
@ -225,7 +232,7 @@ num_operands(test_op_t op)
case TEST_OP_GE:
case TEST_OP_LT:
case TEST_OP_LE:
case TEST_OP_BITWISE_AND:
case OP_BITWISE_AND:
case TEST_OP_CONTAINS:
case TEST_OP_MATCHES:
case TEST_OP_IN:
@ -325,8 +332,18 @@ sttype_register_test(void)
test_dup,
test_tostr
};
/* XXX Bitwise ops are not "tests". */
static sttype_t bitwise_type = {
STTYPE_BITWISE,
"BITWISE",
test_new,
test_free,
test_dup,
test_tostr
};
sttype_register(&test_type);
sttype_register(&bitwise_type);
}
/*

View File

@ -412,7 +412,8 @@ visit_tree(wmem_strbuf_t *buf, stnode_t *node, int level)
{
stnode_t *left, *right;
if (stnode_type_id(node) == STTYPE_TEST) {
if (stnode_type_id(node) == STTYPE_TEST ||
stnode_type_id(node) == STTYPE_BITWISE) {
wmem_strbuf_append_printf(buf, "%s(", stnode_todebug(node));
sttype_test_get(node, NULL, &left, &right);
if (left && right) {

View File

@ -32,6 +32,7 @@ typedef enum {
STTYPE_FUNCTION,
STTYPE_SET,
STTYPE_PCRE,
STTYPE_BITWISE,
STTYPE_NUM_TYPES
} sttype_id_t;
@ -49,7 +50,8 @@ typedef enum {
TEST_OP_GE,
TEST_OP_LT,
TEST_OP_LE,
TEST_OP_BITWISE_AND,
OP_BITWISE_AND,
TEST_OP_NOTZERO,
TEST_OP_CONTAINS,
TEST_OP_MATCHES,
TEST_OP_IN

View File

@ -515,26 +515,29 @@ cmp_order(const fvalue_t *fv_a, const fvalue_t *fv_b)
return memcmp(a->data, b->data, a->len);
}
static gboolean
cmp_bitwise_and(const fvalue_t *fv_a, const fvalue_t *fv_b)
static enum ft_result
bytes_bitwise_and(fvalue_t *fv_dst, const fvalue_t *fv_a, const fvalue_t *fv_b, char **err_ptr _U_)
{
GByteArray *a = fv_a->value.bytes;
GByteArray *b = fv_b->value.bytes;
guint i = 0;
GByteArray *dst;
unsigned char *p_a, *p_b;
if (b->len != a->len) {
return FALSE;
guint len = MIN(a->len, b->len);
if (len == 0) {
fv_dst->value.bytes = g_byte_array_new();
return FT_OK;
}
dst = g_byte_array_sized_new(len);
p_a = a->data;
p_b = b->data;
while (i < b->len) {
if (p_a[i] & p_b[i])
return TRUE;
else
i++;
for (guint i = 0; i < len; i++) {
guint8 byte = p_a[i] & p_b[i];
g_byte_array_append(dst, &byte, 1);
}
return FALSE;
fv_dst->value.bytes = dst;
return FT_OK;
}
static gboolean
@ -559,6 +562,22 @@ cmp_matches(const fvalue_t *fv, const ws_regex_t *regex)
return ws_regex_matches_length(regex, a->data, a->len);
}
static gboolean
bytes_is_true(const fvalue_t *fv_a)
{
GByteArray *a = fv_a->value.bytes;
if (a->len == 0)
return FALSE;
for (guint i = 0; i < a->len; i++) {
if (a->data[i] != 0) {
return TRUE;
}
}
return FALSE;
}
void
ftype_register_bytes(void)
{
@ -579,12 +598,13 @@ ftype_register_bytes(void)
{ .get_value_ptr = value_get }, /* union get_value */
cmp_order,
cmp_bitwise_and,
cmp_contains,
cmp_matches,
bytes_is_true, /* is_true */
len,
slice,
bytes_bitwise_and, /* bitwise_and */
};
static ftype_t uint_bytes_type = {
@ -603,12 +623,13 @@ ftype_register_bytes(void)
{ .get_value_ptr = value_get }, /* union get_value */
cmp_order,
cmp_bitwise_and,
cmp_contains,
NULL, /* cmp_matches */
bytes_is_true, /* is_true */
len,
slice,
bytes_bitwise_and, /* bitwise_and */
};
static ftype_t ax25_type = {
@ -627,12 +648,13 @@ ftype_register_bytes(void)
{ .get_value_ptr = value_get }, /* union get_value */
cmp_order,
cmp_bitwise_and,
cmp_contains,
cmp_matches,
bytes_is_true, /* is_true */
len,
slice,
bytes_bitwise_and, /* bitwise_and */
};
static ftype_t vines_type = {
@ -651,12 +673,13 @@ ftype_register_bytes(void)
{ .get_value_ptr = value_get }, /* union get_value */
cmp_order,
cmp_bitwise_and,
cmp_contains,
cmp_matches,
bytes_is_true, /* is_true */
len,
slice,
bytes_bitwise_and, /* bitwise_and */
};
static ftype_t ether_type = {
@ -675,12 +698,13 @@ ftype_register_bytes(void)
{ .get_value_ptr = value_get }, /* union get_value */
cmp_order,
cmp_bitwise_and,
cmp_contains,
cmp_matches,
bytes_is_true, /* is_true */
len,
slice,
bytes_bitwise_and, /* bitwise_and */
};
static ftype_t oid_type = {
@ -699,12 +723,13 @@ ftype_register_bytes(void)
{ .get_value_ptr = value_get }, /* union get_value */
cmp_order,
cmp_bitwise_and,
cmp_contains,
NULL, /* cmp_matches */
bytes_is_true, /* is_true */
len,
slice,
bytes_bitwise_and, /* bitwise_and */
};
static ftype_t rel_oid_type = {
@ -723,12 +748,13 @@ ftype_register_bytes(void)
{ .get_value_ptr = value_get }, /* union get_value */
cmp_order,
cmp_bitwise_and,
cmp_contains,
NULL, /* cmp_matches */
bytes_is_true, /* is_true */
len,
slice,
bytes_bitwise_and, /* bitwise_and */
};
static ftype_t system_id_type = {
@ -747,12 +773,13 @@ ftype_register_bytes(void)
{ .get_value_ptr = value_get }, /* union get_value */
cmp_order,
cmp_bitwise_and,
cmp_contains,
NULL, /* cmp_matches */
bytes_is_true, /* is_true */
len,
slice,
bytes_bitwise_and, /* bitwise_and */
};
static ftype_t fcwwn_type = {
@ -771,12 +798,13 @@ ftype_register_bytes(void)
{ .get_value_ptr = value_get }, /* union get_value */
cmp_order,
cmp_bitwise_and,
cmp_contains,
cmp_matches,
bytes_is_true, /* is_true */
len,
slice,
bytes_bitwise_and, /* bitwise_and */
};
ftype_register(FT_BYTES, &bytes_type);

View File

@ -85,6 +85,12 @@ double_val_to_repr(wmem_allocator_t *scope, const fvalue_t *fv, ftrepr_t rtype _
return buf;
}
static gboolean
double_is_true(const fvalue_t *fv)
{
return fv->value.floating != 0.0;
}
static int
cmp_order(const fvalue_t *a, const fvalue_t *b)
{
@ -115,12 +121,13 @@ ftype_register_double(void)
{ .get_value_floating = value_get_floating }, /* union get_value */
cmp_order,
NULL, /* cmp_bitwise_and */
NULL, /* cmp_contains */
NULL, /* cmp_matches */
double_is_true, /* is_true */
NULL,
NULL,
NULL, /* bitwise_and */
};
static ftype_t double_type = {
@ -139,12 +146,13 @@ ftype_register_double(void)
{ .get_value_floating = value_get_floating }, /* union get_value */
cmp_order,
NULL, /* cmp_bitwise_and */
NULL, /* cmp_contains */
NULL, /* cmp_matches */
double_is_true, /* is_true */
NULL,
NULL,
NULL, /* bitwise_and */
};
ftype_register(FT_FLOAT, &float_type);

View File

@ -114,11 +114,12 @@ ftype_register_guid(void)
cmp_order,
NULL,
NULL,
NULL, /* cmp_matches */
NULL,
NULL,
NULL,
NULL,
};
ftype_register(FT_GUID, &guid_type);

View File

@ -453,9 +453,9 @@ sfloat_ieee_11073_cmp_order(const fvalue_t *a, const fvalue_t *b)
}
static gboolean
sfloat_ieee_11073_cmp_bitwise_and(const fvalue_t *a, const fvalue_t *b)
sfloat_ieee_11073_is_true(const fvalue_t *a)
{
return ((a->value.uinteger & b->value.uinteger) != 0);
return a->value.sfloat_ieee_11073 != 0;
}
/*============================================================================*/
@ -862,9 +862,9 @@ float_ieee_11073_cmp_order(const fvalue_t *a, const fvalue_t *b)
}
static gboolean
float_ieee_11073_cmp_bitwise_and(const fvalue_t *a, const fvalue_t *b)
float_ieee_11073_is_true(const fvalue_t *a)
{
return ((a->value.uinteger & b->value.uinteger) != 0);
return a->value.float_ieee_11073 != 0;
}
/*============================================================================*/
@ -914,12 +914,13 @@ Example: 114 is 0x0072
{ .get_value_uinteger = sfloat_ieee_11073_value_get }, /* union get_value */
sfloat_ieee_11073_cmp_order,
sfloat_ieee_11073_cmp_bitwise_and, /* cmp_bitwise_and */
NULL, /* cmp_contains */
NULL, /* cmp_matches */
NULL, /* len */
NULL, /* slice */
sfloat_ieee_11073_is_true, /* is_true */
NULL, /* len */
NULL, /* slice */
NULL, /* bitwise_and */
};
/*
@ -965,12 +966,13 @@ Example: 36.4 is 0xFF00016C
{ .get_value_uinteger = float_ieee_11073_value_get }, /* union get_value */
float_ieee_11073_cmp_order,
float_ieee_11073_cmp_bitwise_and, /* cmp_bitwise_and */
NULL, /* cmp_contains */
NULL, /* cmp_matches */
float_ieee_11073_is_true, /* is_true */
NULL, /* len */
NULL, /* slice */
NULL, /* bitwise_and */
};
ftype_register(FT_IEEE_11073_SFLOAT, &sfloat_type);

View File

@ -458,12 +458,6 @@ sinteger64_cmp_order(const fvalue_t *a, const fvalue_t *b)
return a->value.sinteger64 < b->value.sinteger64 ? -1 : 1;
}
static gboolean
cmp_bitwise_and(const fvalue_t *a, const fvalue_t *b)
{
return ((a->value.uinteger & b->value.uinteger) != 0);
}
static void
int64_fvalue_new(fvalue_t *fv)
{
@ -746,10 +740,56 @@ uinteger64_to_repr(wmem_allocator_t *scope, const fvalue_t *fv, ftrepr_t rtype _
return result;
}
static gboolean
cmp_bitwise_and64(const fvalue_t *a, const fvalue_t *b)
enum ft_result
uint_bitwise_and(fvalue_t *dst, const fvalue_t *a, const fvalue_t *b, char **err_ptr _U_)
{
return ((a->value.uinteger64 & b->value.uinteger64) != 0);
dst->value.uinteger = a->value.uinteger & b->value.uinteger;
return FT_OK;
}
gboolean
uint_is_true(const fvalue_t *fv)
{
return fv->value.uinteger != 0;
}
enum ft_result
uint64_bitwise_and(fvalue_t *dst, const fvalue_t *a, const fvalue_t *b, char **err_ptr _U_)
{
dst->value.uinteger64 = a->value.uinteger64 & b->value.uinteger64;
return FT_OK;
}
gboolean
uint64_is_true(const fvalue_t *fv)
{
return fv->value.uinteger64 != 0;
}
enum ft_result
sint_bitwise_and(fvalue_t *dst, const fvalue_t *a, const fvalue_t *b, char **err_ptr _U_)
{
dst->value.sinteger = a->value.sinteger & b->value.sinteger;
return FT_OK;
}
gboolean
sint_is_true(const fvalue_t *fv)
{
return fv->value.sinteger != 0;
}
enum ft_result
sint64_bitwise_and(fvalue_t *dst, const fvalue_t *a, const fvalue_t *b, char **err_ptr _U_)
{
dst->value.sinteger64 = a->value.sinteger64 & b->value.sinteger64;
return FT_OK;
}
gboolean
sint64_is_true(const fvalue_t *fv)
{
return fv->value.sinteger64 != 0;
}
/* BOOLEAN-specific */
@ -869,12 +909,13 @@ ftype_register_integers(void)
{ .get_value_uinteger = get_uinteger }, /* union get_value */
uinteger_cmp_order,
cmp_bitwise_and,
NULL, /* cmp_contains */
NULL, /* cmp_matches */
uint_is_true, /* is_true */
NULL, /* len */
NULL, /* slice */
uint_bitwise_and, /* bitwise_and */
};
static ftype_t uint8_type = {
FT_UINT8, /* ftype */
@ -892,12 +933,13 @@ ftype_register_integers(void)
{ .get_value_uinteger = get_uinteger }, /* union get_value */
uinteger_cmp_order,
cmp_bitwise_and,
NULL, /* cmp_contains */
NULL, /* cmp_matches */
uint_is_true, /* is_true */
NULL, /* len */
NULL, /* slice */
uint_bitwise_and, /* bitwise_and */
};
static ftype_t uint16_type = {
FT_UINT16, /* ftype */
@ -915,12 +957,13 @@ ftype_register_integers(void)
{ .get_value_uinteger = get_uinteger }, /* union get_value */
uinteger_cmp_order,
cmp_bitwise_and,
NULL, /* cmp_contains */
NULL, /* cmp_matches */
uint_is_true, /* is_true */
NULL, /* len */
NULL, /* slice */
uint_bitwise_and, /* bitwise_and */
};
static ftype_t uint24_type = {
FT_UINT24, /* ftype */
@ -938,12 +981,13 @@ ftype_register_integers(void)
{ .get_value_uinteger = get_uinteger }, /* union get_value */
uinteger_cmp_order,
cmp_bitwise_and,
NULL, /* cmp_contains */
NULL, /* cmp_matches */
uint_is_true, /* is_true */
NULL, /* len */
NULL, /* slice */
uint_bitwise_and, /* bitwise_and */
};
static ftype_t uint32_type = {
FT_UINT32, /* ftype */
@ -961,12 +1005,13 @@ ftype_register_integers(void)
{ .get_value_uinteger = get_uinteger }, /* union get_value */
uinteger_cmp_order,
cmp_bitwise_and,
NULL, /* cmp_contains */
NULL, /* cmp_matches */
uint_is_true, /* is_true */
NULL, /* len */
NULL, /* slice */
uint_bitwise_and, /* bitwise_and */
};
static ftype_t uint40_type = {
FT_UINT40, /* ftype */
@ -984,12 +1029,13 @@ ftype_register_integers(void)
{ .get_value_uinteger64 = get_uinteger64 }, /* union get_value */
uinteger64_cmp_order,
cmp_bitwise_and64,
NULL, /* cmp_contains */
NULL, /* cmp_matches */
NULL,
NULL,
uint64_is_true, /* is_true */
NULL, /* len */
NULL, /* slice */
uint64_bitwise_and, /* bitwise_and */
};
static ftype_t uint48_type = {
FT_UINT48, /* ftype */
@ -1007,12 +1053,13 @@ ftype_register_integers(void)
{ .get_value_uinteger64 = get_uinteger64 }, /* union get_value */
uinteger64_cmp_order,
cmp_bitwise_and64,
NULL, /* cmp_contains */
NULL, /* cmp_matches */
NULL,
NULL,
uint64_is_true, /* is_true */
NULL, /* len */
NULL, /* slice */
uint64_bitwise_and, /* bitwise_and */
};
static ftype_t uint56_type = {
FT_UINT56, /* ftype */
@ -1030,12 +1077,13 @@ ftype_register_integers(void)
{ .get_value_uinteger64 = get_uinteger64 }, /* union get_value */
uinteger64_cmp_order,
cmp_bitwise_and64,
NULL, /* cmp_contains */
NULL, /* cmp_matches */
NULL,
NULL,
uint64_is_true, /* is_true */
NULL, /* len */
NULL, /* slice */
uint64_bitwise_and, /* bitwise_and */
};
static ftype_t uint64_type = {
FT_UINT64, /* ftype */
@ -1053,12 +1101,13 @@ ftype_register_integers(void)
{ .get_value_uinteger64 = get_uinteger64 }, /* union get_value */
uinteger64_cmp_order,
cmp_bitwise_and64,
NULL, /* cmp_contains */
NULL, /* cmp_matches */
NULL,
NULL,
uint64_is_true, /* is_true */
NULL, /* len */
NULL, /* slice */
uint64_bitwise_and, /* bitwise_and */
};
static ftype_t int8_type = {
FT_INT8, /* ftype */
@ -1076,12 +1125,13 @@ ftype_register_integers(void)
{ .get_value_sinteger = get_sinteger }, /* union get_value */
sinteger_cmp_order,
cmp_bitwise_and,
NULL, /* cmp_contains */
NULL, /* cmp_matches */
sint_is_true, /* is_true */
NULL, /* len */
NULL, /* slice */
sint_bitwise_and, /* bitwise_and */
};
static ftype_t int16_type = {
FT_INT16, /* ftype */
@ -1099,12 +1149,13 @@ ftype_register_integers(void)
{ .get_value_sinteger = get_sinteger }, /* union get_value */
sinteger_cmp_order,
cmp_bitwise_and,
NULL, /* cmp_contains */
NULL, /* cmp_matches */
sint_is_true, /* is_true */
NULL, /* len */
NULL, /* slice */
sint_bitwise_and, /* bitwise_and */
};
static ftype_t int24_type = {
FT_INT24, /* ftype */
@ -1122,12 +1173,13 @@ ftype_register_integers(void)
{ .get_value_sinteger = get_sinteger }, /* union get_value */
sinteger_cmp_order,
cmp_bitwise_and,
NULL, /* cmp_contains */
NULL, /* cmp_matches */
sint_is_true, /* is_true */
NULL, /* len */
NULL, /* slice */
sint_bitwise_and, /* bitwise_and */
};
static ftype_t int32_type = {
FT_INT32, /* ftype */
@ -1145,12 +1197,13 @@ ftype_register_integers(void)
{ .get_value_sinteger = get_sinteger }, /* union get_value */
sinteger_cmp_order,
cmp_bitwise_and,
NULL, /* cmp_contains */
NULL, /* cmp_matches */
sint_is_true, /* is_true */
NULL, /* len */
NULL, /* slice */
sint_bitwise_and, /* bitwise_and */
};
static ftype_t int40_type = {
FT_INT40, /* ftype */
@ -1168,12 +1221,13 @@ ftype_register_integers(void)
{ .get_value_sinteger64 = get_sinteger64 }, /* union get_value */
sinteger64_cmp_order,
cmp_bitwise_and64,
NULL, /* cmp_contains */
NULL, /* cmp_matches */
NULL,
NULL,
sint64_is_true, /* is_true */
NULL, /* len */
NULL, /* slice */
sint64_bitwise_and, /* bitwise_and */
};
static ftype_t int48_type = {
FT_INT48, /* ftype */
@ -1191,12 +1245,13 @@ ftype_register_integers(void)
{ .get_value_sinteger64 = get_sinteger64 }, /* union get_value */
sinteger64_cmp_order,
cmp_bitwise_and64,
NULL, /* cmp_contains */
NULL, /* cmp_matches */
NULL,
NULL,
sint64_is_true, /* is_true */
NULL, /* len */
NULL, /* slice */
sint64_bitwise_and, /* bitwise_and */
};
static ftype_t int56_type = {
FT_INT56, /* ftype */
@ -1214,12 +1269,13 @@ ftype_register_integers(void)
{ .get_value_sinteger64 = get_sinteger64 }, /* union get_value */
sinteger64_cmp_order,
cmp_bitwise_and64,
NULL, /* cmp_contains */
NULL, /* cmp_matches */
NULL,
NULL,
sint64_is_true, /* is_true */
NULL, /* len */
NULL, /* slice */
sint64_bitwise_and, /* bitwise_and */
};
static ftype_t int64_type = {
FT_INT64, /* ftype */
@ -1237,12 +1293,13 @@ ftype_register_integers(void)
{ .get_value_sinteger64 = get_sinteger64 }, /* union get_value */
sinteger64_cmp_order,
cmp_bitwise_and64,
NULL, /* cmp_contains */
NULL, /* cmp_matches */
NULL,
NULL,
sint64_is_true, /* is_true */
NULL, /* len */
NULL, /* slice */
sint64_bitwise_and, /* bitwise_and */
};
static ftype_t boolean_type = {
FT_BOOLEAN, /* ftype */
@ -1260,12 +1317,13 @@ ftype_register_integers(void)
{ .get_value_uinteger64 = get_uinteger64 }, /* union get_value */
boolean_cmp_order, /* cmp_eq */
NULL, /* cmp_bitwise_and */
NULL, /* cmp_contains */
NULL, /* cmp_matches */
uint64_is_true, /* is_true */
NULL, /* len */