From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id 84101267E7 for ; Sat, 19 Jan 2019 08:21:45 -0500 (EST) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 9Gks3yPR_OBu for ; Sat, 19 Jan 2019 08:20:22 -0500 (EST) Received: from smtpng3.m.smailru.net (smtpng3.m.smailru.net [94.100.177.149]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id E002A267BF for ; Sat, 19 Jan 2019 08:20:21 -0500 (EST) From: imeevma@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 Message-Id: In-Reply-To: References: Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-help: List-unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-subscribe: List-owner: List-post: List-archive: To: tarantool-patches@freelists.org, v.shpilevoy@tarantool.org 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 >> #include >> > > 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 [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 >>> #include >>> +#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 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 #include -#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 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