matcher-ac: expansion of nested alternates within alternate expr

matcher-ac: three types of alternates: byte, fixed, and generic (variable)
remotes/push_mirror/klin/altstr-yara
Kevin Lin 10 years ago
parent 2b51265826
commit 59506ff519
  1. 2
      libclamav/filtering.c
  2. 686
      libclamav/matcher-ac.c
  3. 16
      libclamav/matcher-ac.h

@ -279,7 +279,7 @@ static inline unsigned char spec_ith_char(const struct char_spec *spec, unsigned
if (alt) {
assert (alt->type == 1);
assert (i < alt->num);
return alt->str[i];
return (alt->alt).byte[i];
}
return i;
}

@ -91,7 +91,8 @@ static inline int insert_list(struct cli_matcher *root, struct cli_ac_patt *patt
struct cli_ac_list **newtable;
struct cli_ac_patt *php;
struct cli_ac_special *a1, *a2;
uint8_t i, match;
struct cli_alt_node *b1, *b2;
uint8_t i, j, match;
new = (struct cli_ac_list *)mpool_calloc(root->mempool, 1, sizeof(struct cli_ac_list));
if (!new) {
@ -142,23 +143,40 @@ static inline int insert_list(struct cli_matcher *root, struct cli_ac_patt *patt
match = 0;
break;
} else if(a1->type == AC_SPECIAL_ALT_CHAR) {
if(memcmp(a1->str, a2->str, a1->num)) {
if(memcmp((a1->alt).byte, (a2->alt).byte, a1->num)) {
match = 0;
break;
}
} else if(a1->type == AC_SPECIAL_ALT_STR_FIXED) {
if(a1->len != a2->len) {
match = 0;
break;
}
for(j = 0; j < a1->num; j++) {
if(memcmp((a1->alt).f_str[j], (a2->alt).f_str[j], a1->len))
break;
}
if(j < a1->num) {
match = 0;
break;
}
} else if(a1->type == AC_SPECIAL_ALT_STR) {
while(a1 && a2) {
if((a1->len != a2->len) || memcmp(a1->str, a2->str, a1->len))
break;
a1 = a1->next;
a2 = a2->next;
}
b1 = (a1->alt).v_str;
b2 = (a2->alt).v_str;
while(b1 && b2) {
if((b1->len != b2->len) || memcmp(b1->str, b2->str, b1->len))
break;
b1 = b1->next;
b2 = b2->next;
}
if(a1 || a2) {
match = 0;
break;
}
}
if(b1 || b2) {
match = 0;
break;
}
}
}
} else {
match = 0;
@ -521,8 +539,9 @@ static void ac_free_special(mpool_t *mempool, struct cli_ac_patt *p)
static void ac_free_special(struct cli_ac_patt *p)
#endif
{
unsigned int i;
struct cli_ac_special *a1, *a2;
unsigned int i, j;
struct cli_ac_special *a1;
struct cli_alt_node *b1, *b2;
if(!p->special)
@ -530,14 +549,22 @@ static void ac_free_special(struct cli_ac_patt *p)
for(i = 0; i < p->special; i++) {
a1 = p->special_table[i];
while(a1) {
a2 = a1;
a1 = a1->next;
if(a2->str)
mpool_free(mempool, a2->str);
mpool_free(mempool, a2);
}
if (a1->type == AC_SPECIAL_ALT_CHAR) {
mpool_free(mempool, (a1->alt).byte);
} else if (a1->type == AC_SPECIAL_ALT_STR_FIXED) {
for (j = 0; j < a1->num; j++)
mpool_free(mempool, (a1->alt).f_str[j]);
mpool_free(mempool, (a1->alt).f_str);
} else if (a1->type == AC_SPECIAL_ALT_STR) {
b1 = (a1->alt).v_str;
while (b1) {
b2 = b1->next;
mpool_free(mempool, b1->str);
mpool_free(mempool, b1);
b1 = b2;
}
}
mpool_free(mempool, a1);
}
mpool_free(mempool, p->special_table);
}
@ -838,50 +865,58 @@ static int ac_findmatch_branch(const unsigned char *buffer, uint32_t offset, uin
/* special handler */
inline static int ac_findmatch_special(const unsigned char *buffer, uint32_t offset, uint32_t fileoffset, uint32_t length, const struct cli_ac_patt *pattern, uint32_t pattoffset, uint16_t specialcnt, uint32_t *end)
{
int match;
int match, cmp;
uint16_t j, b = buffer[offset];
struct cli_ac_special *special = pattern->special_table[specialcnt];
struct cli_alt_node *alt = NULL;
match = special->negative;
switch(special->type) {
case AC_SPECIAL_ALT_CHAR:
for(j = 0; j < special->num; j++) {
if(special->str[j] == b) {
match = !special->negative;
break;
} else if(special->str[j] > b)
break;
case AC_SPECIAL_ALT_CHAR: /* single-byte */
for (j = 0; j < special->num; j++) {
if ((special->alt).byte[j] == b) {
match = !special->negative;
break;
} else if ((special->alt).byte[j] > b)
break;
}
break;
case AC_SPECIAL_ALT_STR_FIXED: /* old */
/*
while(special) {
if(bp + special->len <= length) {
if(!memcmp(&buffer[bp], special->str, special->len)) {
match = (!special->negative) * special->len;
break;
}
}
special = special->next;
}
*/
case AC_SPECIAL_ALT_STR_FIXED: /* fixed length multi-byte */
if (offset + special->len > length)
break;
for (j = 0; j < special->num; j++) {
if (!memcmp(&buffer[offset], (special->alt).f_str[j], special->len)) {
match = (!special->negative) * special->len;
break;
} /* TODO - handle sorting case */
}
break;
case AC_SPECIAL_ALT_STR: /* generic */
/* branch for backtracking */
while(special) {
if(offset + special->len <= length) {
if((!special->negative && !memcmp(&buffer[offset], special->str, special->len)) || special->negative) {
match = ac_findmatch_branch(buffer, offset+special->len, fileoffset, length, pattern, pattoffset+1, specialcnt+1, end);
if (match)
return -1; /* contrary to popular belief, this is good */
}
}
special = special->next;
}
break;
alt = (special->alt).v_str;
while (alt) {
if (offset + alt->len > length) {
alt = alt->next;
continue;
}
/* note that generic alternates CANNOT be negated */
/* generic alternates are sorted alphabetically */
cmp = memcmp(&buffer[offset], alt->str, alt->len);
if (!cmp) {
match = ac_findmatch_branch(buffer, offset+alt->len, fileoffset, length, pattern, pattoffset+1, specialcnt+1, end);
if (match)
return -1; /* alerts caller that match has been resolved in child callee */
} else if (cmp < 0)
break;
alt = alt->next;
}
break;
case AC_SPECIAL_LINE_MARKER:
if(b == '\n')
@ -1781,6 +1816,16 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
return (mode & AC_SCAN_FT) ? type : CL_CLEAN;
}
/* TODO - remove debugging on production */
#define ALTN_DEBUG 0
#if ALTN_DEBUG == 1
#define cli_altnmsg(...) cli_dbgmsg(__VA_ARGS__)
#elif ALTN_DEBUG == 2
#define cli_altnmsg(...) cli_errmsg(__VA_ARGS__)
#else
#define cli_altnmsg(...)
#endif
static int qcompare(const void *a, const void *b)
{
return *(const unsigned char *)a - *(const unsigned char *)b;
@ -1808,255 +1853,351 @@ inline static int find_paren_end(char *hexstr, char **end)
return nest;
}
/* analyzes expr, returns number of subexpr, if fixed length subexpr and longest subexpr len */
inline static int ac_analyze_expr(char *hexstr, int *fixed_len, int *slen)
/* analyzes expr, returns number of subexpr, if fixed length subexpr and longest subexpr len *
* goes to either end of string or to closing parenthesis; allowed to be unbalanced *
* counts applied to start of expr (not end, i.e. numexpr starts at 1 for the first expr */
inline static int ac_analyze_expr(char *hexstr, int *fixed_len, int *sub_len)
{
/* len calc is off */
int i, level = 0, len = 0, numexpr = 1;
int flen, slen;
*fixed_len = 1;
*slen = 0;
flen = 1;
slen = 0;
for (i = 0; i < strlen(hexstr); i++) {
if (hexstr[i] == '(') {
*fixed_len = 0;
flen = 0;
level++;
} else if (hexstr[i] == ')') {
if (!level) {
if (!(*slen)) {
*slen = len;
} else if (len != *slen) {
*fixed_len = 0;
if (len > *slen)
*slen = len;
if (!slen) {
slen = len;
} else if (len != slen) {
flen = 0;
if (len > slen)
slen = len;
}
numexpr++;
break;
}
level--;
}
if (!level && hexstr[i] == '|') {
if (!(*slen)) {
*slen = len;
} else if (len != *slen) {
*fixed_len = 0;
if (len > *slen)
*slen = len;
if (!slen) {
slen = len;
} else if (len != slen) {
flen = 0;
if (len > slen)
slen = len;
}
len = 0;
numexpr++;
} else {
len++;
}
//cli_errmsg("%c, %d\n", hexstr[i], len);
//cli_altnmsg("%c, %d\n", hexstr[i], len);
}
if (len > *slen)
*slen = len;
if (len > slen)
slen = len;
if (sub_len)
*sub_len = slen;
if (fixed_len)
*fixed_len = flen;
return numexpr;
}
/* recursive special handler for alternate string specials (so many specials!) */
static int ac_addspecial_alt(const char *hexpr, int neg)
/* add new generic alternate node to special */
inline static int ac_addspecial_add_alt_node(const char *subexpr, struct cli_ac_special *special, struct cli_matcher *root)
{
char *hexprcpy;
int ret, num, fixed, slen, len;
cli_errmsg("called ac_addspecial_alt\n");
struct cli_alt_node *newnode, **prev, *ins;
char *c;
int cmp;
newnode = (struct cli_alt_node *)mpool_calloc(root->mempool, 1, sizeof(struct cli_alt_node));
if (!newnode) {
cli_errmsg("ac_addspecial_add_alt_node: Can't allocate new alternate node\n");
return CL_EMEM;
}
c = (char *)cli_mpool_hex2str(root->mempool, subexpr);
if (!c) {
free(newnode);
return CL_EMALFDB;
}
newnode->str = c;
newnode->len = strlen(subexpr)/2;
/* search for location to insert node (alphabetically through memcmp) */
prev = &((special->alt).v_str);
ins = (special->alt).v_str;
while (ins) {
if (ins->len == newnode->len) {
cmp = memcmp(newnode->str, ins->str, ins->len); /* TODO - change when uint16_t is used */
if (cmp == 0) { /* duplicate */
free(newnode);
return CL_SUCCESS;
} else if (cmp < 0) {
break;
}
}
if (!(hexprcpy = cli_strdup(hexpr))) {
cli_errmsg("ac_addspecial_alt: Can't duplicate alternate expression\n");
return CL_EDUP;
prev = &(ins->next);
ins = ins->next;
}
len = strlen(hexpr);
num = ac_analyze_expr(hexprcpy, &fixed, &slen);
cli_errmsg("-----------------------------------\n");
cli_errmsg("hexpr: %s\n", hexprcpy);
cli_errmsg("%d strings of %d len %s\n", num, slen, fixed ? "(fixed)" : "(max)");
cli_errmsg("-----------------------------------\n");
*prev = newnode;
newnode->next = ins;
special->num++;
return CL_SUCCESS;
}
if (fixed) {
if (slen == 2) /* single-bytes are len 2 in hex */
cli_errmsg("ac_addspecial_alt: discovered AC_SPECIAL_ALT_CHAR\n");
else
cli_errmsg("ac_addspecial_alt: discovered AC_SPECIAL_ALT_STR_FIXED\n");
/* just use the tokenizer here */
} else { /* generic alternate string */
/* ------------------(----------)--------(------)--------- */
/* ^ ^ */
/* expr npt */
/* things get complicated */
/* utilize similar string method as normal parents */
/* reconstruct the final string, the ac_analyze_expr determines that slen is longest possible length */
char *sexpr, *sexpr_new, *spt, term;
int sexpr_len = slen+1, subneg, scnt = 0;
cli_errmsg("ac_addspecial_alt: discovered AC_SPECIAL_ALT_STR\n");
if (neg) {
cli_errmsg("ac_addspecial_alt: Can't apply negation operation to generic alternate strings\n");
free(hexprcpy);
return CL_EMALFDB;
/* recursive special handler for expanding and adding generic alternates */
static int ac_special_altexpand(char *hexpr, char *subexpr, uint16_t maxlen, int lvl, int maxlvl, int rec, struct cli_ac_special *special, struct cli_matcher *root)
{
int ret, scnt = 0, numexpr;
char *ept, *sexpr, *end, term;
char *fp;
ept = sexpr = hexpr;
fp = subexpr + strlen(subexpr);
numexpr = ac_analyze_expr(hexpr, NULL, NULL);
//cli_altnmsg("hexpr: %s\n", hexpr);
//cli_altnmsg("numexpr: %d [%d,%d]\n", numexpr, lvl, maxlvl);
/* while there are expressions to resolve */
while (scnt < numexpr) {
scnt++;
while ((*ept != '(') && (*ept != '|') && (*ept != ')') && (*ept != '\0'))
ept++;
/* check for invalid negation */
term = *ept;
if ((*ept == '(') && (ept >= hexpr+1)) {
if (ept[-1] == '!') {
cli_errmsg("ac_special_altexpand: Generic alternates cannot contain negations\n");
return CL_EMALFDB;
}
}
if (!(sexpr_new = cli_calloc(sexpr_len, sizeof(char)))) {
cli_errmsg("ac_addspecial_alt: Can't allocate space for reconstructed string\n");
free(hexprcpy);
/* appended token */
*ept = 0;
if (cli_strlcat(subexpr, sexpr, maxlen) >= maxlen) {
cli_errmsg("ac_special_altexpand: Unexpected expression larger than expected\n");
return CL_EMEM;
}
*ept++ = term;
spt = sexpr = hexprcpy;
/* loop starts here */
while (scnt < num) {
//cli_errmsg("cycling\n");
while ((*spt != '(') && (*spt != '|') && (*spt != ')') && (*spt != '\0'))
spt++;
term = *spt;
subneg = 0;
if ((term == '(') && (spt >= sexpr+1)) {
if (spt[-1] == '!') {
subneg = 1;
spt[-1] = 0;
}
}
*spt++ = 0;
sexpr = ept;
//cli_altnmsg("ac_special_altexpand: %s\n", subexpr);
//cli_errmsg("sexpr_new: %s\n", sexpr_new);
//cli_errmsg("sexpr: %s\n", sexpr);
//cli_errmsg("sexpr_len: %d\n", sexpr_len);
if (term == '|') {
//cli_altnmsg("ept: %s\n", ept);
if (lvl == 0) {
cli_altnmsg("export: %s\n", subexpr);
if ((ret = ac_addspecial_add_alt_node(subexpr, special, root)) != CL_SUCCESS)
return ret;
} else {
find_paren_end(ept, &end);
if (!end) {
cli_errmsg("ac_special_altexpand: Missing closing parenthesis\n");
return CL_EMALFDB;
}
end++;
/* consume token */
if ((ret = cli_strlcat(sexpr_new, sexpr, sexpr_len)) >= sexpr_len) {
//cli_errmsg("sexpr_new: %s\n", sexpr_new);
//cli_errmsg("cli_strlcat_ret: %d\n", ret);
//cli_altnmsg("descending recursive call on %s\n", end);
if ((ret = ac_special_altexpand(end, subexpr, maxlen, lvl-1, lvl, special, root)) != CL_SUCCESS)
return ret;
//cli_altnmsg("return descending recursive call\n");
}
cli_errmsg("ac_addspecial_alt: Unexpected expression larger than expected\n");
free(sexpr_new);
free(hexprcpy);
/* TODO - clean up */
*fp = 0;
} else if (term == ')') {
//cli_altnmsg("ept: %s\n", ept);
if (lvl == 0) {
cli_errmsg("ac_special_altexpand: Unexpected closing parenthesis\n");
return CL_EPARSE;
}
if (term == '(') {
/* recursive call */
cli_errmsg("encountered '(': %s\n", sexpr_new);
sexpr = spt;
find_paren_end(spt, &spt);
*spt++ = 0;
//cli_altnmsg("descending recursive call\n");
if ((ret = ac_special_altexpand(ept, subexpr, maxlen, lvl-1, lvl, special, root)) != CL_SUCCESS)
return ret;
//cli_altnmsg("return descending recursive call\n");
break;
} else if (term == '(') {
int inner, found;
find_paren_end(ept, &end);
if (!end) {
cli_errmsg("ac_special_altexpand: Missing closing parenthesis\n");
return CL_EMALFDB;
}
end++;
if ((ret = ac_addspecial_alt(sexpr, subneg)) != CL_SUCCESS) {
cli_errmsg("returned ac_addspecial_alt %d\n", ret);
free(sexpr_new);
free(hexprcpy);
/* TODO - clean up */
return CL_EPARSE;
//cli_altnmsg("ascending recursive call\n");
if ((ret = ac_special_altexpand(ept, subexpr, maxlen, lvl+1, lvl+1, special, root)) != CL_SUCCESS)
return ret;
//cli_altnmsg("return ascending recursive call\n");
/* move ept to end of current alternate expression */
ept = end;
inner = 0;
found = 0;
while (!found && *ept != '\0') {
switch(*ept) {
case '|':
if (!inner)
found = 1;
break;
case '(':
inner++;
break;
case ')':
inner--;
break;
}
cli_strlcat(sexpr_new, "()", sexpr_len);
cli_errmsg("returned ac_addspecial_alt %d\n", ret);
} else if (term == '|') {
/* push special */
cli_errmsg("encountered '|': %s\n", sexpr_new);
memset(sexpr_new, 0, sexpr_len);
scnt++;
} else if (term == '\0') {
/* push special and break */
cli_errmsg("encountered FOE: %s\n", sexpr_new);
scnt++;
break;
} else {
cli_errmsg("ac_addspecial_alt: Unexpected end of expression: %s\n", sexpr);
/* TODO - clean up */
ept++;
}
sexpr = spt;
if (*ept == '|')
ept++;
sexpr = ept;
*fp = 0;
} else if (term == '\0') {
cli_altnmsg("export: %s\n", subexpr);
if ((ret = ac_addspecial_add_alt_node(subexpr, special, root)) != CL_SUCCESS)
return ret;
break;
}
free(sexpr_new);
if ((scnt != num) || (spt - hexprcpy - 1 != len)) {
//cli_errmsg("scnt %d num %d, parsed %d len %d\n", scnt, num, spt - hexprcpy, len);
cli_errmsg("ac_addspecial: Mismatch in parsed and expected signature\n");
free(hexprcpy);
return CL_EPARSE;
} else
cli_errmsg("subexpr cnt OK\n");
//cli_altnmsg("%d %d\n", lvl, maxlvl);
if (lvl != maxlvl)
return CL_SUCCESS;
}
if (scnt != numexpr) {
//cli_altnmsg("scnt %d numexpr %d\n", scnt, numexpr);
cli_errmsg("ac_addspecial: Mismatch in parsed and expected signature\n");
return CL_EMALFDB;
}
#if ALTN_DEBUG
else
cli_altnmsg("subexpr cnt OK\n");
#endif
free(hexprcpy);
return CL_SUCCESS;
}
#define ARBITRARY_NEST_LIMIT 100 /* 0 = NO nesting (sorry birds...) */
/* special block '(', ')' handler */
inline static int ac_addspecial(const char *hexsig)
/* alternate string specials (so many specials!) */
inline static int ac_special_altstr(const char *hexpr, struct cli_ac_special *special, struct cli_matcher *root)
{
struct cli_ac_special *newspecial;
char *start, *pt, *hexcpy;
int nest, ret;
char *hexprcpy, *h, *c;
int i, ret, num, fixed, slen, len;
//cli_errmsg("called ac_special_altstr\n");
if (!(hexcpy = cli_strdup(hexsig))) {
cli_errmsg("ac_addspecial: Can't duplicate hexsig\n");
if (!(hexprcpy = cli_strdup(hexpr))) {
cli_errmsg("ac_special_altstr: Can't duplicate alternate expression\n");
return CL_EDUP;
}
start = pt = hexcpy;
/* search for parenthesis sequence */
while((pt = strchr(start, '('))) {
int neg = 0;
*pt++ = 0;
len = strlen(hexpr);
num = ac_analyze_expr(hexprcpy, &fixed, &slen);
/* check for negation */
if(pt >= hexcpy + 2) {
if(pt[-2] == '!') {
neg = 1;
pt[-2] = 0;
cli_altnmsg("-----------------------------------\n");
cli_altnmsg("hexpr: %s\n", hexprcpy);
cli_altnmsg("%d strings of %d len %s\n", num, slen, fixed ? "(fixed)" : "(max)");
cli_altnmsg("-----------------------------------\n");
if (fixed) {
special->num = 0;
special->len = slen / 2;
/* single-bytes are len 2 in hex */
if (slen == 2) {
cli_altnmsg("ac_special_altstr: discovered AC_SPECIAL_ALT_CHAR\n");
special->type = AC_SPECIAL_ALT_CHAR;
(special->alt).byte = (unsigned char *) mpool_malloc(root->mempool, num);
if (!((special->alt).byte)) {
cli_errmsg("cli_ac_special_altstr: Can't allocate newspecial->str\n");
free(hexprcpy);
return CL_EMEM;
}
} else {
cli_altnmsg("ac_special_altstr: discovered AC_SPECIAL_ALT_STR_FIXED\n");
special->type = AC_SPECIAL_ALT_STR_FIXED;
(special->alt).f_str = (unsigned char **) mpool_malloc(root->mempool, num);
if (!((special->alt).f_str)) {
cli_errmsg("cli_ac_special_altstr: Can't allocate newspecial->str\n");
free(hexprcpy);
return CL_EMEM;
}
}
/* determine if nesting is occuring */
nest = find_paren_end(pt, &start);
if (!start) {
cli_errmsg("ac_addspecial: Missing closing parenthesis\n");
return CL_EMALFDB;
for (i = 0; i < num; i++) {
if (num == 1) {
c = (char *) cli_mpool_hex2str(root->mempool, hexprcpy);
} else {
if(!(h = cli_strtok(hexprcpy, i, "|"))) {
free(hexprcpy);
return CL_EMEM;
}
c = (char *) cli_mpool_hex2str(root->mempool, h);
free(h);
}
if (!c) {
free(hexprcpy);
return CL_EMALFDB;
}
if (special->type == AC_SPECIAL_ALT_CHAR) {
(special->alt).byte[i] = *c;
mpool_free(root->mempool, c);
} else {
(special->alt).f_str[i] = c;
}
special->num++;
}
*start++ = 0;
if (!strlen(pt)) {
cli_errmsg("ac_addspecial: Empty block\n");
free(hexcpy);
/* sorting byte alternates */
if (special->num > 1 && special->type == AC_SPECIAL_ALT_CHAR)
cli_qsort((special->alt).byte, special->num, sizeof(unsigned char), qcompare);
/* TODO - sorting str alternates */
} else { /* generic alternates */
char *subexpr;
cli_altnmsg("ac_special_altstr: discovered AC_SPECIAL_ALT_STR\n");
if (special->negative) {
cli_errmsg("ac_special_altstr: Can't apply negation operation to generic alternate strings\n");
free(hexprcpy);
return CL_EMALFDB;
}
cli_errmsg("nest %d\n", nest);
special->type = AC_SPECIAL_ALT_STR;
if (nest > ARBITRARY_NEST_LIMIT) {
cli_errmsg("ac_addspecial: We've gone too deep!\n");
free(hexcpy);
return CL_EMALFDB;
/* allocate reusable subexpr */
if (!(subexpr = cli_calloc(slen+1, sizeof(char)))) {
cli_errmsg("ac_special_altstr: Can't allocate subexpr container\n");
return CL_EMEM;
}
/* character class handling */
if(!strcmp(hexpr, "B")) {
cli_errmsg("encountered 'B': ()\n");
} else if(!strcmp(hexpr, "L")) {
cli_errmsg("encountered 'L': ()\n");
} else if(!strcmp(hexpr, "W")) {
cli_errmsg("encountered 'W': ()\n");
} else {
if ((ret = ac_addspecial_alt(pt, neg)) != CL_SUCCESS) {
cli_errmsg("returned ac_addspecial_alt %d\n", ret);
free(hexcpy);
return ret;
}
// static int ac_special_altexpand(char *hexpr, char *subexpr, uint16_t maxlen, int lvl, int maxlvl, struct cli_ac_special *special, struct cli_matcher *root)
ret = ac_special_altexpand(hexprcpy, subexpr, slen+1, 0, 0, special, root);
#if ALTN_DEBUG
struct cli_alt_node *node = (special->alt).v_str;
while (node) {
cli_errmsg("%d: %s\n", node->len, node->str);
node = node->next;
}
#endif
free(subexpr);
free(hexprcpy);
return ret;
}
free(hexcpy);
free(hexprcpy);
return CL_SUCCESS;
}
#define ARBITRARY_NEST_LIMIT 100 /* 0 = NO nesting (sorry birds...) */
/* FIXME: clean up the code */
int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hexsig, uint8_t sigopts, uint32_t sigid, uint16_t parts, uint16_t partno, uint16_t rtype, uint16_t type, uint32_t mindist, uint32_t maxdist, const char *offset, const uint32_t *lsigid, unsigned int options)
{
@ -2190,7 +2331,8 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex
}
if(strchr(hexsig, '(')) {
char *hexnew, *start, *h, *c;
char *hexnew, *start;
uint8_t nest;
size_t hexnewsz;
if(hex) {
@ -2200,8 +2342,6 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex
return CL_EMEM;
}
ac_addspecial(hexcpy);
hexnewsz = strlen(hexsig) + 1;
if(!(hexnew = (char *) cli_calloc(1, hexnewsz))) {
free(new);
@ -2231,7 +2371,9 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex
}
cli_strlcat(hexnew, start, hexnewsz);
if(!(start = strchr(pt, ')'))) {
nest = find_paren_end(pt, &start);
if(!start) {
cli_errmsg("cli_ac_addsig: Missing closing parenthesis\n");
mpool_free(root->mempool, newspecial);
error = CL_EMALFDB;
break;
@ -2239,10 +2381,17 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex
*start++ = 0;
if(!strlen(pt)) {
cli_errmsg("cli_ac_addsig: Empty block\n");
mpool_free(root->mempool, newspecial);
error = CL_EMALFDB;
break;
}
if (nest > ARBITRARY_NEST_LIMIT) {
cli_errmsg("ac_addspecial: We've gone too deep!\n");
free(hexcpy);
return CL_EMALFDB;
}
if(!strcmp(pt, "B")) {
if(!*start) {
new->boundary |= AC_BOUNDARY_RIGHT;
@ -2306,72 +2455,11 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex
} else if(!strcmp(pt, "W")) {
newspecial->type = AC_SPECIAL_WORD_MARKER;
} else {
newspecial->num = 1;
for(i = 0; i < strlen(pt); i++)
if(pt[i] == '|')
newspecial->num++;
if(3 * newspecial->num - 1 == (uint16_t) strlen(pt)) {
newspecial->type = AC_SPECIAL_ALT_CHAR;
newspecial->str = (unsigned char *) mpool_malloc(root->mempool, newspecial->num);
if(!newspecial->str) {
cli_errmsg("cli_ac_addsig: Can't allocate newspecial->str\n");
error = CL_EMEM;
break;
}
} else {
newspecial->type = AC_SPECIAL_ALT_STR;
}
for(i = 0; i < newspecial->num; i++) {
unsigned int clen;
if(newspecial->num == 1) {
c = (char *) cli_mpool_hex2str(root->mempool, pt);
clen = strlen(pt) / 2;
} else {
if(!(h = cli_strtok(pt, i, "|"))) {
error = CL_EMEM;
break;
}
c = (char *) cli_mpool_hex2str(root->mempool, h);
clen = strlen(h) / 2;
free(h);
}
if(!c) {
error = CL_EMALFDB;
break;
}
if(newspecial->type == AC_SPECIAL_ALT_CHAR) {
newspecial->str[i] = *c;
mpool_free(root->mempool, c);
} else {
if(i) {
specialpt = newspecial;
while(specialpt->next)
specialpt = specialpt->next;
specialpt->next = (struct cli_ac_special *) mpool_calloc(root->mempool, 1, sizeof(struct cli_ac_special));
if(!specialpt->next) {
cli_errmsg("cli_ac_addsig: Can't allocate specialpt->next\n");
error = CL_EMEM;
free(c);
break;
}
specialpt->next->str = (unsigned char *) c;
specialpt->next->len = clen;
} else {
newspecial->str = (unsigned char *) c;
newspecial->len = clen;
}
}
}
if(newspecial->num > 1 && newspecial->type == AC_SPECIAL_ALT_CHAR)
cli_qsort(newspecial->str, newspecial->num, sizeof(unsigned char), qcompare);
if(error)
if ((ret = ac_special_altstr(pt, newspecial, root)) != CL_SUCCESS) {
//cli_altnmsg("returned ac_special_altstr %d\n", ret);
error = ret;
break;
}
}
}

@ -67,9 +67,21 @@ struct cli_ac_data {
uint32_t min_partno;
};
struct cli_ac_special {
struct cli_alt_node {
//uint16_t *str;
unsigned char *str;
struct cli_ac_special *next;
uint16_t len;
struct cli_alt_node *next;
};
struct cli_ac_special {
union {
//uint16_t *byte;
//uint16_t **f_str;
unsigned char *byte;
unsigned char **f_str;
struct cli_alt_node *v_str;
} alt;
uint16_t len, num;
uint16_t type, negative;
};

Loading…
Cancel
Save