~ubuntu-branches/ubuntu/feisty/clamav/feisty

« back to all changes in this revision

Viewing changes to libclamav/mpool.c

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2007-02-20 10:33:44 UTC
  • mto: This revision was merged to the branch mainline in revision 16.
  • Revision ID: james.westby@ubuntu.com-20070220103344-zgcu2psnx9d98fpa
Tags: upstream-0.90
ImportĀ upstreamĀ versionĀ 0.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  Copyright (C) 2008 Sourcefire, Inc.
3
 
 *
4
 
 *  Authors: aCaB <acab@clamav.net>
5
 
 *
6
 
 *  This program is free software; you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License version 2 as
8
 
 *  published by the Free Software Foundation.
9
 
 *
10
 
 *  This program is distributed in the hope that it will be useful,
11
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *  GNU General Public License for more details.
14
 
 *
15
 
 *  You should have received a copy of the GNU General Public License
16
 
 *  along with this program; if not, write to the Free Software
17
 
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
 
 *  MA 02110-1301, USA.
19
 
 */
20
 
 
21
 
/* a naive pool allocator */
22
 
 
23
 
#if HAVE_CONFIG_H
24
 
#include "clamav-config.h"
25
 
#endif
26
 
 
27
 
#ifdef USE_MPOOL
28
 
 
29
 
#include <sys/types.h>
30
 
#include <sys/stat.h>
31
 
#include <fcntl.h>
32
 
#ifdef HAVE_UNISTD_H
33
 
#include <unistd.h>
34
 
#endif
35
 
#if HAVE_STRING_H
36
 
#include <string.h>
37
 
#endif
38
 
#if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H)
39
 
#include <sys/mman.h>
40
 
#endif
41
 
#include <stddef.h>
42
 
 
43
 
#include "others.h"
44
 
#include "str.h"
45
 
#include "readdb.h"
46
 
 
47
 
/*#define CL_DEBUG*/
48
 
#ifdef CL_DEBUG
49
 
#include <assert.h>
50
 
#define MPOOLMAGIC 0xadde
51
 
#define ALLOCPOISON 0x5a
52
 
#define FREEPOISON 0xde
53
 
#endif
54
 
 
55
 
/*#define DEBUGMPOOL
56
 
#define EXIT_ON_FLUSH*/
57
 
#ifdef DEBUGMPOOL
58
 
#define spam(...) cli_warnmsg( __VA_ARGS__)
59
 
#else
60
 
static inline void spam(const char *fmt, ...) { fmt = fmt; } /* gcc STFU */
61
 
#endif
62
 
 
63
 
#include "mpool.h"
64
 
 
65
 
#undef CL_DEBUG /* bb#2222 */
66
 
 
67
 
#define MIN_FRAGSIZE 262144
68
 
 
69
 
#if SIZEOF_VOID_P==8
70
 
static const unsigned int fragsz[] = {
71
 
    8,
72
 
    11,
73
 
    13,
74
 
    16,
75
 
    17,
76
 
    19,
77
 
    20,
78
 
    21,
79
 
    22,
80
 
    23,
81
 
    24,
82
 
    25,
83
 
    26,
84
 
    27,
85
 
    28,
86
 
    29,
87
 
    30,
88
 
    31,
89
 
    32,
90
 
    33,
91
 
    37,
92
 
    40,
93
 
    41,
94
 
    48,
95
 
    56,
96
 
    72,
97
 
    74,
98
 
    75,
99
 
    76,
100
 
    78,
101
 
    79,
102
 
    80,
103
 
    81,
104
 
    101,
105
 
    104,
106
 
    109,
107
 
    113,
108
 
    116,
109
 
    120,
110
 
    128,
111
 
    131,
112
 
    143,
113
 
    151,
114
 
    152,
115
 
    153,
116
 
    196,
117
 
    256,
118
 
    360,
119
 
    403,
120
 
    404,
121
 
    432,
122
 
    486,
123
 
    514,
124
 
    548,
125
 
    578,
126
 
    604,
127
 
    633,
128
 
    697,
129
 
    743,
130
 
    784,
131
 
    839,
132
 
   1176,
133
 
   1536,
134
 
   1666,
135
 
   2056,
136
 
   2168,
137
 
   2392,
138
 
   2985,
139
 
   3221,
140
 
   3433,
141
 
   3753,
142
 
   3832,
143
 
   4104,
144
 
   4280,
145
 
   4696,
146
 
   4952,
147
 
   5256,
148
 
   5826,
149
 
   6264,
150
 
   7176,
151
 
   8440,
152
 
   9096,
153
 
  16392,
154
 
  32780,
155
 
  50961,
156
 
  63504,
157
 
  65558,
158
 
 101912,
159
 
 131088,
160
 
 262144,
161
 
 507976,
162
 
 524296,
163
 
1048584,
164
 
2097152,
165
 
4194304,
166
 
8388608,
167
 
 /* MAX_ALLOCATION is 184549376 but that's really not need here */
168
 
};
169
 
 
170
 
