libs/core: Add recursion detection to dumptable, serialize_data
Dumptable now writes to stderr
This commit is contained in:
parent
b5b0914ae3
commit
ba22660cb8
2 changed files with 34 additions and 8 deletions
|
@ -616,6 +616,13 @@ function NamedSection.parse(self)
|
||||||
AbstractSection.parse_dynamic(self, s)
|
AbstractSection.parse_dynamic(self, s)
|
||||||
if luci.http.formvalue("cbi.submit") then
|
if luci.http.formvalue("cbi.submit") then
|
||||||
Node.parse(self, s)
|
Node.parse(self, s)
|
||||||
|
|
||||||
|
if not self.override_scheme and self.map.scheme then
|
||||||
|
local co = self.map:get()
|
||||||
|
local stat, err = self.map.validator:validate_section(self.config, s, co)
|
||||||
|
luci.http.prepare_content("text/html")
|
||||||
|
luci.util.dumptable(err)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
AbstractSection.parse_optionals(self, s)
|
AbstractSection.parse_optionals(self, s)
|
||||||
end
|
end
|
||||||
|
@ -705,10 +712,17 @@ function TypedSection.parse(self)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local co
|
||||||
for i, k in ipairs(self:cfgsections()) do
|
for i, k in ipairs(self:cfgsections()) do
|
||||||
AbstractSection.parse_dynamic(self, k)
|
AbstractSection.parse_dynamic(self, k)
|
||||||
if luci.http.formvalue("cbi.submit") then
|
if luci.http.formvalue("cbi.submit") then
|
||||||
Node.parse(self, k)
|
Node.parse(self, k)
|
||||||
|
|
||||||
|
if not self.override_scheme and self.map.scheme then
|
||||||
|
co = co or self.map:get()
|
||||||
|
local stat, err = self.map.uvl:validate_section(self.config, k, co)
|
||||||
|
luci.util.perror(err)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
AbstractSection.parse_optionals(self, k)
|
AbstractSection.parse_optionals(self, k)
|
||||||
end
|
end
|
||||||
|
|
|
@ -185,12 +185,19 @@ end
|
||||||
-- @param t Table value to dump
|
-- @param t Table value to dump
|
||||||
-- @param i Number of tabs to prepend to each line
|
-- @param i Number of tabs to prepend to each line
|
||||||
-- @return Always nil
|
-- @return Always nil
|
||||||
function dumptable(t, i)
|
function dumptable(t, i, seen)
|
||||||
i = i or 0
|
i = i or 0
|
||||||
|
seen = seen or setmetatable({}, {__mode="k"})
|
||||||
|
|
||||||
for k,v in pairs(t) do
|
for k,v in pairs(t) do
|
||||||
print(string.rep("\t", i) .. tostring(k), tostring(v))
|
perror(string.rep("\t", i) .. tostring(k), tostring(v))
|
||||||
if type(v) == "table" then
|
if type(v) == "table" then
|
||||||
dumptable(v, i+1)
|
if not seen[v] then
|
||||||
|
seen[v] = true
|
||||||
|
dumptable(v, i+1, seen)
|
||||||
|
else
|
||||||
|
perror(string.rep("\t", i) .. "*** RECURSION ***")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -425,11 +432,14 @@ end
|
||||||
|
|
||||||
|
|
||||||
-- Serialize the contents of a table value.
|
-- Serialize the contents of a table value.
|
||||||
function _serialize_table(t)
|
function _serialize_table(t, seen)
|
||||||
|
assert(not seen[t], "Recursion detected.")
|
||||||
|
seen[t] = true
|
||||||
|
|
||||||
local data = ""
|
local data = ""
|
||||||
for k, v in pairs(t) do
|
for k, v in pairs(t) do
|
||||||
k = serialize_data(k)
|
k = serialize_data(k, seen)
|
||||||
v = serialize_data(v)
|
v = serialize_data(v, seen)
|
||||||
data = data .. ( #data > 0 and ", " or "" ) ..
|
data = data .. ( #data > 0 and ", " or "" ) ..
|
||||||
'[' .. k .. '] = ' .. v
|
'[' .. k .. '] = ' .. v
|
||||||
end
|
end
|
||||||
|
@ -442,7 +452,9 @@ end
|
||||||
-- @return String value containing the serialized code
|
-- @return String value containing the serialized code
|
||||||
-- @see restore_data
|
-- @see restore_data
|
||||||
-- @see get_bytecode
|
-- @see get_bytecode
|
||||||
function serialize_data(val)
|
function serialize_data(val, seen)
|
||||||
|
seen = seen or setmetatable({}, {__mode="k"})
|
||||||
|
|
||||||
if val == nil then
|
if val == nil then
|
||||||
return "nil"
|
return "nil"
|
||||||
elseif type(val) == "number" then
|
elseif type(val) == "number" then
|
||||||
|
@ -454,7 +466,7 @@ function serialize_data(val)
|
||||||
elseif type(val) == "function" then
|
elseif type(val) == "function" then
|
||||||
return string.format("loadstring(%q)", get_bytecode(val))
|
return string.format("loadstring(%q)", get_bytecode(val))
|
||||||
elseif type(val) == "table" then
|
elseif type(val) == "table" then
|
||||||
return "{ " .. _serialize_table(val) .. " }"
|
return "{ " .. _serialize_table(val, seen) .. " }"
|
||||||
else
|
else
|
||||||
return '"[unhandled data type:' .. type(val) .. ']"'
|
return '"[unhandled data type:' .. type(val) .. ']"'
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue