diff options
author | fanquake <fanquake@gmail.com> | 2023-07-26 15:47:41 +0100 |
---|---|---|
committer | fanquake <fanquake@gmail.com> | 2023-07-26 16:03:39 +0100 |
commit | f57e724a809feb139c5ae71c4db65635427e4802 (patch) | |
tree | 66590b095bd3eaa684891b0f8a5ef91cf43a36de | |
parent | f033a981ed72ceab8133ccddc6d99cd0d4b2d707 (diff) | |
parent | fa9108f85afdc926fd6a8b96cc2acff7ca25d7a8 (diff) |
Merge bitcoin/bitcoin#28127: refactor: Remove C-style const-violating cast, Use reinterpret_cast
fa9108f85afdc926fd6a8b96cc2acff7ca25d7a8 refactor: Use reinterpret_cast where appropriate (MarcoFalke)
3333f950d49f13662842650ae76599a0dff052eb refactor: Avoid casting away constness (MarcoFalke)
fa6394dd10ae71755e46fd523dd43c2a1f2b832d refactor: Remove unused C-style casts (MarcoFalke)
Pull request description:
Using a C-style cast to convert pointer types to a byte-like pointer type has many issues:
* It may accidentally and silently throw away `const`.
* It forces reviewers to check that it doesn't accidentally throw away `const`.
For example, on current master a `const char*` is cast to `unsigned char*` (without `const`), see https://github.com/bitcoin/bitcoin/blob/d23fda05842ba4539b225bbab01b94df0060f697/src/span.h#L273 . This can lead to UB, and the only reason why it didn't lead to UB is because the return type added back the `const`. (Obviously this would break if the return type was deduced via `auto`)
Fix all issues by adding back the `const` and using `reinterpret_cast` where appropriate.
ACKs for top commit:
darosior:
re-utACK fa9108f85afdc926fd6a8b96cc2acff7ca25d7a8
hebasto:
re-ACK fa9108f85afdc926fd6a8b96cc2acff7ca25d7a8.
john-moffett:
ACK fa9108f85afdc926fd6a8b96cc2acff7ca25d7a8
Tree-SHA512: 87f6e4b574f9bd96d4e0f2a0631fd0a9dc6096e5d4f1b95042fe9f197afc2fe9a24e333aeb34fed11feefcdb184a238fe1ea5aff10d580bb18d76bfe48b76a10
-rw-r--r-- | src/crypto/common.h | 22 | ||||
-rw-r--r-- | src/dbwrapper.h | 18 | ||||
-rw-r--r-- | src/span.h | 12 | ||||
-rw-r--r-- | src/test/argsman_tests.cpp | 54 | ||||
-rw-r--r-- | src/wallet/crypter.cpp | 2 |
5 files changed, 55 insertions, 53 deletions
diff --git a/src/crypto/common.h b/src/crypto/common.h index dc12ed9942..6ae5d4cd24 100644 --- a/src/crypto/common.h +++ b/src/crypto/common.h @@ -17,73 +17,73 @@ uint16_t static inline ReadLE16(const unsigned char* ptr) { uint16_t x; - memcpy((char*)&x, ptr, 2); + memcpy(&x, ptr, 2); return le16toh(x); } uint32_t static inline ReadLE32(const unsigned char* ptr) { uint32_t x; - memcpy((char*)&x, ptr, 4); + memcpy(&x, ptr, 4); return le32toh(x); } uint64_t static inline ReadLE64(const unsigned char* ptr) { uint64_t x; - memcpy((char*)&x, ptr, 8); + memcpy(&x, ptr, 8); return le64toh(x); } void static inline WriteLE16(unsigned char* ptr, uint16_t x) { uint16_t v = htole16(x); - memcpy(ptr, (char*)&v, 2); + memcpy(ptr, &v, 2); } void static inline WriteLE32(unsigned char* ptr, uint32_t x) { uint32_t v = htole32(x); - memcpy(ptr, (char*)&v, 4); + memcpy(ptr, &v, 4); } void static inline WriteLE64(unsigned char* ptr, uint64_t x) { uint64_t v = htole64(x); - memcpy(ptr, (char*)&v, 8); + memcpy(ptr, &v, 8); } uint16_t static inline ReadBE16(const unsigned char* ptr) { uint16_t x; - memcpy((char*)&x, ptr, 2); + memcpy(&x, ptr, 2); return be16toh(x); } uint32_t static inline ReadBE32(const unsigned char* ptr) { uint32_t x; - memcpy((char*)&x, ptr, 4); + memcpy(&x, ptr, 4); return be32toh(x); } uint64_t static inline ReadBE64(const unsigned char* ptr) { uint64_t x; - memcpy((char*)&x, ptr, 8); + memcpy(&x, ptr, 8); return be64toh(x); } void static inline WriteBE32(unsigned char* ptr, uint32_t x) { uint32_t v = htobe32(x); - memcpy(ptr, (char*)&v, 4); + memcpy(ptr, &v, 4); } void static inline WriteBE64(unsigned char* ptr, uint64_t x) { uint64_t v = htobe64(x); - memcpy(ptr, (char*)&v, 8); + memcpy(ptr, &v, 8); } /** Return the smallest number n such that (x >> n) == 0 (or 64 if the highest bit in x is set. */ diff --git a/src/dbwrapper.h b/src/dbwrapper.h index 35782edca6..4ae2106211 100644 --- a/src/dbwrapper.h +++ b/src/dbwrapper.h @@ -54,6 +54,8 @@ struct DBParams { DBOptions options{}; }; +inline auto CharCast(const std::byte* data) { return reinterpret_cast<const char*>(data); } + class dbwrapper_error : public std::runtime_error { public: @@ -113,12 +115,12 @@ public: { ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE); ssKey << key; - leveldb::Slice slKey((const char*)ssKey.data(), ssKey.size()); + leveldb::Slice slKey(CharCast(ssKey.data()), ssKey.size()); ssValue.reserve(DBWRAPPER_PREALLOC_VALUE_SIZE); ssValue << value; ssValue.Xor(dbwrapper_private::GetObfuscateKey(parent)); - leveldb::Slice slValue((const char*)ssValue.data(), ssValue.size()); + leveldb::Slice slValue(CharCast(ssValue.data()), ssValue.size()); batch.Put(slKey, slValue); // LevelDB serializes writes as: @@ -138,7 +140,7 @@ public: { ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE); ssKey << key; - leveldb::Slice slKey((const char*)ssKey.data(), ssKey.size()); + leveldb::Slice slKey(CharCast(ssKey.data()), ssKey.size()); batch.Delete(slKey); // LevelDB serializes erases as: @@ -177,7 +179,7 @@ public: DataStream ssKey{}; ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE); ssKey << key; - leveldb::Slice slKey((const char*)ssKey.data(), ssKey.size()); + leveldb::Slice slKey(CharCast(ssKey.data()), ssKey.size()); piter->Seek(slKey); } @@ -265,7 +267,7 @@ public: DataStream ssKey{}; ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE); ssKey << key; - leveldb::Slice slKey((const char*)ssKey.data(), ssKey.size()); + leveldb::Slice slKey(CharCast(ssKey.data()), ssKey.size()); std::string strValue; leveldb::Status status = pdb->Get(readoptions, slKey, &strValue); @@ -307,7 +309,7 @@ public: DataStream ssKey{}; ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE); ssKey << key; - leveldb::Slice slKey((const char*)ssKey.data(), ssKey.size()); + leveldb::Slice slKey(CharCast(ssKey.data()), ssKey.size()); std::string strValue; leveldb::Status status = pdb->Get(readoptions, slKey, &strValue); @@ -351,8 +353,8 @@ public: ssKey2.reserve(DBWRAPPER_PREALLOC_KEY_SIZE); ssKey1 << key_begin; ssKey2 << key_end; - leveldb::Slice slKey1((const char*)ssKey1.data(), ssKey1.size()); - leveldb::Slice slKey2((const char*)ssKey2.data(), ssKey2.size()); + leveldb::Slice slKey1(CharCast(ssKey1.data()), ssKey1.size()); + leveldb::Slice slKey2(CharCast(ssKey2.data()), ssKey2.size()); uint64_t size = 0; leveldb::Range range(slKey1, slKey2); pdb->GetApproximateSizes(&range, 1, &size); diff --git a/src/span.h b/src/span.h index 0563556dc2..7209d21a58 100644 --- a/src/span.h +++ b/src/span.h @@ -5,10 +5,10 @@ #ifndef BITCOIN_SPAN_H #define BITCOIN_SPAN_H -#include <type_traits> -#include <cstddef> #include <algorithm> -#include <assert.h> +#include <cassert> +#include <cstddef> +#include <type_traits> #ifdef DEBUG #define CONSTEXPR_IF_NOT_DEBUG @@ -267,10 +267,10 @@ Span<std::byte> MakeWritableByteSpan(V&& v) noexcept } // Helper functions to safely cast to unsigned char pointers. -inline unsigned char* UCharCast(char* c) { return (unsigned char*)c; } +inline unsigned char* UCharCast(char* c) { return reinterpret_cast<unsigned char*>(c); } inline unsigned char* UCharCast(unsigned char* c) { return c; } -inline unsigned char* UCharCast(std::byte* c) { return (unsigned char*)c; } -inline const unsigned char* UCharCast(const char* c) { return (unsigned char*)c; } +inline unsigned char* UCharCast(std::byte* c) { return reinterpret_cast<unsigned char*>(c); } +inline const unsigned char* UCharCast(const char* c) { return reinterpret_cast<const unsigned char*>(c); } inline const unsigned char* UCharCast(const unsigned char* c) { return c; } inline const unsigned char* UCharCast(const std::byte* c) { return reinterpret_cast<const unsigned char*>(c); } diff --git a/src/test/argsman_tests.cpp b/src/test/argsman_tests.cpp index 0b789e7f5c..1f46efe464 100644 --- a/src/test/argsman_tests.cpp +++ b/src/test/argsman_tests.cpp @@ -112,7 +112,7 @@ public: test.SetupArgs({{"-value", flags}}); const char* argv[] = {"ignored", arg}; std::string error; - bool success = test.ParseParameters(arg ? 2 : 1, (char**)argv, error); + bool success = test.ParseParameters(arg ? 2 : 1, argv, error); BOOST_CHECK_EQUAL(test.GetSetting("-value").write(), expect.setting.write()); auto settings_list = test.GetSettingsList("-value"); @@ -217,13 +217,13 @@ BOOST_AUTO_TEST_CASE(util_ParseParameters) std::string error; LOCK(testArgs.cs_args); testArgs.SetupArgs({a, b, ccc, d}); - BOOST_CHECK(testArgs.ParseParameters(0, (char**)argv_test, error)); + BOOST_CHECK(testArgs.ParseParameters(0, argv_test, error)); BOOST_CHECK(testArgs.m_settings.command_line_options.empty() && testArgs.m_settings.ro_config.empty()); - BOOST_CHECK(testArgs.ParseParameters(1, (char**)argv_test, error)); + BOOST_CHECK(testArgs.ParseParameters(1, argv_test, error)); BOOST_CHECK(testArgs.m_settings.command_line_options.empty() && testArgs.m_settings.ro_config.empty()); - BOOST_CHECK(testArgs.ParseParameters(7, (char**)argv_test, error)); + BOOST_CHECK(testArgs.ParseParameters(7, argv_test, error)); // expectation: -ignored is ignored (program name argument), // -a, -b and -ccc end up in map, -d ignored because it is after // a non-option argument (non-GNU option parsing) @@ -248,17 +248,17 @@ BOOST_AUTO_TEST_CASE(util_ParseInvalidParameters) const char* argv[] = {"ignored", "-registered"}; std::string error; - BOOST_CHECK(test.ParseParameters(2, (char**)argv, error)); + BOOST_CHECK(test.ParseParameters(2, argv, error)); BOOST_CHECK_EQUAL(error, ""); argv[1] = "-unregistered"; - BOOST_CHECK(!test.ParseParameters(2, (char**)argv, error)); + BOOST_CHECK(!test.ParseParameters(2, argv, error)); BOOST_CHECK_EQUAL(error, "Invalid parameter -unregistered"); // Make sure registered parameters prefixed with a chain type trigger errors. // (Previously, they were accepted and ignored.) argv[1] = "-test.registered"; - BOOST_CHECK(!test.ParseParameters(2, (char**)argv, error)); + BOOST_CHECK(!test.ParseParameters(2, argv, error)); BOOST_CHECK_EQUAL(error, "Invalid parameter -test.registered"); } @@ -269,7 +269,7 @@ static void TestParse(const std::string& str, bool expected_bool, int64_t expect std::string arg = "-value=" + str; const char* argv[] = {"ignored", arg.c_str()}; std::string error; - BOOST_CHECK(test.ParseParameters(2, (char**)argv, error)); + BOOST_CHECK(test.ParseParameters(2, argv, error)); BOOST_CHECK_EQUAL(test.GetBoolArg("-value", false), expected_bool); BOOST_CHECK_EQUAL(test.GetBoolArg("-value", true), expected_bool); BOOST_CHECK_EQUAL(test.GetIntArg("-value", 99998), expected_int); @@ -331,7 +331,7 @@ BOOST_AUTO_TEST_CASE(util_GetBoolArg) std::string error; LOCK(testArgs.cs_args); testArgs.SetupArgs({a, b, c, d, e, f}); - BOOST_CHECK(testArgs.ParseParameters(7, (char**)argv_test, error)); + BOOST_CHECK(testArgs.ParseParameters(7, argv_test, error)); // Each letter should be set. for (const char opt : "abcdef") @@ -368,7 +368,7 @@ BOOST_AUTO_TEST_CASE(util_GetBoolArgEdgeCases) const char *argv_test[] = {"ignored", "-nofoo", "-foo", "-nobar=0"}; testArgs.SetupArgs({foo, bar}); std::string error; - BOOST_CHECK(testArgs.ParseParameters(4, (char**)argv_test, error)); + BOOST_CHECK(testArgs.ParseParameters(4, argv_test, error)); // This was passed twice, second one overrides the negative setting. BOOST_CHECK(!testArgs.IsArgNegated("-foo")); @@ -380,7 +380,7 @@ BOOST_AUTO_TEST_CASE(util_GetBoolArgEdgeCases) // Config test const char *conf_test = "nofoo=1\nfoo=1\nnobar=0\n"; - BOOST_CHECK(testArgs.ParseParameters(1, (char**)argv_test, error)); + BOOST_CHECK(testArgs.ParseParameters(1, argv_test, error)); testArgs.ReadConfigString(conf_test); // This was passed twice, second one overrides the negative setting, @@ -395,7 +395,7 @@ BOOST_AUTO_TEST_CASE(util_GetBoolArgEdgeCases) // Combined test const char *combo_test_args[] = {"ignored", "-nofoo", "-bar"}; const char *combo_test_conf = "foo=1\nnobar=1\n"; - BOOST_CHECK(testArgs.ParseParameters(3, (char**)combo_test_args, error)); + BOOST_CHECK(testArgs.ParseParameters(3, combo_test_args, error)); testArgs.ReadConfigString(combo_test_conf); // Command line overrides, but doesn't erase old setting @@ -655,38 +655,38 @@ BOOST_AUTO_TEST_CASE(util_GetChainTypeString) const char* testnetconf = "testnet=1\nregtest=0\n[test]\nregtest=1"; std::string error; - BOOST_CHECK(test_args.ParseParameters(0, (char**)argv_testnet, error)); + BOOST_CHECK(test_args.ParseParameters(0, argv_testnet, error)); BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "main"); - BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_testnet, error)); + BOOST_CHECK(test_args.ParseParameters(2, argv_testnet, error)); BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "test"); - BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_regtest, error)); + BOOST_CHECK(test_args.ParseParameters(2, argv_regtest, error)); BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "regtest"); - BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_test_no_reg, error)); + BOOST_CHECK(test_args.ParseParameters(3, argv_test_no_reg, error)); BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "test"); - BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_both, error)); + BOOST_CHECK(test_args.ParseParameters(3, argv_both, error)); BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error); - BOOST_CHECK(test_args.ParseParameters(0, (char**)argv_testnet, error)); + BOOST_CHECK(test_args.ParseParameters(0, argv_testnet, error)); test_args.ReadConfigString(testnetconf); BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "test"); - BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_testnet, error)); + BOOST_CHECK(test_args.ParseParameters(2, argv_testnet, error)); test_args.ReadConfigString(testnetconf); BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "test"); - BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_regtest, error)); + BOOST_CHECK(test_args.ParseParameters(2, argv_regtest, error)); test_args.ReadConfigString(testnetconf); BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error); - BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_test_no_reg, error)); + BOOST_CHECK(test_args.ParseParameters(3, argv_test_no_reg, error)); test_args.ReadConfigString(testnetconf); BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "test"); - BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_both, error)); + BOOST_CHECK(test_args.ParseParameters(3, argv_both, error)); test_args.ReadConfigString(testnetconf); BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error); @@ -694,23 +694,23 @@ BOOST_AUTO_TEST_CASE(util_GetChainTypeString) // [test] regtest=1 potentially relevant) doesn't break things test_args.SelectConfigNetwork("test"); - BOOST_CHECK(test_args.ParseParameters(0, (char**)argv_testnet, error)); + BOOST_CHECK(test_args.ParseParameters(0, argv_testnet, error)); test_args.ReadConfigString(testnetconf); BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "test"); - BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_testnet, error)); + BOOST_CHECK(test_args.ParseParameters(2, argv_testnet, error)); test_args.ReadConfigString(testnetconf); BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "test"); - BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_regtest, error)); + BOOST_CHECK(test_args.ParseParameters(2, argv_regtest, error)); test_args.ReadConfigString(testnetconf); BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error); - BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_test_no_reg, error)); + BOOST_CHECK(test_args.ParseParameters(2, argv_test_no_reg, error)); test_args.ReadConfigString(testnetconf); BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "test"); - BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_both, error)); + BOOST_CHECK(test_args.ParseParameters(3, argv_both, error)); test_args.ReadConfigString(testnetconf); BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error); } diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index e2799c2d05..57a19fb5f2 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -112,7 +112,7 @@ bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vch memcpy(chIV.data(), &nIV, WALLET_CRYPTO_IV_SIZE); if(!cKeyCrypter.SetKey(vMasterKey, chIV)) return false; - return cKeyCrypter.Encrypt(*((const CKeyingMaterial*)&vchPlaintext), vchCiphertext); + return cKeyCrypter.Encrypt(vchPlaintext, vchCiphertext); } bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext) |