#else
171
 
 
172
 
static const unsigned int fragsz[] = {
173
 
    4,
174
 
    5,
175
 
    8,
176
 
    9,
177
 
    11,
178
 
    12,
179
 
    13,
180
 
    14,
181
 
    15,
182
 
    16,
183
 
    17,
184
 
    19,
185
 
    20,
186
 
    21,
187
 
    22,
188
 
    23,
189
 
    24,
190
 
    25,
191
 
    26,
192
 
    27,
193
 
    28,
194
 
    29,
195
 
    30,
196
 
    31,
197
 
    32,
198
 
    33,
199
 
    35,
200
 
    36,
201
 
    37,
202
 
    39,
203
 
    40,
204
 
    41,
205
 
    44,
206
 
    48,
207
 
    49,
208
 
    52,
209
 
    53,
210
 
    56,
211
 
    58,
212
 
    59,
213
 
    60,
214
 
    61,
215
 
    62,
216
 
    63,
217
 
    64,
218
 
    65,
219
 
    68,
220
 
    69,
221
 
    72,
222
 
    73,
223
 
    77,
224
 
    80,
225
 
    81,
226
 
    83,
227
 
    85,
228
 
    88,
229
 
    89,
230
 
    93,
231
 
    96,
232
 
    99,
233
 
    101,
234
 
    103,
235
 
    104,
236
 
    105,
237
 
    108,
238
 
    112,
239
 
    113,
240
 
    115,
241
 
    116,
242
 
    117,
243
 
    119,
244
 
    120,
245
 
    121,
246
 
    124,
247
 
    128,
248
 
    129,
249
 
    131,
250
 
    133,
251
 
    136,
252
 
    137,
253
 
    141,
254
 
    143,
255
 
    145,
256
 
    148,
257
 
    151,
258
 
    152,
259
 
    153,
260
 
    160,
261
 
    168,
262
 
    173,
263
 
    176,
264
 
    184,
265
 
    194,
266
 
    200,
267
 
    208,
268
 
    216,
269
 
    224,
270
 
    229,
271
 
    232,
272
 
    241,
273
 
    244,
274
 
    248,
275
 
    256,
276
 
    257,
277
 
    264,
278
 
    274,
279
 
    280,
280
 
    293,
281
 
    296,
282
 
    304,
283
 
    307,
284
 
    312,
285
 
    326,
286
 
    344,
287
 
    354,
288
 
    372,
289
 
    396,
290
 
    403,
291
 
    418,
292
 
    456,
293
 
    485,
294
 
    514,
295
 
    546,
296
 
    581,
297
 
    608,
298
 
    646,
299
 
    693,
300
 
    740,
301
 
    776,
302
 
    805,
303
 
    828,
304
 
    902,
305
 
    964,
306
 
    1028,
307
 
    1032,
308
 
    1136,
309
 
    1238,
310
 
    1314,
311
 
    1420,
312
 
    1501,
313
 
    1668,
314
 
    1720,
315
 
    1832,
316
 
    1940,
317
 
    2048,
318
 
    2119,
319
 
    2264,
320
 
    2584,
321
 
    2724,
322
 
    2994,
323
 
    3336,
324
 
    3428,
325
 
    3828,
326
 
    4104,
327
 
    4471,
328
 
    4836,
329
 
    5044,
330
 
    5176,
331
 
    5912,
332
 
    6227,
333
 
    6792,
334
 
    7732,
335
 
    8192,
336
 
    11272,
337
 
    12500,
338
 
    16384,
339
 
    32768,
340
 
    63500,
341
 
    65536,
342
 
    131080,
343
 
    253988,
344
 
    262148,
345
 
    524292,
346
 
    1048576,
347
 
    2097152,
348
 
    4194304,
349
 
    8388608,
350
 
};
351
 
#endif
352
 
#define FRAGSBITS (sizeof(fragsz)/sizeof(fragsz[0]))
353
 
 
354
 
struct MPMAP {
355
 
  struct MPMAP *next;
356
 
  unsigned int size;
357
 
  unsigned int usize;
358
 
};
359
 
 
360
 
struct MP {
361
 
  unsigned int psize;
362
 
  struct FRAG *avail[FRAGSBITS];
363
 
  union {
364
 
      struct MPMAP mpm;
365
 
      uint64_t dummy_align;
366
 
  } u;
367
 
};
368
 
 
369
 
/* alignment of fake handled in the code! */
370
 
struct alloced {
371
 
    uint8_t padding;
372
 
    uint8_t sbits;
373
 
    uint8_t fake;
374
 
};
375
 
 
376
 
struct FRAG {
377
 
#ifdef CL_DEBUG
378
 
  uint16_t magic;
379
 
#endif
380
 
  union {
381
 
      struct alloced a;
382
 
      struct unaligned_ptr next;
383
 
  } u;
384
 
};
385
 
#define FRAG_OVERHEAD (offsetof(struct FRAG, u.a.fake))
386
 
 
387
 
static unsigned int align_to_pagesize(struct MP *mp, unsigned int size) {
388
 
  return (size / mp->psize + (size % mp->psize != 0)) * mp->psize;
389
 
}
390
 
 
391
 
static unsigned int to_bits(unsigned int size) {
392
 
  unsigned int i;
393
 
  for(i=0; i<FRAGSBITS; i++)
394
 
    if(fragsz[i] >= size) return i;
395
 
  return FRAGSBITS;
396
 
}
397
 
 
398
 
static unsigned int from_bits(unsigned int bits) {
399
 
  if (bits >= FRAGSBITS) return 0;
400
 
  return fragsz[bits];
401
 
}
402
 
 
403
 
static inline unsigned int alignof(unsigned int size)
404
 
{
405
 
    /* conservative estimate of alignment.
406
 
     * A struct that needs alignment of 'align' is padded by the compiler
407
 
     * so that sizeof(struct)%align == 0 
408
 
     * (otherwise you wouldn't be able to use it in an array)
409
 
     * Also align = 2^n.
410
 
     * Largest alignment we need is 8 bytes (ptr/int64), since we don't use long
411
 
     * double or __aligned attribute.
412
 
     * This conservatively estimates that size 32 needs alignment of 8 (even if it might only
413
 
     * need an alignment of 4).
414
 
     */
415
 
    switch (size%8) {
416
 
        case 0:
417
 
            return 8;
418
 
        case 2:
419
 
        case 6:
420
 
            return 2;
421
 
        case 4:
422
 
            return 4;
423
 
        default:
424
 
            return 1;
425
 
    }
426
 
}
427
 
 
428
 
static inline size_t alignto(size_t p, size_t size)
429
 
{
430
 
    /* size is power of 2 */
431
 
    return (p+size-1)&(~(size-1));
432
 
}
433
 
 
434
 
struct MP *mpool_create() {
435
 
  struct MP mp, *mpool_p;
436
 
  unsigned int sz;
437
 
  memset(&mp, 0, sizeof(mp));
438
 
  mp.psize = cli_getpagesize();
439
 
  sz = align_to_pagesize(&mp, MIN_FRAGSIZE);
440
 
  mp.u.mpm.usize = sizeof(struct MPMAP);
441
 
  mp.u.mpm.size = sz - sizeof(mp);
442
 
#ifndef _WIN32
443
 
