2024 Clojure 状态调查! 中分享您的想法。

欢迎!请查看 关于 页面以了解有关此工具的更多详细信息。

+3
语法和读取器
重标记

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

假设有一个定义包含以下内容的库的 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 的启动时间,那么变量命名空间的实际加载可能是在读取第一个标签字面时发生的吗?
如果原因是意外代码执行的安全性影响,那么可能可以通过配置 *read-eval* 来配置要求数据读取器命名空间的行为?

2 个答案

0
关于安全影响的说明:我的理解是,这里的威胁是一个恶意的包位于类路径中,当有漏洞的系统在读取字符串时由攻击者提供用户输入时,该恶意包被激活。我认为这确实是不安全的,但类路径中存在恶意包已经足够是一个安全漏洞——它可以提供一个自己的 `clojure.core` 命名空间,该命名空间将从类路径加载,而不是来自 `org.clojure/clojure` 仓库。

因此,攻击者根本没有必要使用读取标签进行攻击,因为最终进入类路径就足够了。

因此,也许应该始终要求读取标签 nses,而不要使用 `*read-eval*` 来控制这种加载,只需建议用户在将 `*data-readers*` 绑定到已存在的 `default-data-readers` 时执行读取...
0

如果这种行为有所改变或可以配置,那就太好了。

目前,很难使用像 haspdebux 这样的开发时间工具,因为您必须要么在所有地方都要求它们,或者使用像 user.clj 注入 这样的解决方案来要求。

...