Tarantool development patches archive
 help / color / mirror / Atom feed
From: imeevma@tarantool.org
To: tarantool-patches@freelists.org, v.shpilevoy@tarantool.org
Subject: [tarantool-patches] [PATCH v8 1/6] lua: remove exceptions from function luaL_tofield()
Date: Sat, 19 Jan 2019 16:20:19 +0300	[thread overview]
Message-ID: <f3d5e7ec4d7b75f81a022ce196fc2a8fdd4f5b98.1547902954.git.imeevma@gmail.com> (raw)
In-Reply-To: <cover.1547902954.git.imeevma@gmail.com>

Hi! Thank you for review. My answers, diff between versions and
new version below.


On 1/16/19 9:25 PM, Vladislav Shpilevoy wrote:
> Hi! Thanks for the patch! See 4 comments below.
>
> On 15/01/2019 19:10, imeevma@tarantool.org wrote:
>> Before this commit, the luaL_tofield() function threw a Lua
>> exception when an error occurred. This behavior has been changed
>> in this commit, now it sets diag_set() and returns -1 in case of
>> an error.
>>
>> Needed for #3505
>> ---
>>   src/box/lua/call.c  |   9 +++--
>>   src/box/lua/tuple.c |   3 +-
>>   src/lua/msgpack.c   |  12 ++++--
>>   src/lua/utils.c     | 105 ++++++++++++++++++++++++++++++----------------------
>>   src/lua/utils.h     |   8 +++-
>>   5 files changed, 83 insertions(+), 54 deletions(-)
>>
>> diff --git a/src/box/lua/call.c b/src/box/lua/call.c
>> index 52939ae..39df05d 100644
>> --- a/src/box/lua/call.c
>> +++ b/src/box/lua/call.c
>> @@ -164,7 +164,8 @@ luamp_encode_call_16(lua_State *L, struct luaL_serializer *cfg,
>>            */
>>           for (int i = 1; i <= nrets; ++i) {
>>               struct luaL_field field;
>> -            luaL_tofield(L, cfg, i, &field);
>> +            if (luaL_tofield(L, cfg, i, &field) < 0)
>> +                luaT_error(L); 
>
> 1. I know, it is weird, but usually we write return luaT_error/luaL_error().
> Difference is in 'return' usage. Do not ask me why, I do not know. Maybe to
> emphasize that this statement finishes the function. So please, write 'return'
> where possible. Here and in other places.
>
Fixed in functions that return int.

>>               struct tuple *tuple;
>>               if (field.type == MP_EXT &&
>>                   (tuple = luaT_istuple(L, i)) != NULL) {
>> diff --git a/src/lua/utils.c b/src/lua/utils.c
>> index 978fe61..9a9fd3a 100644
>> --- a/src/lua/utils.c
>> +++ b/src/lua/utils.c
>> @@ -37,6 +37,8 @@
>>   #include <diag.h>
>>   #include <fiber.h>
>>   
>
> 2. Unnecessary empty line.
>
Removed header.

>> +#include "box/error.h"
>> +
>>   int luaL_nil_ref = LUA_REFNIL;
>>   int luaL_map_metatable_ref = LUA_REFNIL;
>>   int luaL_array_metatable_ref = LUA_REFNIL;
>> @@ -408,10 +411,11 @@ lua_field_inspect_table(struct lua_State *L, struct luaL_serializer *cfg,
>>           lua_call(L, 1, 1);
>>           /* replace obj with the unpacked value */
>>           lua_replace(L, idx); 
>
> 3. In my opinion there is still a problem with lua_* methods,
> throwing exceptions on OOM *and on a simple stack overflow*.
> Even fixed GC will not fix the problem if all memory is
> occupied by non-garbage memory. I adhere to my opinion that it
> is better to use lua_cpcall. There is nothing bad with it. *_pcall
> just remembers a couple of registers, it is not too expensive for
> such a vast function. Also lua_cpcall causes much less diff.
>
> We can do it, for example, by renaming luaL_tofield to luaL_tofield_xc
> and introducing new luaL_tofield, calling luaL_tofield_xc via
> lua_cpcall. Just like we used to work with C++ *_xc wrappers.
>
> Please, ask again in the server team chat about the proposal above.
> Do not forget about stack overflow error, which also is possible and
> does not mean panic. Moreover, it is worth noting that diff is going
> to be much less and simpler. If they decline the proposal, I give in.
>
As I understood, this suggestion was rejected.

>> -        luaL_tofield(L, cfg, idx, field);
>> -        return;
>> +        return luaL_tofield(L, cfg, idx, field);
>>       } else if (!lua_isstring(L, -1)) {
>> -        luaL_error(L, "invalid " LUAL_SERIALIZE  " value");
>> +        diag_set(ClientError, ER_PROC_LUA,
>> +             "invalid " LUAL_SERIALIZE " value");
>> +        return -1;
>>       }
>>         type = lua_tostring(L, -1);
>> @@ -525,94 +539,96 @@ luaL_tofield(struct lua_State *L, struct luaL_serializer *cfg, int index,
>>               field->dval = num;
>>               CHECK_NUMBER(num);
>>           }
>> -        return;
>> +        break; 
>
> 4. Why no to return 0? Anyway all your breaks lead to a simple 'return 0'.
>
Fixed.

>> @@ -620,14 +636,15 @@ luaL_tofield(struct lua_State *L, struct luaL_serializer *cfg, int index,
>>           field->sval.len = 0;
>>           if (lua_touserdata(L, index) == NULL) {
>>               field->type = MP_NIL;
>> -            return;
>> +            break;
>>           }
>>           /* Fall through */
>>       default:
>>           field->type = MP_EXT;
>> -        return;
>> +        break;
>>       }
>>   #undef CHECK_NUMBER
>> +    return 0;
>>   }
>>     void 


On 1/17/19 4:15 PM, Vladislav Shpilevoy wrote:
>
>
> On 17/01/2019 14:38, Konstantin Osipov wrote:
>> * imeevma@tarantool.org <imeevma@tarantool.org> [19/01/15 19:14]:
>>> Before this commit, the luaL_tofield() function threw a Lua
>>> diff --git a/src/lua/utils.c b/src/lua/utils.c
>>> index 978fe61..9a9fd3a 100644
>>> --- a/src/lua/utils.c
>>> +++ b/src/lua/utils.c
>>> @@ -37,6 +37,8 @@
>>>   #include <diag.h>
>>>   #include <fiber.h>
>>>   +#include "box/error.h" 
>>
>> Please don't. This violates encapsulation.
>>
>>
>
> Oh, of course. Sorry, dismissed it. Mergen, we can not
> use ClientError outside of box/ module. See exception.h for
> available errors. I think, LuajitError is the most suitable
> here.
>
Thanks, fixed.


Diff between versions:

commit 07bcff72336fe861fd51d895fe088662a9d09fe4
Author: Mergen Imeev <imeevma@gmail.com>
Date:   Thu Jan 17 15:00:27 2019 +0300

    Temporary: Review fixes

diff --git a/src/box/lua/call.c b/src/box/lua/call.c
index 39df05d..2049ee5 100644
--- a/src/box/lua/call.c
+++ b/src/box/lua/call.c
@@ -165,7 +165,7 @@ luamp_encode_call_16(lua_State *L, struct luaL_serializer *cfg,
 		for (int i = 1; i <= nrets; ++i) {
 			struct luaL_field field;
 			if (luaL_tofield(L, cfg, i, &field) < 0)
-				luaT_error(L);
+				return luaT_error(L);
 			struct tuple *tuple;
 			if (field.type == MP_EXT &&
 			    (tuple = luaT_istuple(L, i)) != NULL) {
@@ -194,7 +194,7 @@ luamp_encode_call_16(lua_State *L, struct luaL_serializer *cfg,
 	 */
 	struct luaL_field root;
 	if (luaL_tofield(L, cfg, 1, &root) < 0)
-		luaT_error(L);
+		return luaT_error(L);
 	struct tuple *tuple;
 	if (root.type == MP_EXT && (tuple = luaT_istuple(L, 1)) != NULL) {
 		/* `return box.tuple()` */
@@ -224,7 +224,7 @@ luamp_encode_call_16(lua_State *L, struct luaL_serializer *cfg,
 		lua_rawgeti(L, 1, t);
 		struct luaL_field field;
 		if (luaL_tofield(L, cfg, -1, &field) < 0)
-			luaT_error(L);
+			return luaT_error(L);
 		if (field.type == MP_EXT && (tuple = luaT_istuple(L, -1))) {
 			tuple_to_mpstream(tuple, stream);
 		} else if (field.type != MP_ARRAY) {
diff --git a/src/lua/msgpack.c b/src/lua/msgpack.c
index d00ade9..1b1874e 100644
--- a/src/lua/msgpack.c
+++ b/src/lua/msgpack.c
@@ -150,11 +150,11 @@ restart: /* used by MP_EXT */
 		while (lua_next(L, top) != 0) {
 			lua_pushvalue(L, -2); /* push a copy of key to top */
 			if (luaL_tofield(L, cfg, lua_gettop(L), field) < 0)
-				luaT_error(L);
+				return luaT_error(L);
 			luamp_encode_r(L, cfg, stream, field, level + 1);
 			lua_pop(L, 1); /* pop a copy of key */
 			if (luaL_tofield(L, cfg, lua_gettop(L), field) < 0)
-				luaT_error(L);
+				return luaT_error(L);
 			luamp_encode_r(L, cfg, stream, field, level + 1);
 			lua_pop(L, 1); /* pop value */
 		}
@@ -171,7 +171,7 @@ restart: /* used by MP_EXT */
 		for (uint32_t i = 0; i < size; i++) {
 			lua_rawgeti(L, top, i + 1);
 			if (luaL_tofield(L, cfg, top + 1, field) < 0)
-				luaT_error(L);
+				return luaT_error(L);
 			luamp_encode_r(L, cfg, stream, field, level + 1);
 			lua_pop(L, 1);
 		}
@@ -207,7 +207,7 @@ luamp_encode(struct lua_State *L, struct luaL_serializer *cfg,
 
 	struct luaL_field field;
 	if (luaL_tofield(L, cfg, lua_gettop(L), &field) < 0)
-		luaT_error(L);
+		return luaT_error(L);
 	enum mp_type top_type = luamp_encode_r(L, cfg, stream, &field, 0);
 
 	if (!on_top) {
diff --git a/src/lua/utils.c b/src/lua/utils.c
index 9a9fd3a..c10403d 100644
--- a/src/lua/utils.c
+++ b/src/lua/utils.c
@@ -37,8 +37,6 @@
 #include <diag.h>
 #include <fiber.h>
 
-#include "box/error.h"
-
 int luaL_nil_ref = LUA_REFNIL;
 int luaL_map_metatable_ref = LUA_REFNIL;
 int luaL_array_metatable_ref = LUA_REFNIL;
@@ -413,8 +411,7 @@ lua_field_inspect_table(struct lua_State *L, struct luaL_serializer *cfg,
 		lua_replace(L, idx);
 		return luaL_tofield(L, cfg, idx, field);
 	} else if (!lua_isstring(L, -1)) {
-		diag_set(ClientError, ER_PROC_LUA,
-			 "invalid " LUAL_SERIALIZE " value");
+		diag_set(LuajitError, "invalid " LUAL_SERIALIZE " value");
 		return -1;
 	}
 
@@ -438,8 +435,7 @@ lua_field_inspect_table(struct lua_State *L, struct luaL_serializer *cfg,
 		lua_pop(L, 1); /* type */
 		return 0;
 	} else {
-		diag_set(ClientError, ER_PROC_LUA,
-			 "invalid " LUAL_SERIALIZE " value");
+		diag_set(LuajitError, "invalid " LUAL_SERIALIZE " value");
 		return -1;
 	}
 
@@ -473,8 +469,7 @@ skip:
 	    max > size * (uint32_t)cfg->encode_sparse_ratio &&
 	    max > (uint32_t)cfg->encode_sparse_safe) {
 		if (!cfg->encode_sparse_convert) {
-			diag_set(ClientError, ER_PROC_LUA,
-				 "excessively sparse array");
+			diag_set(LuajitError, "excessively sparse array");
 			return -1;
 		}
 		field->type = MP_MAP;
@@ -515,8 +510,7 @@ luaL_tofield(struct lua_State *L, struct luaL_serializer *cfg, int index,
 #define CHECK_NUMBER(x) ({							\
 	if (!isfinite(x) && !cfg->encode_invalid_numbers) {			\
 		if (!cfg->encode_invalid_as_nil) {				\
-			diag_set(ClientError, ER_PROC_LUA,			\
-				 "number must not be NaN or Inf");		\
+			diag_set(LuajitError, "number must not be NaN or Inf");	\
 			return -1;						\
 		}								\
 		field->type = MP_NIL;						\
@@ -539,7 +533,7 @@ luaL_tofield(struct lua_State *L, struct luaL_serializer *cfg, int index,
 			field->dval = num;
 			CHECK_NUMBER(num);
 		}
-		break;
+		return 0;
 	case LUA_TCDATA:
 	{
 		GCcdata *cd = cdataV(L->base + index - 1);
@@ -550,85 +544,84 @@ luaL_tofield(struct lua_State *L, struct luaL_serializer *cfg, int index,
 		case CTID_BOOL:
 			field->type = MP_BOOL;
 			field->bval = *(bool*) cdata;
-			break;
+			return 0;
 		case CTID_CCHAR:
 		case CTID_INT8:
 			ival = *(int8_t *) cdata;
 			field->type = (ival >= 0) ? MP_UINT : MP_INT;
 			field->ival = ival;
-			break;
+			return 0;
 		case CTID_INT16:
 			ival = *(int16_t *) cdata;
 			field->type = (ival >= 0) ? MP_UINT : MP_INT;
 			field->ival = ival;
-			break;
+			return 0;
 		case CTID_INT32:
 			ival = *(int32_t *) cdata;
 			field->type = (ival >= 0) ? MP_UINT : MP_INT;
 			field->ival = ival;
-			break;
+			return 0;
 		case CTID_INT64:
 			ival = *(int64_t *) cdata;
 			field->type = (ival >= 0) ? MP_UINT : MP_INT;
 			field->ival = ival;
-			break;
+			return 0;
 		case CTID_UINT8:
 			field->type = MP_UINT;
 			field->ival = *(uint8_t *) cdata;
-			break;
+			return 0;
 		case CTID_UINT16:
 			field->type = MP_UINT;
 			field->ival = *(uint16_t *) cdata;
-			break;
+			return 0;
 		case CTID_UINT32:
 			field->type = MP_UINT;
 			field->ival = *(uint32_t *) cdata;
-			break;
+			return 0;
 		case CTID_UINT64:
 			field->type = MP_UINT;
 			field->ival = *(uint64_t *) cdata;
-			break;
+			return 0;
 		case CTID_FLOAT:
 			field->type = MP_FLOAT;
 			field->fval = *(float *) cdata;
 			CHECK_NUMBER(field->fval);
-			break;
+			return 0;
 		case CTID_DOUBLE:
 			field->type = MP_DOUBLE;
 			field->dval = *(double *) cdata;
 			CHECK_NUMBER(field->dval);
-			break;
+			return 0;
 		case CTID_P_CVOID:
 		case CTID_P_VOID:
 			if (*(void **) cdata == NULL) {
 				field->type = MP_NIL;
-				break;
+				return 0;
 			}
 			/* Fall through */
 		default:
 			field->type = MP_EXT;
-			break;
 		}
-		break;
+		return 0;
 	}
 	case LUA_TBOOLEAN:
 		field->type = MP_BOOL;
 		field->bval = lua_toboolean(L, index);
-		break;
+		return 0;
 	case LUA_TNIL:
 		field->type = MP_NIL;
-		break;
+		return 0;
 	case LUA_TSTRING:
 		field->sval.data = lua_tolstring(L, index, &size);
 		field->sval.len = (uint32_t) size;
 		field->type = MP_STR;
-		break;
+		return 0;
 	case LUA_TTABLE:
 	{
 		field->compact = false;
 		if (lua_field_inspect_table(L, cfg, index, field) < 0)
 			return -1;
-		break;
+		return 0;
 	}
 	case LUA_TLIGHTUSERDATA:
 	case LUA_TUSERDATA:
@@ -636,12 +629,11 @@ luaL_tofield(struct lua_State *L, struct luaL_serializer *cfg, int index,
 		field->sval.len = 0;
 		if (lua_touserdata(L, index) == NULL) {
 			field->type = MP_NIL;
-			break;
+			return 0;
 		}
 		/* Fall through */
 	default:
 		field->type = MP_EXT;
-		break;
 	}
 #undef CHECK_NUMBER
 	return 0;


New versions:

commit 3080ab1d7d2e8d8716ac91fc71150db7cde4ffe4
Author: Mergen Imeev <imeevma@gmail.com>
Date:   Fri Jan 11 21:16:12 2019 +0300

    lua: remove exceptions from function luaL_tofield()
    
    Before this commit, the luaL_tofield() function threw a Lua
    exception when an error occurred. This behavior has been changed
    in this commit, now it sets diag_set() and returns -1 in case of
    an error.
    
    Needed for ...3505

diff --git a/src/box/lua/call.c b/src/box/lua/call.c
index 52939ae..2049ee5 100644
--- a/src/box/lua/call.c
+++ b/src/box/lua/call.c
@@ -164,7 +164,8 @@ luamp_encode_call_16(lua_State *L, struct luaL_serializer *cfg,
 		 */
 		for (int i = 1; i <= nrets; ++i) {
 			struct luaL_field field;
-			luaL_tofield(L, cfg, i, &field);
+			if (luaL_tofield(L, cfg, i, &field) < 0)
+				return luaT_error(L);
 			struct tuple *tuple;
 			if (field.type == MP_EXT &&
 			    (tuple = luaT_istuple(L, i)) != NULL) {
@@ -192,7 +193,8 @@ luamp_encode_call_16(lua_State *L, struct luaL_serializer *cfg,
 	 * Inspect the first result
 	 */
 	struct luaL_field root;
-	luaL_tofield(L, cfg, 1, &root);
+	if (luaL_tofield(L, cfg, 1, &root) < 0)
+		return luaT_error(L);
 	struct tuple *tuple;
 	if (root.type == MP_EXT && (tuple = luaT_istuple(L, 1)) != NULL) {
 		/* `return box.tuple()` */
@@ -221,7 +223,8 @@ luamp_encode_call_16(lua_State *L, struct luaL_serializer *cfg,
 	for (uint32_t t = 1; t <= root.size; t++) {
 		lua_rawgeti(L, 1, t);
 		struct luaL_field field;
-		luaL_tofield(L, cfg, -1, &field);
+		if (luaL_tofield(L, cfg, -1, &field) < 0)
+			return luaT_error(L);
 		if (field.type == MP_EXT && (tuple = luaT_istuple(L, -1))) {
 			tuple_to_mpstream(tuple, stream);
 		} else if (field.type != MP_ARRAY) {
diff --git a/src/box/lua/tuple.c b/src/box/lua/tuple.c
index 1867f81..f76d656 100644
--- a/src/box/lua/tuple.c
+++ b/src/box/lua/tuple.c
@@ -223,7 +223,8 @@ luamp_convert_key(struct lua_State *L, struct luaL_serializer *cfg,
 		return tuple_to_mpstream(tuple, stream);
 
 	struct luaL_field field;
-	luaL_tofield(L, cfg, index, &field);
+	if (luaL_tofield(L, cfg, index, &field) < 0)
+		luaT_error(L);
 	if (field.type == MP_ARRAY) {
 		lua_pushvalue(L, index);
 		luamp_encode_r(L, cfg, stream, &field, 0);
diff --git a/src/lua/msgpack.c b/src/lua/msgpack.c
index b470060..1b1874e 100644
--- a/src/lua/msgpack.c
+++ b/src/lua/msgpack.c
@@ -149,10 +149,12 @@ restart: /* used by MP_EXT */
 		lua_pushnil(L);  /* first key */
 		while (lua_next(L, top) != 0) {
 			lua_pushvalue(L, -2); /* push a copy of key to top */
-			luaL_tofield(L, cfg, lua_gettop(L), field);
+			if (luaL_tofield(L, cfg, lua_gettop(L), field) < 0)
+				return luaT_error(L);
 			luamp_encode_r(L, cfg, stream, field, level + 1);
 			lua_pop(L, 1); /* pop a copy of key */
-			luaL_tofield(L, cfg, lua_gettop(L), field);
+			if (luaL_tofield(L, cfg, lua_gettop(L), field) < 0)
+				return luaT_error(L);
 			luamp_encode_r(L, cfg, stream, field, level + 1);
 			lua_pop(L, 1); /* pop value */
 		}
@@ -168,7 +170,8 @@ restart: /* used by MP_EXT */
 		mpstream_encode_array(stream, size);
 		for (uint32_t i = 0; i < size; i++) {
 			lua_rawgeti(L, top, i + 1);
-			luaL_tofield(L, cfg, top + 1, field);
+			if (luaL_tofield(L, cfg, top + 1, field) < 0)
+				return luaT_error(L);
 			luamp_encode_r(L, cfg, stream, field, level + 1);
 			lua_pop(L, 1);
 		}
@@ -203,7 +206,8 @@ luamp_encode(struct lua_State *L, struct luaL_serializer *cfg,
 	}
 
 	struct luaL_field field;
-	luaL_tofield(L, cfg, lua_gettop(L), &field);
+	if (luaL_tofield(L, cfg, lua_gettop(L), &field) < 0)
+		return luaT_error(L);
 	enum mp_type top_type = luamp_encode_r(L, cfg, stream, &field, 0);
 
 	if (!on_top) {
diff --git a/src/lua/utils.c b/src/lua/utils.c
index 978fe61..c10403d 100644
--- a/src/lua/utils.c
+++ b/src/lua/utils.c
@@ -383,12 +383,13 @@ lua_field_inspect_ucdata(struct lua_State *L, struct luaL_serializer *cfg,
 		lua_pcall(L, 1, 1, 0);
 		/* replace obj with the unpacked value */
 		lua_replace(L, idx);
-		luaL_tofield(L, cfg, idx, field);
+		if (luaL_tofield(L, cfg, idx, field) < 0)
+			luaT_error(L);
 	} /* else ignore lua_gettable exceptions */
 	lua_settop(L, top); /* remove temporary objects */
 }
 
-static void
+static int
 lua_field_inspect_table(struct lua_State *L, struct luaL_serializer *cfg,
 			int idx, struct luaL_field *field)
 {
@@ -408,10 +409,10 @@ lua_field_inspect_table(struct lua_State *L, struct luaL_serializer *cfg,
 		lua_call(L, 1, 1);
 		/* replace obj with the unpacked value */
 		lua_replace(L, idx);
-		luaL_tofield(L, cfg, idx, field);
-		return;
+		return luaL_tofield(L, cfg, idx, field);
 	} else if (!lua_isstring(L, -1)) {
-		luaL_error(L, "invalid " LUAL_SERIALIZE  " value");
+		diag_set(LuajitError, "invalid " LUAL_SERIALIZE " value");
+		return -1;
 	}
 
 	type = lua_tostring(L, -1);
@@ -424,7 +425,7 @@ lua_field_inspect_table(struct lua_State *L, struct luaL_serializer *cfg,
 			field->compact = true;
 		lua_pop(L, 1); /* type */
 
-		return;
+		return 0;
 	} else if (strcmp(type, "map") == 0 || strcmp(type, "mapping") == 0) {
 		field->type = MP_MAP;   /* Override type */
 		field->size = luaL_maplen(L, idx);
@@ -432,9 +433,10 @@ lua_field_inspect_table(struct lua_State *L, struct luaL_serializer *cfg,
 		if (cfg->has_compact && type[3] == '\0')
 			field->compact = true;
 		lua_pop(L, 1); /* type */
-		return;
+		return 0;
 	} else {
-		luaL_error(L, "invalid " LUAL_SERIALIZE "  value");
+		diag_set(LuajitError, "invalid " LUAL_SERIALIZE " value");
+		return -1;
 	}
 
 skip:
@@ -456,7 +458,7 @@ skip:
 			}
 			field->type = MP_MAP;
 			field->size = size;
-			return;
+			return 0;
 		}
 		if (k > max)
 			max = k;
@@ -466,15 +468,18 @@ skip:
 	if (cfg->encode_sparse_ratio > 0 &&
 	    max > size * (uint32_t)cfg->encode_sparse_ratio &&
 	    max > (uint32_t)cfg->encode_sparse_safe) {
-		if (!cfg->encode_sparse_convert)
-			luaL_error(L, "excessively sparse array");
+		if (!cfg->encode_sparse_convert) {
+			diag_set(LuajitError, "excessively sparse array");
+			return -1;
+		}
 		field->type = MP_MAP;
 		field->size = size;
-		return;
+		return 0;
 	}
 
 	assert(field->type == MP_ARRAY);
 	field->size = max;
+	return 0;
 }
 
 static void
@@ -487,12 +492,13 @@ lua_field_tostring(struct lua_State *L, struct luaL_serializer *cfg, int idx,
 	lua_call(L, 1, 1);
 	lua_replace(L, idx);
 	lua_settop(L, top);
-	luaL_tofield(L, cfg, idx, field);
+	if (luaL_tofield(L, cfg, idx, field) < 0)
+		luaT_error(L);
 }
 
-void
+int
 luaL_tofield(struct lua_State *L, struct luaL_serializer *cfg, int index,
-		 struct luaL_field *field)
+	     struct luaL_field *field)
 {
 	if (index < 0)
 		index = lua_gettop(L) + index + 1;
@@ -501,10 +507,12 @@ luaL_tofield(struct lua_State *L, struct luaL_serializer *cfg, int index,
 	double intpart;
 	size_t size;
 
-#define CHECK_NUMBER(x) ({\
-	if (!isfinite(x) && !cfg->encode_invalid_numbers) {		\
-		if (!cfg->encode_invalid_as_nil)				\
-			luaL_error(L, "number must not be NaN or Inf");		\
+#define CHECK_NUMBER(x) ({							\
+	if (!isfinite(x) && !cfg->encode_invalid_numbers) {			\
+		if (!cfg->encode_invalid_as_nil) {				\
+			diag_set(LuajitError, "number must not be NaN or Inf");	\
+			return -1;						\
+		}								\
 		field->type = MP_NIL;						\
 	}})
 
@@ -525,94 +533,95 @@ luaL_tofield(struct lua_State *L, struct luaL_serializer *cfg, int index,
 			field->dval = num;
 			CHECK_NUMBER(num);
 		}
-		return;
+		return 0;
 	case LUA_TCDATA:
 	{
-		uint32_t ctypeid = 0;
-		void *cdata = luaL_checkcdata(L, index, &ctypeid);
+		GCcdata *cd = cdataV(L->base + index - 1);
+		void *cdata = (void *)cdataptr(cd);
+
 		int64_t ival;
-		switch (ctypeid) {
+		switch (cd->ctypeid) {
 		case CTID_BOOL:
 			field->type = MP_BOOL;
 			field->bval = *(bool*) cdata;
-			return;
+			return 0;
 		case CTID_CCHAR:
 		case CTID_INT8:
 			ival = *(int8_t *) cdata;
 			field->type = (ival >= 0) ? MP_UINT : MP_INT;
 			field->ival = ival;
-			return;
+			return 0;
 		case CTID_INT16:
 			ival = *(int16_t *) cdata;
 			field->type = (ival >= 0) ? MP_UINT : MP_INT;
 			field->ival = ival;
-			return;
+			return 0;
 		case CTID_INT32:
 			ival = *(int32_t *) cdata;
 			field->type = (ival >= 0) ? MP_UINT : MP_INT;
 			field->ival = ival;
-			return;
+			return 0;
 		case CTID_INT64:
 			ival = *(int64_t *) cdata;
 			field->type = (ival >= 0) ? MP_UINT : MP_INT;
 			field->ival = ival;
-			return;
+			return 0;
 		case CTID_UINT8:
 			field->type = MP_UINT;
 			field->ival = *(uint8_t *) cdata;
-			return;
+			return 0;
 		case CTID_UINT16:
 			field->type = MP_UINT;
 			field->ival = *(uint16_t *) cdata;
-			return;
+			return 0;
 		case CTID_UINT32:
 			field->type = MP_UINT;
 			field->ival = *(uint32_t *) cdata;
-			return;
+			return 0;
 		case CTID_UINT64:
 			field->type = MP_UINT;
 			field->ival = *(uint64_t *) cdata;
-			return;
+			return 0;
 		case CTID_FLOAT:
 			field->type = MP_FLOAT;
 			field->fval = *(float *) cdata;
 			CHECK_NUMBER(field->fval);
-			return;
+			return 0;
 		case CTID_DOUBLE:
 			field->type = MP_DOUBLE;
 			field->dval = *(double *) cdata;
 			CHECK_NUMBER(field->dval);
-			return;
+			return 0;
 		case CTID_P_CVOID:
 		case CTID_P_VOID:
 			if (*(void **) cdata == NULL) {
 				field->type = MP_NIL;
-				return;
+				return 0;
 			}
 			/* Fall through */
 		default:
 			field->type = MP_EXT;
-			return;
 		}
-		return;
+		return 0;
 	}
 	case LUA_TBOOLEAN:
 		field->type = MP_BOOL;
 		field->bval = lua_toboolean(L, index);
-		return;
+		return 0;
 	case LUA_TNIL:
 		field->type = MP_NIL;
-		return;
+		return 0;
 	case LUA_TSTRING:
 		field->sval.data = lua_tolstring(L, index, &size);
 		field->sval.len = (uint32_t) size;
 		field->type = MP_STR;
-		return;
+		return 0;
 	case LUA_TTABLE:
 	{
 		field->compact = false;
-		lua_field_inspect_table(L, cfg, index, field);
-		return;
+		if (lua_field_inspect_table(L, cfg, index, field) < 0)
+			return -1;
+		return 0;
 	}
 	case LUA_TLIGHTUSERDATA:
 	case LUA_TUSERDATA:
@@ -620,14 +629,14 @@ luaL_tofield(struct lua_State *L, struct luaL_serializer *cfg, int index,
 		field->sval.len = 0;
 		if (lua_touserdata(L, index) == NULL) {
 			field->type = MP_NIL;
-			return;
+			return 0;
 		}
 		/* Fall through */
 	default:
 		field->type = MP_EXT;
-		return;
 	}
 #undef CHECK_NUMBER
+	return 0;
 }
 
 void
diff --git a/src/lua/utils.h b/src/lua/utils.h
index a47e3d2..fde3514 100644
--- a/src/lua/utils.h
+++ b/src/lua/utils.h
@@ -304,8 +304,11 @@ struct luaL_field {
  * @param cfg configuration
  * @param index stack index
  * @param field conversion result
+ *
+ * @retval  0 Success.
+ * @retval -1 Error.
  */
-void
+int
 luaL_tofield(struct lua_State *L, struct luaL_serializer *cfg, int index,
 	     struct luaL_field *field);
 
@@ -345,7 +348,8 @@ static inline void
 luaL_checkfield(struct lua_State *L, struct luaL_serializer *cfg, int idx,
 		struct luaL_field *field)
 {
-	luaL_tofield(L, cfg, idx, field);
+	if (luaL_tofield(L, cfg, idx, field) < 0)
+		luaT_error(L);
 	if (field->type != MP_EXT)
 		return;
 	luaL_convertfield(L, cfg, idx, field);
-- 
2.7.4

  reply	other threads:[~2019-01-19 13:21 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-01-19 13:20 [tarantool-patches] [PATCH v8 0/6] sql: remove box.sql.execute imeevma
2019-01-19 13:20 ` imeevma [this message]
2019-01-22 19:58   ` [tarantool-patches] Re: [PATCH v8 1/6] lua: remove exceptions from function luaL_tofield() Vladislav Shpilevoy
2019-01-24  7:27     ` Imeev Mergen
2019-01-29 20:42   ` Vladislav Shpilevoy
2019-01-19 13:20 ` [tarantool-patches] [PATCH v8 2/6] iproto: move map creation to sql_response_dump() imeevma
2019-01-25 16:07   ` [tarantool-patches] " Konstantin Osipov
2019-01-29 20:42     ` Vladislav Shpilevoy
2019-01-19 13:20 ` [tarantool-patches] [PATCH v8 3/6] iproto: create port_sql imeevma
2019-01-19 13:20 ` [tarantool-patches] [PATCH v8 4/6] lua: create method dump_lua for port_sql imeevma
2019-01-29 20:42   ` [tarantool-patches] " Vladislav Shpilevoy
2019-01-19 13:20 ` [tarantool-patches] [PATCH v8 5/6] lua: parameter binding for new execute() imeevma
2019-01-19 13:20 ` [tarantool-patches] [PATCH v8 6/6] sql: check new box.sql.execute() imeevma
2019-01-22 19:58 ` [tarantool-patches] Re: [PATCH v8 0/6] sql: remove box.sql.execute Vladislav Shpilevoy
2019-01-24  7:31   ` Imeev Mergen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f3d5e7ec4d7b75f81a022ce196fc2a8fdd4f5b98.1547902954.git.imeevma@gmail.com \
    --to=imeevma@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --cc=v.shpilevoy@tarantool.org \
    --subject='Re: [tarantool-patches] [PATCH v8 1/6] lua: remove exceptions from function luaL_tofield()' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox