- Code: Select all
--does string math
--acceptable values:
--numbers .+-*/^ ()
--math library functions
--this function does this validation so that you can be certain it cant execute arbitrary lua code.
--vars array is optional, if you pass in an array of variables and values they will be substituted before calculation
--********************************
function string_math(str,vars)
for k,v in pairs(vars) do
str=string.gsub(str,k,v)
end --for
end --if
--now all variables have been substituted, test if string is math ONLY
--(do not allow arbitrary lua code execution)
--is there a reason to define this array globaly or external to the function?
local allowed={"math%.abs","math%.acos","math%.asin","math%.atan","math%.ceil",
"math%.cos","math%.deg","math%.exp","math%.floor","math%.fmod","math%.huge",
"math%.log","math%.max","math%.maxinteger","math%.min","math%.mininteger",
"math%.modf","math%.pi","math%.rad","math%.random","math%.randomseed",
"math%.sin","math%.sqrt","math%.tan","math%.tointeger","math%.type","math%.ult",
"1","2","3","4","5","6","7","8","9","%.","+","-","*","/","%^","%(","%)",","," "}
local test=str
for k,v in pairs(allowed) do
test=string.gsub(test,v,"0") --change EVERYTHING that is allowed into 0
end --for a
--so why change everything to 0 instead of just ""? paranoia, it means
--something like mathmath.pi.floor cant slip through, although I am not
--certain what someone could do with that anyway
--math.pi3 CAN slip through, but again, I'm not certain what someone could
--do with that.
test=string.gsub(test,"0","") --remove all zeros
local rslt=""
if test=="" then --if the string was good, it should now be empty
rslt=loadstring("return "..str.."+0")()
else
rslt="Invalid String"
end --if test==""
return rslt
end --string_math
---example call:
- Code: Select all
local vars={clowns=3,monkeys=5,ringmasters=1}
str="math.floor((clowns+monkeys)/(ringmasters*math.pi))" --this would probably be read in from a settings file
circus=string_math(str,vars)
and now circus=2
So, what is the purpose of this?
I'm using it to allow values as formulas to be put into a settings file instead of having to be coded into the init.lua
So the user can say in the setting file:
tentsize=(monkeys*clowns)/ringmasters
and my lua can read that in and calculate the result on the fly.
I think a settings file is a bit more accessible for many users.
PLUS, it has the advantage that updating the code does not wipe out all of the users settings/preferences.
I just needed a way to be able to do MATH on the settings with variables so the user could enter formulas. But I'm paranoid and wanted to try and limit arbitrary lua code execution