e21657df |
/* |
14e2247b |
* Copyright (C) 2015-2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved. |
e21657df |
* Copyright (C) 2008 Sourcefire, Inc.
* |
946bd266 |
* Authors: aCaB <acab@clamav.net> |
e21657df |
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
/* a naive pool allocator */
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
#ifdef USE_MPOOL |
160930d4 |
|
e21657df |
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_STRING_H
#include <string.h>
#endif |
11195c0b |
#if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H)
#include <sys/mman.h>
#endif |
e21657df |
#include <stddef.h>
|
60d8d2c3 |
#include "clamav.h" |
946bd266 |
#include "others.h" |
ad0fd728 |
#include "str.h" |
d6e1ef16 |
#include "readdb.h" |
e21657df |
|
d068119a |
/*#define CL_DEBUG*/ |
1b802d3c |
#ifdef CL_DEBUG
#include <assert.h> |
d068119a |
#define MPOOLMAGIC 0xadde |
1b802d3c |
#define ALLOCPOISON 0x5a
#define FREEPOISON 0xde
#endif
|
d068119a |
/*#define DEBUGMPOOL
#define EXIT_ON_FLUSH*/ |
e21657df |
#ifdef DEBUGMPOOL |
7866b37c |
#define spam(...) cli_warnmsg( __VA_ARGS__) |
e21657df |
#else |
cd94be7a |
static inline void spam(const char *fmt, ...) { UNUSEDPARAM(fmt); } |
e21657df |
#endif
#include "mpool.h"
|
80871017 |
#undef CL_DEBUG /* bb#2222 */
|
18f620f2 |
#ifdef C_HPUX
#define MIN_FRAGSIZE 1048576 /* Goes with LDFLAGS=-Wl,+pd,1M */
#else |
34e79a80 |
#define MIN_FRAGSIZE 262144 |
18f620f2 |
#endif |
e21657df |
|
0281fb4d |
#if SIZEOF_VOID_P==8
static const unsigned int fragsz[] = { |
697b276e |
8,
11,
13,
16,
17,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
37,
40,
41,
48,
56,
72,
74,
75,
76,
78,
79,
80,
81,
101,
104,
109,
113,
116,
120,
128,
131,
143,
151,
152,
153,
196,
256,
360,
403,
404,
432,
486,
514,
548,
578,
604,
633,
697,
743,
784,
839,
1176,
1536,
1666,
2056,
2168,
2392,
2985,
3221,
3433,
3753,
3832,
4104,
4280,
4696,
4952,
5256,
5826,
6264,
7176,
8440,
9096,
16392,
32780,
50961,
63504,
65558,
101912,
131088,
262144,
507976,
524296,
1048584, |
ebf10d4a |
2097152,
4194304,
8388608, |
2beb84a1 |
16777216,
33554432,
67108864,
134217728, |
34e79a80 |
/* MAX_ALLOCATION is 184549376 but that's really not need here */ |
2beb84a1 |
/* ^^ This MAX_ALLOCATION warning for Mac OS should now be fixed */ |
0281fb4d |
};
#else
|
5684130b |
static const unsigned int fragsz[] = { |
d4c6e1d6 |
4,
5,
8,
9,
11,
12,
13,
14,
15,
16,
17,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
35,
36,
37,
39,
40,
41,
44,
48,
49,
52,
53,
56,
58,
59,
60,
61,
62,
63,
64,
65,
68,
69,
72,
73,
77,
80,
81,
83,
85,
88,
89,
93,
96,
99,
101,
103,
104,
105,
108,
112,
113,
115,
116,
117,
119,
120,
121,
124,
128,
129,
131,
133,
136,
137,
141,
143,
145,
148,
151,
152,
153,
160,
168,
173,
176,
184,
194,
200,
208,
216,
224,
229,
232,
241,
244,
248,
256,
257,
264,
274,
280,
293,
296,
304,
307,
312,
326,
344,
354,
372,
396,
403,
418,
456,
485,
514,
546,
581,
608,
646,
693,
740,
776,
805,
828,
902,
964,
1028,
1032,
1136,
1238,
1314,
1420,
1501,
1668,
1720,
1832,
1940,
2048,
2119,
2264,
2584,
2724,
2994,
3336,
3428,
3828,
4104,
4471,
4836,
5044,
5176,
5912,
6227,
6792,
7732,
8192,
11272,
12500,
16384,
32768,
63500,
65536,
131080,
253988,
262148,
524292,
1048576,
2097152,
4194304,
8388608, |
2beb84a1 |
16777216,
33554432,
67108864,
134217728, |
0281fb4d |
};
#endif |
cd7c9a4f |
|
0281fb4d |
#define FRAGSBITS (sizeof(fragsz)/sizeof(fragsz[0]))
struct MPMAP {
struct MPMAP *next; |
110714bb |
size_t size;
size_t usize; |
0281fb4d |
};
struct MP { |
110714bb |
size_t psize; |
0281fb4d |
struct FRAG *avail[FRAGSBITS]; |
630d47cb |
union {
struct MPMAP mpm;
uint64_t dummy_align;
} u; |
0281fb4d |
}; |
e21657df |
|
d068119a |
/* alignment of fake handled in the code! */
struct alloced {
uint8_t padding;
uint8_t sbits;
uint8_t fake;
};
|
e21657df |
struct FRAG { |
261e29da |
#ifdef CL_DEBUG |
d068119a |
uint16_t magic; |
261e29da |
#endif |
b26d0ef3 |
union { |
d068119a |
struct alloced a;
struct unaligned_ptr next; |
b26d0ef3 |
} u; |
e21657df |
}; |
d068119a |
#define FRAG_OVERHEAD (offsetof(struct FRAG, u.a.fake)) |
e21657df |
|
110714bb |
static size_t align_to_pagesize(struct MP *mp, size_t size) { |
e21657df |
return (size / mp->psize + (size % mp->psize != 0)) * mp->psize;
}
|
110714bb |
static unsigned int to_bits(size_t size) { |
e21657df |
unsigned int i; |
948644e6 |
for(i=0; i<FRAGSBITS; i++)
if(fragsz[i] >= size) return i; |
946bd266 |
return FRAGSBITS; |
e21657df |
} |
d068119a |
|
110714bb |
static size_t from_bits(unsigned int bits) { |
0281fb4d |
if (bits >= FRAGSBITS) return 0; |
948644e6 |
return fragsz[bits]; |
e21657df |
}
|
110714bb |
static inline unsigned int alignof(size_t size) |
d068119a |
{
/* conservative estimate of alignment.
* A struct that needs alignment of 'align' is padded by the compiler
* so that sizeof(struct)%align == 0
* (otherwise you wouldn't be able to use it in an array)
* Also align = 2^n.
* Largest alignment we need is 8 bytes (ptr/int64), since we don't use long
* double or __aligned attribute.
* This conservatively estimates that size 32 needs alignment of 8 (even if it might only
* need an alignment of 4).
*/
switch (size%8) {
case 0:
return 8;
case 2: |
5f12eacb |
case 6: |
d068119a |
return 2;
case 4:
return 4;
default:
return 1;
}
}
static inline size_t alignto(size_t p, size_t size)
{
/* size is power of 2 */
return (p+size-1)&(~(size-1));
}
|
47d40feb |
struct MP *mpool_create() {
struct MP mp, *mpool_p; |
110714bb |
size_t sz; |
e21657df |
memset(&mp, 0, sizeof(mp)); |
86d59b24 |
mp.psize = cli_getpagesize(); |
948644e6 |
sz = align_to_pagesize(&mp, MIN_FRAGSIZE); |
d068119a |
mp.u.mpm.usize = sizeof(struct MPMAP);
mp.u.mpm.size = sz - sizeof(mp);
if (FRAGSBITS > 255) {
cli_errmsg("At most 255 frags possible!\n");
return NULL;
}
if (fragsz[0] < sizeof(void*)) {
cli_errmsg("fragsz[0] too small!\n");
return NULL;
} |
f526f0b2 |
#ifndef _WIN32
if ((mpool_p = (struct MP *)mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE|ANONYMOUS_MAP, -1, 0)) == MAP_FAILED)
#else
if(!(mpool_p = (struct MP *)VirtualAlloc(NULL, sz, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)))
#endif
return NULL; |
1b802d3c |
#ifdef CL_DEBUG
memset(mpool_p, ALLOCPOISON, sz);
#endif |
47d40feb |
memcpy(mpool_p, &mp, sizeof(mp)); |
110714bb |
spam("Map created @%p->%p - size %lu out of %lu - voidptr=%lu\n", mpool_p, (char *)mpool_p + mp.u.mpm.size, (unsigned long)mp.u.mpm.usize, (unsigned long)mp.u.mpm.size, (unsigned long)SIZEOF_VOID_P); |
47d40feb |
return mpool_p; |
e21657df |
}
|
47d40feb |
void mpool_destroy(struct MP *mp) { |
630d47cb |
struct MPMAP *mpm_next = mp->u.mpm.next, *mpm; |
110714bb |
size_t mpmsize; |
1b802d3c |
|
e21657df |
while((mpm = mpm_next)) { |
1b802d3c |
mpmsize = mpm->size; |
e21657df |
mpm_next = mpm->next; |
1b802d3c |
#ifdef CL_DEBUG
memset(mpm, FREEPOISON, mpmsize);
#endif |
4743d54f |
#ifndef _WIN32 |
1b802d3c |
munmap((void *)mpm, mpmsize); |
4743d54f |
#else
VirtualFree(mpm, 0, MEM_RELEASE);
#endif |
e21657df |
} |
630d47cb |
mpmsize = mp->u.mpm.size; |
1b802d3c |
#ifdef CL_DEBUG |
d068119a |
memset(mp, FREEPOISON, mpmsize + sizeof(*mp)); |
1b802d3c |
#endif |
4743d54f |
#ifndef _WIN32 |
d068119a |
munmap((void *)mp, mpmsize + sizeof(*mp)); |
4743d54f |
#else
VirtualFree(mp, 0, MEM_RELEASE);
#endif |
34e79a80 |
spam("Map destroyed @%p\n", mp); |
e21657df |
}
|
47d40feb |
void mpool_flush(struct MP *mp) { |
34e79a80 |
size_t used = 0, mused; |
630d47cb |
struct MPMAP *mpm_next = mp->u.mpm.next, *mpm; |
1b802d3c |
|
34e79a80 |
#ifdef EXIT_ON_FLUSH
exit(0);
#endif
while((mpm = mpm_next)) {
mpm_next = mpm->next;
mused = align_to_pagesize(mp, mpm->usize);
if(mused < mpm->size) { |
1b802d3c |
#ifdef CL_DEBUG |
34e79a80 |
memset((char *)mpm + mused, FREEPOISON, mpm->size - mused); |
1b802d3c |
#endif |
4743d54f |
#ifndef _WIN32 |
34e79a80 |
munmap((char *)mpm + mused, mpm->size - mused); |
4743d54f |
#else
VirtualFree((char *)mpm + mused, mpm->size - mused, MEM_DECOMMIT);
#endif |
34e79a80 |
mpm->size = mused;
}
used += mpm->size;
}
|
d068119a |
mused = align_to_pagesize(mp, mp->u.mpm.usize + sizeof(*mp));
if (mused < mp->u.mpm.size + sizeof(*mp)) { |
1b802d3c |
#ifdef CL_DEBUG |
d068119a |
memset((char *)mp + mused, FREEPOISON, mp->u.mpm.size + sizeof(*mp) - mused); |
1b802d3c |
#endif |
4743d54f |
#ifndef _WIN32 |
d068119a |
munmap((char *)mp + mused, mp->u.mpm.size + sizeof(*mp) - mused); |
4743d54f |
#else |
d068119a |
VirtualFree((char *)mp + mused, mp->u.mpm.size + sizeof(*mp) - mused, MEM_DECOMMIT); |
4743d54f |
#endif |
d068119a |
mp->u.mpm.size = mused - sizeof(*mp); |
34e79a80 |
} |
630d47cb |
used += mp->u.mpm.size; |
7cbc72d3 |
cli_dbgmsg("pool memory used: %.3f MB\n", used/(1024*1024.0)); |
110714bb |
spam("Map flushed @%p, in use: %lu\n", mp, (unsigned long)used); |
deb30312 |
}
|
47d40feb |
int mpool_getstats(const struct cl_engine *eng, size_t *used, size_t *total) |
deb30312 |
{ |
1b802d3c |
size_t sum_used = 0, sum_total = 0;
const struct MPMAP *mpm;
const mpool_t *mp;
/* checking refcount is not necessary, but safer */
if (!eng || !eng->refcount)
return -1;
mp = eng->mempool;
if (!mp)
return -1; |
630d47cb |
for(mpm = &mp->u.mpm; mpm; mpm = mpm->next) { |
1b802d3c |
sum_used += mpm->usize;
sum_total += mpm->size;
}
*used = sum_used;
*total = sum_total;
return 0; |
e21657df |
}
|
110714bb |
static inline size_t align_increase(size_t size, size_t a) |
d068119a |
{
/* we must pad with at most a-1 bytes to align start of struct */
return size + a - 1;
}
|
110714bb |
static void* allocate_aligned(struct MPMAP *mpm, size_t size, unsigned align, const char *dbg) |
d068119a |
{
/* We could always align the size to maxalign (8), however that wastes
* space.
* So just align the start of each allocation as needed, and then see in
* which sbits bin we fit into.
* Since we are no longer allocating in multiple of 8, we must always
* align the start of each allocation!
*| end of previous allocation | padding | FRAG_OVERHEAD | ptr_aligned |*/
unsigned p = mpm->usize + FRAG_OVERHEAD;
unsigned p_aligned = alignto(p, align);
struct FRAG *f = (struct FRAG*)((char*)mpm + p_aligned - FRAG_OVERHEAD);
unsigned realneed = p_aligned + size - mpm->usize; |
110714bb |
unsigned int sbits = to_bits(realneed);
size_t needed = from_bits(sbits); |
d068119a |
#ifdef CL_DEBUG
assert(p_aligned + size <= mpm->size);
#endif
f->u.a.sbits = sbits;
f->u.a.padding = p_aligned - p;
mpm->usize += needed;
#ifdef CL_DEBUG
assert(mpm->usize <= mpm->size);
#endif |
110714bb |
spam("malloc @%p size %lu (%s) origsize %lu overhead %lu\n", f, (unsigned long)realneed, dbg, (unsigned long)size, (unsigned long)(needed - size)); |
d068119a |
#ifdef CL_DEBUG
f->magic = MPOOLMAGIC;
memset(&f->u.a.fake, ALLOCPOISON, size);
#endif
return &f->u.a.fake;
}
|
47d40feb |
void *mpool_malloc(struct MP *mp, size_t size) { |
110714bb |
size_t align = alignof(size);
size_t i, needed = align_increase(size+FRAG_OVERHEAD, align); |
e21657df |
const unsigned int sbits = to_bits(needed);
struct FRAG *f = NULL; |
630d47cb |
struct MPMAP *mpm = &mp->u.mpm; |
e21657df |
|
948644e6 |
/* check_all(mp); */ |
946bd266 |
if (!size || sbits == FRAGSBITS) { |
964a1e73 |
cli_errmsg("mpool_malloc(): Attempt to allocate %lu bytes. Please report to https://bugzilla.clamav.net\n", (unsigned long) size); |
946bd266 |
return NULL;
} |
e21657df |
/* Case 1: We have a free'd frag */ |
0281fb4d |
if((f = mp->avail[sbits])) { |
d068119a |
struct FRAG *fold = f;
mp->avail[sbits] = f->u.next.ptr;
/* we always have enough space for this, align_increase ensured that */ |
ac20e91b |
#ifdef _WIN64 |
b6768907 |
f = (struct FRAG*)(alignto((unsigned long long)f + FRAG_OVERHEAD, align)-FRAG_OVERHEAD); |
ac20e91b |
#else |
b6768907 |
f = (struct FRAG*)(alignto((unsigned long)f + FRAG_OVERHEAD, align)-FRAG_OVERHEAD); |
ac20e91b |
#endif |
d068119a |
f->u.a.sbits = sbits;
f->u.a.padding = (char*)f - (char*)fold; |
ad0fd728 |
#ifdef CL_DEBUG |
d068119a |
f->magic = MPOOLMAGIC;
memset(&f->u.a.fake, ALLOCPOISON, size); |
ad0fd728 |
#endif |
110714bb |
spam("malloc @%p size %lu (freed) origsize %lu overhead %lu\n", f, (unsigned long)(f->u.a.padding + FRAG_OVERHEAD + size), (unsigned long)size, (unsigned long)(needed - size)); |
d068119a |
return &f->u.a.fake; |
e21657df |
}
|
946bd266 |
if (!(needed = from_bits(sbits))) { |
964a1e73 |
cli_errmsg("mpool_malloc(): Attempt to allocate %lu bytes. Please report to https://bugzilla.clamav.net\n", (unsigned long) size); |
946bd266 |
return NULL;
} |
e21657df |
/* Case 2: We have nuff room available for this frag already */
while(mpm) { |
d068119a |
if(mpm->size - mpm->usize >= needed)
return allocate_aligned(mpm, size, align, "hole"); |
e21657df |
mpm = mpm->next;
}
/* Case 3: We allocate more */ |
d068119a |
if (needed + sizeof(*mpm) > MIN_FRAGSIZE)
i = align_to_pagesize(mp, needed + sizeof(*mpm)); |
e21657df |
else
i = align_to_pagesize(mp, MIN_FRAGSIZE); |
4743d54f |
#ifndef _WIN32 |
946bd266 |
if ((mpm = (struct MPMAP *)mmap(NULL, i, PROT_READ | PROT_WRITE, MAP_PRIVATE|ANONYMOUS_MAP, -1, 0)) == MAP_FAILED) { |
4743d54f |
#else
if (!(mpm = (struct MPMAP *)VirtualAlloc(NULL, i, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE))) {
#endif |
110714bb |
cli_errmsg("mpool_malloc(): Can't allocate memory (%lu bytes).\n", (unsigned long)i);
spam("failed to alloc %lu bytes (%lu requested)\n", (unsigned long)i, (unsigned long)size); |
e21657df |
return NULL;
} |
1b802d3c |
#ifdef CL_DEBUG
memset(mpm, ALLOCPOISON, i);
#endif |
e21657df |
mpm->size = i; |
d068119a |
mpm->usize = sizeof(*mpm); |
630d47cb |
mpm->next = mp->u.mpm.next;
mp->u.mpm.next = mpm; |
d068119a |
return allocate_aligned(mpm, size, align, "new map");
}
static void *allocbase_fromfrag(struct FRAG *f)
{ |
7866b37c |
#ifdef CL_DEBUG |
d068119a |
assert(f->u.a.padding < 8); |
7866b37c |
#endif |
d068119a |
return (char*)f - f->u.a.padding; |
e21657df |
}
|
47d40feb |
void mpool_free(struct MP *mp, void *ptr) { |
fd856af4 |
struct FRAG *f = (struct FRAG *)((char *)ptr - FRAG_OVERHEAD); |
b26d0ef3 |
unsigned int sbits; |
e21657df |
if (!ptr) return;
|
7866b37c |
#ifdef CL_DEBUG |
47d40feb |
assert(f->magic == MPOOLMAGIC && "Attempt to mpool_free a pointer we did not allocate!"); |
7866b37c |
#endif
|
34e79a80 |
spam("free @%p\n", f); |
d068119a |
sbits = f->u.a.sbits;
f = allocbase_fromfrag(f);
#ifdef CL_DEBUG
memset(f, FREEPOISON, from_bits(sbits));
#endif
f->u.next.ptr = mp->avail[sbits];
mp->avail[sbits] = f; |
e21657df |
}
|
47d40feb |
void *mpool_calloc(struct MP *mp, size_t nmemb, size_t size) { |
110714bb |
size_t needed = nmemb*size; |
e21657df |
void *ptr;
if(!needed) return NULL; |
47d40feb |
if((ptr = mpool_malloc(mp, needed))) |
e21657df |
memset(ptr, 0, needed);
return ptr;
}
|
47d40feb |
void *mpool_realloc(struct MP *mp, void *ptr, size_t size) { |
fd856af4 |
struct FRAG *f = (struct FRAG *)((char *)ptr - FRAG_OVERHEAD); |
110714bb |
size_t csize; |
e21657df |
void *new_ptr; |
47d40feb |
if (!ptr) return mpool_malloc(mp, size); |
e21657df |
|
d068119a |
if(!size || !(csize = from_bits(f->u.a.sbits))) { |
964a1e73 |
cli_errmsg("mpool_realloc(): Attempt to allocate %lu bytes. Please report to https://bugzilla.clamav.net\n", (unsigned long) size); |
946bd266 |
return NULL;
} |
d068119a |
csize -= FRAG_OVERHEAD + f->u.a.padding;
if (csize >= size && (!f->u.a.sbits || from_bits(f->u.a.sbits-1)-FRAG_OVERHEAD-f->u.a.padding < size)) { |
34e79a80 |
spam("free @%p\n", f); |
110714bb |
spam("malloc @%p size %lu (self) origsize %lu overhead %lu\n", f, (unsigned long)(size + FRAG_OVERHEAD + f->u.a.padding), (unsigned long)size, (unsigned long)(csize-size+FRAG_OVERHEAD+f->u.a.padding)); |
b26d0ef3 |
return ptr; |
34e79a80 |
} |
47d40feb |
if (!(new_ptr = mpool_malloc(mp, size))) |
e21657df |
return NULL; |
46826baf |
memcpy(new_ptr, ptr, csize <= size ? csize : size); |
47d40feb |
mpool_free(mp, ptr); |
e21657df |
return new_ptr;
}
|
47d40feb |
void *mpool_realloc2(struct MP *mp, void *ptr, size_t size) { |
34e79a80 |
void *new_ptr = mpool_realloc(mp, ptr, size);
if(new_ptr)
return new_ptr; |
47d40feb |
mpool_free(mp, ptr); |
0281fb4d |
return NULL; |
e21657df |
}
|
7b1f1aaf |
char *cli_mpool_hex2str(mpool_t *mp, const char *hex) {
char *str; |
eaf2aebd |
size_t len = strlen((const char*)hex);
if (len&1) { |
5fc6e404 |
cli_errmsg("cli_hex2str(): Malformed hexstring: %s (length: %lu)\n", hex, (unsigned long)len); |
eaf2aebd |
return NULL;
}
str = mpool_malloc(mp, (len/2) + 1); |
e522909e |
if (str == NULL) { /* oops, we have a memory pool allocation failure */ |
5fc6e404 |
cli_errmsg("cli_mpool_hex2str(): Can't allocate memory (%lu bytes).\n", (unsigned long)(len/2 + 1)); |
e522909e |
return NULL;
} |
7b1f1aaf |
if (cli_hex2str_to(hex, str, len) == -1) { |
eaf2aebd |
mpool_free(mp, str);
return NULL;
}
str[len/2] = '\0';
return str; |
ad0fd728 |
}
|
47d40feb |
char *cli_mpool_strdup(mpool_t *mp, const char *s) { |
d6e1ef16 |
char *alloc; |
110714bb |
size_t strsz; |
d6e1ef16 |
if(s == NULL) { |
964a1e73 |
cli_errmsg("cli_mpool_strdup(): s == NULL. Please report to https://bugzilla.clamav.net\n"); |
d6e1ef16 |
return NULL;
}
strsz = strlen(s) + 1; |
47d40feb |
alloc = mpool_malloc(mp, strsz); |
d6e1ef16 |
if(!alloc) |
110714bb |
cli_errmsg("cli_mpool_strdup(): Can't allocate memory (%lu bytes).\n", (unsigned long) strsz); |
d6e1ef16 |
else
memcpy(alloc, s, strsz);
return alloc;
}
|
67f8441d |
char *cli_mpool_strndup(mpool_t *mp, const char *s, size_t n) {
char *alloc;
size_t strsz;
if(s == NULL) { |
964a1e73 |
cli_errmsg("cli_mpool_strndup(): s == NULL. Please report to https://bugzilla.clamav.net\n"); |
67f8441d |
return NULL;
}
|
47a544dc |
strsz = cli_strnlen(s, n) + 1; |
67f8441d |
alloc = mpool_malloc(mp, strsz);
if(!alloc)
cli_errmsg("cli_mpool_strndup(): Can't allocate memory (%lu bytes).\n", (unsigned long) strsz);
else
memcpy(alloc, s, strsz-1);
alloc[strsz-1] = '\0';
return alloc;
}
|
4f798ac6 |
/* #define EXPAND_PUA */ |
47d40feb |
char *cli_mpool_virname(mpool_t *mp, const char *virname, unsigned int official) { |
d6e1ef16 |
char *newname, *pt; |
4f798ac6 |
#ifdef EXPAND_PUA
char buf[1024];
#endif
|
d6e1ef16 |
if(!virname)
return NULL;
|
eaf2aebd |
if((pt = strchr(virname, ' ')))
if((pt = strstr(pt, " (Clam)")))
*pt='\0'; |
d6e1ef16 |
if(!virname[0]) {
cli_errmsg("cli_virname: Empty virus name\n");
return NULL;
}
|
4f798ac6 |
#ifdef EXPAND_PUA
if(!strncmp(virname, "PUA.", 4)) {
snprintf(buf, sizeof(buf), "Possibly-Unwanted-Application(www.clamav.net/support/pua).%s", virname + 4);
buf[sizeof(buf)-1] = '\0';
virname = buf;
}
#endif |
d6e1ef16 |
if(official) |
47d40feb |
return cli_mpool_strdup(mp, virname); |
d6e1ef16 |
|
47d40feb |
newname = (char *)mpool_malloc(mp, strlen(virname) + 11 + 1); |
d6e1ef16 |
if(!newname) {
cli_errmsg("cli_virname: Can't allocate memory for newname\n");
return NULL;
}
sprintf(newname, "%s.UNOFFICIAL", virname);
return newname;
}
|
47d40feb |
uint16_t *cli_mpool_hex2ui(mpool_t *mp, const char *hex) { |
38e881e3 |
uint16_t *str; |
110714bb |
size_t len; |
38e881e3 |
len = strlen(hex);
if(len % 2 != 0) { |
110714bb |
cli_errmsg("cli_mpool_hex2ui(): Malformed hexstring: %s (length: %lu)\n", hex, (unsigned long)len); |
38e881e3 |
return NULL;
}
|
47d40feb |
str = mpool_calloc(mp, (len / 2) + 1, sizeof(uint16_t)); |
38e881e3 |
if(!str)
return NULL;
if(cli_realhex2ui(hex, str, len))
return str;
|
47d40feb |
mpool_free(mp, str); |
38e881e3 |
return NULL;
}
|
946bd266 |
#ifdef DEBUGMPOOL |
47d40feb |
void mpool_stats(struct MP *mp) { |
110714bb |
size_t i=0, ta=0, tu=0; |
630d47cb |
struct MPMAP *mpm = &mp->u.mpm; |
946bd266 |
cli_warnmsg("MEMORY POOL STATISTICS\n map \tsize\tused\t%\n");
while(mpm) { |
110714bb |
cli_warnmsg("- %lu\t%lu\t%lu\t%f%%\n", (unsigned long)i, (unsigned long)(mpm->size), (unsigned long)(mpm->usize), (float)mpm->usize/(float)mpm->size*100); |
946bd266 |
ta+=mpm->size;
tu+=mpm->usize;
i++;
mpm = mpm->next;
} |
110714bb |
cli_warnmsg("MEMORY POOL SUMMARY\nMaps: %lu\nTotal: %lu\nUsed: %lu (%f%%)\n", (unsigned long)i, (unsigned long)ta, (unsigned long)tu, (float)tu/(float)ta*100); |
946bd266 |
}
void check_all(struct MP *mp) { |
630d47cb |
struct MPMAP *mpm = &mp->u.mpm; |
946bd266 |
while(mpm) {
volatile unsigned char *c = (unsigned char *)mpm; |
110714bb |
size_t len = mpm->size;
spam("checking object %p - size %lu\n", mpm, (unsigned long)len); |
946bd266 |
while (len--) {
c[len];
}
mpm=mpm->next;
}
}
#endif /* DEBUGMPOOL */
|
ad0fd728 |
|
db43492c |
#else
/* dummy definitions to make Solaris linker happy.
* these symbols are declared in libclamav.map */ |
47d40feb |
void mpool_free() {}
void mpool_create() {}
void mpool_destroy() {}
void mpool_getstats() {} |
8a6c2921 |
void mpool_calloc() {} |
ad0fd728 |
|
e21657df |
#endif /* USE_MPOOL */ |
db43492c |
|
110714bb |
|