Beispiel #1
0
void fixing_test(MPOOL_T *mpool_p, void *arr_malloc[], size_t count)
{
	int index, i, fix_bytes;
	assert(mpool_p && arr_malloc);	
	memset(arr_malloc, 0, count*sizeof(void*));
	index = 0;
	i = 0;
	fix_bytes = 33;
	while(i++ < 50)
	{
		printf("---------------------------------------------------\n");
		index = i % count;
		printf("[%d]test: index=%d bytes=%d\n", i++, index, fix_bytes);
		if (arr_malloc[index])
			mpool_free(*mpool_p, arr_malloc[index]);
		arr_malloc[index]=mpool_malloc(*mpool_p, fix_bytes);
		if (!arr_malloc[index])
			printf("%s\n", PROMPT_FAILED);
		else
			memset(arr_malloc[index], 5, fix_bytes);
		mpool_print(*mpool_p);
	}
	i=0;
	while(i < count)
	{
		mpool_free(*mpool_p, arr_malloc[i++]);
	}
	mpool_print(*mpool_p);
}
Beispiel #2
0
void main()
{
	MPOOL_T mpool;
	int i=20;
	char *new_p1, *new_p2, *new_p3;
	void* arr_malloc[MAX_HANDLES];
	char mem_1[500];
	char mem_2[300];
	mpool_init(&mpool, mem_1, sizeof(mem_1), 0, 4);
	new_p1 = mpool_malloc(mpool, 10);
	mpool_print(mpool);
	if (!new_p1) printf("%s", PROMPT_FAILED);

	mpool_grow(mpool,mem_2, sizeof(mem_2));
	mpool_print(mpool);

	new_p2 = mpool_malloc(mpool, 32);
	if (!new_p2) printf("%s", PROMPT_FAILED);
	mpool_free(mpool, new_p2);
	mpool_print(mpool);
	new_p3 = mpool_malloc(mpool, 12);
	mpool_print(mpool);
	if (!new_p3) printf("%s", PROMPT_FAILED);
	mpool_free(mpool, new_p1);
	mpool_print(mpool);
	mpool_free(mpool, new_p2);
	mpool_print(mpool);
	mpool_free(mpool, new_p3);
	mpool_print(mpool);
	random_test(&mpool, arr_malloc, MAX_HANDLES, 10);
	lining_test(&mpool, arr_malloc, MAX_HANDLES);
	fixing_test(&mpool, arr_malloc, MAX_HANDLES);
}
Beispiel #3
0
/* Allocates the trees for the engine cache */
int cli_cache_init(struct cl_engine *engine) {
    struct CACHE *cache;
    unsigned int i, j;

    if(!engine) {
	cli_errmsg("cli_cache_init: mpool malloc fail\n");
	return 1;
    }

    if(!(cache = mpool_malloc(engine->mempool, sizeof(struct CACHE) * TREES))) {
	cli_errmsg("cli_cache_init: mpool malloc fail\n");
	return 1;
    }

    for(i=0; i<TREES; i++) {
	if(pthread_mutex_init(&cache[i].mutex, NULL)) {
	    cli_errmsg("cli_cache_init: mutex init fail\n");
	    for(j=0; j<i; j++) cacheset_destroy(&cache[j].cacheset, engine->mempool);
	    for(j=0; j<i; j++) pthread_mutex_destroy(&cache[j].mutex);
	    mpool_free(engine->mempool, cache);
	    return 1;
	}
	if(cacheset_init(&cache[i].cacheset, engine->mempool)) {
	    for(j=0; j<i; j++) cacheset_destroy(&cache[j].cacheset, engine->mempool);
	    for(j=0; j<=i; j++) pthread_mutex_destroy(&cache[j].mutex);
	    mpool_free(engine->mempool, cache);
	    return 1;
	}
    }
    engine->cache = cache;
    return 0;
}
Beispiel #4
0
void random_test(MPOOL_T *mpool_p, void *arr_malloc[], size_t count, int times)
{
	int index, rand_bytes, i;
	assert(mpool_p && arr_malloc)
	memset(arr_malloc, 0, count*sizeof(void*));
	srand ((unsigned)time(NULL)); 
	i=0;
	while (times--)
	{
		printf("---------------------------------------------------\n");
		index=rand()%count;
		rand_bytes = rand()%150;
		printf("[%d]test: index=%d rand_bytes=%d\n", i++, index, rand_bytes);
		if (arr_malloc[index])
			mpool_free(*mpool_p, arr_malloc[index]);
		arr_malloc[index]=mpool_malloc(*mpool_p, rand_bytes);
		if (!arr_malloc[index])
			printf("%s\n", PROMPT_FAILED);
		else
			memset(arr_malloc[index], 5,rand_bytes);
		mpool_print(*mpool_p);
	}
	i=0;
	while(i < count)
	{
		mpool_free(*mpool_p, arr_malloc[i++]);
	}
	mpool_print(*mpool_p);
}
Beispiel #5
0
int phishing_init(struct cl_engine* engine)
{
	struct phishcheck* pchk;
	if(!engine->phishcheck) {
		pchk = engine->phishcheck = mpool_malloc(engine->mempool, sizeof(struct phishcheck));
		if(!pchk) {
            cli_errmsg("Phishcheck: Unable to allocate memory for initialization\n");
			return CL_EMEM;
        }
		pchk->is_disabled=1;
	}
	else {
		pchk = engine->phishcheck;
		if(!pchk)
			return CL_ENULLARG;
		if(!pchk->is_disabled) {
			/* already initialized */
			return CL_SUCCESS;
		}
	}

	cli_dbgmsg("Initializing phishcheck module\n");

	if(build_regex(&pchk->preg_numeric,numeric_url_regex,1)) {
		mpool_free(engine->mempool, pchk);
		engine->phishcheck = NULL;
		return CL_EFORMAT;
	}
	pchk->is_disabled = 0;
	cli_dbgmsg("Phishcheck module initialized\n");
	return CL_SUCCESS;
}
void dconf_teardown(void)
{
	mpool_free(pool, dconf);
#ifdef USE_MPOOL
	if (pool)
		mpool_destroy(pool);
#endif
}
Beispiel #7
0
void cli_pcre_freetable(struct cli_matcher *root)
{
    uint32_t i;
    struct cli_pcre_meta *pm = NULL;

    for (i = 0; i < root->pcre_metas; ++i) {
        /* free pcre meta */
        pm = root->pcre_metatable[i];
        cli_pcre_freemeta(root, pm);
        mpool_free(root->mempool, pm);
    }

    /* free holding structures and set count to zero */
    mpool_free(root->mempool, root->pcre_metatable);
    root->pcre_metatable = NULL;
    root->pcre_metas = 0;
}
Beispiel #8
0
void cli_bm_free(struct cli_matcher *root)
{
	struct cli_bm_patt *patt, *prev;
	uint16_t i, size = HASH(255, 255, 255) + 1;


    if(root->bm_shift)
	mpool_free(root->mempool, root->bm_shift);

    if(root->bm_suffix) {
	for(i = 0; i < size; i++) {
	    patt = root->bm_suffix[i];
	    while(patt) {
		prev = patt;
		patt = patt->next;
		if(prev->prefix)
		    mpool_free(root->mempool, prev->prefix);
		else
		    mpool_free(root->mempool, prev->pattern);
		if(prev->virname)
		    mpool_free(root->mempool, prev->virname);
		if(prev->offset)
		    mpool_free(root->mempool, prev->offset);
		mpool_free(root->mempool, prev);
	    }
	}
	mpool_free(root->mempool, root->bm_suffix);
    }
}
Beispiel #9
0
void *mpool_realloc2(struct MP *mp, void *ptr, size_t size) {
  struct FRAG *f = (struct FRAG *)((char *)ptr - FRAG_OVERHEAD);
  unsigned int csize;
  void *new_ptr;

  if (!ptr) return mpool_malloc(mp, size);

  spam("realloc @ %p (size %u -> %u))\n", f, from_bits(f->u.sbits), size);
  if(!size || !(csize = from_bits(f->u.sbits))) {
    cli_errmsg("mpool_realloc2(): Attempt to allocate %lu bytes. Please report to http://bugs.clamav.net\n", (unsigned long int) size);
    mpool_free(mp, ptr);
    return NULL;
  }
  csize -= FRAG_OVERHEAD;
  if (csize >= size && (!f->u.sbits || from_bits(f->u.sbits-1)-FRAG_OVERHEAD < size))
    return ptr;
  if ((new_ptr = mpool_malloc(mp, size)))
    memcpy(new_ptr, ptr, csize);
  mpool_free(mp, ptr);
  return new_ptr;
}
Beispiel #10
0
void cli_pcre_freemeta(struct cli_matcher *root, struct cli_pcre_meta *pm)
{
    if (!pm)
        return;

    if (pm->trigger) {
        mpool_free(root->mempool, pm->trigger);
        pm->trigger = NULL;
    }

    if (pm->virname) {
        mpool_free(root->mempool, pm->virname);
        pm->virname = NULL;
    }

    if (pm->statname) {
        free(pm->statname);
        pm->statname = NULL;
    }

    cli_pcre_free_single(&(pm->pdata));
}
Beispiel #11
0
/* Frees the engine cache */
void cli_cache_destroy(struct cl_engine *engine) {
    struct CACHE *cache;
    unsigned int i;

    if(!engine || !(cache = engine->cache))
	return;

    for(i=0; i<TREES; i++) {
	cacheset_destroy(&cache[i].cacheset, engine->mempool);
	pthread_mutex_destroy(&cache[i].mutex);
    }
    mpool_free(engine->mempool, cache);
}
Beispiel #12
0
void phishing_done(struct cl_engine* engine)
{
	struct phishcheck* pchk = engine->phishcheck;
	cli_dbgmsg("Cleaning up phishcheck\n");
	if(pchk && !pchk->is_disabled) {
		free_regex(&pchk->preg_numeric);
	}
	whitelist_done(engine);
	domainlist_done(engine);
	if(pchk) {
		cli_dbgmsg("Freeing phishcheck struct\n");
		mpool_free(engine->mempool, pchk);
	}
	cli_dbgmsg("Phishcheck cleaned up\n");
}
Beispiel #13
0
unsigned char *cli_mpool_hex2str(mpool_t *mp, const unsigned char *hex) {
    unsigned char *str;
    size_t len = strlen((const char*)hex);

    if (len&1) {
	cli_errmsg("cli_hex2str(): Malformed hexstring: %s (length: %u)\n", hex, (unsigned)len);
	return NULL;
    }

    str = mpool_malloc(mp, (len/2) + 1);
    if (cli_hex2str_to(hex, str, len) == -1) {
	mpool_free(mp, str);
	return NULL;
    }
    str[len/2] = '\0';
    return str;
}
Beispiel #14
0
/****************************************************************************************
* Function name - heap_reset
*
* Description - De-allocates memory and inits to the initial values heap, but does 
*               not deallocate the heap itself.
*
* Input -       *h - pointer to an initialized heap
* Return Code/Output - none
****************************************************************************************/
void heap_reset (heap*const h)
{
  if (h->heap)
    {
      free (h->heap);
    }
  if (h->ids_arr)
    {
      free (h->ids_arr);
    }
  if (h->nodes_mpool)
    {
      mpool_free (h->nodes_mpool);
      free (h->nodes_mpool);
    }
  memset (h, 0, sizeof (*h));
}
Beispiel #15
0
/* Frees the engine cache */
void cli_cache_destroy(struct cl_engine *engine) {
    struct CACHE *cache;
    unsigned int i;

    if(!engine || !(cache = engine->cache))
	return;

    if (engine->engine_options & ENGINE_OPTIONS_DISABLE_CACHE) {
        return;
    }

    for(i=0; i<TREES; i++) {
	cacheset_destroy(&cache[i].cacheset, engine->mempool);
	pthread_mutex_destroy(&cache[i].mutex);
    }
    mpool_free(engine->mempool, cache);
}
Beispiel #16
0
void mm_free(void *p)
    {
#ifndef DONT_USE_POOL
    Memnode *n = (Memnode *)(((char *)p) - sizeof(Memnode));
    int poolindex = roundsize(n->esize);
    if (poolindex >= 0)
        {
        mpool_free(p, general_pools[poolindex]);
        return;
        }

    /* more then 256 bytes, use free */
    free(n);
#else
    free(p);
#endif
    }
