devdanzin/lafleur

GitHub: devdanzin/lafleur

面向 CPython 实验性 JIT 编译器的覆盖率引导进化模糊测试工具,用于发现崩溃、正确性错误和挂起问题。

Stars: 21 | Forks: 4

# lafleur [![CI](https://static.pigsec.cn/wp-content/uploads/repos/2026/03/41851a1ed5234508.svg)](https://github.com/devdanzin/lafleur/actions) [![PyPI](https://img.shields.io/pypi/v/lafleur)](https://pypi.org/project/lafleur/ [![Python 3.14+](https://img.shields.io/badge/python-3.14+-blue.svg)](https://www.python.org/) [![License: GPL v2](https://img.shields.io/badge/License-GPL_v2-blue.svg)](https://www.gnu.org/licenses/gpl-2.0) CPython JIT 编译器的反馈驱动进化模糊测试工具。 `lafleur` 是一个专用的模糊测试工具,旨在发现 CPython 实验性 JIT 编译器中的崩溃、正确性错误和挂起。与随机生成代码的传统模糊测试工具不同,`lafleur` 采用覆盖率引导的进化方法。它执行测试用例,通过分析详细的跟踪日志来观察其对 JIT 行为的影响,并利用该反馈来指导其变异,从而随着时间推移变得越来越善于发现有趣的代码路径。 这个名字来源于法语表达 *la fleur au fusil*,捕捉了项目启动时的精神。`lafleur` 最初是 Victor Stinner 创建的 [fusil](https://github.com/devdanzin/fusil) 项目中的一个高级功能集,后来作为一个独立工具分离出来。 ## 功能特性 * **覆盖率引导:** 使用有状态的 uop 边覆盖率来跟踪 JIT 在跟踪、优化和执行状态下的行为,区分在新的 JIT 状态中发现边与发现真正新颖的边。 * **60 多种 JIT 特定变异器:** 一个针对特定 JIT 弱点的 AST 转换库 —— 类型推测、内联缓存、守卫处理、闭包单元、帧内省和稀有事件触发器。 * **自适应学习:** 一个 epsilon-greedy 变异引擎,跟踪哪些变异器发现了新的覆盖率并动态聚焦于最有效的策略,通过衰减分数来偏向最近成功的技术。 * **会话模糊测试:** 在共享进程中与“污染”脚本一起执行脚本,以压力测试 JIT 状态持久性、缓存污染和内存布局 —— 发现隔离执行会遗漏的深层、依赖状态的错误。 * **JIT 内省:** 使用 `ctypes` 在运行时检查 CPython 内部的 `_PyExecutorObject` 结构体,提取退出密度、僵尸跟踪计数和布隆过滤器状态,以奖励引发 JIT 不稳定性的变异。 * **智能调度:** 采用多因素评分系统来优先考虑快速、小型且发现了稀有或富饶代码路径的测试用例。 * **活动工具链:** 监控单个实例,将多核活动聚合到仪表板中,并使用链接到 GitHub 问题的 SQLite 注册表对崩溃进行分类。 ## 安装和设置 `lafleur` 需要特定的 CPython 构建环境。请仔细遵循以下步骤。 ### 步骤 1:构建启用 JIT 的 CPython `lafleur` 必须在 **启用了实验性 JIT 编译器的 CPython 调试构建** 上运行。 1. **克隆 CPython:** git clone https://github.com/python/cpython.git cd cpython 2. **配置和构建(第一步):** ./configure --with-pydebug --enable-experimental-jit make -j$(nproc) 3. **创建虚拟环境:** ./python -m venv ~/venvs/lafleur_venv ### 步骤 2:安装 `lafleur` 并调整 JIT 1. **激活您的虚拟环境:** source ~/venvs/lafleur_venv/bin/activate 2. **从源码安装 `lafleur`(推荐):** git clone https://github.com/devdanzin/lafleur.git cd lafleur pip install -e . 可编辑安装(`-e`)允许您通过 `git pull` 保持更新,并且是用户和开发者的推荐路径。虽然 [PyPI 上也提供](https://pypi.org/project/lafleur/)了发布版(`pip install lafleur`),但可能落后于最新的开发版本。 3. **调整 JIT:** 运行调整脚本,指向您的 CPython 源目录。这会降低 CPython C 头文件中的 `JIT_THRESHOLD` 和 `trace_stack_size`,使 JIT 更早编译并使用更浅的跟踪堆栈,这非常适合模糊测试。 lafleur-jit-tweak /path/to/your/cpython 4. **重新构建 CPython** 以应用调整后的设置: cd /path/to/your/cpython make -j$(nproc) ### 步骤 3:填充语料库(可选) `lafleur` 可以使用经典的 `fusil` 模糊测试工具生成一组初始的有趣种子文件。这是推荐的,但不是必需的。 1. **安装 `fusil`:** git clone https://github.com/devdanzin/fusil.git cd fusil pip install . 如果您不想安装 `fusil`,可以在您的工作目录中创建一个名为 `corpus/jit_interesting_tests/` 的目录,并将您自己手工编写的 Python 种子文件放入其中。 ## 使用方法 安装完成后,您可以从任何目录运行 `lafleur`。它将在当前工作目录中创建其输出子目录(`corpus/`、`crashes/` 等)。别忘了先激活您的虚拟环境。 ### 基本用法(恢复运行) 如果语料库已经存在,此命令将加载状态并恢复模糊测试会话。 ``` lafleur --fusil-path /path/to/fusil/fuzzers/fusil-python-threaded ``` ### 填充新语料库 使用 `--min-corpus-files` 调用 `fusil` 填充器,直到语料库在启动主进化循环之前至少有 20 个文件。 ``` lafleur --fusil-path /path/to/fusil/fuzzers/fusil-python-threaded --min-corpus-files 20 ``` ### 会话模糊测试(有状态 JIT 测试) 使用 `--session-fuzz` 在共享进程中执行脚本。这会跨脚本边界保留 JIT 状态,从而实现“热 JIT”攻击,即污染脚本在变异子代运行之前对缓存和内存布局施加压力。 ``` lafleur --fusil-path /path/to/fusil/fuzzers/fusil-python-threaded --session-fuzz ``` ### 针对特定的 CPython 构建 默认情况下,`lafleur` 使用您活动虚拟环境中的 Python 解释器。使用 `--target-python` 来模糊测试不同的构建。 ``` lafleur --fusil-path /path/to/fusil/fuzzers/fusil-python-threaded --target-python /path/to/cpython/python ``` ### 其他选项 | 选项 | 描述 | |--------|-------------| | `--runs N` | 将每个变异的测试用例运行 N 次(对非确定性错误有用) | | `--dynamic-runs` | 根据父分数自动调整运行次数 | | `--timeout N` | 设置脚本执行超时时间(秒)(默认值:10) | | `--instance-name NAME` | 此模糊测试实例的人类可读名称 | | `--deepening-probability P` | 深度优先与会话的概率(默认值:0.2) | | `--prune-corpus` | 分析并报告冗余的语料库文件,然后退出 | | `--keep-tmp-logs` | 保留临时日志文件以进行调试 | ### 诊断模式 用于快速冒烟测试和变异器开发: ``` # 有界冒烟测试(3 个会话,每个 2 个 mutation,可复现) python -m lafleur --max-sessions 3 --max-mutations-per-session 2 --seed 42 # 在 dry-run 模式下测试特定 mutator python -m lafleur --mutators GCInjector --strategy spam \ --max-sessions 1 --max-mutations-per-session 5 --dry-run --keep-children # 列出所有可用的 mutator python -m lafleur --list-mutators ``` 有关详细信息,请参阅 [诊断模式文档](doc/dev/09_diagnostic_mode.md)。 ## 分析与分类 `lafleur` 包含一套工具,用于监控模糊测试进度、聚合活动结果以及长期管理崩溃发现。 | 工具 | 用途 | |------|---------| | **`lafleur-report`** | 检查正在运行的模糊测试器的脉搏。为单个实例生成健康状况、覆盖率和崩溃摘要。 | | **`lafleur-campaign`** | 将 50 多个核心的结果聚合到一个仪表板中。对崩溃进行去重,生成队列范围的指标,并生成 HTML 报告。 | | **`lafleur-triage`** | 使用内置的 SQLite 数据库跟踪回归和已知问题。将崩溃链接到 GitHub 问题并管理其生命周期。 | ### 快速示例 ``` # 单实例报告 lafleur-report /path/to/instance # 带 HTML 输出的 Campaign 仪表板 lafleur-campaign runs/ --html report.html --registry crashes.db # 交互式 Crash 分类 lafleur-triage interactive ``` 有关详细用法,请参阅[分析与分类工作流](docs/TOOLING.md)文档。 ## 解读结果 模糊测试运行最重要的发现将保存在两个目录中: * **`crashes/`**:包含导致硬崩溃(例如 SegFault)或引发严重错误的脚本。每个 `.py` 文件都伴有一个包含崩溃输出的 `.log` 文件。 * **`timeouts/`**:包含运行时间过长(默认值 > 10 秒)的脚本,通常表示无限循环错误。 ## 文档 要全面了解 `lafleur` 的内部原理,请参阅 [开发者文档](doc/dev/00_index.md) —— 这是一个包含 8 个文档的系列,涵盖了架构、进化循环、覆盖率信号、变异引擎、状态格式、设置、扩展和测试。 ## 贡献与提交问题 `lafleur` 是一个开源项目,欢迎贡献。有关完整的贡献者指南,请参阅 [CONTRIBUTING.md](CONTRIBUTING.md)。 要提交错误报告或功能请求,请使用项目的 [GitHub Issues](https://github.com/devdanzin/lafleur/issues) 页面。提交由 `lafleur` 发现的 JIT 错误时,请包含: 1. 崩溃的测试用例(`.py` 文件)。 2. 完整的日志文件(`.log`)。 3. 您正在模糊测试的 CPython 版本的提交哈希(可以使用 `python -VV` 获取)。
标签:AST变换, CPython, DNS解析, Fuzzing, JIT编译器, Python, 代码安全, 即时编译器, 多模态安全, 安全测试, 开源项目, 异常检测, 攻击性安全, 无后门, 测试工具, 漏洞枚举, 自动化payload嵌入, 覆盖率引导, 软件开发, 进化算法