mirror of
https://github.com/luanti-org/luanti.git
synced 2025-06-27 16:36:03 +00:00
Deprecate function support in core.[de]serialize
This commit is contained in:
parent
f2ea4a4565
commit
dd2e45ee82
5 changed files with 78 additions and 22 deletions
|
@ -14,11 +14,6 @@ local function basic_dump(o)
|
||||||
return tostring(o)
|
return tostring(o)
|
||||||
elseif tp == "nil" then
|
elseif tp == "nil" then
|
||||||
return "nil"
|
return "nil"
|
||||||
-- Uncomment for full function dumping support.
|
|
||||||
-- Not currently enabled because bytecode isn't very human-readable and
|
|
||||||
-- dump's output is intended for humans.
|
|
||||||
--elseif tp == "function" then
|
|
||||||
-- return string.format("loadstring(%q)", string.dump(o))
|
|
||||||
elseif tp == "userdata" then
|
elseif tp == "userdata" then
|
||||||
return tostring(o)
|
return tostring(o)
|
||||||
else
|
else
|
||||||
|
|
|
@ -190,7 +190,33 @@ local function serialize(value, write)
|
||||||
dump(value)
|
dump(value)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Whether `value` recursively contains a function
|
||||||
|
local function contains_function(value)
|
||||||
|
local seen = {}
|
||||||
|
local function check(val)
|
||||||
|
if type(val) == "function" then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
if type(val) == "table" then
|
||||||
|
if seen[val] then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
seen[val] = true
|
||||||
|
for k, v in pairs(val) do
|
||||||
|
if check(k) or check(v) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return check(value)
|
||||||
|
end
|
||||||
|
|
||||||
function core.serialize(value)
|
function core.serialize(value)
|
||||||
|
if contains_function(value) then
|
||||||
|
core.log("deprecated", "Support for dumping functions in `core.serialize` is deprecated.")
|
||||||
|
end
|
||||||
local rope = {}
|
local rope = {}
|
||||||
serialize(value, function(text)
|
serialize(value, function(text)
|
||||||
-- Faster than table.insert(rope, text) on PUC Lua 5.1
|
-- Faster than table.insert(rope, text) on PUC Lua 5.1
|
||||||
|
|
|
@ -93,7 +93,16 @@ describe("serialize", function()
|
||||||
assert_preserves(test_in)
|
assert_preserves(test_in)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("strips functions in safe mode", function()
|
describe("safe mode", function()
|
||||||
|
setup(function()
|
||||||
|
assert(not core.log)
|
||||||
|
-- logging a deprecation warning will be attempted
|
||||||
|
function core.log() end
|
||||||
|
end)
|
||||||
|
teardown(function()
|
||||||
|
core.log = nil
|
||||||
|
end)
|
||||||
|
it("functions are stripped", function()
|
||||||
local test_in = {
|
local test_in = {
|
||||||
func = function(a, b)
|
func = function(a, b)
|
||||||
error("test")
|
error("test")
|
||||||
|
@ -109,6 +118,25 @@ describe("serialize", function()
|
||||||
assert.is_nil(test_out.func)
|
assert.is_nil(test_out.func)
|
||||||
assert.equals(test_out.foo, "bar")
|
assert.equals(test_out.foo, "bar")
|
||||||
end)
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("deprecation warnings", function()
|
||||||
|
before_each(function()
|
||||||
|
assert(not core.log)
|
||||||
|
core.log = spy.new(function(level)
|
||||||
|
assert(level == "deprecated")
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
after_each(function()
|
||||||
|
core.log = nil
|
||||||
|
end)
|
||||||
|
it("dumping functions", function()
|
||||||
|
local t = {f = function() end, g = function() end}
|
||||||
|
t.t = t
|
||||||
|
core.serialize(t)
|
||||||
|
assert.spy(core.log).was.called(1) -- should have been called exactly *once*
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
it("vectors work", function()
|
it("vectors work", function()
|
||||||
local v = vector.new(1, 2, 3)
|
local v = vector.new(1, 2, 3)
|
||||||
|
|
|
@ -23,3 +23,5 @@ This list is largely advisory and items may be reevaluated once the time comes.
|
||||||
* stop reading initial properties from bare entity def
|
* stop reading initial properties from bare entity def
|
||||||
* change particle default blend mode to `clip`
|
* change particle default blend mode to `clip`
|
||||||
* remove built-in knockback and related functions entirely
|
* remove built-in knockback and related functions entirely
|
||||||
|
* remove `safe` parameter from `core.serialize`, always enforce `safe = true`.
|
||||||
|
possibly error when `loadstring` calls are encountered in `core.deserialize`.
|
||||||
|
|
|
@ -7611,14 +7611,19 @@ Misc.
|
||||||
* `core.serialize(table)`: returns a string
|
* `core.serialize(table)`: returns a string
|
||||||
* Convert a table containing tables, strings, numbers, booleans and `nil`s
|
* Convert a table containing tables, strings, numbers, booleans and `nil`s
|
||||||
into string form readable by `core.deserialize`
|
into string form readable by `core.deserialize`
|
||||||
|
* Support for dumping function bytecode is **deprecated**.
|
||||||
* Example: `serialize({foo="bar"})`, returns `'return { ["foo"] = "bar" }'`
|
* Example: `serialize({foo="bar"})`, returns `'return { ["foo"] = "bar" }'`
|
||||||
* `core.deserialize(string[, safe])`: returns a table
|
* `core.deserialize(string[, safe])`: returns a table
|
||||||
* Convert a string returned by `core.serialize` into a table
|
* Convert a string returned by `core.serialize` into a table
|
||||||
* `string` is loaded in an empty sandbox environment.
|
* `string` is loaded in an empty sandbox environment.
|
||||||
* Will load functions if safe is false or omitted. Although these functions
|
* Will load functions if `safe` is `false` or omitted.
|
||||||
cannot directly access the global environment, they could bypass this
|
Although these functions cannot directly access the global environment,
|
||||||
restriction with maliciously crafted Lua bytecode if mod security is
|
they could bypass this restriction with maliciously crafted Lua bytecode
|
||||||
disabled.
|
if mod security is disabled.
|
||||||
|
* Will silently strip functions embedded via calls to `loadstring`
|
||||||
|
(typically bytecode dumped by `core.serialize`) if `safe` is `true`.
|
||||||
|
You should not rely on this if possible.
|
||||||
|
* Example: `core.deserialize("return loadstring('')", true)` will be `nil`.
|
||||||
* This function should not be used on untrusted data, regardless of the
|
* This function should not be used on untrusted data, regardless of the
|
||||||
value of `safe`. It is fine to serialize then deserialize user-provided
|
value of `safe`. It is fine to serialize then deserialize user-provided
|
||||||
data, but directly providing user input to deserialize is always unsafe.
|
data, but directly providing user input to deserialize is always unsafe.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue