/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
/* @UNSAFE: whole file */
#include "lib.h"
#include "safe-memset.h"
#include "mempool.h"
#ifndef DEBUG
#else
# define POOL_ALLOCONLY_MAX_EXTRA \
#endif
struct alloconly_pool {
int refcount;
#ifdef DEBUG
const char *name;
bool disable_warning;
#endif
bool clean_frees;
};
struct pool_block {
/* unsigned char data[]; */
};
((unsigned char *) (block) + SIZEOF_POOLBLOCK)
#ifdef DEBUG
#else
# define SENTRY_COUNT 0
# define CLEAR_CHR 0
#endif
};
.v = &static_alloconly_pool_vfuncs,
.alloconly_pool = TRUE,
};
#ifdef DEBUG
{
for (i = 0; i < used_size; ) {
i_panic("mempool-alloconly: saved alloc size broken");
i += MEM_ALIGN(sizeof(alloc_size));
i += alloc_size;
for (; i < max_pos; i++) {
i_panic("mempool-alloconly: buffer overflow");
}
}
if (i != used_size)
i_panic("mempool-alloconly: used_size wrong");
/* The unused data must be NULs */
if (data[i] != '\0')
i_unreached();
}
}
#endif
{
#ifdef DEBUG
sizeof(size_t)*2;
#endif
/* create a fake alloconly_pool so we can call block_alloc() */
/* now allocate the actual alloconly_pool from the created block */
#ifdef DEBUG
}
/* set base_size so p_clear() doesn't trash alloconly_pool structure. */
#endif
/* the first pool allocations must be from the first block */
}
{
return pool;
}
{
void *block;
/* destroy all but the last block */
/* destroy the last block */
#ifdef DEBUG
#else
if (apool->clean_frees) {
}
#endif
}
{
#ifdef DEBUG
#else
return "alloconly";
#endif
}
{
}
{
/* erase the pointer before freeing anything, as the pointer may
exist inside the pool's memory area */
return;
}
{
/* each block is at least twice the size of the previous one */
/* avoid crashing in nearest_power() if size is too large */
/* nearest_power() could have grown size to SSIZE_T_MAX+1 */
#ifdef DEBUG
if (!apool->disable_warning) {
/* i_debug() overwrites unallocated data in data
stack, so make sure everything is allocated before
calling it. */
}
#endif
}
"): Out of memory", size);
}
}
{
void *mem;
#ifndef DEBUG
#else
#endif
/* we need a new block */
}
#ifdef DEBUG
/* write CLEAR_CHRs to sentry */
#endif
return mem;
}
{
/* we can free only the last allocation */
}
}
{
/* see if we want to grow the memory we allocated last */
/* yeah, see if we can grow */
/* just shrink the available size */
return TRUE;
}
}
return FALSE;
}
{
unsigned char *new_mem;
return mem;
/* see if we can directly grow it */
/* slow way - allocate + copy */
}
return mem;
}
{
#ifdef DEBUG
#endif
/* destroy all blocks but the oldest, which contains the
struct alloconly_pool allocation. */
#ifdef DEBUG
#else
if (apool->clean_frees) {
}
#endif
}
/* clear the first block */
#ifdef DEBUG
#else
#endif
}
{
}
{
return size;
}
{
return size;
}