Last active
March 23, 2026 09:26
-
-
Save depthso/9b99778a52b9fe7e497d8426d89c6e55 to your computer and use it in GitHub Desktop.
Check the types of arguments passed into a function to prevent type attacks such as table attacks mimicking Objects
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --[[ | |
| Created by @depso (depthso) | |
| Example usage: | |
| local BindedFunction = Module:BindFunction( | |
| {"string", "number"}, | |
| function(A: string, B: number) | |
| print("Pass! Hello", A, "you are", B, "years old!") | |
| end | |
| ) | |
| BindedFunction("Max", 10) -- Correct | |
| BindedFunction("Max", "10") -- Incorrect | |
| local BindedFunctionMulti = Module:BindFunction( | |
| {"string", { | |
| { | |
| "number" | |
| }, | |
| "number", | |
| "number", | |
| }}, | |
| function(...) | |
| print("Pass!") | |
| end | |
| ) | |
| BindedFunctionMulti("Max", { | |
| { | |
| 10 | |
| }, | |
| 20, | |
| 30 | |
| }) -- Correct | |
| BindedFunctionMulti("Max", { | |
| { | |
| 10 | |
| }, | |
| 10 | |
| }) -- Incorrect | |
| local BindedFunctionDict = Module:BindFunction( | |
| { | |
| "string", | |
| { | |
| "number", | |
| { | |
| ["number"] = { | |
| ["string"] = "string", | |
| }, | |
| ["string"] = { | |
| "string" -- probkem | |
| } | |
| } | |
| } | |
| }, | |
| function(...) | |
| print("Pass!") | |
| end | |
| ) | |
| BindedFunctionDict("Max", { | |
| 10, | |
| { | |
| [20] = { | |
| ["Hello"] = "World", | |
| }, | |
| ["Hello"] = { | |
| "World" | |
| } | |
| } | |
| }) -- Correct | |
| BindedFunctionDict("Max", { | |
| 10, | |
| { | |
| [20] = { | |
| [10] = "World", | |
| }, | |
| ["Hello"] = { | |
| "World" | |
| } | |
| }, | |
| }) -- Incorrect | |
| BindedFunctionDict("Max", { | |
| 10, | |
| { | |
| [20] = { | |
| ["10"] = 10, | |
| }, | |
| ["Hello"] = { | |
| "World" | |
| } | |
| }, | |
| }) -- Incorrect | |
| BindedFunctionDict("Max", { | |
| "string", | |
| { | |
| [20] = { | |
| ["H"] = "World", | |
| }, | |
| ["Hello"] = { | |
| "World" | |
| } | |
| }, | |
| }) -- Incorrect | |
| ]] | |
| --!native | |
| -- Created by @depso (depthso) | |
| local Module = {} | |
| --// Types | |
| type ArgumentTypes = {string | ArgumentTypes} | |
| type Function = (...any) -> (...any) | |
| function Module:_CompareArgs(A, B, ExpectedA, ExpectedB): boolean | |
| --// Types | |
| local AType = typeof(A) | |
| local BType = typeof(B) | |
| --// Check for args overflow | |
| if not ExpectedB then return false end | |
| --// String type comparsion | |
| if typeof(ExpectedA) == "string" and AType ~= ExpectedA then return false end | |
| if typeof(ExpectedB) == "string" and BType ~= ExpectedB then return false end | |
| --// Recursive tables | |
| if AType == "table" then | |
| if not self:_Validate(ExpectedA, A) then | |
| return false | |
| end | |
| end | |
| if BType == "table" then | |
| if not self:_Validate(ExpectedB, B) then | |
| return false | |
| end | |
| end | |
| return true | |
| end | |
| function Module:_Validate(ExpectedTypes: ArgumentTypes, Packed: {any}): boolean | |
| local IsArray = typeof(next(ExpectedTypes)) == "number" | |
| local Cursor = nil | |
| for A, B in next, Packed do | |
| local ExpectedA, ExpectedB | |
| --// Fetch expected types | |
| if IsArray then | |
| ExpectedA, ExpectedB = next(ExpectedTypes, Cursor) | |
| Cursor = ExpectedA | |
| else | |
| ExpectedB = ExpectedTypes[typeof(A)] | |
| end | |
| --// Compare entry to expected types | |
| if not self:_CompareArgs(A, B, ExpectedA, ExpectedB) then | |
| return false | |
| end | |
| end | |
| --// Args count check (minium) | |
| if IsArray and next(ExpectedTypes, Cursor) ~= nil then | |
| return false | |
| end | |
| return true | |
| end | |
| function Module:BindFunction<t>(Args: ArgumentTypes, Func: t & Function): t | |
| return @native function(...) | |
| --if not self:_Validate(Args, {...}) then print("Args error") return end -- Without producing an error | |
| assert(self:_Validate(Args, {...}), "Invalid arguments passed to function!") | |
| return Func(...) | |
| end | |
| end | |
| return Module |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment