Macros 一旦编译完成,程序是否可以假设在不调用eval的情况下运行?

Macros 一旦编译完成,程序是否可以假设在不调用eval的情况下运行?,macros,clojure,lisp,eval,Macros,Clojure,Lisp,Eval,我正在学习Clojure是如何工作的,我想知道是否有可能(只是为了了解Clojure和Lisps方言通常是如何工作的)编译Clojure程序,然后运行它,同时“禁止”使用eval 请注意,我不是在问,在技术上是否可能,比如说,对正在运行的Clojure程序进行热补丁,以便一旦编译了Clojure程序,如果调用eval,该程序就会抛出异常 我想问的是,如果技术上可以禁止使用eval,那么大多数Clojure程序不使用REPL,也不专门使用eval,是否仍然有效 或者默认/内置API/宏/函数是否在

我正在学习Clojure是如何工作的,我想知道是否有可能(只是为了了解Clojure和Lisps方言通常是如何工作的)编译Clojure程序,然后运行它,同时“禁止”使用eval

请注意,我不是在问,在技术上是否可能,比如说,对正在运行的Clojure程序进行热补丁,以便一旦编译了Clojure程序,如果调用eval,该程序就会抛出异常

我想问的是,如果技术上可以禁止使用eval,那么大多数Clojure程序不使用REPL,也不专门使用eval,是否仍然有效


或者默认/内置API/宏/函数是否在运行时使用eval?

eval
将交互编程引入Clojure(和Lisps)。一旦将Clojure代码编译成jvm字节码(在任何地方都不使用eval函数调用),或者将其他Lisp方言编译成目标运行时(主要是本机代码),就不需要eval


eval
应用程序的主要目的是在运行时生成代码并执行它,基本上它允许创建“运行时宏”,而这不是语言的核心API需要做的事情。

可以公平地说:

  • eval
    的大多数使用是以交互方式(在REPL时)或在编译时(例如在宏的扩展和执行期间)完成的
  • eval的一些用法发生在常规代码中。这可能是一个有用的技巧,例如在电子表格程序中执行动态生成的数学公式时

由于第二个原因,如果您禁止在全球范围内使用eval,即使所有内容都已编译,您也会在运行时破坏许多代码/库。

我很久以前就提出了这个问题,我现在回答自己的问题,因为出现了附加信息和漏洞利用,而另一个问题没有正确地解决这个问题

基本上,默认读取函数是不安全的

2013年,在所有Ruby漏洞攻击(人们突然对安全问题感到担忧)之后,Clojure小组在一个名为:

“读取评估默认值为false”

Clojure文件本身明确指出:

请注意,即使将read eval设置为false也是不够的(至少在Clojure 1.5之前是不够的),因为一些Java构造函数可能会被强制调用,并通过精心设计恶意输入产生副作用

这在一篇名为“Clojure的读者不安全”的博客文章中有详细解释


长话短说:使用其他东西,比如
clojure.edn

我对clojure的内部结构不太熟悉,但总体上描述了Lisp解释器的体系结构。它的两个主要功能之一称为
eval
,但它可以重命名,并且不需要对正在运行的代码可见,代码才能正常工作。您是说在代码中禁止eval吗?在宏中用括号括起eval,然后根据某种标志启用/禁用它怎么样?@octopusgrabbus:如果我可以根据某种标志的突发奇想完全禁用读取和eval,我会非常高兴。。。但在这一点上,主要是为了更好地理解Clojure/Lisps是如何工作的+1好的,那太好了。。。阅读也是一样的,对吧?我的意思是:如果没有特别使用read,那么编译后的JVM字节码在任何地方都不会使用read调用?@CedricMartin不应该,只要它不是解释过的Lisp方言。而Clojure却不是。@Ankur:许多心怀恶意的人,比如那些创建盗版机器僵尸网络的人,也非常喜欢JavaScript的eval。似乎有无数利用漏洞的行为,允许基于(较差的)站点获得root/admin权限,这些站点允许通过使用eval;)进行代码注入因此,您远不是唯一一个喜欢eval在运行时可用的人:)@Ankur:我知道我可以“简单地不使用read或eval”,但如果某个糟糕的API在后台使用它,而我受到了使用该API的影响,该怎么办?如果一个默认的/内置的API正在公开它呢?我只是想更好地了解正在发生的事情。那么,为什么在公共Lisp中建议将READ-EVAL绑定到nil,并将READTABLE绑定到您自己的表,以确保输入已清理/未执行?这里真的“没什么可看的,快走”吗?或者这只是一个“我们还没有被黑客入侵,但它会到来”的例子?
;; WARNING: You SHOULD NOT use clojure.core/read or
;; clojure.core/read-string to read data from untrusted sources.  They
;; were designed only for reading Clojure code and data from trusted
;; sources