Jump to content

Lua "bug" NaN, Inf, -Inf


Recommended Posts

Hey,

due to recent events, I wanted to publish a bug, which was available in my itemshop a few years ago.

In many pub systems written with Lua, it is still present and some people like to take advantage of it.


If we continue the example with the itemshop, it was possible to "buy" items for free.

For example, instead of a number, the client sends the value "NaN" (Not a Number) for the number of items to be bought.

In the quest tonumber() is now executed and "NaN" remains "NaN".

cmd = "NaN" --(sends "NaN" instead of a number)
amount = tonumber(cmd) -- now contains NaN

 

If a comparison now is made, the result is always false:

if amount > 200 then print'The maximum amount is 200.' return end -- FALSE
if amount < 1 then print'The minimum amount is 1.' return end -- FALSE


That is not such a big problem at first.

But if you do a calculation and then compare if the coins are enough, then we have a problem:

cmd = "NaN" --(sends "NaN" instead of a number)
amount = tonumber(cmd) -- now contains NaN
mycoins = 0 -- The number of coins from the Coins column of the account table
itemPrice = 1000 -- Price of the item in the item store
realPrice = itemPrice*amount -- 1000 * NaN => NaN
if mycoins < realPrice then print 'Unfortunately you do not have enough coins.' return end -- FALSE (0 < NaN)
-- Not enough Coins, but it goes on, because the comparison was false.
-- Give item.
-- Item was bought with 0 Coins.

 

Here is a link to it:

http://lua-users.org/wiki/InfAndNanComparisons

 

A script for testing (https://repl.it/ under Lua):

-- cmd is the value sent by the client as example a number of items you want to buy. If you now calculate with this value and send instead of a number NaN, inf, -inf, ...
cmd = "200"
--cmd = "NaN" -- remove comment for testing (sends "NaN" instead of a number)
amount = tonumber(cmd)
-- mycoins is the number of coins, which are in the Coins column of the account table
mycoins = 1000
-- mycoins = 0 -- remove comment for testing (sets existing coins to 0)
itemPrice = 100
 
if amount > 200 then print 'The maximum amount is 200.' return end
if amount < 1 then print 'The minimum amount is 1.' return end
 
realPrice = itemPrice*amount
 
if mycoins < realPrice then print 'Unfortunately you do not have enough coins.' return end
 
newCoins = mycoins-realPrice
 
print('set new coins in db '..newCoins)
print 'give item

 

How it can be fixed, for example:

function IsFinite(num)
    return not (num ~= num or tostring(num) == "inf" or tostring(num) == "-inf" )
end

-- Example call
amount = tonumber("123")
if not IsFinite(amount) then return end -- Everything ok
amount = tonumber("NaN")
if not IsFinite(amount) then return end -- triggers return

 

  • Sad 1
  • Love 4
Link to comment
Share on other sites

Announcements



×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.