From 18443657956c1cbde98370c0c86e9e5862282a8a Mon Sep 17 00:00:00 2001
From: Dmitry Simonenko <pmwkaa@gmail.com>
Date: Mon, 21 May 2012 18:50:37 +0400
Subject: [PATCH] connector-c-fix: connector updated to the latest server
 changes * using new delete version with flags * splice offset type fixed *
 added tnt_tuple_reply tuple validation + test case

---
 connector/c/include/tarantool/tnt_proto.h  |  2 +-
 connector/c/include/tarantool/tnt_update.h |  2 +-
 connector/c/tnt/tnt_delete.c               |  3 ++-
 connector/c/tnt/tnt_tuple.c                | 31 ++++++++++++++++++++--
 connector/c/tnt/tnt_update.c               |  3 +--
 test/connector_c/connector.result          |  1 +
 test/connector_c/tt.c                      | 19 +++++++++++++
 7 files changed, 54 insertions(+), 7 deletions(-)

diff --git a/connector/c/include/tarantool/tnt_proto.h b/connector/c/include/tarantool/tnt_proto.h
index 5e6778c563..f0dec21109 100644
--- a/connector/c/include/tarantool/tnt_proto.h
+++ b/connector/c/include/tarantool/tnt_proto.h
@@ -29,7 +29,7 @@
 #define TNT_OP_INSERT      13
 #define TNT_OP_SELECT      17
 #define TNT_OP_UPDATE      19
-#define TNT_OP_DELETE      20
+#define TNT_OP_DELETE      21
 #define TNT_OP_CALL        22
 #define TNT_OP_PING        65280
 
diff --git a/connector/c/include/tarantool/tnt_update.h b/connector/c/include/tarantool/tnt_update.h
index 5b6a36ecf9..8e2e4e0fa0 100644
--- a/connector/c/include/tarantool/tnt_update.h
+++ b/connector/c/include/tarantool/tnt_update.h
@@ -56,7 +56,7 @@ tnt_update_assign(struct tnt_stream *s, uint32_t field,
 ssize_t
 tnt_update_splice(struct tnt_stream *s, uint32_t field,
 		  uint32_t offset,
-		  uint32_t length, char *data, size_t size);
+		  int32_t length, char *data, size_t size);
 
 ssize_t
 tnt_update_delete(struct tnt_stream *s, uint32_t field);
diff --git a/connector/c/tnt/tnt_delete.c b/connector/c/tnt/tnt_delete.c
index 8539a7c326..e68f3915c7 100644
--- a/connector/c/tnt/tnt_delete.c
+++ b/connector/c/tnt/tnt_delete.c
@@ -36,6 +36,7 @@
 
 struct tnt_header_delete {
 	uint32_t ns;
+	uint32_t flags;
 };
 
 /*
@@ -61,7 +62,7 @@ tnt_delete(struct tnt_stream *s, uint32_t ns, uint32_t flags, struct tnt_tuple *
 	/* filling delete header */
 	struct tnt_header_delete hdr_del;
 	hdr_del.ns = ns;
-	(void)flags;
+	hdr_del.flags = flags;
 	/* writing data to stream */
 	struct iovec v[3];
 	v[0].iov_base = &hdr;
diff --git a/connector/c/tnt/tnt_tuple.c b/connector/c/tnt/tnt_tuple.c
index c55a2ab7a4..00129c1310 100644
--- a/connector/c/tnt/tnt_tuple.c
+++ b/connector/c/tnt/tnt_tuple.c
@@ -209,6 +209,33 @@ tnt_tuple(struct tnt_tuple *t, char *fmt, ...)
 	return t;
 }
 
