AeneasVerif/aeneas

GitHub: AeneasVerif/aeneas

Aeneas 是一个将 Rust 程序的中间表示转换为纯函数式 lambda 演算、并支持多种定理证明器后端的形式化验证工具链。

Stars: 857 | Forks: 89

Iapyx removing arrowhead from Aeneas
Unknown author, Iapyx removing arrowhead from Aeneas [Fresco]. Wall in Pompei, digital image from Michael Lahanis. Source

# Aeneas Aeneas(发音为 [Eh-nee-as])是一个用于 Rust 程序的验证工具链。它依赖于从 Rust 的 MIR 内部语言到纯 lambda 演算的转换。它旨在与 [Charon](https://github.com/AeneasVerif/charon) 结合使用,后者将 Rust 程序编译为名为 LLBC 的中间 表示。它目前拥有 [F\*](https://www.fstar-lang.org)、 [Coq](https://coq.inria.fr/)、[HOL4](https://hol-theorem-prover.org/) 和 [LEAN](https://leanprover.github.io/) 的后端。 如果你想贡献代码或提出问题,我们强烈鼓励你加入 [Zulip](https://aeneas-verif.zulipchat.com/)。特别是,我们欢迎外部 贡献,但要求贡献者在深入修改 代码或实现非平凡功能之前与我们进行沟通,因为这些需要深入的设计 讨论和仔细的审查。如果你想贡献新功能,你应该在 Zulip 上讨论,或者在 github 上开启相应的 issue。 ## 项目结构 - `src`:OCaml 源代码。请注意,我们依赖 [Dune](https://github.com/ocaml/dune) 来构建项目。 - `backends`:现有后端的标准库(例如算术运算的定义,向量等标准集合,定理,策略等)。 - `tests`:将 Aeneas 应用于 Charon 的部分测试文件生成的文件, 并辅以手写文件(主要是证明脚本)。 ## 安装与构建 你需要安装 OCaml 以及一些包。 我们建议你按照这些[说明](https://ocaml.org/docs/install.html)进行操作, 并在过程中安装 OPAM(同样的说明)。 我们正在使用 **OCaml 5** 开发 Aeneas。例如,如果你想使用 OCaml 5.3.0: ``` opam switch create 5.3.0 ``` 然后你可以使用以下命令安装依赖项: ``` opam install calendar core_unix domainslib easy_logging menhir \ ocamlformat.0.27.0 ocamlgraph odoc ppx_deriving ppx_deriving_yojson \ progress unionFind visitors yojson zarith ``` 此外,Aeneas 使用了 [Charon](https://github.com/AeneasVerif/charon) 项目和库。 为了使 Aeneas 正常工作,`./charon` 必须包含 [Charon](https://github.com/AeneasVerif/charon) 仓库的一个克隆,且提交版本需符合 `./charon-pin` 的指定。最简单的设置方法是调用 `make setup-charon` (这会使用 [rustup](https://rustup.rs/) 或 [nix](https://nixos.org/download/) 来构建 Charon,具体取决于安装了哪一个)。 如果版本不匹配,系统将提示你更新 Charon。 如果你也在开发 Charon,你可以将 `./charon` 设置为指向你本地版本的符号链接: `ln -s PATH_TO_CHARON_REPO charon`。在这种情况下,脚本将不会检查你的 Charon 安装是否处于兼容的提交版本。当你拉取新版本的 Aeneas 时,你偶尔 需要更新你的 Charon 仓库,以便 Aeneas 能够正确构建和运行。 最后,只需在顶层目录中运行 `make` 即可 构建项目。 你还可以使用 `make test` 和 `make verify` 来运行测试,并检查 生成的文件。由于 `make test` 将运行使用 Charon 测试的测试, 你需要重新生成 `.llbc` 文件。为此,请在 `make test` 之前运行 `make setup-charon`。或者,调用 `REGEN_LLBC=1 make test-...` 来仅重新生成所需的文件。 ## 文档 如果你运行 `make`,你将生成一份可从 [`doc.html`](./doc.html) 访问的文档。 此外,[这里](./tests/lean/Tutorial/) 提供了使用 Aeneas Lean 后端的教程;原始的 Rust 文件可以在[这里](./tests/src/tutorial/src/lib.rs)找到。 它需要安装有效的 Lean。 ## 用法 你应该首先通过在你想翻译的 crate *内部*调用 Charon (类似于 cargo)来生成序列化的 `.llbc` 文件。**重要提示:**你应该 使用以下选项调用 Charon: ``` charon cargo --preset=aeneas ``` Aeneas 的二进制文件位于 `bin` 中;你可以运行:`./bin/aeneas -backend {fstar|coq|lean|hol4} [OPTIONS] LLBC_FILE`, 其中 `LLBC_FILE` 是由 Charon 生成的 .llbc 文件。 Aeneas 提供了大量的 flag 和选项来调整其行为:你可以使用 `--help` 来显示详细的文档。 ## 目标子集和当前限制 Aeneas 目前对安全 Rust 的一个子集进行了函数化,我们正在 通过引入基于分离逻辑的推理来扩展函数模型,以 支持 unsafe 代码和并发代码。 我们目前对*安全*子集有以下限制,我们计划逐一 解决: - **循环**:暂不支持在*嵌套*循环内使用 `return`,或向*外层*循环使用 `break`/`continue` (例如,`'a : loop { loop { break 'a; } } `)。这是一个 技术限制,而非根本性问题,我们计划在 不久的将来解决它,并且可以根据用户的需求确定优先级。 以下限制将随着分离逻辑方面的工作进展而被解除: - **unsafe 代码** - **并发** 如果你需要某些特定功能或 有兴趣贡献代码,请随时联系团队或加入 Zulip。 ## 后端支持 我们目前支持 F\*、Coq、HOL4 和 Lean。我们对开发 Isabelle 后端很感兴趣。我们最成熟的后端是 Lean 和 HOL4,特别地, 我们为它们提供了对部分函数和外部终止证明的支持(参见 `./backends/lean/Base/Diverge/Elab.lean` 和 `./backends/hol4/divDefLib.sig`), 以及专为单子程序设计的策略(参见 `./backends/lean/Base/Progress/Progress.lean` 和 `./backends/hol4/primitivesLib.sml`)。 ## 将 Rust 定义的模型添加到 Lean 后端 在翻译需要外部定义(即来自外部依赖项(如 Rust 标准库)的定义)的 crate 时,我们建议使用 `-split-files` 选项。使用 `-split-files` 时,Aeneas 将生成模板文件,其中列出了 用户必须提供手写模型的缺失定义。 例如,它可能会在 Lean 中生成以下结构: ``` ... // Files containing type definitions, etc. FunsExternal_Template.lean // automatically generated template file FunsExternal.lean // hand-written file maintained by the user (not overwritten during the translation) Funs.lean // automatically generated file which imports FunsExternal.lean ``` 与其将模型添加到 `TypesExternal.lean`、`FunsExternal.lean` 等文件中, 不如将这些模型移植到 Aeneas 标准库,这样所有客户端项目 都可以从中受益。这样做时,务必要让 Aeneas 知道这些新 模型。这可以通过使用适当的 attribute (`rust_type`、`rust_const`、`rust_fun`、`rust_trait` 或 `rust_trait_impl`)标注 Lean 模型,然后运行 命令 `make extract-lean-std` 来完成。此命令将构建 Aeneas 的 Lean 库, 收集这些定义,并重新生成 `src/extract/ExtractBuiltinLean.ml` 文件, 该文件提供了有关这些模型的信息。 请注意,当在 `TypesExternal.lean` 等文件中列出缺失的外部定义时,Aeneas 会自动引入 `rust_type` 等 attribute: 用户只需复制/粘贴这些定义并填补漏洞(holes)。另外请注意, 这些 attribute 有相当多的选项可以调整提取的行为: 我们邀请用户阅读它们的 docstring 以获取更多信息。 ## Nix 用户的快速入门 假设已安装 Nix,并且支持 Flakes(`*`): ``` $ # Run Charon with the exact same version required by Aeneas $ nix run github:aeneasverif/aeneas#charon -L $ nix run github:aeneasverif/aeneas -L -- -backend your_preferred_backend your_llbc.file ``` 要重新生成提取内容,只需再次运行第 2 步和第 3 步。 `(*)`:Flakes 并非必需,以下是在没有它的情况下执行类似步骤的示例: ``` $ nix-shell '' -A packages.x86_64-linux.charon --run "charon" -I aeneas=https://github.com/AeneasVerif/aeneas/archive/main.tar.gz $ nix-shell '' -A packages.x86_64-linux.default --run "aeneas --backend your_preferred_backend your_llbc.file" -I aeneas=https://github.com/AeneasVerif/aeneas/archive/main.tar.gz ``` ## 形式化 该转换已经过形式化,并在 ICFP2022 上发表:[Aeneas:通过函数 转换进行 Rust 验证](https://dl.acm.org/doi/abs/10.1145/3547647) ([长版本](https://arxiv.org/abs/2206.07185))。我们还有一个证明表明, Aeneas 在转换期间执行的符号执行正确地 实现了 borrow checker,并在 ICFP 2024 上发表:[Sound Borrow-Checking for Rust via Symbolic Semantics](https://dl.acm.org/doi/10.1145/3674640)([长版本](https://arxiv.org/abs/2404.02680))。
标签:OCaml, Rust, Web安全扫描, 可视化界面, 定理证明, 形式化验证, 漏洞数据库, 编译器工具链, 网络流量审计