• Home
Name Date Size #Lines LOC

..--

tools/12-May-2024-528357

BUILD.gnD12-May-20242.8 KiB6254

README_zh.mdD12-May-202410.1 KiB336222

fuzzer_helper.pyD12-May-20247.9 KiB266203

README_zh.md

1# 测试框架Fuzzing安全测试指导
2
3- [Fuzzing简介](#section7730298375831)
4- [Fuzzing测试关注的风险接口](#section00067164921)
5- [使用测试框架DTFuzz](#section0009871491)
6  - [配置启动测试框架](#section005187487501)
7  - [单个Fuzz用例初始化](#section372106507189)
8  - [Fuzz用例编写](#section98175917)
9  - [Fuzz用例编译](#section00816581589)
10  - [Fuzz用例执行](#section7510974319)
11- [测试结果与日志](#section016190470)
12
13## Fuzzing简介<a name="section7730298375831"></a>
14
15模糊测试(fuzzing test)是一种软件测试技术,其核心思想是将自动或半自动生成的随机数据输入到一个程序中,并监视程序异常,如崩溃,断言(assertion)失败,以发现可能的程序错误,比如内存泄漏,访问越界等。
16
17Fuzzing测试框架使用了LLVM编译器框架中的[libFuzzer](https://llvm.org/docs/LibFuzzer.html)作为Fuzzing引擎进行构建,libFuzzer是一个基于LLVM编译时路径插桩,可以对被测库API进行路径引导测试的Fuzzing引擎。
18
19使用Fuzzing测试框架,需要完成fuzzer测试用例初始化、fuzzer用例编写、fuzzer用例编译和fuzzer用例执行几步。
20
21
22
23## Fuzzing测试关注的风险接口<a name="section00067164921"></a>
24
25开发者应该了解自身模块的接口数据输入是基于不可信的来源输入,特别是针对
26
27- 解析处理远程发送来的TCP/UDP或者蓝牙等协议数据
28- 通过复杂的文件解码处理等,包括音视频、图片解码、解压缩等
29- IPC跨进程的数据输入处理
30
31通过Fuzzing的覆盖引导能力,可以有效的探测和消减外部输入造成的内存安全问题,也可以极大的增强系统稳定性。
32
33
34
35## 使用测试框架开展Fuzzing<a name="section0009871491"></a>
36
37### 配置启动测试框架<a name="section005187487501"></a>
38
39参考[ 开发者测试组件](https://gitee.com/openharmony/test_developertest/blob/master/README_zh.md)中的描述完成测试框架安装、设备连接配置,并在linux环境下通过
40
41```
42./start.sh
43```
44
45启动测试框架。
46
47
48
49### 单个Fuzz用例初始化<a name="section372106507189"></a>
50
511. Fuzz测试用例生成
52
53   执行gen命令用于fuzzer源文件生成,会自动生成fuzzer源文件、fuzzer配置文件和corpus语料,目录结构如下
54
55   ```
56   parse_fuzzer/
57   ├── corpus                        # Fuzz语料目录
58   │   ├── init                      # Fuzz语料
59   ├── BUILD.gn                      # Fuzz用例编译配置
60   ├── parse_fuzzer.cpp              # Fuzz用例源文件
61   ├── parse_fuzzer.h                # Fuzz用例头文件
62   ├── project.xml                   # Fuzz选项配置文件
63   ```
64
652. 命令参数说明,参数可以指定fuzzer名称和fuzzer路径
66
67   ```
68   gen -t TESTTYPE -fn FUZZERNAME -dp DIRECTORYPATH
69   ```
70
71   | 参数 | 描述       | 说明           | 备注                                       |
72   | ---- | ---------- | -------------- | ------------------------------------------ |
73   | -t   | testtype   | 测试类型       | 目前仅支持"FUZZ"                           |
74   | -fn  | fuzzername | fuzzer名称     | 为显式区分Fuzz用例,名称必须以"fuzzer"结尾 |
75   | -dp  | dirpath    | fuzzer生成路径 | 路径不存在则自动创建目录                   |
76
773. gen命令示例,-t、-fn和-dp均为必选项
78
79   ```
80   gen -t FUZZ -fn parse_fuzzer -dp test/developertest/example/calculator/test/fuzztest/common
81   ```
82
83   执行完毕后会在test/developertest/example/calculator/test/fuzztest/common目录下生成一个Fuzz用例demo。
84
85
86
87### Fuzz用例编写<a name="section98175917"></a>
88
891. 源文件编写
90
91   Fuzz用例主要在**${fuzzer名称}.cpp**源文件中,一个Fuzz用例仅支持一个接口进行fuzz测试。
92
93   源文件包含两个接口:
94
95   | 接口                            | 说明                             |
96   | ------------------------------- | -------------------------------- |
97   | LLVMFuzzerTestOneInput          | Fuzz入口函数,由Fuzz框架调用     |
98   | DoSomethingInterestingWithMyAPI | 被测试接口,实现各业务被测试逻辑 |
99
100   ![img](../../public_sys-resources/icon-note.gif) **说明:** DoSomethingInterestingWithMyAPI接口名称允许依据业务逻辑修改。两接口参数data和size为fuzz测试标准化参数,不可修改。
101
102   ```
103   #include "parse_fuzzer.h"
104
105   #include <stddef.h>
106   #include <stdint.h>
107
108   const int FUZZ_DATA_LEN = 3;
109   const int FUZZ_FST_DATA = 0;
110   const int FUZZ_SND_DATA = 1;
111   const int FUZZ_TRD_DATA = 2;
112   const int FUZZ_FTH_DATA = 3;
113
114   namespace OHOS {
115       bool DoSomethingInterestingWithMyAPI(const uint8_t* data, size_t size)
116       {
117           bool result = false;
118           if (size >= FUZZ_DATA_LEN) {
119               result = data[FUZZ_FST_DATA] == 'F' &&
120                   data[FUZZ_SND_DATA] == 'U' &&
121                   data[FUZZ_TRD_DATA] == 'Z' &&
122                   data[FUZZ_FTH_DATA] == 'Z';
123           }
124           return result;
125       }
126   }
127
128   /* Fuzzer entry point */
129   extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
130   {
131       /* Run your code on data */
132       OHOS::DoSomethingInterestingWithMyAPI(data, size);
133       return 0;
134   }
135   ```
136
137
138
1392. BUILD.gn编写
140
141   基于[ohos_fuzztest]配置Fuzz模板,例如:
142
143   ```
144   ohos_fuzztest("CalculatorFuzzTest") {     #定义测试套名称CalculatorFuzzTest
145     module_out_path = module_output_path
146
147     include_dirs = []
148     cflags = [
149       "-g",
150       "-O0",
151       "-Wno-unused-variable",
152       "-fno-omit-frame-pointer",
153     ]
154     sources = [ "parse_fuzzer.cpp" ]
155   }
156   ```
157
158   [group]引用测试套,例如:
159
160   ```
161   group("fuzztest") {
162     testonly = true
163     deps = []
164
165     deps += [
166       # deps file
167       ":CalculatorFuzzTest",     #引用测试套
168     ]
169   }
170   ```
171
172
173
1743. Fuzz配置编写
175
176   project.xml为DTFuzz参数配置文件,提供基于libFuzzer参数的动态配置,更多参数配置可参考[libFuzzer参数配置](https://llvm.org/docs/LibFuzzer.html#options)177
178   ```
179   <!-- maximum length of a test input -->
180   <max_len>1000</max_len>
181   <!-- maximum total time in seconds to run the DTFuzz -->
182   <max_total_time>300</max_total_time>
183   <!-- memory usage limit in Mb -->
184   <rss_limit_mb>4096</rss_limit_mb>
185   ```
186
187
188
189### Fuzz用例编译<a name="section00816581589"></a>
190
191添加Fuzz用例编译到模块的test_list中:
192
1931. 在需要DTFuzz测试的对应模块ohos.build添加Fuzz用例路径,如在examples/ohos.build添加:
194
195   ```
196   "test_list": [
197     "//test/developertest/examples/calculator/test:unittest",
198     "//test/developertest/examples/calculator/test:fuzztest", #添加DTFuzz用例路径
199     "//test/developertest/examples/detector/test:unittest",
200     "//test/developertest/examples/sleep/test:performance",
201     "//test/developertest/examples/distributedb/test:distributedtest"
202   ]
203   ```
204
2052. 在用例路径下的BUILD.gn添加group,如examples/calculator/testBUILD.gn
206
207   ```
208   group("fuzztest") {
209     testonly = true
210     deps = []
211
212     deps += [ "fuzztest/common/parse_fuzzer:fuzztest" ]
213   }
214   ```
215
216
217
218### Fuzz用例执行<a name="section7510974319"></a>
219
220Fuzz能力集成,在测试类型-t中新增FUZZ类型,执行Fuzz测试指令示例,其中-t为必选,-ss和-tm为可选
221
222```
223run -t FUZZ -ss developertest -tm calculator
224```
225
226| 参数 | 描述       | 说明     | 备注                     |
227| ---- | ---------- | -------- | ------------------------ |
228| -t   | TESTTYPE   | 测试类型 |                          |
229| -ss  | SUBSYSTEM  | 子系统   | 被测试子系统             |
230| -tm  | TESTMODULE | 模块     | 被测试模块,如calculator |
231
232- Windows环境脱离源码执行
233
234  Windows环境可通过归档DTFuzz用例配置文件project.xml、语料corpus和可执行文件执行DTFuzz。
235
236  1. 归档用例配置文件、语料
237
238     新建目录,如:
239
240     ```
241     D:\test\res\parse_fuzzer
242     ```
243
244     parse_fuzzer用例的配置文件project.xml、语料corpus拷贝到该路径下。如有多个需要执行的用例,在res目录下新建多个xxx_fuzzer目录。
245
246  2. 归档用例可执行文件
247
248     用例可执行文件为DTFuzz源文件编译产出文件,为DTFuzz用例在设备中实际执行文件,以二进制形式存储在out/release/package/phone/tests/fuzztest下,名称为对应的测试套名。
249
250     新建目录,如:
251
252     ```
253     D:\test\cases
254     ```
255
256     将fuzztest目录拷贝到该路径下。
257
258  3. 配置执行用例
259
260     libs\fuzzlib中新建fuzzer_list.txt,其中配置需要执行的DTFuzz用例,如需要执行parse_fuzzer用例:
261
262     ```
263     #格式:用例配置文件和语料归档路径 可执行文件名
264     D:\test\res\parse_fuzzer CalculatorFuzzTest
265     ```
266
267     ![img](../../public_sys-resources/icon-note.gif) **说明:**
268
269     1.fuzzer_list.txt中可配置多行,每行对应一个DTFuzz用例
270
271     2.路径与可执行文件名严格一一对应,如例子中路径归档的是parse_fuzzer用例的配置文件和语料,CalculatorFuzzTest为parse_fuzzer用例的可执行文件。
272
273  4. 配置用例路径
274
275     config\user_config.xml中配置用例归档路径:
276
277     ```
278     <!-- configure test cases path -->
279     <test_cases>
280       <dir>D:\test\cases</dir>     #用例可执行文件归档路径
281     </test_cases>
282     ```
283
284  5. 执行用例
285
286     执行DTFuzz命令示例,无需参数-ss、-tm
287
288     ```
289     run -t FUZZ
290     ```
291
292
293
294## 测试结果与日志<a name="section016190470"></a>
295
296- 通过在测试框架中执行测试指令,即可以生成测试日志和测试报告。
297
298- 测试结果
299
300  测试用例的结果会直接显示在控制台上,执行一次的测试结果根路径如下:
301
302  ```
303  reports/xxxx-xx-xx-xx-xx-xx
304  ```
305
306  测试用例格式化结果
307
308  ```
309  result/
310  ```
311
312  测试用例日志
313
314  ```
315  log/plan_log_xxxx-xx-xx-xx-xx-xx.log
316  ```
317
318  测试报告汇总
319
320  ```
321  summary_report.html
322  ```
323
324  测试报告详情
325
326  ```
327  details_report.html
328  ```
329
330  最新测试报告
331
332  ```
333  reports/latest
334  ```
335
336