|
|
|
@ -266,6 +266,7 @@ struct char_spec { |
|
|
|
|
uint8_t start; |
|
|
|
|
uint8_t end; |
|
|
|
|
uint8_t step; |
|
|
|
|
uint8_t negative; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static inline unsigned char spec_ith_char(const struct char_spec *spec, unsigned i) |
|
|
|
@ -279,7 +280,7 @@ static inline unsigned char spec_ith_char(const struct char_spec *spec, unsigned |
|
|
|
|
return i; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static const struct char_spec full_range = {NULL, 0,0xff,1}; |
|
|
|
|
static const struct char_spec full_range = {NULL, 0,0xff,1,0}; |
|
|
|
|
|
|
|
|
|
static inline int spec_is_fullrange(const struct char_spec *spec0, const struct char_spec *spec1) |
|
|
|
|
{ |
|
|
|
@ -292,6 +293,24 @@ static inline int spec_is_fullrange(const struct char_spec *spec0, const struct |
|
|
|
|
#define MIN(a,b) ((a) < (b) ? (a) : (b)) |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#define SPEC_FOREACH(spec0, k0, spec1, k1) do {\ |
|
|
|
|
unsigned char c0 = spec_ith_char(spec0, k0);\
|
|
|
|
|
unsigned char c1 = spec_ith_char(spec1, k1);\
|
|
|
|
|
unsigned c0end, c1end, cc0,cc1;\
|
|
|
|
|
c0end = spec0->negative ? 255 : c0;\
|
|
|
|
|
c1end = spec1->negative ? 255 : c1;\
|
|
|
|
|
cc0 = spec0->negative ? 0 : c0;\
|
|
|
|
|
cc1 = spec1->negative ? 0 : c1;\
|
|
|
|
|
for (;cc0 <= c0end;cc0++) {\
|
|
|
|
|
for (;cc1 <= c1end; cc1++) {\
|
|
|
|
|
uint16_t a = cc0 | (cc1<<8);\
|
|
|
|
|
if (spec0->negative && cc0 == c0)\
|
|
|
|
|
continue;\
|
|
|
|
|
if (spec1->negative && cc1 == c1)\
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
#define SPEC_END_FOR }}} while(0) |
|
|
|
|
|
|
|
|
|
enum badness { |
|
|
|
|
reject, |
|
|
|
|
/* try to avoid if possible */ |
|
|
|
@ -343,11 +362,10 @@ static inline void get_score(enum badness badness, unsigned i, const struct filt |
|
|
|
|
/* at most 256 iterations here, otherwise base would be negative */ |
|
|
|
|
for(k0=spec0->start;k0 <= spec0->end;k0 += spec0->step) { |
|
|
|
|
for(k1=spec1->start;k1 <= spec1->end;k1 += spec1->step) { |
|
|
|
|
unsigned char c0 = spec_ith_char(spec0, k0); |
|
|
|
|
unsigned char c1 = spec_ith_char(spec1, k1); |
|
|
|
|
uint16_t a = c0 | (c1<<8); |
|
|
|
|
SPEC_FOREACH(spec0, k0, spec1, k1) { |
|
|
|
|
num_introduced += filter_isset(m, i, a); |
|
|
|
|
num_end_introduced += filter_end_isset(m, i, a); |
|
|
|
|
} SPEC_END_FOR; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
*score = base - num_introduced; |
|
|
|
@ -396,8 +414,12 @@ static inline void add_choice(struct choice *choices, unsigned *cnt, unsigned i, |
|
|
|
|
|
|
|
|
|
static inline int32_t spec_iter(const struct char_spec *spec) |
|
|
|
|
{ |
|
|
|
|
assert(spec->step); |
|
|
|
|
return (1 + spec->end - spec->start)/spec->step; |
|
|
|
|
unsigned count; |
|
|
|
|
assert(spec->step); |
|
|
|
|
count = (1 + spec->end - spec->start)/spec->step; |
|
|
|
|
if (spec->negative) /* all chars except itself are added */ |
|
|
|
|
count *= 254; |
|
|
|
|
return count; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int filter_add_acpatt(struct filter *m, const struct cli_ac_patt *pat) |
|
|
|
@ -436,6 +458,7 @@ int filter_add_acpatt(struct filter *m, const struct cli_ac_patt *pat) |
|
|
|
|
struct char_spec *spec = &chars[i]; |
|
|
|
|
const uint16_t p = i < prefix_len ? pat->prefix[i] : pat->pattern[i - prefix_len]; |
|
|
|
|
spec->alt = NULL; |
|
|
|
|
spec->negative = 0; |
|
|
|
|
switch (p & CLI_MATCH_WILDCARD) { |
|
|
|
|
case CLI_MATCH_CHAR: |
|
|
|
|
spec->start = spec->end = (uint8_t)p; |
|
|
|
@ -450,6 +473,7 @@ int filter_add_acpatt(struct filter *m, const struct cli_ac_patt *pat) |
|
|
|
|
assert(pat->special_table); |
|
|
|
|
/* assert(altcnt < pat->alt); */ |
|
|
|
|
assert(pat->special_table[altcnt]); |
|
|
|
|
spec->negative = pat->special_table[altcnt]->negative; |
|
|
|
|
switch (pat->special_table[altcnt++]->type) { |
|
|
|
|
case 1: /* ALT_CHAR */ |
|
|
|
|
spec->start = 0; |
|
|
|
@ -459,8 +483,7 @@ int filter_add_acpatt(struct filter *m, const struct cli_ac_patt *pat) |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
stop = 1; |
|
|
|
|
break; |
|
|
|
|
/* TODO: should something be done here?
|
|
|
|
|
break; /* TODO: should something be done here?
|
|
|
|
|
* */ |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
@ -508,6 +531,10 @@ int filter_add_acpatt(struct filter *m, const struct cli_ac_patt *pat) |
|
|
|
|
for(k1=spec1->start;k1 <= spec1->end;k1 += spec1->step) { |
|
|
|
|
unsigned char c0 = spec_ith_char(spec0, k0); |
|
|
|
|
unsigned char c1 = spec_ith_char(spec1, k1); |
|
|
|
|
if (spec0->negative || spec1->negative) { |
|
|
|
|
scor = avoid_anywhere; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
if ((!c0 && !c1) || (c0 == 0xff && c1 == 0xff)) { |
|
|
|
|
scor = avoid_first; |
|
|
|
|
break; |
|
|
|
@ -630,12 +657,12 @@ int filter_add_acpatt(struct filter *m, const struct cli_ac_patt *pat) |
|
|
|
|
|
|
|
|
|
for(k0=spec0->start;k0 <= spec0->end;k0 += spec0->step) { |
|
|
|
|
for(k1=spec1->start;k1 <= spec1->end;k1 += spec1->step) { |
|
|
|
|
unsigned char c0 = spec_ith_char(spec0, k0); |
|
|
|
|
unsigned char c1 = spec_ith_char(spec1, k1); |
|
|
|
|
if (!c0 && !c1 && !i) { |
|
|
|
|
SPEC_FOREACH(spec0, k0, spec1, k1) { |
|
|
|
|
if (!cc0 && !cc1 && !i) { |
|
|
|
|
detailed_dbg("filter (warning): subsignature begins with zero: %s\n",pat->virname); |
|
|
|
|
} |
|
|
|
|
filter_set_atpos(m, i, c0 | (c1<<8)); |
|
|
|
|
filter_set_atpos(m, i, a); |
|
|
|
|
} SPEC_END_FOR; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -644,12 +671,12 @@ int filter_add_acpatt(struct filter *m, const struct cli_ac_patt *pat) |
|
|
|
|
if (spec0 && spec1) { |
|
|
|
|
for (k0=spec0->start;k0 <= spec0->end;k0 += spec0->step) { |
|
|
|
|
for (k1=spec1->start;k1 <= spec1->end;k1 += spec1->step) { |
|
|
|
|
unsigned char c0 = spec_ith_char(spec0, k0); |
|
|
|
|
unsigned char c1 = spec_ith_char(spec1, k1); |
|
|
|
|
if (!c0 && !c1) { |
|
|
|
|
detailed_dbg("filter (warning): subsignature ends with zero: %s\n",pat->virname); |
|
|
|
|
SPEC_FOREACH(spec0, k0, spec1, k1) { |
|
|
|
|
if (!cc0 && !cc1) { |
|
|
|
|
detailed_dbg("filter (warning): subsignature ends with zero: %s\n",pat->virname); |
|
|
|
|
} |
|
|
|
|
filter_set_end(m, j, c0 | (c1<<8)); |
|
|
|
|
filter_set_end(m, j, a); |
|
|
|
|
} SPEC_END_FOR; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|