news 2026/9/23 7:44:17

将 Swift 项目接入 OSS-Fuzz:Swift fuzz target 编写与构建配置全指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
将 Swift 项目接入 OSS-Fuzz:Swift fuzz target 编写与构建配置全指南

将 Swift 项目接入 OSS-Fuzz:Swift fuzz target 编写与构建配置全指南

【免费下载链接】oss-fuzzOSS-Fuzz - continuous fuzzing for open source software.项目地址: https://gitcode.com/gh_mirrors/os/oss-fuzz

本篇指南基于 OSS-Fuzz 官方文档《Integrating a Swift project》展开,系统讲解如何将一个 Swift 语言项目接入 OSS-Fuzz 持续模糊测试平台。读完本文,你将掌握 Swift fuzz target 的编写规范、project.yamlDockerfile的 Swift 专属配置要点,以及precompile_swift辅助脚本与SWIFTFLAGS的底层构建原理,并可直接参照仓库中 swift-nio、swift-protobuf 两个真实项目落地实践。

概述:Swift 集成与通用流程的关系

Swift 项目接入 OSS-Fuzz 的整体流程与新项目接入通用指南高度一致:仍然需要在一个项目目录下放置project.yamlDockerfilebuild.sh及 fuzz target 源文件,仍由 OSS-Fuzz 基础设施负责拉取代码、构建镜像、编译 fuzz target 并投喂测试用例。二者的差异集中在与 Swift 语言工具链相关的几个具体环节上:

  • Swift 有独立的构建基础镜像(base-builder-swift);
  • fuzz target 需要用 Swift 编写并导出LLVMFuzzerTestOneInput符号;
  • 构建脚本需要通过precompile_swift脚本生成一组专用的SWIFTFLAGS编译参数;
  • 引擎与 sanitizer 的选择范围较窄。

下文逐项展开这些 Swift 特有细节。

编写 Swift fuzz target

与 C/C++/Go 项目相同,Swift 项目接入 OSS-Fuzz 的第一步,是编写一个接受「字节流输入」并调用被测程序 API 的 fuzz target。该 fuzz target 应存放在你的项目仓库中(而不是 OSS-Fuzz 仓库),在构建阶段通过 Dockerfile 拷贝或克隆进构建环境。

Swift fuzz target 的核心要求是:通过@_cdecl导出LLVMFuzzerTestOneInput符号,参数签名为(UnsafeRawPointer, Int) -> CInt,即接收 libFuzzer 传入的原始内存指针与长度。仓库中 swift-nio 项目的 HTTP 解析器 fuzz target fuzz_http1.swift 是一个完整可参考的范例:

import NIOHTTP1 import NIO @_cdecl("LLVMFuzzerTestOneInput") public func test(_ start: UnsafeRawPointer, _ count: Int) -> CInt { let bytes = UnsafeRawBufferPointer(start: start, count: count) let channel = EmbeddedChannel() var buffer = channel.allocator.buffer(capacity: count) buffer.writeBytes(bytes) do { try channel.pipeline.addHandler(ByteToMessageHandler(HTTPRequestDecoder())).wait() try channel.writeInbound(buffer) channel.embeddedEventLoop.run() } catch { } do { try channel.finish(acceptAlreadyClosed: true) } catch { } return 0 }

这个例子展示了 Swift fuzz target 的几个典型模式:

  • @_cdecl导出@_cdecl("LLVMFuzzerTestOneInput")将 Swift 函数导出为 C 符号,libFuzzer 才能以 C ABI 调用它;
  • 字节流接入:将UnsafeRawPointer与长度包装为UnsafeRawBufferPointer,再写入被测库(如 NIO 的ByteBuffer);
  • 异常兜底:用do/catch吞掉业务异常(如解析错误),避免异常导致进程异常退出干扰模糊测试;
  • 固定返回值:函数统一返回0,崩溃与否完全交由 sanitizer 判定。

在搭建你自己的 fuzz target 时,将import与处理逻辑替换为被测 Swift 库的 API 即可。

项目目录结构与 project.yaml 配置

Swift 项目在 OSS-Fuzz 仓库中的目录结构与其他语言项目并无差别,即projects/<project-name>/下放置project.yamlDockerfilebuild.sh等文件。差异主要体现在project.yaml的字段取值上。

language 字段必须指定

project.yamllanguage属性必须显式声明为swift

language: swift

引擎与 sanitizer 的限定范围

Swift 项目目前唯一支持的 fuzzing 引擎是libfuzzer,支持的 sanitizer 为address(AddressSanitizer)与thread(ThreadSanitizer)。以仓库中 swift-nio/project.yaml 的真实配置为例:

homepage: "https://github.com/apple/swift-nio" language: swift primary_contact: "lukasa@apple.com" auto_ccs : - "johannesweiss@apple.com" - "pp_adams@apple.com" - "p.antoine@catenacyber.fr" fuzzing_engines: - libfuzzer sanitizers: - address - thread main_repo: 'https://github.com/apple/swift-nio.git' base_os_version: ubuntu-24-04

需要注意:Swift 项目不支持coverage之外的额外引擎(如aflhonggfuzz),也不支持undefinedmemory等 sanitizer。这一限制来自底层 Swift 工具链与 libFuzzer 的集成方式,配置超出范围会导致构建/运行阶段失败。

此外,仓库中的 swift-protobuf/project.yaml 还展示了 Swift 项目可用的coverage_extra_args配置——用于在覆盖率统计中排除自动生成的.pb.swift文件与构建产物目录:

coverage_extra_args: > -ignore-filename-regex=.*\.pb\.swift -ignore-filename-regex=.*/\.build/.*

Dockerfile:基于 base-builder-swift 基础镜像

Swift 项目的 Dockerfile 必须从gcr.io/oss-fuzz-base/base-builder-swift开始,而不是通用基础镜像base-builder。该镜像已预装 Swift 工具链与precompile_swift脚本。

以 swift-nio/Dockerfile 为参照:

FROM gcr.io/oss-fuzz-base/base-builder-swift:ubuntu-24-04 # specific swift-nio RUN git clone --depth 1 https://github.com/google/fuzzing RUN git clone --depth 1 https://github.com/apple/swift-nio.git COPY build.sh $SRC COPY *.swift $SRC/ WORKDIR $SRC/swift-nio

值得注意的细节:

  • 显式指定 tag:仓库中 Swift 项目的 Dockerfile 均使用带版本 tag 的镜像,如:ubuntu-24-04,并在project.yaml中同步声明base_os_version: ubuntu-24-04
  • fuzz target 的拷贝方式:通过COPY *.swift $SRC/将项目仓库中的 Swift fuzz target 拷贝到构建环境(对应前文「fuzz target 存放在项目仓库」的要求);
  • $SRC环境变量:与其他语言项目一致,$SRC是 OSS-Fuzz 约定的源码工作目录。

该基础镜像的构成可以在仓库中追溯:base-builder-swift/Dockerfile 在base-builder之上执行install_swift.sh,并将precompile_swift脚本安装到/usr/local/bin/

FROM gcr.io/oss-fuzz-base/base-builder RUN install_swift.sh COPY precompile_swift /usr/local/bin/

而 install_swift.sh 则完成了 Swift 工具链的安装:安装libc6-devlibstdc++-9-devpkg-configuuid-devzlib1g-dev等依赖包,下载并解压 Swift 6.1.3 release 工具链到/usr/,并从 LLVM 源码编译出专供 Swift 使用的llvm-symbolizer-swift(用于崩溃栈符号化,对应precompile_swift中将其复制到$OUT的动作)。

build.sh 与 precompile_swift:SWIFTFLAGS 的生成与使用

核心用法

build.sh的第一步应当 source(执行)precompile_swift脚本,该脚本会生成环境变量SWIFTFLAGS,随后即可将$SWIFTFLAGS直接拼接到 Swift 构建命令中,例如:

