Skip to content

Commit 9fc8db7

Browse files
committed
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.
1 parent 9c466f6 commit 9fc8db7

6 files changed

Lines changed: 301 additions & 92 deletions

File tree

libclamav/matcher-ac.c

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -641,10 +641,36 @@ static void ac_free_special(struct cli_ac_patt *p)
641641
MPOOL_FREE(mempool, p->special_table);
642642
}
643643

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(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+
644670
void cli_ac_free(struct cli_matcher *root)
645671
{
646-
uint32_t i;
647-
struct cli_ac_patt *patt;
672+
uint32_t i = 0;
673+
struct cli_ac_patt *patt = NULL;
648674

649675
for (i = 0; i < root->ac_patterns; i++) {
650676
patt = root->ac_pattable[i];
@@ -669,9 +695,11 @@ void cli_ac_free(struct cli_matcher *root)
669695
/* Freeing trans nodes must be done before freeing table nodes! */
670696
for (i = 0; i < root->ac_nodes; i++) {
671697
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);
698+
root->ac_root->trans != root->ac_nodetable[i]->trans) {
699+
700+
if (need_to_free(root, i)) {
701+
MPOOL_FREE(root->mempool, root->ac_nodetable[i]->trans);
702+
}
675703
}
676704
}
677705

@@ -681,19 +709,22 @@ void cli_ac_free(struct cli_matcher *root)
681709
if (root->ac_listtable)
682710
MPOOL_FREE(root->mempool, root->ac_listtable);
683711

684-
for (i = 0; i < root->ac_nodes; i++)
712+
for (i = 0; i < root->ac_nodes; i++) {
685713
MPOOL_FREE(root->mempool, root->ac_nodetable[i]);
714+
}
686715

687-
if (root->ac_nodetable)
716+
if (root->ac_nodetable) {
688717
MPOOL_FREE(root->mempool, root->ac_nodetable);
718+
}
689719

690720
if (root->ac_root) {
691721
MPOOL_FREE(root->mempool, root->ac_root->trans);
692722
MPOOL_FREE(root->mempool, root->ac_root);
693723
}
694724

695-
if (root->filter)
725+
if (root->filter) {
696726
MPOOL_FREE(root->mempool, root->filter);
727+
}
697728
}
698729

699730
/*

libclamav/others.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1177,6 +1177,19 @@ uint8_t cli_set_debug_flag(uint8_t debug_flag);
11771177
} while (0)
11781178
#endif
11791179

1180+
#ifndef CLI_STRDUP
1181+
#define CLI_STRDUP(buf, var, ...) \
1182+
do { \
1183+
var = cli_strdup(buf); \
1184+
if (NULL == var) { \
1185+
do { \
1186+
__VA_ARGS__; \
1187+
} while (0); \
1188+
goto done; \
1189+
} \
1190+
} while (0)
1191+
#endif
1192+
11801193
#ifndef FREE
11811194
#define FREE(var) \
11821195
do { \
@@ -1251,4 +1264,29 @@ uint8_t cli_set_debug_flag(uint8_t debug_flag);
12511264
} while (0)
12521265
#endif
12531266

1267+
/**
1268+
* @brief Wrapper around realloc that limits how much may be allocated to CLI_MAX_ALLOCATION.
1269+
*
1270+
* IMPORTANT: This differs from realloc() in that if size==0, it will NOT free the ptr.
1271+
*
1272+
* NOTE: cli_realloc() will NOT free ptr if size==0. It is safe to free ptr after `done:`.
1273+
*
1274+
* @param ptr
1275+
* @param size
1276+
* @return void*
1277+
*/
1278+
#ifndef CLI_REALLOC
1279+
#define CLI_REALLOC(ptr, size, ...) \
1280+
do { \
1281+
void *vTmp = cli_realloc(ptr, size); \
1282+
if (NULL == vTmp) { \
1283+
do { \
1284+
__VA_ARGS__; \
1285+
} while (0); \
1286+
goto done; \
1287+
} \
1288+
ptr = vTmp; \
1289+
} while (0)
1290+
#endif
1291+
12541292
#endif

0 commit comments

Comments
 (0)