43
43
#include "readdb.h"
44
44
#include "default.h"
45
#include "filtering.h"
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
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
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
48
82
int cli_ac_addpatt(struct cli_matcher *root, struct cli_ac_patt *pattern)
50
84
struct cli_ac_node *pt, *next;
51
85
struct cli_ac_patt *ph;
53
struct cli_ac_alt *a1, *a2;
87
struct cli_ac_special *a1, *a2;
55
89
uint16_t len = MIN(root->ac_maxdepth, pattern->length);
346
386
root->ac_mindepth = mindepth;
347
387
root->ac_maxdepth = maxdepth;
389
if (cli_mtargets[root->type].enable_prefiltering && dconf_prefiltering) {
390
root->filter = mpool_malloc(root->mempool, sizeof(*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);
397
filter_init(root->filter);
349
400
return CL_SUCCESS;
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)
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)
361
struct cli_ac_alt *a1, *a2;
412
struct cli_ac_special *a1, *a2;
367
for(i = 0; i < p->alt; i++) {
418
for(i = 0; i < p->special; i++) {
419
a1 = p->special_table[i];
649
703
* more than one of them can match at the current position.
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) \
659
case CLI_MATCH_IGNORE: \
662
case CLI_MATCH_ALTERNATIVE: \
664
alt = pattern->alttable[altcnt]; \
666
for(j = 0; j < alt->num; j++) { \
667
if(alt->str[j] == b) { \
674
if(bp + alt->len <= length) { \
675
if(!memcmp(&buffer[bp], alt->str, alt->len)) { \
677
bp += alt->len - 1; \
687
case CLI_MATCH_NIBBLE_HIGH: \
688
if((unsigned char) (p & 0x00f0) != (b & 0xf0)) \
692
case CLI_MATCH_NIBBLE_LOW: \
693
if((unsigned char) (p & 0x000f) != (b & 0x0f)) \
698
cli_errmsg("ac_findmatch: Unknown wildcard 0x%x\n", wc); \
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) \
713
case CLI_MATCH_IGNORE: \
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; \
725
} else if(special->str[j] > b) \
730
case AC_SPECIAL_ALT_STR: \
732
if(bp + special->len <= length) { \
733
if(!memcmp(&buffer[bp], special->str, special->len)) { \
734
match = !special->negative; \
735
bp += special->len - 1; \
739
special = special->next; \
743
case AC_SPECIAL_LINE_MARKER: \
745
match = !special->negative; \
746
} else if(b == '\r' && (bp + 1 < length && buffer[bp + 1] == '\n')) { \
748
match = !special->negative; \
752
case AC_SPECIAL_BOUNDARY: \
754
match = !special->negative; \
758
cli_errmsg("ac_findmatch: Unknown special\n"); \
764
case CLI_MATCH_NIBBLE_HIGH: \
765
if((unsigned char) (p & 0x00f0) != (b & 0xf0)) \
769
case CLI_MATCH_NIBBLE_LOW: \
770
if((unsigned char) (p & 0x000f) != (b & 0x0f)) \
775
cli_errmsg("ac_findmatch: Unknown wildcard 0x%x\n", wc); \
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)
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;
709
786
if((offset + pattern->length > length) || (pattern->prefix_length > offset))
803
928
free(data->lsigcnt);
805
930
free(data->offmatrix);
806
933
cli_errmsg("cli_ac_init: Can't allocate memory for data->lsigcnt[0]\n");
809
936
for(i = 1; i < lsigs; i++)
810
937
data->lsigcnt[i] = data->lsigcnt[0] + 64 * i;
940
data->lsigsuboff = (uint32_t **) cli_malloc(lsigs * sizeof(uint32_t *));
941
if(!data->lsigsuboff) {
942
free(data->lsigcnt[0]);
945
free(data->offmatrix);
948
cli_errmsg("cli_ac_init: Can't allocate memory for data->lsigsuboff\n");
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]);
957
free(data->offmatrix);
960
cli_errmsg("cli_ac_init: Can't allocate memory for data->lsigsuboff[0]\n");
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;
972
data->macro_lastmatch[i] = CLI_OFF_NONE;
977
int cli_ac_caloff(const struct cli_matcher *root, struct cli_ac_data *data, fmap_t *map)
981
struct cli_ac_patt *patt;
982
struct cli_target_info info;
985
memset(&info, 0, sizeof(info));
986
info.fsize = map->len;
989
info.exeinfo.vinfo = &data->vinfo;
991
for(i = 0; i < root->ac_reloff_num; i++) {
992
patt = root->ac_reloff[i];
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);
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;
1004
if(map && info.exeinfo.section)
1005
free(info.exeinfo.section);
813
1007
return CL_SUCCESS;
868
1070
return CL_SUCCESS;
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)
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)
1085
id = tdb->macro_ptids[lsigid2];
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
1104
mdata->lsigcnt[lsigid1][lsigid2] = 0;
1105
mdata->lsigsuboff[lsigid1][lsigid2] = realoff;
1107
/* mark the macro sig itself matched */
1108
mdata->lsigcnt[lsigid1][lsigid2+1]++;
1109
mdata->lsigsuboff[lsigid1][lsigid2+1] = last_macro_match;
1112
if (realoff != CLI_OFF_NONE) {
1113
mdata->lsigcnt[lsigid1][lsigid2]++;
1117
void cli_ac_chkmacro(struct cli_matcher *root, struct cli_ac_data *data, unsigned lsigid1)
1119
const struct cli_lsig_tdb *tdb = &root->ac_lsigtable[lsigid1]->tdb;
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);
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)
873
1131
struct cli_ac_node *current;
874
1132
struct cli_ac_patt *patt, *pt;
877
1135
int32_t **offmatrix;
879
struct cli_target_info info;
880
1137
int type = CL_CLEAN;
881
1138
struct cli_ac_result *newres;
884
1140
if(!root->ac_root)
885
1141
return CL_CLEAN;
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;
892
memset(&info, 0, sizeof(info));
893
1148
current = root->ac_root;
895
1150
for(i = 0; i < length; i++) {
898
current = current->fail;
900
1151
current = current->trans[buffer[i]];
902
1153
if(IS_FINAL(current)) {
903
1154
patt = current->list;
1155
if (IS_LEAF(current))
1156
current = current->fail;
905
1158
bp = i + 1 - patt->depth;
906
if(ac_findmatch(buffer, bp, length, patt, &matchend)) {
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) {
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) {
1171
if(mdata->offset[patt->offset_min] == CLI_OFF_NONE || mdata->offset[patt->offset_max] < realoff || mdata->offset[patt->offset_min] > realoff) {
1178
if(ac_findmatch(buffer, bp, offset + bp - patt->prefix_length, length, patt, &matchend)) {
910
1180
if((pt->type && !(mode & AC_SCAN_FT)) || (!pt->type && !(mode & AC_SCAN_VIR))) {
911
1181
pt = pt->next_same;
915
1184
realoff = offset + bp - pt->prefix_length;
917
if(pt->offset && (!pt->sigid || pt->partno == 1)) {
918
if(!cli_validatesig(ftype, pt->offset, realoff, &info, fd, pt->virname)) {
1185
if(patt->offdata[0] == CLI_OFF_VERSION) {
1186
if(!cli_hashset_contains_maybe_noalloc(&mdata->vinfo, realoff)) {
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;
1195
} else if(pt->offset_min != CLI_OFF_ANY && (!pt->sigid || pt->partno == 1)) {
1196
if(pt->offset_min == CLI_OFF_NONE) {
1200
if(pt->offdata[0] == CLI_OFF_ABSOLUTE) {
1201
if(pt->offset_max < realoff || pt->offset_min > realoff) {
1206
if(mdata->offset[pt->offset_min] == CLI_OFF_NONE || mdata->offset[pt->offset_max] < realoff || mdata->offset[pt->offset_min] > realoff) {
924
1212
if(pt->sigid) { /* it's a partial signature */
926
1214
if(pt->partno != 1 && (!mdata->offmatrix[pt->sigid - 1] || !mdata->offmatrix[pt->sigid - 1][pt->partno - 2][0])) {
1253
1513
error = CL_EMALFDB;
1516
newspecial = (struct cli_ac_special *) mpool_calloc(root->mempool, 1, sizeof(struct cli_ac_special));
1518
cli_errmsg("cli_ac_addsig: Can't allocate newspecial\n");
1522
if(pt >= hexcpy + 2) {
1524
newspecial->negative = 1;
1257
1528
strcat(hexnew, start);
1258
strcat(hexnew, "()");
1260
1530
if(!(start = strchr(pt, ')'))) {
1531
mpool_free(root->mempool, newspecial);
1261
1532
error = CL_EMALFDB;
1266
newalt = (struct cli_ac_alt *) mpool_calloc(root->mempool, 1, sizeof(struct cli_ac_alt));
1268
cli_errmsg("cli_ac_addsig: Can't allocate newalt\n");
1537
cli_errmsg("cli_ac_addsig: Empty block\n");
1275
newtable = (struct cli_ac_alt **) mpool_realloc(root->mempool, new->alttable, new->alt * sizeof(struct cli_ac_alt *));
1542
if(!strcmp(pt, "B")) {
1544
new->boundary |= AC_BOUNDARY_RIGHT;
1545
if(newspecial->negative)
1546
new->boundary |= AC_BOUNDARY_RIGHT_NEGATIVE;
1547
mpool_free(root->mempool, newspecial);
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);
1556
} else if(!strcmp(pt, "L")) {
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);
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);
1571
strcat(hexnew, "()");
1573
newtable = (struct cli_ac_special **) mpool_realloc(root->mempool, new->special_table, new->special * sizeof(struct cli_ac_special *));
1276
1574
if(!newtable) {
1278
mpool_free(root->mempool, newalt);
1279
cli_errmsg("cli_ac_addsig: Can't realloc new->alttable\n");
1576
mpool_free(root->mempool, newspecial);
1577
cli_errmsg("cli_ac_addsig: Can't realloc new->special_table\n");
1280
1578
error = CL_EMEM;
1283
newtable[new->alt - 1] = newalt;
1284
new->alttable = newtable;
1286
for(i = 0; i < strlen(pt); i++)
1296
if(3 * newalt->num - 1 == (uint16_t) strlen(pt)) {
1298
newalt->str = (unsigned char *) mpool_malloc(root->mempool, newalt->num);
1300
cli_errmsg("cli_ac_addsig: Can't allocate newalt->str\n");
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;
1584
if(!strcmp(pt, "B")) {
1585
newspecial->type = AC_SPECIAL_BOUNDARY;
1586
} else if(!strcmp(pt, "L")) {
1587
newspecial->type = AC_SPECIAL_LINE_MARKER;
1589
} else if(strcmp(pt, "W")) {
1590
newspecial->type = AC_SPECIAL_WHITE;
1593
for(i = 0; i < strlen(pt); i++)
1597
if(!newspecial->num) {
1308
1598
error = CL_EMALFDB;
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");
1612
newspecial->type = AC_SPECIAL_ALT_STR;
1312
if(!(c = cli_mpool_hex2str(root->mempool, h))) {
1615
for(i = 0; i < newspecial->num; i++) {
1616
if(!(h = cli_strtok(pt, i, "|"))) {
1621
if(!(c = cli_mpool_hex2str(root->mempool, h))) {
1627
if(newspecial->type == AC_SPECIAL_ALT_CHAR) {
1628
newspecial->str[i] = *c;
1629
mpool_free(root->mempool, c);
1632
specialpt = newspecial;
1633
while(specialpt->next)
1634
specialpt = specialpt->next;
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");
1644
specialpt->next->str = (unsigned char *) c;
1645
specialpt->next->len = strlen(h) / 2;
1647
newspecial->str = (unsigned char *) c;
1648
newspecial->len = strlen(h) / 2;
1653
if(newspecial->type == AC_SPECIAL_ALT_CHAR)
1654
cli_qsort(newspecial->str, newspecial->num, sizeof(unsigned char), qcompare);
1318
if(newalt->chmode) {
1319
newalt->str[i] = *c;
1320
mpool_free(root->mempool, c);
1325
altpt = altpt->next;
1327
altpt->next = (struct cli_ac_alt *) mpool_calloc(root->mempool, 1, sizeof(struct cli_ac_alt));
1329
cli_errmsg("cli_ac_addsig: Can't allocate altpt->next\n");
1336
altpt->next->str = (unsigned char *) c;
1337
altpt->next->len = strlen(h) / 2;
1339
newalt->str = (unsigned char *) c;
1340
newalt->len = strlen(h) / 2;
1446
1767
if(new->lsigid[0])
1447
1768
root->ac_lsigtable[new->lsigid[1]]->virname = new->virname;
1450
new->offset = cli_mpool_strdup(root->mempool, 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);
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);
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);
1465
mpool_free(root->mempool, new->offset);
1782
mpool_ac_free_special(root->mempool, new);
1466
1783
mpool_free(root->mempool, new);
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");
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++;
1470
1799
return CL_SUCCESS;