swift build -c release $SWIFTFLAGS

swift-protobuf 的完整范例

仓库中 swift-protobuf 项目的构建脚本(文档原文引用)展示了完整的用法,其中还包含 fuzz target 产物的收集与重命名逻辑:

. precompile_swift # build project cd FuzzTesting swift build -c debug $SWIFTFLAGS ( cd .build/debug/ find . -maxdepth 1 -type f -name "*Fuzzer" -executable | while read i; do cp $i $OUT/"$i"-debug; done )

逐步解读这段脚本:

  1. . precompile_swift:以 source 方式执行脚本,使SWIFTFLAGS等环境变量在当前 shell 生效;
  2. swift build -c debug $SWIFTFLAGS:进入 fuzz 测试工程目录(本例为FuzzTesting),携带$SWIFTFLAGS执行构建。使用-c debug而非 release,可以保留更多调试信息、提升 sanitizer 报错的可读性;
  3. 收集产物:find.build/debug/下查找名称以Fuzzer结尾、且带可执行权限的文件,逐个拷贝到$OUT并追加-debug后缀。由于 swiftpm 会生成多个可执行目标,这种批量收集方式可以避免遗漏;
  4. $OUT是 OSS-Fuzz 约定的 fuzz target 输出目录,构建产物最终会被打包并运行于集群。

precompile_swift 的底层实现原理

SWIFTFLAGS的内容由 precompile_swift 脚本根据当前构建上下文动态生成,其核心逻辑如下(摘录关键行):

cp /usr/local/bin/llvm-symbolizer-swift $OUT/llvm-symbolizer export SWIFTFLAGS="-Xswiftc -parse-as-library -Xswiftc -static-stdlib --static-swift-stdlib" if [ "$SANITIZER" = "coverage" ] then export SWIFTFLAGS="$SWIFTFLAGS -Xswiftc -profile-generate -Xswiftc -profile-coverage-mapping -Xswiftc -sanitize=fuzzer" else export SWIFTFLAGS="$SWIFTFLAGS -Xswiftc -sanitize=fuzzer,$SANITIZER --sanitize=$SANITIZER" for f in $CFLAGS; do export SWIFTFLAGS="$SWIFTFLAGS -Xcc=$f" done for f in $CXXFLAGS; do export SWIFTFLAGS="$SWIFTFLAGS -Xcxx=$f" done fi

逐项拆解这些标志的含义:

标志作用
-Xswiftc -parse-as-library将顶层代码按库(library)而非可执行文件解析,这是 fuzz target 以函数入口(而非main)组织的必要条件
-Xswiftc -static-stdlib/--static-swift-stdlib静态链接 Swift 标准库,避免运行时依赖动态库导致 fuzz target 在 OSS-Fuzz 运行环境中无法加载
-Xswiftc -sanitize=fuzzer,$SANITIZER/--sanitize=$SANITIZER同时启用 libFuzzer 与当前 sanitizer(address/thread),其中$SANITIZER由 OSS-Fuzz 构建系统按project.yamlsanitizers字段注入
-Xswiftc -profile-generate/-profile-coverage-mapping仅 coverage 构建时启用,生成覆盖率映射信息(配合-sanitize=fuzzer实现带覆盖引导的模糊测试)
-Xcc=$f/-Xcxx=$f将 OSS-Fuzz 为 C/C++ 设置的$CFLAGS/$CXXFLAGS(如-fsanitize-O1等)逐条透传给底层 Clang 编译器,保证 Swift 与 C/C++ 混合代码的插桩与 sanitizer 行为一致

此外,脚本第一步将llvm-symbolizer-swift复制为$OUT/llvm-symbolizer,使崩溃报告能够正确符号化 Swift 栈帧。这与project.yaml中仅声明libfuzzer引擎、address/threadsanitizer 的限制遥相呼应:precompile_swift是在 Swift 工具链之上补齐 libFuzzer 集成的关键胶水层。

端到端集成清单

将以上内容整合,一个 Swift 项目接入 OSS-Fuzz 的完整落地步骤为:

  1. 编写 fuzz target(置于你的项目仓库):用@_cdecl("LLVMFuzzerTestOneInput")导出入口,签名(UnsafeRawPointer, Int) -> CInt
  2. 创建项目目录:在 OSS-Fuzz 仓库的projects/<name>/下准备三个文件;
  3. 配置 project.yaml:声明language: swiftfuzzing_engines仅填libfuzzersanitizersaddress/thread,建议同步声明base_os_version: ubuntu-24-04
  4. 编写 DockerfileFROM gcr.io/oss-fuzz-base/base-builder-swift:ubuntu-24-04,克隆源码并COPYfuzz target 与build.sh
  5. 编写 build.sh:以. precompile_swift开头,用swift build -c debug $SWIFTFLAGS构建,再按需将产物复制到$OUT(可参考 swift-protobuf 的批量收集写法)。

完成上述步骤后,即可按照新项目接入通用指南的后续流程提交项目、通过本地构建验证并接入 OSS-Fuzz 的持续模糊测试。仓库中的 swift-nio 与 swift-protobuf 两个目录是完整的 Swift 项目参考实现,涵盖project.yamlDockerfilebuild.sh与 Swift fuzz target 源文件,可作为新项目模板对照学习。

【免费下载链接】oss-fuzzOSS-Fuzz - continuous fuzzing for open source software.项目地址: https://gitcode.com/gh_mirrors/os/oss-fuzz

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/23 7:44:13

多机器人覆盖路径规划:蒙特卡洛树搜索实战指南

简介&#xff1a;本资源面向计算机、人工智能、自动化等专业的在校学生与研究人员&#xff0c;提供一套基于蒙特卡洛树搜索算法实现多机器人区域覆盖路径规划的完整项目源码&#xff0c;可用于课程设计、毕业设计或算法学习进阶。压缩包共6个文件&#xff0c;包含4个Python脚本…

作者头像 李华
网站建设 2026/9/23 7:43:52

基于 Java Spring Boot 的关爱自闭症儿童服务平台设计与实现

温馨提示&#xff1a;本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 1. 项目背景与意义 自闭症谱系障碍是一种广泛性发育障碍&#xff0c;近年来发病率呈上升趋势。由于自闭症儿童在社交沟通、行为模式等方面存在特殊需求&#xff0c;其家…

作者头像 李华
网站建设 2026/9/23 7:43:31

中小企业智能客服选型:5款主流方案的NLU性能与接入成本平衡分析

中小企业在部署智能客服时&#xff0c;常面临一个典型矛盾&#xff1a;NLU&#xff08;自然语言理解&#xff09;引擎的意图识别准确率直接影响用户体验&#xff0c;而API调用成本、知识库维护投入和并发承载能力又决定了项目能否持续运行。电商售后场景中&#xff0c;用户表述…

作者头像 李华
网站建设 2026/9/23 7:40:49

从截止日期倒排项目计划:WBS拆解、里程碑与风险预案实战复盘

"2026-3-9"这个日期&#xff0c;在我日历里躺了整整三个月&#xff0c;用加粗的红框标着。不是纪念日&#xff0c;也不是发薪日&#xff0c;而是一个项目的最终交付节点。定下这个日期的当天&#xff0c;我做的第一件事不是召集开会&#xff0c;也不是开工写代码&…

作者头像 李华
网站建设 2026/9/23 7:40:26

生成式AI文本检测与降AI率工具测评指南

1. 项目背景与核心需求2023年以来&#xff0c;生成式AI技术呈现爆发式增长&#xff0c;各类AI写作工具如雨后春笋般涌现。作为学术研究者&#xff0c;特别是研究生群体&#xff0c;在论文写作过程中如何合理使用这些工具&#xff0c;同时确保学术诚信&#xff0c;成为亟待解决的…

作者头像 李华
网站建设 2026/9/23 7:39:31

一次网页请求背后的计算机网络:TCP握手、CRC校验与分层模型

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华