lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Wed, Apr 18, 2018 at 6:51 AM, Dirk Laurie <dirk.laurie@gmail.com> wrote:

> As in most C libraries, the Lua API functions do not check their arguments for validity or consistency.

That makes perfect sense, once "validity" and "consistency" are unambiguously defined for each API call. As you might have inferred from this and the earlier discussion, I suspect this may not always be the case today.

> However, you can change this behavior by compiling Lua with the macro LUA_USE_APICHECK defined.

I addressed this in the previous discussion.

That said, the fact that the macro exists and the corresponding verification macros are in the code base, it is probably not very painful to identify all the existing API expectations and document them as such. That will probably not cover everything, but it is a good starting point, and it will certainly cover the lua_next() case. Something a student could do, perhaps :)

Looking at the source of Lua 5.3.3, api_check() is used in 30 places directly, in 23 places via api_checknelems(), in 2 places via api_checkstackindex(), 
in 1 place via api_checkvalidindex(), and  in 2 places via checkresults()

Having inspected all that, I have the following list of API functions that have validation code:

lua_arith *
lua_callk
lua_checkstack
lua_compare *
lua_concat
lua_copy
lua_dump
lua_error
lua_getinfo -
lua_getuservalue
lua_next
lua_pcallk
lua_pushcclosure
lua_rawget
lua_rawgeti
lua_rawgetp
lua_rawset
lua_rawseti
lua_rawsetp
lua_resume
lua_rotate *
lua_setfield
lua_setglobal
lua_seti
lua_setmetatable
lua_settable
lua_settop -
lua_setupvalue
lua_setuservalue
lua_typename *
lua_upvalueid
lua_upvaluejoin
lua_xmove
lua_yieldk

The list may be incomplete, because the following internal functions, apparently related to Lua/C transitions and coroutines, also do API checks:

luaD_precall
finishCcall
resume

These would need to be investigated by someone more knowledgeable about Lua's internals.

In the list above, the functions marked with * have some wording in their descriptions that could be interpreted as a specification of "validity", such as "The value of op must be one of the following constants" for lua_arith. This is great but the specs are incomplete and, unfortunately, very rare overall.

The functions marked with - have descriptions that may be interpreted as more permissive than their internal expectations.

lua_getinfo: "This function returns 0 on error (for instance, an invalid option in what)." Yet certain combinations of inputs are fatal. Unless I had looked at the implementation, I would most likely have assumed that invalid input is signalled by the zero return value, not by a crash or some other misbehavior.

lua_settop: "Accepts any index, or 0, and sets the stack top to this index. If the new top is larger than the old one, then the new elements are filled with nil." Yet an attempt to specify a new top value greater that the current stack's size can be fatal. Changing this to "Accepts any acceptable index..." could resolve the ambiguity. I am aware of the statement in the manual that "Except when noted otherwise, functions in the API work with acceptable indices.", but "any index" could be interpreted as "noted otherwise".

In the entire list above, perhaps only lua_callk, lua_getinfo, and lua_pcallk would need an elaborate specification of validity, in all the others, like lua_next(), not much more than the following needs to be said: "The value at the given index must be a table; otherwise, the behavior is undefined".

For the record, api_check() is also used in 34 places via api_incr_top() and 47 places in index2addr(), but I think that is already adequately covered by the manual that documents the API stack discipline.

Cheers,
V.