mirror of
https://github.com/neovim/neovim.git
synced 2026-01-22 12:50:37 +00:00
Problem: Build is not reproducible, because generated source files (.c/.h/) are not deterministic, mostly because Lua pairs() is unordered by design (for security). https://github.com/LuaJIT/LuaJIT/issues/626#issuecomment-707005671 https://www.lua.org/manual/5.1/manual.html#pdf-next > The order in which the indices are enumerated is not specified [...] > >> The hardening of the VM deliberately randomizes string hashes. This in >> turn randomizes the iteration order of tables with string keys. Solution: - Update the code generation scripts to be deterministic. - That is only a partial solution: the exported function (funcs_metadata.generated.h) and ui event (ui_events_metadata.generated.h) metadata have some mpack'ed tables, which are not serialized deterministically. - As a workaround, introduce `PRG_GEN_LUA` cmake setting, so you can inject a modified build of luajit (with LUAJIT_SECURITY_PRN=0) that preserves table order. - Longer-term we should change the mpack'ed data structure so it no longer uses tables keyed by strings. Closes #20124 Co-Authored-By: dundargoc <gocdundar@gmail.com> Co-Authored-By: Arnout Engelen <arnout@bzzt.net>
81 lines
1.8 KiB
Lua
81 lines
1.8 KiB
Lua
local nvimsrcdir = arg[1]
|
|
local shared_file = arg[2]
|
|
local funcs_file = arg[3]
|
|
local defs_file = arg[4]
|
|
|
|
_G.vim = loadfile(shared_file)()
|
|
|
|
if nvimsrcdir == '--help' then
|
|
print([[
|
|
Usage:
|
|
lua gen_keyset.lua TODOFIXUPDATETHIS
|
|
|
|
Will generate build/src/nvim/auto/keyset.generated.h with definition of functions
|
|
static const array.
|
|
]])
|
|
os.exit(0)
|
|
end
|
|
|
|
|
|
package.path = nvimsrcdir .. '/?.lua;' .. package.path
|
|
local hashy = require'generators.hashy'
|
|
|
|
local funcspipe = io.open(funcs_file, 'wb')
|
|
local defspipe = io.open(defs_file, 'wb')
|
|
|
|
local keysets = require'api.keysets'
|
|
|
|
local keywords = {
|
|
register = true;
|
|
default = true;
|
|
}
|
|
|
|
local function sanitize(key)
|
|
if keywords[key] then
|
|
return key .. "_"
|
|
end
|
|
return key
|
|
end
|
|
|
|
for _, v in ipairs(keysets) do
|
|
local name = v[1]
|
|
local keys = v[2]
|
|
local neworder, hashfun = hashy.hashy_hash(name, keys, function (idx)
|
|
return name.."_table["..idx.."].str"
|
|
end)
|
|
|
|
defspipe:write("typedef struct {\n")
|
|
for _, key in ipairs(neworder) do
|
|
defspipe:write(" Object "..sanitize(key)..";\n")
|
|
end
|
|
defspipe:write("} KeyDict_"..name..";\n\n")
|
|
|
|
defspipe:write("extern KeySetLink "..name.."_table[];\n")
|
|
|
|
funcspipe:write("KeySetLink "..name.."_table[] = {\n")
|
|
for _, key in ipairs(neworder) do
|
|
funcspipe:write(' {"'..key..'", offsetof(KeyDict_'..name..", "..sanitize(key)..")},\n")
|
|
end
|
|
funcspipe:write(' {NULL, 0},\n')
|
|
funcspipe:write("};\n\n")
|
|
|
|
funcspipe:write(hashfun)
|
|
|
|
funcspipe:write([[
|
|
Object *KeyDict_]]..name..[[_get_field(void *retval, const char *str, size_t len)
|
|
{
|
|
int hash = ]]..name..[[_hash(str, len);
|
|
if (hash == -1) {
|
|
return NULL;
|
|
}
|
|
|
|
return (Object *)((char *)retval + ]]..name..[[_table[hash].ptr_off);
|
|
}
|
|
|
|
]])
|
|
defspipe:write("#define api_free_keydict_"..name.."(x) api_free_keydict(x, "..name.."_table)\n")
|
|
end
|
|
|
|
funcspipe:close()
|
|
defspipe:close()
|