Beispiel #17
0
int cli_bm_init(struct cli_matcher *root)
{
	uint16_t i, size = HASH(255, 255, 255) + 1;
#ifdef USE_MPOOL
    assert (root->mempool && "mempool must be initialized");
#endif
    if(!(root->bm_shift = (uint8_t *) mpool_calloc(root->mempool, size, sizeof(uint8_t))))
	return CL_EMEM;

    if(!(root->bm_suffix = (struct cli_bm_patt **) mpool_calloc(root->mempool, size, sizeof(struct cli_bm_patt *)))) {
	mpool_free(root->mempool, root->bm_shift);
	return CL_EMEM;
    }

    for(i = 0; i < size; i++)
	root->bm_shift[i] = BM_MIN_LENGTH - BM_BLOCK_SIZE + 1;

    return CL_SUCCESS;
}
Beispiel #18
0
uint16_t *cli_mpool_hex2ui(mpool_t *mp, const char *hex) {
  uint16_t *str;
  unsigned int len;
  
  len = strlen(hex);

  if(len % 2 != 0) {
    cli_errmsg("cli_hex2si(): Malformed hexstring: %s (length: %u)\n", hex, len);
    return NULL;
  }

  str = mpool_calloc(mp, (len / 2) + 1, sizeof(uint16_t));
  if(!str)
    return NULL;

  if(cli_realhex2ui(hex, str, len))
    return str;
    
  mpool_free(mp, str);
  return NULL;
}
Beispiel #19
0
static void cacheset_rehash(struct cache_set *map, mpool_t *mempool)
{
    unsigned i;
    int ret;
    struct cache_set tmp_set;
    struct cache_key *key;
    pthread_mutex_lock(&pool_mutex);
    ret = cacheset_init(&tmp_set, mempool);
    pthread_mutex_unlock(&pool_mutex);
    if (ret)
	return;

    key = map->lru_head;
    for (i=0;key && i < tmp_set.maxelements/2;i++) {
	cacheset_add(&tmp_set, (unsigned char*)&key->digest, key->size, mempool);
	key = key->lru_next;
    }
    pthread_mutex_lock(&pool_mutex);
    mpool_free(mempool, map->data);
    pthread_mutex_unlock(&pool_mutex);
    memcpy(map, &tmp_set, sizeof(tmp_set));
}
Beispiel #20
0
/* free both size-specific and agnostic hash sets */
void hm_free(struct cli_matcher *root) {
    enum CLI_HASH_TYPE type;

    if(!root)
	return;

    for(type = CLI_HASH_MD5; type < CLI_HASH_AVAIL_TYPES; type++) {
	struct cli_htu32 *ht = &root->hm.sizehashes[type];
	const struct cli_htu32_element *item = NULL;

	if(!root->hm.sizehashes[type].capacity)
	    continue;

	while((item = cli_htu32_next(ht, item))) {
	    struct cli_sz_hash *szh = (struct cli_sz_hash *)item->data.as_ptr;

	    mpool_free(root->mempool, szh->hash_array);
	    while(szh->items)
		mpool_free(root->mempool, (void *)szh->virusnames[--szh->items]);
	    mpool_free(root->mempool, szh->virusnames);
	    mpool_free(root->mempool, szh);
	}
	cli_htu32_free(ht, root->mempool);
    }

    for(type = CLI_HASH_MD5; type < CLI_HASH_AVAIL_TYPES; type++) {
	struct cli_sz_hash *szh = &root->hwild.hashes[type];

	if(!szh->items)
	    continue;

	mpool_free(root->mempool, szh->hash_array);
	while(szh->items)
	    mpool_free(root->mempool, (void *)szh->virusnames[--szh->items]);
	mpool_free(root->mempool, szh->virusnames);
    }
}
Beispiel #21
0
int cli_pcre_addpatt(struct cli_matcher *root, const char *virname, const char *trigger, const char *pattern, const char *cflags, const char *offset, const uint32_t *lsigid, unsigned int options)
{
    struct cli_pcre_meta **newmetatable = NULL, *pm = NULL;
    uint32_t pcre_count;
    const char *opt;
    int ret = CL_SUCCESS, rssigs;

    if (!root || !trigger || !pattern || !offset) {
        cli_errmsg("cli_pcre_addpatt: NULL root or NULL trigger or NULL pattern or NULL offset\n");
        return CL_ENULLARG;
    }

    /* TODO: trigger and regex checking (backreference limitations?) (control pattern limitations?) */
    /* cli_ac_chklsig will fail a empty trigger; empty patterns can cause an infinite loop */
    if (*trigger == '\0' || *pattern == '\0') {
        cli_errmsg("cli_pcre_addpatt: trigger or pattern cannot be an empty string\n");
        return CL_EMALFDB;
    }
    if (cflags && *cflags == '\0') {
        cflags = NULL;
    }

    if (lsigid)
        pm_dbgmsg("cli_pcre_addpatt: Adding /%s/%s%s triggered on (%s) as subsig %d for lsigid %d\n", 
                  pattern, cflags ? " with flags " : "", cflags ? cflags : "", trigger, lsigid[1], lsigid[0]);
    else
        pm_dbgmsg("cli_pcre_addpatt: Adding /%s/%s%s triggered on (%s) [no lsigid]\n",
                  pattern, cflags ? " with flags " : "", cflags ? cflags : "", trigger);

#ifdef PCRE_BYPASS
    /* check for trigger bypass */
    if (strcmp(trigger, PCRE_BYPASS)) {
#endif
        /* validate the lsig trigger */
        rssigs = cli_ac_chklsig(trigger, trigger + strlen(trigger), NULL, NULL, NULL, 1);
        if(rssigs == -1) {
            cli_errmsg("cli_pcre_addpatt: regex subsig /%s/ is missing a valid logical trigger\n", pattern);
            return CL_EMALFDB;
        }

        if (lsigid) {
            if (rssigs > lsigid[1]) {
                cli_errmsg("cli_pcre_addpatt: regex subsig %d logical trigger refers to subsequent subsig %d\n", lsigid[1], rssigs);
                return CL_EMALFDB;
            }
            if (rssigs == lsigid[1]) {
                cli_errmsg("cli_pcre_addpatt: regex subsig %d logical trigger is self-referential\n", lsigid[1]);
                return CL_EMALFDB;
            }
        }
        else {
            cli_dbgmsg("cli_pcre_addpatt: regex subsig is missing lsigid data\n");
        }
#ifdef PCRE_BYPASS
    }
#endif

    /* allocating entries */
    pm = (struct cli_pcre_meta *)mpool_calloc(root->mempool, 1, sizeof(*pm));
    if (!pm) {
        cli_errmsg("cli_pcre_addpatt: Unable to allocate memory for new pcre meta\n");
        return CL_EMEM;
    }

    pm->trigger = cli_mpool_strdup(root->mempool, trigger);
    if (!pm->trigger) {
        cli_errmsg("cli_pcre_addpatt: Unable to allocate memory for trigger string\n");
        cli_pcre_freemeta(root, pm);
        mpool_free(root->mempool, pm);
        return CL_EMEM;
    }

    pm->virname = (char *)cli_mpool_virname(root->mempool, virname, options & CL_DB_OFFICIAL);
    if(!pm->virname) {
        cli_errmsg("cli_pcre_addpatt: Unable to allocate memory for virname or NULL virname\n");
        cli_pcre_freemeta(root, pm);
        mpool_free(root->mempool, pm);
        return CL_EMEM;
    }

    if (lsigid) {
        root->ac_lsigtable[lsigid[0]]->virname = pm->virname;

        pm->lsigid[0] = 1;
        pm->lsigid[1] = lsigid[0];
        pm->lsigid[2] = lsigid[1];
    }
    else {
        /* sigtool */
        pm->lsigid[0] = 0;
    }

    pm->pdata.expression = strdup(pattern);
    if (!pm->pdata.expression) {
        cli_errmsg("cli_pcre_addpatt: Unable to allocate memory for expression\n");
        cli_pcre_freemeta(root, pm);
        mpool_free(root->mempool, pm);
        return CL_EMEM;
    }

    /* offset parsing and usage, similar to cli_ac_addsig */
    /* relative and type-specific offsets handled during scan */
    ret = cli_caloff(offset, NULL, root->type, pm->offdata, &(pm->offset_min), &(pm->offset_max));
    if (ret != CL_SUCCESS) {
        cli_errmsg("cli_pcre_addpatt: cannot calculate offset data: %s for pattern: %s\n", offset, pattern);
        cli_pcre_freemeta(root, pm);
        mpool_free(root->mempool, pm);
        return ret;
    }
    if(pm->offdata[0] != CLI_OFF_ANY) {
        if(pm->offdata[0] == CLI_OFF_ABSOLUTE)
            root->pcre_absoff_num++;
        else
            root->pcre_reloff_num++;
    }

    /* parse and add options, also totally not from snort */
    if (cflags) {
        opt = cflags;

        /* cli_pcre_addoptions handles pcre specific options */
        while (cli_pcre_addoptions(&(pm->pdata), &opt, 0) != CL_SUCCESS) {
            /* handle matcher specific options here */
            switch (*opt) {
            case 'g':  pm->flags |= CLI_PCRE_GLOBAL;            break;
            case 'r':  pm->flags |= CLI_PCRE_ROLLING;           break;
            case 'e':  pm->flags |= CLI_PCRE_ENCOMPASS;         break;
            default:
                cli_errmsg("cli_pcre_addpatt: unknown/extra pcre option encountered %c\n", *opt);
                cli_pcre_freemeta(root, pm);
                mpool_free(root->mempool, pm);
                return CL_EMALFDB;
            }
            opt++;
        }

        if (pm->flags) {
            pm_dbgmsg("Matcher:  %s%s%s\n",
                      pm->flags & CLI_PCRE_GLOBAL ? "CLAMAV_GLOBAL " : "",
                      pm->flags & CLI_PCRE_ROLLING ? "CLAMAV_ROLLING " : "",
                      pm->flags & CLI_PCRE_ENCOMPASS ? "CLAMAV_ENCOMPASS " : "");
        }
        else
            pm_dbgmsg("Matcher:  NONE\n");

        if (pm->pdata.options) {
#if USING_PCRE2
            pm_dbgmsg("Compiler: %s%s%s%s%s%s%s\n",
                      pm->pdata.options & PCRE2_CASELESS ? "PCRE2_CASELESS " : "",
                      pm->pdata.options & PCRE2_DOTALL ? "PCRE2_DOTALL " : "",
                      pm->pdata.options & PCRE2_MULTILINE ? "PCRE2_MULTILINE " : "",
                      pm->pdata.options & PCRE2_EXTENDED ? "PCRE2_EXTENDED " : "",

                      pm->pdata.options & PCRE2_ANCHORED ? "PCRE2_ANCHORED " : "",
                      pm->pdata.options & PCRE2_DOLLAR_ENDONLY ? "PCRE2_DOLLAR_ENDONLY " : "",
                      pm->pdata.options & PCRE2_UNGREEDY ? "PCRE2_UNGREEDY " : "");
#else
            pm_dbgmsg("Compiler: %s%s%s%s%s%s%s\n",
                      pm->pdata.options & PCRE_CASELESS ? "PCRE_CASELESS " : "",
                      pm->pdata.options & PCRE_DOTALL ? "PCRE_DOTALL " : "",
                      pm->pdata.options & PCRE_MULTILINE ? "PCRE_MULTILINE " : "",
                      pm->pdata.options & PCRE_EXTENDED ? "PCRE_EXTENDED " : "",

                      pm->pdata.options & PCRE_ANCHORED ? "PCRE_ANCHORED " : "",
                      pm->pdata.options & PCRE_DOLLAR_ENDONLY ? "PCRE_DOLLAR_ENDONLY " : "",
                      pm->pdata.options & PCRE_UNGREEDY ? "PCRE_UNGREEDY " : "");
#endif
        }
        else
            pm_dbgmsg("Compiler: NONE\n");
    }

    /* add metadata to the performance tracker */
    if (options & CL_DB_PCRE_STATS)
        pcre_perf_events_init(pm, virname);

    /* add pcre data to root after reallocation */
    pcre_count = root->pcre_metas+1;
    newmetatable = (struct cli_pcre_meta **)mpool_realloc(root->mempool, root->pcre_metatable,
                                         pcre_count * sizeof(struct cli_pcre_meta *));
    if (!newmetatable) {
        cli_errmsg("cli_pcre_addpatt: Unable to allocate memory for new pcre meta table\n");
        cli_pcre_freemeta(root, pm);
        mpool_free(root->mempool, pm);
        return CL_EMEM;
    }

    newmetatable[pcre_count-1] = pm;
    root->pcre_metatable = newmetatable;

    root->pcre_metas = pcre_count;

    return CL_SUCCESS;
}
Beispiel #22
0
int hm_addhash_bin(struct cli_matcher *root, const void *binhash, enum CLI_HASH_TYPE type, uint32_t size, const char *virusname) {
    const unsigned int hlen = hashlen[type];
    const struct cli_htu32_element *item;
    struct cli_sz_hash *szh;
    struct cli_htu32 *ht;
    int i;

    if (size) {
        /* size non-zero, find sz_hash element in size-driven hashtable  */
        ht = &root->hm.sizehashes[type];
        if(!root->hm.sizehashes[type].capacity) {
            i = cli_htu32_init(ht, 64, root->mempool);
            if(i) return i;
        }

        item = cli_htu32_find(ht, size);
        if(!item) {
	    struct cli_htu32_element htitem;
	    szh = mpool_calloc(root->mempool, 1, sizeof(*szh));
	    if(!szh) {
	        cli_errmsg("hm_addhash_bin: failed to allocate size hash\n");
	        return CL_EMEM;
	    }

	    htitem.key = size;
	    htitem.data.as_ptr = szh;
	    i = cli_htu32_insert(ht, &htitem, root->mempool);
	    if(i) {
	        cli_errmsg("hm_addhash_bin: failed to add item to hashtab");
	        mpool_free(root->mempool, szh);
	        return i;
	    }
        } else
	    szh = (struct cli_sz_hash *)item->data.as_ptr;
    }
    else {
        /* size 0 = wildcard */
        szh = &root->hwild.hashes[type];
    }
    szh->items++;

    szh->hash_array = mpool_realloc2(root->mempool, szh->hash_array, hlen * szh->items);
    if(!szh->hash_array) {
	cli_errmsg("hm_addhash_bin: failed to grow hash array to %u entries\n", szh->items);
	szh->items=0;
	mpool_free(root->mempool, szh->virusnames);
	szh->virusnames = NULL;
	return CL_EMEM;
    }

    szh->virusnames = mpool_realloc2(root->mempool, szh->virusnames, sizeof(*szh->virusnames) * szh->items);
    if(!szh->virusnames) {
	cli_errmsg("hm_addhash_bin: failed to grow virusname array to %u entries\n", szh->items);
	szh->items=0;
	mpool_free(root->mempool, szh->hash_array);
	szh->hash_array = NULL;
	return CL_EMEM;
    }

    memcpy(&szh->hash_array[(szh->items-1) * hlen], binhash, hlen);
    szh->virusnames[(szh->items-1)] = virusname;
    
    return 0;
}
Beispiel #23
0
Datei: env.c Projekt: berkus/moto
void
moto_freeEnv(MotoEnv *env) {
    Enumeration *e;

    /* Free any outstanding frames */
    while(vec_size(env->frames) > 0) {
        moto_freeFrame(env);
    }

    /* Free all the globals */
    e = stab_getKeys(env->globals);
    while (enum_hasNext(e)) {
        char* n = (char*)enum_next(e);
        MotoVar* var = stab_get(env->globals,n);

        if(env->mode != COMPILER_MODE) {
            moto_freeVal(env,var->vs);
        } else {
            opool_release(env->valpool,var->vs);
        }
        free(var);
    }
    enum_free(e);
    stab_free(env->globals);

    /* free all cached regular expressions */
    e = stab_getKeys(env->rxcache);
    while (enum_hasNext(e)) {
        char *rx = (char *)enum_next(e);
        MDFA *mdfa = (MDFA *)stab_get(env->rxcache, rx);
        if (mdfa != NULL) {
            mdfa_free(mdfa);
        }
    }
    enum_free(e);

    /* free all remaining pointers */
    e = hset_elements(env->ptrs);
    while (enum_hasNext(e)) {
        void *ptr = enum_next(e);
        if (shared_check(ptr)) {
            free(ptr);
        }
    }
    enum_free(e);

    /* free all errors */
    e = sset_elements(env->errs);
    while (enum_hasNext(e)) {
        void *ptr = enum_next(e);
        if (shared_check(ptr)) {
            free(ptr);
        }
    }
    enum_free(e);

    /* free all scopes */
    e = stack_elements(env->scope);
    while (enum_hasNext(e)) {
        free(enum_next(e));
    }
    enum_free(e);

    /* free all cells */
    moto_freeTreeCells(env);

    /* free all class defs */
    stab_free(env->cdefs);

    /* free remainder of env struct */
    hset_free(env->ptrs);
    buf_free(env->out);
    buf_free(env->err);
    stab_free(env->types);
    vec_free(env->frames);

    ftab_free(env->ftable);

    /* Free all the stuff that got put in the mpool ... this includes
    	MotoFunctions and MotoClassDefinitions */
    mpool_free(env->mpool);

    stack_free(env->scope);
    stab_free(env->rxcache);
    //stack_free(env->callstack);
    sset_free(env->errs);
    sset_free(env->uses);
    sset_free(env->includes);
    buf_free(env->fcodebuffer);
    istack_free(env->scopeIDStack);

    htab_free(env->fdefs);
    htab_free(env->adefs);
    buf_free(env->constantPool);
    moto_freeTree(env->tree);

    opool_free(env->valpool);
    opool_free(env->bufpool);
    opool_free(env->stkpool);

    e = stab_getKeys(env->fcache);
    while (enum_hasNext(e))
        free((char *)enum_next(e));
    enum_free(e);
    stab_free(env->fcache);

    free(env);
}
Beispiel #24
0
Datei: pp.c Projekt: berkus/moto
void motopp_freeEnv(MotoPP *ppenv) {
   Enumeration *e;
   
   log_debug(__FILE__, ">>> motopp_freeEnv\n");
  
   buf_free(ppenv->out);
   buf_free(ppenv->err);
   buf_free(ppenv->argbuf);
   istack_free(ppenv->dirstack);
   stack_free(ppenv->frames);   

   /* free vals */
   e = hset_elements(ppenv->vallist);
   while (enum_hasNext(e)) {
      MotoPPVal *val = enum_next(e);
      if (shared_check(val->sval)) {
         free(val->sval);
         hset_remove(ppenv->ptrs, val->sval);
      }
      free(val);
   }
   enum_free(e);
   hset_free(ppenv->vallist);
   
   /* free macros */
   while (stack_size(ppenv->macrostack) > 0) {
      SymbolTable *macros = stack_pop(ppenv->macrostack);
      e = stab_getKeys(macros);
      while (enum_hasNext(e)) {
         char *name = (char *)enum_next(e);
         MotoMacro *m = (MotoMacro *)stab_get(macros, name);
         motopp_freeMacro(m);
      }
      stab_free(macros);
      enum_free(e);
   }
   
   /* free all remaining sys pointers */
   e = hset_elements(ppenv->sysptrs);
   while (enum_hasNext(e)) {
      void *ptr = enum_next(e);
      if (ptr) {
         sys_free(ptr);         
      }
   }
   enum_free(e);
      
   /* free all remaining pointers */
   e = hset_elements(ppenv->ptrs);
   while (enum_hasNext(e)) {
      void *ptr = enum_next(e);
      if (shared_check(ptr)) {
         free(ptr);         
      }
   }
   enum_free(e);
      
   /* free remaining pooled memory */
   mpool_free(ppenv->mpool);

   /* free remainder of env struct */
   hset_free(ppenv->sysptrs);
   hset_free(ppenv->ptrs);
   stack_free(ppenv->macrostack);   
   
   free(ppenv);

   log_debug(__FILE__, "<<< motopp_freeEnv\n");

}
Beispiel #25
0
/* Frees all the nodes */
static inline void cacheset_destroy(struct cache_set *cs, mpool_t *mempool) {
    mpool_free(mempool, cs->data);
    cs->data = NULL;
}
Beispiel #26
0
int cli_cvdload(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, unsigned int dbtype, const char *filename, unsigned int chkonly)
{
	struct cl_cvd cvd, dupcvd;
	FILE *dupfs;
	int ret;
	time_t s_time;
	int cfd;
	struct cli_dbio dbio;
	struct cli_dbinfo *dbinfo = NULL;
	char *dupname;

    dbio.hashctx = NULL;

    cli_dbgmsg("in cli_cvdload()\n");

    /* verify */
    if((ret = cli_cvdverify(fs, &cvd, dbtype)))
	return ret;

    if(dbtype <= 1) {
	/* check for duplicate db */
	dupname = cli_strdup(filename);
	if(!dupname)
	    return CL_EMEM;
	dupname[strlen(dupname) - 2] = (dbtype == 1 ? 'v' : 'l');
	if(!access(dupname, R_OK) && (dupfs = fopen(dupname, "rb"))) {
	    if((ret = cli_cvdverify(dupfs, &dupcvd, !dbtype))) {
		fclose(dupfs);
		free(dupname);
		return ret;
	    }
	    fclose(dupfs);
	    if(dupcvd.version > cvd.version) {
		cli_warnmsg("Detected duplicate databases %s and %s. The %s database is older and will not be loaded, you should manually remove it from the database directory.\n", filename, dupname, filename);
		free(dupname);
		return CL_SUCCESS;
	    } else if(dupcvd.version == cvd.version && !dbtype) {
		cli_warnmsg("Detected duplicate databases %s and %s, please manually remove one of them\n", filename, dupname);
		free(dupname);
		return CL_SUCCESS;
	    }
	}
	free(dupname);
    }

    if(strstr(filename, "daily.")) {
	time(&s_time);
	if(cvd.stime > s_time) {
	    if(cvd.stime - (unsigned int ) s_time > 3600) {
		cli_warnmsg("******************************************************\n");
		cli_warnmsg("***      Virus database timestamp in the future!   ***\n");
		cli_warnmsg("***  Please check the timezone and clock settings  ***\n");
		cli_warnmsg("******************************************************\n");
	    }
	} else if((unsigned int) s_time - cvd.stime > 604800) {
	    cli_warnmsg("**************************************************\n");
	    cli_warnmsg("***  The virus database is older than 7 days!  ***\n");
	    cli_warnmsg("***   Please update it as soon as possible.    ***\n");
	    cli_warnmsg("**************************************************\n");
	}
	engine->dbversion[0] = cvd.version;
	engine->dbversion[1] = cvd.stime;
    }

    if(cvd.fl > cl_retflevel()) {
	cli_warnmsg("***********************************************************\n");
	cli_warnmsg("***  This version of the ClamAV engine is outdated.     ***\n");
	cli_warnmsg("*** DON'T PANIC! Read http://www.clamav.net/support/faq ***\n");
	cli_warnmsg("***********************************************************\n");
    }

    cfd = fileno(fs);
    dbio.chkonly = 0;
    if(dbtype == 2)
	ret = cli_tgzload(cfd, engine, signo, options | CL_DB_UNSIGNED, &dbio, NULL);
    else
	ret = cli_tgzload(cfd, engine, signo, options | CL_DB_OFFICIAL, &dbio, NULL);
    if(ret != CL_SUCCESS)
	return ret;

    dbinfo = engine->dbinfo;
    if(!dbinfo || !dbinfo->cvd || (dbinfo->cvd->version != cvd.version) || (dbinfo->cvd->sigs != cvd.sigs) || (dbinfo->cvd->fl != cvd.fl) || (dbinfo->cvd->stime != cvd.stime)) {
	cli_errmsg("cli_cvdload: Corrupted CVD header\n");
	return CL_EMALFDB;
    }
    dbinfo = engine->dbinfo ? engine->dbinfo->next : NULL;
    if(!dbinfo) {
	cli_errmsg("cli_cvdload: dbinfo error\n");
	return CL_EMALFDB;
    }

    dbio.chkonly = chkonly;
    if(dbtype == 2)
	options |= CL_DB_UNSIGNED;
    else
	options |= CL_DB_SIGNED | CL_DB_OFFICIAL;

    ret = cli_tgzload(cfd, engine, signo, options, &dbio, dbinfo);

    while(engine->dbinfo) {
	dbinfo = engine->dbinfo;
	engine->dbinfo = dbinfo->next;
	mpool_free(engine->mempool, dbinfo->name);
	mpool_free(engine->mempool, dbinfo->hash);
	if(dbinfo->cvd)
	    cl_cvdfree(dbinfo->cvd);
	mpool_free(engine->mempool, dbinfo);
    }

    return ret;
}
int main(void)
{
  size_t n, m;
  usCount start, end;
  size_t roundings[16];
  printf("N1527lib test program\n"
         "-=-=-=-=-=-=-=-=-=-=-\n");
  n=mpool_minimum_roundings(roundings, 16); assert(n<16);
  printf("Minimum roundings from available allocators:\n");
  for(m=0; m<n; m++)
  {
    printf("  %u\n", roundings[m]);
  }
  {
    mpool pool128, pool4096, poolA;
    void *temp1, *temp2;
    size_t usagecount, *alignments, *roundings;
    pool128=mpool_obtain(alignment128_attributes);
    temp1=mpool_malloc(pool128, 1);
    temp2=mpool_malloc(pool128, 1);
    printf("128 aligned %p (%u), %p (%u)", temp1, mpool_usable_size(pool128, temp1), temp2, mpool_usable_size(pool128, temp2));
    assert(!((size_t)temp1 & 127));
    assert(!((size_t)temp2 & 127));
    mpool_info(pool128, &usagecount, &alignments, &roundings, NULL);
    printf("  usagecount=%u, roundings[0]=%u\n", usagecount, roundings[0]);

    pool4096=mpool_obtain(alignment4096_attributes);
    temp1=mpool_malloc(pool4096, 1);
    temp2=mpool_malloc(pool4096, 1);
    printf("4096 aligned %p (%u), %p (%u)", temp1, mpool_usable_size(pool4096, temp1), temp2, mpool_usable_size(pool4096, temp2));
    assert(!((size_t)temp1 & 4095));
    assert(!((size_t)temp2 & 4095));
    mpool_info(pool4096, &usagecount, &alignments, &roundings, NULL);
    printf("  usagecount=%u, roundings[0]=%u\n", usagecount, roundings[0]);

    poolA=mpool_obtain(alignment128_attributes_a);
    mpool_info(poolA, &usagecount, &alignments, &roundings, NULL);
    printf("PoolA: usagecount=%u, roundings[0]=%u\n", usagecount, roundings[0]);
    assert(poolA==pool128);
  }

  syspool=mpool_obtain(MPOOL_DEFAULT);
  srand(1);
  for(n=0; n<RECORDS; n++)
    sizes[n]=rand() & 1023;
  if(1)
  {
    unsigned frees=0;
    printf("Fragmenting free space ...\n");
    start=GetUsCount();
    while(GetUsCount()-start<3000000000000)
    {
      n=rand() % RECORDS;
      if(ptrs[n]) { mpool_free(syspool, ptrs[n]); ptrs[n]=0; frees++; }
      else ptrs[n]=mpool_malloc(syspool, sizes[n]);
    }
    memset(ptrs, 0, RECORDS*sizeof(void *));
    printf("Did %u frees\n", frees);
  }

  if(0)
  {
    typedef void* mspace;
    extern mspace get_dlmalloc_mspace(mpool pool);
    extern void* mspace_malloc(mspace msp, size_t bytes);
    extern void mspace_free(mspace msp, void* mem);
    printf("\ndlmalloc Speed test\n"
             "-------------------\n");
    {
      mspace ms=get_dlmalloc_mspace(syspool);
      for(m=0; m<3; m++)
      {
        size_t count=RECORDS, size=1024;
        for(n=0; n<RECORDS; n++)
          sizes[n]=rand() & 1023;

        start=GetUsCount();
        for(n=0; n<RECORDS; n++)
        {
          ptrs[n]=mspace_malloc(ms, sizes[n]);
        }
        end=GetUsCount();
        printf("mspace_malloc() does %f mallocs/sec\n", RECORDS/((end-start)/1000000000000.0));

        start=GetUsCount();
        for(n=0; n<RECORDS; n++)
        {
          mspace_free(ms, ptrs[n]);
          ptrs[n]=0;
        }
        end=GetUsCount();
        printf("mspace_free() does %f frees/sec\n\n", RECORDS/((end-start)/1000000000000.0));
      }
    }
  }
  if(1)
  {
    printf("\nMPool Speed test\n"
             "----------------\n");
    for(m=0; m<3; m++)
    {
      size_t count=RECORDS, size=1024;
      for(n=0; n<RECORDS; n++)
        sizes[n]=rand() & 1023;

      start=GetUsCount();
      mpool_batch(syspool, NULL, ptrs, sizes, &count, 0);
      end=GetUsCount();
      printf("mpool_batch() does %f mallocs/sec\n", RECORDS/((end-start)/1000000000000.0));

      count=RECORDS;
      start=GetUsCount();
      mpool_batch(syspool, NULL, ptrs, NULL, &count, 0);
      end=GetUsCount();
      printf("mpool_batch() does %f frees/sec\n", RECORDS/((end-start)/1000000000000.0));

      start=GetUsCount();
      for(n=0; n<RECORDS; n++)
      {
        ptrs[n]=mpool_malloc(syspool, sizes[n]);
      }
      end=GetUsCount();
      printf("mpool_malloc() does %f mallocs/sec\n", RECORDS/((end-start)/1000000000000.0));

      start=GetUsCount();
      for(n=0; n<RECORDS; n++)
      {
        mpool_free(syspool, ptrs[n]);
        ptrs[n]=0;
      }
      end=GetUsCount();
      printf("mpool_free() does %f frees/sec\n\n", RECORDS/((end-start)/1000000000000.0));
    }
  }
#ifdef _MSC_VER
  printf("Press Return to exit ...\n");
  getchar();
#endif
  return 0;
}
Beispiel #28
0
int cli_ac_addpatt(struct cli_matcher *root, struct cli_ac_patt *pattern)
{
	struct cli_ac_node *pt, *next;
	struct cli_ac_patt *ph;
	void *newtable;
	struct cli_ac_alt *a1, *a2;
	uint8_t i, match;
	uint16_t len = MIN(root->ac_maxdepth, pattern->length);


    for(i = 0; i < len; i++) {
	if(pattern->pattern[i] & CLI_MATCH_WILDCARD) {
	    len = i;
	    break;
	}
    }

    if(len < root->ac_mindepth) {
	/* cli_errmsg("cli_ac_addpatt: Signature for %s is too short\n", pattern->virname); */
	return CL_EMALFDB;
    }

    pt = root->ac_root;

    for(i = 0; i < len; i++) {
	if(!pt->trans) {
	    pt->trans = (struct cli_ac_node **) mpool_calloc(root->mempool, 256, sizeof(struct cli_ac_node *));
	    if(!pt->trans) {
		cli_errmsg("cli_ac_addpatt: Can't allocate memory for pt->trans\n");
		return CL_EMEM;
	    }
	}

	next = pt->trans[(unsigned char) (pattern->pattern[i] & 0xff)]; 

	if(!next) {
	    next = (struct cli_ac_node *) mpool_calloc(root->mempool, 1, sizeof(struct cli_ac_node));
	    if(!next) {
		cli_errmsg("cli_ac_addpatt: Can't allocate memory for AC node\n");
		return CL_EMEM;
	    }

	    if(i != len - 1) {
		next->trans = (struct cli_ac_node **) mpool_calloc(root->mempool, 256, sizeof(struct cli_ac_node *));
		if(!next->trans) {
		    cli_errmsg("cli_ac_addpatt: Can't allocate memory for next->trans\n");
		    mpool_free(root->mempool, next);
		    return CL_EMEM;
		}
	    }

	    root->ac_nodes++;
	    newtable = mpool_realloc(root->mempool, root->ac_nodetable, root->ac_nodes * sizeof(struct cli_ac_node *));
	    if(!newtable) {
		root->ac_nodes--;
		cli_errmsg("cli_ac_addpatt: Can't realloc ac_nodetable\n");
		if(next->trans)
		    mpool_free(root->mempool, next->trans);
		mpool_free(root->mempool, next);
		return CL_EMEM;
	    }
	    root->ac_nodetable = (struct cli_ac_node **) newtable;
	    root->ac_nodetable[root->ac_nodes - 1] = next;

	    pt->trans[(unsigned char) (pattern->pattern[i] & 0xff)] = next;
	}

	pt = next;
    }

    root->ac_patterns++;
    newtable = mpool_realloc(root->mempool, root->ac_pattable, root->ac_patterns * sizeof(struct cli_ac_patt *));
    if(!newtable) {
	root->ac_patterns--;
	cli_errmsg("cli_ac_addpatt: Can't realloc ac_pattable\n");
	return CL_EMEM;
    }
    root->ac_pattable = (struct cli_ac_patt **) newtable;
    root->ac_pattable[root->ac_patterns - 1] = pattern;

    pattern->depth = i;

    ph = pt->list;
    while(ph) {
	if((ph->length == pattern->length) && (ph->prefix_length == pattern->prefix_length) && (ph->ch[0] == pattern->ch[0]) && (ph->ch[1] == pattern->ch[1])) {
	    if(!memcmp(ph->pattern, pattern->pattern, ph->length * sizeof(uint16_t)) && !memcmp(ph->prefix, pattern->prefix, ph->prefix_length * sizeof(uint16_t))) {
		if(!ph->alt && !pattern->alt) {
		    match = 1;
		} else if(ph->alt == pattern->alt) {
		    match = 1;
		    for(i = 0; i < ph->alt; i++) {
			a1 = ph->alttable[i];
			a2 = pattern->alttable[i];

			if(a1->num != a2->num) {
			    match = 0;
			    break;
			}
			if(a1->chmode != a2->chmode) {
			    match = 0;
			    break;
			} else if(a1->chmode) {
			    if(memcmp(a1->str, a2->str, a1->num)) {
				match = 0;
				break;
			    }
			} else {
			    while(a1 && a2) {
				if((a1->len != a2->len) || memcmp(a1->str, a2->str, a1->len))
				    break;
				a1 = a1->next;
				a2 = a2->next;
			    }
			    if(a1 || a2) {
				match = 0;
				break;
			    }
			}
		    }
		} else {
		    match = 0;
		}

		if(match) {
		    pattern->next_same = ph->next_same;
		    ph->next_same = pattern;
		    return CL_SUCCESS;
		}
	    }
	}
	ph = ph->next;
    }

    pattern->next = pt->list;
    pt->list = pattern;

    return CL_SUCCESS;
}
int cli_bm_addpatt(struct cli_matcher *root, struct cli_bm_patt *pattern, const char *offset)
{
	uint16_t idx, i;
	const unsigned char *pt = pattern->pattern;
	struct cli_bm_patt *prev, *next = NULL;
	int ret;


    if(pattern->length < BM_MIN_LENGTH) {
	cli_errmsg("cli_bm_addpatt: Signature for %s is too short\n", pattern->virname);
	return CL_EMALFDB;
    }

    if((ret = cli_caloff(offset, NULL, root->type, pattern->offdata, &pattern->offset_min, &pattern->offset_max))) {
	cli_errmsg("cli_bm_addpatt: Can't calculate offset for signature %s\n", pattern->virname);
	return ret;
    }
    if(pattern->offdata[0] != CLI_OFF_ANY) {
	if(pattern->offdata[0] == CLI_OFF_ABSOLUTE)
	    root->bm_absoff_num++;
	else
	    root->bm_reloff_num++;
    }

    /* bm_offmode doesn't use the prefilter for BM signatures anyway, so
     * don't add these to the filter. */
    if(root->filter && !root->bm_offmode) {
	/* the bm_suffix load balancing below can shorten the sig,
	 * we want to see the entire signature! */
	if (filter_add_static(root->filter, pattern->pattern, pattern->length, pattern->virname) == -1) {
	    cli_warnmsg("cli_bm_addpatt: cannot use filter for trie\n");
	    mpool_free(root->mempool, root->filter);
	    root->filter = NULL;
	}
	/* TODO: should this affect maxpatlen? */
    }

#if BM_MIN_LENGTH == BM_BLOCK_SIZE
    /* try to load balance bm_suffix (at the cost of bm_shift) */
    for(i = 0; i < pattern->length - BM_BLOCK_SIZE + 1; i++) {
	idx = HASH(pt[i], pt[i + 1], pt[i + 2]);
	if(!root->bm_suffix[idx]) {
	    if(i) {
		pattern->prefix = pattern->pattern;
		pattern->prefix_length = i;
		pattern->pattern = &pattern->pattern[i];
		pattern->length -= i;
		pt = pattern->pattern;
	    }
	    break;
	}
    }
#endif

    for(i = 0; i <= BM_MIN_LENGTH - BM_BLOCK_SIZE; i++) {
	idx = HASH(pt[i], pt[i + 1], pt[i + 2]);
	root->bm_shift[idx] = MIN(root->bm_shift[idx], BM_MIN_LENGTH - BM_BLOCK_SIZE - i);
    }

    prev = next = root->bm_suffix[idx];
    while(next) {
	if(pt[0] >= next->pattern0)
	    break;
	prev = next;
	next = next->next;
    }

    if(next == root->bm_suffix[idx]) {
	pattern->next = root->bm_suffix[idx];
	if(root->bm_suffix[idx])
	    pattern->cnt = root->bm_suffix[idx]->cnt;
	root->bm_suffix[idx] = pattern;
    } else {
	pattern->next = prev->next;
	prev->next = pattern;
    }
    pattern->pattern0 = pattern->pattern[0];
    root->bm_suffix[idx]->cnt++;

    if(root->bm_offmode) {
	root->bm_pattab = (struct cli_bm_patt **) mpool_realloc2(root->mempool, root->bm_pattab, (root->bm_patterns + 1) * sizeof(struct cli_bm_patt *));
	if(!root->bm_pattab) {
	    cli_errmsg("cli_bm_addpatt: Can't allocate memory for root->bm_pattab\n");
	    return CL_EMEM;
	}
	root->bm_pattab[root->bm_patterns] = pattern;
	if(pattern->offdata[0] != CLI_OFF_ABSOLUTE)
	    pattern->offset_min = root->bm_patterns;
    }

    root->bm_patterns++;
    return CL_SUCCESS;
}