diff --git a/fuzztest/fuzztest_macros.h b/fuzztest/fuzztest_macros.h index 6228e2fbc..172d0f695 100644 --- a/fuzztest/fuzztest_macros.h +++ b/fuzztest/fuzztest_macros.h @@ -15,6 +15,7 @@ #ifndef FUZZTEST_FUZZTEST_FUZZTEST_MACROS_H_ #define FUZZTEST_FUZZTEST_FUZZTEST_MACROS_H_ +#include #include #include #include @@ -126,6 +127,12 @@ inline std::vector> ReadFilesFromDirectory( return internal::ReadFilesFromDirectory({dir.data(), dir.size()}); } +// Converts string_view into a byte-array, useful when working with the LLVM +// fuzzer interfaces. +inline std::vector ToByteArray(std::string_view str) { + return std::vector(str.begin(), str.end()); +} + } // namespace fuzztest #endif // FUZZTEST_FUZZTEST_FUZZTEST_MACROS_H_ diff --git a/fuzztest/internal/domains/container_of_impl.h b/fuzztest/internal/domains/container_of_impl.h index db59c660f..2b22a1103 100644 --- a/fuzztest/internal/domains/container_of_impl.h +++ b/fuzztest/internal/domains/container_of_impl.h @@ -247,7 +247,8 @@ class ContainerOfImplBase } auto GetPrinter() const { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || + std::is_same_v>) { // std::string has special handling for better output return StringPrinter{}; } else { diff --git a/fuzztest/internal/type_support.h b/fuzztest/internal/type_support.h index fb0e8ed51..f09a1d79e 100644 --- a/fuzztest/internal/type_support.h +++ b/fuzztest/internal/type_support.h @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include "absl/debugging/symbolize.h" #include "absl/numeric/int128.h" @@ -172,9 +172,11 @@ struct StringPrinter { // Make sure to properly C-escape strings when printing source code, and // explicitly construct a std::string of the right length if there is an // embedded NULL character. - const absl::string_view input(v.data(), v.size()); + const std::string input(v.data(), v.data() + v.size()); const std::string escaped = absl::CEscape(input); - if (absl::StrContains(input, '\0')) { + if constexpr (std::is_convertible_v>) { + absl::Format(out, "fuzztest::ToByteArray(\"%s\")", escaped); + } else if (absl::StrContains(input, '\0')) { absl::Format(out, "std::string(\"%s\", %d)", escaped, v.size()); } else { absl::Format(out, "\"%s\"", escaped); @@ -584,7 +586,8 @@ decltype(auto) AutodetectTypePrinter() { } else if constexpr (std::is_floating_point_v) { return FloatingPrinter{}; } else if constexpr (std::is_convertible_v || - std::is_convertible_v) { + std::is_convertible_v || + std::is_convertible_v>) { return StringPrinter{}; } else if constexpr (is_monostate_v) { return MonostatePrinter{}; diff --git a/fuzztest/internal/type_support_test.cc b/fuzztest/internal/type_support_test.cc index fe2c3f0e2..13df5f901 100644 --- a/fuzztest/internal/type_support_test.cc +++ b/fuzztest/internal/type_support_test.cc @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -193,6 +194,12 @@ TEST(StringTest, Printer) { R"("printf(\"Hello, world!\");")")); } +TEST(ByteArrayTest, Printer) { + EXPECT_THAT(TestPrintValue(std::vector{'\0', 'a', 0223, 'b', '\"'}), + ElementsAre(R"("\000a\223b"")", + R"(fuzztest::ToByteArray("\000a\223b\""))")); +} + TEST(CompoundTest, Printer) { EXPECT_THAT( TestPrintValue(std::pair(1, 1.5), Arbitrary>()),