mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-01 23:25:38 +00:00
ISC_MEM_FILL was corrupting memory when the block being allocated or freed
was bigger than the memory context's max size. Force alignment to 8 bytes, since some otherwise 32-bit platforms have a 64 bit "long long".
This commit is contained in:
@@ -54,6 +54,17 @@
|
|||||||
#define ISC_MEMPOOL_NAMES 1
|
#define ISC_MEMPOOL_NAMES 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Constants.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DEF_MAX_SIZE 1100
|
||||||
|
#define DEF_MEM_TARGET 4096
|
||||||
|
#define ALIGNMENT_SIZE 8
|
||||||
|
#define NUM_BASIC_BLOCKS 64 /* must be > 1 */
|
||||||
|
#define TABLE_INCREMENT 1024
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Types.
|
* Types.
|
||||||
*/
|
*/
|
||||||
@@ -63,10 +74,13 @@ typedef struct {
|
|||||||
} element;
|
} element;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t size;
|
|
||||||
/*
|
/*
|
||||||
* This structure must be ALIGNMENT_SIZE bytes.
|
* This structure must be ALIGNMENT_SIZE bytes.
|
||||||
*/
|
*/
|
||||||
|
union {
|
||||||
|
size_t size;
|
||||||
|
char bytes[ALIGNMENT_SIZE];
|
||||||
|
} u;
|
||||||
} size_info;
|
} size_info;
|
||||||
|
|
||||||
struct stats {
|
struct stats {
|
||||||
@@ -127,21 +141,17 @@ struct isc_mempool {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Forward. */
|
/*
|
||||||
|
* Forward.
|
||||||
|
*/
|
||||||
|
|
||||||
static inline size_t quantize(size_t);
|
static inline size_t quantize(size_t);
|
||||||
static inline void mem_putunlocked(isc_mem_t *, void *, size_t);
|
static inline void mem_putunlocked(isc_mem_t *, void *, size_t);
|
||||||
static inline void * mem_getunlocked(isc_mem_t *, size_t);
|
static inline void * mem_getunlocked(isc_mem_t *, size_t);
|
||||||
|
|
||||||
/* Constants. */
|
/*
|
||||||
|
* Private Inline-able.
|
||||||
#define DEF_MAX_SIZE 1100
|
*/
|
||||||
#define DEF_MEM_TARGET 4096
|
|
||||||
#define ALIGNMENT_SIZE sizeof (void *)
|
|
||||||
#define NUM_BASIC_BLOCKS 64 /* must be > 1 */
|
|
||||||
#define TABLE_INCREMENT 1024
|
|
||||||
|
|
||||||
/* Private Inline-able. */
|
|
||||||
|
|
||||||
static inline size_t
|
static inline size_t
|
||||||
quantize(size_t size) {
|
quantize(size_t size) {
|
||||||
@@ -157,7 +167,9 @@ quantize(size_t size) {
|
|||||||
return (temp - temp % ALIGNMENT_SIZE);
|
return (temp - temp % ALIGNMENT_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Private. */
|
/*
|
||||||
|
* Private.
|
||||||
|
*/
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
default_memalloc(void *arg, size_t size) {
|
default_memalloc(void *arg, size_t size) {
|
||||||
@@ -171,7 +183,9 @@ default_memfree(void *arg, void *ptr) {
|
|||||||
free(ptr);
|
free(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Public. */
|
/*
|
||||||
|
* Public.
|
||||||
|
*/
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
isc_mem_createx(size_t init_max_size, size_t target_size,
|
isc_mem_createx(size_t init_max_size, size_t target_size,
|
||||||
@@ -391,6 +405,12 @@ mem_getunlocked(isc_mem_t *ctx, size_t size)
|
|||||||
ctx->total += size;
|
ctx->total += size;
|
||||||
ctx->stats[ctx->max_size].gets++;
|
ctx->stats[ctx->max_size].gets++;
|
||||||
ctx->stats[ctx->max_size].totalgets++;
|
ctx->stats[ctx->max_size].totalgets++;
|
||||||
|
/*
|
||||||
|
* If we don't set new_size to size, then the
|
||||||
|
* ISC_MEM_FILL code might write over bytes we
|
||||||
|
* don't own.
|
||||||
|
*/
|
||||||
|
new_size = size;
|
||||||
}
|
}
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@@ -472,12 +492,11 @@ mem_putunlocked(isc_mem_t *ctx, void *mem, size_t size)
|
|||||||
{
|
{
|
||||||
size_t new_size = quantize(size);
|
size_t new_size = quantize(size);
|
||||||
|
|
||||||
#if ISC_MEM_FILL
|
|
||||||
memset(mem, 0xde, new_size); /* Mnemonic for "dead". */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (size == ctx->max_size || new_size >= ctx->max_size) {
|
if (size == ctx->max_size || new_size >= ctx->max_size) {
|
||||||
/* memput() called on something beyond our upper limit */
|
/* memput() called on something beyond our upper limit */
|
||||||
|
#if ISC_MEM_FILL
|
||||||
|
memset(mem, 0xde, size); /* Mnemonic for "dead". */
|
||||||
|
#endif
|
||||||
(ctx->memfree)(ctx->arg, mem);
|
(ctx->memfree)(ctx->arg, mem);
|
||||||
INSIST(ctx->stats[ctx->max_size].gets != 0);
|
INSIST(ctx->stats[ctx->max_size].gets != 0);
|
||||||
ctx->stats[ctx->max_size].gets--;
|
ctx->stats[ctx->max_size].gets--;
|
||||||
@@ -486,6 +505,10 @@ mem_putunlocked(isc_mem_t *ctx, void *mem, size_t size)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ISC_MEM_FILL
|
||||||
|
memset(mem, 0xde, new_size); /* Mnemonic for "dead". */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* The free list uses the "rounded-up" size "new_size": */
|
/* The free list uses the "rounded-up" size "new_size": */
|
||||||
((element *)mem)->next = ctx->freelists[new_size];
|
((element *)mem)->next = ctx->freelists[new_size];
|
||||||
ctx->freelists[new_size] = (element *)mem;
|
ctx->freelists[new_size] = (element *)mem;
|
||||||
@@ -603,7 +626,7 @@ isc_mem_allocate(isc_mem_t *ctx, size_t size) {
|
|||||||
si = isc_mem_get(ctx, size);
|
si = isc_mem_get(ctx, size);
|
||||||
if (si == NULL)
|
if (si == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
si->size = size;
|
si->u.size = size;
|
||||||
return (&si[1]);
|
return (&si[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -612,7 +635,7 @@ isc_mem_free(isc_mem_t *ctx, void *ptr) {
|
|||||||
size_info *si;
|
size_info *si;
|
||||||
|
|
||||||
si = &(((size_info *)ptr)[-1]);
|
si = &(((size_info *)ptr)[-1]);
|
||||||
isc_mem_put(ctx, si, si->size);
|
isc_mem_put(ctx, si, si->u.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user