From 8159347d05eb93cf7c0997f0db57f40c45a184cf Mon Sep 17 00:00:00 2001 From: Nikolay Shirokovskiy <nshirokovskiy@tarantool.org> Date: Thu, 21 Sep 2023 12:56:14 +0300 Subject: [PATCH] misc: avoid allocations of size 0 for region Regular region implementation supports allocations of size 0 with no extra efforts. It returns a non-NULL pointer in this case. However in case of ASAN friendly implementation it will require a special care for this case. Instead let's avaid allocations if size 0 for region. Also use xregion_ macros for allocations. Our current policy is to panic on OOM on runtime allocations. Part of tarantool/tarantool#7327 NO_TEST=internal NO_CHANGELOG=internal NO_DOC=internal --- src/box/alter.cc | 14 +++++--------- src/box/index_def.c | 12 ++++-------- src/box/index_def.h | 3 +-- src/box/lua/key_def.c | 9 ++------- src/box/memtx_space.c | 4 ---- src/box/service_engine.c | 4 ---- src/box/sql/build.c | 8 ++++++-- src/box/sql/func.c | 4 +++- src/box/sql/select.c | 11 ++++++++--- src/box/sysview.c | 4 ---- src/box/vinyl.c | 13 ++++--------- src/box/vy_point_lookup.c | 11 ++++------- src/box/xrow_update.c | 12 ++++++++---- src/lib/mpstream/mpstream.c | 3 ++- 14 files changed, 47 insertions(+), 65 deletions(-) diff --git a/src/box/alter.cc b/src/box/alter.cc index bcd2a1b544..4823ae7b40 100644 --- a/src/box/alter.cc +++ b/src/box/alter.cc @@ -2460,16 +2460,12 @@ on_replace_dd_space(struct trigger * /* trigger */, void *event) * these fields become optional - index * comparators must be updated. */ - struct key_def **keys; - size_t bsize; + struct key_def **keys = NULL; RegionGuard region_guard(&fiber()->gc); - keys = region_alloc_array(&fiber()->gc, typeof(keys[0]), - old_space->index_count, &bsize); - if (keys == NULL) { - diag_set(OutOfMemory, bsize, "region_alloc_array", - "keys"); - return -1; - } + if (old_space->index_count > 0) + keys = xregion_alloc_array(&fiber()->gc, + typeof(keys[0]), + old_space->index_count); for (uint32_t i = 0; i < old_space->index_count; ++i) keys[i] = old_space->index[i]->def->key_def; alter->new_min_field_count = diff --git a/src/box/index_def.c b/src/box/index_def.c index 20e51254e5..60926ebc1c 100644 --- a/src/box/index_def.c +++ b/src/box/index_def.c @@ -252,15 +252,11 @@ index_def_to_key_def(struct rlist *index_defs, int *size) struct index_def *index_def; rlist_foreach_entry(index_def, index_defs, link) key_count++; - size_t bsize; - struct key_def **keys = - region_alloc_array(&fiber()->gc, typeof(keys[0]), key_count, - &bsize); - if (keys == NULL) { - diag_set(OutOfMemory, bsize, "region_alloc_array", "keys"); - return NULL; - } *size = key_count; + if (key_count == 0) + return NULL; + struct key_def **keys = + xregion_alloc_array(&fiber()->gc, typeof(keys[0]), key_count); key_count = 0; rlist_foreach_entry(index_def, index_defs, link) keys[key_count++] = index_def->key_def; diff --git a/src/box/index_def.h b/src/box/index_def.h index 05ab1fc33a..ab57088287 100644 --- a/src/box/index_def.h +++ b/src/box/index_def.h @@ -398,8 +398,7 @@ index_def_new(uint32_t space_id, uint32_t iid, const char *name, * * @param index_defs List head. * @param[out] size Array size. - * @retval not NULL Array of pointers to key_def - * @retval NULL Memory error. + * @retval Array of pointers to key_def (NULL if size == 0). */ struct key_def ** index_def_to_key_def(struct rlist *index_defs, int *size); diff --git a/src/box/lua/key_def.c b/src/box/lua/key_def.c index 2ea239f4a6..80c7d2d28a 100644 --- a/src/box/lua/key_def.c +++ b/src/box/lua/key_def.c @@ -494,18 +494,13 @@ lbox_key_def_new(struct lua_State *L) struct region *region = &fiber()->gc; size_t region_svp = region_used(region); - size_t size; - struct key_part_def *parts = - region_alloc_array(region, typeof(parts[0]), part_count, &size); - if (parts == NULL) { - diag_set(OutOfMemory, size, "region_alloc_array", "parts"); - return luaT_error(L); - } if (part_count == 0) { diag_set(IllegalParams, "Key definition can only be constructed" " by using at least 1 key_part"); return luaT_error(L); } + struct key_part_def *parts = + xregion_alloc_array(region, typeof(parts[0]), part_count); for (uint32_t i = 0; i < part_count; ++i) { lua_pushinteger(L, i + 1); diff --git a/src/box/memtx_space.c b/src/box/memtx_space.c index 04476eeca8..67bfa0b632 100644 --- a/src/box/memtx_space.c +++ b/src/box/memtx_space.c @@ -1416,10 +1416,6 @@ memtx_space_new(struct memtx_engine *memtx, int key_count = 0; size_t region_svp = region_used(&fiber()->gc); struct key_def **keys = index_def_to_key_def(key_list, &key_count); - if (keys == NULL) { - free(memtx_space); - return NULL; - } struct tuple_format *format = space_tuple_format_new(&memtx_tuple_format_vtab, memtx, keys, key_count, def); diff --git a/src/box/service_engine.c b/src/box/service_engine.c index 65b48f2f29..af48c36dba 100644 --- a/src/box/service_engine.c +++ b/src/box/service_engine.c @@ -65,10 +65,6 @@ service_engine_create_space(struct engine *engine, struct space_def *def, int key_count = 0; size_t region_svp = region_used(&fiber()->gc); struct key_def **keys = index_def_to_key_def(key_list, &key_count); - if (keys == NULL) { - free(space); - return NULL; - } struct tuple_format *format = space_tuple_format_new(&tuple_format_runtime->vtab, NULL, keys, key_count, def); diff --git a/src/box/sql/build.c b/src/box/sql/build.c index cf4cacf611..0d032f2f16 100644 --- a/src/box/sql/build.c +++ b/src/box/sql/build.c @@ -276,8 +276,12 @@ sql_shallow_space_copy(struct Parse *parse, struct space *space) struct space *ret = sql_template_space_new(parse, space->def->name); ret->index_count = space->index_count; ret->index_id_max = space->index_id_max; - ret->index = xregion_alloc_array(&parse->region, typeof(struct index *), - space->index_count); + if (space->index_count > 0) + ret->index = xregion_alloc_array(&parse->region, + struct index *, + space->index_count); + else + ret->index = NULL; memcpy(ret->index, space->index, sizeof(struct index *) * space->index_count); memcpy(ret->def, space->def, sizeof(struct space_def)); diff --git a/src/box/sql/func.c b/src/box/sql/func.c index e95118b778..4693eececb 100644 --- a/src/box/sql/func.c +++ b/src/box/sql/func.c @@ -517,7 +517,9 @@ func_trim_str(struct sql_context *ctx, int argc, const struct Mem *argv) struct region *region = &fiber()->gc; size_t svp = region_used(region); - uint8_t *chars_len = xregion_alloc(region, chars_size); + uint8_t *chars_len = NULL; + if (chars_size > 0) + chars_len = xregion_alloc(region, chars_size); size_t chars_count = 0; int32_t offset = 0; diff --git a/src/box/sql/select.c b/src/box/sql/select.c index 71c53b107c..5649e36e25 100644 --- a/src/box/sql/select.c +++ b/src/box/sql/select.c @@ -2054,9 +2054,14 @@ sqlColumnsFromExprList(Parse * parse, ExprList * expr_list, */ assert(space_def->fields == NULL); struct region *region = &parse->region; - space_def->fields = - xregion_alloc_array(region, typeof(space_def->fields[0]), - column_count); + if (column_count > 0) { + space_def->fields = + xregion_alloc_array(region, + typeof(space_def->fields[0]), + column_count); + } else { + space_def->fields = NULL; + } for (uint32_t i = 0; i < column_count; i++) { memcpy(&space_def->fields[i], &field_def_default, sizeof(field_def_default)); diff --git a/src/box/sysview.c b/src/box/sysview.c index 6b3dfd790d..77e21233c9 100644 --- a/src/box/sysview.c +++ b/src/box/sysview.c @@ -538,10 +538,6 @@ sysview_engine_create_space(struct engine *engine, struct space_def *def, */ size_t region_svp = region_used(&fiber()->gc); struct key_def **keys = index_def_to_key_def(key_list, &key_count); - if (keys == NULL) { - free(space); - return NULL; - } struct tuple_format *format = space_tuple_format_new(NULL, NULL, keys, key_count, def); region_truncate(&fiber()->gc, region_svp); diff --git a/src/box/vinyl.c b/src/box/vinyl.c index 6a5c1b1980..17c014e94a 100644 --- a/src/box/vinyl.c +++ b/src/box/vinyl.c @@ -622,16 +622,11 @@ vinyl_engine_create_space(struct engine *engine, struct space_def *def, struct index_def *index_def; rlist_foreach_entry(index_def, key_list, link) key_count++; - struct key_def **keys; - size_t size; + struct key_def **keys = NULL; size_t region_svp = region_used(&fiber()->gc); - keys = region_alloc_array(&fiber()->gc, typeof(keys[0]), key_count, - &size); - if (keys == NULL) { - diag_set(OutOfMemory, size, "region_alloc_array", "keys"); - free(space); - return NULL; - } + if (key_count > 0) + keys = xregion_alloc_array(&fiber()->gc, typeof(keys[0]), + key_count); key_count = 0; rlist_foreach_entry(index_def, key_list, link) keys[key_count++] = index_def->key_def; diff --git a/src/box/vy_point_lookup.c b/src/box/vy_point_lookup.c index 119a8d2028..af625dae25 100644 --- a/src/box/vy_point_lookup.c +++ b/src/box/vy_point_lookup.c @@ -185,15 +185,12 @@ vy_point_lookup_scan_slices(struct vy_lsm *lsm, const struct vy_read_view **rv, ITER_EQ, key); assert(range != NULL); int slice_count = range->slice_count; - size_t size; size_t region_svp = region_used(&fiber()->gc); + if (slice_count == 0) + return 0; struct vy_slice **slices = - region_alloc_array(&fiber()->gc, typeof(slices[0]), slice_count, - &size); - if (slices == NULL) { - diag_set(OutOfMemory, size, "region_alloc_array", "slices"); - return -1; - } + xregion_alloc_array(&fiber()->gc, typeof(slices[0]), + slice_count); int i = 0; struct vy_slice *slice; rlist_foreach_entry(slice, &range->slices, in_range) { diff --git a/src/box/xrow_update.c b/src/box/xrow_update.c index 9b3217a6a8..81a5dd43aa 100644 --- a/src/box/xrow_update.c +++ b/src/box/xrow_update.c @@ -167,10 +167,14 @@ xrow_update_read_ops(struct xrow_update *update, const char *expr, return -1; } - int size = update->op_count * sizeof(update->ops[0]); - update->ops = (struct xrow_update_op *) - xregion_aligned_alloc(&fiber()->gc, size, - alignof(struct xrow_update_op)); + if (update->op_count > 0) { + update->ops = (struct xrow_update_op *) + xregion_alloc_array(&fiber()->gc, + typeof(update->ops[0]), + update->op_count); + } else { + update->ops = NULL; + } struct xrow_update_op *op = update->ops; struct xrow_update_op *ops_end = op + update->op_count; for (int i = 1; op < ops_end; op++, i++) { diff --git a/src/lib/mpstream/mpstream.c b/src/lib/mpstream/mpstream.c index 0c4274bf63..3cff2dad96 100644 --- a/src/lib/mpstream/mpstream.c +++ b/src/lib/mpstream/mpstream.c @@ -29,7 +29,8 @@ mpstream_panic_cb(void *error_ctx) void mpstream_reserve_slow(struct mpstream *stream, size_t size) { - stream->alloc(stream->ctx, stream->pos - stream->buf); + if (stream->pos != stream->buf) + stream->alloc(stream->ctx, stream->pos - stream->buf); stream->buf = stream->reserve(stream->ctx, &size); if (stream->buf == NULL) { diag_set(OutOfMemory, size, "mpstream", "reserve"); -- GitLab