  if ((mpool_p = (struct MP *)mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE|ANONYMOUS_MAP, -1, 0)) == MAP_FAILED)
444
 
#else
445
 
  if(!(mpool_p = (struct MP *)VirtualAlloc(NULL, sz, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)))
446
 
#endif
447
 
    return NULL;
448
 
  if (FRAGSBITS > 255) {
449
 
      cli_errmsg("At most 255 frags possible!\n");
450
 
      return NULL;
451
 
  }
452
 
  if (fragsz[0] < sizeof(void*)) {
453
 
      cli_errmsg("fragsz[0] too small!\n");
454
 
      return NULL;
455
 
  }
456
 
#ifdef CL_DEBUG
457
 
  memset(mpool_p, ALLOCPOISON, sz);
458
 
#endif
459
 
  memcpy(mpool_p, &mp, sizeof(mp));
460
 
  spam("Map created @%p->%p - size %u out of %u - voidptr=%u\n", mpool_p, (char *)mpool_p + mp.u.mpm.size, mp.u.mpm.usize, mp.u.mpm.size, SIZEOF_VOID_P);
461
 
  return mpool_p;
462
 
}
463
 
 
464
 
void mpool_destroy(struct MP *mp) {
465
 
  struct MPMAP *mpm_next = mp->u.mpm.next, *mpm;
466
 
  unsigned int mpmsize;
467
 
 
468
 
  while((mpm = mpm_next)) {
469
 
    mpmsize = mpm->size;
470
 
    mpm_next = mpm->next;
471
 
#ifdef CL_DEBUG
472
 
    memset(mpm, FREEPOISON, mpmsize);
473
 
#endif
474
 
#ifndef _WIN32
475
 
    munmap((void *)mpm, mpmsize);
476
 
#else
477
 
    VirtualFree(mpm, 0, MEM_RELEASE);
478
 
#endif
479
 
  }
480
 
  mpmsize = mp->u.mpm.size;
481
 
#ifdef CL_DEBUG
482
 
  memset(mp, FREEPOISON, mpmsize + sizeof(*mp));
483
 
#endif
484
 
#ifndef _WIN32
485
 
  munmap((void *)mp, mpmsize + sizeof(*mp));
486
 
#else
487
 
  VirtualFree(mp, 0, MEM_RELEASE);
488
 
#endif
489
 
  spam("Map destroyed @%p\n", mp);
490
 
}
491
 
 
492
 
void mpool_flush(struct MP *mp) {
493
 
    size_t used = 0, mused;
494
 
    struct MPMAP *mpm_next = mp->u.mpm.next, *mpm;
495
 
 
496
 
#ifdef EXIT_ON_FLUSH
497
 
    exit(0);
498
 
#endif
499
 
 
500
 
    while((mpm = mpm_next)) {
501
 
        mpm_next = mpm->next;
502
 
        mused = align_to_pagesize(mp, mpm->usize);
503
 
        if(mused < mpm->size) {
504
 
#ifdef CL_DEBUG
505
 
            memset((char *)mpm + mused, FREEPOISON, mpm->size - mused);
506
 
#endif
507
 
#ifndef _WIN32
508
 
            munmap((char *)mpm + mused, mpm->size - mused);
509
 
#else
510
 
            VirtualFree((char *)mpm + mused, mpm->size - mused, MEM_DECOMMIT);
511
 
#endif
512
 
            mpm->size = mused;
513
 
        }
514
 
        used += mpm->size;
515
 
    }
516
 
 
517
 
    mused = align_to_pagesize(mp, mp->u.mpm.usize + sizeof(*mp));
518
 
    if (mused < mp->u.mpm.size + sizeof(*mp)) {
519
 
#ifdef CL_DEBUG
520
 
        memset((char *)mp + mused, FREEPOISON, mp->u.mpm.size + sizeof(*mp) - mused);
521
 
#endif
522
 
#ifndef _WIN32
523
 
        munmap((char *)mp + mused, mp->u.mpm.size + sizeof(*mp) - mused);
524
 
#else
525
 
        VirtualFree((char *)mp + mused, mp->u.mpm.size + sizeof(*mp) - mused, MEM_DECOMMIT);
526
 
#endif
527
 
        mp->u.mpm.size = mused - sizeof(*mp);
528
 
    }
529
 
    used += mp->u.mpm.size;
530
 
    cli_dbgmsg("pool memory used: %.3f MB\n", used/(1024*1024.0));
531
 
    spam("Map flushed @%p, in use: %lu\n", mp, used);
532
 
}
533
 
 
534
 
int mpool_getstats(const struct cl_engine *eng, size_t *used, size_t *total)
535
 
{
536
 
  size_t sum_used = 0, sum_total = 0;
537
 
  const struct MPMAP *mpm;
538
 
  const mpool_t *mp;
539
 
  
540
 
  /* checking refcount is not necessary, but safer */
541
 
  if (!eng || !eng->refcount)
542
 
    return -1;
543
 
  mp = eng->mempool;
544
 
  if (!mp)
545
 
    return -1;
546
 
  for(mpm = &mp->u.mpm; mpm; mpm = mpm->next) {
547
 
    sum_used += mpm->usize;
548
 
    sum_total += mpm->size;
549
 
  }
550
 
  *used = sum_used;
551
 
  *total = sum_total;
552
 
  return 0;
553
 
}
554
 
 
555
 
static inline unsigned align_increase(unsigned size, unsigned a)
556
 
{
557
 
    /* we must pad with at most a-1 bytes to align start of struct */
558
 
    return size + a - 1;
559
 
}
560
 
 
561
 
static void* allocate_aligned(struct MPMAP *mpm, unsigned long size, unsigned align, const char *dbg)
562
 
{
563
 
    /* We could always align the size to maxalign (8), however that wastes
564
 
     * space.
565
 
     * So just align the start of each allocation as needed, and then see in
566
 
     * which sbits bin we fit into.
567
 
     * Since we are no longer allocating in multiple of 8, we must always
568
 
     * align the start of each allocation!
569
 
     *| end of previous allocation | padding | FRAG_OVERHEAD | ptr_aligned |*/
570
 
    unsigned p = mpm->usize + FRAG_OVERHEAD;
571
 
    unsigned p_aligned = alignto(p, align);
572
 
    struct FRAG *f = (struct FRAG*)((char*)mpm + p_aligned - FRAG_OVERHEAD);
573
 
    unsigned realneed = p_aligned + size - mpm->usize;
574
 
    unsigned sbits = to_bits(realneed);
575
 
    unsigned needed = from_bits(sbits);
576
 
#ifdef CL_DEBUG
577
 
    assert(p_aligned + size <= mpm->size);
578
 
#endif
579
 
    f->u.a.sbits = sbits;
580
 
    f->u.a.padding = p_aligned - p;
581
 
 
582
 
    mpm->usize += needed;
583
 
#ifdef CL_DEBUG
584
 
    assert(mpm->usize <= mpm->size);
585
 
#endif
586
 
    spam("malloc @%p size %u (%s) origsize %u overhead %u\n", f, realneed, dbg, size, needed - size);
587
 
#ifdef CL_DEBUG
588
 
    f->magic = MPOOLMAGIC;
589
 
    memset(&f->u.a.fake, ALLOCPOISON, size);
590
 
#endif
591
 
    return &f->u.a.fake;
592
 
}
593
 
 
594
 
