请在 2024 年 Clojure 状况调查! 中分享您的看法。

欢迎!请参阅 关于 页面以了解更多关于这个工作的信息。

+3
语法和读取器
重标记

我以为 Clojure 会自动加载用于在源代码中读取标记字面量的 vars 的命名空间,但显然并不是这样。

假设有一个库定义了下面内容的 data_readers.clj

{foo/bar my.library.foo/bar
 foo/baz my.library/baz}

尝试读取 #foo/bar [1 2 3] 将产生这个异常

Syntax error reading source at (REPL:1:69).
Attempting to call unbound fn: #'my.library.foo/bar

为了避免这个异常,您需要在使用读取器标签之前require 库命名空间。

能够只通过将其添加到类路径中而不进行显式的 require 步骤来使用库读取器标签会更方便。

我不知道为什么这么做...

如果理由是 clojure.core 启动时间,那么实际的 var ns 加载可能发生在第一次读取标记字面量的时间?
如果理由是意外代码执行的安全影响,也许可以通过 *read-eval* 配置读取数据读者命名空间的行为?

2 个答案

0
by
by
关于安全影响的说明:我的理解是,这里的威胁是一个恶意的类路径包,当有漏洞的系统在读取由攻击者提供的用户输入时被激活。我认为,尽管这很不可取,但类路径上存在恶意包本身就已经足够是一个安全漏洞——它可以提供它自己的`clojure.core`命名空间,将从类路径加载,而不是由`org.clojure/clojure`工件提供的。

所以当最终在类路径上时,攻击者使用reader标签进行攻击实际上没有必要。

因此,可能需要始终要求reader标签命名空间,并且而不是使用`*read-eval*`来控制这种加载,仅建议用户绑定到已有`default-data-readers`进行读取就足够了...
0
by

如果这种行为有所改变或可以配置,那将是多么好。

目前使用dev时间工具如haspdebux相当困难,因为你必须要么到处 require,要么使用类似的用户.clj注入来获取 require。

...