[Tarantool-patches] [PATCH] lua: lua_field_inspect_table without pushcfunction

Sergey Kaplun skaplun at tarantool.org
Mon May 25 15:06:33 MSK 2020


On 22.05.20, Alexander Turenko wrote:
> On Mon, May 18, 2020 at 12:37:48PM +0300, Sergey Kaplun wrote:
> > Currently on encoding table we push cfunction (lua_field_try_serialize)
> > to lua stack with additional lightuserdata and table value and after
> > pcall that function to avoid a raise of error.
> 
> It is often used to catch 'not enough memory' error. Say, to avoid a
> leak if some resource should be freed before reporting an error. Or when
> you want to return an error instead of raising it.
> 
> Please, look whether it was added by intention and verify that
> everything still good after the patch.

Hi!

As far as I can tell from the code lua_field_try_serialize hasn't got any calls
of lua API that can raise error about OOM or so on, exept lua_tostring and
lua_pushvalue. But we have already used lua_pushvalue and lua_pushcfunction so
with this patch probability of raising error is smaller (because we need less
arguments to push).

And lua_tolstring calls only after checking type of lua
object so lj_gc_check branch is unreacheble.

504         if (!lua_isstring(L, -1)) {
505 +---  2 lines: diag_set(LuajitError, "invalid " LUAL_SERIALIZE " value");--
507         }
508         const char *type = lua_tostring(L, -1);

491 LUA_API const char *lua_tolstring(lua_State *L, int idx, size_t *len)
492 {
493   TValue *o = index2adr(L, idx);
494   GCstr *s;
495   if (LJ_LIKELY(tvisstr(o))) {
496     s = strV(o);
497   } else if (tvisnumber(o)) {
498     lj_gc_check(L);


If I understand correctly, we must avoid panic when called luaL_tofield. I was
able to come up with a similar example, how to show that the behavior has not
changed. But I am not 100% sure that this test covers all corner cases.
Do you have any idea of a more complete test?


| 13:00:04 jobs:0 burii at root:~/builds_workspace/tarantool/master$
| >>> ../no-ticket-lua-inspect-table-refactoring/src/tarantool 
| Tarantool 2.5.0-32-g7f20272ea
| type 'help' for interactive help
| tarantool> collectgarbage("stop")
|            local source = setmetatable({}, {__serialize = "map"})
|            print("start")
|            for i = 1, 340000 do
|                table.insert(source, (tostring(i)):rep(1024))
|            end
|            print("end")
|            local msgpack = require "msgpack"
|            return  pcall(msgpack.encode, source)
| start
| end
| ---
| - false
| - not enough memory
| ...
| 
| tarantool> 13:00:41 jobs:0 burii at root:~/builds_workspace/tarantool/master$
| >>> src/tarantool 
| Tarantool 2.5.0-1-gad13b6d57
| type 'help' for interactive help
| tarantool> collectgarbage("stop")
|            local source = {}
|            print("start")
|            for i = 1, 340000 do
|                table.insert(source, (tostring(i)):rep(1024))
|            end
|            print("end")
|            local msgpack = require "msgpack"
|            return  pcall(msgpack.encode, source)
| start
| end
| ---
| - false
| - not enough memory
| ...

-- 
Best regards,
Sergey Kaplun


More information about the Tarantool-patches mailing list