~louis/ubuntu/trusty/clamav/lp799623_fix_logrotate

« back to all changes in this revision

Viewing changes to libclamav/matcher-ac.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman
  • Date: 2010-03-12 11:30:04 UTC
  • mfrom: (0.41.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100312113004-b0fop4bkycszdd0z
Tags: 0.96~rc1+dfsg-0ubuntu1
* New upstream RC - FFE (LP: #537636):
  - Add OfficialDatabaseOnly option to clamav-base.postinst.in
  - Add LocalSocketGroup option to clamav-base.postinst.in
  - Add LocalSocketMode option to clamav-base.postinst.in
  - Add CrossFilesystems option to clamav-base.postinst.in
  - Add ClamukoScannerCount option to clamav-base.postinst.in
  - Add BytecodeSecurity opiton to clamav-base.postinst.in
  - Add DetectionStatsHostID option to clamav-freshclam.postinst.in
  - Add Bytecode option to clamav-freshclam.postinst.in
  - Add MilterSocketGroup option to clamav-milter.postinst.in
  - Add MilterSocketMode option to clamav-milter.postinst.in
  - Add ReportHostname option to clamav-milter.postinst.in
  - Bump libclamav SO version to 6.1.0 in libclamav6.install
  - Drop clamdmon from clamav.examples (no longer shipped by upstream)
  - Drop libclamav.a from libclamav-dev.install (not built by upstream)
  - Update SO version for lintian override for libclamav6
  - Add new Bytecode Testing Tool, usr/bin/clambc, to clamav.install
  - Add build-depends on python and python-setuptools for new test suite
  - Update debian/copyright for the embedded copy of llvm (using the system
    llvm is not currently feasible)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 *  Copyright (C) 2007-2008 Sourcefire, Inc.
 
2
 *  Copyright (C) 2007-2009 Sourcefire, Inc.
3
3
 *
4
4
 *  Authors: Tomasz Kojm
5
5
 *
42
42
#include "str.h"
43
43
#include "readdb.h"
44
44
#include "default.h"
 
45
#include "filtering.h"
45
46
 
46
47
#include "mpool.h"
47
48
 
 
49
#define AC_SPECIAL_ALT_CHAR     1
 
50
#define AC_SPECIAL_ALT_STR      2
 
51
#define AC_SPECIAL_LINE_MARKER  3
 
52
#define AC_SPECIAL_BOUNDARY     4
 
53
 
 
54
#define AC_BOUNDARY_LEFT                1
 
55
#define AC_BOUNDARY_LEFT_NEGATIVE       2
 
56
#define AC_BOUNDARY_RIGHT               4
 
57
#define AC_BOUNDARY_RIGHT_NEGATIVE      8
 
58
#define AC_LINE_MARKER_LEFT             16
 
59
#define AC_LINE_MARKER_LEFT_NEGATIVE    32
 
60
#define AC_LINE_MARKER_RIGHT            64
 
61
#define AC_LINE_MARKER_RIGHT_NEGATIVE   128
 
62
 
 
63
static char boundary[256] = {
 
64
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 
 
65
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 
66
    3, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 1, 3, 
 
67
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 0, 
 
68
    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 
69
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 
 
70
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 
71
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 
72
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 
73
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 
74
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 
75
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 
76
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 
77
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 
78
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 
79
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 
80
};
 
81
 
48
82
int cli_ac_addpatt(struct cli_matcher *root, struct cli_ac_patt *pattern)
49
83
{
50
84
        struct cli_ac_node *pt, *next;
51
85
        struct cli_ac_patt *ph;
52
86
        void *newtable;
53
 
        struct cli_ac_alt *a1, *a2;
 
87
        struct cli_ac_special *a1, *a2;
54
88
        uint8_t i, match;
55
89
        uint16_t len = MIN(root->ac_maxdepth, pattern->length);
56
90
 
131
165
    while(ph) {
132
166
        if((ph->length == pattern->length) && (ph->prefix_length == pattern->prefix_length) && (ph->ch[0] == pattern->ch[0]) && (ph->ch[1] == pattern->ch[1])) {
133
167
            if(!memcmp(ph->pattern, pattern->pattern, ph->length * sizeof(uint16_t)) && !memcmp(ph->prefix, pattern->prefix, ph->prefix_length * sizeof(uint16_t))) {
134
 
                if(!ph->alt && !pattern->alt) {
135
 
                    match = 1;
136
 
                } else if(ph->alt == pattern->alt) {
137
 
                    match = 1;
138
 
                    for(i = 0; i < ph->alt; i++) {
139
 
                        a1 = ph->alttable[i];
140
 
                        a2 = pattern->alttable[i];
 
168
                if(!ph->special && !pattern->special) {
 
169
                    match = 1;
 
170
                } else if(ph->special == pattern->special) {
 
171
                    match = 1;
 
172
                    for(i = 0; i < ph->special; i++) {
 
173
                        a1 = ph->special_table[i];
 
174
                        a2 = pattern->special_table[i];
141
175
 
142
176
                        if(a1->num != a2->num) {
143
177
                            match = 0;
144
178
                            break;
145
179
                        }
146
 
                        if(a1->chmode != a2->chmode) {
147
 
                            match = 0;
148
 
                            break;
149
 
                        } else if(a1->chmode) {
 
180
                        if(a1->negative != a2->negative) {
 
181
                            match = 0;
 
182
                            break;
 
183
                        }
 
184
                        if(a1->type != a2->type) {
 
185
                            match = 0;
 
186
                            break;
 
187
                        } else if(a1->type == AC_SPECIAL_ALT_CHAR) {
150
188
                            if(memcmp(a1->str, a2->str, a1->num)) {
151
189
                                match = 0;
152
190
                                break;
153
191
                            }
154
 
                        } else {
 
192
                        } else if(a1->type == AC_SPECIAL_ALT_STR) {
155
193
                            while(a1 && a2) {
156
194
                                if((a1->len != a2->len) || memcmp(a1->str, a2->str, a1->len))
157
195
                                    break;
296
334
            continue;
297
335
        for(i = 0; i < 256; i++) {
298
336
            child = node->trans[i];
299
 
            if(!child) {
 
337
            if (!child || (!IS_FINAL(child) && IS_LEAF(child))) {
300
338
                struct cli_ac_node *failtarget = node->fail;
301
339
                while(IS_LEAF(failtarget) || !failtarget->trans[i])
302
340
                    failtarget = failtarget->fail;
321
359
        return CL_SUCCESS;
322
360
    }
323
361
 
 
362
    if (root->filter)
 
363
        cli_dbgmsg("Using filter for trie %d\n", root->type);
324
364
    return ac_maketrans(root);
325
365
}
326
366
 
327
 
int cli_ac_init(struct cli_matcher *root, uint8_t mindepth, uint8_t maxdepth)
 
367
int cli_ac_init(struct cli_matcher *root, uint8_t mindepth, uint8_t maxdepth, uint8_t dconf_prefiltering)
328
368
{
329
369
#ifdef USE_MPOOL
330
370
    assert(root->mempool && "mempool must be initialized");
346
386
    root->ac_mindepth = mindepth;
347
387
    root->ac_maxdepth = maxdepth;
348
388
 
 
389
    if (cli_mtargets[root->type].enable_prefiltering && dconf_prefiltering) {
 
390
        root->filter = mpool_malloc(root->mempool, sizeof(*root->filter));
 
391
        if (!root->filter) {
 
392
            cli_errmsg("cli_ac_init: Can't allocate memory for ac_root->filter\n");
 
393
            mpool_free(root->mempool, root->ac_root->trans);
 
394
            mpool_free(root->mempool, root->ac_root);
 
395
            return CL_EMEM;
 
396
        }
 
397
        filter_init(root->filter);
 
398
    }
 
399
 
349
400
    return CL_SUCCESS;
350
401
}
351
402
 
352
403
#ifdef USE_MPOOL
353
 
#define mpool_ac_free_alt(a, b) ac_free_alt(a, b)
354
 
static void ac_free_alt(mpool_t *mempool, struct cli_ac_patt *p)
 
404
#define mpool_ac_free_special(a, b) ac_free_special(a, b)
 
405
static void ac_free_special(mpool_t *mempool, struct cli_ac_patt *p)
355
406
#else
356
 
#define mpool_ac_free_alt(a, b) ac_free_alt(b)
357
 
static void ac_free_alt(struct cli_ac_patt *p)
 
407
#define mpool_ac_free_special(a, b) ac_free_special(b)
 
408
static void ac_free_special(struct cli_ac_patt *p)
358
409
#endif
359
410
{
360
 
        uint16_t i;
361
 
        struct cli_ac_alt *a1, *a2;
362
 
 
363
 
 
364
 
    if(!p->alt)
 
411
        unsigned int i;
 
412
        struct cli_ac_special *a1, *a2;
 
413
 
 
414
 
 
415
    if(!p->special)
365
416
        return;
366
417
 
367
 
    for(i = 0; i < p->alt; i++) {
368
 
        a1 = p->alttable[i];
 
418
    for(i = 0; i < p->special; i++) {
 
419
        a1 = p->special_table[i];
369
420
        while(a1) {
370
421
            a2 = a1;
371
422
            a1 = a1->next;
374
425
            mpool_free(mempool, a2);
375
426
        }
376
427
    }
377
 
    mpool_free(mempool, p->alttable);
 
428
    mpool_free(mempool, p->special_table);
378
429
}
379
430
 
380
431
void cli_ac_free(struct cli_matcher *root)
387
438
        patt = root->ac_pattable[i];
388
439
        mpool_free(root->mempool, patt->prefix ? patt->prefix : patt->pattern);
389
440
        mpool_free(root->mempool, patt->virname);
390
 
        if(patt->offset)
391
 
            mpool_free(root->mempool, patt->offset);
392
 
        if(patt->alt)
393
 
            mpool_ac_free_alt(root->mempool, patt);
 
441
        if(patt->special)
 
442
            mpool_ac_free_special(root->mempool, patt);
394
443
        mpool_free(root->mempool, patt);
395
444
    }
396
445
    if(root->ac_pattable)
397
446
        mpool_free(root->mempool, root->ac_pattable);
398
447
 
 
448
    if(root->ac_reloff)
 
449
        mpool_free(root->mempool, root->ac_reloff);
 
450
 
399
451
    for(i = 0; i < root->ac_nodes; i++) {
400
452
        if(!IS_LEAF(root->ac_nodetable[i]))
401
453
            mpool_free(root->mempool, root->ac_nodetable[i]->trans);
408
460
        mpool_free(root->mempool, root->ac_root->trans);
409
461
        mpool_free(root->mempool, root->ac_root);
410
462
    }
 
463
    if (root->filter)
 
464
        mpool_free(root->mempool, root->filter);
411
465
}
412
466
 
413
467
/*
649
703
 *        more than one of them can match at the current position.
650
704
 */
651
705
 
652
 
#define AC_MATCH_CHAR(p,b)                                              \
653
 
    switch(wc = p & CLI_MATCH_WILDCARD) {                               \
654
 
        case CLI_MATCH_CHAR:                                            \
655
 
            if((unsigned char) p != b)                                  \
656
 
                match = 0;                                              \
657
 
            break;                                                      \
658
 
                                                                        \
659
 
        case CLI_MATCH_IGNORE:                                          \
660
 
            break;                                                      \
661
 
                                                                        \
662
 
        case CLI_MATCH_ALTERNATIVE:                                     \
663
 
            match = 0;                                                  \
664
 
            alt = pattern->alttable[altcnt];                            \
665
 
            if(alt->chmode) {                                           \
666
 
                for(j = 0; j < alt->num; j++) {                         \
667
 
                    if(alt->str[j] == b) {                              \
668
 
                        match = 1;                                      \
669
 
                        break;                                          \
670
 
                    }                                                   \
671
 
                }                                                       \
672
 
            } else {                                                    \
673
 
                while(alt) {                                            \
674
 
                    if(bp + alt->len <= length) {                       \
675
 
                        if(!memcmp(&buffer[bp], alt->str, alt->len)) {  \
676
 
                            match = 1;                                  \
677
 
                            bp += alt->len - 1;                         \
678
 
                            break;                                      \
679
 
                        }                                               \
680
 
                    }                                                   \
681
 
                    alt = alt->next;                                    \
682
 
                }                                                       \
683
 
            }                                                           \
684
 
            altcnt++;                                                   \
685
 
            break;                                                      \
686
 
                                                                        \
687
 
        case CLI_MATCH_NIBBLE_HIGH:                                     \
688
 
            if((unsigned char) (p & 0x00f0) != (b & 0xf0))              \
689
 
                match = 0;                                              \
690
 
            break;                                                      \
691
 
                                                                        \
692
 
        case CLI_MATCH_NIBBLE_LOW:                                      \
693
 
            if((unsigned char) (p & 0x000f) != (b & 0x0f))              \
694
 
                match = 0;                                              \
695
 
            break;                                                      \
696
 
                                                                        \
697
 
        default:                                                        \
698
 
            cli_errmsg("ac_findmatch: Unknown wildcard 0x%x\n", wc);    \
699
 
            match = 0;                                                  \
 
706
#define AC_MATCH_CHAR(p,b)                                                              \
 
707
    switch(wc = p & CLI_MATCH_WILDCARD) {                                               \
 
708
        case CLI_MATCH_CHAR:                                                            \
 
709
            if((unsigned char) p != b)                                                  \
 
710
                match = 0;                                                              \
 
711
            break;                                                                      \
 
712
                                                                                        \
 
713
        case CLI_MATCH_IGNORE:                                                          \
 
714
            break;                                                                      \
 
715
                                                                                        \
 
716
        case CLI_MATCH_SPECIAL:                                                         \
 
717
            special = pattern->special_table[specialcnt];                               \
 
718
            match = special->negative;                                                  \
 
719
            switch(special->type) {                                                     \
 
720
                case AC_SPECIAL_ALT_CHAR:                                               \
 
721
                    for(j = 0; j < special->num; j++) {                                 \
 
722
                        if(special->str[j] == b) {                                      \
 
723
                            match = !special->negative;                                 \
 
724
                            break;                                                      \
 
725
                        } else if(special->str[j] > b)                                  \
 
726
                            break;                                                      \
 
727
                    }                                                                   \
 
728
                    break;                                                              \
 
729
                                                                                        \
 
730
                case AC_SPECIAL_ALT_STR:                                                \
 
731
                    while(special) {                                                    \
 
732
                        if(bp + special->len <= length) {                               \
 
733
                            if(!memcmp(&buffer[bp], special->str, special->len)) {      \
 
734
                                match = !special->negative;                             \
 
735
                                bp += special->len - 1;                                 \
 
736
                                break;                                                  \
 
737
                            }                                                           \
 
738
                        }                                                               \
 
739
                        special = special->next;                                        \
 
740
                    }                                                                   \
 
741
                    break;                                                              \
 
742
                                                                                        \
 
743
                case AC_SPECIAL_LINE_MARKER:                                            \
 
744
                    if(b == '\n') {                                                     \
 
745
                        match = !special->negative;                                     \
 
746
                    } else if(b == '\r' && (bp + 1 < length && buffer[bp + 1] == '\n')) {   \
 
747
                        bp++;                                                           \
 
748
                        match = !special->negative;                                     \
 
749
                    }                                                                   \
 
750
                    break;                                                              \
 
751
                                                                                        \
 
752
                case AC_SPECIAL_BOUNDARY:                                               \
 
753
                    if(boundary[b])                                                     \
 
754
                        match = !special->negative;                                     \
 
755
                    break;                                                              \
 
756
                                                                                        \
 
757
                default:                                                                \
 
758
                    cli_errmsg("ac_findmatch: Unknown special\n");                      \
 
759
                    match = 0;                                                          \
 
760
            }                                                                           \
 
761
            specialcnt++;                                                               \
 
762
            break;                                                                      \
 
763
                                                                                        \
 
764
        case CLI_MATCH_NIBBLE_HIGH:                                                     \
 
765
            if((unsigned char) (p & 0x00f0) != (b & 0xf0))                              \
 
766
                match = 0;                                                              \
 
767
            break;                                                                      \
 
768
                                                                                        \
 
769
        case CLI_MATCH_NIBBLE_LOW:                                                      \
 
770
            if((unsigned char) (p & 0x000f) != (b & 0x0f))                              \
 
771
                match = 0;                                                              \
 
772
            break;                                                                      \
 
773
                                                                                        \
 
774
        default:                                                                        \
 
775
            cli_errmsg("ac_findmatch: Unknown wildcard 0x%x\n", wc);                    \
 
776
            match = 0;                                                                  \
700
777
    }
701
778
 
702
 
inline static int ac_findmatch(const unsigned char *buffer, uint32_t offset, uint32_t length, const struct cli_ac_patt *pattern, uint32_t *end)
 
779
inline static int ac_findmatch(const unsigned char *buffer, uint32_t offset, uint32_t fileoffset, uint32_t length, const struct cli_ac_patt *pattern, uint32_t *end)
703
780
{
704
781
        uint32_t bp, match;
705
 
        uint16_t wc, i, j, altcnt = pattern->alt_pattern;
706
 
        struct cli_ac_alt *alt;
 
782
        uint16_t wc, i, j, specialcnt = pattern->special_pattern;
 
783
        struct cli_ac_special *special;
707
784
 
708
785
 
709
786
    if((offset + pattern->length > length) || (pattern->prefix_length > offset))
720
797
    }
721
798
    *end = bp;
722
799
 
 
800
    if(pattern->boundary & AC_BOUNDARY_LEFT) {
 
801
        match = !!(pattern->boundary & AC_BOUNDARY_LEFT_NEGATIVE);
 
802
        if(!fileoffset || (offset && (boundary[buffer[offset - 1]] == 1 || boundary[buffer[offset - 1]] == 3)))
 
803
            match = !match;
 
804
        if(!match)
 
805
            return 0;
 
806
    }
 
807
 
 
808
    if(pattern->boundary & AC_BOUNDARY_RIGHT) {
 
809
        match = !!(pattern->boundary & AC_BOUNDARY_RIGHT_NEGATIVE);
 
810
        if((length <= SCANBUFF) && (bp == length || boundary[buffer[bp]] >= 2))
 
811
            match = !match;
 
812
        if(!match)
 
813
            return 0;
 
814
    }
 
815
 
 
816
    if(pattern->boundary & AC_LINE_MARKER_LEFT) {
 
817
        match = !!(pattern->boundary & AC_LINE_MARKER_LEFT_NEGATIVE);
 
818
        if(!fileoffset || (offset && (buffer[offset - 1] == '\n')))
 
819
            match = !match;
 
820
        if(!match)
 
821
            return 0;
 
822
    }
 
823
 
 
824
    if(pattern->boundary & AC_LINE_MARKER_RIGHT) {
 
825
        match = !!(pattern->boundary & AC_LINE_MARKER_RIGHT_NEGATIVE);
 
826
        if((length <= SCANBUFF) && (bp == length || buffer[bp] == '\n' || (buffer[bp] == '\r' && bp + 1 < length && buffer[bp + 1] == '\n')))
 
827
            match = !match;
 
828
        if(!match)
 
829
            return 0;
 
830
    }
 
831
 
723
832
    if(!(pattern->ch[1] & CLI_MATCH_IGNORE)) {
724
833
        bp += pattern->ch_mindist[1];
725
834
        for(i = pattern->ch_mindist[1]; i <= pattern->ch_maxdist[1]; i++) {
736
845
    }
737
846
 
738
847
    if(pattern->prefix) {
739
 
        altcnt = 0;
 
848
        specialcnt = 0;
740
849
        bp = offset - pattern->prefix_length;
741
850
        match = 1;
742
851
        for(i = 0; i < pattern->prefix_length; i++) {
769
878
    return 1;
770
879
}
771
880
 
772
 
int cli_ac_initdata(struct cli_ac_data *data, uint32_t partsigs, uint32_t lsigs, uint8_t tracklen)
 
881
int cli_ac_initdata(struct cli_ac_data *data, uint32_t partsigs, uint32_t lsigs, uint32_t reloffsigs, uint8_t tracklen)
773
882
{
774
 
        unsigned int i;
 
883
        unsigned int i, j;
775
884
 
776
885
 
777
886
    if(!data) {
779
888
        return CL_ENULLARG;
780
889
    }
781
890
 
 
891
    cli_hashset_init_noalloc(&data->vinfo);
 
892
 
 
893
    data->reloffsigs = reloffsigs;
 
894
    if(reloffsigs) {
 
895
        data->offset = (uint32_t *) cli_malloc(reloffsigs * 2 * sizeof(uint32_t));
 
896
        if(!data->offset) {
 
897
            cli_errmsg("cli_ac_init: Can't allocate memory for data->offset\n");
 
898
            return CL_EMEM;
 
899
        }
 
900
        for(i = 0; i < reloffsigs * 2; i += 2)
 
901
            data->offset[i] = CLI_OFF_NONE;
 
902
    }
 
903
 
782
904
    data->partsigs = partsigs;
783
 
 
784
905
    if(partsigs) {
785
906
        data->offmatrix = (int32_t ***) cli_calloc(partsigs, sizeof(int32_t **));
786
907
        if(!data->offmatrix) {
787
908
            cli_errmsg("cli_ac_init: Can't allocate memory for data->offmatrix\n");
 
909
            if(reloffsigs)
 
910
                free(data->offset);
788
911
            return CL_EMEM;
789
912
        }
790
913
    }
795
918
        if(!data->lsigcnt) {
796
919
            if(partsigs)
797
920
                free(data->offmatrix);
 
921
            if(reloffsigs)
 
922
                free(data->offset);
798
923
            cli_errmsg("cli_ac_init: Can't allocate memory for data->lsigcnt\n");
799
924
            return CL_EMEM;
800
925
        }
803
928
            free(data->lsigcnt);
804
929
            if(partsigs)
805
930
                free(data->offmatrix);
 
931
            if(reloffsigs)
 
932
                free(data->offset);
806
933
            cli_errmsg("cli_ac_init: Can't allocate memory for data->lsigcnt[0]\n");
807
934
            return CL_EMEM;
808
935
        }
809
936
        for(i = 1; i < lsigs; i++)
810
937
            data->lsigcnt[i] = data->lsigcnt[0] + 64 * i;
811
 
     }
812
 
 
 
938
 
 
939
        /* subsig offsets */
 
940
        data->lsigsuboff = (uint32_t **) cli_malloc(lsigs * sizeof(uint32_t *));
 
941
        if(!data->lsigsuboff) {
 
942
            free(data->lsigcnt[0]);
 
943
            free(data->lsigcnt);
 
944
            if(partsigs)
 
945
                free(data->offmatrix);
 
946
            if(reloffsigs)
 
947
                free(data->offset);
 
948
            cli_errmsg("cli_ac_init: Can't allocate memory for data->lsigsuboff\n");
 
949
            return CL_EMEM;
 
950
        }
 
951
        data->lsigsuboff[0] = (uint32_t *) cli_calloc(lsigs * 64, sizeof(uint32_t));
 
952
        if(!data->lsigsuboff[0]) {
 
953
            free(data->lsigsuboff);
 
954
            free(data->lsigcnt[0]);
 
955
            free(data->lsigcnt);
 
956
            if(partsigs)
 
957
                free(data->offmatrix);
 
958
            if(reloffsigs)
 
959
                free(data->offset);
 
960
            cli_errmsg("cli_ac_init: Can't allocate memory for data->lsigsuboff[0]\n");
 
961
            return CL_EMEM;
 
962
        }
 
963
        for(j = 0; j < 64; j++)
 
964
            data->lsigsuboff[0][j] = CLI_OFF_NONE;
 
965
        for(i = 1; i < lsigs; i++) {
 
966
            data->lsigsuboff[i] = data->lsigsuboff[0] + 64 * i;
 
967
            for(j = 0; j < 64; j++)
 
968
                data->lsigsuboff[i][j] = CLI_OFF_NONE;
 
969
        }
 
970
    }
 
971
    for (i=0;i<32;i++)
 
972
        data->macro_lastmatch[i] = CLI_OFF_NONE;
 
973
 
 
974
    return CL_SUCCESS;
 
975
}
 
976
 
 
977
int cli_ac_caloff(const struct cli_matcher *root, struct cli_ac_data *data, fmap_t *map)
 
978
{
 
979
        int ret;
 
980
        unsigned int i;
 
981
        struct cli_ac_patt *patt;
 
982
        struct cli_target_info info;
 
983
 
 
984
    if(map) {
 
985
        memset(&info, 0, sizeof(info));
 
986
        info.fsize = map->len;
 
987
    }
 
988
 
 
989
    info.exeinfo.vinfo = &data->vinfo;
 
990
 
 
991
    for(i = 0; i < root->ac_reloff_num; i++) {
 
992
        patt = root->ac_reloff[i];
 
993
        if(!map) {
 
994
            data->offset[patt->offset_min] = CLI_OFF_NONE;
 
995
        } else if((ret = cli_caloff(NULL, &info, map, root->type, patt->offdata, &data->offset[patt->offset_min], &data->offset[patt->offset_max]))) {
 
996
            cli_errmsg("cli_ac_caloff: Can't calculate relative offset in signature for %s\n", patt->virname);
 
997
            if(info.exeinfo.section)
 
998
                free(info.exeinfo.section);
 
999
            return ret;
 
1000
        } else if((data->offset[patt->offset_min] != CLI_OFF_NONE) && (data->offset[patt->offset_min] + patt->length > info.fsize)) {
 
1001
            data->offset[patt->offset_min] = CLI_OFF_NONE;
 
1002
        }
 
1003
    }
 
1004
    if(map && info.exeinfo.section)
 
1005
        free(info.exeinfo.section);
 
1006
 
813
1007
    return CL_SUCCESS;
814
1008
}
815
1009
 
817
1011
{
818
1012
        uint32_t i;
819
1013
 
 
1014
    cli_hashset_destroy(&data->vinfo);
820
1015
 
821
1016
    if(data && data->partsigs) {
822
1017
        for(i = 0; i < data->partsigs; i++) {
832
1027
    if(data && data->lsigs) {
833
1028
        free(data->lsigcnt[0]);
834
1029
        free(data->lsigcnt);
 
1030
        free(data->lsigsuboff[0]);
 
1031
        free(data->lsigsuboff);
835
1032
        data->lsigs = 0;
836
1033
    }
 
1034
 
 
1035
    if(data && data->reloffsigs) {
 
1036
        free(data->offset);
 
1037
        data->reloffsigs = 0;
 
1038
    }
837
1039
}
838
1040
 
839
1041
inline static int ac_addtype(struct cli_matched_type **list, cli_file_t type, off_t offset, const cli_ctx *ctx)
868
1070
    return CL_SUCCESS;
869
1071
}
870
1072
 
871
 
int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, void **customdata, struct cli_ac_result **res, const struct cli_matcher *root, struct cli_ac_data *mdata, uint32_t offset, cli_file_t ftype, int fd, struct cli_matched_type **ftoffset, unsigned int mode, const cli_ctx *ctx)
 
1073
static inline void lsig_sub_matched(const struct cli_matcher *root, struct cli_ac_data *mdata, uint32_t lsigid1, uint32_t lsigid2, uint32_t realoff)
 
1074
{
 
1075
    if(mdata->lsigsuboff[lsigid1][lsigid2] == CLI_OFF_NONE)
 
1076
        mdata->lsigsuboff[lsigid1][lsigid2] = realoff;
 
1077
    else if (mdata->lsigcnt[lsigid1][lsigid2] == 1) {
 
1078
        /* Check that the previous match had a macro match following it at the 
 
1079
         * correct distance. This check is only done after the 1st match.*/
 
1080
        const struct cli_lsig_tdb *tdb = &root->ac_lsigtable[lsigid1]->tdb;
 
1081
        const struct cli_ac_patt *macropt;
 
1082
        uint32_t id, last_macro_match, smin, smax, last_macroprev_match;
 
1083
        if (!tdb->macro_ptids)
 
1084
            return;
 
1085
        id = tdb->macro_ptids[lsigid2];
 
1086
        if (!id)
 
1087
            return;
 
1088
        macropt = root->ac_pattable[id];
 
1089
        smin = macropt->ch_mindist[0];
 
1090
        smax = macropt->ch_maxdist[0];
 
1091
        /* start of last macro match */
 
1092
        last_macro_match = mdata->macro_lastmatch[macropt->sigid];
 
1093
        /* start of previous lsig subsig match */
 
1094
        last_macroprev_match = mdata->lsigsuboff[lsigid1][lsigid2];
 
1095
        if (last_macro_match != CLI_OFF_NONE)
 
1096
            cli_dbgmsg("Checking macro match: %u + (%u - %u) == %u\n",
 
1097
                       last_macroprev_match, smin, smax, last_macro_match);
 
1098
        if (last_macro_match == CLI_OFF_NONE ||
 
1099
            last_macroprev_match + smin > last_macro_match ||
 
1100
            last_macroprev_match + smax < last_macro_match) {
 
1101
            cli_dbgmsg("Canceled false lsig macro match\n");
 
1102
            /* Previous match was false, cancel it and make this match the first
 
1103
             * one.*/
 
1104
            mdata->lsigcnt[lsigid1][lsigid2] = 0;
 
1105
            mdata->lsigsuboff[lsigid1][lsigid2] = realoff;
 
1106
        } else {
 
1107
            /* mark the macro sig itself matched */
 
1108
            mdata->lsigcnt[lsigid1][lsigid2+1]++;
 
1109
            mdata->lsigsuboff[lsigid1][lsigid2+1] = last_macro_match;
 
1110
        }
 
1111
    }
 
1112
    if (realoff != CLI_OFF_NONE) {
 
1113
        mdata->lsigcnt[lsigid1][lsigid2]++;
 
1114
    }
 
1115
}
 
1116
 
 
1117
void cli_ac_chkmacro(struct cli_matcher *root, struct cli_ac_data *data, unsigned lsigid1)
 
1118
{
 
1119
    const struct cli_lsig_tdb *tdb = &root->ac_lsigtable[lsigid1]->tdb;
 
1120
    unsigned i;
 
1121
    /* Loop through all subsigs, and if they are tied to macros check that the
 
1122
     * macro matched at a correct distance */
 
1123
    for (i=0;i<tdb->subsigs;i++) {
 
1124
        lsig_sub_matched(root, data, lsigid1, i, CLI_OFF_NONE);
 
1125
    }
 
1126
}
 
1127
 
 
1128
 
 
1129
int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, void **customdata, struct cli_ac_result **res, const struct cli_matcher *root, struct cli_ac_data *mdata, uint32_t offset, cli_file_t ftype, struct cli_matched_type **ftoffset, unsigned int mode, const cli_ctx *ctx)
872
1130
{
873
1131
        struct cli_ac_node *current;
874
1132
        struct cli_ac_patt *patt, *pt;
876
1134
        uint16_t j;
877
1135
        int32_t **offmatrix;
878
1136
        uint8_t found;
879
 
        struct cli_target_info info;
880
1137
        int type = CL_CLEAN;
881
1138
        struct cli_ac_result *newres;
882
1139
 
883
 
 
884
1140
    if(!root->ac_root)
885
1141
        return CL_CLEAN;
886
1142
 
887
 
    if(!mdata) {
 
1143
    if(!mdata && (root->ac_partsigs || root->ac_lsigs || root->ac_reloff_num)) {
888
1144
        cli_errmsg("cli_ac_scanbuff: mdata == NULL\n");
889
1145
        return CL_ENULLARG;
890
1146
    }
891
1147
 
892
 
    memset(&info, 0, sizeof(info));
893
1148
    current = root->ac_root;
894
1149
 
895
1150
    for(i = 0; i < length; i++)  {
896
 
 
897
 
        if(IS_LEAF(current))
898
 
            current = current->fail;
899
 
 
900
1151
        current = current->trans[buffer[i]];
901
1152
 
902
1153
        if(IS_FINAL(current)) {
903
1154
            patt = current->list;
 
1155
            if (IS_LEAF(current))
 
1156
                current = current->fail;
904
1157
            while(patt) {
905
1158
                bp = i + 1 - patt->depth;
906
 
                if(ac_findmatch(buffer, bp, length, patt, &matchend)) {
907
 
                    pt = patt;
 
1159
                if(patt->offdata[0] != CLI_OFF_VERSION && patt->offdata[0] != CLI_OFF_MACRO && !patt->next_same && (patt->offset_min != CLI_OFF_ANY) && (!patt->sigid || patt->partno == 1)) {
 
1160
                    if(patt->offset_min == CLI_OFF_NONE) {
 
1161
                        patt = patt->next;
 
1162
                        continue;
 
1163
                    }
 
1164
                    realoff = offset + bp - patt->prefix_length;
 
1165
                    if(patt->offdata[0] == CLI_OFF_ABSOLUTE) {
 
1166
                        if(patt->offset_max < realoff || patt->offset_min > realoff) {
 
1167
                            patt = patt->next;
 
1168
                            continue;
 
1169
                        }
 
1170
                    } else {
 
1171
                        if(mdata->offset[patt->offset_min] == CLI_OFF_NONE || mdata->offset[patt->offset_max] < realoff || mdata->offset[patt->offset_min] > realoff) {
 
1172
                            patt = patt->next;
 
1173
                            continue;
 
1174
                        }
 
1175
                    }
 
1176
                }
 
1177
                pt = patt;
 
1178
                if(ac_findmatch(buffer, bp, offset + bp - patt->prefix_length, length, patt, &matchend)) {
908
1179
                    while(pt) {
909
 
 
910
1180
                        if((pt->type && !(mode & AC_SCAN_FT)) || (!pt->type && !(mode & AC_SCAN_VIR))) {
911
1181
                            pt = pt->next_same;
912
1182
                            continue;
913
1183
                        }
914
 
 
915
1184
                        realoff = offset + bp - pt->prefix_length;
916
 
 
917
 
                        if(pt->offset && (!pt->sigid || pt->partno == 1)) {
918
 
                            if(!cli_validatesig(ftype, pt->offset, realoff, &info, fd, pt->virname)) {
919
 
                                pt = pt->next_same;
920
 
                                continue;
 
1185
                        if(patt->offdata[0] == CLI_OFF_VERSION) {
 
1186
                            if(!cli_hashset_contains_maybe_noalloc(&mdata->vinfo, realoff)) {
 
1187
                                pt = pt->next_same;
 
1188
                                continue;
 
1189
                            }
 
1190
                            cli_dbgmsg("cli_ac_scanbuff: VI match for offset %x\n", realoff);
 
1191
                        } else if (patt->offdata[0] == CLI_OFF_MACRO) {
 
1192
                            mdata->macro_lastmatch[patt->offdata[1]] = realoff;
 
1193
                            pt = pt->next_same;
 
1194
                            continue;
 
1195
                        } else if(pt->offset_min != CLI_OFF_ANY && (!pt->sigid || pt->partno == 1)) {
 
1196
                            if(pt->offset_min == CLI_OFF_NONE) {
 
1197
                                pt = pt->next_same;
 
1198
                                continue;
 
1199
                            }
 
1200
                            if(pt->offdata[0] == CLI_OFF_ABSOLUTE) {
 
1201
                                if(pt->offset_max < realoff || pt->offset_min > realoff) {
 
1202
                                    pt = pt->next_same;
 
1203
                                    continue;
 
1204
                                }
 
1205
                            } else {
 
1206
                                if(mdata->offset[pt->offset_min] == CLI_OFF_NONE || mdata->offset[pt->offset_max] < realoff || mdata->offset[pt->offset_min] > realoff) {
 
1207
                                    pt = pt->next_same;
 
1208
                                    continue;
 
1209
                                }
921
1210
                            }
922
1211
                        }
923
 
 
924
1212
                        if(pt->sigid) { /* it's a partial signature */
925
1213
 
926
1214
                            if(pt->partno != 1 && (!mdata->offmatrix[pt->sigid - 1] || !mdata->offmatrix[pt->sigid - 1][pt->partno - 2][0])) {
932
1220
                                mdata->offmatrix[pt->sigid - 1] = cli_malloc(pt->parts * sizeof(int32_t *));
933
1221
                                if(!mdata->offmatrix[pt->sigid - 1]) {
934
1222
                                    cli_errmsg("cli_ac_scanbuff: Can't allocate memory for mdata->offmatrix[%u]\n", pt->sigid - 1);
935
 
                                    if(info.exeinfo.section)
936
 
                                        free(info.exeinfo.section);
937
1223
                                    return CL_EMEM;
938
1224
                                }
939
1225
 
942
1228
                                    cli_errmsg("cli_ac_scanbuff: Can't allocate memory for mdata->offmatrix[%u][0]\n", pt->sigid - 1);
943
1229
                                    free(mdata->offmatrix[pt->sigid - 1]);
944
1230
                                    mdata->offmatrix[pt->sigid - 1] = NULL;
945
 
                                    if(info.exeinfo.section)
946
 
                                        free(info.exeinfo.section);
947
1231
                                    return CL_EMEM;
948
1232
                                }
949
1233
                                memset(mdata->offmatrix[pt->sigid - 1][0], -1, pt->parts * (CLI_DEFAULT_AC_TRACKLEN + 1) * sizeof(int32_t));
982
1266
                            } else if(found && pt->partno == pt->parts) {
983
1267
                                if(pt->type) {
984
1268
 
985
 
                                    if(pt->type == CL_TYPE_IGNORED && (!pt->rtype || ftype == pt->rtype)) {
986
 
                                        if(info.exeinfo.section)
987
 
                                            free(info.exeinfo.section);
988
 
 
 
1269
                                    if(pt->type == CL_TYPE_IGNORED && (!pt->rtype || ftype == pt->rtype))
989
1270
                                        return CL_TYPE_IGNORED;
990
 
                                    }
991
1271
 
992
1272
                                    if((pt->type > type || pt->type >= CL_TYPE_SFX || pt->type == CL_TYPE_MSEXE) && (!pt->rtype || ftype == pt->rtype)) {
993
1273
                                        cli_dbgmsg("Matched signature for file type %s\n", pt->virname);
994
1274
                                        type = pt->type;
995
1275
                                        if(ftoffset && (!*ftoffset || (*ftoffset)->cnt < MAX_EMBEDDED_OBJ || type == CL_TYPE_ZIPSFX) && (type >= CL_TYPE_SFX || ((ftype == CL_TYPE_MSEXE || ftype == CL_TYPE_ZIP || ftype == CL_TYPE_MSOLE2) && type == CL_TYPE_MSEXE)))  {
996
1276
                                            /* FIXME: we don't know which offset of the first part is the correct one */
997
 
                                            for(j = 1; j <= CLI_DEFAULT_AC_TRACKLEN && offmatrix[0][j] != -1; j++) {
998
 
                                                if(ac_addtype(ftoffset, type, offmatrix[pt->parts - 1][j], ctx)) {
999
 
                                                    if(info.exeinfo.section)
1000
 
                                                        free(info.exeinfo.section);
 
1277
                                            for(j = 1; j <= CLI_DEFAULT_AC_TRACKLEN && offmatrix[0][j] != -1; j++)
 
1278
                                                if(ac_addtype(ftoffset, type, offmatrix[pt->parts - 1][j], ctx))
1001
1279
                                                    return CL_EMEM;
1002
 
                                                }
1003
 
                                            }
1004
1280
                                        }
1005
1281
 
1006
1282
                                        memset(offmatrix[0], -1, pt->parts * (CLI_DEFAULT_AC_TRACKLEN + 1) * sizeof(int32_t));
1010
1286
 
1011
1287
                                } else { /* !pt->type */
1012
1288
                                    if(pt->lsigid[0]) {
1013
 
                                        mdata->lsigcnt[pt->lsigid[1]][pt->lsigid[2]]++;
 
1289
                                        lsig_sub_matched(root, mdata, pt->lsigid[1], pt->lsigid[2], realoff);
1014
1290
                                        pt = pt->next_same;
1015
1291
                                        continue;
1016
1292
                                    }
1017
1293
 
1018
1294
                                    if(res) {
1019
1295
                                        newres = (struct cli_ac_result *) malloc(sizeof(struct cli_ac_result));
1020
 
                                        if(!newres) {
1021
 
                                            if(info.exeinfo.section)
1022
 
                                                free(info.exeinfo.section);
 
1296
                                        if(!newres)
1023
1297
                                            return CL_EMEM;
1024
 
                                        }
1025
1298
                                        newres->virname = pt->virname;
1026
1299
                                        newres->customdata = pt->customdata;
1027
1300
                                        newres->next = *res;
 
1301
                                        newres->offset = realoff;
1028
1302
                                        *res = newres;
1029
1303
 
1030
1304
                                        pt = pt->next_same;
1034
1308
                                            *virname = pt->virname;
1035
1309
                                        if(customdata)
1036
1310
                                            *customdata = pt->customdata;
1037
 
 
1038
 
                                        if(info.exeinfo.section)
1039
 
                                            free(info.exeinfo.section);
1040
 
 
1041
1311
                                        return CL_VIRUS;
1042
1312
                                    }
1043
1313
                                }
1045
1315
 
1046
1316
                        } else { /* old type signature */
1047
1317
                            if(pt->type) {
1048
 
                                if(pt->type == CL_TYPE_IGNORED && (!pt->rtype || ftype == pt->rtype)) {
1049
 
                                    if(info.exeinfo.section)
1050
 
                                        free(info.exeinfo.section);
1051
 
 
 
1318
                                if(pt->type == CL_TYPE_IGNORED && (!pt->rtype || ftype == pt->rtype))
1052
1319
                                    return CL_TYPE_IGNORED;
1053
 
                                }
 
1320
 
1054
1321
                                if((pt->type > type || pt->type >= CL_TYPE_SFX || pt->type == CL_TYPE_MSEXE) && (!pt->rtype || ftype == pt->rtype)) {
1055
1322
                                    cli_dbgmsg("Matched signature for file type %s at %u\n", pt->virname, realoff);
1056
1323
                                    type = pt->type;
1057
1324
                                    if(ftoffset && (!*ftoffset || (*ftoffset)->cnt < MAX_EMBEDDED_OBJ || type == CL_TYPE_ZIPSFX) && (type >= CL_TYPE_SFX || ((ftype == CL_TYPE_MSEXE || ftype == CL_TYPE_ZIP || ftype == CL_TYPE_MSOLE2) && type == CL_TYPE_MSEXE)))  {
1058
1325
 
1059
 
                                        if(ac_addtype(ftoffset, type, realoff, ctx)) {
1060
 
                                            if(info.exeinfo.section)
1061
 
                                                free(info.exeinfo.section);
 
1326
                                        if(ac_addtype(ftoffset, type, realoff, ctx))
1062
1327
                                            return CL_EMEM;
1063
 
                                        }
1064
1328
                                    }
1065
1329
                                }
1066
1330
                            } else {
1067
1331
                                if(pt->lsigid[0]) {
1068
 
                                    mdata->lsigcnt[pt->lsigid[1]][pt->lsigid[2]]++;
 
1332
                                    lsig_sub_matched(root, mdata, pt->lsigid[1], pt->lsigid[2], realoff);
1069
1333
                                    pt = pt->next_same;
1070
1334
                                    continue;
1071
1335
                                }
1072
1336
 
1073
1337
                                if(res) {
1074
1338
                                    newres = (struct cli_ac_result *) malloc(sizeof(struct cli_ac_result));
1075
 
                                    if(!newres) {
1076
 
                                        if(info.exeinfo.section)
1077
 
                                            free(info.exeinfo.section);
 
1339
                                    if(!newres)
1078
1340
                                        return CL_EMEM;
1079
 
                                    }
1080
1341
                                    newres->virname = pt->virname;
1081
1342
                                    newres->customdata = pt->customdata;
 
1343
                                    newres->offset = realoff;
1082
1344
                                    newres->next = *res;
1083
1345
                                    *res = newres;
1084
1346
 
1089
1351
                                        *virname = pt->virname;
1090
1352
                                    if(customdata)
1091
1353
                                        *customdata = pt->customdata;
1092
 
 
1093
 
                                    if(info.exeinfo.section)
1094
 
                                        free(info.exeinfo.section);
1095
 
 
1096
1354
                                    return CL_VIRUS;
1097
1355
                                }
1098
1356
                            }
1105
1363
        }
1106
1364
    }
1107
1365
 
1108
 
    if(info.exeinfo.section)
1109
 
        free(info.exeinfo.section);
1110
 
 
1111
1366
    return (mode & AC_SCAN_FT) ? type : CL_CLEAN;
1112
1367
}
1113
1368
 
 
1369
static int qcompare(const void *a, const void *b)
 
1370
{
 
1371
    return *(const unsigned char *)a - *(const unsigned char *)b;
 
1372
}
 
1373
 
1114
1374
/* FIXME: clean up the code */
1115
1375
int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hexsig, 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)
1116
1376
{
1118
1378
        char *pt, *pt2, *hex = NULL, *hexcpy = NULL;
1119
1379
        uint16_t i, j, ppos = 0, pend, *dec, nzpos = 0;
1120
1380
        uint8_t wprefix = 0, zprefix = 1, plen = 0, nzplen = 0;
1121
 
        struct cli_ac_alt *newalt, *altpt, **newtable;
 
1381
        struct cli_ac_special *newspecial, *specialpt, **newtable;
1122
1382
        int ret, error = CL_SUCCESS;
1123
1383
 
1124
1384
 
1253
1513
                error = CL_EMALFDB;
1254
1514
                break;
1255
1515
            }
1256
 
 
 
1516
            newspecial = (struct cli_ac_special *) mpool_calloc(root->mempool, 1, sizeof(struct cli_ac_special));
 
1517
            if(!newspecial) {
 
1518
                cli_errmsg("cli_ac_addsig: Can't allocate newspecial\n");
 
1519
                error = CL_EMEM;
 
1520
                break;
 
1521
            }
 
1522
            if(pt >= hexcpy + 2) {
 
1523
                if(pt[-2] == '!') {
 
1524
                    newspecial->negative = 1;
 
1525
                    pt[-2] = 0;
 
1526
                }
 
1527
            }
1257
1528
            strcat(hexnew, start);
1258
 
            strcat(hexnew, "()");
1259
1529
 
1260
1530
            if(!(start = strchr(pt, ')'))) {
 
1531
                mpool_free(root->mempool, newspecial);
1261
1532
                error = CL_EMALFDB;
1262
1533
                break;
1263
1534
            }
1264
1535
            *start++ = 0;
1265
 
 
1266
 
            newalt = (struct cli_ac_alt *) mpool_calloc(root->mempool, 1, sizeof(struct cli_ac_alt));
1267
 
            if(!newalt) {
1268
 
                cli_errmsg("cli_ac_addsig: Can't allocate newalt\n");
1269
 
                error = CL_EMEM;
 
1536
            if(!strlen(pt)) {
 
1537
                cli_errmsg("cli_ac_addsig: Empty block\n");
 
1538
                error = CL_EMALFDB;
1270
1539
                break;
1271
1540
            }
1272
1541
 
1273
 
            new->alt++;
1274
 
 
1275
 
            newtable = (struct cli_ac_alt **) mpool_realloc(root->mempool, new->alttable, new->alt * sizeof(struct cli_ac_alt *));
 
1542
            if(!strcmp(pt, "B")) {
 
1543
                if(!*start) {
 
1544
                    new->boundary |= AC_BOUNDARY_RIGHT;
 
1545
                    if(newspecial->negative)
 
1546
                        new->boundary |= AC_BOUNDARY_RIGHT_NEGATIVE;
 
1547
                    mpool_free(root->mempool, newspecial);
 
1548
                    continue;
 
1549
                } else if(pt - 1 == hexcpy) {
 
1550
                    new->boundary |= AC_BOUNDARY_LEFT;
 
1551
                    if(newspecial->negative)
 
1552
                        new->boundary |= AC_BOUNDARY_LEFT_NEGATIVE;
 
1553
                    mpool_free(root->mempool, newspecial);
 
1554
                    continue;
 
1555
                }
 
1556
            } else if(!strcmp(pt, "L")) {
 
1557
                if(!*start) {
 
1558
                    new->boundary |= AC_LINE_MARKER_RIGHT;
 
1559
                    if(newspecial->negative)
 
1560
                        new->boundary |= AC_LINE_MARKER_RIGHT_NEGATIVE;
 
1561
                    mpool_free(root->mempool, newspecial);
 
1562
                    continue;
 
1563
                } else if(pt - 1 == hexcpy) {
 
1564
                    new->boundary |= AC_LINE_MARKER_LEFT;
 
1565
                    if(newspecial->negative)
 
1566
                        new->boundary |= AC_LINE_MARKER_LEFT_NEGATIVE;
 
1567
                    mpool_free(root->mempool, newspecial);
 
1568
                    continue;
 
1569
                }
 
1570
            }
 
1571
            strcat(hexnew, "()");
 
1572
            new->special++;
 
1573
            newtable = (struct cli_ac_special **) mpool_realloc(root->mempool, new->special_table, new->special * sizeof(struct cli_ac_special *));
1276
1574
            if(!newtable) {
1277
 
                new->alt--;
1278
 
                mpool_free(root->mempool, newalt);
1279
 
                cli_errmsg("cli_ac_addsig: Can't realloc new->alttable\n");
 
1575
                new->special--;
 
1576
                mpool_free(root->mempool, newspecial);
 
1577
                cli_errmsg("cli_ac_addsig: Can't realloc new->special_table\n");
1280
1578
                error = CL_EMEM;
1281
1579
                break;
1282
1580
            }
1283
 
            newtable[new->alt - 1] = newalt;
1284
 
            new->alttable = newtable;
1285
 
 
1286
 
            for(i = 0; i < strlen(pt); i++)
1287
 
                if(pt[i] == '|')
1288
 
                    newalt->num++;
1289
 
 
1290
 
            if(!newalt->num) {
1291
 
                error = CL_EMALFDB;
1292
 
                break;
1293
 
            } else
1294
 
                newalt->num++;
1295
 
 
1296
 
            if(3 * newalt->num - 1 == (uint16_t) strlen(pt)) {
1297
 
                newalt->chmode = 1;
1298
 
                newalt->str = (unsigned char *) mpool_malloc(root->mempool, newalt->num);
1299
 
                if(!newalt->str) {
1300
 
                    cli_errmsg("cli_ac_addsig: Can't allocate newalt->str\n");
1301
 
                    error = CL_EMEM;
1302
 
                    break;
1303
 
                }
1304
 
            }
1305
 
 
1306
 
            for(i = 0; i < newalt->num; i++) {
1307
 
                if(!(h = cli_strtok(pt, i, "|"))) {
 
1581
            newtable[new->special - 1] = newspecial;
 
1582
            new->special_table = newtable;
 
1583
 
 
1584
            if(!strcmp(pt, "B")) {
 
1585
                newspecial->type = AC_SPECIAL_BOUNDARY;
 
1586
            } else if(!strcmp(pt, "L")) {
 
1587
                newspecial->type = AC_SPECIAL_LINE_MARKER;
 
1588
            /*
 
1589
            } else if(strcmp(pt, "W")) {
 
1590
                newspecial->type = AC_SPECIAL_WHITE;
 
1591
            */
 
1592
            } else {
 
1593
                for(i = 0; i < strlen(pt); i++)
 
1594
                    if(pt[i] == '|')
 
1595
                        newspecial->num++;
 
1596
 
 
1597
                if(!newspecial->num) {
1308
1598
                    error = CL_EMALFDB;
1309
1599
                    break;
 
1600
                } else
 
1601
                    newspecial->num++;
 
1602
 
 
1603
                if(3 * newspecial->num - 1 == (uint16_t) strlen(pt)) {
 
1604
                    newspecial->type = AC_SPECIAL_ALT_CHAR;
 
1605
                    newspecial->str = (unsigned char *) mpool_malloc(root->mempool, newspecial->num);
 
1606
                    if(!newspecial->str) {
 
1607
                        cli_errmsg("cli_ac_addsig: Can't allocate newspecial->str\n");
 
1608
                        error = CL_EMEM;
 
1609
                        break;
 
1610
                    }
 
1611
                } else {
 
1612
                    newspecial->type = AC_SPECIAL_ALT_STR;
1310
1613
                }
1311
1614
 
1312
 
                if(!(c = cli_mpool_hex2str(root->mempool, h))) {
 
1615
                for(i = 0; i < newspecial->num; i++) {
 
1616
                    if(!(h = cli_strtok(pt, i, "|"))) {
 
1617
                        error = CL_EMALFDB;
 
1618
                        break;
 
1619
                    }
 
1620
 
 
1621
                    if(!(c = cli_mpool_hex2str(root->mempool, h))) {
 
1622
                        free(h);
 
1623
                        error = CL_EMALFDB;
 
1624
                        break;
 
1625
                    }
 
1626
 
 
1627
                    if(newspecial->type == AC_SPECIAL_ALT_CHAR) {
 
1628
                        newspecial->str[i] = *c;
 
1629
                        mpool_free(root->mempool, c);
 
1630
                    } else {
 
1631
                        if(i) {
 
1632
                            specialpt = newspecial;
 
1633
                            while(specialpt->next)
 
1634
                                specialpt = specialpt->next;
 
1635
 
 
1636
                            specialpt->next = (struct cli_ac_special *) mpool_calloc(root->mempool, 1, sizeof(struct cli_ac_special));
 
1637
                            if(!specialpt->next) {
 
1638
                                cli_errmsg("cli_ac_addsig: Can't allocate specialpt->next\n");
 
1639
                                error = CL_EMEM;
 
1640
                                free(c);
 
1641
                                free(h);
 
1642
                                break;
 
1643
                            }
 
1644
                            specialpt->next->str = (unsigned char *) c;
 
1645
                            specialpt->next->len = strlen(h) / 2;
 
1646
                        } else {
 
1647
                            newspecial->str = (unsigned char *) c;
 
1648
                            newspecial->len = strlen(h) / 2;
 
1649
                        }
 
1650
                    }
1313
1651
                    free(h);
1314
 
                    error = CL_EMALFDB;
 
1652
                }
 
1653
                if(newspecial->type == AC_SPECIAL_ALT_CHAR)
 
1654
                    cli_qsort(newspecial->str, newspecial->num, sizeof(unsigned char), qcompare);
 
1655
 
 
1656
                if(error)
1315
1657
                    break;
1316
 
                }
1317
 
 
1318
 
                if(newalt->chmode) {
1319
 
                    newalt->str[i] = *c;
1320
 
                    mpool_free(root->mempool, c);
1321
 
                } else {
1322
 
                    if(i) {
1323
 
                        altpt = newalt;
1324
 
                        while(altpt->next)
1325
 
                            altpt = altpt->next;
1326
 
 
1327
 
                        altpt->next = (struct cli_ac_alt *) mpool_calloc(root->mempool, 1, sizeof(struct cli_ac_alt));
1328
 
                        if(!altpt->next) {
1329
 
                            cli_errmsg("cli_ac_addsig: Can't allocate altpt->next\n");
1330
 
                            error = CL_EMEM;
1331
 
                            free(c);
1332
 
                            free(h);
1333
 
                            break;
1334
 
                        }
1335
 
 
1336
 
                        altpt->next->str = (unsigned char *) c;
1337
 
                        altpt->next->len = strlen(h) / 2;
1338
 
                    } else {
1339
 
                        newalt->str = (unsigned char *) c;
1340
 
                        newalt->len = strlen(h) / 2;
1341
 
                    }
1342
 
                }
1343
 
 
1344
 
                free(h);
1345
1658
            }
1346
 
 
1347
 
            if(error)
1348
 
                break;
1349
1659
        }
1350
1660
 
1351
1661
        if(start)
1355
1665
        free(hexcpy);
1356
1666
 
1357
1667
        if(error) {
1358
 
            if(new->alt) {
 
1668
            if(new->special) {
1359
1669
                free(hex);
1360
 
                mpool_ac_free_alt(root->mempool, new);
 
1670
                mpool_ac_free_special(root->mempool, new);
1361
1671
            }
1362
1672
            mpool_free(root->mempool, new);
1363
1673
            return error;
1366
1676
 
1367
1677
    new->pattern = cli_mpool_hex2ui(root->mempool, hex ? hex : hexsig);
1368
1678
    if(new->pattern == NULL) {
1369
 
        if(new->alt)
1370
 
            mpool_ac_free_alt(root->mempool, new);
 
1679
        if(new->special)
 
1680
            mpool_ac_free_special(root->mempool, new);
1371
1681
        mpool_free(root->mempool, new);
1372
1682
        free(hex);
1373
1683
        return CL_EMALFDB;
1376
1686
    new->length = strlen(hex ? hex : hexsig) / 2;
1377
1687
    free(hex);
1378
1688
 
 
1689
    if (root->filter) {
 
1690
        /* so that we can show meaningful messages */
 
1691
        new->virname = (char*)virname;
 
1692
        if (filter_add_acpatt(root->filter, new) == -1) {
 
1693
            cli_warnmsg("cli_ac_addpatt: cannot use filter for trie\n");
 
1694
            mpool_free(root->mempool, root->filter);
 
1695
            root->filter = NULL;
 
1696
        }
 
1697
        /* TODO: should this affect maxpatlen? */
 
1698
    }
 
1699
 
1379
1700
    for(i = 0; i < root->ac_maxdepth && i < new->length; i++) {
1380
1701
        if(new->pattern[i] & CLI_MATCH_WILDCARD) {
1381
1702
            wprefix = 1;
1416
1737
 
1417
1738
        if(plen < root->ac_mindepth) {
1418
1739
            cli_errmsg("cli_ac_addsig: Can't find a static subpattern of length %u\n", root->ac_mindepth);
1419
 
            mpool_ac_free_alt(root->mempool, new);
 
1740
            mpool_ac_free_special(root->mempool, new);
1420
1741
            mpool_free(root->mempool, new->pattern);
1421
1742
            mpool_free(root->mempool, new);
1422
1743
            return CL_EMALFDB;
1428
1749
        new->length -= ppos;
1429
1750
 
1430
1751
        for(i = 0; i < new->prefix_length; i++)
1431
 
            if((new->prefix[i] & CLI_MATCH_WILDCARD) == CLI_MATCH_ALTERNATIVE)
1432
 
                new->alt_pattern++;
 
1752
            if((new->prefix[i] & CLI_MATCH_WILDCARD) == CLI_MATCH_SPECIAL)
 
1753
                new->special_pattern++;
1433
1754
    }
1434
1755
 
1435
 
    if(new->length > root->maxpatlen)
1436
 
        root->maxpatlen = new->length;
 
1756
    if(new->length + new->prefix_length > root->maxpatlen)
 
1757
        root->maxpatlen = new->length + new->prefix_length;
1437
1758
 
1438
 
    new->virname = cli_mpool_virname(root->mempool, (char *) virname, options & CL_DB_OFFICIAL);
 
1759
    new->virname = cli_mpool_virname(root->mempool, virname, options & CL_DB_OFFICIAL);
1439
1760
    if(!new->virname) {
1440
1761
        mpool_free(root->mempool, new->prefix ? new->prefix : new->pattern);
1441
 
        mpool_ac_free_alt(root->mempool, new);
 
1762
        mpool_ac_free_special(root->mempool, new);
1442
1763
        mpool_free(root->mempool, new);
1443
1764
        return CL_EMEM;
1444
1765
    }
1446
1767
    if(new->lsigid[0])
1447
1768
        root->ac_lsigtable[new->lsigid[1]]->virname = new->virname;
1448
1769
 
1449
 
    if(offset) {
1450
 
        new->offset = cli_mpool_strdup(root->mempool, offset);
1451
 
        if(!new->offset) {
1452
 
            mpool_free(root->mempool, new->prefix ? new->prefix : new->pattern);
1453
 
            mpool_ac_free_alt(root->mempool, new);
1454
 
            mpool_free(root->mempool, new->virname);
1455
 
            mpool_free(root->mempool, new);
1456
 
            return CL_EMEM;
1457
 
        }
 
1770
    ret = cli_caloff(offset, NULL, NULL, root->type, new->offdata, &new->offset_min, &new->offset_max);
 
1771
    if(ret != CL_SUCCESS) {
 
1772
        mpool_free(root->mempool, new->prefix ? new->prefix : new->pattern);
 
1773
        mpool_ac_free_special(root->mempool, new);
 
1774
        mpool_free(root->mempool, new->virname);
 
1775
        mpool_free(root->mempool, new);
 
1776
        return ret;
1458
1777
    }
1459
1778
 
1460
1779
    if((ret = cli_ac_addpatt(root, new))) {
1461
1780
        mpool_free(root->mempool, new->prefix ? new->prefix : new->pattern);
1462
1781
        mpool_free(root->mempool, new->virname);
1463
 
        mpool_ac_free_alt(root->mempool, new);
1464
 
        if(new->offset)
1465
 
            mpool_free(root->mempool, new->offset);
 
1782
        mpool_ac_free_special(root->mempool, new);
1466
1783
        mpool_free(root->mempool, new);
1467
1784
        return ret;
1468
1785
    }
1469
1786
 
 
1787
    if(new->offdata[0] != CLI_OFF_ANY && new->offdata[0] != CLI_OFF_ABSOLUTE && new->offdata[0] != CLI_OFF_MACRO) {
 
1788
        root->ac_reloff = (struct cli_ac_patt **) mpool_realloc2(root->mempool, root->ac_reloff, (root->ac_reloff_num + 1) * sizeof(struct cli_ac_patt *));
 
1789
        if(!root->ac_reloff) {
 
1790
            cli_errmsg("cli_ac_addsig: Can't allocate memory for root->ac_reloff\n");
 
1791
            return CL_EMEM;
 
1792
        }
 
1793
        root->ac_reloff[root->ac_reloff_num] = new;
 
1794
        new->offset_min = root->ac_reloff_num * 2;
 
1795
        new->offset_max = new->offset_min + 1;
 
1796
        root->ac_reloff_num++;
 
1797
    }
 
1798
 
1470
1799
    return CL_SUCCESS;
1471
1800
}