]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - builtin/common/serialize.lua
ContentDB: Add reason to downloads (#10876)
[dragonfireclient.git] / builtin / common / serialize.lua
index c91d2d5ce6208926608cb27a8a83a85d02d606e2..300b394c63166fa2086d2263be989c0b502d031b 100644 (file)
@@ -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)