diff --git a/.gitmodules b/.gitmodules index 2a8c091212286c89e5bace4680bfdc477bd311df..76fef526c356cbe2821b62c3555115217b46a8ae 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "third_party/lua-cjson"] path = third_party/lua-cjson - url = git://github.com/mpx/lua-cjson.git + url = https://github.com/mpx/lua-cjson.git [submodule "third_party/luajit"] path = third_party/luajit - url = git://github.com/tarantool/luajit.git + url = https://github.com/tarantool/luajit.git diff --git a/debian/changelog b/debian/changelog index c52f88a0017d31f04b46b6f775fceff385e867e6..6c9d88a39326e1714b67bf5c24141dfc23e8ed37 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +tarantool (1.5.1.150.g029f82f-1) unstable; urgency=low + + * New Debian snapshot (fix memory corruption). + + -- Dmitry E. Oboukhov <unera@debian.org> Fri, 25 Oct 2013 15:26:36 +0400 + tarantool (1.5.1.148.g6dddbc7-1) unstable; urgency=low * New Debian snapshot. diff --git a/doc/user/errcode.xml b/doc/user/errcode.xml index 3a772f9edf307188df36c8cd124630e9a065c26a..601feb8653083c3e7f46ffeb26e4dbbbf862c5b5 100644 --- a/doc/user/errcode.xml +++ b/doc/user/errcode.xml @@ -85,6 +85,12 @@ file <filename xlink:href="https://github.com/tarantool/tarantool/blob/master/in </para></listitem> </varlistentry> + <varlistentry> + <term xml:id="ER_UPDATE_FIELD" xreflabel="ER_UPDATE_FIELD">ER_UPDATE_FIELD</term> + <listitem><para>A error occured during update of a field. + </para></listitem> + </varlistentry> + </variablelist> </appendix> diff --git a/include/errcode.h b/include/errcode.h index 3a6499027f13dece496bff9ecbd2ce0c49fbc76d..4a921f5e1bd22bf99b53e8c565141a07c0caebfc 100644 --- a/include/errcode.h +++ b/include/errcode.h @@ -93,7 +93,7 @@ enum { TNT_ERRMSG_MAX = 512 }; /* 38 */_(ER_KEY_FIELD_TYPE, 2, "Supplied key field type does not match index type: expected %s") \ /* 39 */_(ER_WAL_IO, 2, "Failed to write to disk") \ /* 40 */_(ER_FIELD_TYPE, 2, "Field type does not match one required by operation: expected a %s") \ - /* 41 */_(ER_ARG_TYPE, 2, "Argument type in operation does not match field type: expected a %s") \ + /* 41 */_(ER_ARG_TYPE, 2, "Argument type in operation on field %u does not match field type: expected a %s") \ /* 42 */_(ER_SPLICE, 2, "Field SPLICE error: %s") \ /* 43 */_(ER_TUPLE_IS_TOO_LONG, 2, "Tuple is too long %u") \ /* 44 */_(ER_UNKNOWN_UPDATE_OP, 2, "Unknown UPDATE operation") \ @@ -108,7 +108,7 @@ enum { TNT_ERRMSG_MAX = 512 }; /* 53 */_(ER_NO_SUCH_INDEX, 2, "No index #%u is defined in space %u") \ /* 54 */_(ER_NO_SUCH_FIELD, 2, "Field %u was not found in the tuple") \ /* 55 */_(ER_TUPLE_FOUND, 2, "Duplicate key exists in unique index %u") \ - /* 56 */_(ER_UNUSED, 2, "") \ + /* 56 */_(ER_UPDATE_FIELD, 2, "Field %u UPDATE error: %s") \ /* 57 */_(ER_NO_SUCH_SPACE, 2, "Space %u does not exist") diff --git a/src/box/box_lua.cc b/src/box/box_lua.cc index 9548c5bc8e7914a053d83444e74f6397e0cc918f..9bc7b989d9736efb0c96fb9b967d6496888481f0 100644 --- a/src/box/box_lua.cc +++ b/src/box/box_lua.cc @@ -314,7 +314,9 @@ lbox_tuple_transform(struct lua_State *L) /* * Calculate the number of operations and length of UPDATE expression */ - uint32_t op_cnt = offset < tuple->field_count ? field_count : 0; + uint32_t op_cnt = 0; + if (offset < tuple->field_count && field_count > 0) + op_cnt++; if (argc > 3) op_cnt += argc - 3; @@ -331,10 +333,13 @@ lbox_tuple_transform(struct lua_State *L) luaL_buffinit(L, &b); luaL_addlstring(&b, (char *) &op_cnt, sizeof(op_cnt)); uint32_t offset_u32 = (uint32_t) offset; - for (uint32_t i = 0; i < (uint32_t) field_count; i++) { + uint32_t field_count_u32 = (uint32_t) field_count; + if (field_count > 0) { luaL_addlstring(&b, (char *) &offset_u32, sizeof(offset_u32)); - luaL_addchar(&b, UPDATE_OP_DELETE); - luaL_addvarint32(&b, 0); /* Unused. */ + luaL_addchar(&b, UPDATE_OP_DELETE); /* multi-delete */ + luaL_addvarint32(&b, sizeof(field_count_u32)); + luaL_addlstring(&b, (char *) &field_count_u32, + sizeof(field_count_u32)); } for (int i = argc ; i > 3; i--) { diff --git a/src/box/tuple_update.cc b/src/box/tuple_update.cc index 451b579ce5478aa689603abfdf91ac89f579c145..1c4bc9ad3efd5c4456a8e4caa5e57aecd2f62e2a 100644 --- a/src/box/tuple_update.cc +++ b/src/box/tuple_update.cc @@ -319,12 +319,39 @@ init_update_op_set(struct tuple_update *update, struct update_op *op) } static void -init_update_op_delete(struct tuple_update *update, struct update_op *op) +init_update_op_delete_1_4(struct tuple_update *update, struct update_op *op) { op_adjust_field_no(op, rope_size(update->rope) - 1); rope_erase(update->rope, op->field_no); } +static void +init_update_op_delete(struct tuple_update *update, struct update_op *op) +{ + op_adjust_field_no(op, rope_size(update->rope) - 1); + + uint32_t delete_count = 1; + if (op->arg.set.length > 0) { + /* Check the operand type, if present. */ + if (op->arg.set.length != sizeof(int32_t)) + tnt_raise(ClientError, ER_ARG_TYPE, + op->field_no, "NUM"); + + delete_count = *(int32_t *)op->arg.set.value; + if (delete_count == UINT32_MAX) + delete_count = rope_size(update->rope) - op->field_no; + else if (op->field_no + delete_count > rope_size(update->rope)) + delete_count = rope_size(update->rope) - op->field_no; + + if (delete_count == 0) + tnt_raise(ClientError, ER_UPDATE_FIELD, + op->field_no, "cannot delete 0 fields"); + } + + for (uint32_t u = 0; u < delete_count; u++) + rope_erase(update->rope, op->field_no); +} + static void init_update_op_arith(struct tuple_update *update, struct update_op *op) { @@ -342,7 +369,7 @@ init_update_op_arith(struct tuple_update *update, struct update_op *op) /* Check the operand type. */ if (op->arg.set.length != sizeof(int32_t)) tnt_raise(ClientError, ER_ARG_TYPE, - "32-bit int"); + op->field_no, "NUM"); arg->i32_val = *(int32_t *)op->arg.set.value; break; @@ -360,7 +387,7 @@ init_update_op_arith(struct tuple_update *update, struct update_op *op) break; default: tnt_raise(ClientError, ER_ARG_TYPE, - "32-bit or 64-bit int"); + op->field_no, "NUM or NUM64"); } break; default: @@ -423,16 +450,17 @@ init_update_op_splice(struct tuple_update *update, struct update_op *op) STAILQ_INSERT_TAIL(&field->ops, op, next); } -static struct update_op_meta update_op_meta[UPDATE_OP_MAX + 1] = { +static struct update_op_meta update_op_meta[update_op_codes_MAX] = { { init_update_op_set, (do_op_func) do_update_op_set, true }, { init_update_op_arith, (do_op_func) do_update_op_add, true }, { init_update_op_arith, (do_op_func) do_update_op_and, true }, { init_update_op_arith, (do_op_func) do_update_op_xor, true }, { init_update_op_arith, (do_op_func) do_update_op_or, true }, { init_update_op_splice, (do_op_func) do_update_op_splice, false }, - { init_update_op_delete, (do_op_func) NULL, true }, + { init_update_op_delete_1_4, (do_op_func) NULL, true }, { init_update_op_insert, (do_op_func) do_update_op_insert, true }, { init_update_op_arith, (do_op_func) do_update_op_subtract, true }, + { init_update_op_delete, (do_op_func) NULL, true }, }; static inline size_t @@ -625,7 +653,7 @@ update_read_ops(struct tuple_update *update, const char *expr, op->field_no = pick_u32(&expr, expr_end); op->opcode = pick_u8(&expr, expr_end); - if (op->opcode >= UPDATE_OP_MAX) + if (op->opcode >= update_op_codes_MAX) tnt_raise(ClientError, ER_UNKNOWN_UPDATE_OP); op->meta = &update_op_meta[op->opcode]; diff --git a/src/box/tuple_update.h b/src/box/tuple_update.h index 5bc7b5402646fa2c82ad59ce8de468f75846727d..327655634ee4e8242d464b0c18ef6417b811e75c 100644 --- a/src/box/tuple_update.h +++ b/src/box/tuple_update.h @@ -45,10 +45,10 @@ enum { _(UPDATE_OP_XOR, 3) \ _(UPDATE_OP_OR, 4) \ _(UPDATE_OP_SPLICE, 5) \ - _(UPDATE_OP_DELETE, 6) \ + _(UPDATE_OP_DELETE_1_4, 6) \ _(UPDATE_OP_INSERT, 7) \ _(UPDATE_OP_SUBTRACT, 8) \ - _(UPDATE_OP_MAX, 10) \ + _(UPDATE_OP_DELETE, 9) ENUM(update_op_codes, UPDATE_OP_CODES); diff --git a/src/salloc.cc b/src/salloc.cc index 4a15de7392d72c27fe8b5a90de901e606c107122..9223bb91c2818d8cd1975521cab722bc1b576d25 100644 --- a/src/salloc.cc +++ b/src/salloc.cc @@ -45,6 +45,8 @@ #define SLAB_ALIGN_PTR(ptr) (void *)((uintptr_t)(ptr) & ~(SLAB_SIZE - 1)) +extern int snapshot_pid; + #ifdef SLAB_DEBUG #undef NDEBUG uint8_t red_zone[4] = { 0xfa, 0xfa, 0xfa, 0xfa }; @@ -322,6 +324,9 @@ sfree(void *ptr) static void sfree_batch(void) { + if (snapshot_pid) + return; + ssize_t batch = arena.delayed_free_batch; while (--batch >= 0 && !SLIST_EMPTY(&free_delayed)) { diff --git a/src/tarantool.cc b/src/tarantool.cc index 4e81d2e69f2d4ee0a92f4ef231f4e4e7e0de70c6..e0a2315aa2310de023e6397a5dcb6597fb843bda 100644 --- a/src/tarantool.cc +++ b/src/tarantool.cc @@ -324,8 +324,6 @@ snapshot(void) if (snapshot_pid) return EINPROGRESS; - /* increment snapshot version */ - snapshot_version++; pid_t p = fork(); if (p < 0) { @@ -334,6 +332,8 @@ snapshot(void) } if (p > 0) { snapshot_pid = p; + /* increment snapshot version */ + snapshot_version++; int status = wait_for_child(p); snapshot_pid = 0; return (WIFSIGNALED(status) ? EINTR : WEXITSTATUS(status)); diff --git a/test/big/lua.result b/test/big/lua.result index e10bb33fa784b591572a8ff333051615d6561a44..37f969d0edf5744756753b61102ec18ff052ea41 100644 --- a/test/big/lua.result +++ b/test/big/lua.result @@ -480,6 +480,22 @@ lua t:transform(0, 1, {}) --- error: 'tuple.transform(): unsupported field type ''table''' ... +lua n = 50000; +--- +... +lua tab = {}; for i=1,n,1 do table.insert(tab, i) end +--- +... +lua t = box.tuple.new(tab) +--- +... +lua t:transform(0, n - 1) +--- + - 50000: {} +... +lua t = nil +--- +... lua t=box.insert(12, 'A', '2', '3', '4', '3', '2', '5', '6', '3', '7') --- ... diff --git a/test/big/lua.test b/test/big/lua.test index 03a4bfc9835b1f2e3a13fe35d927a78514aa036b..a99d46a72e497651da371db246482996fe9dd254 100644 --- a/test/big/lua.test +++ b/test/big/lua.test @@ -175,6 +175,17 @@ exec admin "lua t:transform(0, 3, 1, 2, 3)" exec admin "lua t:transform(3, 1, tonumber64(4))" exec admin "lua t:transform(0, 1, {})" +# +# Tests for OPENTAR-64 - a limitation for the second argument to tuple:transform +# + +# 50K is enough for everyone +exec admin "lua n = 50000;" +exec admin "lua tab = {}; for i=1,n,1 do table.insert(tab, i) end" +exec admin "lua t = box.tuple.new(tab)" +exec admin "lua t:transform(0, n - 1)" +exec admin "lua t = nil" + # # Tests for lua tuple:find() and tuple:findall() # diff --git a/test/box/lua_misc.result b/test/box/lua_misc.result index e4a93593306388d349eb4c4dd1fdc46491e72695..1bd86818bf699184a1bbde4563a3844d62c54700 100644 --- a/test/box/lua_misc.result +++ b/test/box/lua_misc.result @@ -105,8 +105,9 @@ box.error.ER_NONMASTER: 258 box.error.ER_PROC_RET: 12290 box.error.ER_TUPLE_IS_TOO_LONG: 11010 box.error.ER_EXACT_MATCH: 11522 -box.error.ER_FIELD_TYPE: 10242 box.error.ER_PROC_LUA: 13058 +box.error.ER_FIELD_TYPE: 10242 +box.error.ER_UPDATE_FIELD: 14338 box.error.ER_TUPLE_FOUND: 14082 box.error.ER_OK: 0 box.error.ER_NO_SUCH_FIELD: 13826