+/*
+ * tnt_tuple_validate()
+ *
+ * check if supplied buffer is a valid tuple;
+ *
+ * buf  - iproto tuple buffer representation
+ * size - buffer size
+ *
+ * returns 0, or -1 on error.
+*/
+static int tnt_tuple_validate(char *buf, size_t size) {
+	if (size < sizeof(uint32_t))
+		return -1;
+	size_t fld_off = sizeof(uint32_t);
+	uint32_t cardinality = *(uint32_t*)buf;
+	while (cardinality-- != 0) {
+		uint32_t fld_size;
+		int fld_esize = tnt_enc_read(buf + fld_off, &fld_size);
+		if (fld_esize == -1)
+			return -1;
+		fld_off += fld_esize + fld_size;
+		if (fld_off > size)
+			return -1;
+	}
+	return 0;
+}
+
 /*
  * tnt_tuple_set()
  *
@@ -224,14 +251,14 @@ tnt_tuple(struct tnt_tuple *t, char *fmt, ...)
  * returns tuple pointer, or NULL on error.
 */
 struct tnt_tuple *tnt_tuple_set(struct tnt_tuple *t, char *buf, size_t size) {
+	if (tnt_tuple_validate(buf, size) == -1)
+		return NULL;
 	int allocated = t == NULL;
 	if (t == NULL) {
 		t = tnt_tuple_add(NULL, NULL, 0);
 		if (t == NULL)
 			return NULL;
 	}
-	if (size < sizeof(uint32_t))
-		goto error;
 	t->cardinality = *(uint32_t*)buf;
 	t->size = size;
 	t->data = tnt_mem_alloc(size);
diff --git a/connector/c/tnt/tnt_update.c b/connector/c/tnt/tnt_update.c
index e796b776a9..0f370de261 100644
--- a/connector/c/tnt/tnt_update.c
+++ b/connector/c/tnt/tnt_update.c
@@ -158,7 +158,7 @@ tnt_update_assign(struct tnt_stream *s, uint32_t field,
 ssize_t
 tnt_update_splice(struct tnt_stream *s, uint32_t field,
 		  uint32_t offset,
-		  uint32_t length, char *data, size_t size)
+		  int32_t length, char *data, size_t size)
 {
 	/* calculating splice data sizes */
 	uint32_t offset_len = tnt_enc_size(sizeof(offset)),
@@ -213,7 +213,6 @@ tnt_update_insert(struct tnt_stream *s, uint32_t field,
 	return tnt_update_op(s, field, TNT_UPDATE_INSERT, data, size);
 }
 
-
 struct tnt_header_update {
 	uint32_t ns;
 	uint32_t flags;
diff --git a/test/connector_c/connector.result b/test/connector_c/connector.result
index 922997eee8..e6e074ff4e 100644
--- a/test/connector_c/connector.result
+++ b/test/connector_c/connector.result
@@ -2,6 +2,7 @@
 > tuple2                        [OK]
 > list                          [OK]
 > stream buffer                 [OK]
+> tuple set                     [OK]
 > iterator tuple                [OK]
 > iterator tuple (single field) [OK]
 > iterator tuple (tnt_field)    [OK]
diff --git a/test/connector_c/tt.c b/test/connector_c/tt.c
index 50e1c6c357..75c5988774 100644
--- a/test/connector_c/tt.c
+++ b/test/connector_c/tt.c
@@ -188,6 +188,24 @@ static void tt_tnt_sbuf(struct tt_test *test) {
 	tnt_stream_free(&s);
 }
 
+/* tuple set */
+static void tt_tnt_tuple_set(struct tt_test *test) {
+	char buf[75];
+	*((uint32_t*)buf) = 2; /* cardinality */
+	/* 4 + 1 + 5 + 1 + 64 = 75 */
+	uint32_t off = sizeof(uint32_t);
+	int esize = tnt_enc_size(5);
+	tnt_enc_write(buf + off, 5);
+	off += esize + 5;
+	esize = tnt_enc_size(64);
+	tnt_enc_write(buf + off, 64);
+	off += esize + 64;
+	struct tnt_tuple t;
+	TT_ASSERT(tnt_tuple_set(&t, buf, 70) == NULL);
+	TT_ASSERT(tnt_tuple_set(&t, buf, sizeof(buf)) != NULL);
+	tnt_tuple_free(&t);
+}
+
 /* iterator tuple */
 static void tt_tnt_iter1(struct tt_test *test) {
 	struct tnt_tuple *t = tnt_tuple(NULL, "%s%d%s", "foo", 123, "bar");
@@ -871,6 +889,7 @@ main(int argc, char * argv[])
 	tt_test(&t, "tuple2", tt_tnt_tuple2);
 	tt_test(&t, "list", tt_tnt_list);
 	tt_test(&t, "stream buffer", tt_tnt_sbuf);
+	tt_test(&t, "tuple set", tt_tnt_tuple_set);
 	tt_test(&t, "iterator tuple", tt_tnt_iter1);
 	tt_test(&t, "iterator tuple (single field)", tt_tnt_iter11);
 	tt_test(&t, "iterator tuple (tnt_field)", tt_tnt_iter2);
-- 
GitLab