void *mpool_malloc(struct MP *mp, size_t size) {
595
 
  unsigned align = alignof(size);
596
 
  unsigned int i, needed = align_increase(size+FRAG_OVERHEAD, align);
597
 
  const unsigned int sbits = to_bits(needed);
598
 
  struct FRAG *f = NULL;
599
 
  struct MPMAP *mpm = &mp->u.mpm;
600
 
 
601
 
  /*  check_all(mp); */
602
 
  if (!size || sbits == FRAGSBITS) {
603
 
    cli_errmsg("mpool_malloc(): Attempt to allocate %lu bytes. Please report to http://bugs.clamav.net\n", (unsigned long int) size);
604
 
    return NULL;
605
 
  }
606
 
 
607
 
  /* Case 1: We have a free'd frag */
608
 
  if((f = mp->avail[sbits])) {
609
 
    struct FRAG *fold = f;
610
 
    mp->avail[sbits] = f->u.next.ptr;
611
 
    /* we always have enough space for this, align_increase ensured that */
612
 
    f = (struct FRAG*)(alignto((unsigned long)f + FRAG_OVERHEAD, align)-FRAG_OVERHEAD);
613
 
    f->u.a.sbits = sbits;
614
 
    f->u.a.padding = (char*)f - (char*)fold;
615
 
#ifdef CL_DEBUG
616
 
    f->magic = MPOOLMAGIC;
617
 
    memset(&f->u.a.fake, ALLOCPOISON, size);
618
 
#endif
619
 
    spam("malloc @%p size %u (freed) origsize %u overhead %u\n", f, f->u.a.padding + FRAG_OVERHEAD + size, size, needed - size);
620
 
    return &f->u.a.fake;
621
 
  }
622
 
 
623
 
  if (!(needed = from_bits(sbits))) {
624
 
    cli_errmsg("mpool_malloc(): Attempt to allocate %lu bytes. Please report to http://bugs.clamav.net\n", (unsigned long int) size);
625
 
    return NULL;
626
 
  }
627
 
 
628
 
  /* Case 2: We have nuff room available for this frag already */
629
 
  while(mpm) {
630
 
    if(mpm->size - mpm->usize >= needed)
631
 
        return allocate_aligned(mpm, size, align, "hole");
632
 
    mpm = mpm->next;
633
 
  }
634
 
 
635
 
  /* Case 3: We allocate more */
636
 
  if (needed + sizeof(*mpm) > MIN_FRAGSIZE)
637
 
  i = align_to_pagesize(mp, needed + sizeof(*mpm));
638
 
  else
639
 
  i = align_to_pagesize(mp, MIN_FRAGSIZE);
640
 
 
641
 
#ifndef _WIN32
642
 
  if ((mpm = (struct MPMAP *)mmap(NULL, i, PROT_READ | PROT_WRITE, MAP_PRIVATE|ANONYMOUS_MAP, -1, 0)) == MAP_FAILED) {
643
 
#else
644
 
  if (!(mpm = (struct MPMAP *)VirtualAlloc(NULL, i, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE))) {
645
 
#endif
646
 
    cli_errmsg("mpool_malloc(): Can't allocate memory (%lu bytes).\n", (unsigned long int)i);
647
 
    spam("failed to alloc %u bytes (%u requested)\n", i, size);
648
 
    return NULL;
649
 
  }
650
 
#ifdef CL_DEBUG
651
 
  memset(mpm, ALLOCPOISON, i);
652
 
#endif
653
 
  mpm->size = i;
654
 
  mpm->usize = sizeof(*mpm);
655
 
  mpm->next = mp->u.mpm.next;
656
 
  mp->u.mpm.next = mpm;
657
 
  return allocate_aligned(mpm, size, align, "new map");
658
 
}
659
 
 
660
 
static void *allocbase_fromfrag(struct FRAG *f)
661
 
{
662
 
#ifdef CL_DEBUG
663
 
    assert(f->u.a.padding < 8);
664
 
#endif
665
 
    return (char*)f - f->u.a.padding;
666
 
}
667
 
 
668
 
void mpool_free(struct MP *mp, void *ptr) {
669
 
  struct FRAG *f = (struct FRAG *)((char *)ptr - FRAG_OVERHEAD);
670
 
  unsigned int sbits;
671
 
  if (!ptr) return;
672
 
 
673
 
#ifdef CL_DEBUG
674
 
  assert(f->magic == MPOOLMAGIC && "Attempt to mpool_free a pointer we did not allocate!");
675
 
#endif
676
 
 
677
 
  spam("free @%p\n", f);
678
 
  sbits = f->u.a.sbits;
679
 
  f = allocbase_fromfrag(f);
680
 
#ifdef CL_DEBUG
681
 
  memset(f, FREEPOISON, from_bits(sbits));
682
 
#endif
683
 
 
684
 
  f->u.next.ptr = mp->avail[sbits];
685
 
  mp->avail[sbits] = f;
686
 
}
687
 
 
688
 
void *mpool_calloc(struct MP *mp, size_t nmemb, size_t size) {
689
 
  unsigned int needed = nmemb*size;
690
 
  void *ptr;
691
 
 
692
 
  if(!needed) return NULL;
693
 
  if((ptr = mpool_malloc(mp, needed)))
694
 
    memset(ptr, 0, needed);
695
 
  return ptr;
696
 
}
697
 
 
698
 
void *mpool_realloc(struct MP *mp, void *ptr, size_t size) {
699
 
  struct FRAG *f = (struct FRAG *)((char *)ptr - FRAG_OVERHEAD);
700
 
  unsigned int csize;
701
 
  void *new_ptr;
702
 
  if (!ptr) return mpool_malloc(mp, size);
703
 
 
704
 
  if(!size || !(csize = from_bits(f->u.a.sbits))) {
705
 
    cli_errmsg("mpool_realloc(): Attempt to allocate %lu bytes. Please report to http://bugs.clamav.net\n", (unsigned long int) size);
706
 
    return NULL;
707
 
  }
708
 
  csize -= FRAG_OVERHEAD + f->u.a.padding;
709
 
  if (csize >= size && (!f->u.a.sbits || from_bits(f->u.a.sbits-1)-FRAG_OVERHEAD-f->u.a.padding < size)) {
710
 
    spam("free @%p\n", f);
711
 
    spam("malloc @%p size %u (self) origsize %u overhead %u\n", f, size + FRAG_OVERHEAD + f->u.a.padding, size, csize-size+FRAG_OVERHEAD+f->u.a.padding);
712
 
    return ptr;
713
 
  }
714
 
  if (!(new_ptr = mpool_malloc(mp, size)))
715
 
    return NULL;
716
 
  memcpy(new_ptr, ptr, csize <= size ? csize : size);
717
 
  mpool_free(mp, ptr);
718
 
  return new_ptr;
719
 
}
720
 
 
721
 
void *mpool_realloc2(struct MP *mp, void *ptr, size_t size) {
722
 
    void *new_ptr = mpool_realloc(mp, ptr, size);
723
 
    if(new_ptr)
724
 
        return new_ptr;
725
 
    mpool_free(mp, ptr);
726
 
    return NULL;
727
 
}
728
 
 
729
 
unsigned char *cli_mpool_hex2str(mpool_t *mp, const char *hex) {
730
 
    unsigned char *str;
731
 
    size_t len = strlen((const char*)hex);
732
 
 
733
 
    if (len&1) {
734
 
        cli_errmsg("cli_hex2str(): Malformed hexstring: %s (length: %u)\n", hex, (unsigned)len);
735
 
        return NULL;
736
 
    }
737
 
 
738
 
    str = mpool_malloc(mp, (len/2) + 1);
739
 
    if (cli_hex2str_to(hex, (char*)str, len) == -1) {
740
 
        mpool_free(mp, str);
741
 
        return NULL;
742
 
    }
743
 
    str[len/2] = '\0';
744
 
    return str;
745
 
}
746
 
 
747
 
char *cli_mpool_strdup(mpool_t *mp, const char *s) {
748
 
  char *alloc;
749
 
  unsigned int strsz;
750
 
 
751
 
  if(s == NULL) {
752
 
    cli_errmsg("cli_mpool_strdup(): s == NULL. Please report to http://bugs.clamav.net\n");
753
 
    return NULL;
754
 
  }
755
 
 
756
 
  strsz = strlen(s) + 1;
757
 
  alloc = mpool_malloc(mp, strsz);
758
 
  if(!alloc)
759
 
    cli_errmsg("cli_mpool_strdup(): Can't allocate memory (%u bytes).\n", (unsigned int) strsz);
760
 
  else
761
 
    memcpy(alloc, s, strsz);
762
 
  return alloc;
763
 
}
764
 
 
765
 
/* #define EXPAND_PUA */
766
 
char *cli_mpool_virname(mpool_t *mp, const char *virname, unsigned int official) {
767
 
  char *newname, *pt;
768
 
#ifdef EXPAND_PUA
769
 
  char buf[1024];
770
 
#endif
771
 
 
772
 
  if(!virname)
773
 
    return NULL;
774
 
 
775
 
  if((pt = strchr(virname, ' ')))
776
 
      if((pt = strstr(pt, " (Clam)")))
777
 
          *pt='\0';
778
 
 
779
 
  if(!virname[0]) {
780
 
    cli_errmsg("cli_virname: Empty virus name\n");
781
 
    return NULL;
782
 
  }
783
 
 
784
 
#ifdef EXPAND_PUA
785
 
    if(!strncmp(virname, "PUA.", 4)) {
786
 
        snprintf(buf, sizeof(buf), "Possibly-Unwanted-Application(www.clamav.net/support/pua).%s", virname + 4);
787
 
        buf[sizeof(buf)-1] = '\0';
788
 
        virname = buf;
789
 
    }
790
 
#endif
791
 
  if(official)
792
 
    return cli_mpool_strdup(mp, virname);
793
 
 
794
 
  newname = (char *)mpool_malloc(mp, strlen(virname) + 11 + 1);
795
 
  if(!newname) {
796
 
    cli_errmsg("cli_virname: Can't allocate memory for newname\n");
797
 
    return NULL;
798
 
  }
799
 
  sprintf(newname, "%s.UNOFFICIAL", virname);
800
 
  return newname;
801
 
}
802
 
 
803
 
 
804
 
uint16_t *cli_mpool_hex2ui(mpool_t *mp, const char *hex) {
805
 
  uint16_t *str;
806
 
  unsigned int len;
807
 
  
808
 
  len = strlen(hex);
809
 
 
810
 
  if(len % 2 != 0) {
811
 
    cli_errmsg("cli_mpool_hex2ui(): Malformed hexstring: %s (length: %u)\n", hex, len);
812
 
    return NULL;
813
 
  }
814
 
 
815
 
  str = mpool_calloc(mp, (len / 2) + 1, sizeof(uint16_t));
816
 
  if(!str)
817
 
    return NULL;
818
 
 
819
 
  if(cli_realhex2ui(hex, str, len))
820
 
    return str;
821
 
    
822
 
  mpool_free(mp, str);
823
 
  return NULL;
824
 
}
825
 
 
826
 
 
827
 
#ifdef DEBUGMPOOL
828
 
void mpool_stats(struct MP *mp) {
829
 
  unsigned int i=0, ta=0, tu=0;
830
 
  struct MPMAP *mpm = &mp->u.mpm;
831
 
 
832
 
  cli_warnmsg("MEMORY POOL STATISTICS\n map  \tsize\tused\t%\n");
833
 
  while(mpm) {
834
 
    cli_warnmsg("- %u\t%u\t%u\t%f%%\n", i, mpm->size, mpm->usize, (float)mpm->usize/(float)mpm->size*100);
835
 
    ta+=mpm->size;
836
 
    tu+=mpm->usize;
837
 
    i++;
838
 
    mpm = mpm->next;
839
 
  }
840
 
  cli_warnmsg("MEMORY POOL SUMMARY\nMaps: %u\nTotal: %u\nUsed: %u (%f%%)\n", i, ta, tu, (float)tu/(float)ta*100);
841
 
}
842
 
 
843
 
void check_all(struct MP *mp) {
844
 
  struct MPMAP *mpm = &mp->u.mpm;
845
 
  while(mpm) {
846
 
    volatile unsigned char *c = (unsigned char *)mpm;
847
 
    unsigned int len = mpm->size;
848
 
    spam("checking object %p - size %u\n", mpm, len);
849
 
    while (len--) {
850
 
      c[len];
851
 
    }
852
 
    mpm=mpm->next;
853
 
  }
854
 
}
855
 
#endif /* DEBUGMPOOL */
856
 
 
857
 
 
858
 
#else
859
 
/* dummy definitions to make Solaris linker happy.
860
 
 * these symbols are declared in libclamav.map */
861
 
void mpool_free() {}
862
 
void mpool_create() {}
863
 
void mpool_destroy() {}
864
 
void mpool_getstats() {}
865
 
 
866
 
#endif /* USE_MPOOL */
867