diff --git a/connector/c/include/tarantool/tnt_proto.h b/connector/c/include/tarantool/tnt_proto.h index 5e6778c5637de049610f7e9d25cce4594e60ec97..f0dec21109f263c00f40e352361a27338adfa0e4 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 5b6a36ecf9da3c81107b0e36bcbb5471fa6217e7..8e2e4e0fa03e517921fd1fa9fb3ae9094dd56d3f 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 8539a7c326648964b6826d777d7c5678f3d1f787..e68f3915c7c6d0e115c10fd43e11db808a1c74d2 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 c55a2ab7a49c07cf8a973b0ad73118fa65f8c66c..00129c1310b33506dcbf7ed926d61307825fb683 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 e796b776a9d9b6b77c815953d5e892097b29d010..0f370de2618bb7c02176ccf3acd5b7269e5fa90e 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 922997eee87c659cfea02bb647230287e17758c9..e6e074ff4e1232d5d525c699ff6cc1c086c426f5 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 50e1c6c3575f7565512bae5923a39daaa7f72c3a..75c5988774a3df232c423cd1b1d7ac70566dfd2b 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);