正如评论中提到的那样,您不应该使用Code.eval_string
. 但是,有一种方法可以安全地将代码转换为 Elixir 结构,使用Code
模块:
ex(1)> encoded = "%Sample.Struct{list: [], total: \"0.00\", day: 6, id: \"8vfts6\"}"
"%Sample.Struct{list: [], total: \"0.00\", day: 6, id: \"8vfts6\"}"
首先,从字符串中获取 AST,但使用模式匹配来确保它是您正在寻找的结构 ( {:__aliases__, _, [:Sample, :Struct]}
)。所有其他(可能是恶意的)代码都将失败此匹配:
iex(2)> {:ok, {:%, _, [{:__aliases__, _, [:Sample, :Struct]}, {:%{}, _, keymap}]} = ast} = Code.string_to_quoted(encoded)
{:ok,
{:%, [line: 1],
[{:__aliases__, [line: 1], [:Sample, :Struct]},
{:%{}, [line: 1], [list: [], total: "0.00", day: 6, id: "8vfts6"]}]}}
在这里,你有完整ast
的结构,和keymap
. 您现在可能很想使用eval_quoted
AST 来获得所需的结构:
iex(3)> {struct, _} = Code.eval_quoted(ast)
{%Sample.Struct{day: 6, id: "8vfts6", list: [], total: "0.00"}, []}
iex(4)> struct
%Sample.Struct{day: 6, id: "8vfts6", list: [], total: "0.00"}
但是还是不安全!有人可能会将一个导致副作用的函数放入字符串中,例如"%Sample.Struct{list: IO.puts \"Something\"}"
,它将在评估期间执行。所以你需要检查第一个keymap
,如果它包含安全数据。
或者您可以直接使用keymap
,而不评估任何内容:
iex(5)> struct(Sample.Struct, keymap)
%Sample.Struct{day: 6, id: "8vfts6", list: [], total: "0.00"}