Skip to content

[Reflection] Add an utility to stress test the metadata reader. #23464

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions tools/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ endif()

if(LLVM_USE_SANITIZE_COVERAGE)
add_swift_tool_subdirectory(swift-demangle-fuzzer)
add_swift_tool_subdirectory(swift-reflection-fuzzer)
endif()

if(SWIFT_BUILD_STDLIB AND SWIFT_BUILD_SDK_OVERLAY)
Expand Down
8 changes: 8 additions & 0 deletions tools/swift-reflection-fuzzer/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
add_swift_fuzzer_host_tool(swift-reflection-fuzzer
swift-reflection-fuzzer.cpp
LLVM_COMPONENT_DEPENDS support
SWIFT_COMPONENT tools
)
target_link_libraries(swift-reflection-fuzzer
PRIVATE
swiftReflection)
97 changes: 97 additions & 0 deletions tools/swift-reflection-fuzzer/swift-reflection-fuzzer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//===--- swift-reflection-fuzzer.cpp - Swift reflection fuzzer ------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This program tries to fuzz the metadata reader shipped as part of the swift
// runtime and used by the debugger.
// For this to work you need to pass --enable-sanitizer-coverage to build-script
// otherwise the fuzzer doesn't have coverage information to make progress
// (making the whole fuzzing operation really ineffective).
// It is recommended to use the tool together with another sanitizer to expose
// more bugs (asan, lsan, etc...)
//
//===----------------------------------------------------------------------===//

#include "swift/Reflection/ReflectionContext.h"
#include "swift/Reflection/TypeRef.h"
#include "swift/Reflection/TypeRefBuilder.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ELF.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/MachOUniversal.h"
#include "llvm/Support/CommandLine.h"
#include <stddef.h>
#include <stdint.h>

using namespace llvm::object;

using namespace swift;
using namespace swift::reflection;
using namespace swift::remote;

using NativeReflectionContext = swift::reflection::ReflectionContext<
External<RuntimeTarget<sizeof(uintptr_t)>>>;

template <typename T> static T unwrap(llvm::Expected<T> value) {
if (value)
return std::move(value.get());
return T();
}

class ObjectMemoryReader : public MemoryReader {
public:
ObjectMemoryReader() {}

bool queryDataLayout(DataLayoutQueryType type, void *inBuffer,
void *outBuffer) override {
switch (type) {
case DLQ_GetPointerSize: {
auto result = static_cast<uint8_t *>(outBuffer);
*result = sizeof(void *);
return true;
}
case DLQ_GetSizeSize: {
auto result = static_cast<uint8_t *>(outBuffer);
*result = sizeof(size_t);
return true;
}
}

return false;
}

RemoteAddress getSymbolAddress(const std::string &name) override {
return RemoteAddress(nullptr);
}

bool isAddressValid(RemoteAddress addr, uint64_t size) const { return true; }

ReadBytesResult readBytes(RemoteAddress address, uint64_t size) override {
return ReadBytesResult((const void *)address.getAddressData(),
[](const void *) {});
}

bool readString(RemoteAddress address, std::string &dest) override {
if (!isAddressValid(address, 1))
return false;
auto cString = StringRef((const char *)address.getAddressData());
dest.append(cString.begin(), cString.end());
return true;
}
};

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
auto reader = std::make_shared<ObjectMemoryReader>();
NativeReflectionContext context(std::move(reader));
context.addImage(RemoteAddress(Data));
context.getBuilder().dumpAllSections(std::cout);
return 0; // Non-zero return values are reserved for future use.
}