From c2f0d0586e621d97ee6e876e360b0b7e677fe44a Mon Sep 17 00:00:00 2001
From: Roman Tokarev <rtokarev@corp.mail.ru>
Date: Tue, 19 Apr 2011 13:12:02 +0400
Subject: [PATCH] A fix and a test case for Bug#735140

A fix and a test case for
http://bugs.launchpad.net/bugs/735140
"Partial REPLACE corrupts index"

Check in validate_indexes if a tuple is long enough to cover
all indexes supported in a namespace.
---
 mod/silverbox/box.c   |  4 ++--
 mod/silverbox/index.c |  5 ++++-
 mod/silverbox/index.h |  2 +-
 test/box/sql.result   | 19 +++++++++++++++++++
 test/box/sql.test     | 23 +++++++++++++++++++++++
 5 files changed, 49 insertions(+), 4 deletions(-)

diff --git a/mod/silverbox/box.c b/mod/silverbox/box.c
index 596b31273e..24f73910b3 100644
--- a/mod/silverbox/box.c
+++ b/mod/silverbox/box.c
@@ -253,7 +253,7 @@ prepare_replace(struct box_txn *txn, size_t cardinality, struct tbuf *data)
 	if (txn->flags & BOX_REPLACE && txn->old_tuple == NULL)
 		box_raise(ERR_CODE_NODE_NOT_FOUND, "tuple not found");
 
-	validate_indeces(txn);
+	validate_indexes(txn);
 	run_hooks(txn, before_commit_update_hook);
 
 	if (txn->old_tuple != NULL) {
@@ -528,7 +528,7 @@ prepare_update_fields(struct box_txn *txn, struct tbuf *data)
 		p += fields[i]->len;
 	}
 
-	validate_indeces(txn);
+	validate_indexes(txn);
 	run_hooks(txn, before_commit_update_hook);
 
 	if (data->len != 0)
diff --git a/mod/silverbox/index.c b/mod/silverbox/index.c
index e31e8c8507..59cccfe09c 100644
--- a/mod/silverbox/index.c
+++ b/mod/silverbox/index.c
@@ -446,11 +446,14 @@ index_iterator_next_tree_str(struct index *self, struct tree_index_member *patte
 }
 
 void
-validate_indeces(struct box_txn *txn)
+validate_indexes(struct box_txn *txn)
 {
 	if (namespace[txn->n].index[1].key_cardinality != 0) {	/* there is more then one index */
 		foreach_index(txn->n, index) {
 			for (u32 f = 0; f < index->key_cardinality; ++f) {
+				if (index->key_field[f].fieldno >= txn->tuple->cardinality)
+					box_raise(ERR_CODE_ILLEGAL_PARAMS, "tuple is too short");
+
 				if (index->key_field[f].type == STR)
 					continue;
 
diff --git a/mod/silverbox/index.h b/mod/silverbox/index.h
index a7eb36aa27..f7c3bddfff 100644
--- a/mod/silverbox/index.h
+++ b/mod/silverbox/index.h
@@ -119,7 +119,7 @@ void index_iterator_init_tree_str(struct index *self, struct tree_index_member *
 struct box_tuple * index_iterator_next_tree_str(struct index *self, struct tree_index_member *pattern);
 
 struct box_txn;
-void validate_indeces(struct box_txn *txn);
+void validate_indexes(struct box_txn *txn);
 void build_indexes(void);
 
 #endif
diff --git a/test/box/sql.result b/test/box/sql.result
index c2f700da67..3816ec7499 100644
--- a/test/box/sql.result
+++ b/test/box/sql.result
@@ -87,3 +87,22 @@ select * from t65537 where k0 = 0
 An error occurred: ERR_CODE_NO_SUCH_NAMESPACE, 'No namespace with specified id exists'
 select * from t4294967295 where k0 = 0
 An error occurred: ERR_CODE_NO_SUCH_NAMESPACE, 'No namespace with specified id exists'
+
+#
+# A test case for: http://bugs.launchpad.net/bugs/735140
+# Partial REPLACE corrupts index.
+#
+
+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='Britney'
+Found 1 tuple:
+['Spears', 'Britney']
+insert into t0 values ('Spears')
+An error occurred: ERR_CODE_ILLEGAL_PARAMS, 'Illegal parameters'
+select * from t0 where k0='Spears'
+Found 1 tuple:
+['Spears', 'Britney']
diff --git a/test/box/sql.test b/test/box/sql.test
index d10dfcd292..6eac208fe8 100644
--- a/test/box/sql.test
+++ b/test/box/sql.test
@@ -52,5 +52,28 @@ exec sql "select * from t1 where k0 = 0"
 exec sql "select * from t65537 where k0 = 0"
 exec sql "select * from t4294967295 where k0 = 0"
 
+print """
+#
+# A test case for: http://bugs.launchpad.net/bugs/735140
+# Partial REPLACE corrupts index.
+#
+"""
+# clean data and restart with appropriate config
+server.stop()
+server.deploy("box/tarantool_bug735140.cfg")
+server.start()
+
+exec sql "insert into t0 values ('Spears', 'Britney')"
+exec sql "select * from t0 where k0='Spears'"
+exec sql "select * from t0 where k1='Britney'"
+# try to insert the incoplete tuple
+exec sql "insert into t0 values ('Spears')"
+# check that nothing has been updated
+exec sql "select * from t0 where k0='Spears'"
+
+# resore default suite config
+server.stop()
+server.deploy(self.suite_ini["config"])
+server.start()
 
 # vim: syntax=python
-- 
GitLab