[tarantool-patches] Re: [PATCH v9 4/7] lua: remove exceptions from function luaL_tofield()

Vladislav Shpilevoy v.shpilevoy at tarantool.org
Wed Mar 27 00:48:32 MSK 2019


Thanks for the patch!

>> 2. Looking at lua_field_inspect_table I found that if a table has __serialize
>> metamethod, it is called without a protection (utils.c:409). __serialize is an
>> arbitrary unprotected user code, that can throw an error deliberately. What are
>> we gonna do with that? Personally I've already faced with some user code, throwing
>> an error from __serialize, deliberately. On not critical errors not meaning panic.
>>
>> As a solution we could 1) do not care, again; 2) finally accept the fact that
>> wrap into a pcall was not so bad and use it; 3) use lua_pcall in that
>> particular place. Please, consult Kostja, what does he choose.
> 
> I checked it this way:
> 
> diff --git a/src/lua/utils.c b/src/lua/utils.c
> index bbfc549..eae3b5f 100644
> --- a/src/lua/utils.c
> +++ b/src/lua/utils.c
> @@ -398,6 +398,20 @@ lua_field_inspect_ucdata(struct lua_State *L, struct luaL_serializer *cfg,
>  	lua_settop(L, top); /* remove temporary objects */
>  }
>  
> +/**
> + * Check that the field LUAL_SERIALIZE of the metatable is
> + * available.
> + *
> + * @param L Lua State.
> + */
> +static int
> +get_metafield_serialize(struct lua_State *L)
> +{
> +	int idx = *(int *)lua_topointer(L, -1);
> +	luaL_getmetafield(L, idx, LUAL_SERIALIZE);
> +	return 0;
> +}
> +
>  static int
>  lua_field_inspect_table(struct lua_State *L, struct luaL_serializer *cfg,
>  			int idx, struct luaL_field *field)
> @@ -408,6 +422,9 @@ lua_field_inspect_table(struct lua_State *L, struct luaL_serializer *cfg,
>  	uint32_t max = 0;
>  
>  	/* Try to get field LUAL_SERIALIZER_TYPE from metatable */
> +	if (!cfg->encode_load_metatables &&
> +	    luaT_cpcall(L, get_metafield_serialize, &idx) != 0)
> +		return -1;
>  	if (!cfg->encode_load_metatables ||
>  	    !luaL_getmetafield(L, idx, LUAL_SERIALIZE))
>  		goto skip;
> 

Unfortunately, it was not the place I told about. You
wrapped just a fetch of __serialize function, but not its
call. It is still unsafe on line 435. In other words it was:

    1 func = obj.__serialize
    2 func(obj)

You made it:

    1 func = pcall(function() obj.__serialize end)
    2 func(obj)

The second line is still unsafe. And much more unsafe than
the first one.

But it is a good catch too, because a user could define
such an __index for his metatable, that it throws an error.
You should wrap both __serialize fetch and call into a single
lua_cpcall.




More information about the Tarantool-patches mailing list