From e16ed4bfbd733a0ac5276980d3bb1a522c02d19d Mon Sep 17 00:00:00 2001 From: disarray2077 <86157825+disarray2077@users.noreply.github.com> Date: Mon, 27 Jun 2022 20:00:40 -0300 Subject: [PATCH] Add BeefFuzz for Beef fuzzing --- BeefFuzz/BeefFuzz.cpp | 87 +++++++++ BeefFuzz/BeefFuzz.h | 180 ++++++++++++++++++ BeefFuzz/BeefFuzz.vcxproj | 182 ++++++++++++++++++ BeefFuzz/BeefFuzz.vcxproj.filters | 33 ++++ BeefFuzz/CMakeLists.txt | 169 +++++++++++++++++ BeefFuzz/FuzzApp.cpp | 300 ++++++++++++++++++++++++++++++ BeefFuzz/FuzzApp.h | 66 +++++++ 7 files changed, 1017 insertions(+) create mode 100644 BeefFuzz/BeefFuzz.cpp create mode 100644 BeefFuzz/BeefFuzz.h create mode 100644 BeefFuzz/BeefFuzz.vcxproj create mode 100644 BeefFuzz/BeefFuzz.vcxproj.filters create mode 100644 BeefFuzz/CMakeLists.txt create mode 100644 BeefFuzz/FuzzApp.cpp create mode 100644 BeefFuzz/FuzzApp.h diff --git a/BeefFuzz/BeefFuzz.cpp b/BeefFuzz/BeefFuzz.cpp new file mode 100644 index 00000000..df405bbf --- /dev/null +++ b/BeefFuzz/BeefFuzz.cpp @@ -0,0 +1,87 @@ +#pragma warning(disable:4996) + +#include +#include "BeefySysLib/Common.h" +#include "BeefySysLib/util/Array.h" +#include "BeefySysLib/util/SizedArray.h" +#include "BeefySysLib/util/Dictionary.h" +#include "BeefySysLib/util/CabUtil.h" +#include "BeefySysLib/util/BeefPerf.h" +#include "BeefySysLib/util/Deque.h" +#include "BeefySysLib/util/HashSet.h" +#include "BeefySysLib/util/MultiHashSet.h" + +#define BF_DBG_64 +#include "IDEHelper/StrHashMap.h" + +using namespace Beefy; + +#include "FuzzApp.h" + +BF_IMPORT void BF_CALLTYPE IDEHelper_ProgramStart(); +BF_IMPORT void BF_CALLTYPE IDEHelper_ProgramDone(); + +static void FuzzInit() +{ + BfpSystem_SetCommandLine(0, NULL); + + BfpThread_SetName(NULL, "MainThread", NULL); + + BfpSystem_Init(BFP_VERSION, BfpSystemInitFlag_None); + + IDEHelper_ProgramStart(); + + gApp = new FuzzApp(); + gApp->SetTargetPath("fuzz_testd"); + gApp->AddDefine("CLI"); + gApp->AddDefine("DEBUG"); + gApp->SetStartupObject("fuzz_test.Program"); + gApp->SetLinkParams("./libBeefRT_d.a ./libBeefySysLib_d.so -ldl -lpthread -Wl,-rpath -Wl,$ORIGIN"); + + BF_ASSERT(gApp->Init()); +} + +void trimwhitespace(const uint8_t*& str, size_t& len) +{ + while (len > 0 && isspace(*str)) + { + str++; + len--; + } + + const uint8_t* end = str + len - 1; + while (len > 0 && isspace(*end)) + { + end--; + len--; + } +} + +static bool init = false; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) +{ + if (!init) + { + init = true; + FuzzInit(); + } + + trimwhitespace(Data, Size); + if (Size == 0) + return 0; + + gApp->PrepareCompiler(); + + bool ready = gApp->QueueFile((char*)Data, Size); + + //if (ready) + // ready = gApp->QueuePath("./corlib/src"); + + //if (ready) + // gApp->Compile(); + + gApp->ReleaseCompiler(); + + return 0; +} \ No newline at end of file diff --git a/BeefFuzz/BeefFuzz.h b/BeefFuzz/BeefFuzz.h new file mode 100644 index 00000000..724d73cc --- /dev/null +++ b/BeefFuzz/BeefFuzz.h @@ -0,0 +1,180 @@ +#pragma once + +#include "BeefySysLib/Common.h" +#include "BeefySysLib/util/Array.h" +#include "BeefySysLib/util/String.h" +#include +//#include + +#pragma warning(disable:4996) + +NS_BF_BEGIN + +#define APPEND2(VAL1, VAL2) VAL1##VAL2 +#define APPEND(VAL1, VAL2) APPEND2(VAL1, VAL2) +#define ENUM_VAL_GENERATE(ENUM_ENTRY) APPEND(ENUM_TYPE, _##ENUM_ENTRY), +#define ENUM_NAME_GENERATE(ENUM_ENTRY) #ENUM_ENTRY, +#define ENUM_CREATE_DO2(EnumName) \ + static const char* EnumName##_Names[] = { ENUM_DECLARE(ENUM_NAME_GENERATE) }; \ + enum EnumName { ENUM_DECLARE(ENUM_VAL_GENERATE) }; \ + static bool EnumParse(const String& name, EnumName& result) \ + { \ + for (int i = 0; i < sizeof(EnumName##_Names)/sizeof(const char*); i++) \ + if (name == EnumName##_Names[i]) { result = (EnumName)i; return true; } \ + return false; \ + } \ + static const char* EnumToString(EnumName enumVal) \ + { \ + return EnumName##_Names[(int)enumVal]; \ + } +#define ENUM_CREATE_DO(EnumType) ENUM_CREATE_DO2(EnumType) +#define ENUM_CREATE ENUM_CREATE_DO(ENUM_TYPE) + +class IDEUtils +{ +public: + static bool FixFilePath(String& filePath) + { + if (filePath.length() == 0) + return false; + + if (filePath[0] == '<') + return false; + + if ((filePath.length() > 1) && (filePath[1] == ':')) + filePath[0] = tolower(filePath[0]); + + bool prevWasSlash = false; + for (int i = 0; i < filePath.length(); i++) + { + //if ((filePath[i] == '/') && (filePath[i - 1]) + + if (filePath[i] == DIR_SEP_CHAR_ALT) + filePath[i] = DIR_SEP_CHAR; + + if (filePath[i] == DIR_SEP_CHAR) + { + if ((prevWasSlash) && (i > 1)) + { + filePath.Remove(i, 1); + i--; + continue; + } + + prevWasSlash = true; + } + else + prevWasSlash = false; + + if ((i >= 4) && (filePath[i - 3] == DIR_SEP_CHAR) && (filePath[i - 2] == '.') && (filePath[i - 1] == '.') && (filePath[i] == DIR_SEP_CHAR)) + { + int prevSlash = (int)filePath.LastIndexOf(DIR_SEP_CHAR, i - 4); + if (prevSlash != -1) + { + filePath.Remove(prevSlash, i - prevSlash); + i = prevSlash; + } + } + } + return true; + } + + static void GetDirWithSlash(String& dirName) + { + if (dirName.length() == 0) + return; + char lastC = dirName[dirName.length() - 1]; + if ((lastC != '\\') && (lastC != '/')) + dirName += DIR_SEP_CHAR; + } + + static FILE* CreateFileWithDir(const String& fileName, const char* options) + { + FILE* fp = fopen(fileName.c_str(), options); + if (fp == NULL) + { + String fileDir = GetFileDir(fileName); + if (!fileDir.empty()) + { + RecursiveCreateDirectory(fileDir); + fp = fopen(fileName.c_str(), "w"); + } + } + return fp; + } + + static bool WriteAllText(const String& fileName, const String& data) + { + FILE* fp = CreateFileWithDir(fileName, "w"); + if (fp == NULL) + return false; + fwrite(data.c_str(), 1, data.length(), fp); + fclose(fp); + return true; + } + + static void GetFileNameWithoutExtension(const String& filePath, String& outFileName) + { + outFileName += GetFileName(filePath); + int dot = (int)outFileName.LastIndexOf('.'); + if (dot != -1) + outFileName.RemoveToEnd(dot); + } + + static void GetExtension(const String& filePath, String& ext) + { + int idx = (int)filePath.LastIndexOf('.'); + if (idx != -1) + ext = filePath.Substring(idx); + } + + static void AppendWithOptionalQuotes(String& targetStr, const String& srcFileName) + { + if ((int)srcFileName.IndexOf(' ') == -1) + targetStr += srcFileName; + else + targetStr += "\"" + srcFileName + "\""; + } +}; + +class ArgBuilder +{ +public: + String* mTarget; + bool mDoLongBreak; + int mLastBreak; + std::multiset mLinkPaths; + +public: + ArgBuilder(String& target, bool doLongBreak) + { + mTarget = ⌖ + mDoLongBreak = doLongBreak; + if (mDoLongBreak) + mLastBreak = (int)mTarget->LastIndexOf('\n'); + else + mLastBreak = 0; + } + + void AddSep() + { + if (mDoLongBreak) + { + if (mTarget->length() - mLastBreak > 0x1F000) + { + mLastBreak = (int)mTarget->length(); + mTarget->Append('\n'); + return; + } + } + mTarget->Append(' '); + } + + void AddFileName(const String& filePath) + { + IDEUtils::AppendWithOptionalQuotes(*mTarget, filePath); + } +}; + +NS_BF_END + diff --git a/BeefFuzz/BeefFuzz.vcxproj b/BeefFuzz/BeefFuzz.vcxproj new file mode 100644 index 00000000..adb08cb8 --- /dev/null +++ b/BeefFuzz/BeefFuzz.vcxproj @@ -0,0 +1,182 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {F5FD6845-BBAE-47B6-AE4E-2C1D30F6E145} + Win32Proj + BeefFuzz + 10.0.17763.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)\ide\dist\ + + + true + $(ProjectName)_d + $(SolutionDir)\ide\dist\ + + + false + $(SolutionDir)\ide\dist\ + + + false + $(SolutionDir)\ide\dist\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../;../IDEHelper;../BeefySysLib/platform/win;../BeefySysLib/third_party;..\extern\llvm-project_13_0_1\llvm\include;..\extern\llvm_win64_13_0_1\include;..\extern\llvm-project_13_0_1\llvm\lib\Target;..\extern\llvm_win64_13_0_1\lib\Target\X86;..\extern\llvm-project_13_0_1\llvm\tools\clang\include + true + false + MultiThreadedDebug + false + ProgramDatabase + + + Console + DebugFull + $(SolutionDir)\ide\dist\$(TargetName).exe + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + ../;../IDEHelper;../BeefySysLib/platform/win;../BeefySysLib/third_party;..\extern\llvm-project_13_0_1\llvm\include;..\extern\llvm_win64_13_0_1\include;..\extern\llvm-project_13_0_1\llvm\lib\Target;..\extern\llvm_win64_13_0_1\lib\Target\X86;..\extern\llvm\tools\clang\include + MultiThreaded + false + + + Console + true + true + DebugFull + $(SolutionDir)\ide\dist\$(TargetName).exe + Default + + + + + + + + + {eceab68d-2f15-495f-a29c-5ea9548aa23d} + + + {f8d29c38-d37c-4af2-8540-2f6e543264f1} + false + + + + + + + + + + \ No newline at end of file diff --git a/BeefFuzz/BeefFuzz.vcxproj.filters b/BeefFuzz/BeefFuzz.vcxproj.filters new file mode 100644 index 00000000..bd3cc797 --- /dev/null +++ b/BeefFuzz/BeefFuzz.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/BeefFuzz/CMakeLists.txt b/BeefFuzz/CMakeLists.txt new file mode 100644 index 00000000..518c2542 --- /dev/null +++ b/BeefFuzz/CMakeLists.txt @@ -0,0 +1,169 @@ +cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR) + +################### Variables. #################### +# Change if you want modify path or other values. # +################################################### + +set(PROJECT_NAME BeefFuzz) +# Output Variables +set(OUTPUT_DEBUG Debug/bin) +set(OUTPUT_RELEASE Release/bin) + +############## CMake Project ################ +# The main options of project # +############################################# + +project(${PROJECT_NAME} CXX C) + +set (CMAKE_CXX_STANDARD 14) +add_definitions(-D_GLIBCXX_USE_CXX11_ABI=1) + +#set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +# Define Release by default. +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Debug") + message(STATUS "Build type not specified: Use Debug by default.") +endif(NOT CMAKE_BUILD_TYPE) + +# Definition of Macros +add_definitions( + -DIDEHELPER_EXPORTS + -DBFSYSLIB_DYNAMIC + -DUNICODE + -D_UNICODE + -DBF_NO_FBX + -DFT2_BUILD_LIBRARY + -DBFSYSLIB_DYNAMIC +) + +if (${APPLE}) + include_directories( + . + ../ + ../BeefySysLib/ + ../BeefySysLib/third_party + ../BeefySysLib/third_party/freetype/include + ../extern/llvm-project_13_0_1/llvm/include + ../extern/llvm-project_13_0_1/llvm/lib/Target + ../IDEHelper + + ../BeefySysLib/platform/osx + ) +else() + include_directories( + . + ../ + ../BeefySysLib/ + ../BeefySysLib/third_party + ../BeefySysLib/third_party/freetype/include + ../extern/llvm-project_13_0_1/llvm/include + ../extern/llvm-project_13_0_1/llvm/lib/Target + ../IDEHelper + + ../BeefySysLib/platform/linux + ) +endif() + +############## Artefacts Output ################# +# Defines outputs , depending Debug or Release. # +################################################# + +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + add_definitions( + -D_DEBUG + ) + include_directories( + ../extern/llvm_linux_13_0_1/include + ../extern/llvm_linux_13_0_1/lib/Target/X86 + ) + set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}/${OUTPUT_DEBUG}") + set(LLVM_LIB "${CMAKE_CURRENT_SOURCE_DIR}/../extern/llvm_linux_13_0_1/lib") +else() + include_directories( + ../extern/llvm_linux_rel_13_0_1/include + ../extern/llvm_linux_rel_13_0_1/lib/Target/X86 + ) + set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}/${OUTPUT_RELEASE}") + set(LLVM_LIB "${CMAKE_CURRENT_SOURCE_DIR}/../extern/llvm_linux_rel_13_0_1/lib") +endif() + +################### Dependencies ################## +# Add Dependencies to project. # +################################################### + +option(BUILD_DEPENDS + "Build other CMake project." + ON +) + +# Dependencies : disable BUILD_DEPENDS to link with lib already build. +if(BUILD_DEPENDS) + +else() + +endif() + +################# Flags ################ +# Defines Flags for Windows and Linux. # +######################################## + +if(MSVC) + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /W3 /MD /MDd /Od /EHsc") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /W3 /GL /Od /Oi /Gy /EHsc") +else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -Wno-multichar -Wno-invalid-offsetof -fno-omit-frame-pointer -fsanitize=fuzzer") + if (BF_ENABLE_ASAN) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") + endif() +endif() + +################ Files ################ +# -- Add files to project. -- # +####################################### + +file(GLOB SRC_FILES + BeefFuzz.cpp + FuzzApp.cpp +) + +# Add executable to build. +add_executable(${PROJECT_NAME} + ${SRC_FILES} +) + +execute_process( + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/../extern/llvm_linux_13_0_1/bin/llvm-config --system-libs --link-static + OUTPUT_VARIABLE LLVM_SYSTEM_LIBS + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE EXEC_RESULT +) + +if (EXEC_RESULT AND NOT EXEC_RESULT EQUAL 0) + if (EXEC_RESULT MATCHES "^[0-9]+$") + message(FATAL_ERROR "llvm-config exited with code ${EXEC_RESULT}.") + else() + message(FATAL_ERROR "llvm-config couldn't be executed: ${EXEC_RESULT}") + endif() +endif() + +if (${APPLE}) + set(TARGET_LIBS_OS "") +else() + #set(TARGET_LIBS_OS "curses") + #set(TARGET_LIBS_OS "-Xlinker --no-demangle -v") + + set(TARGET_LIBS_OS "${LLVM_SYSTEM_LIBS}") +endif() + +# Link with other dependencies. +if(MSVC) + target_link_libraries(${PROJECT_NAME} BeefySysLib IDEHelper kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib) +else() + target_link_libraries(${PROJECT_NAME} BeefySysLib + IDEHelper + ${TARGET_LIBS_OS} + + #${LLVM_LIB}/libLLVMSupport.a + ) +endif() diff --git a/BeefFuzz/FuzzApp.cpp b/BeefFuzz/FuzzApp.cpp new file mode 100644 index 00000000..ff919a5d --- /dev/null +++ b/BeefFuzz/FuzzApp.cpp @@ -0,0 +1,300 @@ +#pragma warning(disable:4996) + +#include "FuzzApp.h" +#include +#include "BeefySysLib/util/String.h" +#include "BeefySysLib/util/FileEnumerator.h" +#include "BeefySysLib/util/WorkThread.h" +#include "BeefySysLib/platform/PlatformHelper.h" +#include "Compiler/BfSystem.h" + +#ifdef BF_PLATFORM_WINDOWS +#include +#endif + +BF_IMPORT void BF_CALLTYPE Targets_Create(); +BF_IMPORT void BF_CALLTYPE Targets_Delete(); + +BF_IMPORT void BF_CALLTYPE BfSystem_ReportMemory(void* bfSystem); +BF_EXPORT void BF_CALLTYPE BfCompiler_ProgramDone(); + +BF_IMPORT void BF_CALLTYPE Debugger_FullReportMemory(); + +////////////////////////////////////////////////////////////////////////// + +BF_IMPORT void BF_CALLTYPE BfCompiler_Delete(void* bfCompiler); +BF_EXPORT void BF_CALLTYPE BfCompiler_SetOptions(void* bfCompiler, void* hotProject, int hotIdx, + const char* targetTriple, const char* targetCPU, int toolsetType, int simdSetting, int allocStackCount, int maxWorkerThreads, + Beefy::BfCompilerOptionFlags optionFlags, const char* mallocLinkName, const char* freeLinkName); +BF_IMPORT void BF_CALLTYPE BfCompiler_ClearBuildCache(void* bfCompiler); +BF_IMPORT bool BF_CALLTYPE BfCompiler_Compile(void* bfCompiler, void* bfPassInstance, const char* outputPath); +BF_IMPORT float BF_CALLTYPE BfCompiler_GetCompletionPercentage(void* bfCompiler); +BF_IMPORT const char* BF_CALLTYPE BfCompiler_GetUsedOutputFileNames(void* bfCompiler, void* bfProject, bool flushQueuedHotFiles, bool* hadOutputChanges); + +BF_IMPORT void* BF_CALLTYPE BfSystem_CreateParser(void* bfSystem, void* bfProject); +BF_IMPORT void BF_CALLTYPE BfParser_SetSource(void* bfParser, const char* data, int length, const char* fileName); +BF_IMPORT void BF_CALLTYPE BfParser_SetCharIdData(void* bfParser, uint8* data, int length); +BF_IMPORT bool BF_CALLTYPE BfParser_Parse(void* bfParser, void* bfPassInstance, bool compatMode); +BF_IMPORT bool BF_CALLTYPE BfParser_Reduce(void* bfParser, void* bfPassInstance); +BF_IMPORT bool BF_CALLTYPE BfParser_BuildDefs(void* bfParser, void* bfPassInstance, void* resolvePassData, bool fullRefresh); + +////////////////////////////////////////////////////////////////////////// + +BF_IMPORT void* BF_CALLTYPE BfSystem_Create(); +BF_EXPORT void BF_CALLTYPE BfSystem_Lock(void* bfSystem, int priority); +BF_EXPORT void BF_CALLTYPE BfSystem_Unlock(void* bfSystem); +BF_IMPORT void BF_CALLTYPE BfSystem_ReportMemory(void* bfSystem); +BF_IMPORT void BF_CALLTYPE BfSystem_Delete(void* bfSystem); +BF_IMPORT void* BF_CALLTYPE BfSystem_CreatePassInstance(void* bfSystem); +BF_IMPORT void* BF_CALLTYPE BfSystem_CreateCompiler(void* bfSystem, bool isResolveOnly); +BF_IMPORT void* BF_CALLTYPE BfSystem_CreateProject(void* bfSystem, const char* projectName, const char* projectDir); +BF_IMPORT void BF_CALLTYPE BfParser_Delete(void* bfParser); +BF_IMPORT void BF_CALLTYPE BfSystem_AddTypeOptions(void* bfSystem, const char* filter, int32 simdSetting, int32 optimizationLevel, int32 emitDebugInfo, int32 arrayBoundsCheck, + int32 initLocalVariables, int32 emitDynamicCastCheck, int32 emitObjectAccessCheck, int32 allocStackTraceDepth); + +////////////////////////////////////////////////////////////////////////// + +BF_IMPORT void BF_CALLTYPE BfProject_SetDisabled(void* bfProject, bool disabled); +BF_IMPORT void BF_CALLTYPE BfProject_SetOptions(void* bfProject, int targetType, const char* startupObject, const char* preprocessorMacros, + int optLevel, int ltoType, int relocType, int picLevel, int32 flags); +BF_IMPORT void BF_CALLTYPE BfProject_ClearDependencies(void* bfProject); +BF_IMPORT void BF_CALLTYPE BfProject_AddDependency(void* bfProject, void* depProject); + +////////////////////////////////////////////////////////////////////////// + +BF_IMPORT const char* BF_CALLTYPE BfPassInstance_PopOutString(void* bfPassInstance); +BF_IMPORT void BF_CALLTYPE BfPassInstance_Delete(void* bfPassInstance); + +////////////////////////////////////////////////////////////////////////// + +BF_IMPORT const char* BF_CALLTYPE VSSupport_Find(); + +////////////////////////////////////////////////////////////////////////// + +USING_NS_BF; + +FuzzApp* Beefy::gApp = NULL; + + +FuzzApp::FuzzApp() +{ + Targets_Create(); + + mTargetType = BfTargetType_BeefConsoleApplication; + + mSystem = NULL; + mCompiler = NULL; + mProject = NULL; + mCELibProject = NULL; + mIsCERun = false; + mStartupObject = "Program"; + +#ifdef BF_PLATFORM_WINDOWS + mOptLevel = BfOptLevel_OgPlus; + mToolset = BfToolsetType_Microsoft; +#else + mOptLevel = BfOptLevel_O0; + mToolset = BfToolsetType_GNU; +#endif + +#ifdef BF_PLATFORM_WINDOWS + mTargetTriple = "x86_64-pc-windows-msvc"; +#elif defined BF_PLATFORM_MACOS + mTargetTriple = "x86_64-apple-macosx10.8.0"; +#else + mTargetTriple = "x86_64-unknown-linux-gnu"; +#endif +} + +FuzzApp::~FuzzApp() +{ + Targets_Delete(); +} + +bool FuzzApp::Init() +{ + char* cwdPtr = getcwd(NULL, 0); + mWorkingDir = cwdPtr; + free(cwdPtr); + + if (mTargetPath.IsEmpty()) + return false; + + return true; +} + +bool FuzzApp::QueueFile(const char* data, size_t len) +{ + bool worked = true; + void* bfParser = BfSystem_CreateParser(mSystem, (mCELibProject != NULL) ? mCELibProject : mProject); + BfParser_SetSource(bfParser, data, len, "Fuzz.bf"); + //bfParser.SetCharIdData(charIdData); + worked &= BfParser_Parse(bfParser, mPassInstance, false); + worked &= BfParser_Reduce(bfParser, mPassInstance); + worked &= BfParser_BuildDefs(bfParser, mPassInstance, NULL, false); + return worked; +} + +bool FuzzApp::QueuePath(const StringImpl& path) +{ + if (DirectoryExists(path)) + { + for (auto& fileEntry : FileEnumerator(path, FileEnumerator::Flags_Files)) + { + String filePath = fileEntry.GetFilePath(); + + String fileName; + fileName = GetFileName(filePath); + + String ext; + ext = GetFileExtension(filePath); + + if ((ext.Equals(".bf", StringImpl::CompareKind_OrdinalIgnoreCase)) || + (ext.Equals(".cs", StringImpl::CompareKind_OrdinalIgnoreCase))) + { + int len; + const char* data = LoadTextData(filePath, &len); + if (data != NULL) + { + bool success = QueueFile(data, len); + delete[] data; + + if (!success) + return false; + } + } + } + + for (auto& fileEntry : FileEnumerator(path, FileEnumerator::Flags_Directories)) + { + String childPath = fileEntry.GetFilePath(); + String dirName; + dirName = GetFileName(childPath); + + if (dirName == "build") + continue; + + if (!QueuePath(childPath)) + return false; + } + + return true; + } + + return false; +} + +bool FuzzApp::CopyFile(const StringImpl& srcPath, const StringImpl& destPath) +{ + BfpFileResult result = BfpFileResult_Ok; + for (int i = 0; i < 20; i++) + { + BfpFile_Copy(srcPath.c_str(), destPath.c_str(), BfpFileCopyKind_Always, &result); + if (result == BfpFileResult_Ok) + return true; + BfpThread_Sleep(100); + } + return false; +} + +void FuzzApp::PrepareCompiler() +{ + mSystem = BfSystem_Create(); + + mCompiler = BfSystem_CreateCompiler(mSystem, false); + + String projectName = GetFileName(mTargetPath); + int dotPos = (int)projectName.IndexOf('.'); + if (dotPos != -1) + projectName.RemoveToEnd(dotPos); + if (projectName.IsEmpty()) + projectName.Append("BeefProject"); + + mProject = BfSystem_CreateProject(mSystem, projectName.c_str(), GetFileDir(mTargetPath).c_str()); + + if (mIsCERun) + { + mCELibProject = BfSystem_CreateProject(mSystem, "BeefLib", GetFileDir(mTargetPath).c_str()); + BfProject_SetOptions(mCELibProject, BfTargetType_BeefLib, "", mDefines.c_str(), mOptLevel, 0, 0, 0, BfProjectFlags_None); + } + + String defines = mDefines; + if (!defines.IsEmpty()) + defines.Append("\n"); + defines.Append("BF_64_BIT"); + defines.Append("\nBF_LITTLE_ENDIAN"); + defines.Append("\n"); + defines.Append(BF_PLATFORM_NAME); + + int ltoType = 0; + BfProject_SetOptions(mProject, mTargetType, mStartupObject.c_str(), defines.c_str(), BfOptLevel_O0, ltoType, 0, 0, BfProjectFlags_None); + + if (mCELibProject != NULL) + BfProject_AddDependency(mProject, mCELibProject); + + mPassInstance = BfSystem_CreatePassInstance(mSystem); + + Beefy::String exePath; + BfpGetStrHelper(exePath, [](char* outStr, int* inOutStrSize, BfpResult* result) + { + BfpSystem_GetExecutablePath(outStr, inOutStrSize, (BfpSystemResult*)result); + }); + mBuildDir = GetFileDir(exePath) + "/build"; + + RecursiveCreateDirectory(mBuildDir + "/" + projectName); + if (mIsCERun) + RecursiveCreateDirectory(mBuildDir + "/BeefLib"); + + BfCompilerOptionFlags optionFlags = (BfCompilerOptionFlags)(BfCompilerOptionFlag_EmitDebugInfo | BfCompilerOptionFlag_EmitLineInfo | BfCompilerOptionFlag_GenerateOBJ | BfCompilerOptionFlag_OmitDebugHelpers); + + //int maxWorkerThreads = BfpSystem_GetNumLogicalCPUs(NULL); + //if (maxWorkerThreads <= 1) + // maxWorkerThreads = 6; + + BfCompiler_SetOptions(mCompiler, NULL, 0, mTargetTriple.c_str(), "", mToolset, BfSIMDSetting_SSE2, 1, 1, optionFlags, "malloc", "free"); +} + + +bool FuzzApp::Compile() +{ + BfCompiler_ClearBuildCache(mCompiler); + + if (!BfCompiler_Compile(mCompiler, mPassInstance, mBuildDir.c_str())) + return false; + + if (!mCEDest.IsEmpty()) + { + String ext; + String srcResult = mBuildDir + "/BeefProject/BeefProject"; + srcResult += BF_OBJ_EXT; + + if (!CopyFile(srcResult, mCEDest)) + return false; + } + + while (true) + { + const char* msg = BfPassInstance_PopOutString(mPassInstance); + if (msg == NULL) + break; + + if ((strncmp(msg, ":error ", 7) == 0) || + (strncmp(msg, "ERROR(", 6) == 0) || + (strncmp(msg, "ERROR:", 6) == 0)) + { + return false; + } + } + + return true; +} + +void FuzzApp::ReleaseCompiler() +{ + BfPassInstance_Delete(mPassInstance); + BfCompiler_Delete(mCompiler); + + BfSystem_Delete(mSystem); +} + + diff --git a/BeefFuzz/FuzzApp.h b/BeefFuzz/FuzzApp.h new file mode 100644 index 00000000..b491e256 --- /dev/null +++ b/BeefFuzz/FuzzApp.h @@ -0,0 +1,66 @@ +#pragma once + +#include "BeefFuzz.h" +#include "BeefySysLib/FileStream.h" +#include "BeefySysLib/util/CritSect.h" +#include "BeefySysLib/util/String.h" +#include "BeefySysLib/util/Array.h" +#include "Compiler/BfSystem.h" + +NS_BF_BEGIN + +class FuzzApp +{ +public: + BfTargetType mTargetType; + String mTargetTriple; + BfOptLevel mOptLevel; + BfToolsetType mToolset; + String mBuildDir; + String mWorkingDir; + String mDefines; + String mStartupObject; + String mTargetPath; + String mLinkParams; + + void* mSystem; + void* mCompiler; + void* mProject; + void* mPassInstance; + + bool mIsCERun; + void* mCELibProject; + String mCEDest; + +public: + bool CopyFile(const StringImpl& srcPath, const StringImpl& destPath); + + bool QueueFile(const char* data, size_t len); + bool QueuePath(const StringImpl& path); + +public: + FuzzApp(); + ~FuzzApp(); + + void SetTargetType(BfTargetType value) { mTargetType = value; } + void SetTargetTriple(const String& value) { mTargetTriple = value; } + void SetOptLevel(BfOptLevel value) { mOptLevel = value; } + void SetToolset(BfToolsetType value) { mToolset = value; } + void SetBuildDir(const String& value) { mBuildDir = value; } + void SetWorkingDir(const String& value) { mWorkingDir = value; } + void AddDefine(const String& value) { mDefines += mDefines.IsEmpty() ? value : "\n" + value; } + void SetStartupObject(const String& value) { mStartupObject = value; } + void SetTargetPath(const String& value) { mTargetPath = value; } + void SetLinkParams(const String& value) { mLinkParams = value; } + void SetCEDest(const String& value) { mCEDest = value; } + + bool Init(); + + void PrepareCompiler(); + bool Compile(); + void ReleaseCompiler(); +}; + +extern FuzzApp* gApp; + +NS_BF_END