...
|
...
|
@@ -266,6 +266,7 @@ struct char_spec {
|
266
|
266
|
uint8_t start;
|
267
|
267
|
uint8_t end;
|
268
|
268
|
uint8_t step;
|
|
269
|
+ uint8_t negative;
|
269
|
270
|
};
|
270
|
271
|
|
271
|
272
|
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
|
279
|
279
|
return i;
|
280
|
280
|
}
|
281
|
281
|
|
282
|
|
-static const struct char_spec full_range = {NULL, 0,0xff,1};
|
|
282
|
+static const struct char_spec full_range = {NULL, 0,0xff,1,0};
|
283
|
283
|
|
284
|
284
|
static inline int spec_is_fullrange(const struct char_spec *spec0, const struct char_spec *spec1)
|
285
|
285
|
{
|
...
|
...
|
@@ -292,6 +293,24 @@ static inline int spec_is_fullrange(const struct char_spec *spec0, const struct
|
292
|
292
|
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
293
|
293
|
#endif
|
294
|
294
|
|
|
295
|
+#define SPEC_FOREACH(spec0, k0, spec1, k1) do {\
|
|
296
|
+ unsigned char c0 = spec_ith_char(spec0, k0);\
|
|
297
|
+ unsigned char c1 = spec_ith_char(spec1, k1);\
|
|
298
|
+ unsigned c0end, c1end, cc0,cc1;\
|
|
299
|
+ c0end = spec0->negative ? 255 : c0;\
|
|
300
|
+ c1end = spec1->negative ? 255 : c1;\
|
|
301
|
+ cc0 = spec0->negative ? 0 : c0;\
|
|
302
|
+ cc1 = spec1->negative ? 0 : c1;\
|
|
303
|
+ for (;cc0 <= c0end;cc0++) {\
|
|
304
|
+ for (;cc1 <= c1end; cc1++) {\
|
|
305
|
+ uint16_t a = cc0 | (cc1<<8);\
|
|
306
|
+ if (spec0->negative && cc0 == c0)\
|
|
307
|
+ continue;\
|
|
308
|
+ if (spec1->negative && cc1 == c1)\
|
|
309
|
+ continue;
|
|
310
|
+
|
|
311
|
+#define SPEC_END_FOR }}} while(0)
|
|
312
|
+
|
295
|
313
|
enum badness {
|
296
|
314
|
reject,
|
297
|
315
|
/* try to avoid if possible */
|
...
|
...
|
@@ -343,11 +362,10 @@ static inline void get_score(enum badness badness, unsigned i, const struct filt
|
343
|
343
|
/* at most 256 iterations here, otherwise base would be negative */
|
344
|
344
|
for(k0=spec0->start;k0 <= spec0->end;k0 += spec0->step) {
|
345
|
345
|
for(k1=spec1->start;k1 <= spec1->end;k1 += spec1->step) {
|
346
|
|
- unsigned char c0 = spec_ith_char(spec0, k0);
|
347
|
|
- unsigned char c1 = spec_ith_char(spec1, k1);
|
348
|
|
- uint16_t a = c0 | (c1<<8);
|
|
346
|
+ SPEC_FOREACH(spec0, k0, spec1, k1) {
|
349
|
347
|
num_introduced += filter_isset(m, i, a);
|
350
|
348
|
num_end_introduced += filter_end_isset(m, i, a);
|
|
349
|
+ } SPEC_END_FOR;
|
351
|
350
|
}
|
352
|
351
|
}
|
353
|
352
|
*score = base - num_introduced;
|
...
|
...
|
@@ -396,8 +414,12 @@ static inline void add_choice(struct choice *choices, unsigned *cnt, unsigned i,
|
396
|
396
|
|
397
|
397
|
static inline int32_t spec_iter(const struct char_spec *spec)
|
398
|
398
|
{
|
399
|
|
- assert(spec->step);
|
400
|
|
- return (1 + spec->end - spec->start)/spec->step;
|
|
399
|
+ unsigned count;
|
|
400
|
+ assert(spec->step);
|
|
401
|
+ count = (1 + spec->end - spec->start)/spec->step;
|
|
402
|
+ if (spec->negative) /* all chars except itself are added */
|
|
403
|
+ count *= 254;
|
|
404
|
+ return count;
|
401
|
405
|
}
|
402
|
406
|
|
403
|
407
|
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)
|
436
|
436
|
struct char_spec *spec = &chars[i];
|
437
|
437
|
const uint16_t p = i < prefix_len ? pat->prefix[i] : pat->pattern[i - prefix_len];
|
438
|
438
|
spec->alt = NULL;
|
|
439
|
+ spec->negative = 0;
|
439
|
440
|
switch (p & CLI_MATCH_WILDCARD) {
|
440
|
441
|
case CLI_MATCH_CHAR:
|
441
|
442
|
spec->start = spec->end = (uint8_t)p;
|
...
|
...
|
@@ -450,6 +473,7 @@ int filter_add_acpatt(struct filter *m, const struct cli_ac_patt *pat)
|
450
|
450
|
assert(pat->special_table);
|
451
|
451
|
/* assert(altcnt < pat->alt); */
|
452
|
452
|
assert(pat->special_table[altcnt]);
|
|
453
|
+ spec->negative = pat->special_table[altcnt]->negative;
|
453
|
454
|
switch (pat->special_table[altcnt++]->type) {
|
454
|
455
|
case 1: /* ALT_CHAR */
|
455
|
456
|
spec->start = 0;
|
...
|
...
|
@@ -459,8 +483,7 @@ int filter_add_acpatt(struct filter *m, const struct cli_ac_patt *pat)
|
459
|
459
|
break;
|
460
|
460
|
default:
|
461
|
461
|
stop = 1;
|
462
|
|
- break;
|
463
|
|
- /* TODO: should something be done here?
|
|
462
|
+ break; /* TODO: should something be done here?
|
464
|
463
|
* */
|
465
|
464
|
}
|
466
|
465
|
break;
|
...
|
...
|
@@ -508,6 +531,10 @@ int filter_add_acpatt(struct filter *m, const struct cli_ac_patt *pat)
|
508
|
508
|
for(k1=spec1->start;k1 <= spec1->end;k1 += spec1->step) {
|
509
|
509
|
unsigned char c0 = spec_ith_char(spec0, k0);
|
510
|
510
|
unsigned char c1 = spec_ith_char(spec1, k1);
|
|
511
|
+ if (spec0->negative || spec1->negative) {
|
|
512
|
+ scor = avoid_anywhere;
|
|
513
|
+ break;
|
|
514
|
+ }
|
511
|
515
|
if ((!c0 && !c1) || (c0 == 0xff && c1 == 0xff)) {
|
512
|
516
|
scor = avoid_first;
|
513
|
517
|
break;
|
...
|
...
|
@@ -630,12 +657,12 @@ int filter_add_acpatt(struct filter *m, const struct cli_ac_patt *pat)
|
630
|
630
|
|
631
|
631
|
for(k0=spec0->start;k0 <= spec0->end;k0 += spec0->step) {
|
632
|
632
|
for(k1=spec1->start;k1 <= spec1->end;k1 += spec1->step) {
|
633
|
|
- unsigned char c0 = spec_ith_char(spec0, k0);
|
634
|
|
- unsigned char c1 = spec_ith_char(spec1, k1);
|
635
|
|
- if (!c0 && !c1 && !i) {
|
|
633
|
+ SPEC_FOREACH(spec0, k0, spec1, k1) {
|
|
634
|
+ if (!cc0 && !cc1 && !i) {
|
636
|
635
|
detailed_dbg("filter (warning): subsignature begins with zero: %s\n",pat->virname);
|
637
|
636
|
}
|
638
|
|
- filter_set_atpos(m, i, c0 | (c1<<8));
|
|
637
|
+ filter_set_atpos(m, i, a);
|
|
638
|
+ } SPEC_END_FOR;
|
639
|
639
|
}
|
640
|
640
|
}
|
641
|
641
|
}
|
...
|
...
|
@@ -644,12 +671,12 @@ int filter_add_acpatt(struct filter *m, const struct cli_ac_patt *pat)
|
644
|
644
|
if (spec0 && spec1) {
|
645
|
645
|
for (k0=spec0->start;k0 <= spec0->end;k0 += spec0->step) {
|
646
|
646
|
for (k1=spec1->start;k1 <= spec1->end;k1 += spec1->step) {
|
647
|
|
- unsigned char c0 = spec_ith_char(spec0, k0);
|
648
|
|
- unsigned char c1 = spec_ith_char(spec1, k1);
|
649
|
|
- if (!c0 && !c1) {
|
650
|
|
- detailed_dbg("filter (warning): subsignature ends with zero: %s\n",pat->virname);
|
|
647
|
+ SPEC_FOREACH(spec0, k0, spec1, k1) {
|
|
648
|
+ if (!cc0 && !cc1) {
|
|
649
|
+ detailed_dbg("filter (warning): subsignature ends with zero: %s\n",pat->virname);
|
651
|
650
|
}
|
652
|
|
- filter_set_end(m, j, c0 | (c1<<8));
|
|
651
|
+ filter_set_end(m, j, a);
|
|
652
|
+ } SPEC_END_FOR;
|
653
|
653
|
}
|
654
|
654
|
}
|
655
|
655
|
}
|