diff --git a/compiler-rt/lib/fuzzer/FuzzerIO.h b/compiler-rt/lib/fuzzer/FuzzerIO.h --- a/compiler-rt/lib/fuzzer/FuzzerIO.h +++ b/compiler-rt/lib/fuzzer/FuzzerIO.h @@ -54,6 +54,10 @@ void CloseStdout(); +// For testing. +FILE *GetOutputFile(); +void SetOutputFile(FILE *NewOutputFile); + void Printf(const char *Fmt, ...); void VPrintf(bool Verbose, const char *Fmt, ...); diff --git a/compiler-rt/lib/fuzzer/FuzzerIO.cpp b/compiler-rt/lib/fuzzer/FuzzerIO.cpp --- a/compiler-rt/lib/fuzzer/FuzzerIO.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerIO.cpp @@ -23,6 +23,14 @@ static FILE *OutputFile = stderr; +FILE *GetOutputFile() { + return OutputFile; +} + +void SetOutputFile(FILE *NewOutputFile) { + OutputFile = NewOutputFile; +} + long GetEpoch(const std::string &Path) { struct stat St; if (stat(Path.c_str(), &St)) diff --git a/compiler-rt/lib/fuzzer/FuzzerUtil.cpp b/compiler-rt/lib/fuzzer/FuzzerUtil.cpp --- a/compiler-rt/lib/fuzzer/FuzzerUtil.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerUtil.cpp @@ -43,7 +43,7 @@ else if (Byte >= 32 && Byte < 127) Printf("%c", Byte); else - Printf("\\x%02x", Byte); + Printf("\\%03o", Byte); } void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter) { diff --git a/compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp b/compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp --- a/compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp +++ b/compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp @@ -591,6 +591,42 @@ EXPECT_EQ("YWJjeHl6", Base64({'a', 'b', 'c', 'x', 'y', 'z'})); } +#ifdef __GLIBC__ +class PrintfCapture { + public: + PrintfCapture() { + OldOutputFile = GetOutputFile(); + SetOutputFile(open_memstream(&Buffer, &Size)); + } + ~PrintfCapture() { + fclose(GetOutputFile()); + SetOutputFile(OldOutputFile); + free(Buffer); + } + std::string str() { return std::string(Buffer, Size); } + + private: + char *Buffer; + size_t Size; + FILE *OldOutputFile; +}; + +TEST(FuzzerUtil, PrintASCII) { + auto f = [](const char *Str, const char *PrintAfter = "") { + PrintfCapture Capture; + PrintASCII(reinterpret_cast(Str), strlen(Str), PrintAfter); + return Capture.str(); + }; + EXPECT_EQ("hello", f("hello")); + EXPECT_EQ("c:\\\\", f("c:\\")); + EXPECT_EQ("\\\"hi\\\"", f("\"hi\"")); + EXPECT_EQ("\\011a", f("\ta")); + EXPECT_EQ("\\0111", f("\t1")); + EXPECT_EQ("hello\\012", f("hello\n")); + EXPECT_EQ("hello\n", f("hello", "\n")); +} +#endif + TEST(Corpus, Distribution) { DataFlowTrace DFT; Random Rand(0);