Commit d7eec28b authored by Jonathan Metzman's avatar Jonathan Metzman Committed by Commit Bot

[unrar] Add fuzzer

Bug: 960422
Change-Id: Id239f4a5dbe49882864c405fb092b615f8b7cf5c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1602875
Commit-Queue: Jonathan Metzman <metzman@chromium.org>
Auto-Submit: Jonathan Metzman <metzman@chromium.org>
Reviewed-by: default avatarMax Moroz <mmoroz@chromium.org>
Reviewed-by: default avatarVarun Khaneja <vakh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#658349}
parent c09494ad
...@@ -17,6 +17,7 @@ import("//testing/test.gni") ...@@ -17,6 +17,7 @@ import("//testing/test.gni")
# - additional_configs - additional configs to be used for compilation # - additional_configs - additional configs to be used for compilation
# - dict - a dictionary file for the fuzzer. # - dict - a dictionary file for the fuzzer.
# - environment_variables - certain whitelisted environment variables for the # - environment_variables - certain whitelisted environment variables for the
# - configs_to_remove - (EXPERIMENTAL, don't use) configs to remove.
# fuzzer (AFL_DRIVER_DONT_DEFER is the only one allowed currently). # fuzzer (AFL_DRIVER_DONT_DEFER is the only one allowed currently).
# - libfuzzer_options - options for the fuzzer (e.g. -max_len=N or -timeout=N). # - libfuzzer_options - options for the fuzzer (e.g. -max_len=N or -timeout=N).
# - asan_options - AddressSanitizer options (e.g. allow_user_segv_handler=1). # - asan_options - AddressSanitizer options (e.g. allow_user_segv_handler=1).
...@@ -195,6 +196,9 @@ template("fuzzer_test") { ...@@ -195,6 +196,9 @@ template("fuzzer_test") {
]) ])
deps = test_deps deps = test_deps
if (defined(invoker.configs_to_remove)) {
configs -= invoker.configs_to_remove
}
if (defined(invoker.additional_configs)) { if (defined(invoker.additional_configs)) {
configs += invoker.additional_configs configs += invoker.additional_configs
} }
......
...@@ -3,8 +3,9 @@ ...@@ -3,8 +3,9 @@
# found in the LICENSE file. # found in the LICENSE file.
import("//build/config/features.gni") import("//build/config/features.gni")
import("//testing/libfuzzer/fuzzer_test.gni")
if (safe_browsing_mode == 1) { if (safe_browsing_mode == 1 || use_fuzzing_engine) {
static_library("unrar") { static_library("unrar") {
sources = [ sources = [
"src/archive.cpp", "src/archive.cpp",
...@@ -78,15 +79,33 @@ if (safe_browsing_mode == 1) { ...@@ -78,15 +79,33 @@ if (safe_browsing_mode == 1) {
# The following is set to disable certain macro definitions in the unrar # The following is set to disable certain macro definitions in the unrar
# source code. # source code.
"CHROMIUM_UNRAR", "CHROMIUM_UNRAR",
]
if (!use_libfuzzer) {
# Disables exceptions in unrar, replaces them with process termination. # Disables exceptions in unrar, replaces them with process termination.
"UNRAR_NO_EXCEPTIONS", defines += [ "UNRAR_NO_EXCEPTIONS" ]
] } else {
configs -= [ "//build/config/compiler:no_exceptions" ]
}
deps = [ deps = [
"//base", "//base",
] ]
} }
if (use_fuzzing_engine && !is_asan && !is_msan) {
fuzzer_test("unrar_fuzzer") {
sources = [
"unrar_fuzzer.cc",
]
deps = [
":unrar",
]
include_dirs = [ "//third_party/unrar/src" ]
defines = [ "CHROMIUM_UNRAR" ]
configs_to_remove = [ "//build/config/compiler:no_exceptions" ]
}
}
} }
config("unrar_warnings") { config("unrar_warnings") {
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <ftw.h>
#include <stddef.h>
#include <stdint.h>
#include <unistd.h>
#include <fstream>
#include <memory>
#include <string>
#include "rar.hpp"
using third_party_unrar::CmdExtract;
using third_party_unrar::CommandData;
static int removeFile(const char* fpath,
const struct stat* sb,
int typeflag,
struct FTW* ftwbuf) {
if (remove(fpath) != 0)
abort();
return 0;
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
// unrar likes to create files in the current directory.
// So, the following few lines created and 'cd' to a directory named 'o'
// in the current working directory.
constexpr size_t kMaxCwdLength = 10000;
static char cwd[kMaxCwdLength];
if (!getcwd(cwd, sizeof(cwd)))
abort();
std::string original_path = std::string(cwd, strlen(cwd));
std::string out_path = original_path + "/o";
if (!(opendir(out_path.c_str()) || mkdir(out_path.c_str(), 0700) == 0))
abort();
if (chdir(out_path.c_str()) != 0)
abort();
static const std::string filename = "temp.rar";
std::ofstream file(filename,
std::ios::binary | std::ios::out | std::ios::trunc);
if (!file.is_open())
abort();
file.write(reinterpret_cast<const char*>(data), size);
file.close();
std::unique_ptr<CommandData> cmd_data(new CommandData);
cmd_data->ParseArg(const_cast<wchar_t*>(L"-p"));
cmd_data->ParseArg(const_cast<wchar_t*>(L"x"));
cmd_data->ParseDone();
std::wstring wide_filename(filename.begin(), filename.end());
cmd_data->AddArcName(wide_filename.c_str());
try {
CmdExtract extractor(cmd_data.get());
extractor.DoExtract();
} catch (...) {
}
// 'cd' back to the original directory and delete 'o' along with
// all its contents.
if (chdir(original_path.c_str()) != 0)
abort();
if (nftw(out_path.c_str(), removeFile, 20,
FTW_DEPTH | FTW_MOUNT | FTW_PHYS) != 0)
abort();
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment