Skip to content

Conversation

@maflcko
Copy link
Member

@maflcko maflcko commented Aug 8, 2023

All fmt functions only accept a raw C-string as argument.

There should never be a need to pass a format string that is not a compile-time string literal, so disallow it in WalletLogPrintf() to avoid accidentally introducing it.

Apart from consistency, this also fixes the clang-tidy plugin bug #26296 (comment).

@DrahtBot
Copy link
Contributor

DrahtBot commented Aug 8, 2023

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Reviews

See the guideline for information on the review process.

Type Reviewers
ACK theuni

If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #27277 (Move log messages: tx enqueue to mempool, allocation to blockstorage by Sjors)

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@DrahtBot DrahtBot changed the title refactor: Enforce C-str fmt strings in WalletLogPrintf() refactor: Enforce C-str fmt strings in WalletLogPrintf() Aug 8, 2023
@maflcko maflcko force-pushed the 2308-wallet-c-str- branch from faf82ca to faa8ff0 Compare August 8, 2023 07:26
@maflcko maflcko force-pushed the 2308-wallet-c-str- branch from faa8ff0 to faf0575 Compare August 8, 2023 07:32
@maflcko maflcko force-pushed the 2308-wallet-c-str- branch from faf0575 to fa6dc57 Compare August 8, 2023 08:55
@DrahtBot DrahtBot removed the CI failed label Aug 8, 2023
{
LOCK(cs_wallet);
WalletLogPrintf("CommitTransaction:\n%s", tx->ToString());
WalletLogPrintf("CommitTransaction:\n%s", tx->ToString()); // NOLINT(bitcoin-unterminated-logprintf)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, this one wasn't being caught before?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, see #26296 (comment)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm.

I haven't tried this using the c-i scripts, but running clang-tidy manually against current master, this works fine for me as-is:

$ /opt/clang+llvm-16.0.0-x86_64-linux-gnu-ubuntu-18.04/bin/clang-tidy-16 --load=/home/cory/dev/bitcoin2/contrib/devtools/bitcoin-tidy/build2/libbitcoin-tidy.so -checks="-*,bitcoin-*" wallet/wallet.cpp -- -DHAVE_BUILD_INFO -I. -I./minisketch/include -I./secp256k1/include -I./univalue/include -I./leveldb/include -isystem /home/cory/dev/bitcoin2/depends/x86_64-pc-linux-gnu/include -DBOOST_MULTI_INDEX_DISABLE_SERIALIZATION -DBOOST_NO_CXX98_FUNCTION_BASE -DHAVE_CONFIG_H  -std=c++17
1 warning generated.
/home/cory/dev/bitcoin2/src/wallet/wallet.cpp:2322:21: error: Unterminated format string used with LogPrintf [bitcoin-unterminated-logprintf,-warnings-as-errors]
    WalletLogPrintf("CommitTransaction:\n%s", tx->ToString());
                    ^
                                           \n
1 warning treated as error

Any idea what the difference is?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@theuni You'll have to share exact steps to reproduce, ideally starting from a fresh install of you operating system. Otherwise it will be close to impossible to reproduce. Locally and on CI this isn't caught (otherwise CI would be red). c.f

$ (cd src/ &&  clang-tidy --load=/home/fake/bitcoin/contrib/devtools/bitcoin-tidy/build/libbitcoin-tidy.so -checks="-*,bitcoin-*" wallet/wallet.cpp ) 
12 warnings generated.
Suppressed 12 warnings (12 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh. For whatever reason, my clang-tidy-16 acts as if IgnoreUnlessSpelledInSource is set. That's weird.

It came from here: https://github.com/llvm/llvm-project/releases/download/llvmorg-16.0.0/clang+llvm-16.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz

I can't reproduce with clang-tidy-15. clang-query-16 only matches if traversal is set to IgnoreUnlessSpelledInSource.

$ /opt/clang+llvm-15.0.2-x86_64-unknown-linux-gnu/bin/clang-query wallet/wallet.cpp -- -DHAVE_BUILD_INFO -I. -I./minisketch/include -I./secp256k1/include -I./univalue/include -I./leveldb/include -isystem /home/cory/dev/bitcoin2/depends/x86_64-pc-linux-gnu/include -DBOOST_MULTI_INDEX_DISABLE_SERIALIZATION -DBOOST_NO_CXX98_FUNCTION_BASE -DHAVE_CONFIG_H -std=c++17 -O2
clang-query> m cxxMemberCallExpr(thisPointerType(qualType(hasDeclaration(cxxRecordDecl(hasName("CWallet"))))),callee(cxxMethodDecl(hasName("WalletLogPrintf"))),hasArgument(0, stringLiteral().bind("logstring")))
0 matches.
clang-query> set traversal IgnoreUnlessSpelledInSource
clang-query> m cxxMemberCallExpr(thisPointerType(qualType(hasDeclaration(cxxRecordDecl(hasName("CWallet"))))),callee(cxxMethodDecl(hasName("WalletLogPrintf"))),hasArgument(0, stringLiteral().bind("logstring")))

...

Match #33:

/home/cory/dev/bitcoin2/src/wallet/wallet.cpp:4149:36: note: "logstring" binds here
wallet.WalletLogPrintf("Making a new watchonly wallet containing the unwatched solvable scripts\n");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/cory/dev/bitcoin2/src/wallet/wallet.cpp:4149:13: note: "root" binds here
wallet.WalletLogPrintf("Making a new watchonly wallet containing the unwatched solvable scripts\n");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
33 matches

I don't think this is worth spending any more time on, but I still don't understand why it's different.

Copy link
Member

@theuni theuni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense to me. I almost did the same thing while poking at WalletLogPrintf for the sake of easier static analysis.

Am I missing some obvious reason though, other than "might as well"?

void WalletLogPrintf(std::string fmt, Params... parameters) const {
LogPrintf(("%s " + fmt).c_str(), GetDisplayName(), parameters...);
template <typename... Params>
void WalletLogPrintf(const char* fmt, Params... parameters) const
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going to suggest the nonnull attribute here, but I believe our tidy check actually enforces that :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hope that the tests (and reviewers) will catch a LogPrint(nullptr, 1, 2, 3). But adding nonnull can be done in a follow-up, if needed, for all log-functions.

@maflcko
Copy link
Member Author

maflcko commented Aug 8, 2023

Am I missing some obvious reason though, other than "might as well"?

Edited OP to list both reasons.

MarcoFalke added 2 commits August 16, 2023 14:48
This makes it easier to add new ones without having to modify this file
every time.
@theuni
Copy link
Member

theuni commented Aug 16, 2023

ACK fa60fa3

@fanquake fanquake merged commit 7bf078f into bitcoin:master Aug 18, 2023
@maflcko maflcko deleted the 2308-wallet-c-str- branch August 18, 2023 10:42
Frank-GER pushed a commit to syscoin/syscoin that referenced this pull request Sep 8, 2023
@bitcoin bitcoin locked and limited conversation to collaborators Aug 17, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants