From ba9d397147854f2a26dbac23b11c9ec7b157fd92 Mon Sep 17 00:00:00 2001
From: Roman Tsisyk <roman@tsisyk.com>
Date: Tue, 2 Jul 2013 17:19:22 +0400
Subject: [PATCH] Use lua_newuserdata instead of palloc in tuple:transform
 (Bug#1194056)

---
 include/lua/init.h |  9 +++++++++
 include/palloc.h   |  6 ++++++
 src/box/box_lua.cc |  5 ++++-
 src/box/request.cc |  4 +++-
 src/box/tuple.cc   | 11 +++--------
 src/box/tuple.h    |  5 +++--
 src/lua/init.cc    |  7 +++++++
 7 files changed, 35 insertions(+), 12 deletions(-)

diff --git a/include/lua/init.h b/include/lua/init.h
index 382516efc3..0088d33046 100644
--- a/include/lua/init.h
+++ b/include/lua/init.h
@@ -28,6 +28,7 @@
  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+#include <stddef.h>
 #include <inttypes.h>
 
 struct lua_State;
@@ -119,5 +120,13 @@ int luaL_pushnumber64(struct lua_State *L, uint64_t val);
 struct tbuf;
 void show_plugins_stat(struct tbuf *out);
 
+/**
+ * @brief A palloc-like wrapper to allocate memory using lua_newuserdata
+ * @param ctx lua_State
+ * @param size a number of bytes to allocate
+ * @return a pointer to the allocated memory
+ */
+void *
+lua_region_alloc(void *ctx, size_t size);
 
 #endif /* INCLUDES_TARANTOOL_LUA_H */
diff --git a/include/palloc.h b/include/palloc.h
index d1f89569e7..c108a42950 100644
--- a/include/palloc.h
+++ b/include/palloc.h
@@ -61,6 +61,12 @@ size_t palloc_allocated(struct palloc_pool *);
 
 void palloc_stat(struct tbuf *buf);
 
+static inline void *
+palloc_region_alloc(void *ctx, size_t size)
+{
+	return palloc((struct palloc_pool *) ctx, size);
+}
+
 #if defined(__cplusplus)
 } /* extern "C" */
 #endif /* defined(__cplusplus) */
diff --git a/src/box/box_lua.cc b/src/box/box_lua.cc
index 21503c9928..761d0e5f17 100644
--- a/src/box/box_lua.cc
+++ b/src/box/box_lua.cc
@@ -353,7 +353,10 @@ lbox_tuple_transform(struct lua_State *L)
 	const char *expr = lua_tolstring(L, -1, &expr_len);
 
 	/* Execute tuple_update */
-	struct tuple *new_tuple = tuple_update(tuple, expr, expr + expr_len);
+	struct tuple *new_tuple = tuple_update(lua_region_alloc, L,
+					       tuple, expr, expr + expr_len);
+	/* Cleanup memory allocated by lua_region_alloc */
+	lua_settop(L, 0);
 	lbox_pushtuple(L, new_tuple);
 	return 1;
 }
diff --git a/src/box/request.cc b/src/box/request.cc
index 4a476811f8..3b662575d9 100644
--- a/src/box/request.cc
+++ b/src/box/request.cc
@@ -113,7 +113,9 @@ execute_update(struct request *request, struct txn *txn)
 		return;
 
 	/* Update the tuple. */
-	struct tuple *new_tuple = tuple_update(old_tuple, *reqpos, reqend);
+	struct tuple *new_tuple = tuple_update(palloc_region_alloc,
+					       fiber->gc_pool,
+					       old_tuple, *reqpos, reqend);
 	try {
 		space_validate_tuple(sp, new_tuple);
 		txn_replace(txn, sp, old_tuple, new_tuple, DUP_INSERT);
diff --git a/src/box/tuple.cc b/src/box/tuple.cc
index 76d1e5dc79..126b3ba1e5 100644
--- a/src/box/tuple.cc
+++ b/src/box/tuple.cc
@@ -195,20 +195,15 @@ tuple_print(struct tbuf *buf, const struct tuple *tuple)
 	tbuf_printf(buf, "}");
 }
 
-static void *
-palloc_region_alloc(void *ctx, size_t size)
-{
-	return palloc((struct palloc_pool *) ctx, size);
-}
-
 struct tuple *
-tuple_update(const struct tuple *old_tuple, const char *expr,
+tuple_update(void *(*region_alloc)(void *, size_t), void *alloc_ctx,
+	     const struct tuple *old_tuple, const char *expr,
 	     const char *expr_end)
 {
 	uint32_t new_size = 0;
 	uint32_t new_field_count = 0;
 	struct tuple_update *update =
-		tuple_update_prepare(palloc_region_alloc, fiber->gc_pool,
+		tuple_update_prepare(region_alloc, alloc_ctx,
 				     expr, expr_end, old_tuple->data,
 				     old_tuple->data + old_tuple->bsize,
 				     old_tuple->field_count, &new_size,
diff --git a/src/box/tuple.h b/src/box/tuple.h
index 401b21a26f..ad7bab91be 100644
--- a/src/box/tuple.h
+++ b/src/box/tuple.h
@@ -166,8 +166,9 @@ void
 tuple_print(struct tbuf *buf, const struct tuple *tuple);
 
 struct tuple *
-tuple_update(const struct tuple *old_tuple, const char *expr,
-             const char *expr_end);
+tuple_update(void *(*region_alloc)(void *, size_t), void *alloc_ctx,
+	     const struct tuple *old_tuple,
+	     const char *expr, const char *expr_end);
 
 /** Tuple length when adding to iov. */
 static inline size_t tuple_len(struct tuple *tuple)
diff --git a/src/lua/init.cc b/src/lua/init.cc
index f0699ce6e6..78e82997f9 100644
--- a/src/lua/init.cc
+++ b/src/lua/init.cc
@@ -1560,3 +1560,10 @@ tarantool_lua_load_init_script(struct lua_State *L)
 	*/
 	tarantool_lua_sandbox(tarantool_L);
 }
+
+void *
+lua_region_alloc(void *ctx, size_t size)
+{
+	struct lua_State *L = (struct lua_State *) ctx;
+	return lua_newuserdata(L, size);
+}
-- 
GitLab