Skip to content

Commit

Permalink
tinyformat: force compile-time checks for format string literals
Browse files Browse the repository at this point in the history
Callsites such as bitcoin-cli that (incorrectly) fail compile-time
validation can still use tfm::format_raw.
  • Loading branch information
stickies-v committed Oct 28, 2024
1 parent b6a39c8 commit b448d60
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 28 deletions.
24 changes: 12 additions & 12 deletions src/bitcoin-cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -540,15 +540,15 @@ class NetinfoRequestHandler : public BaseRequestHandler
// Report detailed peer connections list sorted by direction and minimum ping time.
if (DetailsRequested() && !m_peers.empty()) {
std::sort(m_peers.begin(), m_peers.end());
result += strprintf("<-> type net v mping ping send recv txn blk hb %*s%*s%*s ",
m_max_addr_processed_length, "addrp",
m_max_addr_rate_limited_length, "addrl",
m_max_age_length, "age");
result += tfm::format_raw("<-> type net v mping ping send recv txn blk hb %*s%*s%*s ",
m_max_addr_processed_length, "addrp",
m_max_addr_rate_limited_length, "addrl",
m_max_age_length, "age");
if (m_is_asmap_on) result += " asmap ";
result += strprintf("%*s %-*s%s\n", m_max_id_length, "id", IsAddressSelected() ? m_max_addr_length : 0, IsAddressSelected() ? "address" : "", IsVersionSelected() ? "version" : "");
result += tfm::format_raw("%*s %-*s%s\n", m_max_id_length, "id", IsAddressSelected() ? m_max_addr_length : 0, IsAddressSelected() ? "address" : "", IsVersionSelected() ? "version" : "");
for (const Peer& peer : m_peers) {
std::string version{ToString(peer.version) + peer.sub_version};
result += strprintf(
result += tfm::format_raw(
"%3s %6s %5s %2s%7s%7s%5s%5s%5s%5s %2s %*s%*s%*s%*i %*s %-*s%s\n",
peer.is_outbound ? "out" : "in",
ConnectionTypeForNetinfo(peer.conn_type),
Expand All @@ -575,7 +575,7 @@ class NetinfoRequestHandler : public BaseRequestHandler
IsAddressSelected() ? peer.addr : "",
IsVersionSelected() && version != "0" ? version : "");
}
result += strprintf(" ms ms sec sec min min %*s\n\n", m_max_age_length, "min");
result += tfm::format_raw(" ms ms sec sec min min %*s\n\n", m_max_age_length, "min");
}

// Report peer connection totals by type.
Expand Down Expand Up @@ -624,7 +624,7 @@ class NetinfoRequestHandler : public BaseRequestHandler
max_addr_size = std::max(addr["address"].get_str().length() + 1, max_addr_size);
}
for (const UniValue& addr : local_addrs) {
result += strprintf("\n%-*s port %6i score %6i", max_addr_size, addr["address"].get_str(), addr["port"].getInt<int>(), addr["score"].getInt<int>());
result += tfm::format_raw("\n%-*s port %6i score %6i", max_addr_size, addr["address"].get_str(), addr["port"].getInt<int>(), addr["score"].getInt<int>());
}
}

Expand Down Expand Up @@ -1117,10 +1117,10 @@ static void ParseGetInfoResult(UniValue& result)
}

for (const std::string& wallet : result["balances"].getKeys()) {
result_string += strprintf("%*s %s\n",
max_balance_length,
result["balances"][wallet].getValStr(),
wallet.empty() ? "\"\"" : wallet);
result_string += tfm::format_raw("%*s %s\n",
max_balance_length,
result["balances"][wallet].getValStr(),
wallet.empty() ? "\"\"" : wallet);
}
result_string += "\n";
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/fuzz/strprintf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
template <typename... Args>
void fuzz_fmt(const std::string& fmt, const Args&... args)
{
(void)tfm::format(fmt.c_str(), args...);
(void)tfm::format_raw(fmt.c_str(), args...);
}

FUZZ_TARGET(str_printf)
Expand Down
2 changes: 1 addition & 1 deletion src/test/fuzz/util/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ struct FuzzedWallet {

for (const std::string& desc_fmt : DESCS) {
for (bool internal : {true, false}) {
const auto descriptor{strprintf(desc_fmt.c_str(), "[5aa9973a/66h/4h/2h]" + seed_insecure, int{internal})};
const auto descriptor{tfm::format_raw(desc_fmt.c_str(), "[5aa9973a/66h/4h/2h]" + seed_insecure, int{internal})};

FlatSigningProvider keys;
std::string error;
Expand Down
29 changes: 17 additions & 12 deletions src/tinyformat.h
Original file line number Diff line number Diff line change
Expand Up @@ -1056,33 +1056,33 @@ inline void vformat(std::ostream& out, const char* fmt, FormatListRef list)
#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES

/// Format list of arguments to the stream according to given format string.
template<typename... Args>
void format(std::ostream& out, const char* fmt, const Args&... args)
template <typename... Args>
void format_raw(std::ostream& out, const char* fmt, const Args&... args) // Renamed for Bitcoin Core
{
vformat(out, fmt, makeFormatList(args...));
}

/// Format list of arguments according to the given format string and return
/// the result as a string.
template<typename... Args>
std::string format(const char* fmt, const Args&... args)
template <typename... Args>
std::string format_raw(const char* fmt, const Args&... args) // Renamed for Bitcoin Core
{
std::ostringstream oss;
format(oss, fmt, args...);
format_raw(oss, fmt, args...);
return oss.str();
}

/// Format list of arguments to std::cout, according to the given format string
template<typename... Args>
void printf(const char* fmt, const Args&... args)
template <typename... Args>
void printf_raw(const char* fmt, const Args&... args) // Renamed for Bitcoin Core
{
format(std::cout, fmt, args...);
format_raw(std::cout, fmt, args...);
}

template<typename... Args>
void printfln(const char* fmt, const Args&... args)
template <typename... Args>
void printfln_raw(const char* fmt, const Args&... args) // Renamed for Bitcoin Core
{
format(std::cout, fmt, args...);
format_raw(std::cout, fmt, args...);
std::cout << '\n';
}

Expand Down Expand Up @@ -1150,7 +1150,12 @@ TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_FORMAT_FUNCS)
template <typename... Args>
std::string format(util::ConstevalFormatString<sizeof...(Args)> fmt, const Args&... args)
{
return format(fmt.fmt, args...);
return format_raw(fmt.fmt, args...);
}
template <typename... Args>
void format(std::ostream& out, util::ConstevalFormatString<sizeof...(Args)> fmt, const Args&... args)
{
return format_raw(out, fmt.fmt, args...);
}
} // namespace tinyformat

Expand Down
4 changes: 2 additions & 2 deletions src/util/translation.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ bilingual_str format(const bilingual_str& fmt, const Args&... args)
return arg;
}
}};
return bilingual_str{tfm::format(fmt.original.c_str(), translate_arg(args, false)...),
tfm::format(fmt.translated.c_str(), translate_arg(args, true)...)};
return bilingual_str{tfm::format_raw(fmt.original.c_str(), translate_arg(args, false)...),
tfm::format_raw(fmt.translated.c_str(), translate_arg(args, true)...)};
}
} // namespace tinyformat

Expand Down

0 comments on commit b448d60

Please sign in to comment.