What lua metamethod is being called here? - lua

I was doing some anti metamethod hooks and I was curious on what metamethod is called in the code below between the parentheses
local test = "random string"
if (test == "random string") then --// What metamethod if any is being called here?
print("equals")
end
I've done some research and took a look at the __eq metamethod, but that is only called when comparing two tables which isn't what I'm tryna do.
If there isn't any metamethod being called then how would I protect the if condition?
-- Update --
What if I put every string inside of a table for example:
local _Table1 = {"Test1", "Test2"}
local _Table2 = {"Test1", "Test2"}
for Index, Value in next, _Table1 do
if Value == _Table2[Index] then
print("Tables Match!")
elseif Value ~= _Table2[Index]
print("Tables Don't Match!")
end
end
I'm not doing any string converting here, but I'm showing what I could try and do for a simple anti tamper.

The only operator in the parenthesized expression is ==. Thus the only metamethod in question is __eq. The Lua Reference Manual states the following on __eq:
__eq: the equal (==) operation. Behavior similar to the addition operation, except that Lua will try a metamethod only when the values being compared are either both tables or both full userdata and they are not primitively equal.
Your values are strings and thus no metamethod will be called - even if you were to modify the string metatable to alter __eq.
Strings in Lua are always interned, so this comparison will always run in constant time. Since it is a primitive comparison, it can't possibly throw an error. No metamethod is called.
There is nothing to protect from: No possible performance issue / DoS vulnerability, no possible fancy side effects or code execution, no possible error.
(Highly theoretically: If a debug hook running every n instructions is registered, it might fire as the comparison is executed. You can hardly "protect" against a debug hook though.)

