diff --git a/llvm/lib/Fuzzer/FuzzerIO.cpp b/llvm/lib/Fuzzer/FuzzerIO.cpp index abc444a3d471..043fad396d51 100644 --- a/llvm/lib/Fuzzer/FuzzerIO.cpp +++ b/llvm/lib/Fuzzer/FuzzerIO.cpp @@ -91,11 +91,6 @@ std::string DirPlusFile(const std::string &DirPath, return DirPath + "/" + FileName; } -void PrintFileAsBase64(const std::string &Path) { - std::string Cmd = "base64 -w 0 < " + Path + "; echo"; - ExecuteCommand(Cmd); -} - void Printf(const char *Fmt, ...) { va_list ap; va_start(ap, Fmt); diff --git a/llvm/lib/Fuzzer/FuzzerInternal.h b/llvm/lib/Fuzzer/FuzzerInternal.h index 2c382b2ef314..bc6bec7473d3 100644 --- a/llvm/lib/Fuzzer/FuzzerInternal.h +++ b/llvm/lib/Fuzzer/FuzzerInternal.h @@ -42,7 +42,7 @@ void Print(const Unit &U, const char *PrintAfter = ""); void PrintASCII(const Unit &U, const char *PrintAfter = ""); std::string Hash(const Unit &U); void SetTimer(int Seconds); -void PrintFileAsBase64(const std::string &Path); +std::string Base64(const Unit &U); int ExecuteCommand(const std::string &Command); // Private copy of SHA1 implementation. diff --git a/llvm/lib/Fuzzer/FuzzerLoop.cpp b/llvm/lib/Fuzzer/FuzzerLoop.cpp index 9c52a4dbe774..ca7f82b55607 100644 --- a/llvm/lib/Fuzzer/FuzzerLoop.cpp +++ b/llvm/lib/Fuzzer/FuzzerLoop.cpp @@ -302,10 +302,8 @@ void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) { WriteToFile(U, Path); Printf("artifact_prefix='%s'; Test unit written to %s\n", Options.ArtifactPrefix.c_str(), Path.c_str()); - if (U.size() <= kMaxUnitSizeToPrint) { - Printf("Base64: "); - PrintFileAsBase64(Path); - } + if (U.size() <= kMaxUnitSizeToPrint) + Printf("Base64: %s\n", Base64(U).c_str()); } void Fuzzer::SaveCorpus() { diff --git a/llvm/lib/Fuzzer/FuzzerUtil.cpp b/llvm/lib/Fuzzer/FuzzerUtil.cpp index 20a41e0d4fbb..6c1133fffd37 100644 --- a/llvm/lib/Fuzzer/FuzzerUtil.cpp +++ b/llvm/lib/Fuzzer/FuzzerUtil.cpp @@ -167,4 +167,33 @@ bool ParseDictionaryFile(const std::string &Text, std::vector *Units) { int GetPid() { return getpid(); } + +std::string Base64(const Unit &U) { + static const char Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + std::string Res; + size_t i; + for (i = 0; i + 2 < U.size(); i += 3) { + uint32_t x = (U[i] << 16) + (U[i + 1] << 8) + U[i + 2]; + Res += Table[(x >> 18) & 63]; + Res += Table[(x >> 12) & 63]; + Res += Table[(x >> 6) & 63]; + Res += Table[x & 63]; + } + if (i + 1 == U.size()) { + uint32_t x = (U[i] << 16); + Res += Table[(x >> 18) & 63]; + Res += Table[(x >> 12) & 63]; + Res += "=="; + } else if (i + 2 == U.size()) { + uint32_t x = (U[i] << 16) + (U[i + 1] << 8); + Res += Table[(x >> 18) & 63]; + Res += Table[(x >> 12) & 63]; + Res += Table[(x >> 6) & 63]; + Res += "="; + } + return Res; +} + } // namespace fuzzer diff --git a/llvm/lib/Fuzzer/test/FuzzerUnittest.cpp b/llvm/lib/Fuzzer/test/FuzzerUnittest.cpp index 4a96468f8d7a..b92e61877c6c 100644 --- a/llvm/lib/Fuzzer/test/FuzzerUnittest.cpp +++ b/llvm/lib/Fuzzer/test/FuzzerUnittest.cpp @@ -360,3 +360,16 @@ TEST(FuzzerDictionary, ParseDictionaryFile) { EXPECT_EQ(Units, std::vector({Unit({'a', 'a'}), Unit({'a', 'b', 'c'})})); } + +TEST(FuzzerUtil, Base64) { + EXPECT_EQ("", Base64({})); + EXPECT_EQ("YQ==", Base64({'a'})); + EXPECT_EQ("eA==", Base64({'x'})); + EXPECT_EQ("YWI=", Base64({'a', 'b'})); + EXPECT_EQ("eHk=", Base64({'x', 'y'})); + EXPECT_EQ("YWJj", Base64({'a', 'b', 'c'})); + EXPECT_EQ("eHl6", Base64({'x', 'y', 'z'})); + EXPECT_EQ("YWJjeA==", Base64({'a', 'b', 'c', 'x'})); + EXPECT_EQ("YWJjeHk=", Base64({'a', 'b', 'c', 'x', 'y'})); + EXPECT_EQ("YWJjeHl6", Base64({'a', 'b', 'c', 'x', 'y', 'z'})); +}