diff --git a/core/util.c b/core/util.c index 9e53cabf3e6c0f81ac2d941a5fcc62195c5ad4df..d3032fe877f44e529a636c5bf2a0680261dd741e 100644 --- a/core/util.c +++ b/core/util.c @@ -107,8 +107,9 @@ xrealloc(void *ptr, size_t size) #ifdef ENABLE_BACKTRACE /* - * we use global static buffer because it is too late to do - * any allocation when we are printing bactrace and fiber stack is small + * We use a global static buffer because it is too late to do any + * allocation when we are printing backtrace and fiber stack is + * small. */ static char backtrace_buf[4096 * 4]; diff --git a/mod/silverbox/box.c b/mod/silverbox/box.c index 0432b436a9f604fda40aecae64627ab5f984e235..97d21fe69d52973cf15bc053bf45118b9dfb0775 100644 --- a/mod/silverbox/box.c +++ b/mod/silverbox/box.c @@ -268,17 +268,25 @@ prepare_replace(struct box_txn *txn, size_t cardinality, struct tbuf *data) #endif lock_tuple(txn, txn->old_tuple); } else { + lock_tuple(txn, txn->tuple); /* - * if tuple doesn't exist insert GHOST tuple in indeces - * in order to avoid race condition - * ref count will be incr in commit + * Mark the tuple as ghost before attempting an + * index replace: if it fails, txn_abort() will + * look at the flag and remove the tuple. + */ + txn->tuple->flags |= GHOST; + /* + * If the tuple doesn't exist, insert a GHOST + * tuple in all indices in order to avoid a race + * condition when another INSERT comes along: + * a concurrent INSERT, UPDATE, or DELETE, returns + * an error when meets a ghost tuple. + * + * Tuple reference counter will be incremented in + * txn_commit(). */ - foreach_index(txn->n, index) index->replace(index, NULL, txn->tuple); - - lock_tuple(txn, txn->tuple); - txn->tuple->flags |= GHOST; } return -1; diff --git a/mod/silverbox/index.c b/mod/silverbox/index.c index 268abfd32c328664bcbb7eff61c9a070e910c22a..e31e8c8507c54b71a7ecdcbd5bc14dffb264f530 100644 --- a/mod/silverbox/index.c +++ b/mod/silverbox/index.c @@ -101,7 +101,7 @@ field_compare(struct field *f1, struct field *f2, enum field_data_type type) return -1; } - panic("imposible happend"); + panic("impossible happened"); } @@ -347,6 +347,9 @@ index_replace_hash_num(struct index *self, struct box_tuple *old_tuple, struct b u32 key_size = load_varint32(&key); u32 num = *(u32 *)key; + if (key_size != 4) + box_raise(ERR_CODE_ILLEGAL_PARAMS, "key is not u32"); + if (old_tuple != NULL) { void *old_key = tuple_field(old_tuple, self->key_field->fieldno); load_varint32(&old_key); @@ -354,8 +357,6 @@ index_replace_hash_num(struct index *self, struct box_tuple *old_tuple, struct b assoc_delete(int_ptr_map, self->idx.int_hash, old_num); } - if (key_size != 4) - box_raise(ERR_CODE_ILLEGAL_PARAMS, "key is not u32"); assoc_replace(int_ptr_map, self->idx.int_hash, num, tuple); #ifdef DEBUG say_debug("index_replace_hash_num(self:%p, old_tuple:%p, tuple:%p) key:%i", self, old_tuple, @@ -370,6 +371,9 @@ index_replace_hash_num64(struct index *self, struct box_tuple *old_tuple, struct u32 key_size = load_varint32(&key); u64 num = *(u64 *)key; + if (key_size != 8) + box_raise(ERR_CODE_ILLEGAL_PARAMS, "key is not u64"); + if (old_tuple != NULL) { void *old_key = tuple_field(old_tuple, self->key_field->fieldno); load_varint32(&old_key); @@ -377,8 +381,6 @@ index_replace_hash_num64(struct index *self, struct box_tuple *old_tuple, struct assoc_delete(int64_ptr_map, self->idx.int64_hash, old_num); } - if (key_size != 8) - box_raise(ERR_CODE_ILLEGAL_PARAMS, "key is not u64"); assoc_replace(int64_ptr_map, self->idx.int64_hash, num, tuple); #ifdef DEBUG say_debug("index_replace_hash_num(self:%p, old_tuple:%p, tuple:%p) key:%"PRIu64, self, old_tuple, @@ -391,6 +393,9 @@ index_replace_hash_str(struct index *self, struct box_tuple *old_tuple, struct b { void *key = tuple_field(tuple, self->key_field->fieldno); + if (key == NULL) + box_raise(ERR_CODE_ILLEGAL_PARAMS, "Supplied tuple misses a field which is part of an index"); + if (old_tuple != NULL) { void *old_key = tuple_field(old_tuple, self->key_field->fieldno); assoc_delete(lstr_ptr_map, self->idx.str_hash, old_key); @@ -407,6 +412,9 @@ index_replace_hash_str(struct index *self, struct box_tuple *old_tuple, struct b static void index_replace_tree_str(struct index *self, struct box_tuple *old_tuple, struct box_tuple *tuple) { + if (tuple->cardinality < self->field_cmp_order_cnt) + box_raise(ERR_CODE_ILLEGAL_PARAMS, "Supplied tuple misses a field which is part of an index"); + struct tree_index_member *member = tuple2tree_index_member(self, tuple, NULL); if (old_tuple) diff --git a/test/box_big/sql.result b/test/box_big/sql.result index 0aacd2ae1b46e7d498f66e35bea217886025a90e..1e57a1e562278586922cd9cb82717b0656f06a4f 100644 --- a/test/box_big/sql.result +++ b/test/box_big/sql.result @@ -1,8 +1,8 @@ - -A test case for Bug#729758 -"SELECT fails with a disjunct and small LIMIT" -https://bugs.launchpad.net/tarantool/+bug/729758 - +# +# A test case for Bug#729758 +# "SELECT fails with a disjunct and small LIMIT" +# https://bugs.launchpad.net/tarantool/+bug/729758 +# insert into t0 values ('Doe', 'Richard') Insert OK, 1 row affected insert into t0 values ('Roe', 'Richard') @@ -26,11 +26,11 @@ Found 5 tuples: ['Woe', 'Richard'] ['Major', 'Tomas'] ['Kytes', 'Tomas'] - -A test case for Bug#729879 -"Zero limit is treated the same as no limit" -https://bugs.launchpad.net/tarantool/+bug/729879 - +# +# A test case for Bug#729879 +# "Zero limit is treated the same as no limit" +# https://bugs.launchpad.net/tarantool/+bug/729879 +# select * from t0 where k1='Richard' or k1='Tomas' limit 0 No match delete from t0 where k0='Doe' @@ -49,3 +49,31 @@ delete from t0 where k0='Wales' Delete OK, 1 row affected delete from t0 where k0='Callaghan' Delete OK, 1 row affected +# +# A test case for Bug#730593 +# "Bad data if incomplete tuple" +# https://bugs.launchpad.net/tarantool/+bug/730593 +# Verify that if there is an index on, say, field 2, +# we can't insert tuples with cardinality 1 and +# get away with it. +# +insert into t0 values ('Britney') +An error occurred: ERR_CODE_ILLEGAL_PARAMS, 'Illegal parameters' +select * from t0 where k1='Anything' +No match +insert into t0 values ('Stephanie') +An error occurred: ERR_CODE_ILLEGAL_PARAMS, 'Illegal parameters' +select * from t0 where k1='Anything' +No match +insert into t0 values ('Spears', 'Britney') +Insert OK, 1 row affected +select * from t0 where k0='Spears' +Found 1 tuple: +['Spears', 'Britney'] +select * from t0 where k1='Anything' +No match +select * from t0 where k1='Britney' +Found 1 tuple: +['Spears', 'Britney'] +delete from t0 where k0='Spears' +Delete OK, 1 row affected diff --git a/test/box_big/sql.test b/test/box_big/sql.test index 5d94e8911db648736450ce5e13640cbd75fce905..c49825c0e71132426af794fa8e5afff9e4ab5ed1 100644 --- a/test/box_big/sql.test +++ b/test/box_big/sql.test @@ -1,10 +1,10 @@ # encoding: tarantool # -print """ -A test case for Bug#729758 -"SELECT fails with a disjunct and small LIMIT" -https://bugs.launchpad.net/tarantool/+bug/729758 -""" +print """# +# A test case for Bug#729758 +# "SELECT fails with a disjunct and small LIMIT" +# https://bugs.launchpad.net/tarantool/+bug/729758 +#""" exec sql "insert into t0 values ('Doe', 'Richard')" exec sql "insert into t0 values ('Roe', 'Richard')" @@ -16,11 +16,11 @@ exec sql "insert into t0 values ('Wales', 'Tomas')" exec sql "insert into t0 values ('Callaghan', 'Tomas')" exec sql "select * from t0 where k1='Richard' or k1='Tomas' or k1='Tomas' limit 5" -print """ -A test case for Bug#729879 -"Zero limit is treated the same as no limit" -https://bugs.launchpad.net/tarantool/+bug/729879 -""" +print """# +# A test case for Bug#729879 +# "Zero limit is treated the same as no limit" +# https://bugs.launchpad.net/tarantool/+bug/729879 +#""" exec sql "select * from t0 where k1='Richard' or k1='Tomas' limit 0" # Cleanup @@ -32,4 +32,22 @@ exec sql "delete from t0 where k0='Kytes'" exec sql "delete from t0 where k0='Stiles'" exec sql "delete from t0 where k0='Wales'" exec sql "delete from t0 where k0='Callaghan'" + +print """# +# A test case for Bug#730593 +# "Bad data if incomplete tuple" +# https://bugs.launchpad.net/tarantool/+bug/730593 +# Verify that if there is an index on, say, field 2, +# we can't insert tuples with cardinality 1 and +# get away with it. +#""" +exec sql "insert into t0 values ('Britney')" +exec sql "select * from t0 where k1='Anything'" +exec sql "insert into t0 values ('Stephanie')" +exec sql "select * from t0 where k1='Anything'" +exec sql "insert into t0 values ('Spears', 'Britney')" +exec sql "select * from t0 where k0='Spears'" +exec sql "select * from t0 where k1='Anything'" +exec sql "select * from t0 where k1='Britney'" +exec sql "delete from t0 where k0='Spears'" # vim: syntax=python diff --git a/test/lib/test_suite.py b/test/lib/test_suite.py index 1b04d6a3ea985dc27d7ebbca361ce5b6eb81db89..10f692ee83daaa7accc09377c6c26d882b303fdc 100644 --- a/test/lib/test_suite.py +++ b/test/lib/test_suite.py @@ -219,6 +219,7 @@ class TestSuite: try: server = Server(self.ini["core"], self.ini["module"]) except Exception as e: + print e raise RuntimeError("Unknown server: core = {0}, module = {1}".format( self.ini["core"], self.ini["module"])) server.deploy(self.ini["config"],