diff --git a/.cicd/platforms/gcc.Dockerfile b/.cicd/platforms/gcc.Dockerfile index 6a1e9b3b7e..3ccd18edf5 100644 --- a/.cicd/platforms/gcc.Dockerfile +++ b/.cicd/platforms/gcc.Dockerfile @@ -59,8 +59,9 @@ COPY <<-EOF /extras.cmake set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "" FORCE) set(CMAKE_C_COMPILER "gcc-14" CACHE STRING "") set(CMAKE_CXX_COMPILER "g++-14" CACHE STRING "") - set(CMAKE_C_FLAGS "-Wall -Wextra -fdiagnostics-color=always" CACHE STRING "") - set(CMAKE_CXX_FLAGS "-Wall -Wextra -fdiagnostics-color=always" CACHE STRING "") + # Permit unused callback parameters and partial aggregates that use member defaults. + set(CMAKE_C_FLAGS "-Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fdiagnostics-color=always" CACHE STRING "") + set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fdiagnostics-color=always" CACHE STRING "") EOF ENV SYSIO_PLATFORM_HAS_EXTRAS_CMAKE=1 diff --git a/contracts/tests/external_chain_simulator.hpp b/contracts/tests/external_chain_simulator.hpp index c262fa0115..bef790a96a 100644 --- a/contracts/tests/external_chain_simulator.hpp +++ b/contracts/tests/external_chain_simulator.hpp @@ -121,7 +121,7 @@ class chain { const auto [seen, fresh] = received_.emplace(id, message.SerializeAsString()); FC_ASSERT(fresh || seen->second == message.SerializeAsString(), "conflicting return replay"); if (paid_requests_.contains(id)) return false; - const auto amount = message.amount().amount(); + const auto amount = static_cast(message.amount().amount()); const auto [it, inserted] = pending_.emplace(id, amount); FC_ASSERT(inserted || it->second == amount, "conflicting return replay"); return settle(id); diff --git a/contracts/tests/kicker_tester.hpp b/contracts/tests/kicker_tester.hpp index 1489226e10..2d78e4fd78 100644 --- a/contracts/tests/kicker_tester.hpp +++ b/contracts/tests/kicker_tester.hpp @@ -5,6 +5,7 @@ #include "sysio_liq_tester.hpp" #include #include "kicker_test_reference.hpp" +#include namespace kicker_test_support { namespace math = sysio::kicker_math; using kicker_test_reference::wide; @@ -168,7 +169,8 @@ class kicker_tester : public sysio_liq_tester { const auto row = stat_row(sym); const auto observation = pool(sym); const auto span = (control->pending_block_time() - observation["price_time"].as()).count(); - if (span < configuration()[kicker::field::twap_window_sec].as_uint64() * math::micros_per_sec) return 0; + const auto window_us = configuration()[kicker::field::twap_window_sec].as_uint64() * math::micros_per_sec; + if (std::cmp_less(span, window_us)) return 0; const auto sized_supply = std::min(observation["supply_snapshot"].as_int64(), row["supply"].as().get_amount()); const wide accrued = wide(sized_supply) * observation["rate_bps"].as_uint64() * diff --git a/contracts/tests/sysio.bond_tests.cpp b/contracts/tests/sysio.bond_tests.cpp index 87d7ec8b7b..6fd6ed0adb 100644 --- a/contracts/tests/sysio.bond_tests.cpp +++ b/contracts/tests/sysio.bond_tests.cpp @@ -51,10 +51,6 @@ constexpr std::string_view nothing_msg = "nothing to claim"; constexpr std::string_view wire_no_yield_msg = "WIRE collateral earns no shadow yield"; constexpr std::string_view prune_limit_msg = "limit exceeds the most requests one prune examines"; -/// The memo of the one transfer that pays the issuer an INVALID request's bonds. -constexpr std::string_view forfeit_memo = "sysio.bond::forfeit"; -/// The memo of the transfer that pays a claim in the request's token. -constexpr std::string_view claim_memo = "sysio.bond::claim"; /// `request_state` names as the ABI renders them. constexpr std::string_view STATE_OPEN = "OPEN"; diff --git a/contracts/tests/sysio.kicker_math_tests.cpp b/contracts/tests/sysio.kicker_math_tests.cpp index 56aa6d78b4..d2f8f0fbdb 100644 --- a/contracts/tests/sysio.kicker_math_tests.cpp +++ b/contracts/tests/sysio.kicker_math_tests.cpp @@ -58,7 +58,7 @@ BOOST_AUTO_TEST_CASE(spot_deviation_threshold) { BOOST_CHECK(!math::spot_deviates(0, 0, 1)); // Prices near 2^128 times 10,000 overflow 128 bits; the comparison stays exact against a wide oracle. const math::u128 top = ~math::u128{0}; - for (const auto [spot, twap, bps] : {std::tuple{top, top / 2, 10'000}, + for (const auto& [spot, twap, bps] : {std::tuple{top, top / 2, 10'000}, {top / 2, top, 5'000}, {top / 2, top, 4'999}, {top, top - 1, 1}}) { const wide gap = spot > twap ? wide(spot) - wide(twap) : wide(twap) - wide(spot); BOOST_CHECK_EQUAL(gap * 10'000 > wide(twap) * bps, math::spot_deviates(spot, twap, bps)); diff --git a/contracts/tests/sysio.kicker_tests.cpp b/contracts/tests/sysio.kicker_tests.cpp index d35802fed4..88a0ab8697 100644 --- a/contracts/tests/sysio.kicker_tests.cpp +++ b/contracts/tests/sysio.kicker_tests.cpp @@ -826,7 +826,7 @@ BOOST_AUTO_TEST_CASE(spot_deviation_threshold_is_inclusive) { BOOST_CHECK_EQUAL(0, t.paid()); BOOST_CHECK(after.deviation); BOOST_CHECK_EQUAL(gift, after.shortfall); - BOOST_CHECK(after.observed == t.control->head_block_time()); + BOOST_CHECK(after.observed == t.control->head().block_time()); // The clock and the observation are held. BOOST_CHECK(after.clock == observation.clock); BOOST_CHECK(after.price_time == observation.price_time); diff --git a/contracts/tests/sysio.opreg_tests.cpp b/contracts/tests/sysio.opreg_tests.cpp index 440ccfbd78..2700217919 100644 --- a/contracts/tests/sysio.opreg_tests.cpp +++ b/contracts/tests/sysio.opreg_tests.cpp @@ -125,8 +125,6 @@ constexpr auto kEligibilityBatchOperator = "batchop.a"_n; /// Producer account used by focused eligibility tests. constexpr auto kEligibilityProducer = "producer.a"_n; -/// Ethereum chain and token codename used by focused collateral tests. -constexpr std::string_view kEthCodename = "ETH"; /// Native WIRE chain and token codename used by focused collateral tests. constexpr std::string_view kWireCodename = "WIRE"; @@ -314,9 +312,6 @@ constexpr std::string_view kYieldNotCoveredError = "assertion failure with message: owed yield is rounding dust the WIRE received from sysio.liq does not " "cover; only later slack can cover it"; -/// Recent-actions reason `depositinle` records when it drops a credit naming the depot chain. -constexpr std::string_view kDepotChainCreditReason = - "depot-chain collateral is bonded through deposit, never credited from an outpost"; /// Account with no stake in the yield cases that cranks `claimyield` for someone else. constexpr auto kYieldKeeper = "uwrit.a"_n; diff --git a/contracts/tests/sysio.swap_tests.cpp b/contracts/tests/sysio.swap_tests.cpp index aee3f3e11e..62d040f975 100644 --- a/contracts/tests/sysio.swap_tests.cpp +++ b/contracts/tests/sysio.swap_tests.cpp @@ -2090,7 +2090,7 @@ BOOST_FIXTURE_TEST_CASE( yield_tick_sells_the_reservoir_over_the_horizon, sysio_ BOOST_REQUIRE_EQUAL( wasm_assert_msg("yield tick parameters not set"), tickyield( SHEO ) ); BOOST_REQUIRE_EQUAL( success(), setyield( SHEO, horizon_sec, cap_bps, clip_floor ) ); const int64_t set_at = last_tick_us( SHEO ); - BOOST_REQUIRE_EQUAL( control->head_block_time().time_since_epoch().count(), set_at ); // setyield starts the clock + BOOST_REQUIRE_EQUAL( control->head().block_time().time_since_epoch().count(), set_at ); // setyield starts the clock // An empty reservoir: the tick is a no-op and the clock is untouched. auto before = system_balance( SHEO.value ); diff --git a/libraries/appbase b/libraries/appbase index 40bcefdabb..fcb746bd5a 160000 --- a/libraries/appbase +++ b/libraries/appbase @@ -1 +1 @@ -Subproject commit 40bcefdabb2db7980a501e0d8b886e08d0fff98c +Subproject commit fcb746bd5ad076f43c99fcc5f6be9a0de4083f9f diff --git a/libraries/chain/include/sysio/chain/vote_processor.hpp b/libraries/chain/include/sysio/chain/vote_processor.hpp index 90023a8d36..fc0c290227 100644 --- a/libraries/chain/include/sysio/chain/vote_processor.hpp +++ b/libraries/chain/include/sysio/chain/vote_processor.hpp @@ -115,7 +115,7 @@ class vote_processor_t { for (auto i = idx.begin(); i != idx.end();) { if (stopped) return; - vote v = std::move(*i); + vote v = *i; idx.erase(i); auto bsp = get_block(v.msg->block_id, g); // g is unlocked diff --git a/libraries/chain/include/sysio/chain/webassembly/sys-vm-oc/code_cache.hpp b/libraries/chain/include/sysio/chain/webassembly/sys-vm-oc/code_cache.hpp index 26e7cce8ab..092cb341e5 100644 --- a/libraries/chain/include/sysio/chain/webassembly/sys-vm-oc/code_cache.hpp +++ b/libraries/chain/include/sysio/chain/webassembly/sys-vm-oc/code_cache.hpp @@ -121,7 +121,7 @@ class code_cache_async : public code_cache_base { //If code is in cache: returns pointer & bumps to front of MRU list //If code is not in cache, and not blacklisted, and not currently compiling: return nullptr and kick off compile //otherwise: return nullptr - const code_descriptor* const get_descriptor_for_code(mode m, account_name receiver, const digest_type& code_id, + const code_descriptor* get_descriptor_for_code(mode m, account_name receiver, const digest_type& code_id, const uint8_t& vm_version, get_cd_failure& failure); private: @@ -144,7 +144,7 @@ class code_cache_sync : public code_cache_base { ~code_cache_sync(); //Can still fail and return nullptr if, for example, there is an expected instantiation failure - const code_descriptor* const get_descriptor_for_code_sync(mode m, account_name receiver, + const code_descriptor* get_descriptor_for_code_sync(mode m, account_name receiver, const digest_type& code_id, const uint8_t& vm_version); }; diff --git a/libraries/chain/include/sysio/chain/webassembly/sys-vm-oc/memory.hpp b/libraries/chain/include/sysio/chain/webassembly/sys-vm-oc/memory.hpp index 4da95f5d78..a22321bf18 100644 --- a/libraries/chain/include/sysio/chain/webassembly/sys-vm-oc/memory.hpp +++ b/libraries/chain/include/sysio/chain/webassembly/sys-vm-oc/memory.hpp @@ -28,13 +28,13 @@ class memory { memory(const memory&) = delete; memory& operator=(const memory&) = delete; - uint8_t* const zero_page_memory_base() const { return zeropage_base; } - uint8_t* const full_page_memory_base() const { return fullpage_base; } + uint8_t* zero_page_memory_base() const { return zeropage_base; } + uint8_t* full_page_memory_base() const { return fullpage_base; } - control_block* const get_control_block() const { return reinterpret_cast(zeropage_base - cb_offset);} + control_block* get_control_block() const { return reinterpret_cast(zeropage_base - cb_offset);} //these two are really only inteded for SEGV handling - uint8_t* const start_of_memory_slices() const { return mapbase; } + uint8_t* start_of_memory_slices() const { return mapbase; } size_t size_of_memory_slice_mapping() const { return mapsize; } //to obtain memory protected for n wasm-pages, use the pointer computed from: diff --git a/libraries/chain/wasm_sysio_validation.cpp b/libraries/chain/wasm_sysio_validation.cpp index 46fbef2f4f..25f96e9468 100644 --- a/libraries/chain/wasm_sysio_validation.cpp +++ b/libraries/chain/wasm_sysio_validation.cpp @@ -49,6 +49,7 @@ void globals_validation_visitor::validate( const Module& m ) { case ValueType::i64: case ValueType::f64: mutable_globals_total_size += 4; + [[fallthrough]]; case ValueType::i32: case ValueType::f32: mutable_globals_total_size += 4; diff --git a/libraries/chain/webassembly/runtimes/sys-vm-oc/code_cache.cpp b/libraries/chain/webassembly/runtimes/sys-vm-oc/code_cache.cpp index 058f93fd4a..15d6613e22 100644 --- a/libraries/chain/webassembly/runtimes/sys-vm-oc/code_cache.cpp +++ b/libraries/chain/webassembly/runtimes/sys-vm-oc/code_cache.cpp @@ -160,7 +160,7 @@ std::tuple code_cache_async::consume_compile_thread_queue() { } -const code_descriptor* const +const code_descriptor* code_cache_async::get_descriptor_for_code(mode m, account_name receiver, const digest_type& code_id, const uint8_t& vm_version, get_cd_failure& failure) { //if there are any outstanding compiles, process the result queue now //When app is in write window, all tasks are running sequentially and read-only threads @@ -243,7 +243,7 @@ code_cache_sync::~code_cache_sync() { elog("unexpected response from SYS VM OC compile monitor during shutdown"); } -const code_descriptor* const code_cache_sync::get_descriptor_for_code_sync(mode m, account_name receiver, const digest_type& code_id, const uint8_t& vm_version) { +const code_descriptor* code_cache_sync::get_descriptor_for_code_sync(mode m, account_name receiver, const digest_type& code_id, const uint8_t& vm_version) { //check for entry in cache code_cache_index::index::type::iterator it = _cache_index.get().find(code_id); if(it != _cache_index.get().end()) { diff --git a/libraries/chain/webassembly/runtimes/sys-vm-oc/compile_trampoline.cpp b/libraries/chain/webassembly/runtimes/sys-vm-oc/compile_trampoline.cpp index 0465854513..9b12c9ca83 100644 --- a/libraries/chain/webassembly/runtimes/sys-vm-oc/compile_trampoline.cpp +++ b/libraries/chain/webassembly/runtimes/sys-vm-oc/compile_trampoline.cpp @@ -73,7 +73,7 @@ void run_compile(wrapped_fd&& response_sock, wrapped_fd&& wasm_code, uint64_t st if(!global.type.isMutable) continue; prologue_it -= 8; - global_union* const u = (global_union* const)&*prologue_it; + global_union* const u = (global_union*)&*prologue_it; switch(global.initializer.type) { case InitializerExpression::Type::i32_const: u->i32 = global.initializer.i32; break; diff --git a/libraries/chain/webassembly/runtimes/sys-vm-oc/gs_seg_helpers.c b/libraries/chain/webassembly/runtimes/sys-vm-oc/gs_seg_helpers.c index b2958d7bce..4e88f90b1a 100644 --- a/libraries/chain/webassembly/runtimes/sys-vm-oc/gs_seg_helpers.c +++ b/libraries/chain/webassembly/runtimes/sys-vm-oc/gs_seg_helpers.c @@ -21,7 +21,7 @@ int32_t sys_vm_oc_grow_memory(int32_t grow, int32_t max) { uint64_t previous_page_count = cb_ptr->current_linear_memory_pages; int32_t grow_amount = grow; uint64_t max_pages = max; - if(max_pages > cb_ptr->max_linear_memory_pages) + if(max_pages > (uint64_t)cb_ptr->max_linear_memory_pages) max_pages = cb_ptr->max_linear_memory_pages; if(grow == 0) return (int32_t)cb_ptr->current_linear_memory_pages; @@ -29,8 +29,8 @@ int32_t sys_vm_oc_grow_memory(int32_t grow, int32_t max) { return (int32_t)-1; int64_t max_segments = cb_ptr->execution_thread_memory_length / SYS_VM_OC_MEMORY_STRIDE - 1; - int was_extended = previous_page_count > max_segments; - int will_be_extended = previous_page_count + grow_amount > max_segments; + int was_extended = previous_page_count > (uint64_t)max_segments; + int will_be_extended = previous_page_count + grow_amount > (uint64_t)max_segments; char* extended_memory_start = cb_ptr->full_linear_memory_start + max_segments * 64*1024; int64_t gs_diff; if(will_be_extended && grow_amount > 0) { diff --git a/libraries/chain/webassembly/runtimes/sys-vm-oc/memory.cpp b/libraries/chain/webassembly/runtimes/sys-vm-oc/memory.cpp index a87c94ef52..a39eb27a7c 100644 --- a/libraries/chain/webassembly/runtimes/sys-vm-oc/memory.cpp +++ b/libraries/chain/webassembly/runtimes/sys-vm-oc/memory.cpp @@ -38,7 +38,7 @@ memory::memory(uint64_t sliced_pages) { fullpage_base = last + memory_prologue_size; //layout the intrinsic jump table - uintptr_t* const intrinsic_jump_table = reinterpret_cast(zeropage_base - first_intrinsic_offset); + uintptr_t* const intrinsic_jump_table = reinterpret_cast(zeropage_base - first_intrinsic_offset); const intrinsic_map_t& intrinsics = get_intrinsic_map(); for(const auto& intrinsic : intrinsics) intrinsic_jump_table[-(int)intrinsic.second.ordinal] = (uintptr_t)intrinsic.second.function_ptr; diff --git a/libraries/chaindb/test/undo_index.cpp b/libraries/chaindb/test/undo_index.cpp index cd4cfbd64a..a850f7f330 100644 --- a/libraries/chaindb/test/undo_index.cpp +++ b/libraries/chaindb/test/undo_index.cpp @@ -103,7 +103,8 @@ struct undo_index_in_segment { segment_manager.destroy_ptr(p); } - undo_index_t* const operator->() { + /// Access the stored index without applying an ignored qualifier to the returned pointer. + undo_index_t* operator->() { return p; } diff --git a/libraries/libfc/include/fc/bitset.hpp b/libraries/libfc/include/fc/bitset.hpp index d1e80a8cf8..317aeb1db0 100644 --- a/libraries/libfc/include/fc/bitset.hpp +++ b/libraries/libfc/include/fc/bitset.hpp @@ -27,8 +27,9 @@ struct bitset { static constexpr size_type bits_per_block = 8; static constexpr size_type npos = static_cast(-1); + /// Round up the storage requirement without overflowing at the maximum bit count. static constexpr size_type calc_num_blocks(size_type num_bits) { - return (num_bits + bits_per_block - 1) / bits_per_block; + return num_bits / bits_per_block + (num_bits % bits_per_block != 0); } static size_type block_index(size_type pos) noexcept { return pos / bits_per_block; } @@ -123,13 +124,14 @@ struct bitset { return *this; } + /// Clear padding only when a final storage block exists. void zero_unused_bits() { assert (m_bits.size() == calc_num_blocks(m_num_bits)); // if != 0 this is the number of bits used in the last block const size_type extra_bits = bit_index(size()); - if (extra_bits != 0) + if (!m_bits.empty() && extra_bits != 0) m_bits.back() &= (uint8_t(1) << extra_bits) - 1; } diff --git a/libraries/libfc/include/fc/exception/exception.hpp b/libraries/libfc/include/fc/exception/exception.hpp index 1d0abb47b1..68d3fe64d1 100644 --- a/libraries/libfc/include/fc/exception/exception.hpp +++ b/libraries/libfc/include/fc/exception/exception.hpp @@ -432,10 +432,21 @@ namespace fc throw e; \ } -#define FC_LOG_AND_DROP( FORMAT, ... ) \ - catch( const boost::interprocess::bad_alloc& ) {\ - throw;\ - } catch( fc::exception& er ) { \ +/// Log ordinary failures while allowing shared-memory allocation failures to propagate. +#define FC_LOG_AND_DROP( FORMAT, ... ) \ + catch( const boost::interprocess::bad_alloc& ) { \ + throw; \ + } FC_DETAIL_LOG_AND_DROP( FORMAT, ##__VA_ARGS__ ) + +/// Preserve the fail-fast allocation policy in a noexcept cleanup operation. +#define FC_LOG_AND_DROP_NOEXCEPT( FORMAT, ... ) \ + catch( const boost::interprocess::bad_alloc& ) { \ + std::terminate(); \ + } FC_DETAIL_LOG_AND_DROP( FORMAT, ##__VA_ARGS__ ) + +/// Common logging handlers; callers decide how to handle interprocess allocation failures. +#define FC_DETAIL_LOG_AND_DROP( FORMAT, ... ) \ + catch( fc::exception& er ) { \ wlog( FORMAT " {}", ##__VA_ARGS__, er.to_detail_string() ); \ } catch( const std::exception& e ) { \ fc::std_exception_wrapper sew( \ diff --git a/libraries/libfc/include/fc/io/json_relaxed.hpp b/libraries/libfc/include/fc/io/json_relaxed.hpp index 548789a6fe..c315a22c8e 100644 --- a/libraries/libfc/include/fc/io/json_relaxed.hpp +++ b/libraries/libfc/include/fc/io/json_relaxed.hpp @@ -188,6 +188,7 @@ namespace fc { namespace json_relaxed case 'r': if( strict ) FC_THROW_EXCEPTION( parse_error_exception, "raw strings not supported in strict mode" ); + [[fallthrough]]; case 'R': in.get(); c2 = in.peek(); diff --git a/libraries/libfc/include/fc/io/random_access_file.hpp b/libraries/libfc/include/fc/io/random_access_file.hpp index 2638ec21ff..ce15bbe7f5 100644 --- a/libraries/libfc/include/fc/io/random_access_file.hpp +++ b/libraries/libfc/include/fc/io/random_access_file.hpp @@ -371,11 +371,12 @@ class random_access_file { return write(&c, sizeof(char)); } + /// Flush pending bytes, dropping write errors and retaining fail-fast shared-memory OOM handling. ~write_datastream() { try { if(ctx) do_write(); - } FC_LOG_AND_DROP("write failure ignored"); + } FC_LOG_AND_DROP_NOEXCEPT("write failure ignored"); } private: diff --git a/libraries/libfc/include/fc/safe.hpp b/libraries/libfc/include/fc/safe.hpp index bbe693e1b7..8545114a7a 100644 --- a/libraries/libfc/include/fc/safe.hpp +++ b/libraries/libfc/include/fc/safe.hpp @@ -26,6 +26,8 @@ namespace fc { safe( O o ):value(o){} safe(){} safe( const safe& o ):value(o.value){} + /// Assign the checked value without changing its representation. + safe& operator=(const safe&) = default; static safe min() { diff --git a/libraries/libfc/src/crypto/elliptic_em.cpp b/libraries/libfc/src/crypto/elliptic_em.cpp index 3f6b40d675..ab6a78760c 100644 --- a/libraries/libfc/src/crypto/elliptic_em.cpp +++ b/libraries/libfc/src/crypto/elliptic_em.cpp @@ -49,6 +49,9 @@ class public_key_impl { _init_lib(); } + /// Preserve memberwise key assignment alongside the custom copy constructor. + public_key_impl& operator=(const public_key_impl&) = default; + public_key_data _key{}; }; diff --git a/libraries/libfc/src/crypto/ethereum/ethereum_utils.cpp b/libraries/libfc/src/crypto/ethereum/ethereum_utils.cpp index fa73cd08fe..7d1b61a11c 100644 --- a/libraries/libfc/src/crypto/ethereum/ethereum_utils.cpp +++ b/libraries/libfc/src/crypto/ethereum/ethereum_utils.cpp @@ -93,6 +93,7 @@ fc::em::public_key to_em_public_key(const std::string& pubkey_hex) { switch (pubkey_byte_count) { case 64: copy_to_offset = 1; + [[fallthrough]]; case 65: { em::public_key_data_uncompressed pubkey_data; std::copy_n(pubkey_bytes.data(), pubkey_bytes.size(), pubkey_data.data() + copy_to_offset); diff --git a/libraries/libfc/src/io/json.cpp b/libraries/libfc/src/io/json.cpp index 268703d4b6..e50334904c 100644 --- a/libraries/libfc/src/io/json.cpp +++ b/libraries/libfc/src/io/json.cpp @@ -319,6 +319,7 @@ namespace fc if (dot) FC_THROW_EXCEPTION(parse_error_exception, "Can't parse a number with two decimal places"); dot = true; + [[fallthrough]]; case '0': case '1': case '2': @@ -563,26 +564,31 @@ namespace fc out += "\\t"; break; } + [[fallthrough]]; case '\n': // \x0a if( escape_control_chars ) { out += "\\n"; break; } + [[fallthrough]]; case '\r': // \x0d if( escape_control_chars ) { out += "\\r"; break; } + [[fallthrough]]; case '\\': if( escape_control_chars ) { out += "\\\\"; break; } + [[fallthrough]]; case '\"': if( escape_control_chars ) { out += "\\\""; break; } + [[fallthrough]]; default: out += *itr; } diff --git a/libraries/libfc/test/io/test_secure_file.cpp b/libraries/libfc/test/io/test_secure_file.cpp index 3e48bf0738..15717ce54a 100644 --- a/libraries/libfc/test/io/test_secure_file.cpp +++ b/libraries/libfc/test/io/test_secure_file.cpp @@ -32,7 +32,7 @@ constexpr long minimum_long_filename_name_max = 64; /** * Owns an open file stream and closes its underlying descriptor when a test scope exits. */ -using file_stream_ptr = std::unique_ptr; +using file_stream_ptr = std::unique_ptr; /** * Restores the process umask when a test scope exits. diff --git a/libraries/libfc/test/network/test_http_client.cpp b/libraries/libfc/test/network/test_http_client.cpp index 76cd6f3185..2cfbbc5d3a 100644 --- a/libraries/libfc/test/network/test_http_client.cpp +++ b/libraries/libfc/test/network/test_http_client.cpp @@ -680,13 +680,13 @@ class tls_test_material { /** Write one PEM certificate. */ void write_certificate(std::string_view name, X509& certificate) { - std::unique_ptr output(std::fopen(path(name).c_str(), "w"), &std::fclose); + std::unique_ptr output(std::fopen(path(name).c_str(), "w"), &std::fclose); FC_ASSERT(output && PEM_write_X509(output.get(), &certificate) == 1, "Failed to write TLS test certificate"); } /** Write one unencrypted PEM private key. */ void write_key(std::string_view name, EVP_PKEY& key) { - std::unique_ptr output(std::fopen(path(name).c_str(), "w"), &std::fclose); + std::unique_ptr output(std::fopen(path(name).c_str(), "w"), &std::fclose); FC_ASSERT(output && PEM_write_PrivateKey(output.get(), &key, nullptr, nullptr, 0, nullptr, nullptr) == 1, "Failed to write TLS test private key"); } @@ -745,7 +745,7 @@ bool supports_ipv6_loopback() { /** Return the OpenSSL hashed-directory filename for @p certificate. */ std::string certificate_hash_filename(const std::filesystem::path& certificate) { - std::unique_ptr input(std::fopen(certificate.c_str(), "r"), &std::fclose); + std::unique_ptr input(std::fopen(certificate.c_str(), "r"), &std::fclose); BOOST_REQUIRE(input); std::unique_ptr parsed(PEM_read_X509(input.get(), nullptr, nullptr, nullptr), &X509_free); diff --git a/libraries/libfc/test/test_bitset.cpp b/libraries/libfc/test/test_bitset.cpp index 9d86e556c0..ffb3fb792a 100644 --- a/libraries/libfc/test/test_bitset.cpp +++ b/libraries/libfc/test/test_bitset.cpp @@ -2,6 +2,7 @@ #include #include +#include using namespace fc; @@ -167,4 +168,29 @@ BOOST_AUTO_TEST_CASE(bitset_test) test_bitset("01110011010100101111001101100100100111111111111111111001"); } +/// Extreme sizes must not wrap the byte count to zero before allocating storage. +BOOST_AUTO_TEST_CASE(storage_size_overflow) { + using size_type = fc::bitset::size_type; + constexpr auto max_bits = std::numeric_limits::max(); + constexpr auto max_blocks = size_type{1} << (std::numeric_limits::digits - 3); + BOOST_CHECK_EQUAL(fc::bitset::calc_num_blocks(max_bits), max_blocks); + BOOST_CHECK_EQUAL(fc::bitset::calc_num_blocks(max_bits - 6), max_blocks); + BOOST_CHECK_EQUAL(fc::bitset::calc_num_blocks(max_bits - 7), max_blocks - 1); + + // Exercise the same masking path with no block, a partial block, and a full block. + fc::bitset bits("111111111"); + bits.resize(1); + bits.resize(9); + BOOST_CHECK_EQUAL(bits.to_string(), "000000001"); + BOOST_CHECK(bits.unused_bits_zeroed()); + bits.resize(0); + bits.flip(); + BOOST_CHECK_EQUAL(bits.num_blocks(), 0u); + BOOST_CHECK(bits.unused_bits_zeroed()); + bits.resize(8); + bits.flip(); + BOOST_CHECK_EQUAL(bits.to_string(), "11111111"); + BOOST_CHECK(bits.unused_bits_zeroed()); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/libraries/libfc/test/test_exception.cpp b/libraries/libfc/test/test_exception.cpp index fbea7a9407..660b2a04d1 100644 --- a/libraries/libfc/test/test_exception.cpp +++ b/libraries/libfc/test/test_exception.cpp @@ -2,6 +2,10 @@ #include +#include +#include +#include + BOOST_AUTO_TEST_SUITE(exception) /** @@ -35,4 +39,48 @@ BOOST_AUTO_TEST_CASE(rethrow) try { } FC_LOG_AND_RETHROW(); +/// Preserve the existing policy: cleanup drops ordinary failures and the general macro propagates interprocess OOM. +BOOST_AUTO_TEST_CASE(cleanup_exception_policy) { + const auto cleanup = [](auto failure) noexcept { + try { + failure(); + } FC_LOG_AND_DROP_NOEXCEPT("cleanup regression") + }; + BOOST_CHECK_NO_THROW(cleanup([] { FC_THROW_EXCEPTION(fc::invalid_arg_exception, "expected cleanup failure"); })); + BOOST_CHECK_NO_THROW(cleanup([] { throw std::runtime_error("expected cleanup failure"); })); + BOOST_CHECK_NO_THROW(cleanup([] { throw 0; })); + const auto propagate = [] { + try { + throw boost::interprocess::bad_alloc(); + } FC_LOG_AND_DROP("allocation regression") + }; + BOOST_CHECK_THROW(propagate(), boost::interprocess::bad_alloc); +} + +/// Preserve the existing noexcept cleanup policy, which terminates on interprocess OOM. +BOOST_AUTO_TEST_CASE(cleanup_allocation_failure_terminates) { + constexpr int terminated = 73; + constexpr int returned = 74; + const auto child = ::fork(); + BOOST_REQUIRE(child >= 0); + if (child == 0) { + std::set_terminate([] { ::_exit(terminated); }); + const auto cleanup = []() noexcept { + try { + throw boost::interprocess::bad_alloc(); + } FC_LOG_AND_DROP_NOEXCEPT("allocation regression") + }; + cleanup(); + ::_exit(returned); + } + int status = 0; + pid_t waited; + do { + waited = ::waitpid(child, &status, 0); + } while (waited == -1 && errno == EINTR); + BOOST_REQUIRE_EQUAL(waited, child); + BOOST_REQUIRE(WIFEXITED(status)); + BOOST_CHECK_EQUAL(WEXITSTATUS(status), terminated); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/libraries/opp/client_config/src/client_config_loader.cpp b/libraries/opp/client_config/src/client_config_loader.cpp index 90bda2409e..72ff581313 100644 --- a/libraries/opp/client_config/src/client_config_loader.cpp +++ b/libraries/opp/client_config/src/client_config_loader.cpp @@ -34,7 +34,6 @@ constexpr std::string_view max_priority_fee_per_gas_wei = "max_priority_fee_per_ constexpr std::string_view max_fee_per_gas_wei = "max_fee_per_gas_wei"; constexpr std::string_view max_gas_limit = "max_gas_limit"; constexpr std::string_view max_total_native_cost_wei = "max_total_native_cost_wei"; -constexpr std::string_view read_confirmation = "read_confirmation"; constexpr std::string_view block_tag = "block_tag"; constexpr std::string_view confirmations = "confirmations"; constexpr std::string_view max_finality_lag_sec = "max_finality_lag_sec"; diff --git a/libraries/wasm-jit/Source/ThirdParty/dtoa.c b/libraries/wasm-jit/Source/ThirdParty/dtoa.c index 9a6aae4e79..41f0b4a24d 100644 --- a/libraries/wasm-jit/Source/ThirdParty/dtoa.c +++ b/libraries/wasm-jit/Source/ThirdParty/dtoa.c @@ -1865,7 +1865,7 @@ gethex( CONST char **sp, U *rvp, int rounding, int sign) switch(*++s) { case '-': esign = 1; - /* no break */ + /* fall through */ case '+': s++; } @@ -2532,11 +2532,11 @@ strtod for(s = s00;;s++) switch(*s) { case '-': sign = 1; - /* no break */ + /* fall through */ case '+': if (*++s) goto break2; - /* no break */ + /* fall through */ case 0: goto ret0; case '\t': @@ -2644,6 +2644,7 @@ strtod switch(c = *++s) { case '-': esign = 1; + /* fall through */ case '+': c = *++s; } @@ -3898,7 +3899,7 @@ dtoa break; case 2: leftright = 0; - /* no break */ + /* fall through */ case 4: if (ndigits <= 0) ndigits = 1; @@ -3906,7 +3907,7 @@ dtoa break; case 3: leftright = 0; - /* no break */ + /* fall through */ case 5: i = ndigits + k + 1; ilim = i; diff --git a/plugins/chain_plugin/src/account_query_db.cpp b/plugins/chain_plugin/src/account_query_db.cpp index e100204881..8d5651c3b0 100644 --- a/plugins/chain_plugin/src/account_query_db.cpp +++ b/plugins/chain_plugin/src/account_query_db.cpp @@ -412,14 +412,15 @@ namespace sysio::chain_apis { const auto& authorizer = itr->first.value; auto weight = itr->first.weight; - result.accounts.emplace_back(result_t::account_result{ + // Construct the aggregate in place, including disengaged optional authorizers. + result.accounts.emplace_back( pi.owner, pi.name, make_optional_authorizer(authorizer), make_optional_authorizer(authorizer), weight, pi.threshold - }); + ); } }; diff --git a/plugins/chain_plugin/src/chain_plugin.cpp b/plugins/chain_plugin/src/chain_plugin.cpp index 49cc599a00..0eff2d1f31 100644 --- a/plugins/chain_plugin/src/chain_plugin.cpp +++ b/plugins/chain_plugin/src/chain_plugin.cpp @@ -1095,7 +1095,7 @@ void chain_plugin_impl::plugin_initialize(const variables_map& options) { } chain_config->sig_cpu_bill_pct = options.at("signature-cpu-billable-pct").as(); - SYS_ASSERT( chain_config->sig_cpu_bill_pct >= 0 && chain_config->sig_cpu_bill_pct <= 100, plugin_config_exception, + SYS_ASSERT( chain_config->sig_cpu_bill_pct <= 100, plugin_config_exception, "signature-cpu-billable-pct must be 0 - 100, {}", chain_config->sig_cpu_bill_pct ); chain_config->sig_cpu_bill_pct *= config::percent_1; diff --git a/plugins/http_plugin/include/sysio/http_plugin/common.hpp b/plugins/http_plugin/include/sysio/http_plugin/common.hpp index 758e1c45b9..665613b4bd 100644 --- a/plugins/http_plugin/include/sysio/http_plugin/common.hpp +++ b/plugins/http_plugin/include/sysio/http_plugin/common.hpp @@ -218,7 +218,7 @@ inline auto make_http_response_handler(http_plugin_state& plugin_state, detail:: if (content_type == http_content_type::plaintext && !plaintext_body) session_ptr->set_content_type_header(http_content_type::json); // HTTP 204 never carries a body, including JSON-RPC notifications. - if (code == magic_enum::enum_integer(boost::beast::http::status::no_content)) { + if (code == static_cast(magic_enum::enum_integer(boost::beast::http::status::no_content))) { session_ptr->send_response({}, code); } else if (response.has_value()) { std::string json = plaintext_body diff --git a/plugins/net_plugin/include/sysio/net_plugin/buffer_factory.hpp b/plugins/net_plugin/include/sysio/net_plugin/buffer_factory.hpp index f63f8f7a2e..baaeefae38 100644 --- a/plugins/net_plugin/include/sysio/net_plugin/buffer_factory.hpp +++ b/plugins/net_plugin/include/sysio/net_plugin/buffer_factory.hpp @@ -29,7 +29,7 @@ namespace sysio { static send_buffer_type create_send_buffer( const net_message& m ) { const uint32_t payload_size = fc::raw::pack_size( m ); - const char* const header = reinterpret_cast(&payload_size); // avoid variable size encoding of uint32_t + const char* const header = reinterpret_cast(&payload_size); // avoid variable size encoding of uint32_t const size_t buffer_size = message_header_size + payload_size; auto send_buffer = std::make_shared>(buffer_size); @@ -46,7 +46,7 @@ namespace sysio { const uint32_t which_size = fc::raw::pack_size( unsigned_int( which ) ); const uint32_t payload_size = which_size + fc::raw::pack_size( v ); - const char* const header = reinterpret_cast(&payload_size); // avoid variable size encoding of uint32_t + const char* const header = reinterpret_cast(&payload_size); // avoid variable size encoding of uint32_t const size_t buffer_size = message_header_size + payload_size; auto send_buffer = std::make_shared>( buffer_size ); @@ -65,7 +65,7 @@ namespace sysio { const uint32_t which_size = fc::raw::pack_size( unsigned_int( signed_block_which ) ); const uint32_t payload_size = which_size + v.size(); - const char* const header = reinterpret_cast(&payload_size); // avoid variable size encoding of uint32_t + const char* const header = reinterpret_cast(&payload_size); // avoid variable size encoding of uint32_t const size_t buffer_size = message_header_size + payload_size; auto send_buffer = std::make_shared>( buffer_size ); @@ -143,7 +143,7 @@ namespace sysio { const uint32_t trx_size = fc::raw::pack_size( *trx ); const uint32_t payload_size = which_size + id_size + trx_size; - const char* const header = reinterpret_cast(&payload_size); + const char* const header = reinterpret_cast(&payload_size); const size_t buffer_size = message_header_size + payload_size; auto send_buffer = std::make_shared>( buffer_size ); @@ -183,7 +183,7 @@ namespace sysio { const uint32_t msg_size = fc::raw::pack_size( msg ); const uint32_t payload_size = which_size + id_size + msg_size; - const char* const header = reinterpret_cast(&payload_size); + const char* const header = reinterpret_cast(&payload_size); const size_t buffer_size = message_header_size + payload_size; auto send_buffer = std::make_shared>( buffer_size ); @@ -223,7 +223,7 @@ namespace sysio { } const uint32_t payload_size = which_size + s; - const char* const header = reinterpret_cast(&payload_size); // avoid variable size encoding of uint32_t + const char* const header = reinterpret_cast(&payload_size); // avoid variable size encoding of uint32_t const size_t buffer_size = message_header_size + payload_size; auto send_buffer = std::make_shared>( buffer_size ); @@ -263,7 +263,7 @@ namespace sysio { s += fc::raw::pack_size(signed_empty); const uint32_t payload_size = which_size + s; - const char* const header = reinterpret_cast(&payload_size); // avoid variable size encoding of uint32_t + const char* const header = reinterpret_cast(&payload_size); // avoid variable size encoding of uint32_t const size_t buffer_size = message_header_size + payload_size; auto send_buffer = std::make_shared>( buffer_size ); diff --git a/plugins/outpost_ethereum_client_plugin/test/test_outpost_ethereum_client_plugin.cpp b/plugins/outpost_ethereum_client_plugin/test/test_outpost_ethereum_client_plugin.cpp index 4ea2f2e475..274234d0fb 100644 --- a/plugins/outpost_ethereum_client_plugin/test/test_outpost_ethereum_client_plugin.cpp +++ b/plugins/outpost_ethereum_client_plugin/test/test_outpost_ethereum_client_plugin.cpp @@ -179,9 +179,6 @@ constexpr std::string_view emit_outbound_envelope_abi_name = "emitOutboundEnvelo constexpr std::string_view emit_outbound_envelope_selector = "a3ad9cc3"; constexpr std::string_view test_opp_address = "5FbDB2315678afecb367f032d93F642f64180aa3"; const std::string latest_slot_test_rpc_url = startup_test::unused_url(); -constexpr std::string_view http_scheme_prefix = "http://"; -/** Prefix identifying the bounded transport category in chain-id startup diagnostics. */ -constexpr std::string_view last_failure_detail_prefix = "last_failure="; constexpr std::string_view latest_slot_test_entry_id = "latest-slot-test"; constexpr std::string_view latest_slot_test_private_key = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"; @@ -199,7 +196,6 @@ constexpr size_t emit_outbound_envelope_call_hex_chars = evm_function_selector_hex_chars + evm_abi_word_hex_chars; constexpr uint64_t test_outpost_chain_code = 1; constexpr uint32_t test_evm_chain_id = 31337; -constexpr size_t transient_chain_id_failures = 1; constexpr uint32_t test_wire_epoch = 7; constexpr uint32_t test_stale_wire_epoch = test_wire_epoch - 1; constexpr uint32_t test_different_wire_epoch = test_wire_epoch + 1; diff --git a/plugins/trace_api_plugin/src/store_provider.cpp b/plugins/trace_api_plugin/src/store_provider.cpp index bea469cf72..70509e1cb7 100644 --- a/plugins/trace_api_plugin/src/store_provider.cpp +++ b/plugins/trace_api_plugin/src/store_provider.cpp @@ -372,7 +372,7 @@ namespace sysio::trace_api { result.open(); } - return std::move(result); + return result; } else { return {}; } diff --git a/programs/clio/do_http_post_libcurl.cpp b/programs/clio/do_http_post_libcurl.cpp index 803f444828..7713fb8475 100644 --- a/programs/clio/do_http_post_libcurl.cpp +++ b/programs/clio/do_http_post_libcurl.cpp @@ -51,6 +51,7 @@ namespace sysio { namespace client { namespace http { switch (type) { case CURLINFO_TEXT: fprintf(stderr, "== Info: %s", data); + [[fallthrough]]; default: /* in case a new one is introduced to shock us */ return 0; case CURLINFO_HEADER_OUT: text = "=> Send header"; break; diff --git a/programs/clio/main.cpp b/programs/clio/main.cpp index cf297bb04a..e815a51b4a 100644 --- a/programs/clio/main.cpp +++ b/programs/clio/main.cpp @@ -640,7 +640,7 @@ fc::variant json_from_file_or_string(const string& file_or_str, fc::json::parse_ } else if (looks_like_json) { try { return fc::json::from_string(file_or_str, ptype); - } SYS_RETHROW_EXCEPTIONS(json_parse_exception, "Fail to parse JSON from string: {}", ("string", file_or_str)); + } SYS_RETHROW_EXCEPTIONS(json_parse_exception, "Fail to parse JSON from string: {}", file_or_str); } else { return file_or_str; } diff --git a/tests/trx_generator/trx_provider.cpp b/tests/trx_generator/trx_provider.cpp index 63fc7d6c01..d0705095b8 100644 --- a/tests/trx_generator/trx_provider.cpp +++ b/tests/trx_generator/trx_provider.cpp @@ -46,7 +46,7 @@ namespace sysio::testing { const uint32_t payload_size = fc::raw::pack_size(net_msg); const size_t buffer_size = message_header_size + payload_size; // Avoid variable-size encoding for the fixed-width P2P length prefix. - const char* const header = reinterpret_cast(&payload_size); + const char* const header = reinterpret_cast(&payload_size); auto send_buffer = std::make_shared>(buffer_size); fc::datastream ds(send_buffer->data(), buffer_size); @@ -109,7 +109,7 @@ namespace sysio::testing { const size_t buffer_size = message_header_size + payload_size; // Avoid variable-size encoding for the fixed-width P2P length prefix. - const char* const header = reinterpret_cast(&payload_size); + const char* const header = reinterpret_cast(&payload_size); auto send_buffer = std::make_shared>(buffer_size); fc::datastream ds( send_buffer->data(), buffer_size); diff --git a/unittests/fork_db_tests.cpp b/unittests/fork_db_tests.cpp index 9f7e9e6b7b..3c2bdd9dfb 100644 --- a/unittests/fork_db_tests.cpp +++ b/unittests/fork_db_tests.cpp @@ -303,7 +303,7 @@ BOOST_AUTO_TEST_CASE(locks_out_branch_of_test) try { }; // root (block 10) - // / \ + // / \ (branches) // bsp11a bsp11b // | | // bsp12a bsp12b @@ -536,7 +536,7 @@ BOOST_AUTO_TEST_CASE(locks_out_branch_of_lib_advanced_past_shared_ancestor) try // root (block 10) // | // bsp11_shared (block 11) <-- shared ancestor; will be qc_target - // / \ + // / \ (branches) // bsp12a bsp12b (carries strong QC for 11) // | | // bsp13a_shared bsp13b (carries strong QC for 12, lib advances to 11) diff --git a/unittests/snapshot_tests.cpp b/unittests/snapshot_tests.cpp index ba962914f6..52c70affd1 100644 --- a/unittests/snapshot_tests.cpp +++ b/unittests/snapshot_tests.cpp @@ -1815,8 +1815,7 @@ BOOST_AUTO_TEST_CASE( snapshot_perf_benchmark ) // Large-scale benchmark of the two KV sections, which hold nearly all contract state. // // Build with RUN_PERF_BENCHMARKS defined for this file, then run: -// TMPDIR= ./unit_test --run_test=snapshot_part2_tests/snapshot_large_benchmark \ -// --log_level=message -- --sys-vm +// TMPDIR= ./unit_test --run_test=snapshot_part2_tests/snapshot_large_benchmark --log_level=message -- --sys-vm // // TMPDIR holds the mapped state and the snapshot, so a tmpfs would hide the file I/O and rule out KV_SNAP_BENCH_COLD. //