Created
November 27, 2023 02:13
-
-
Save appgurueu/51ab3382fe406bd2e6c3bd087069e586 to your computer and use it in GitHub Desktop.
Randomization of `pairs` traversal order in Lua
This file contains 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
--[[ | |
Randomize `pairs` traversal order to deliberately break code that relies on it. | |
Works by doing a coin toss to decide whether to "postpone" visiting the first entry | |
(visiting it at the end of the traversal). | |
Shuffling all keys, then iterating in that shuffled order would provide more thorough randomization; however: | |
* It is less efficient if the loop is exited early; it may arbitrarily wreck performance | |
(consider a large table where `pairs` is only used to inspect very few entries.) | |
* I believe this simple solution already suffices for most code | |
that incorrectly relies on a specific order of traversal. | |
Notably, this has a 50% chance of breaking code that | |
expects `pairs` to exhibit `ipairs`-like behavior. | |
This does not seed the random for you, | |
so if you want to achieve different outcomes across different runs, | |
seed the random yourself. | |
]] | |
function pairs(tab) | |
local fk, fv = next(tab) | |
local sk = nil | |
if math.random(2) == 1 then | |
sk = fk | |
end | |
local f = sk ~= nil | |
local done = false | |
return function(t, k) | |
if done then | |
return nil | |
end | |
local rk, rv = next(t, k) | |
if rk == nil then | |
done = true | |
if f then | |
f = false | |
return fk, fv | |
end | |
return nil | |
end | |
if f and rawequal(rk, fk) then | |
f = false | |
end | |
return rk, rv | |
end, tab, sk | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment