aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am14
-rw-r--r--src/bitcoin-tx.cpp19
-rw-r--r--src/core_read.cpp53
-rw-r--r--src/interfaces/chain.h2
-rw-r--r--src/node/interfaces.cpp2
-rw-r--r--src/rest.cpp12
-rw-r--r--src/test/script_parse_tests.cpp2
-rw-r--r--src/test/validation_chainstate_tests.cpp23
-rw-r--r--src/util/strencodings.h4
-rw-r--r--src/util/syscall_sandbox.cpp9
10 files changed, 71 insertions, 69 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 12fdc9ad75..9d15120b72 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -808,20 +808,8 @@ clean-local:
$(AM_V_GEN) $(WINDRES) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CPPFLAGS) -DWINDRES_PREPROC -i $< -o $@
check-symbols: $(bin_PROGRAMS)
-if TARGET_DARWIN
- @echo "Checking macOS dynamic libraries..."
+ @echo "Running symbol and dynamic library checks..."
$(AM_V_at) $(PYTHON) $(top_srcdir)/contrib/devtools/symbol-check.py $(bin_PROGRAMS)
-endif
-
-if TARGET_WINDOWS
- @echo "Checking Windows dynamic libraries..."
- $(AM_V_at) $(PYTHON) $(top_srcdir)/contrib/devtools/symbol-check.py $(bin_PROGRAMS)
-endif
-
-if TARGET_LINUX
- @echo "Checking glibc back compat..."
- $(AM_V_at) CPPFILT='$(CPPFILT)' $(PYTHON) $(top_srcdir)/contrib/devtools/symbol-check.py $(bin_PROGRAMS)
-endif
check-security: $(bin_PROGRAMS)
if HARDEN
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index fc3bc6aa71..eb97cfc6f6 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -235,6 +235,16 @@ static void MutateTxRBFOptIn(CMutableTransaction& tx, const std::string& strInId
}
}
+template <typename T>
+static T TrimAndParse(const std::string& int_str, const std::string& err)
+{
+ const auto parsed{ToIntegral<T>(TrimString(int_str))};
+ if (!parsed.has_value()) {
+ throw std::runtime_error(err + " '" + int_str + "'");
+ }
+ return parsed.value();
+}
+
static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInput)
{
std::vector<std::string> vStrInputParts;
@@ -261,8 +271,9 @@ static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInpu
// extract the optional sequence number
uint32_t nSequenceIn = CTxIn::SEQUENCE_FINAL;
- if (vStrInputParts.size() > 2)
- nSequenceIn = std::stoul(vStrInputParts[2]);
+ if (vStrInputParts.size() > 2) {
+ nSequenceIn = TrimAndParse<uint32_t>(vStrInputParts.at(2), "invalid TX sequence id");
+ }
// append to transaction input list
CTxIn txin(txid, vout, CScript(), nSequenceIn);
@@ -352,10 +363,10 @@ static void MutateTxAddOutMultiSig(CMutableTransaction& tx, const std::string& s
CAmount value = ExtractAndValidateValue(vStrInputParts[0]);
// Extract REQUIRED
- uint32_t required = stoul(vStrInputParts[1]);
+ const uint32_t required{TrimAndParse<uint32_t>(vStrInputParts.at(1), "invalid multisig required number")};
// Extract NUMKEYS
- uint32_t numkeys = stoul(vStrInputParts[2]);
+ const uint32_t numkeys{TrimAndParse<uint32_t>(vStrInputParts.at(2), "invalid multisig total number")};
// Validate there are the correct number of pubkeys
if (vStrInputParts.size() < numkeys + 3)
diff --git a/src/core_read.cpp b/src/core_read.cpp
index 320811b9e9..2149b428d2 100644
--- a/src/core_read.cpp
+++ b/src/core_read.cpp
@@ -26,20 +26,20 @@ opcodetype ParseOpCode(const std::string& s)
{
static std::map<std::string, opcodetype> mapOpNames;
- if (mapOpNames.empty())
- {
- for (unsigned int op = 0; op <= MAX_OPCODE; op++)
- {
+ if (mapOpNames.empty()) {
+ for (unsigned int op = 0; op <= MAX_OPCODE; op++) {
// Allow OP_RESERVED to get into mapOpNames
- if (op < OP_NOP && op != OP_RESERVED)
+ if (op < OP_NOP && op != OP_RESERVED) {
continue;
+ }
std::string strName = GetOpName(static_cast<opcodetype>(op));
- if (strName == "OP_UNKNOWN")
+ if (strName == "OP_UNKNOWN") {
continue;
+ }
mapOpNames[strName] = static_cast<opcodetype>(op);
// Convenience: OP_ADD and just ADD are both recognized:
- if (strName.compare(0, 3, "OP_") == 0) { // strName starts with "OP_"
+ if (strName.compare(0, 3, "OP_") == 0) { // strName starts with "OP_"
mapOpNames[strName.substr(3)] = static_cast<opcodetype>(op);
}
}
@@ -59,44 +59,35 @@ CScript ParseScript(const std::string& s)
std::vector<std::string> words;
boost::algorithm::split(words, s, boost::algorithm::is_any_of(" \t\n"), boost::algorithm::token_compress_on);
- for (std::vector<std::string>::const_iterator w = words.begin(); w != words.end(); ++w)
- {
- if (w->empty())
- {
+ for (const std::string& w : words) {
+ if (w.empty()) {
// Empty string, ignore. (boost::split given '' will return one word)
- }
- else if (std::all_of(w->begin(), w->end(), ::IsDigit) ||
- (w->front() == '-' && w->size() > 1 && std::all_of(w->begin()+1, w->end(), ::IsDigit)))
+ } else if (std::all_of(w.begin(), w.end(), ::IsDigit) ||
+ (w.front() == '-' && w.size() > 1 && std::all_of(w.begin() + 1, w.end(), ::IsDigit)))
{
// Number
- int64_t n = LocaleIndependentAtoi<int64_t>(*w);
+ const auto num{ToIntegral<int64_t>(w)};
- //limit the range of numbers ParseScript accepts in decimal
- //since numbers outside -0xFFFFFFFF...0xFFFFFFFF are illegal in scripts
- if (n > int64_t{0xffffffff} || n < -1 * int64_t{0xffffffff}) {
+ // limit the range of numbers ParseScript accepts in decimal
+ // since numbers outside -0xFFFFFFFF...0xFFFFFFFF are illegal in scripts
+ if (!num.has_value() || num > int64_t{0xffffffff} || num < -1 * int64_t{0xffffffff}) {
throw std::runtime_error("script parse error: decimal numeric value only allowed in the "
"range -0xFFFFFFFF...0xFFFFFFFF");
}
- result << n;
- }
- else if (w->substr(0,2) == "0x" && w->size() > 2 && IsHex(std::string(w->begin()+2, w->end())))
- {
+ result << num.value();
+ } else if (w.substr(0, 2) == "0x" && w.size() > 2 && IsHex(std::string(w.begin() + 2, w.end()))) {
// Raw hex data, inserted NOT pushed onto stack:
- std::vector<unsigned char> raw = ParseHex(std::string(w->begin()+2, w->end()));
+ std::vector<unsigned char> raw = ParseHex(std::string(w.begin() + 2, w.end()));
result.insert(result.end(), raw.begin(), raw.end());
- }
- else if (w->size() >= 2 && w->front() == '\'' && w->back() == '\'')
- {
+ } else if (w.size() >= 2 && w.front() == '\'' && w.back() == '\'') {
// Single-quoted string, pushed as data. NOTE: this is poor-man's
// parsing, spaces/tabs/newlines in single-quoted strings won't work.
- std::vector<unsigned char> value(w->begin()+1, w->end()-1);
+ std::vector<unsigned char> value(w.begin() + 1, w.end() - 1);
result << value;
- }
- else
- {
+ } else {
// opcode, e.g. OP_ADD or ADD:
- result << ParseOpCode(*w);
+ result << ParseOpCode(w);
}
}
diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h
index 9a97cad1f8..d4ceb517dd 100644
--- a/src/interfaces/chain.h
+++ b/src/interfaces/chain.h
@@ -289,7 +289,7 @@ public:
virtual void requestMempoolTransactions(Notifications& notifications) = 0;
//! Check if Taproot has activated
- virtual bool isTaprootActive() const = 0;
+ virtual bool isTaprootActive() = 0;
};
//! Interface to let node manage chain clients (wallets, or maybe tools for
diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp
index 5b6d8416a7..73f4036057 100644
--- a/src/node/interfaces.cpp
+++ b/src/node/interfaces.cpp
@@ -698,7 +698,7 @@ public:
notifications.transactionAddedToMempool(entry.GetSharedTx(), 0 /* mempool_sequence */);
}
}
- bool isTaprootActive() const override
+ bool isTaprootActive() override
{
LOCK(::cs_main);
const CBlockIndex* tip = Assert(m_node.chainman)->ActiveChain().Tip();
diff --git a/src/rest.cpp b/src/rest.cpp
index e50ab33e54..f6e34c2d81 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -189,9 +189,10 @@ static bool rest_headers(const std::any& context,
if (path.size() != 2)
return RESTERR(req, HTTP_BAD_REQUEST, "No header count specified. Use /rest/headers/<count>/<hash>.<ext>.");
- long count = strtol(path[0].c_str(), nullptr, 10);
- if (count < 1 || count > 2000)
+ const auto parsed_count{ToIntegral<size_t>(path[0])};
+ if (!parsed_count.has_value() || *parsed_count < 1 || *parsed_count > 2000) {
return RESTERR(req, HTTP_BAD_REQUEST, "Header count out of range: " + path[0]);
+ }
std::string hashStr = path[1];
uint256 hash;
@@ -199,8 +200,8 @@ static bool rest_headers(const std::any& context,
return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hashStr);
const CBlockIndex* tip = nullptr;
- std::vector<const CBlockIndex *> headers;
- headers.reserve(count);
+ std::vector<const CBlockIndex*> headers;
+ headers.reserve(*parsed_count);
{
ChainstateManager* maybe_chainman = GetChainman(context, req);
if (!maybe_chainman) return false;
@@ -211,8 +212,9 @@ static bool rest_headers(const std::any& context,
const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(hash);
while (pindex != nullptr && active_chain.Contains(pindex)) {
headers.push_back(pindex);
- if (headers.size() == (unsigned long)count)
+ if (headers.size() == *parsed_count) {
break;
+ }
pindex = active_chain.Next(pindex);
}
}
diff --git a/src/test/script_parse_tests.cpp b/src/test/script_parse_tests.cpp
index 5b8b6a725f..004c1a9a84 100644
--- a/src/test/script_parse_tests.cpp
+++ b/src/test/script_parse_tests.cpp
@@ -38,7 +38,6 @@ BOOST_AUTO_TEST_CASE(parse_script)
{"'17'", "023137"},
{"ELSE", "67"},
{"NOP10", "b9"},
- {"11111111111111111111", "00"},
};
std::string all_in;
std::string all_out;
@@ -49,6 +48,7 @@ BOOST_AUTO_TEST_CASE(parse_script)
}
BOOST_CHECK_EQUAL(HexStr(ParseScript(all_in)), all_out);
+ BOOST_CHECK_EXCEPTION(ParseScript("11111111111111111111"), std::runtime_error, HasReason("script parse error: decimal numeric value only allowed in the range -0xFFFFFFFF...0xFFFFFFFF"));
BOOST_CHECK_EXCEPTION(ParseScript("11111111111"), std::runtime_error, HasReason("script parse error: decimal numeric value only allowed in the range -0xFFFFFFFF...0xFFFFFFFF"));
BOOST_CHECK_EXCEPTION(ParseScript("OP_CHECKSIGADD"), std::runtime_error, HasReason("script parse error: unknown opcode"));
}
diff --git a/src/test/validation_chainstate_tests.cpp b/src/test/validation_chainstate_tests.cpp
index 726c9ebbb8..9bb08f774f 100644
--- a/src/test/validation_chainstate_tests.cpp
+++ b/src/test/validation_chainstate_tests.cpp
@@ -107,20 +107,21 @@ BOOST_FIXTURE_TEST_CASE(chainstate_update_tip, TestChain100Setup)
curr_tip = ::g_best_block;
- CChainState* background_cs;
-
BOOST_CHECK_EQUAL(chainman.GetAll().size(), 2);
- for (CChainState* cs : chainman.GetAll()) {
- if (cs != &chainman.ActiveChainstate()) {
- background_cs = cs;
+
+ CChainState& background_cs{*[&] {
+ for (CChainState* cs : chainman.GetAll()) {
+ if (cs != &chainman.ActiveChainstate()) {
+ return cs;
+ }
}
- }
- BOOST_CHECK(background_cs);
+ assert(false);
+ }()};
// Create a block to append to the validation chain.
std::vector<CMutableTransaction> noTxns;
CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
- CBlock validation_block = this->CreateBlock(noTxns, scriptPubKey, *background_cs);
+ CBlock validation_block = this->CreateBlock(noTxns, scriptPubKey, background_cs);
auto pblock = std::make_shared<const CBlock>(validation_block);
BlockValidationState state;
CBlockIndex* pindex = nullptr;
@@ -133,15 +134,15 @@ BOOST_FIXTURE_TEST_CASE(chainstate_update_tip, TestChain100Setup)
LOCK(::cs_main);
bool checked = CheckBlock(*pblock, state, chainparams.GetConsensus());
BOOST_CHECK(checked);
- bool accepted = background_cs->AcceptBlock(
+ bool accepted = background_cs.AcceptBlock(
pblock, state, &pindex, true, nullptr, &newblock);
BOOST_CHECK(accepted);
}
// UpdateTip is called here
- bool block_added = background_cs->ActivateBestChain(state, pblock);
+ bool block_added = background_cs.ActivateBestChain(state, pblock);
// Ensure tip is as expected
- BOOST_CHECK_EQUAL(background_cs->m_chain.Tip()->GetBlockHash(), validation_block.GetHash());
+ BOOST_CHECK_EQUAL(background_cs.m_chain.Tip()->GetBlockHash(), validation_block.GetHash());
// g_best_block should be unchanged after adding a block to the background
// validation chain.
diff --git a/src/util/strencodings.h b/src/util/strencodings.h
index 1f7762aeef..eedb5ec2f8 100644
--- a/src/util/strencodings.h
+++ b/src/util/strencodings.h
@@ -72,7 +72,7 @@ void SplitHostPort(std::string in, uint16_t& portOut, std::string& hostOut);
// LocaleIndependentAtoi is provided for backwards compatibility reasons.
//
-// New code should use the ParseInt64/ParseUInt64/ParseInt32/ParseUInt32 functions
+// New code should use ToIntegral or the ParseInt* functions
// which provide parse error feedback.
//
// The goal of LocaleIndependentAtoi is to replicate the exact defined behaviour
@@ -125,7 +125,7 @@ constexpr inline bool IsSpace(char c) noexcept {
/**
* Convert string to integral type T. Leading whitespace, a leading +, or any
* trailing character fail the parsing. The required format expressed as regex
- * is `-?[0-9]+`.
+ * is `-?[0-9]+`. The minus sign is only permitted for signed integer types.
*
* @returns std::nullopt if the entire string could not be parsed, or if the
* parsed value is not in the range representable by the type T.
diff --git a/src/util/syscall_sandbox.cpp b/src/util/syscall_sandbox.cpp
index 7e76ecbf3a..b361b09568 100644
--- a/src/util/syscall_sandbox.cpp
+++ b/src/util/syscall_sandbox.cpp
@@ -46,6 +46,12 @@ bool g_syscall_sandbox_log_violation_before_terminating{false};
// Define system call numbers for x86_64 that are referenced in the system call profile
// but not provided by the kernel headers used in the GUIX build.
+// Usually, they can be found via "grep name /usr/include/x86_64-linux-gnu/asm/unistd_64.h"
+
+#ifndef __NR_clone3
+#define __NR_clone3 435
+#endif
+
#ifndef __NR_statx
#define __NR_statx 332
#endif
@@ -115,6 +121,7 @@ const std::map<uint32_t, std::string> LINUX_SYSCALLS{
{__NR_clock_nanosleep, "clock_nanosleep"},
{__NR_clock_settime, "clock_settime"},
{__NR_clone, "clone"},
+ {__NR_clone3, "clone3"},
{__NR_close, "close"},
{__NR_connect, "connect"},
{__NR_copy_file_range, "copy_file_range"},
@@ -540,6 +547,7 @@ public:
allowed_syscalls.insert(__NR_brk); // change data segment size
allowed_syscalls.insert(__NR_madvise); // give advice about use of memory
allowed_syscalls.insert(__NR_membarrier); // issue memory barriers on a set of threads
+ allowed_syscalls.insert(__NR_mincore); // check if virtual memory is in RAM
allowed_syscalls.insert(__NR_mlock); // lock memory
allowed_syscalls.insert(__NR_mmap); // map files or devices into memory
allowed_syscalls.insert(__NR_mprotect); // set protection on a region of memory
@@ -705,6 +713,7 @@ public:
void AllowProcessStartOrDeath()
{
allowed_syscalls.insert(__NR_clone); // create a child process
+ allowed_syscalls.insert(__NR_clone3); // create a child process
allowed_syscalls.insert(__NR_exit); // terminate the calling process
allowed_syscalls.insert(__NR_exit_group); // exit all threads in a process
allowed_syscalls.insert(__NR_fork); // create a child process