From 879b70267452ed1f913781fd926d02bfb2d3c161 Mon Sep 17 00:00:00 2001 From: Konstantin Osipov <kostja@tarantool.org> Date: Sun, 29 Apr 2012 00:14:16 +0400 Subject: [PATCH] Fix a bug with a crash when slab alloc arena is full. When the slab alloc arena is fully used, and we try to truncate a space, we could crash, since a) we never check return value of salloc() b) we used to salloc() an iterator for truncate(), and it would return NULL, and we would try to access it without a check. The fix is: - to throw exceptions directly from salloc() - to not use salloc() for iterators, since we still should be able to truncate a namespace when the slab alloc arena is full. --- include/salloc.h | 2 +- mod/box/index.m | 4 ++-- mod/box/tree.m | 5 ++--- mod/box/tuple.m | 5 +---- src/salloc.m | 12 +++++++----- 5 files changed, 13 insertions(+), 15 deletions(-) diff --git a/include/salloc.h b/include/salloc.h index 4c9e8773a4..b8545dc717 100644 --- a/include/salloc.h +++ b/include/salloc.h @@ -34,7 +34,7 @@ struct tbuf; bool salloc_init(size_t size, size_t minimal, double factor); void salloc_destroy(void); -void *salloc(size_t size); +void *salloc(size_t size, const char *what); void sfree(void *ptr); void slab_validate(); void slab_stat(struct tbuf *buf); diff --git a/mod/box/index.m b/mod/box/index.m index 9e8af16cb1..f71b398070 100644 --- a/mod/box/index.m +++ b/mod/box/index.m @@ -224,7 +224,7 @@ void hash_iterator_free(struct iterator *iterator) { assert(iterator->next == hash_iterator_next); - sfree(iterator); + free(iterator); } @@ -285,7 +285,7 @@ hash_iterator_free(struct iterator *iterator) - (struct iterator *) allocIterator { - struct hash_iterator *it = salloc(sizeof(struct hash_iterator)); + struct hash_iterator *it = malloc(sizeof(struct hash_iterator)); if (it) { memset(it, 0, sizeof(struct hash_iterator)); it->base.next = hash_iterator_next; diff --git a/mod/box/tree.m b/mod/box/tree.m index 73c35c974d..b256bd31e2 100644 --- a/mod/box/tree.m +++ b/mod/box/tree.m @@ -26,7 +26,6 @@ #include "tree.h" #include "box.h" #include "tuple.h" -#include <salloc.h> #include <pickle.h> /* {{{ Utilities. *************************************************/ @@ -801,7 +800,7 @@ tree_iterator_free(struct iterator *iterator) if (it->iter) sptree_index_iterator_free(it->iter); - sfree(it); + free(it); } /* }}} */ @@ -926,7 +925,7 @@ tree_iterator_free(struct iterator *iterator) - (struct iterator *) allocIterator { struct tree_iterator *it - = salloc(sizeof(struct tree_iterator) + SIZEOF_SPARSE_PARTS(key_def)); + = malloc(sizeof(struct tree_iterator) + SIZEOF_SPARSE_PARTS(key_def)); if (it) { memset(it, 0, sizeof(struct tree_iterator)); diff --git a/mod/box/tuple.m b/mod/box/tuple.m index c6af90b5b0..b7b5512267 100644 --- a/mod/box/tuple.m +++ b/mod/box/tuple.m @@ -39,10 +39,7 @@ struct box_tuple * tuple_alloc(size_t size) { size_t total = sizeof(struct box_tuple) + size; - struct box_tuple *tuple = salloc(total); - - if (tuple == NULL) - tnt_raise(LoggedError, :ER_MEMORY_ISSUE, total, "slab allocator", "tuple"); + struct box_tuple *tuple = salloc(total, "tuple"); tuple->flags = tuple->refs = 0; tuple->bsize = size; diff --git a/src/salloc.m b/src/salloc.m index bb54a13ceb..efe340ab11 100644 --- a/src/salloc.m +++ b/src/salloc.m @@ -38,6 +38,7 @@ #include <util.h> #include <tbuf.h> #include <say.h> +#include "exception.h" #define SLAB_ALIGN_PTR(ptr) (void *)((uintptr_t)(ptr) & ~(SLAB_SIZE - 1)) @@ -258,17 +259,18 @@ valid_item(struct slab *slab, void *item) #endif void * -salloc(size_t size) +salloc(size_t size, const char *what) { struct slab_class *class; struct slab *slab; struct slab_item *item; - if ((class = class_for(size)) == NULL) - return NULL; + if ((class = class_for(size)) == NULL || + (slab = slab_of(class)) == NULL) { - if ((slab = slab_of(class)) == NULL) - return NULL; + tnt_raise(LoggedError, :ER_MEMORY_ISSUE, size, + "slab allocator", what); + } if (slab->free == NULL) { assert(valid_item(slab, slab->brk)); -- GitLab