But it makes sense, for example a check against the Length.
A check against the Content seems also possible but need more lines.
And i like one liner in Lua Standalone to show...
> _VERSION
Lua 5.4
> eqtab = setmetatable({"Test1", "Test2"}, {__eq = function(left, right) print('SIMON SAYS:') return(#left == #right) end})
> eqtab == {1}
SIMON SAYS:
false
> eqtab == {}
SIMON SAYS:
false
> eqtab == {"Test1", "Test2"}
SIMON SAYS:
true
> eqtab == {1, 2}
SIMON SAYS:
true

Related

Why does the doc say `__index` is looked up in the table?

From the Lua 5.3 doc:
__index: The indexing access table[key]. ... The metamethod is looked up in table.
It says the same thing for __newindex, but not for any other metamethod.
If this were true (which it's not), it would be a major departure from previous versions of Lua. The following code outputs nil, as I would expect, but it's inconsistent with the doc.
#!/usr/bin/env lua5.3
local proto = {a = 54}
local t0 = {__index = proto}
print(t0.a)
To be clear: If the doc was correct, I would expect t0 in the above code to only require an __index field without an actual metatable for t0.a to be 54. So does anyone know what's going on with the doc?
You are incorrectly interpreting the meaning of the term. To say that it is "metamethod Y is looked up in X" does not mean that it searches the X table for an entry named Y. It means that it gets the metatable for X and looks up an entry named Y, as if by rawget(getmetatable(X) or {}, "Y"), as specified in the docs.
This terminology is repeatedly used in the metamethod descriptions. For example:
First, Lua will check the first operand (even if it is valid). If that operand does not define a metamethod for __add, then Lua will check the second operand.
It's not asking if the first (or second) operand have a method __add; it asks if they have a metamethod __add.
As you can see from the __add example, you have to specify which of the operands it tries to get metamethods from, and in which order. For table[key], the point of the text is that doesn't try to get the metamethod from key, only from table. That may seem a tad bit obvious, but completeness is better than incompleteness.

Lua custom number concatenation

I have been learning about metatables in Lua and I wanted to implement range operators as in Ruby, so I used this model
debug.setmetatable(1, {
__concat = function(a, b)
if a > b then
error(table.concat({
"attempt to create a range of values with a",
"minimum larger than the maximum"
}, " "))
elseif a == b then
return a
else
return unpack((function(nStart,nEnd)
local nTable = {}
for it = nStart,nEnd do
table.insert(nTable, it)
end
return nTable
end)(a, b))
end
end
})
print(6 .. 6)
But it seems that that it continues to use the default behavior. Is there any way to get this to work? I am aware that I could make a function to emulate the behavior and call it with range(n,n2) or similar but that defeats the purpose. Thanks.
Please see section 3.4.5 of the Lua 5.2 manual.
The string concatenation operator in Lua is denoted by two dots ('..'). If both operands are strings or numbers, then they are converted to strings according to the rules mentioned in §3.4.2. Otherwise, the __concat metamethod is called (see §2.4).
If you want to change this behavior, look into lvm.c, specifically the luaV_concat function.

What's the difference between table.insert(t, i) and t[#t+1] = i?

In Lua, there seem to be two ways of appending an element to an array:
table.insert(t, i)
and
t[#t+1] = i
Which should I use, and why?
Which to use is a matter of preference and circumstance: as the # length operator was introduced in version 5.1, t[#t+1] = i will not work in Lua 5.0, whereas table.insert has been present since 5.0 and will work in both. On the other hand, t[#t+1] = i uses exclusively language-level operators, wheras table.insert involves a function (which has a slight amount of overhead to look up and call and depends on the table module in the environment).
In the second edition of Programming in Lua (an update of the Lua 5.0-oriented first edition), Roberto Ierusalimschy (the designer of Lua) states that he prefers t[#t+1] = i, as it's more visible.
Also, depending on your use case, the answer may be "neither". See the manual entry on the behavior of the length operator:
If the array has "holes" (that is, nil values between other non-nil values), then #t can be any of the indices that directly precedes a nil value (that is, it may consider any such nil value as the end of the array).
As such, if you're dealing with an array with holes, using either one (table.insert uses the length operator) may "append" your value to a lower index in the array than you want. How you define the size of your array in this scenario is up to you, and, again, depends on preference and circumstance: you can use table.maxn (disappearing in 5.2 but trivial to write), you can keep an n field in the table and update it when necessary, you can wrap the table in a metatable, or you could use another solution that better fits your situation (in a loop, a local tsize in the scope immediately outside the loop will often suffice).
The following is slightly on the amusing side but possibly with a grain of aesthetics. Even though there are obvious reasons that mytable:operation() is not supplied like mystring:operation(), one can easily roll one's own variant, and get a third notation if desired.
Table = {}
Table.__index = table
function Table.new()
local t = {}
setmetatable(t, Table)
return t
end
mytable = Table.new()
mytable:insert('Hello')
mytable:insert('World')
for _, s in ipairs(mytable) do
print(s)
end
insert can insert arbitrarily (as its name states), it only defaults to #t + 1, where as t[#t + 1] = i will always append to the (end of the) table. see section 5.5 in the lua manual.
'#' operator only use indexed key table.
t = {1, 2 ,3 ,4, 5, x=1, y=2}
at above code
print(#t) --> print 5 not 7
'#' operator whenever not using.
If you want to '#' operator, then check it to table elements type.
Insert function can using any type use.But element count to work slow than '#'

Lua: How to set a variable to zero

I have variable that contains a number. While Lua allows variables to be set to nil, the variable then becomes toxic - destroying all code in its path.
If a variable contains a nil, I want it converted to a zero.
local score;
score = gameResults.finalScore;
I want to ensure that score contains a number, so I try:
local score;
score = tonumber(gameResults.finalScore);
but that doesn't work. So I try:
local function ToNumberEx(v)
if (v == nil) then
return 0
else
return tonumber(v)
end
local score;
score = ToNumberEx(gameResults.finalScore);
but that doesn't work. So I try:
local function ToNumberEx(v)
if (v == nil) then
return 0
else
return tonumber(v)
end
local score;
score = ToNumberEx(gameResults.finalScore);
if (score == nil) then
score = 0
end
That works, but defeats the purpose of having a function.
What is wrong with the function? I'm sure there is a perfectly reasonable and logical explanation - except to anyone who is familiar with programming languages.
score = tonumber(gameResults.finalScore) or 0
If the argument is already a number or
a string convertible to a number, then
tonumber returns this number;
otherwise, it returns nil.
Your code was good, except you didn't take into account what happens when gameResult.finalScore can't be converted to a number, if it was " " or "stuff" or a table than tonumber would return nil. None of your checks could detect that kind of situation.
If you really want to enforce that this variable gameResults.finalScore has this behavior (set to zero when receives any value different from a number), than you should take a look at Lua metatables.
You could create a metatable for gameResults, and "overwrite" the "index" and "newindex" methods of the metatable, checking the value for the finalScore field, and thus enforcing it's value to be on the desired ranges.
Not the best solution, but depending on your case, could be a good defensive practice against some other "evil developer" on the team. :-)
www.lua.org/pil/13.html (I'm not currently allowed to post more than 1 link) PiL 1 can help too, if you are still using Lua 5.0 or you want a more deep understanding of the metatables concept.

Design disagreement: Security checks

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

Resources