Incredibly hacky evaluate implementation

This commit is contained in:
David Adrian 2013-09-20 14:35:07 -04:00
parent f7939bfbcb
commit 29c291c562
7 changed files with 140 additions and 13 deletions

View File

@ -1,11 +1,17 @@
#include "expression.h" #include "expression.h"
#include "fieldset.H"
#include "../lib/xalloc.h" #include "../lib/xalloc.h"
/* Static helper functions */ /* Static helper functions */
static node_t* alloc_node(); static node_t* alloc_node();
static int eval_single_node(node_t* node); static int eval_gt_node(node_t *node, fieldset_t *fields);
static int eval_lt_node(node_t *node, fieldset_t *fields);
static int eval_eq_node(node_t *node, fieldset_t *fields);
static int eval_lt_eq_node(node_t *node, fieldset_t *fields);
static int eval_gt_eq_node(node_t *node, fieldset_t *fields);
static node_t* alloc_node() static node_t* alloc_node()
{ {
@ -14,6 +20,54 @@ static node_t* alloc_node()
return node; return node;
} }
static int eval_gt_node(node_t *node, fieldset_t *fields)
{
int index = node->left_child->value.field.index;
uint64_t expected = node->right_child->value.int_literal;
uint64_t actual = fs_get_uint64_by_index(fields, index);
return (actual > expected);
}
static int eval_lt_node(node_t *node, fieldset_t *fields)
{
int index = node->left_child->value.field.index;
uint64_t expected = node->right_child->value.int_literal;
uint64_t actual = fs_get_uint64_by_index(fields, index);
return (actual < expected);
}
static int eval_eq_node(node_t *node, fieldset_t *fields)
{
node_t *literal = node->right_child;
int index = node->left_child->value.field.index;
char *expected, *actual;
switch (literal->type) {
case STRING:
expected = literal->value.string_literal;
actual = fs_get_string_by_index(fields, index);
return (strcmp(expected, actual) == 0);
break;
case INT:
return (fs_get_uint64_by_index(fields, index) == literal->value.int_literal);
break;
default:
printf("wat\n");
break;
}
return 0;
}
static int eval_lt_eq_node(node_t *node, fieldset_t *fields)
{
return !(eval_gt_node(node, fields));
}
static int eval_gt_eq_node(node_t *node, fieldset_t *fields)
{
return !(eval_lt_node(node, fields));
}
/* Exposed functions */ /* Exposed functions */
node_t* make_op_node(enum operation op) node_t* make_op_node(enum operation op)
@ -48,10 +102,37 @@ node_t* make_int_node(int literal)
return node; return node;
} }
int evaluate_expression(node_t *root) { int evaluate_expression(node_t *root, fieldset_t *fields) {
if (!root) return 0; if (!root) return 1;
int result = 1; switch (root->type) { /* XXX Not sure if runs */
return result; case FIELD:
case STRING:
case INT:
return 1;
case OP:
break;
}
switch (root->value.op) {
case GT:
return eval_gt_node(root, fields);
case LT:
return eval_lt_node(root, fields);
case EQ:
return eval_eq_node(root, fields);
case NEQ:
return (!eval_eq_node(root, fields));
case LT_EQ:
return eval_lt_eq_node(root, fields);
case GT_EQ:
return eval_gt_eq_node(root, fields);
case AND:
return (evaluate_expression(root->left_child, fields)
&& evaluate_expression(root->right_child, fields));
case OR:
return (evaluate_expression(root->left_child, fields)
|| evaluate_expression(root->right_child, fields));
}
return 0;
} }
void print_expression(node_t *root) { void print_expression(node_t *root) {
@ -69,7 +150,7 @@ void print_expression(node_t *root) {
printf("%s) ", root->value.string_literal); printf("%s) ", root->value.string_literal);
break; break;
case INT: case INT:
printf(" %d) ", root->value.int_literal); printf(" %llu) ", (long long unsigned) root->value.int_literal);
break; break;
default: default:
break; break;

View File

@ -1,9 +1,12 @@
#ifndef ZMAP_TREE_H #ifndef ZMAP_TREE_H
#define ZMAP_TREE_H #define ZMAP_TREE_H
#include "fieldset.h"
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h>
enum operation { enum operation {
GT, LT, EQ, NEQ, AND, OR, LT_EQ, GT_EQ GT, LT, EQ, NEQ, AND, OR, LT_EQ, GT_EQ
@ -21,7 +24,7 @@ struct field_id {
union node_value { union node_value {
struct field_id field; struct field_id field;
char *string_literal; char *string_literal;
int int_literal; uint64_t int_literal;
enum operation op; enum operation op;
}; };
@ -40,8 +43,6 @@ node_t* make_string_node(char *literal);
node_t* make_int_node(int literal); node_t* make_int_node(int literal);
int evaluate_expression(node_t *root); int evaluate_expression(node_t *root, fieldset_t *fields);
void print_expression(node_t *root);
#endif /* ZMAP_TREE_H */ #endif /* ZMAP_TREE_H */

View File

@ -4,10 +4,32 @@
#include "y.tab.h" #include "y.tab.h"
#include "../lib/logger.h" #include "../lib/logger.h"
#include <string.h>
extern int yyparse(); extern int yyparse();
node_t *zfilter; node_t *zfilter;
static int validate_node(node_t *node, fielddefset_t *fields)
{
int i;
if (node->type != FIELD) {
return 1;
}
for (i = 0; i < MAX_FIELDS; i++) {
if (fields->fielddefs[i].name) {
if (strcmp(fields->fielddefs[i].name, node->value.field.fieldname) == 0) {
node->value.field.index = i;
return 1;
}
}
}
// Didn't find it
return 0;
}
int parse_filter_string(char *filter) int parse_filter_string(char *filter)
{ {
YY_BUFFER_STATE buffer_state = yy_scan_string(filter); YY_BUFFER_STATE buffer_state = yy_scan_string(filter);
@ -23,4 +45,18 @@ int parse_filter_string(char *filter)
printf("%s\n", ""); printf("%s\n", "");
fflush(stdout); fflush(stdout);
return 1; return 1;
} }
int validate_filter(node_t *root, fielddefset_t *fields)
{
int valid;
if (!root) {
return 1;
}
valid = validate_node(root, fields);
if (!valid) {
return 0;
}
return (validate_filter(root->left_child, fields) && validate_filter(root->right_child, fields));
}

View File

@ -2,6 +2,7 @@
#define ZMAP_FILTER_H #define ZMAP_FILTER_H
#include "expression.h" #include "expression.h"
#include "fieldset.h"
struct output_filter { struct output_filter {
node_t *expression; node_t *expression;
@ -9,4 +10,6 @@ struct output_filter {
int parse_filter_string(char *filter); int parse_filter_string(char *filter);
int validate_filter(node_t *root, fielddefset_t *fields);
#endif /* ZMAP_FILTER_H */ #endif /* ZMAP_FILTER_H */

View File

@ -745,7 +745,7 @@ do_action: /* This label is used only to access EOF actions. */
case 1: case 1:
YY_RULE_SETUP YY_RULE_SETUP
#line 10 "lexer.l" #line 10 "lexer.l"
yylval.int_literal = atoi(yytext); return T_NUMBER; yylval.int_literal = (uint64_t) atoll(yytext); return T_NUMBER;
YY_BREAK YY_BREAK
case 2: case 2:
/* rule 2 can match eol */ /* rule 2 can match eol */

View File

@ -7,7 +7,7 @@
%option noinput %option noinput
%option nounput %option nounput
%% %%
[0-9]+ yylval.int_literal = atoi(yytext); return T_NUMBER; [0-9]+ yylval.int_literal = (uint64_t) atoll(yytext); return T_NUMBER;
\n /* Ignore end of line */ \n /* Ignore end of line */
[ \t]+ /* Ignore whitespace */ [ \t]+ /* Ignore whitespace */
!= return T_NOT_EQ; != return T_NOT_EQ;

View File

@ -501,9 +501,15 @@ int main(int argc, char *argv[])
// Parse and validate the output filter, if any // Parse and validate the output filter, if any
if (args.output_filter_arg) { if (args.output_filter_arg) {
// Run it through yyparse to build the expression tree
if (!parse_filter_string(args.output_filter_arg)) { if (!parse_filter_string(args.output_filter_arg)) {
log_fatal("zmap", "Unable to parse filter expression"); log_fatal("zmap", "Unable to parse filter expression");
} }
// Check the fields used against the fieldset in use
if (!validate_filter(zconf.filter.expression, &zconf.fsconf.defs)) {
log_fatal("zmap", "Field does not exist");
}
} }
SET_BOOL(zconf.dryrun, dryrun); SET_BOOL(zconf.dryrun, dryrun);