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 命名空间加载可能发生在第一次读取标记文字时?
如果是出于意外代码执行的安全影响考虑,也许可以通过 *read-eval* 来配置要求数据读取器命名空间的行为?

2 答案

0
关于安全影响的一个注解:我的理解是,这里的威胁是恶意包在类路径上激活,当易受攻击的系统读取字符串时,由攻击者提供。我认为尽管这很不安全,但恶意包在类路径上是足够的安全漏洞 — 它可以提供自己的 `clojure.core` 命名空间,该命名空间将从类路径加载,而不是由 `org.clojure/clojure` 构件提供。

所以攻击者没有必要在使用读者标记进行攻击时,当他们最终进入类路径时。

所以也许应该始终要求读者标记命名空间,而不是使用 `*read-eval*` 来控制此加载,只需建议用户使用绑定到 `*data-readers*` 为 `default-data-readers` 的读取...(该 `default-data-readers` 已经存在)
0

如果这种行为改变或者可以配置将是很好的。

目前很难使用开发时间工具,如 haspdebux,因为你必须要求它们在所有地方,或者使用如 user.clj注入 之类的方案来获取require。

...