Prevention of freeing non-freeable memory pool block.

This commit is contained in:
Igor Sysoev
2018-04-20 19:46:36 +03:00
parent ad36c8ca8d
commit b95d5b8882

View File

@@ -89,6 +89,7 @@ typedef enum {
typedef struct { typedef struct {
NXT_RBTREE_NODE (node); NXT_RBTREE_NODE (node);
nxt_mp_block_type_t type:8; nxt_mp_block_type_t type:8;
uint8_t freeable;
/* Block size must be less than 4G. */ /* Block size must be less than 4G. */
uint32_t size; uint32_t size;
@@ -150,7 +151,8 @@ static void *nxt_mp_get_small(nxt_mp_t *mp, nxt_queue_t *pages, size_t size);
static nxt_mp_page_t *nxt_mp_alloc_page(nxt_mp_t *mp); static nxt_mp_page_t *nxt_mp_alloc_page(nxt_mp_t *mp);
static nxt_mp_block_t *nxt_mp_alloc_cluster(nxt_mp_t *mp); static nxt_mp_block_t *nxt_mp_alloc_cluster(nxt_mp_t *mp);
#endif #endif
static void *nxt_mp_alloc_large(nxt_mp_t *mp, size_t alignment, size_t size); static void *nxt_mp_alloc_large(nxt_mp_t *mp, size_t alignment, size_t size,
nxt_bool_t freeable);
static intptr_t nxt_mp_rbtree_compare(nxt_rbtree_node_t *node1, static intptr_t nxt_mp_rbtree_compare(nxt_rbtree_node_t *node1,
nxt_rbtree_node_t *node2); nxt_rbtree_node_t *node2);
static nxt_mp_block_t *nxt_mp_find_block(nxt_rbtree_t *tree, u_char *p); static nxt_mp_block_t *nxt_mp_find_block(nxt_rbtree_t *tree, u_char *p);
@@ -395,12 +397,12 @@ nxt_mp_alloc(nxt_mp_t *mp, size_t size)
p = nxt_mp_alloc_small(mp, size); p = nxt_mp_alloc_small(mp, size);
} else { } else {
p = nxt_mp_alloc_large(mp, NXT_MAX_ALIGNMENT, size); p = nxt_mp_alloc_large(mp, NXT_MAX_ALIGNMENT, size, 1);
} }
#else #else
p = nxt_mp_alloc_large(mp, NXT_MAX_ALIGNMENT, size); p = nxt_mp_alloc_large(mp, NXT_MAX_ALIGNMENT, size, 1);
#endif #endif
@@ -444,12 +446,12 @@ nxt_mp_align(nxt_mp_t *mp, size_t alignment, size_t size)
p = nxt_mp_alloc_small(mp, aligned_size); p = nxt_mp_alloc_small(mp, aligned_size);
} else { } else {
p = nxt_mp_alloc_large(mp, alignment, size); p = nxt_mp_alloc_large(mp, alignment, size, 1);
} }
#else #else
p = nxt_mp_alloc_large(mp, alignment, size); p = nxt_mp_alloc_large(mp, alignment, size, 1);
#endif #endif
@@ -706,7 +708,8 @@ nxt_mp_alloc_cluster(nxt_mp_t *mp)
static void * static void *
nxt_mp_alloc_large(nxt_mp_t *mp, size_t alignment, size_t size) nxt_mp_alloc_large(nxt_mp_t *mp, size_t alignment, size_t size,
nxt_bool_t freeable)
{ {
u_char *p; u_char *p;
size_t aligned_size; size_t aligned_size;
@@ -747,6 +750,7 @@ nxt_mp_alloc_large(nxt_mp_t *mp, size_t alignment, size_t size)
} }
block->type = type; block->type = type;
block->freeable = freeable;
block->size = size; block->size = size;
block->start = p; block->start = p;
@@ -790,6 +794,8 @@ nxt_mp_free(nxt_mp_t *mp, void *p)
} }
} else if (nxt_fast_path(p == block->start)) { } else if (nxt_fast_path(p == block->start)) {
if (block->freeable) {
nxt_rbtree_delete(&mp->blocks, &block->node); nxt_rbtree_delete(&mp->blocks, &block->node);
if (block->type == NXT_MP_DISCRETE_BLOCK) { if (block->type == NXT_MP_DISCRETE_BLOCK) {
@@ -799,6 +805,9 @@ nxt_mp_free(nxt_mp_t *mp, void *p)
nxt_free(p); nxt_free(p);
return; return;
}
err = "freed pointer points to non-freeable block: %p";
} else { } else {
err = "freed pointer points to middle of block: %p"; err = "freed pointer points to middle of block: %p";
@@ -859,7 +868,7 @@ nxt_mp_chunk_free(nxt_mp_t *mp, nxt_mp_block_t *cluster, u_char *p)
} }
if (nxt_slow_path(page->size == 0xFF)) { if (nxt_slow_path(page->size == 0xFF)) {
return "freed pointer points to non-freeble page: %p"; return "freed pointer points to non-freeable page: %p";
} }
size = page->size << mp->chunk_size_shift; size = page->size << mp->chunk_size_shift;
@@ -963,12 +972,12 @@ nxt_mp_nget(nxt_mp_t *mp, size_t size)
p = nxt_mp_get_small(mp, &mp->nget_pages, size); p = nxt_mp_get_small(mp, &mp->nget_pages, size);
} else { } else {
p = nxt_mp_alloc_large(mp, NXT_MAX_ALIGNMENT, size); p = nxt_mp_alloc_large(mp, NXT_MAX_ALIGNMENT, size, 0);
} }
#else #else
p = nxt_mp_alloc_large(mp, NXT_MAX_ALIGNMENT, size); p = nxt_mp_alloc_large(mp, NXT_MAX_ALIGNMENT, size, 0);
#endif #endif
@@ -990,12 +999,12 @@ nxt_mp_get(nxt_mp_t *mp, size_t size)
p = nxt_mp_get_small(mp, &mp->get_pages, size); p = nxt_mp_get_small(mp, &mp->get_pages, size);
} else { } else {
p = nxt_mp_alloc_large(mp, NXT_MAX_ALIGNMENT, size); p = nxt_mp_alloc_large(mp, NXT_MAX_ALIGNMENT, size, 0);
} }
#else #else
p = nxt_mp_alloc_large(mp, NXT_MAX_ALIGNMENT, size); p = nxt_mp_alloc_large(mp, NXT_MAX_ALIGNMENT, size, 0);
#endif #endif