Browse code

Fixed heap buffer overflow while loading signatures

There is a possible overflow read when loading PDB and WDB phishing
signatures.

This issue is not a vulnerability.

Changed const char pointers to uint8_t pointers when they are to be used
with data, as well as removing asserts and adding additional error
checking.

Thank you MichaƂ Dardas for reporting this issue.

This fix also resolves:
- https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=43845
- https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=43812
- https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=43866

This commit also fixes a minor leak of pattern matching trans nodes
that was observed when testing with the MPOOL module disabled.

ragusaa authored on 2022/05/17 10:29:25
Showing 6 changed files
... ...
@@ -641,10 +641,36 @@ static void ac_free_special(struct cli_ac_patt *p)
641 641
     MPOOL_FREE(mempool, p->special_table);
642 642
 }
643 643
 
644
+/*
645
+ * This is a test to see if we have already seen this pointer.  If we have, we
646
+ * have already freed it, so don't do it again (double-free)
647
+ */
648
+static int need_to_free_trans(struct cli_matcher *root, const size_t idx)
649
+{
650
+    size_t j;
651
+    size_t min = idx;
652
+    if (root->ac_nodes < idx) {
653
+        /*Should never happen, but check just to be safe.*/
654
+        min = root->ac_nodes;
655
+    }
656
+
657
+    for (j = 0; j < min; j++) {
658
+        if (NULL == root->ac_nodetable[j]) {
659
+            continue;
660
+        }
661
+
662
+        if (root->ac_nodetable[idx]->trans == root->ac_nodetable[j]->trans) {
663
+            return 0;
664
+        }
665
+    }
666
+
667
+    return 1;
668
+}
669
+
644 670
 void cli_ac_free(struct cli_matcher *root)
645 671
 {
646
-    uint32_t i;
647
-    struct cli_ac_patt *patt;
672
+    uint32_t i               = 0;
673
+    struct cli_ac_patt *patt = NULL;
648 674
 
649 675
     for (i = 0; i < root->ac_patterns; i++) {
650 676
         patt = root->ac_pattable[i];
... ...
@@ -655,45 +681,55 @@ void cli_ac_free(struct cli_matcher *root)
655 655
                TODO: never store the virname in the ac pattern and only store it per-signature, not per-pattern. */
656 656
             MPOOL_FREE(root->mempool, patt->virname);
657 657
         }
658
-        if (patt->special)
658
+        if (patt->special) {
659 659
             mpool_ac_free_special(root->mempool, patt);
660
+        }
660 661
         MPOOL_FREE(root->mempool, patt);
661 662
     }
662 663
 
663
-    if (root->ac_pattable)
664
+    if (root->ac_pattable) {
664 665
         MPOOL_FREE(root->mempool, root->ac_pattable);
666
+    }
665 667
 
666
-    if (root->ac_reloff)
668
+    if (root->ac_reloff) {
667 669
         MPOOL_FREE(root->mempool, root->ac_reloff);
670
+    }
668 671
 
669 672
     /* Freeing trans nodes must be done before freeing table nodes! */
670 673
     for (i = 0; i < root->ac_nodes; i++) {
671 674
         if (!IS_LEAF(root->ac_nodetable[i]) &&
672
-            root->ac_nodetable[i]->fail &&
673
-            root->ac_nodetable[i]->trans != root->ac_nodetable[i]->fail->trans) {
674
-            MPOOL_FREE(root->mempool, root->ac_nodetable[i]->trans);
675
+            root->ac_root->trans != root->ac_nodetable[i]->trans) {
676
+
677
+            if (need_to_free_trans(root, i)) {
678
+                MPOOL_FREE(root->mempool, root->ac_nodetable[i]->trans);
679
+            }
675 680
         }
676 681
     }
677 682
 
678
-    for (i = 0; i < root->ac_lists; i++)
683
+    for (i = 0; i < root->ac_lists; i++) {
679 684
         MPOOL_FREE(root->mempool, root->ac_listtable[i]);
685
+    }
680 686
 
