unsigned long long pool_total_used(void);
void pool_flush(struct pool_head *pool);
void pool_gc(struct pool_head *pool_ctx);
-struct pool_head *create_pool_with_loc(const char *name, unsigned int size, unsigned int align,
+struct pool_head *create_pool_with_loc(const char *name, ullong size, unsigned int align,
unsigned int flags, const char *file, unsigned int line);
struct pool_head *create_pool_from_reg(const char *name, struct pool_registration *reg);
void create_pool_callback(struct pool_head **ptr, char *name, struct pool_registration *reg);
* registration struct. Use create_pool() instead which does it for free.
* The alignment will be stored as-is in the registration.
*/
-struct pool_head *create_pool_with_loc(const char *name, unsigned int size,
+struct pool_head *create_pool_with_loc(const char *name, ullong size,
unsigned int align, unsigned int flags,
const char *file, unsigned int line)
{
{
unsigned int extra_mark, extra_caller, extra;
unsigned int flags = reg->flags;
- unsigned int size = reg->size;
+ ullong reg_size = reg->size; // copy of the originally requested size
+ ullong size = reg_size;
unsigned int alignment = reg->align;
struct pool_head *pool = NULL;
struct pool_head *entry;
extra_caller = (pool_debugging & POOL_DBG_CALLER) ? POOL_EXTRA_CALLER : 0;
extra = extra_mark + extra_caller;
+ if (size > 0xFFFFFFFFULL || (size + extra) > 0xFFFFFFFFULL || (uint)(size + extra) < (uint)reg_size)
+ goto ovf;
+
if (!(pool_debugging & POOL_DBG_NO_CACHE)) {
/* we'll store two lists there, we need the room for this. Let's
* make sure it's always OK even when including the extra word
*/
if (!(flags & MEM_F_EXACT)) {
align = (pool_debugging & POOL_DBG_TAG) ? sizeof(void *) : 16;
- size = ((size + align - 1) & -align);
+ size = ((size + align - 1) & -(ullong)align);
}
if (pool_debugging & POOL_DBG_BACKUP) {
extra += size;
}
+ if (size > 0xFFFFFFFFULL || (size + extra) > 0xFFFFFFFFULL || (uint)(size + extra) < (uint)reg_size)
+ goto ovf;
+
/* TODO: thread: we do not lock pool list for now because all pools are
* created during HAProxy startup (so before threads creation) */
start = &pools;
fail:
return pool;
+ ovf:
+ ha_alert("Failed to create pool '%s' of size '%llu': overflow detected due to too large "
+ "a configured size and/or configured pool options. Aborting.\n",
+ name, reg_size);
+ return NULL;
}
/* Tries to allocate an object for the pool <pool> using the system's allocator
struct pool_registration *reg;
list_for_each_entry(reg, &ctx->pool_info[i].entry->regs, list) {
- chunk_appendf(&trash, " > %-12s: size=%u flags=%#x align=%u", reg->name, reg->size, reg->flags, reg->align);
+ chunk_appendf(&trash, " > %-12s: size=%llu flags=%#x align=%u", reg->name, reg->size, reg->flags, reg->align);
if (reg->file && reg->line)
chunk_appendf(&trash, " [%s:%u]", reg->file, reg->line);
chunk_appendf(&trash, "\n");
{
*ptr = create_pool_from_reg(name, reg);
if (!*ptr) {
- ha_alert("Failed to allocate pool '%s' of size %u : %s. Aborting.\n",
+ ha_alert("Failed to allocate pool '%s' of size %llu : %s. Aborting.\n",
name, reg->size, strerror(errno));
exit(1);
}