检查是否可以安全地评估符号

时间:2015-06-21 08:09:33

标签: julia

我有一个字符串x。我认为x是类型的字符串表示形式,是Number的子类型。例如,x可能会使用值"Float64"。我可以使用以下方式检查:

eval(parse(x)) <: Number

但是,x可能包含某些危险内容,例如"rm(something_important)"上的某些变体,因此在我确定eval之前使用x是一个坏主意安全

有什么方法可以安全地检查x是否是Number子类型的字符串表示形式?

(除了构建Number所有可能子类型的字符串数组并进行比较...)

2 个答案:

答案 0 :(得分:4)

HDF5.jl包必须处理这个问题。 It tackles it解析字符串,然后在 eval之前检查结果。如果解析后的字符串是它认为是valid_type_expression的字符串,那么它知道在Main命名空间中进行评估应该是安全的。这允许它从主命名空间中拾取自baremodule中无法使用的自定义类型。

更多细节:解析任意字符串后,您可以检查返回的对象以查看它是否“安全”进行评估:

julia> dump(parse("Int"))
Symbol Int

julia> dump(parse("Vector{Int}"))
Expr
  head: Symbol curly
  args: Array(Any,(2,))
    1: Symbol Vector
    2: Symbol Int
  typ: Any

julia> dump(parse("""rm("/")"""))
Expr
  head: Symbol call
  args: Array(Any,(2,))
    1: Symbol rm
    2: ASCIIString "/"
  typ: Any

我们希望确保我们永远不会eval一个可以调用任意行为的表达式。根据您希望支持类型语法的完整程度,您的解决方案可能非常简单,也可能与我上面链接的HDF5解决方案一样复杂。如果你只是简单的,未参数化的类型,我们可以大大简化:

is_valid_type_expression(ex::Symbol) = true
is_valid_type_expression(ex) = false

function julia_type(string)
    ex = parse(string)
    if is_valid_type_expression(ex)
        try
            typ = eval(Main, ex)
            isa(typ, Type) && typ <: Number && return typ
        end
    end
    error("unsupported type: $string")
end

julia> julia_type("String")
ERROR: unsupported type: String
 in julia_type at none:9

julia> julia_type("Int")
Int64

julia> julia_type("""rm("/")""")
ERROR: unsupported type: rm("/")
 in julia_type at none:9

请注意,任何比符号更复杂的内容都不允许为eval。在eval表达式之后,我们检查以确保类型是Type,并且它是Number的子类型。除了内置的子类型之外,这还将允许Number的自定义子类型,因为我们正在Main命名空间中对其进行评估。

答案 1 :(得分:2)

修改:此解决方案不安全。阅读评论。我离开它是因为它仍然具有指导性。

eval可选择将模块作为其第一个参数。

您可以在裸模块(baremodule)中对其进行评估,因此命令无法访问标准库(然后它不会造成太大的伤害)。

julia> baremodule M
       end

julia> x = :(rm("/"))
:(rm("/"))

julia> eval(M, x)
ERROR: rm not defined

julia> x = :"Float64"
"Float64"

julia> eval(M, x)
"Float64"