diff --git a/config/framework_config.xml b/config/framework_config.xml
index 041b510111a883c041e9fbb325b97591c7fa6550..4bad38c2c0da378adf6bfcb9c0f4c6a7a04db1de 100755
--- a/config/framework_config.xml
+++ b/config/framework_config.xml
@@ -35,6 +35,9 @@
+
diff --git a/config/fuzz_config.xml b/config/fuzz_config.xml
new file mode 100644
index 0000000000000000000000000000000000000000..85e7ef2c1cc6471e288306f6e3dcea5287a78b0e
--- /dev/null
+++ b/config/fuzz_config.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+ 1000
+
+ 300
+
+ 4096
+
+
diff --git a/examples/calculator/test/BUILD.gn b/examples/calculator/test/BUILD.gn
index f629f1bd87fb2007666033324cc667d940cc81e2..730de036ffcefc5724da64eef9135d26d2dfc4b9 100755
--- a/examples/calculator/test/BUILD.gn
+++ b/examples/calculator/test/BUILD.gn
@@ -24,4 +24,11 @@ group("unittest") {
deps += [ "unittest/phone:unittest" ]
}
}
+
+group("fuzztest") {
+ testonly = true
+ deps = []
+
+ deps += [ "fuzztest/common/parse_fuzzer:fuzztest" ]
+}
###############################################################################
diff --git a/examples/calculator/test/fuzztest/common/parse_fuzzer/BUILD.gn b/examples/calculator/test/fuzztest/common/parse_fuzzer/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..8072e7dadc6404b596c6b0264c3ed6a0d48ada93
--- /dev/null
+++ b/examples/calculator/test/fuzztest/common/parse_fuzzer/BUILD.gn
@@ -0,0 +1,43 @@
+# Copyright (c) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build/config/features.gni")
+import("//build/test.gni")
+
+module_output_path = "subsystem_examples/calculator"
+
+##############################fuzztest##########################################
+ohos_fuzztest("CalculatorFuzzTest") {
+ module_out_path = module_output_path
+
+ include_dirs = []
+ cflags = [
+ "-g",
+ "-O0",
+ "-Wno-unused-variable",
+ "-fno-omit-frame-pointer",
+ ]
+ sources = [ "parse_fuzzer.cpp" ]
+}
+
+###############################################################################
+group("fuzztest") {
+ testonly = true
+ deps = []
+
+ deps += [
+ # deps file
+ ":CalculatorFuzzTest",
+ ]
+}
+###############################################################################
diff --git a/examples/calculator/test/fuzztest/common/parse_fuzzer/corpus/init b/examples/calculator/test/fuzztest/common/parse_fuzzer/corpus/init
new file mode 100644
index 0000000000000000000000000000000000000000..6b7212c8a6a9ee6e433ea43d0c2c2e96568ad4c4
--- /dev/null
+++ b/examples/calculator/test/fuzztest/common/parse_fuzzer/corpus/init
@@ -0,0 +1 @@
+FUZZ
\ No newline at end of file
diff --git a/examples/calculator/test/fuzztest/common/parse_fuzzer/parse_fuzzer.cpp b/examples/calculator/test/fuzztest/common/parse_fuzzer/parse_fuzzer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..576457ac2b63bf9664c6513c4a4126aed79f71fc
--- /dev/null
+++ b/examples/calculator/test/fuzztest/common/parse_fuzzer/parse_fuzzer.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "parse_fuzzer.h"
+
+#include
+#include
+
+const int FUZZ_DATA_LEN = 3;
+const int FUZZ_FST_DATA = 0;
+const int FUZZ_SND_DATA = 1;
+const int FUZZ_TRD_DATA = 2;
+const int FUZZ_FTH_DATA = 3;
+
+namespace OHOS {
+ bool DoSomethingInterestingWithMyAPI(const uint8_t* data, size_t size)
+ {
+ bool result = false;
+ if (size >= FUZZ_DATA_LEN) {
+ result = data[FUZZ_FST_DATA] == 'F' &&
+ data[FUZZ_SND_DATA] == 'U' &&
+ data[FUZZ_TRD_DATA] == 'Z' &&
+ data[FUZZ_FTH_DATA] == 'Z';
+ }
+ return result;
+ }
+}
+
+/* Fuzzer entry point */
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
+{
+ /* Run your code on data */
+ OHOS::DoSomethingInterestingWithMyAPI(data, size);
+ return 0;
+}
+
diff --git a/examples/calculator/test/fuzztest/common/parse_fuzzer/parse_fuzzer.h b/examples/calculator/test/fuzztest/common/parse_fuzzer/parse_fuzzer.h
new file mode 100644
index 0000000000000000000000000000000000000000..bf3acfc48cd91e9eeb848b9e7eca48c6e461d822
--- /dev/null
+++ b/examples/calculator/test/fuzztest/common/parse_fuzzer/parse_fuzzer.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define FUZZ_PROJECT_NAME "parse_fuzzer"
diff --git a/examples/calculator/test/fuzztest/common/parse_fuzzer/project.xml b/examples/calculator/test/fuzztest/common/parse_fuzzer/project.xml
new file mode 100644
index 0000000000000000000000000000000000000000..85e7ef2c1cc6471e288306f6e3dcea5287a78b0e
--- /dev/null
+++ b/examples/calculator/test/fuzztest/common/parse_fuzzer/project.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+ 1000
+
+ 300
+
+ 4096
+
+
diff --git a/examples/ohos.build b/examples/ohos.build
index e87ba886c427d20cc009062342cd102add797a95..ba3c3da48f4615e2475007e2da2f073c7286d5e9 100755
--- a/examples/ohos.build
+++ b/examples/ohos.build
@@ -9,6 +9,7 @@
],
"test_list": [
"//test/developertest/examples/calculator/test:unittest",
+ "//test/developertest/examples/calculator/test:fuzztest",
"//test/developertest/examples/detector/test:unittest",
"//test/developertest/examples/sleep/test:performance",
"//test/developertest/examples/distributedb/test:distributedtest"
diff --git a/libs/fuzzlib/BUILD.gn b/libs/fuzzlib/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..252382787670e98e0113cca643fb064f7db2b67f
--- /dev/null
+++ b/libs/fuzzlib/BUILD.gn
@@ -0,0 +1,61 @@
+# Copyright (c) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("///build/config/sanitizers/sanitizers.gni")
+
+fuzzing_engine_remove_configs = [
+ "//build/config/coverage:default_coverage",
+ "//build/config/sanitizers:default_sanitizer_flags",
+]
+
+fuzzing_engine_add_configs =
+ [ "//build/config/sanitizers:default_sanitizer_flags_but_coverage" ]
+
+source_set("libfuzzer") {
+ sources = [
+ "//third_party/llvm-project/compiler-rt/lib/fuzzer/FuzzerCrossOver.cpp",
+ "//third_party/llvm-project/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.cpp",
+ "//third_party/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp",
+ "//third_party/llvm-project/compiler-rt/lib/fuzzer/FuzzerExtFunctionsDlsym.cpp",
+ "//third_party/llvm-project/compiler-rt/lib/fuzzer/FuzzerExtFunctionsWeak.cpp",
+ "//third_party/llvm-project/compiler-rt/lib/fuzzer/FuzzerExtFunctionsWindows.cpp",
+ "//third_party/llvm-project/compiler-rt/lib/fuzzer/FuzzerExtraCounters.cpp",
+ "//third_party/llvm-project/compiler-rt/lib/fuzzer/FuzzerFork.cpp",
+ "//third_party/llvm-project/compiler-rt/lib/fuzzer/FuzzerIO.cpp",
+ "//third_party/llvm-project/compiler-rt/lib/fuzzer/FuzzerIOPosix.cpp",
+ "//third_party/llvm-project/compiler-rt/lib/fuzzer/FuzzerIOWindows.cpp",
+ "//third_party/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp",
+ "//third_party/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp",
+ "//third_party/llvm-project/compiler-rt/lib/fuzzer/FuzzerMerge.cpp",
+ "//third_party/llvm-project/compiler-rt/lib/fuzzer/FuzzerMutate.cpp",
+ "//third_party/llvm-project/compiler-rt/lib/fuzzer/FuzzerSHA1.cpp",
+ "//third_party/llvm-project/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp",
+ "//third_party/llvm-project/compiler-rt/lib/fuzzer/FuzzerUtil.cpp",
+ "//third_party/llvm-project/compiler-rt/lib/fuzzer/FuzzerUtilDarwin.cpp",
+ "//third_party/llvm-project/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp",
+ "//third_party/llvm-project/compiler-rt/lib/fuzzer/FuzzerUtilLinux.cpp",
+ "//third_party/llvm-project/compiler-rt/lib/fuzzer/FuzzerUtilPosix.cpp",
+ ]
+
+ configs -= fuzzing_engine_remove_configs
+ configs += fuzzing_engine_add_configs
+}
+
+if (use_afl) {
+ source_set("afl_driver") {
+ sources = [ "src/afl/afl_driver.cpp" ]
+
+ configs -= fuzzing_engine_remove_configs
+ configs += fuzzing_engine_add_configs
+ }
+}
diff --git a/libs/fuzzlib/DTFuzz README.md b/libs/fuzzlib/DTFuzz README.md
new file mode 100644
index 0000000000000000000000000000000000000000..49a605eb6ce063791a15ef0a316b04734d6c83d6
--- /dev/null
+++ b/libs/fuzzlib/DTFuzz README.md
@@ -0,0 +1,228 @@
+# 测试框架DTFuzz测试指导
+
+
+
+## 简介
+
+模糊测试(fuzzing test)是一种软件测试技术,其核心思想是将自动或半自动生成的随机数据输入到一个程序中,并监视程序异常,如崩溃,断言(assertion)失败,以发现可能的程序错误,比如内存泄漏,访问越界等。
+
+使用测试框架DTFuzz,需要完成DTFuzz初始化、DTFuzz用例编写、DTFuzz用例编译和DTFuzz用例执行几步。
+
+
+
+## 使用测试框架DTFuzz
+
+- 测试框架配置
+
+ 文件:config/user_config.xml
+
+ 配置测试用例的编译参数
+
+ ```
+
+ false
+ false
+ true
+ ... ...
+
+ ```
+
+ ![img](https://gitee.com/nicoyam/test_developertest/raw/master/public_sys-resources/icon-note.gif) **说明:** 测试用例的编译参数说明如下:
+
+ example:是否编译测试用例示例,默认false。
+
+ version:是否编译测试版本,默认false。
+
+ testcase:是否编译测试用例,默认true。
+
+- 启动测试框架
+
+ 打开test/developertest目录,Windows环境启动测试框架执行
+
+ ```
+ start.bat
+ ```
+
+ Linux环境启动测试框架执行
+
+ ```
+ ./strat.sh
+ ```
+
+- 设备形态选择
+
+ 根据实际的开发板选择,设备形态配置:developertest/config/framework_config.xml。
+
+- 单个DTFuzz初始化
+
+ 1. DTFuzz源文件生成
+
+ 执行gen命令用于DTFuzz源文件生成,会自动生成DTFuzz源文件、DTFuzz options配置文件和corpus语料,目录结构如下
+
+ ```
+ parse_fuzzer/
+ ├── corpus # DTFuzz语料目录
+ │ ├── init # DTFuzz语料
+ ├── BUILD.gn # DTFuzz用例编译配置
+ ├── parse_fuzzer.cpp # DTFuzz用例源文件
+ ├── parse_fuzzer.h # DTFuzz用例头文件
+ ├── project.xml # DTFuzz选项配置文件
+ ```
+
+ 2. 命令参数说明,参数可以指定DTFuzz名称和DTFuzz路径
+
+ ```
+ gen -t TESTTYPE -fn FUZZERNAME -dp DIRECTORYPATH
+ ```
+
+ | 参数 | 说明 | 备注 |
+ | ---- | -------------- | -------------------------------------------------------- |
+ | -t | 测试类型 | 目前仅支持"FUZZ" |
+ | -fn | DTFuzz名称 | 为显式区分DTFuzz,名称必须以"fuzzer"结尾 |
+ | -dp | DTFuzz生成路径 | 执行命令前需要手动创建fuzztest目录和对应形态目录如common |
+
+ 3. gen命令示例,-t、-fn和-dp均为必选项
+
+ ```
+ gen -t FUZZ -fn parse_fuzzer -dp test/developertest/example/calculator/test/fuzztest/common
+ ```
+
+- DTFuzz用例编写
+
+ 1. 源文件编写
+
+ DTFuzz用例主要在${DTFuzz名称}.cpp源文件中,一个DTFuzz仅支持一个接口进行fuzz测试。
+
+ 源文件包含两个接口:
+
+ | 接口 | 说明 |
+ | ------------------------------- | -------------------------------- |
+ | LLVMFuzzerTestOneInput | DTFuzz入口函数,由Fuzz框架调用 |
+ | DoSomethingInterestingWithMyAPI | 被测试接口,实现各业务被测试逻辑 |
+
+ ![img](https://gitee.com/nicoyam/test_developertest/raw/master/public_sys-resources/icon-note.gif) **说明:** DoSomethingInterestingWithMyAPI接口名称允许依据业务逻辑修改。两接口参数data和size为fuzz测试标准化参数,不可修改。
+
+ 2. BUILD.gn编写
+
+ [ohos_fuzztest] # 配置DTFuzz模板,例如:
+
+ ```
+ ohos_fuzztest("CalculatorFuzzTest") { #定义测试套名称CalculatorFuzzTest
+
+ module_out_path = module_output_path
+
+ include_dirs = []
+ cflags = [
+ "-g",
+ "-O0",
+ "-Wno-unused-variable",
+ "-fno-omit-frame-pointer",
+ ]
+ sources = [ "parse_fuzzer.cpp" ]
+ }
+ ```
+
+ [group] # 引用测试套,例如:
+
+ ```
+ group("fuzztest") {
+ testonly = true
+ deps = []
+
+ deps += [
+ # deps file
+ ":CalculatorFuzzTest", #引用测试套
+ ]
+ }
+ ```
+
+ 3. DTFuzz配置编写
+
+ project.xml为DTFuzz参数配置文件,包括:
+
+ ```
+
+ 1000
+
+ 300
+
+ 4096
+ ```
+
+- DTFuzz用例编译
+
+ 添加DTFuzz用例编译:
+
+ 1. 在需要DTFuzz测试的对应模块ohos.build添加DTFuzz用例路径,如在examples/ohos.build添加:
+
+ ```
+ "test_list": [
+ "//test/developertest/examples/calculator/test:unittest",
+ "//test/developertest/examples/calculator/test:fuzztest", #添加DTFuzz用例路径
+ "//test/developertest/examples/detector/test:unittest",
+ "//test/developertest/examples/sleep/test:performance",
+ "//test/developertest/examples/distributedb/test:distributedtest"
+ ]
+ ```
+
+ 2. 在用例路径下的BUILD.gn添加group,如examples/calculator/test的BUILD.gn
+
+ ```
+ group("fuzztest") {
+ testonly = true
+ deps = []
+
+ deps += [ "fuzztest/common/parse_fuzzer:fuzztest" ]
+ }
+ ```
+
+- DTFuzz用例执行
+
+ DTFuzz能力集成在测试类型-t中新增FUZZ类型,执行DTFuzz测试指令示例,其中-t为必选,-ss和-tm为可选
+
+ ```
+ run -t FUZZ -ss subsystem_examples -tm calculator
+ ```
+
+## 测试结果与日志
+
+- 通过在测试框架中执行测试指令,即可以生成测试日志和测试报告。
+
+- 测试结果
+
+ 测试用例的结果会直接显示在控制台上,执行一次的测试结果根路径如下:
+
+ ```
+ reports/xxxx-xx-xx-xx-xx-xx
+ ```
+
+ 测试用例格式化结果
+
+ ```
+ result/
+ ```
+
+ 测试用例日志
+
+ ```
+ log/plan_log_xxxx-xx-xx-xx-xx-xx.log
+ ```
+
+ 测试报告汇总
+
+ ```
+ summary_report.html
+ ```
+
+ 测试报告详情
+
+ ```
+ details_report.html
+ ```
+
+ 最新测试报告
+
+ ```
+ reports/latest
+ ```
+
diff --git a/libs/fuzzlib/fuzzer_helper.py b/libs/fuzzlib/fuzzer_helper.py
new file mode 100644
index 0000000000000000000000000000000000000000..b7d4ee7cf210e3201d507147ec0d150e07f87b9b
--- /dev/null
+++ b/libs/fuzzlib/fuzzer_helper.py
@@ -0,0 +1,266 @@
+#!/usr/bin/env python
+# -*- coding:utf-8 -*-
+#
+# Copyright (c) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+from __future__ import print_function
+import argparse
+import os
+import re
+import sys
+import subprocess
+import zipfile
+import errno
+import pipes
+import traceback
+import time
+import copy
+
+from tools.colored import Colored
+from tools.templates import GN_ENTRY_TEMPLATE
+from tools.templates import PROJECT_GN_TEMPLATE
+from tools.templates import PROJECT_DEMO_TEMPLATE
+from tools.templates import PROJECT_HEADER_TEMPLATE
+from tools.templates import PROJECT_XML_TEMPLATE
+import shutil
+from pprint import pprint
+from tools.run_result import RunResult
+
+CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
+SOURCE_ROOT_DIR = os.path.dirname(
+ os.path.dirname(
+ os.path.dirname(os.path.dirname(CURRENT_DIR))
+ )
+ )
+SOURCE_OUT_DIR = os.path.join(SOURCE_ROOT_DIR, "out")
+
+TDD_BUILD_GN_PATH = os.path.join(
+ SOURCE_ROOT_DIR,
+ "test/developertest/BUILD.gn"
+ )
+###project name must end with _fuzzer. eg. my_fuzzer,extrator_fuzzer.
+VALID_PROJECT_NAME_REGEX = re.compile(r'^[a-zA-Z0-9_-]+(_fuzzer)+$')
+
+
+def _add_environment_args(parser):
+ """Add common environment args."""
+ parser.add_argument(
+ '-t',
+ '--target_platform',
+ default='phone',
+ choices=["phone", "ivi", "plato"],
+ help="set target_platform value, default:phone")
+
+ parser.add_argument(
+ '-f',
+ '--filter',
+ default=None,
+ help="subsystem filter")
+
+
+def _get_command_string(command):
+ """Returns a shell escaped command string."""
+ return ' '.join(pipes.quote(part) for part in command)
+
+
+def parse_projects_path():
+ path_list = []
+ with open(TDD_BUILD_GN_PATH, 'r') as gn_file:
+ for line in gn_file.readlines()[4:]:
+ striped_str = line.strip()
+ if striped_str.endswith("]"):
+ break
+ path_list.append(striped_str.split(":")[0][3:])
+ return path_list
+
+
+def _get_fuzzer_yaml_config(fuzzer_name):
+ project_yaml_path = os.path.join(
+ CURRENT_DIR,
+ "projects",
+ fuzzer_name,
+ "project.yaml")
+ if not os.path.exists(project_yaml_path):
+ return None
+ #log run stdout to fuzzlog dir
+ with open(project_yaml_path) as filehandle:
+ yaml_config = yaml.safe_load(filehandle)
+ return yaml_config
+
+
+#generate template fuzzer project
+def generate(args):
+ print("project name %s." % args.project_name)
+ print("project path %s." % args.project_path)
+ color_logger = Colored.get_project_logger()
+
+ if not VALID_PROJECT_NAME_REGEX.match(args.project_name):
+ print('Invalid project name.', file=sys.stderr)
+ return 1
+
+ template_args = {
+ 'project_name': args.project_name,
+ 'author': "@fixme",
+ 'email': "@fixme"
+ }
+
+ project_dir_path = os.path.join(args.project_path, args.project_name)
+ print("project_dir_path %s." % project_dir_path)
+ try:
+ os.mkdir(project_dir_path)
+ except OSError as os_exception:
+ if os_exception.errno != errno.EEXIST:
+ raise
+ print(color_logger.red('%s already exists.' % project_dir_path),
+ file=sys.stderr)
+ return 1
+ color_logger.green('Writing new files to %s' % project_dir_path)
+
+ file_path = os.path.join(project_dir_path, 'project.xml')
+ with open(file_path, 'w') as filehandle:
+ filehandle.write(PROJECT_XML_TEMPLATE % template_args)
+
+ file_path = os.path.join(project_dir_path, "%s.cc" % args.project_name)
+ with open(file_path, 'w') as filehandle:
+ filehandle.write(PROJECT_DEMO_TEMPLATE % template_args)
+
+ file_path = os.path.join(project_dir_path, "%s.h" % args.project_name)
+ with open(file_path, 'w') as filehandle:
+ filehandle.write(PROJECT_HEADER_TEMPLATE % template_args)
+ file_path = os.path.join(project_dir_path, "BUILD.gn")
+ with open(file_path, 'w') as filehandle:
+ filehandle.write(PROJECT_GN_TEMPLATE % template_args)
+
+ corpus_dir = os.path.join(project_dir_path, 'corpus')
+ if not os.path.exists(corpus_dir):
+ os.mkdir(corpus_dir)
+ with open(os.path.join(corpus_dir, 'init'), 'w') as filehandle:
+ filehandle.write("FUZZ")
+
+
+#complie fuzzer project
+def make(args, stdout=None):
+ """make fuzzer module."""
+ color_logger = Colored.get_project_logger()
+
+ pre_cmd = ['cd', SOURCE_ROOT_DIR]
+ build_target_platform = "build_platform=\"%s\""
+
+ build_script = [
+ './build.sh',
+ '--gn-args',
+ 'build_example=true',
+ '--target-variant sanitizer',
+ '--build-target'
+ ]
+ build_script.append(args.project_name)
+ build_script.append("--gn-args")
+ build_script.append(build_target_platform % args.build_platform)
+ build_script.append("--product-name")
+ build_script.append(args.build_platform)
+ build_script.append("--export-para")
+ build_script.append("PYCACHE_ENABLE:true")
+ build_script.append("--export-para")
+ build_script.append("BUILD_AOSP:false")
+ print("BUILD_SCRIPT %s" % build_script)
+ final_cmd = "%s && %s" % (
+ _get_command_string(pre_cmd),
+ _get_command_string(build_script)
+ )
+
+ color_logger.green('Running:%s' % final_cmd)
+
+ subsystem_src_flag_file_path = os.path.join(
+ SOURCE_OUT_DIR,
+ "release/current_build_fuzz_target.txt"
+ )
+ if not os.path.exists(os.path.dirname(subsystem_src_flag_file_path)):
+ os.makedirs(os.path.dirname(subsystem_src_flag_file_path))
+ with open(subsystem_src_flag_file_path, "wb") as file_handle:
+ file_handle.write(args.project_name.encode())
+
+ try:
+ if stdout:
+ ret = subprocess.check_call(build_script, cwd=SOURCE_ROOT_DIR,
+ stdout=stdout)
+ else:
+ ret = subprocess.check_call(build_script, cwd=SOURCE_ROOT_DIR)
+ return ret
+ except subprocess.CalledProcessError:
+ print("*"*50)
+ print("*"*50)
+ print(
+ 'fuzzers {} build failed.'.format(args.project_name),
+ file=sys.stdout
+ )
+ return -1
+
+
+def report(args):
+ pass
+
+
+def coverage_all(args):
+ pass
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ 'fuzzer_helper.py',
+ description='hydra-fuzz helpers'
+ )
+ subparsers = parser.add_subparsers(dest='command')
+
+ generate_parser = subparsers.add_parser(
+ 'generate',
+ help='Generate files for new project.name must end with "_fuzzer".')
+ generate_parser.add_argument('project_name')
+ generate_parser.add_argument('project_path')
+ _add_environment_args(generate_parser)
+
+ make_parser = subparsers.add_parser(
+ 'make', help='Build a single fuzzer module project. ')
+ make_parser.add_argument('project_name')
+ make_parser.add_argument('build_platform')
+ _add_environment_args(make_parser)
+
+ report_parser = subparsers.add_parser(
+ 'report', help='Report fuzzer log'
+ )
+ _add_environment_args(report_parser)
+ report_parser.add_argument(
+ 'subfunc',
+ default="list",
+ choices=["list", "coverage", "all"]
+ )
+ report_parser.add_argument(
+ "-i",
+ "--id",
+ required=False,
+ help="report ID, e.g. empty_fuzzer.20200211184850"
+ )
+
+ args = parser.parse_args()
+
+ if args.command == 'generate':
+ return generate(args)
+ elif args.command == 'make':
+ return make(args)
+
+ elif args.command == 'report':
+ report(args)
+
+if __name__ == "__main__":
+ main()
diff --git a/libs/fuzzlib/tools/__init__.py b/libs/fuzzlib/tools/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/libs/fuzzlib/tools/colored.py b/libs/fuzzlib/tools/colored.py
new file mode 100644
index 0000000000000000000000000000000000000000..fae3edf70cf0862e416bc765c886b01a1faf79c8
--- /dev/null
+++ b/libs/fuzzlib/tools/colored.py
@@ -0,0 +1,157 @@
+#!/usr/bin/env python
+# -*- coding:utf-8 -*-
+#
+# Copyright (c) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+import sys
+import os
+import time
+
+
+class Colored(object):
+ RED = '\033[1;31m'
+ GREEN = '\033[1;32m'
+ YELLOW = '\033[1;33m'
+ BLUE = '\033[1;34m'
+ FUCHSIA = '\033[1;35m'
+ CYAN = '\033[1;36m'
+ WHITE = '\033[1;37m'
+ RESET = '\033[0m'
+
+ DEBUG = True
+
+ LOG_TO_FILE = False
+ LOG_DIR = "fuzzlog"
+ LOG_PROJECT = None
+ LOG_DATE = None
+
+ PROJECT_LOGGER_MAP = {}
+
+ @staticmethod
+ def get_project_logger(log_project="default"):
+ if log_project in Colored.PROJECT_LOGGER_MAP:
+ return Colored.PROJECT_LOGGER_MAP[log_project]
+ logger = Colored(log_project)
+ Colored.PROJECT_LOGGER_MAP[log_project] = logger
+ return logger
+
+ def __init__(self, log_project="default"):
+ self.is_debug = True
+ self.is_log_file = False
+ self.log_project = log_project
+ self.log_date = time.strftime("%Y%m%d%H%M%S", time.localtime())
+
+
+ def start_log_file(self):
+ self.is_log_file = True
+ if not os.path.exists(Colored.LOG_DIR):
+ os.mkdir(Colored.LOG_DIR)
+
+ project_log_dir = self.get_fuzz_project_log_dir()
+ if not os.path.exists(project_log_dir):
+ os.mkdir(project_log_dir)
+
+ current_project_log_dir = self.get_fuzz_current_project_log_dir()
+ if not os.path.exists(current_project_log_dir):
+ os.mkdir(current_project_log_dir)
+
+
+ def get_fuzz_project_log_dir(self):
+ return os.path.join(Colored.LOG_DIR, self.log_project)
+
+ def get_fuzz_current_project_log_dir(self):
+ return os.path.join(Colored.LOG_DIR, self.log_project, self.log_date)
+
+ def get_fuzz_current_project_log_path(self):
+ return os.path.join(self.get_fuzz_current_project_log_dir(), "run.log")
+
+ def loghook(self, msg):
+ if self.is_log_file:
+ run_log = os.path.join(
+ self.get_fuzz_current_project_log_dir(),
+ "run.log"
+ )
+ with open(run_log, 'ab') as f:
+ f.write(msg+"\n")
+
+
+ def color_str(self, color, s, tag=None):
+ msg = ""
+ if tag:
+ msg = '{}{}{}{}'.format(
+ getattr(Colored, color),
+ tag,
+ s,
+ Colored.RESET
+ )
+ else:
+ msg = '{}{}{}'.format(
+ getattr(Colored, color),
+ s,
+ Colored.RESET
+ )
+ self.loghook(msg)
+ return msg
+
+ def red(self, s):
+ print(self.color_str('RED', s, "[ERROR] "))
+
+
+ def green(self, s):
+ if self.is_debug:
+ print(self.color_str('GREEN', s, "[INFO] "))
+
+
+ def yellow(self, s):
+ print(self.color_str('YELLOW', s, "[WARNING] "))
+
+
+ def blue(self, s):
+ return self.color_str('BLUE', s)
+
+ def fuchsia(self, s):
+ return self.color_str('FUCHSIA', s)
+
+ def cyan(s):
+ return self.color_str('CYAN', s)
+
+ def white(self, s):
+ print(self.color_str('WHITE', s))
+
+
+ def simple_print(self, s):
+ self.loghook(s)
+ print(s)
+
+
+ @staticmethod
+ def get_fuzz_log_dir():
+ return Colored.LOG_DIR
+
+ @staticmethod
+ def log_task_init(project):
+ Colored.LOG_TO_FILE = True
+ Colored.LOG_PROJECT = project
+ Colored.LOG_DATE = time.strftime("%Y%m%d%H%M%S", time.localtime())
+
+ if not os.path.exists(Colored.LOG_DIR):
+ os.mkdir(Colored.LOG_DIR)
+
+ project_log_dir = Colored.get_fuzz_project_log_dir()
+ if not os.path.exists(project_log_dir):
+ os.mkdir(project_log_dir)
+
+ current_project_log_dir = Colored.get_fuzz_current_project_log_dir()
+ if not os.path.exists(current_project_log_dir):
+ os.mkdir(current_project_log_dir)
diff --git a/libs/fuzzlib/tools/run_result.py b/libs/fuzzlib/tools/run_result.py
new file mode 100644
index 0000000000000000000000000000000000000000..5fb2b6edc683e9f0a27568eccde9384378da423f
--- /dev/null
+++ b/libs/fuzzlib/tools/run_result.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python
+# -*- coding:utf-8 -*-
+#
+# Copyright (c) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import re
+
+
+class RunResult():
+ SUCCESS = 0
+
+ RUN_ENV_ERROR = -1
+ RUN_NO_DEVICE_ERROR = -2
+ RUN_CONFIG_FORMAT_ERROR = -3
+ RUN_CONFIG_FORMAT_NOCOLON_ERROR = -4
+ RUN_FUZZER_BIN_NOT_FOUND_ERROR = -5
+ RUN_CONNECT_ERROR = -6
+ RUN_EXEC_ERROR = -7
+ RUN_CONFIG_DICT_ERROR = -8
+ RUN_LINK_ERROR = -9
+
+
+ def __init__(self, code, data):
+ self.code = code
+ self.data = data
+ self.payload = {}
+
+ self.crash_info = {
+ "run_times": 0,
+ "log": "",
+ "project": "",
+ "speed": 0,
+ "summary": "No vulnerable",
+ "command_log": "",
+ "vulnerable": False,
+ "backtrace": "",
+ "cov": 0,
+ "libscov": {},
+ "report_progress": 0
+ }
+
+
+ def get_log(self):
+ return "code :{}, msg: {}".format(self.code, self.data)
+
+ @staticmethod
+ def filter_log(log_str):
+ ansi_escape = re.compile(r'''
+ \x1B
+ (?:
+ [@-Z\\-_]
+ |
+ \[
+ [0-?]*
+ [ -/]*
+ [@-~]
+ )
+ ''', re.VERBOSE)
+ result = ansi_escape.sub('', log_str)
+ return result
+
+ def analysis(self, result, outdir):
+ pass
+
+ def write_analysis_result(self, analysis_ressult_path, html_format=True):
+ with open(analysis_ressult_path, "wb") as f:
+ if html_format:
+ f.write(RunResult.filter_log(render_detail(self.crash_info)))
+ else:
+ f.write(RunResult.filter_log(self.crash_info["backtrace"]))
+
+
+if __name__ == "__main__":
+ cmd_log = ""
+ res_obj = RunResult(0, "OK")
+ res_obj.analysis(cmd_log, "../../../out/")
+ print(res_obj.crash_info)
+
diff --git a/libs/fuzzlib/tools/templates.py b/libs/fuzzlib/tools/templates.py
new file mode 100644
index 0000000000000000000000000000000000000000..936183a4574152b5ced90b28243d3c832cd916eb
--- /dev/null
+++ b/libs/fuzzlib/tools/templates.py
@@ -0,0 +1,240 @@
+#!/usr/bin/env python
+# -*- coding:utf-8 -*-
+#
+# Copyright (c) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import os
+import time
+
+GN_ENTRY_TEMPLATE = """\
+
+group("hydra_fuzz"){
+ testonly = true
+ if (use_libfuzzer) {
+ deps = ["//test/fuzzing_test/projects"]
+ }else{
+ deps = []
+ }
+}
+"""
+
+
+PROJECT_GN_TEMPLATE = """\
+# Copyright (c) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#####################hydra-fuzz###################
+import("//build/config/features.gni")
+import("//build/test.gni")
+
+##############################fuzztest##########################################
+ohos_fuzztest("") {
+ module_out_path = module_output_path
+
+ include_dirs = [
+ ]
+ cflags = ["-g","-O0","-Wno-unused-variable","-fno-omit-frame-pointer"]
+ sources = [
+ "%(project_name)s.cpp",
+ ]
+}
+###############################################################################
+group("fuzztest") {
+ testonly = true
+ deps = []
+ deps += [
+ # deps file
+ ":",
+ ]
+}
+###############################################################################
+"""
+
+
+PROJECT_DEMO_TEMPLATE = """\
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "%(project_name)s.h"
+
+#include
+#include
+
+const int FUZZ_DATA_LEN = 3
+const int FUZZ_FST_DATA = 0
+const int FUZZ_SND_DATA = 1
+const int FUZZ_TRD_DATA = 2
+const int FUZZ_FTH_DATA = 3
+
+namespace OHOS {
+ bool DoSomethingInterestingWithMyAPI(const uint8_t* data, size_t size)
+ {
+ bool result = false;
+ if (size >= FUZZ_DATA_LEN) {
+ result = data[FUZZ_FST_DATA] == 'F' &&
+ data[FUZZ_SND_DATA] == 'U' &&
+ data[FUZZ_TRD_DATA] == 'Z' &&
+ data[FUZZ_FTH_DATA] == 'Z';
+ }
+ return result;
+ }
+}
+
+/* Fuzzer entry point */
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
+{
+ /* Run your code on data */
+ OHOS::DoSomethingInterestingWithMyAPI(data, size);
+ return 0;
+}
+
+"""
+
+PROJECT_HEADER_TEMPLATE = """\
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define FUZZ_PROJECT_NAME "%(project_name)s"
+
+"""
+
+
+PROJECT_XML_TEMPLATE = """\
+
+
+
+
+
+ 1000
+
+ 300
+
+ 4096
+
+
+"""
+
+
+REPORT_CSS_TEMPLATE = """
+"""
+
+
+def render_tbody(data):
+ res = ""
+ for row in data:
+ row_line = ""
+ for row_td in row:
+ row_line = row_line \
+ + "\n{}\n".format(row_td)
+ row_line = "%s %s " % (row_line, " |
")
+ res = res + row_line
+ return res
+
+
+def render_common(data):
+ return REPORT_COMMON_HTML_TEMPLATE % data
+
+
+def get_format_bt(backtrace):
+ new_backtrack = ""
+ line_tag = ["#0", "#1", "#2", "#3", "#4", "#5", "#6", "#7"]
+ block_file_list = [
+ "sanitizer_common_interceptors.inc",
+ "FuzzerDriver.cpp",
+ "FuzzerLoop.cpp",
+ "FuzzerMain.cpp",
+ "??"
+ ]
+
+ tmp_flag = False
+ for line in backtrace.split("\n"):
+ tag_check = False
+ for tag in line_tag:
+ if line.strip().startswith(tag) == True \
+ and "in" in line and "exec/s" not in line:
+ tag_check = True
+ break
+
+ if tag_check:
+ block_flag = False
+ for block_line in block_file_list:
+ if block_line in line:
+ block_flag = True
+ break
+ if block_flag:
+ new_backtrack = " %s %s \n" % (new_backtrack, line)
+ else:
+
+ end_line = ' %s \n' % line
+ new_backtrack = " %s %s " % (new_backtrack, end_line)
+ else:
+ new_backtrack = " %s %s \n" % (new_backtrack, line)
+ return new_backtrack
\ No newline at end of file
diff --git a/libs/fuzzlib/tools/utils.py b/libs/fuzzlib/tools/utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..83250c834f7073e3e7c5c9dcc28753da2ade78a4
--- /dev/null
+++ b/libs/fuzzlib/tools/utils.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+# -*- coding:utf-8 -*-
+#
+# Copyright (c) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+import os
+import signal
+import sys
+import string
+from templates import REPORT_SUMMARY_HTML_TEMPLATE
+
diff --git a/src/core/build/build_manager.py b/src/core/build/build_manager.py
index e299bfbc3fe84520495fa3cac7488d3f586f6117..29ed8108c64a3984efb4d6db85aa16fc36622c68 100755
--- a/src/core/build/build_manager.py
+++ b/src/core/build/build_manager.py
@@ -22,6 +22,7 @@ from core.utils import scan_support_product
from core.config.config_manager import UserConfigManager
from core.build.select_targets import SelectTargets
from core.build.build_testcases import BuildTestcases
+from core.command.gen import Gen
LOG = platform_logger("BuildManager")
@@ -58,6 +59,16 @@ class BuildManager(object):
build_result = False
return build_result
+ @classmethod
+ def _compile_fuzz_test_case(cls, project_root_path, para):
+ build_result = BuildTestcases(
+ project_root_path).build_fuzz_testcases(para)
+ if build_result:
+ LOG.info("Test case compilation successed.")
+ else:
+ LOG.info("Test case compilation failed, please modify.")
+ return build_result
+
@classmethod
def _compile_all_test_cases(cls, project_root_path):
if BuildTestcases(project_root_path).build_all_testcases():
@@ -100,10 +111,15 @@ class BuildManager(object):
"BUILD.gn")
self._make_gn_file(build_cfg_filepath, target_list)
- build_result = self._compile_test_cases_by_target(
- project_root_path,
- para.productform,
- "make_temp_test")
+ if "fuzztest" in para.testtype:
+ Gen().gen_fuzzer_list_file(target_list)
+ build_result = self._compile_fuzz_test_case(
+ project_root_path, para)
+ else:
+ build_result = self._compile_test_cases_by_target(
+ project_root_path,
+ para.productform,
+ "make_temp_test")
self._make_gn_file(build_cfg_filepath, [])
return build_result
diff --git a/src/core/build/build_testcases.py b/src/core/build/build_testcases.py
index a8b00e53bff99ac611f785232a1786afa02b163c..97caf14c54ef346b56d743213eb876bc5175dbde 100755
--- a/src/core/build/build_testcases.py
+++ b/src/core/build/build_testcases.py
@@ -202,6 +202,18 @@ class BuildTestcases(object):
LOG.warning("Error: The %s is not exist" % BUILD_LITE)
return False
+ def build_fuzz_testcases(self, para):
+ self._delete_testcase_dir(para.productform)
+ helper_path = os.path.join("..", "libs", "fuzzlib", "fuzzer_helper.py")
+ command = [sys.executable, helper_path, 'make',
+ 'make_temp_test', para.productform]
+ if subprocess.call(command, shell=False) == 0:
+ build_result = True
+ else:
+ build_result = False
+ self._merge_testcase_dir(para.productform)
+ return build_result
+
def build_testcases(self, productform, target):
command = []
if self.is_build_example:
diff --git a/src/core/command/console.py b/src/core/command/console.py
index 3c6196d451a6f07531b1f5b2e788c164091c132d..8c88f88beaf58f584a188971866b9bb4fcfd57f7 100755
--- a/src/core/command/console.py
+++ b/src/core/command/console.py
@@ -25,6 +25,7 @@ from core.constants import ToolCommandType
from xdevice import platform_logger
from xdevice import EnvironmentManager
from core.command.run import Run
+from core.command.gen import Gen
from core.command.display import display_help_info
from core.command.display import display_show_info
from core.command.display import show_wizard_mode
@@ -192,6 +193,20 @@ class Console(object):
default="",
help="Specify test resource"
)
+ parser.add_argument("-dp", "--dirpath",
+ action="store",
+ type=str,
+ dest="dirpath",
+ default="",
+ help="Specify fuzz test dirpath"
+ )
+ parser.add_argument("-fn", "--fuzzername",
+ action="store",
+ type=str,
+ dest="fuzzername",
+ default="",
+ help="Specify fuzzer name"
+ )
(options, unparsed) = parser.parse_known_args(para_list)
# Set default value
@@ -229,6 +244,8 @@ class Console(object):
if "productform" in self.wizard_dic:
productform = self.wizard_dic["productform"]
self._process_command_show(para_list, productform)
+ elif command.startswith(ToolCommandType.TOOLCMD_KEY_GEN):
+ self._process_command_gen(command, options)
elif command.startswith(ToolCommandType.TOOLCMD_KEY_RUN):
if "productform" in self.wizard_dic:
options.productform = self.wizard_dic["productform"]
@@ -260,6 +277,14 @@ class Console(object):
LOG.error("Wrong show command.")
return
+ @classmethod
+ def _process_command_gen(cls, command, options):
+ if command == ToolCommandType.TOOLCMD_KEY_GEN:
+ Gen().process_command_gen(options)
+ else:
+ LOG.error("Wrong gen command.")
+ return
+
@classmethod
def _process_command_run(cls, command, options):
if command == ToolCommandType.TOOLCMD_KEY_RUN:
diff --git a/src/core/command/gen.py b/src/core/command/gen.py
new file mode 100644
index 0000000000000000000000000000000000000000..e3af63148f34f81fa0306eae055f1171afb2824a
--- /dev/null
+++ b/src/core/command/gen.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python3
+# coding=utf-8
+
+#
+# Copyright (c) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import os
+import sys
+import subprocess
+
+from xdevice import platform_logger
+
+LOG = platform_logger("Gen")
+
+class Gen(object):
+ def process_command_gen(self, options):
+ if (len(options.testtype) != 1) or (options.dirpath == "") or \
+ (options.fuzzername == ""):
+ LOG.error(
+ "GEN need para -t(testtype) -fz(fuzzername) -dp(dirpath)")
+ return
+ if "FUZZ" in options.testtype:
+ self.fuzz_dir_generation(options)
+ else:
+ LOG.error("GEN is not support %s." % options.testtype)
+
+ def gen_fuzzer_list_file(self, fuzzer_list):
+ filepath = os.path.join(sys.source_code_root_path, "test",
+ "developertest", "libs", "fuzzlib", "fuzzer_list.txt")
+ LOG.info("The fuzzer list file path: %s" % filepath)
+ with open(filepath, "w") as gn_file:
+ gn_file.truncate(0)
+ if fuzzer_list:
+ for target in fuzzer_list:
+ if target:
+ gn_file.write("\"%s\",\n" % target)
+
+ @classmethod
+ def fuzz_dir_generation(cls, options):
+ helper_path = os.path.join("..", "libs", "fuzzlib", "fuzzer_helper.py")
+ fuzz_path = os.path.join(sys.source_code_root_path, options.dirpath)
+ LOG.info("fuzz_path = %s" % fuzz_path)
+ if not os.path.exists(fuzz_path):
+ LOG.error("%s is not exist." % fuzz_path)
+ return
+
+ LOG.info("%s exist." % fuzz_path)
+ command = [sys.executable, helper_path, 'generate',
+ options.fuzzername, fuzz_path]
+ LOG.info("command %s" % command)
+ subprocess.call(command, shell=False)
\ No newline at end of file
diff --git a/src/core/config/config_manager.py b/src/core/config/config_manager.py
index 8217bf14566c840cdb0a8ca5a97a8e83e6cd9793..c8224e042d26a63b7753e93ee107bfe3545d743c 100755
--- a/src/core/config/config_manager.py
+++ b/src/core/config/config_manager.py
@@ -283,3 +283,27 @@ class BuildConfigManager(object):
def get_build_path(self):
return self.filepath
+
+class FuzzerConfigManager(object):
+ def __init__(self, config_path=""):
+ if config_path == "":
+ self.filepath = self.filepath = os.path.abspath(os.path.join(
+ CONFIG_PATH, ConfigFileConst.FUZZCONFIG_FILEPATH))
+ else:
+ self.filepath = config_path
+
+ def get_fuzzer_config(self, target_name):
+ config_list = []
+ try:
+ LOG.info("fuzzer config file :%s" % self.filepath)
+ if os.path.exists(self.filepath):
+ tree = ET.parse(self.filepath)
+ root = tree.getroot()
+ node = root.find(target_name)
+ LOG.info("before for")
+ for sub in node:
+ if sub.text is not None:
+ config_list.append(sub.text)
+ except ET.ParseError as xml_exception:
+ LOG.error(("Parse %s fail!" % self.filepath) + xml_exception.args)
+ return config_list
diff --git a/src/core/constants.py b/src/core/constants.py
index cd3129105027e8576bf228303d0c695601223530..29dc0c4d61af1d805f0eda4fa7091f53b5bc0c80 100755
--- a/src/core/constants.py
+++ b/src/core/constants.py
@@ -46,6 +46,7 @@ class ToolCommandType(object):
TOOLCMD_KEY_RUN = "run"
TOOLCMD_KEY_QUIT = "quit"
TOOLCMD_KEY_LIST = "list"
+ TOOLCMD_KEY_GEN = "gen"
@property
def run_command(self):
@@ -64,6 +65,7 @@ class ConfigFileConst(object):
RESOURCECONFIG_FILEPATH = "harmony_test.xml"
CASE_RESOURCE_FILEPATH = "ohos_test.xml"
SCENECONFIG_FILEPATH = "scene_config.xml"
+ FUZZCONFIG_FILEPATH = "fuzz_config.xml"
@property
def framework_config_file(self):
diff --git a/src/core/driver/drivers.py b/src/core/driver/drivers.py
index 2528b34e6adaab4aefd9d8c700f3ddae20c2a29a..51e1cf6e573fc351a9fea572d1b7f8c9ed953872 100755
--- a/src/core/driver/drivers.py
+++ b/src/core/driver/drivers.py
@@ -17,11 +17,11 @@
#
import os
+import re
import time
import platform
from dataclasses import dataclass
-
from xdevice import DeviceTestType
from xdevice import DeviceLabelType
from xdevice import ExecuteTerminate
@@ -31,7 +31,9 @@ from xdevice import IDriver
from xdevice import platform_logger
from xdevice import Plugin
from core.utils import get_decode
+from core.utils import get_fuzzer_path
from core.config.resource_manager import ResourceManager
+from core.config.config_manager import FuzzerConfigManager
__all__ = [
@@ -186,7 +188,68 @@ def _sleep_according_to_result(result):
if result:
time.sleep(1)
+def _create_fuzz_crash_file(filepath, filename):
+ if not os.path.exists(filepath):
+ with open(filepath, "w", encoding='utf-8') as file_desc:
+ time_stamp = time.strftime("%Y-%m-%d %H:%M:%S",
+ time.localtime())
+ file_desc.write('\n')
+ file_desc.write(
+ '\n' % time_stamp)
+ file_desc.write(
+ ' \n' % filename)
+ file_desc.write(
+ ' \n' % (filename, filename))
+ file_desc.write(
+ ' \n')
+ file_desc.write(' \n')
+ file_desc.write(' \n')
+ file_desc.write(' \n')
+ file_desc.write('\n')
+ return
+def _create_fuzz_pass_file(filepath, filename):
+ if not os.path.exists(filepath):
+ with open(filepath, "w", encoding='utf-8') as file_desc:
+ time_stamp = time.strftime("%Y-%m-%d %H:%M:%S",
+ time.localtime())
+ file_desc.write('\n')
+ file_desc.write(
+ '\n' % time_stamp)
+ file_desc.write(
+ ' \n' % filename)
+ file_desc.write(
+ ' \n' % (filename, filename))
+ file_desc.write(' \n')
+ file_desc.write('\n')
+ return
+
+def _create_fuzz_result_file(filepath, filename, error_message):
+ error_message = str(error_message)
+ error_message = error_message.replace("\"", "")
+ error_message = error_message.replace("<", "")
+ error_message = error_message.replace(">", "")
+ error_message = error_message.replace("&", "")
+ if "AddressSanitizer" in error_message:
+ LOG.error("FUZZ TEST CRASH")
+ _create_fuzz_crash_file(filepath, filename)
+ elif re.search(r'Done (\b\d+\b) runs in (\b\d+\b) second',
+ error_message, re.M) is not None:
+ LOG.info("FUZZ TEST PASS")
+ _create_fuzz_pass_file(filepath, filename)
+ else:
+ LOG.error("FUZZ TEST UNAVAILABLE")
+ _create_empty_result_file(filepath, filename, error_message)
+ return
##############################################################################
##############################################################################
@@ -209,6 +272,11 @@ class ResultManager(object):
def get_test_results(self, error_message=""):
# Get test result files
filepath = self.obtain_test_result_file()
+ if "fuzztest" == self.config.testtype[0]:
+ LOG.info("create fuzz test report")
+ _create_fuzz_result_file(filepath, self.testsuite_name,
+ error_message)
+ return filepath
if not os.path.exists(filepath):
_create_empty_result_file(filepath, self.testsuite_name,
error_message)
@@ -394,6 +462,10 @@ class CppTestDriver(IDriver):
"rm -rf %s" % self.config.target_test_path)
self.config.device.execute_shell_command(
"mkdir -p %s" % self.config.target_test_path)
+ if "fuzztest" == self.config.testtype[0]:
+ self.config.device.execute_shell_command(
+ "mkdir -p %s" % os.path.join(self.config.target_test_path,
+ "corpus"))
def _run_gtest(self, suite_file):
from xdevice import Variables
@@ -407,6 +479,7 @@ class CppTestDriver(IDriver):
# push testsuite file
self.config.device.push_file(suite_file, self.config.target_test_path)
+ self._push_corpus_if_exist(filename)
# push resource files
resource_manager = ResourceManager()
@@ -453,6 +526,12 @@ class CppTestDriver(IDriver):
resource_dir,
self.config.device)
+ def _push_corpus_if_exist(self, filename):
+ if "fuzztest" == self.config.testtype[0]:
+ corpus_path = os.path.join(get_fuzzer_path(filename), "corpus")
+ self.config.device.push_file(corpus_path,
+ os.path.join(self.config.target_test_path, "corpus"))
+
@staticmethod
def _get_test_para(testcase,
testlevel,
@@ -472,6 +551,14 @@ class CppTestDriver(IDriver):
test_para = "%s=%s" % (GTestConst.exec_para_level, level_para)
else:
test_para = ""
+
+ if "fuzztest" == testtype[0]:
+ cfg_list = FuzzerConfigManager(os.path.join(get_fuzzer_path(
+ filename), "project.xml")).get_fuzzer_config("fuzztest")
+ LOG.info("config list :%s" % str(cfg_list))
+ test_para += "corpus -max_len=" + cfg_list[0] + \
+ " -max_total_time=" + cfg_list[1] + \
+ " -rss_limit_mb=" + cfg_list[2]
return test_para
diff --git a/src/core/utils.py b/src/core/utils.py
index 4e2af8ef37e4979bd9b2cdbb0517b100fa904aff..752781b33cc4cffdac85511a7882785fdd96836c 100755
--- a/src/core/utils.py
+++ b/src/core/utils.py
@@ -152,3 +152,22 @@ def get_decode(stream):
except (ValueError, AttributeError, TypeError):
ret = str(stream)
return ret
+
+def parse_fuzzer_info():
+ path_list = []
+ bin_list = []
+ list_path = os.path.join(sys.source_code_root_path, "test",
+ "developertest", "libs", "fuzzlib", "fuzzer_list.txt")
+ with open(list_path, 'r') as list_file:
+ for line in list_file.readlines():
+ striped_str = line.strip()
+ path_list.append(striped_str.split(":")[0][3:])
+ bin_list.append(striped_str.split(":")[1].split("(")[0])
+ return path_list, bin_list
+
+def get_fuzzer_path(filename):
+ path_list, bin_list = parse_fuzzer_info()
+ for i, name in enumerate(bin_list):
+ if name == filename:
+ return os.path.join(sys.source_code_root_path, path_list[i])
+ return ""