本项目是一个用于静态分析Rust代码中不安全代码路径的工具。它能够识别从公开API到内部不安全代码块的调用路径,帮助开发者理解和审查项目中的不安全代码使用情况。该工具的设计目标是提高代码的安全性,减少潜在的内存安全问题。
analysis/
├── src/
│ ├── main.rs # 程序入口点
│ ├── lib.rs # 库定义和常量
│ ├── models.rs # 数据模型定义
│ ├── utils.rs # 工具函数
│ ├── analysis/ # 分析模块
│ │ ├── analyzer.rs # 静态分析器实现
│ │ ├── call_graph.rs # 调用图构建
│ │ └── mod.rs # 模块定义
│ └── visitors/ # 代码访问器
│ ├── function.rs # 函数信息收集访问器
│ ├── call.rs # 函数调用关系访问器
│ └── mod.rs # 模块定义
├── tests/ # 测试文件
├── Cargo.toml # 项目依赖定义
└── Cargo.lock # 依赖锁定文件
该工具基于以下核心技术实现:
- syn: 用于解析Rust代码,支持完整的语法树遍历和分析
- rayon: 用于并行处理多个文件,提高分析效率
- walkdir: 用于遍历目录树,收集所有待分析的Rust源码文件
main.rs 是程序的入口点,负责解析命令行参数并启动分析过程。它设置了 panic 处理程序,以便在发生错误时能够优雅地处理并继续执行。
- 命令行参数:程序接受一个 Rust 项目或文件路径作为输入,和一个可选的输出文件路径。
- panic 处理:使用
std::panic::set_hook设置自定义的 panic 处理程序,捕获错误信息并尝试继续执行。
该目录包含与代码分析相关的主要逻辑。
analyzer.rs 负责执行代码分析的核心逻辑,包括:
- 结果写入:
write_results_to_file函数负责将分析结果写入指定的文件。它会生成一个包含不安全函数调用路径的 Rust 代码文件,并添加必要的注释和模块声明。 - 路径分组:分析结果按目标不安全函数分组,确保每个不安全函数的调用路径都被清晰地记录。
功能实现细节:
- 在写入文件时,首先添加文件头部注释,说明该文件是自动生成的,并包含生成时间。
- 通过
HashSet跟踪已处理的文件,避免重复输出。 - 对于每个不安全函数,创建一个子模块,输出路径列表和相关函数信息。
call_graph.rs 负责构建函数调用图,跟踪函数之间的调用关系。它将函数信息和调用路径转换为 PathNodeInfo 结构体,以便后续分析。
功能实现细节:
find_paths_to_unsafe方法查找从公共函数到不安全函数的所有有效路径,并返回详细的函数信息。- 使用广度优先搜索(BFS)算法来遍历函数调用关系,确保所有可达的目标函数都被记录。
该文件定义了项目中使用的各种数据结构,包括:
UnsafeOperationType:枚举类型,表示不同类型的不安全操作,如裸指针解引用、调用不安全函数等。FunctionInfo:包含函数的基本信息,如名称、可见性、源代码、参数类型等。PathNodeInfo:表示函数调用路径中的单个节点,包含函数的完整路径和不安全操作信息。
功能实现细节:
FunctionInfo结构体中包含unsafe_operations字段,用于记录函数中发生的不安全操作。PathNodeInfo结构体用于存储函数的完整路径、可见性、源代码等信息,便于后续分析和输出。
utils.rs 提供了一些实用工具函数,包括:
beautify_source_code:尝试使用prettyplease库格式化源代码,如果失败则使用基本格式化。该函数使用std::panic::catch_unwind捕获可能的 panic,以确保程序的稳定性。filter_doc_comments:过滤掉源代码中的文档注释,以便在输出中只保留实际的代码。
功能实现细节:
beautify_source_code函数首先尝试使用prettyplease进行格式化,如果发生 panic,则使用基本格式化作为后备方案。- 该函数支持对函数、模块和 impl 块的格式化,确保输出的代码结构清晰。
该目录包含用于遍历和分析 AST(抽象语法树)的访问者模式实现。
function.rs 中的 FunctionVisitor 结构体负责收集函数信息并检测不安全块。它实现了以下功能:
- 函数添加:
add_function和add_impl_function方法用于将函数信息添加到结果集中。 - 不安全状态更新:
update_unsafe_state方法更新当前函数的不安全状态,并记录不安全操作。 - 裸指针检测:
might_be_raw_pointer方法检查表达式是否可能是裸指针,支持多种表达式类型的检测。
功能实现细节:
- 在添加函数时,记录函数的可见性、参数类型、返回类型等信息。
- 使用
record_unsafe_operation方法记录不安全操作,包括操作类型、描述和代码片段。 is_raw_pointer_type方法用于判断给定类型是否为裸指针类型,支持多种表达式类型的检测。
- 不安全操作检测:能够检测到裸指针解引用、调用不安全函数、使用内联汇编等不安全操作。
- 路径分析:从公共函数到不安全函数的调用路径分析,生成详细的分析报告。
- 自定义类型支持:识别自定义类型及其在不安全代码路径中的使用情况。
- 并行处理:支持并行处理多个文件,提高分析效率。
- 错误处理机制:确保即使部分文件分析失败也不会中断整体分析过程。
确保您的系统上已安装Rust及Cargo工具链。
# 克隆仓库
git clone [仓库URL]
cd analysis
# 编译项目
cargo build --release# 分析单个Rust文件
cargo run --release -- path/to/file.rs [输出文件路径]
# 分析整个Rust项目目录
cargo run --release -- path/to/rust/project [输出文件路径]如果不指定输出文件路径,结果将保存在当前目录下,文件名基于输入路径自动生成。
该工具提供了一些默认配置常量,可以在源码中修改:
DEFAULT_MAX_SEARCH_DEPTH: 搜索调用链的最大深度 (默认: 20)DEFAULT_FILE_SIZE_LIMIT: 分析文件的大小上限,单位MB (默认: 10MB)DEFAULT_TIMEOUT_SECONDS: 分析单个文件的超时时间,单位秒 (默认: 30秒)
分析结果以Rust源码的形式保存,包含以下信息:
- 从公开API到unsafe代码块的完整调用路径
- 每个函数的可见性信息
- 相关的自定义类型定义
- 路径中的源代码片段
- 当前版本不支持分析宏展开内部的unsafe代码
- 跨crate的调用链分析可能不完整
- 对于非常大型的项目,可能需要调整默认配置参数
欢迎任何对项目的贡献!请遵循以下步骤:
- 克隆仓库:使用
git clone命令克隆项目。 - 创建分支:在进行任何更改之前,请创建一个新的分支。
- 提交更改:在完成更改后,提交并推送到您的分支。
- 创建拉取请求:在 GitHub 上创建一个拉取请求,描述您的更改。
本项目旨在为 Rust 开发人员提供一个强大的工具,以帮助他们识别和分析代码中的不安全部分。希望这个 README 能够帮助后续开发人员更好地理解项目结构和实现细节。如有任何问题或建议,请随时联系项目维护者。