Skip to content

Commit

Permalink
box: fix null pointer dereference in exact_key_validate
Browse files Browse the repository at this point in the history
Fixed a null pointer dereference in `exact_key_validate`. When you tried
to `get()` with an incorrect key format (`ER_EXACT_MATCH`) in `read_view`
from deleted space, a null pointer was dereferenced and tarantool crashed.

Needed for tarantool/tarantool-ee#787

NO_DOC=bugfix
NO_TEST=ee
  • Loading branch information
Astronomax committed Jun 17, 2024
1 parent 5602c28 commit 1a802a9
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## bugfix/box

* Fixed a null pointer dereference when an `ER_EXACT_MATCH` error occurred on an attempt to call `get()` in a `read_view` from the deleted space. (ghe-787).
11 changes: 3 additions & 8 deletions src/box/index.cc
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,7 @@ error_set_index(struct error *error, const struct index_def *index_def)
{
error_set_str(error, "index", index_def->name);
error_set_uint(error, "index_id", index_def->iid);
struct space *space = space_by_id(index_def->space_id);
error_set_str(error, "space", space->def->name);
error_set_str(error, "space", index_def->space_name);
error_set_uint(error, "space_id", index_def->space_id);
}

Expand Down Expand Up @@ -218,10 +217,8 @@ index_check_dup(struct index *index, struct tuple *old_tuple,
* dup_replace_mode is DUP_REPLACE, and
* a tuple with the same key is not found.
*/
struct space *space = space_by_id(index->def->space_id);
assert(space != NULL);
diag_set(ClientError, ER_CANT_UPDATE_PRIMARY_KEY,
space->def->name, space->def->id,
index->def->space_name, index->def->space_id,
old_tuple, new_tuple, NULL);
return -1;
}
Expand All @@ -234,10 +231,8 @@ index_check_dup(struct index *index, struct tuple *old_tuple,
* possibly delete more than one tuple
* at once.
*/
struct space *space = space_by_id(index->def->space_id);
assert(space != NULL);
diag_set(ClientError, ER_TUPLE_FOUND,
index->def->name, space->def->name,
index->def->name, index->def->space_name,
tuple_str(dup_tuple), tuple_str(new_tuple),
dup_tuple, new_tuple);
return -1;
Expand Down
6 changes: 6 additions & 0 deletions src/box/index_def.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "json/json.h"
#include "fiber.h"
#include "tt_static.h"
#include "space_cache.h"

const char *index_type_strs[] = { "HASH", "TREE", "BITSET", "RTREE" };

Expand Down Expand Up @@ -133,6 +134,7 @@ index_def_new(uint32_t space_id, uint32_t iid, const char *name,
}
def->type = type;
def->space_id = space_id;
def->space_name = NULL;
def->iid = iid;
def->opts = *opts;
return def;
Expand All @@ -144,6 +146,8 @@ index_def_dup(const struct index_def *def)
struct index_def *dup = xmalloc(sizeof(*dup));
*dup = *def;
dup->name = xstrdup(def->name);
if (def->space_name)
dup->space_name = xstrdup(def->space_name);
dup->key_def = key_def_dup(def->key_def);
dup->cmp_def = key_def_dup(def->cmp_def);
dup->pk_def = key_def_dup(def->pk_def);
Expand All @@ -157,6 +161,8 @@ index_def_delete(struct index_def *index_def)
{
index_opts_destroy(&index_def->opts);
free(index_def->name);
if (index_def->space_name)
free(index_def->space_name);

if (index_def->key_def)
key_def_delete(index_def->key_def);
Expand Down
2 changes: 2 additions & 0 deletions src/box/index_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ struct index_def {
uint32_t iid;
/* Space id. */
uint32_t space_id;
/* Space name. */
char *space_name;
/** Index name. */
char *name;
/** Index type. */
Expand Down
31 changes: 11 additions & 20 deletions src/box/key_list.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,50 +63,44 @@ key_list_iterator_create(struct key_list_iterator *it, struct tuple *tuple,
port_destroy(&in_port);
if (rc != 0) {
/* Can't evaluate function. */
struct space *space = space_by_id(index_def->space_id);
diag_add(ClientError, ER_FUNC_INDEX_FUNC, index_def->name,
space ? space_name(space) : "",
"can't evaluate function");
index_def->space_name, "can't evaluate function");
return -1;
}
uint32_t key_data_sz;
const char *key_data = port_get_msgpack(&out_port, &key_data_sz);
port_destroy(&out_port);
if (key_data == NULL) {
struct space *space = space_by_id(index_def->space_id);
/* Can't get a result returned by function . */
diag_add(ClientError, ER_FUNC_INDEX_FUNC, index_def->name,
space ? space_name(space) : "",
diag_add(ClientError, ER_FUNC_INDEX_FUNC,
index_def->name, index_def->space_name,
"can't get a value returned by function");
return -1;
}

it->data_end = key_data + key_data_sz;
assert(mp_typeof(*key_data) == MP_ARRAY);
if (mp_decode_array(&key_data) != 1) {
struct space *space = space_by_id(index_def->space_id);
/*
* Function return doesn't follow the
* convention: to many values were returned.
* i.e. return 1, 2
*/
region_truncate(region, region_svp);
diag_set(ClientError, ER_FUNC_INDEX_FORMAT, index_def->name,
space ? space_name(space) : "",
diag_set(ClientError, ER_FUNC_INDEX_FORMAT,
index_def->name, index_def->space_name,
"to many values were returned");
return -1;
}
if (func->def->opts.is_multikey) {
if (mp_typeof(*key_data) != MP_ARRAY) {
struct space * space = space_by_id(index_def->space_id);
/*
* Multikey function must return an array
* of keys.
*/
region_truncate(region, region_svp);
diag_set(ClientError, ER_FUNC_INDEX_FORMAT,
index_def->name,
space ? space_name(space) : "",
index_def->name, index_def->space_name,
"a multikey function mustn't return a scalar");
return -1;
}
Expand Down Expand Up @@ -138,13 +132,12 @@ key_list_iterator_next(struct key_list_iterator *it, struct tuple **value)
}

if (mp_typeof(*key) != MP_ARRAY) {
struct space *space = space_by_id(it->index_def->space_id);
/*
* A value returned by func_index function is
* not a valid key, i.e. {1}.
*/
diag_set(ClientError, ER_FUNC_INDEX_FORMAT, it->index_def->name,
space ? space_name(space) : "",
diag_set(ClientError, ER_FUNC_INDEX_FORMAT,
it->index_def->name, it->index_def->space_name,
tt_sprintf("supplied key type is invalid: expected %s",
field_type_strs[FIELD_TYPE_ARRAY]));
return -1;
Expand All @@ -153,26 +146,24 @@ key_list_iterator_next(struct key_list_iterator *it, struct tuple **value)
const char *rptr = key;
uint32_t part_count = mp_decode_array(&rptr);
if (part_count != key_def->part_count) {
struct space *space = space_by_id(it->index_def->space_id);
/*
* The key must have exact functional index
* definition's part_count(s).
*/
diag_set(ClientError, ER_FUNC_INDEX_FORMAT, it->index_def->name,
space ? space_name(space) : "",
diag_set(ClientError, ER_FUNC_INDEX_FORMAT,
it->index_def->name, it->index_def->space_name,
tt_sprintf(tnt_errcode_desc(ER_EXACT_MATCH),
key_def->part_count, part_count));
return -1;
}
if (key_validate_parts(key_def, rptr, part_count, true,
&key_end) != 0) {
struct space *space = space_by_id(it->index_def->space_id);
/*
* The key doesn't follow functional index key
* definition.
*/
diag_add(ClientError, ER_FUNC_INDEX_FORMAT, it->index_def->name,
space ? space_name(space) : "",
it->index_def->name, it->index_def->space_name,
"key does not follow functional index definition");
return -1;
}
Expand Down
1 change: 1 addition & 0 deletions src/box/space.c
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,7 @@ space_create(struct space *space, struct engine *engine,
struct index *index = space_create_index(space, index_def);
if (index == NULL)
goto fail_free_indexes;
index->def->space_name = xstrdup(def->name);
space->index_map[index_def->iid] = index;
if (index_def->opts.is_unique)
bit_set(space->check_unique_constraint_map,
Expand Down

0 comments on commit 1a802a9

Please sign in to comment.