开发者

Design disagreement: Security checks

开发者 https://www.devze.com 2023-01-29 07:00 出处:网络
We (two people) are doing a project using Lua as an embedded language. My teammate uses argument type checks almost everywhere:

We (two people) are doing a project using Lua as an embedded language.

My teammate uses argument type checks almost everywhere:

function someFunction( a, b,c )
   if a == nil then return end

开发者_开发技巧   --Some stuff here

   if type( b ) ~= "function" then
      Error( "blah" )
   end

   --More here

   if someTable[ c ] == nil then someTable[ c ] = {}
end

I don't really like that as I think that most of those checks are unneccessary.. it kind of takes the "spirit" of using Lua. It also makes the code longer, slower and less readable in my opinion.

In general I would do it this way:

function someFunction( a, b,c )
   --More here

   if someTable[ c ] == nil then someTable[ c ] = {}
end

I leave out almost all type/argument checks and only do those who have a high chance of actually happening.

  • Now we are unsure of what solution is better and decided to ask you: Security checks in Lua - yes or no?


I'm not familiar with Lua, but Wikipedia seems to think it is duck-typed. I'm going to draw an analogy with Python, so forgive me if it's not appropriate.

In Python, functions are designed with the principle that they need an object that meets certain criteria. If you pass in a different object than what the original author intended, as long as it meets the criteria of the function, it should work. The idea being, "if it looks like a duck, walks like a duck, and quacks like a duck, it is a duck." (Hence the name.) That said, there are a few rare instances where you need an object of a specific type, but this is not the general case.

At any rate, you appear to be "fighting the language", which is a code smell in my book. Most languages are designed and intended to be used in certain ways - figure out what principles and design/coding guidelines the Lua community uses, and follow those.


I type check public functions in my api. But do not for only internally used functions. Good type checking:

function ( a , b )
    assert ( type ( a ) == "number" , "Invalid a" )

    b = b or {}
    assert ( type ( b ) == "table" , "B must be a table" )

    c = assert ( type ( c ) == "string" ) and c or "default"
end

Keep in mind though, lua also has a bit of "duck" typing: if all that is required in an object is callable, then a table with a __call method should be allowable. Same for an indexable object: a table and a userdata can both be indexed (not to mention the other types).


I don't know Lua either, and it's a little unclear whether you're asking only about checking the argument types [type(b)~="function"] or do you want to check their values too [a==nil], but here's what I do:

If the function can only ever be called by some other functions of your own, and those other functions have already checked the argument, then there's no need to check it again. On the other hand, if your design doesn't guarantee the safety of your arguments then you do need to check it yourself.

Basically, what can go wrong will go wrong, but it will wait until after you've finished testing and have shipped. You can't take chances - you do need a cast-iron guarantee. The key to choosing your guarantee is to inspect your design and see what you really need.

(Even if the function is only called by your own other functions, you might still want to include checks if you think you might later forget about all this and call it from somewhere else without checking.)


I guess it depends on what you plan to do next: if other people should actually write Lua code to work with your code, it would be useful to check arguments (or make it possible by having something like enableDebug). Something useful I came along yesterday is DecoratorsAndDocstrings which makes it possible to document/typecheck functions without altering the implementation.

Another idiom used for this purpose is :

argument = argument or default -- or
argument = type(argument)=="number" and argument or error'I should get a number'


Now we are unsure of what solution is better and decided to ask you: Security checks in Lua - yes or no?

It depends on the type of the project. If your project is small - i.e. only you and your teammate are going to manage it - it is OK to skip the checks, because you should know that you are passing to functions, and it will make the code small and readable. The downside is that when error occurs - and it may happen somewhere totally unexpected - you'll have to spend time debugging and tracing your functions.

On the other hand, if you are creating an library/API to be used by others, it is very appropriate to do type checking. For the user of your library who doesn't know of the internals, it is very helpful to know when he is passing the wrong arguments.


You need to check types where it is important (and should not check where it is not important). Usually I type-check most of the public function arguments plus I add a check anywhere I encounter a type error when debugging.

To shorten the type checks, I use a small arguments() helper function:

https://github.com/lua-nucleo/lua-nucleo/blob/master/lua-nucleo/args.lua

Example:

https://github.com/lua-aplicado/lua-aplicado/blob/master/lua-aplicado/filesystem.lua#L63-66

local write_file = function(filename, new_data)
  arguments(
      "string", filename,
      "string", new_data
    )

  local file, err = io.open(filename, "w")
  if not file then
    return nil, err
  end

  file:write(new_data)
  file:close()
  file = nil

  return true
end
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号