diff --git a/src/debug_utils-inl.h b/src/debug_utils-inl.h index 03b49490622d49..d5303bf41e50fe 100644 --- a/src/debug_utils-inl.h +++ b/src/debug_utils-inl.h @@ -32,14 +32,18 @@ std::string ToString(const T& value) { } inline std::string SPrintFImpl(const char* format) { - return format; + const char* p = strchr(format, '%'); + if (LIKELY(p == nullptr)) return format; + CHECK(p[1] == '%'); // Only '%%' allowed when there are no arguments. + + return std::string(format, p + 1) + SPrintFImpl(p + 2); } template std::string COLD_NOINLINE SPrintFImpl( // NOLINT(runtime/string) const char* format, Arg&& arg, Args&&... args) { const char* p = strchr(format, '%'); - if (p == nullptr) return format; + CHECK_NOT_NULL(p); std::string ret(format, p); // Ignore long / size_t modifiers while (strchr("lz", *++p) != nullptr) {} diff --git a/test/cctest/test_util.cc b/test/cctest/test_util.cc index de9c5368bddfda..e3a4a700e96583 100644 --- a/test/cctest/test_util.cc +++ b/test/cctest/test_util.cc @@ -282,6 +282,8 @@ TEST(UtilTest, SPrintF) { EXPECT_EQ(SPrintF("%s %s", foo, "bar"), "foo bar"); EXPECT_EQ(SPrintF("%s %s", foo, bar), "foo bar"); + EXPECT_EQ(SPrintF("[%% %s %%]", foo), "[% foo %]"); + struct HasToString { std::string ToString() const { return "meow";