681
-    if (root->ac_listtable)
687
+    if (root->ac_listtable) {
682 688
         MPOOL_FREE(root->mempool, root->ac_listtable);
689
+    }
683 690
 
684
-    for (i = 0; i < root->ac_nodes; i++)
691
+    for (i = 0; i < root->ac_nodes; i++) {
685 692
         MPOOL_FREE(root->mempool, root->ac_nodetable[i]);
693
+    }
686 694
 
687
-    if (root->ac_nodetable)
695
+    if (root->ac_nodetable) {
688 696
         MPOOL_FREE(root->mempool, root->ac_nodetable);
697
+    }
689 698
 
690 699
     if (root->ac_root) {
691 700
         MPOOL_FREE(root->mempool, root->ac_root->trans);
692 701
         MPOOL_FREE(root->mempool, root->ac_root);
693 702
     }
694 703
 
695
-    if (root->filter)
704
+    if (root->filter) {
696 705
         MPOOL_FREE(root->mempool, root->filter);
706
+    }
697 707
 }
698 708
 
699 709
 /*
... ...
@@ -1227,6 +1227,19 @@ uint8_t cli_set_debug_flag(uint8_t debug_flag);
1227 1227
     } while (0)
1228 1228
 #endif
1229 1229
 
1230
+#ifndef CLI_STRDUP
1231
+#define CLI_STRDUP(buf, var, ...) \
1232
+    do {                          \
1233
+        var = cli_strdup(buf);    \
1234
+        if (NULL == var) {        \
1235
+            do {                  \
1236
+                __VA_ARGS__;      \
1237
+            } while (0);          \
1238
+            goto done;            \
1239
+        }                         \
1240
+    } while (0)
1241
+#endif
1242
+
1230 1243
 #ifndef FREE
1231 1244
 #define FREE(var)          \
1232 1245
     do {                   \
... ...
@@ -1326,4 +1339,29 @@ uint8_t cli_set_debug_flag(uint8_t debug_flag);
1326 1326
     } while (0)
1327 1327
 #endif
1328 1328
 
1329
+/**
1330
+ * @brief Wrapper around realloc that limits how much may be allocated to CLI_MAX_ALLOCATION.
1331
+ *
1332
+ * IMPORTANT: This differs from realloc() in that if size==0, it will NOT free the ptr.
1333
+ *
1334
+ * NOTE: cli_realloc() will NOT free ptr if size==0. It is safe to free ptr after `done:`.
1335
+ *
1336
+ * @param ptr
1337
+ * @param size
1338
+ * @return void*
1339
+ */
1340
+#ifndef CLI_REALLOC
1341
+#define CLI_REALLOC(ptr, size, ...)          \
1342
+    do {                                     \
1343
+        void *vTmp = cli_realloc(ptr, size); \
1344
+        if (NULL == vTmp) {                  \
1345
+            do {                             \
1346
+                __VA_ARGS__;                 \
1347
+            } while (0);                     \
1348
+            goto done;                       \
1349
+        }                                    \
1350
+        ptr = vTmp;                          \
1351
+    } while (0)
1352
+#endif
1353
+
1329 1354
 #endif
... ...
@@ -39,7 +39,6 @@
39 39
 
40 40
 #include <limits.h>
41 41
 #include <sys/types.h>
42
-#include <assert.h>
43 42
 
44 43
 #include "regex/regex.h"
45 44
 
