X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=builtin%2Fcommon%2Fserialize.lua;h=300b394c63166fa2086d2263be989c0b502d031b;hb=9c145ba0d8baeea57914c62fcc07c06bc6a0257a;hp=c91d2d5ce6208926608cb27a8a83a85d02d606e2;hpb=8e757859d6a6bf6482480904e8485e9344e567ab;p=dragonfireclient.git diff --git a/builtin/common/serialize.lua b/builtin/common/serialize.lua index c91d2d5ce..300b394c6 100644 --- a/builtin/common/serialize.lua +++ b/builtin/common/serialize.lua @@ -120,15 +120,8 @@ function core.serialize(x) elseif tp == "function" then return string.format("loadstring(%q)", string.dump(x)) elseif tp == "number" then - -- Serialize integers with string.format to prevent - -- scientific notation, which doesn't preserve - -- precision and breaks things like node position - -- hashes. Serialize floats normally. - if math.floor(x) == x then - return string.format("%d", x) - else - return tostring(x) - end + -- Serialize numbers reversibly with string.format + return string.format("%.17g", x) elseif tp == "table" then local vals = {} local idx_dumped = {} @@ -177,13 +170,16 @@ end -- Deserialization -local env = { - loadstring = loadstring, -} +local function safe_loadstring(...) + local func, err = loadstring(...) + if func then + setfenv(func, {}) + return func + end + return nil, err +end -local safe_env = { - loadstring = function() end, -} +local function dummy_func() end function core.deserialize(str, safe) if type(str) ~= "string" then @@ -195,7 +191,10 @@ function core.deserialize(str, safe) end local f, err = loadstring(str) if not f then return nil, err end - setfenv(f, safe and safe_env or env) + + -- The environment is recreated every time so deseralized code cannot + -- pollute it with permanent references. + setfenv(f, {loadstring = safe and dummy_func or safe_loadstring}) local good, data = pcall(f) if good then @@ -204,17 +203,3 @@ function core.deserialize(str, safe) return nil, data end end - - --- Unit tests -local test_in = {cat={sound="nyan", speed=400}, dog={sound="woof"}} -local test_out = core.deserialize(core.serialize(test_in)) - -assert(test_in.cat.sound == test_out.cat.sound) -assert(test_in.cat.speed == test_out.cat.speed) -assert(test_in.dog.sound == test_out.dog.sound) - -test_in = {escape_chars="\n\r\t\v\\\"\'", non_european="θשׁ٩∂"} -test_out = core.deserialize(core.serialize(test_in)) -assert(test_in.escape_chars == test_out.escape_chars) -assert(test_in.non_european == test_out.non_european)