... ...
@@ -162,13 +161,35 @@ cl_error_t regex_list_match(struct regex_matcher *matcher, char *real_url, const
162 162
     struct cli_ac_data mdata;
163 163
     struct cli_ac_result *res = NULL;
164 164
 
165
-    assert(matcher);
166
-    assert(real_url);
167
-    assert(display_url);
165
+    if (NULL == matcher) {
166
+        rc = CL_ENULLARG;
167
+        cli_errmsg("regex_list_match: matcher must be initialized\n");
168
+        goto done;
169
+    }
170
+
171
+    if (NULL == real_url) {
172
+        rc = CL_ENULLARG;
173
+        cli_errmsg("regex_list_match: real_url must be initialized\n");
174
+        goto done;
175
+    }
176
+
177
+    if (NULL == display_url) {
178
+        rc = CL_ENULLARG;
179
+        cli_errmsg("regex_list_match: display_url must be initialized\n");
180
+        goto done;
181
+    }
182
+
168 183
     *info = NULL;
169
-    if (!matcher->list_inited)
170
-        return CL_SUCCESS;
171
-    assert(matcher->list_built);
184
+    if (1 != matcher->list_inited) {
185
+        rc = CL_SUCCESS;
186
+        goto done;
187
+    }
188
+    if (0 == matcher->list_built) {
189
+        cli_errmsg("regex_list_match: matcher->list_built must be initialized\n");
190
+        rc = CL_ENULLARG;
191
+        goto done;
192
+    }
193
+
172 194
     /* skip initial '.' inserted by get_host */
173 195
     if (real_url[0] == '.') real_url++;
174 196
     if (display_url[0] == '.') display_url++;
... ...
@@ -279,6 +300,7 @@ cl_error_t regex_list_match(struct regex_matcher *matcher, char *real_url, const
279 279
         cli_dbgmsg("Lookup result: not in regex list\n");
280 280
     else
281 281
         cli_dbgmsg("Lookup result: in regex list\n");
282
+done:
282 283
     return rc;
283 284
 }
284 285
 
... ...
@@ -287,11 +309,25 @@ cl_error_t regex_list_match(struct regex_matcher *matcher, char *real_url, const
287 287
 cl_error_t init_regex_list(struct regex_matcher *matcher, uint8_t dconf_prefiltering)
288 288
 {
289 289
 #ifdef USE_MPOOL
290
-    mpool_t *mp = matcher->mempool;
290
+    mpool_t *mp = NULL;
291
+#endif
292
+    cl_error_t rc = CL_SUCCESS;
293
+
294
+    if (NULL == matcher) {
295
+        cli_errmsg("init_regex_list: matcher must be initialized\n");
296
+        rc = CL_ENULLARG;
297
+        goto done;
298
+    }
299
+
300
+#ifdef USE_MPOOL
301
+    mp = matcher->mempool;
302
+    if (NULL == mp) {
303
+        cli_errmsg("init_regex_list: matcher->mempool must be initialized\n");
304
+        rc = CL_ENULLARG;
305
+        goto done;
306
+    }
291 307
 #endif
292
-    cl_error_t rc;
293 308
 
294
-    assert(matcher);
295 309
     memset(matcher, 0, sizeof(*matcher));
296 310
 
297 311
     matcher->list_inited = 1;
... ...
@@ -301,23 +337,25 @@ cl_error_t init_regex_list(struct regex_matcher *matcher, uint8_t dconf_prefilte
301 301
 #ifdef USE_MPOOL
302 302
     matcher->mempool          = mp;
303 303
     matcher->suffixes.mempool = mp;
304
-    assert(mp && "mempool must be initialized");
305 304
 #endif
305
+
306 306
     if ((rc = cli_ac_init(&matcher->suffixes, 2, 32, dconf_prefiltering))) {
307
-        return rc;
307
+        goto done;
308 308
     }
309 309
 #ifdef USE_MPOOL
310 310
     matcher->sha256_hashes.mempool  = mp;
311 311
     matcher->hostkey_prefix.mempool = mp;
312 312
 #endif
313 313
     if ((rc = cli_bm_init(&matcher->sha256_hashes))) {
314
-        return rc;
314
+        goto done;
315 315
     }
316 316
     if ((rc = cli_bm_init(&matcher->hostkey_prefix))) {
317
-        return rc;
317
+        goto done;
318 318
     }
319 319
     filter_init(&matcher->filter);
320
-    return CL_SUCCESS;
320
+
321
+done:
322
+    return rc;
321 323
 }
322 324
 
323 325
 static int functionality_level_check(char *line)
... ...
@@ -424,7 +462,10 @@ cl_error_t load_regex_matcher(struct cl_engine *engine, struct regex_matcher *ma
424 424
     int line = 0, entry = 0;
425 425
     char buffer[FILEBUFF];
426 426
 
427
-    assert(matcher);
427
+    if (NULL == matcher) {
428
+        cli_errmsg("load_regex_matcher: matcher must be initialized\n");
429
+        return CL_ENULLARG;
430
+    }
428 431
 
429 432
     if (matcher->list_inited == -1)
430 433
         return CL_EMALFDB; /* already failed to load */
... ...
@@ -510,8 +551,9 @@ cl_error_t load_regex_matcher(struct cl_engine *engine, struct regex_matcher *ma
510 510
 
511 511
         if ((buffer[0] == 'R' && !is_allow_list_lookup) || ((buffer[0] == 'X' || buffer[0] == 'Y') && is_allow_list_lookup)) {
512 512
             /* regex for hostname*/
513
-            if ((rc = regex_list_add_pattern(matcher, pattern)))
513
+            if ((rc = regex_list_add_pattern(matcher, pattern))) {
514 514
                 return rc == CL_EMEM ? CL_EMEM : CL_EMALFDB;
515
+            }
515 516
         } else if ((buffer[0] == 'H' && !is_allow_list_lookup) || (buffer[0] == 'M' && is_allow_list_lookup)) {
516 517
             /*matches displayed host*/
517 518
             if ((rc = add_static_pattern(matcher, pattern)))
... ...
@@ -564,7 +606,10 @@ cl_error_t cli_build_regex_list(struct regex_matcher *matcher)
564 564
 /* Done with this matcher, free resources */
565 565
 void regex_list_done(struct regex_matcher *matcher)
566 566
 {
567
-    assert(matcher);
567
+    if (NULL == matcher) {
568
+        cli_errmsg("regex_list_done: matcher must be initialized\n");
569
+        goto done;
570
+    }
568 571
 
569 572
     if (matcher->list_inited == 1) {
570 573
         size_t i;
... ...
@@ -594,24 +639,55 @@ void regex_list_done(struct regex_matcher *matcher)
594 594
         cli_bm_free(&matcher->sha256_hashes);
595 595
         cli_bm_free(&matcher->hostkey_prefix);
596 596
     }
597
+
598
+done:
599
+    return;
597 600
 }
598 601
 
599 602
 int is_regex_ok(struct regex_matcher *matcher)
600 603
 {
601
-    assert(matcher);
602
-    return (!matcher->list_inited || matcher->list_inited != -1); /* either we don't have a regexlist, or we initialized it successfully */
604
+    int ret = 0;
605
+    if (NULL == matcher) {
606
+        cli_errmsg("is_regex_ok: matcher must be initialized\n");
607
+    } else {
608
+        ret = (!matcher->list_inited || matcher->list_inited != -1); /* either we don't have a regexlist, or we initialized it successfully */
609
+    }
610
+
611
+    return ret;
603 612
 }
604 613
 
605
-static int add_newsuffix(struct regex_matcher *matcher, struct regex_list *info, const char *suffix, size_t len)
614
+static cl_error_t add_newsuffix(struct regex_matcher *matcher, struct regex_list *info, const char *suffix, size_t len)
606 615
 {
607
-    struct cli_matcher *root = &matcher->suffixes;
608
-    struct cli_ac_patt *new  = MPOOL_CALLOC(matcher->mempool, 1, sizeof(*new));
616
+    struct cli_matcher *root = NULL;
617
+    struct cli_ac_patt *new  = NULL;
609 618
     size_t i;
610
-    int ret;
619
+    cl_error_t ret = CL_SUCCESS;
611 620
 
612
-    if (!new)
613
-        return CL_EMEM;
614
-    assert(root && suffix);
621
+    if (NULL == matcher) {
622
+        cli_errmsg("add_newsuffix: matcher must be initialized\n");
623
+        ret = CL_ENULLARG;
624
+        goto done;
625
+    }
626
+
627
+    root = &matcher->suffixes;
628
+    if (NULL == root) {
629
+        cli_errmsg("add_newsuffix: root must be initialized\n");
630
+        ret = CL_ENULLARG;
631
+        goto done;
632
+    }
633
+
634
+    if (NULL == suffix) {
635
+        cli_errmsg("add_newsuffix: suffix must be initialized\n");
636
+        ret = CL_ENULLARG;
637
+        goto done;
638
+    }
639
+
640
+    new = MPOOL_CALLOC(matcher->mempool, 1, sizeof(*new));
641
+    if (!new) {
642
+        cli_errmsg("add_newsuffix: Unable to allocate memory for new\n");
643
+        ret = CL_EMEM;
644
+        goto done;
645
+    }
615 646
 
616 647
     new->rtype      = 0;
617 648
     new->type       = 0;
... ...
@@ -629,22 +705,38 @@ static int add_newsuffix(struct regex_matcher *matcher, struct regex_list *info,
629 629
 
630 630
     new->pattern = MPOOL_MALLOC(matcher->mempool, sizeof(new->pattern[0]) * len);
631 631
     if (!new->pattern) {
632
-        MPOOL_FREE(matcher->mempool, new);
633 632
         cli_errmsg("add_newsuffix: Unable to allocate memory for new->pattern\n");
634
-        return CL_EMEM;
633
+        ret = CL_EMEM;
634
+        goto done;
635 635
     }
636
-    for (i = 0; i < len; i++)
636
+    for (i = 0; i < len; i++) {
637 637
         new->pattern[i] = suffix[i]; /*new->pattern is short int* */
638
+    }
638 639
 
639 640
     new->customdata = info;
640 641
     new->virname    = NULL;
641 642
     if ((ret = cli_ac_addpatt(root, new))) {
642
-        MPOOL_FREE(matcher->mempool, new->pattern);
643
-        MPOOL_FREE(matcher->mempool, new);
644
-        return ret;
643
+        goto done;
645 644
     }
646
-    filter_add_static(&matcher->filter, (const unsigned char *)suffix, len, "regex");
647
-    return CL_SUCCESS;
645
+
646
+    if (filter_add_static(&matcher->filter, (const unsigned char *)suffix, len, "regex") < 0) {
647
+        cli_errmsg("add_newsuffix: Unable to add filter\n");
648
+        ret = CL_ERROR;
649
+        goto done;
650
+    }
651
+
652
+done:
653
+
654
+    if (CL_SUCCESS != ret) {
655
+        if (NULL != new) {
656
+            if (NULL != new->pattern) {
657
+                MPOOL_FREE(matcher->mempool, new->pattern);
658
+            }
659
+            MPOOL_FREE(matcher->mempool, new);
660
+        }
661
+    }
662
+
663
+    return ret;
648 664
 }
649 665
 
650 666
 #define MODULE "regex_list: "
... ...
@@ -663,45 +755,84 @@ static void list_add_tail(struct regex_list_ht *ht, struct regex_list *regex)
663 663
 static cl_error_t add_pattern_suffix(void *cbdata, const char *suffix, size_t suffix_len, const struct regex_list *iregex)
664 664
 {
665 665
     struct regex_matcher *matcher = cbdata;
666
-    struct regex_list *regex      = cli_malloc(sizeof(*regex));
667
-    const struct cli_element *el;
668
-    void *tmp_matcher; /*	save original address if OOM occurs */
666
+    struct regex_list *regex      = NULL;
667
+    const struct cli_element *el  = NULL;
668
+    void *tmp_matcher             = NULL; /*	save original address if OOM occurs */
669
+    cl_error_t ret                = CL_SUCCESS;
669 670
 
670
-    assert(matcher);
671
-    if (!regex) {
672
-        cli_errmsg("add_pattern_suffix: Unable to allocate memory for regex\n");
673
-        return CL_EMEM;
671
+    if (NULL == matcher) {
672
+        cli_errmsg("add_pattern_suffix: matcher must be initialized\n");
673
+        ret = CL_ENULLARG;
674
+        goto done;
675
+    }
676
+    if (NULL == suffix) {
677
+        cli_errmsg("add_pattern_suffix: suffix must be initialized\n");
678
+        ret = CL_ENULLARG;
679
+        goto done;
674 680
     }
675
-    regex->pattern = iregex->pattern ? cli_strdup(iregex->pattern) : NULL;
676
-    regex->preg    = iregex->preg;
677
-    regex->nxt     = NULL;
678
-    el             = cli_hashtab_find(&matcher->suffix_hash, suffix, suffix_len);
681
+    if (NULL == iregex) {
682
+        cli_errmsg("add_pattern_suffix: iregex must be initialized\n");
683
+        ret = CL_ENULLARG;
684
+        goto done;
685
+    }
686
+
687
+    CLI_MALLOC(regex, sizeof(*regex),
688
+               cli_errmsg("add_pattern_suffix: Unable to allocate memory for regex\n");
689
+               ret = CL_EMEM);
690
+
691
+    if (NULL == iregex->pattern) {
692
+        regex->pattern = NULL;
693
+    } else {
694
+        CLI_STRDUP(iregex->pattern, regex->pattern,
695
+                   cli_errmsg("add_pattern_suffix: unable to strdup iregex->pattern");
696
+                   ret = CL_EMEM);
697
+    }
698
+    regex->preg = iregex->preg;
699
+    regex->nxt  = NULL;
700
+    el          = cli_hashtab_find(&matcher->suffix_hash, suffix, suffix_len);
679 701
     /* TODO: what if suffixes are prefixes of eachother and only one will
680 702
      * match? */
681 703
     if (el) {
682 704
         /* existing suffix */
683
-        assert((size_t)el->data < matcher->suffix_cnt);
705
+        if ((size_t)el->data >= matcher->suffix_cnt) {
706
+            cli_errmsg("add_pattern_suffix: el-> data too large");
707
+            ret = CL_ERROR;
708
+            goto done;
709
+        }
684 710
         list_add_tail(&matcher->suffix_regexes[(size_t)el->data], regex);
685 711
     } else {
686 712
         /* new suffix */
687 713
         size_t n    = matcher->suffix_cnt;
688 714
         el          = cli_hashtab_insert(&matcher->suffix_hash, suffix, suffix_len, (cli_element_data)n);
689 715
         tmp_matcher = matcher->suffix_regexes; /*  save the current value before cli_realloc()	*/
690
-        tmp_matcher = cli_realloc(matcher->suffix_regexes, (n + 1) * sizeof(*matcher->suffix_regexes));
691
-        if (!tmp_matcher) {
692
-            FREE(regex->pattern);
693
-            free(regex);
694
-            return CL_EMEM;
695
-        }
696
-        matcher->suffix_regexes         = tmp_matcher; /*  success, point at new memory location   */
716
+        CLI_REALLOC(matcher->suffix_regexes,
717
+                    (n + 1) * sizeof(*matcher->suffix_regexes),
718
+                    cli_errmsg("add_pattern_suffix: Unable to reallocate memory for matcher->suffix_regexes\n");
719
+                    ret = CL_EMEM);
697 720
         matcher->suffix_regexes[n].tail = regex;
698 721
         matcher->suffix_regexes[n].head = regex;
699
-        matcher->suffix_cnt++;
700
-        if (suffix[0] == '/' && suffix[1] == '\0')
722
+        if (suffix[0] == '/' && suffix[1] == '\0') {
701 723
             matcher->root_regex_idx = n;
702
-        add_newsuffix(matcher, regex, suffix, suffix_len);
724
+        }
725
+
726
+        ret = add_newsuffix(matcher, regex, suffix, suffix_len);
727
+
728
+        if (CL_SUCCESS != ret) {
729
+            cli_hashtab_delete(&matcher->suffix_hash, suffix, suffix_len);
730
+            /*shrink the size back to what it was.*/
731
+            CLI_REALLOC(matcher->suffix_regexes, n * sizeof(*matcher->suffix_regexes));
732
+        } else {
733
+            matcher->suffix_cnt++;
734
+        }
703 735
     }
704
-    return CL_SUCCESS;
736
+
737
+done:
738
+    if (CL_SUCCESS != ret) {
739
+        FREE(regex->pattern);
740
+        FREE(regex);
741
+    }
742
+
743
+    return ret;
705 744
 }
706 745
 
707 746
 static size_t reverse_string(char *pattern)
... ...
@@ -737,14 +868,17 @@ static cl_error_t add_static_pattern(struct regex_matcher *matcher, char *patter
737 737
 {
738 738
     size_t len;
739 739
     struct regex_list regex;
740
-    cl_error_t rc;
741
-
742
-    len           = reverse_string(pattern);
743
-    regex.nxt     = NULL;
744
-    regex.pattern = cli_strdup(pattern);
745
-    regex.preg    = NULL;
746
-    rc            = add_pattern_suffix(matcher, pattern, len, &regex);
747
-    free(regex.pattern);
740
+    cl_error_t rc = CL_EMEM;
741
+
742
+    len       = reverse_string(pattern);
743
+    regex.nxt = NULL;
744
+    CLI_STRDUP(pattern, regex.pattern,
745
+               cli_errmsg("add_static_pattern: Cannot allocate memory for regex.pattern\n");
746
+               rc = CL_EMEM);
747
+    regex.preg = NULL;
748
+    rc         = add_pattern_suffix(matcher, pattern, len, &regex);
749
+done:
750
+    FREE(regex.pattern);
748 751
     return rc;
749 752
 }
750 753
 
... ...
@@ -27,7 +27,6 @@
27 27
 #include <stdio.h>
28 28
 #include <stdlib.h>
29 29
 #include <string.h>
30
-#include <assert.h>
31 30
 
32 31
 #include "clamav.h"
33 32
 #include "others.h"
... ...
@@ -180,7 +179,7 @@ static void destroy_tree(struct node *n)
180 180
     free(n);
181 181
 }
182 182
 
183
-static uint8_t *parse_char_class(const char *pat, size_t *pos)
183
+static uint8_t *parse_char_class(const uint8_t *pat, size_t *pos)
184 184
 {
185 185
     unsigned char range_start = 0;
186 186
     int hasprev               = 0;
... ...
@@ -200,7 +199,10 @@ static uint8_t *parse_char_class(const char *pat, size_t *pos)
200 200
             /* it is a range*/
201 201
             unsigned char range_end;
202 202
             unsigned int c;
203
-            assert(range_start);
203
+            if (0 == range_start) {
204
+                cli_errmsg("parse_char_class: range_start not initialized");
205
+                return NULL;
206
+            }
204 207
             ++*pos;
205 208
             if (pat[*pos] == '[')
206 209
                 if (pat[*pos + 1] == '.') {
... ...
@@ -238,7 +240,7 @@ static uint8_t *parse_char_class(const char *pat, size_t *pos)
238 238
     return bitmap;
239 239
 }
240 240
 
241
-static struct node *parse_regex(const char *p, size_t *last)
241
+static struct node *parse_regex(const uint8_t *p, size_t *last)
242 242
 {
243 243
     struct node *v = NULL;
244 244
     struct node *right;
... ...
@@ -426,14 +428,15 @@ static cl_error_t build_suffixtree_descend(struct node *n, struct text_buffer *b
426 426
 
427 427
 cl_error_t cli_regex2suffix(const char *pattern, regex_t *preg, suffix_callback cb, void *cbdata)
428 428
 {
429
-    struct regex_list regex;
430
-    struct text_buffer buf;
431
-    struct node root_node;
432
-    struct node *n;
433
-    size_t last = 0;
429
+    struct regex_list regex = {0};
430
+    struct text_buffer buf  = {0};
431
+    struct node root_node   = {0};
432
+    struct node *n          = NULL;
433
+    size_t last             = 0;
434 434
     int rc;
435 435
 
436
-    assert(pattern);
436
+    VERIFY_POINTER(pattern, cli_errmsg("cli_regex2suffix: pattern must be initialized"); rc = CL_ENULLARG);
437
+    VERIFY_POINTER(preg, cli_errmsg("cli_regex2suffix: preg must be initialized"); rc = CL_ENULLARG);
437 438
 
438 439
     regex.preg = preg;
439 440
     rc         = cli_regcomp(regex.preg, pattern, REG_EXTENDED);
... ...
@@ -449,10 +452,10 @@ cl_error_t cli_regex2suffix(const char *pattern, regex_t *preg, suffix_callback
449 449
         }
450 450
         return rc;
451 451
     }
452
-    regex.nxt     = NULL;
453
-    regex.pattern = cli_strdup(pattern);
452
+    regex.nxt = NULL;
453
+    CLI_STRDUP(pattern, regex.pattern, cli_errmsg("cli_regex2suffix: Unable to duplicate pattern"); rc = CL_EMEM);
454 454
 
455
-    n = parse_regex(pattern, &last);
455
+    n = parse_regex(((const uint8_t *)pattern), &last);
456 456
     if (!n)
457 457
         return REG_ESPACE;
458 458
     memset(&buf, 0, sizeof(buf));
... ...
@@ -460,8 +463,11 @@ cl_error_t cli_regex2suffix(const char *pattern, regex_t *preg, suffix_callback
460 460
     n->parent = &root_node;
461 461
 
462 462
     rc = build_suffixtree_descend(n, &buf, cb, cbdata, &regex);
463
-    free(regex.pattern);
464
-    free(buf.data);
463
+
464
+done:
465
+
466
+    FREE(regex.pattern);
467
+    FREE(buf.data);
465 468
     destroy_tree(n);
466 469
     return rc;
467 470
 }
... ...
@@ -113,8 +113,8 @@ static cl_error_t unz(
113 113
     zip_cb zcb,
114 114
     const char *original_filename)
115 115
 {
116
-    char obuf[BUFSIZ];
117
-    char *tempfile = NULL;
116
+    char obuf[BUFSIZ] = {0};
117
+    char *tempfile    = NULL;
118 118
     int out_file, ret = CL_CLEAN;
119 119
     int res        = 1;
120 120
     size_t written = 0;
... ...
@@ -219,7 +219,7 @@ static const struct rtest {
219 219
     {NULL,
220 220
      "http://key.com", "go to key.com", RTR_CLEAN},
221 221
     {":.+\\.paypal\\.(com|de|fr|it)([/?].*)?:.+\\.ebay\\.(at|be|ca|ch|co\\.uk|de|es|fr|ie|in|it|nl|ph|pl|com(\\.(au|cn|hk|my|sg))?)([/?].*)?/",
222
-     "http://www.paypal.com", "pics.ebay.com", RTR_ALLOWED},
222
+     "http://www.paypal.com", "pics.ebay.com", RTR_INVALID_REGEX},
223 223
     {NULL, "http://somefakeurl.example.com", "someotherdomain-key.com", RTR_CLEAN},
224 224
     {NULL, "http://somefakeurl.example.com", "someotherdomain.key.com", RTR_PHISH},
225 225
     {NULL, "http://malware-test.example.com/something", "test", RTR_BLOCKED},