Squashed 'src/ipc/libmultiprocess/' changes from 28e056576a..e8de5c7b68
What changed, and why it matters
This commit updates a helper library (libmultiprocess) used by Bitcoin Core. The only code change replaces a raw memory copy with a safer standard-library copy in a routine that converts byte arrays for inter-process communication. The rest is version bookkeeping and new test coverage. There is no indication this fixes an active security vulnerability; it is a defensive cleanup to silence an undefined-behavior sanitizer warning.
Treat as a routine dependency/subtree update. Review the upstream libmultiprocess PR #305 for the exact UBSan context, but no immediate security response is warranted based on this commit alone. Include in normal build/test validation.
Security signals we found
Replacement of memcpy with std::ranges::copy in byte-buffer serialization path
Commit message references a UBSan warning, suggesting prior undefined-behavior exposure during sanitiser builds
New regression tests for Data and std::map serialization round-trips
No vendor disclosure of security relevance or CVE linkage in commit or references
Evidence from the diff
The subtree bump pulls libmultiprocess from 28e056576a to e8de5c7b68. The functional code change is in include/mp/type-data.h: the Data builder initialization now uses std::ranges::copy instead of memcpy when copying a std::span of bytes into a capnp::Data::Builder. The commit message frames this as a refactor to ‘work around ubsan warn.’ Other changes are version bumps (12→13), documentation updates, and added test cases for map serialization and Data round-trips. No security advisory, CVE, or researcher attribution is present in the supplied materials.
Changed components
src/ipc/libmultiprocess/include/mp/type-data.hBitcoin Core IPC serialization layer (libmultiprocess subtree)Inspect captured patch +55 / −30
diff --git a/doc/versions.md b/doc/versions.md
index 83b5cf53..35ae76bd 100644
--- a/doc/versions.md
+++ b/doc/versions.md
@@ -7,11 +7,12 @@ Library versions are tracked with simple
Versioning policy is described in the [version.h](../include/mp/version.h)
include.
-## v12
+## v13
- Current unstable version.
-- Adds an optional per-listener `max_connections` parameter to `ListenConnections()`
- so servers can stop accepting new connections when a local connection cap is reached,
- and resume accepting after existing connections disconnect.
+
+## [v12.0](https://github.com/bitcoin-core/libmultiprocess/commits/v12.0)
+- Adds an optional `max_connections` parameter to `ListenConnections` ([#269](https://github.com/bitcoin-core/libmultiprocess/pull/269)).
+- Used in Bitcoin Core 32.x and newer releases with [#35684](https://github.com/bitcoin/bitcoin/pull/35684).
## [v11.0](https://github.com/bitcoin-core/libmultiprocess/commits/v11.0)
- Adds `makePool` method on `ThreadMap` to support thread pool routing, allowing requests without a specific client thread to be dispatched to a pool using a shortest-queue strategy ([#283](https://github.com/bitcoin-core/libmultiprocess/pull/283)).
@@ -24,76 +25,79 @@ include.
- Fixes a race condition in a log print detected by TSan ([#286](https://github.com/bitcoin-core/libmultiprocess/pull/286)).
- Build improvements: makes `target_capnp_sources` work correctly when libmultiprocess is used as a CMake subproject ([#289](https://github.com/bitcoin-core/libmultiprocess/pull/289)), adds `mp_headers` target for better lint tool support ([#291](https://github.com/bitcoin-core/libmultiprocess/pull/291)), and fixes compatibility with recent Nix and CMake 4.0 ([#238](https://github.com/bitcoin-core/libmultiprocess/pull/238)).
- Test, CI, documentation, and minor code improvements: design document corrections ([#278](https://github.com/bitcoin-core/libmultiprocess/pull/278)), field constant comments ([#279](https://github.com/bitcoin-core/libmultiprocess/pull/279)), clang-tidy fix ([#292](https://github.com/bitcoin-core/libmultiprocess/pull/292)), new smoke test for double-precision float values ([#294](https://github.com/bitcoin-core/libmultiprocess/pull/294)), new test for recursive async IPC calls ([#301](https://github.com/bitcoin-core/libmultiprocess/pull/301)), removal of libevent from Core CI builds ([#299](https://github.com/bitcoin-core/libmultiprocess/pull/299)), and rename of `EventLoop::m_num_clients` to `m_num_refs` ([#302](https://github.com/bitcoin-core/libmultiprocess/pull/302)).
-- Used in Bitcoin Core master branch, pulled in by [#35661](https://github.com/bitcoin/bitcoin/pull/35661).
+- Used in Bitcoin Core 32.x and newer releases with [#35661](https://github.com/bitcoin/bitcoin/pull/35661).
## [v10.0](https://github.com/bitcoin-core/libmultiprocess/commits/v10.0)
- Increases spawn test timeout to avoid spurious failures.
- Uses `throwRecoverableException` instead of raw `throw` to improve runtime error messages in macOS builds.
-- Used in Bitcoin Core master branch, pulled in by [#34977](https://github.com/bitcoin/bitcoin/pull/34977). Also pulled into Bitcoin Core 31.x stable branch by [#35028](https://github.com/bitcoin/bitcoin/pull/35028).
+- Used in Bitcoin Core 31.0rc3 and newer releases with [#34977](https://github.com/bitcoin/bitcoin/pull/34977) and backport [#35028](https://github.com/bitcoin/bitcoin/pull/35028).
## [v9.0](https://github.com/bitcoin-core/libmultiprocess/commits/v9.0)
- Fixes race conditions where worker thread could be used after destruction, where getParams() could be called after request cancel, and where m_on_cancel could be called after request finishes.
- Adds `CustomHasField` hook to map Cap'n Proto null values to C++ null values.
- Improves `CustomBuildField` for `std::optional` to use move semantics.
- Adds LLVM 22 compatibility fix in type-map.
-- Used in Bitcoin Core master branch, pulled in by [#34804](https://github.com/bitcoin/bitcoin/pull/34804). Also pulled into Bitcoin Core 31.x stable branch by [#34952](https://github.com/bitcoin/bitcoin/pull/34952).
+- Used in Bitcoin Core 31.0rc3 and newer releases with [#34804](https://github.com/bitcoin/bitcoin/pull/34804) and backport [#34952](https://github.com/bitcoin/bitcoin/pull/34952).
## [v8.0](https://github.com/bitcoin-core/libmultiprocess/commits/v8.0)
- Better support for non-libmultiprocess IPC clients: avoiding errors on unclean disconnects, and allowing simultaneous requests to worker threads which previously triggered "thread busy" errors.
-- Intermediate version used in Bitcoin Core master branch between 30.x and 31.x branches, pulled in by [#34422](https://github.com/bitcoin/bitcoin/pull/34422).
+- Used in Bitcoin Core 31.x and newer releases with [#34422](https://github.com/bitcoin/bitcoin/pull/34422).
## [v7.0](https://github.com/bitcoin-core/libmultiprocess/commits/v7.0)
- Adds SpawnProcess race fix, cmake `target_capnp_sources` option, ci and documentation improvements. Adds `version.h` header declaring major and minor version numbers.
-- Intermediate version used in Bitcoin Core master branch between 30.x and 31.x branches, pulled in by [#34363](https://github.com/bitcoin/bitcoin/pull/34363).
+- Used in Bitcoin Core 31.x and newer releases with [#34363](https://github.com/bitcoin/bitcoin/pull/34363).
## [v7.0-pre2](https://github.com/bitcoin-core/libmultiprocess/commits/v7.0-pre2)
- Fixes intermittent mptest hang and makes other minor improvements.
-- Used in Bitcoin Core 30.1 and 30.2 releases and 30.x branch, pulled in by [#33518](https://github.com/bitcoin/bitcoin/pull/33518) and [#33519](https://github.com/bitcoin/bitcoin/pull/33519).
+- Used in Bitcoin Core 30.1 and newer releases with [#33518](https://github.com/bitcoin/bitcoin/pull/33518) and backport [#33519](https://github.com/bitcoin/bitcoin/pull/33519).
## [v7.0-pre1](https://github.com/bitcoin-core/libmultiprocess/commits/v7.0-pre1)
- Adds support for log levels to reduce logging and "thread busy" error to avoid a crash on misuse.
-- Minimum required version since Bitcoin Core 30.1, pulled in by [#33412](https://github.com/bitcoin/bitcoin/pull/33412), [#33518](https://github.com/bitcoin/bitcoin/pull/33518), and [#33519](https://github.com/bitcoin/bitcoin/pull/33519).
+- Used in Bitcoin Core 30.1 and newer releases with [#33412](https://github.com/bitcoin/bitcoin/pull/33412) and [#33518](https://github.com/bitcoin/bitcoin/pull/33518) and backport [#33519](https://github.com/bitcoin/bitcoin/pull/33519).
+- Minimum required version since Bitcoin Core 30.1 due to [#33517](https://github.com/bitcoin/bitcoin/pull/33517) and backport [#33609](https://github.com/bitcoin/bitcoin/pull/33609).
## [v6.0](https://github.com/bitcoin-core/libmultiprocess/commits/v6.0)
- Adds CI scripts and build and test fixes.
-- Used in Bitcoin Core 30.0 release, pulled in by [#32345](https://github.com/bitcoin/bitcoin/pull/32345), [#33241](https://github.com/bitcoin/bitcoin/pull/33241), and [#33322](https://github.com/bitcoin/bitcoin/pull/33322).
+- Used in Bitcoin Core 30.x and newer releases with [#32345](https://github.com/bitcoin/bitcoin/pull/32345), [#33241](https://github.com/bitcoin/bitcoin/pull/33241), and [#33322](https://github.com/bitcoin/bitcoin/pull/33322).
## [v6.0-pre1](https://github.com/bitcoin-core/libmultiprocess/commits/v6.0-pre1)
- Adds fixes for unclean shutdowns and thread sanitizer issues.
- Drops `EventLoop::addClient` and `EventLoop::removeClient` methods,
requiring clients to use new `EventLoopRef` class instead.
-- Minimum required version for Bitcoin Core 30.0 release, pulled in by [#31741](https://github.com/bitcoin/bitcoin/pull/31741), [#32641](https://github.com/bitcoin/bitcoin/pull/32641), and [#32345](https://github.com/bitcoin/bitcoin/pull/32345).
+- Used in Bitcoin Core 30.x and newer releases with [#31741](https://github.com/bitcoin/bitcoin/pull/31741), [#32641](https://github.com/bitcoin/bitcoin/pull/32641), and [#32345](https://github.com/bitcoin/bitcoin/pull/32345).
+- Minimum required version since Bitcoin Core 30.0 due to [#32345](https://github.com/bitcoin/bitcoin/pull/32345).
## [v5.0](https://github.com/bitcoin-core/libmultiprocess/commits/v5.0)
- Adds build improvements and tidy/warning fixes.
-- Used in Bitcoin Core 29 releases, pulled in by [#31945](https://github.com/bitcoin/bitcoin/pull/31945).
+- Used in Bitcoin Core 29.x and newer releases with [#31945](https://github.com/bitcoin/bitcoin/pull/31945).
## [v5.0-pre1](https://github.com/bitcoin-core/libmultiprocess/commits/v5.0-pre1)
- Adds many improvements to Bitcoin Core mining interface: splitting up type headers, fixing shutdown bugs, adding subtree build support.
- Broke up `proxy-types.h` into `type-*.h` files requiring clients to explicitly
include overloads needed for C++ ↔️ Cap'n Proto type conversions.
- Now requires C++ 20 support.
-- Minimum required version for Bitcoin Core 29 releases, pulled in by [#30509](https://github.com/bitcoin/bitcoin/pull/30509), [#30510](https://github.com/bitcoin/bitcoin/pull/30510), [#31105](https://github.com/bitcoin/bitcoin/pull/31105), [#31740](https://github.com/bitcoin/bitcoin/pull/31740).
+- Used in Bitcoin Core 29.x and newer releases with [#30509](https://github.com/bitcoin/bitcoin/pull/30509), [#30510](https://github.com/bitcoin/bitcoin/pull/30510), [#31105](https://github.com/bitcoin/bitcoin/pull/31105), [#31740](https://github.com/bitcoin/bitcoin/pull/31740).
+- Minimum required version since Bitcoin Core 29.0 due to [#31740](https://github.com/bitcoin/bitcoin/pull/31740).
## [v4.0](https://github.com/bitcoin-core/libmultiprocess/commits/v4.0)
- Added better cmake support, installing cmake package files so clients do not
need to use pkgconfig.
-- Used in Bitcoin Core 28 releases, pulled in by [#30490](https://github.com/bitcoin/bitcoin/pull/30490) and [#30513](https://github.com/bitcoin/bitcoin/pull/30513).
+- Used in Bitcoin Core 28.x and newer releases with [#30490](https://github.com/bitcoin/bitcoin/pull/30490) and [#30513](https://github.com/bitcoin/bitcoin/pull/30513).
## [v3.0](https://github.com/bitcoin-core/libmultiprocess/commits/v3.0)
- Dropped compatibility with Cap'n Proto versions before 0.7.
-- Used in Bitcoin Core 27 releases, pulled in by [#28735](https://github.com/bitcoin/bitcoin/pull/28735), [#28907](https://github.com/bitcoin/bitcoin/pull/28907), and [#29276](https://github.com/bitcoin/bitcoin/pull/29276).
+- Used in Bitcoin Core 27.x and newer releases with [#28735](https://github.com/bitcoin/bitcoin/pull/28735), [#28907](https://github.com/bitcoin/bitcoin/pull/28907), and [#29276](https://github.com/bitcoin/bitcoin/pull/29276).
## [v2.0](https://github.com/bitcoin-core/libmultiprocess/commits/v2.0)
- Changed `PassField` function signature.
- Now requires C++17 support.
-- Used in Bitcoin Core 25 and 26 releases, pulled in by [#26672](https://github.com/bitcoin/bitcoin/pull/26672).
+- Used in Bitcoin Core 25.x and newer releases with [#26672](https://github.com/bitcoin/bitcoin/pull/26672).
## [v1.0](https://github.com/bitcoin-core/libmultiprocess/commits/v1.0)
- Dropped hardcoded includes in generated files, now requiring `include` and
`includeTypes` annotations.
-- Used in Bitcoin Core 22, 23, and 24 releases, pulled in by [#19160](https://github.com/bitcoin/bitcoin/pull/19160).
+- Used in Bitcoin Core 22.x and newer releases with [#19160](https://github.com/bitcoin/bitcoin/pull/19160).
## [v0.0](https://github.com/bitcoin-core/libmultiprocess/commits/v0.0)
- Initial version used in a downstream release.
-- Used in Bitcoin Core 21 releases, pulled in by [#16367](https://github.com/bitcoin/bitcoin/pull/16367), [#18588](https://github.com/bitcoin/bitcoin/pull/18588), and [#18677](https://github.com/bitcoin/bitcoin/pull/18677).
+- Used in Bitcoin Core 21.x and newer releases with [#16367](https://github.com/bitcoin/bitcoin/pull/16367), [#18588](https://github.com/bitcoin/bitcoin/pull/18588), and [#18677](https://github.com/bitcoin/bitcoin/pull/18677).
diff --git a/include/mp/type-data.h b/include/mp/type-data.h
index cdcdd30e..09c93df9 100644
--- a/include/mp/type-data.h
+++ b/include/mp/type-data.h
@@ -9,6 +9,7 @@
#include <concepts>
#include <span>
+#include <ranges>
namespace mp {
template <typename T, typename U>
@@ -33,7 +34,7 @@ requires (std::is_same_v<decltype(output.get()), ::capnp::Data::Builder> && IsBy
{
auto data = std::span{value};
auto result = output.init(data.size());
- memcpy(result.begin(), data.data(), data.size());
+ std::ranges::copy(data, result.begin());
}
template <typename LocalType, typename Input, typename ReadDest>
diff --git a/include/mp/version.h b/include/mp/version.h
index 4587a288..bbf54524 100644
--- a/include/mp/version.h
+++ b/include/mp/version.h
@@ -24,7 +24,7 @@
//! pointing at the prior merge commit. The /doc/versions.md file should also be
//! updated, noting any significant or incompatible changes made since the
//! previous version.
-#define MP_MAJOR_VERSION 12
+#define MP_MAJOR_VERSION 13
//! Minor version number. Should be incremented in stable branches after
//! backporting changes. The /doc/versions.md file should also be updated to
diff --git a/test/mp/test/foo.capnp b/test/mp/test/foo.capnp
index 31736452..9e6213fd 100644
--- a/test/mp/test/foo.capnp
+++ b/test/mp/test/foo.capnp
@@ -27,6 +27,7 @@ interface FooInterface $Proxy.wrap("mp::test::FooImplementation") {
callbackExtended @10 (context :Proxy.Context, callback :ExtendedCallback, arg: Int32) -> (result :Int32);
passCustom @11 (arg :FooCustom) -> (result :FooCustom);
passEmpty @12 (arg :FooEmpty) -> (result :FooEmpty);
+ passData @24 (arg :Data) -> (result :Data);
passMessage @13 (arg :FooMessage) -> (result :FooMessage);
passMutable @14 (arg :FooMutable) -> (arg :FooMutable);
passEnum @15 (arg :Int32) -> (result :Int32);
@@ -55,10 +56,11 @@ interface FooFn $Proxy.wrap("ProxyCallback<std::function<int()>>") {
struct FooStruct $Proxy.wrap("mp::test::FooStruct") {
name @0 :Text;
setInt @1 :List(Int32) $Proxy.name("set_int");
- vBool @2 :List(Bool) $Proxy.name("v_bool");
+ vectorBool @2 :List(Bool) $Proxy.name("vector_bool");
optionalInt @3 :Int32 $Proxy.name("optional_int");
hasOptionalInt @4 :Bool;
unorderedSetInt @5 :List(Int32) $Proxy.name("unordered_set_int");
+ mapStringInt @6 :List(StringIntPair) $Proxy.name("map_string_int");
}
struct FooCustom $Proxy.wrap("mp::test::FooCustom") {
@@ -81,3 +83,8 @@ struct Pair(T1, T2) {
first @0 :T1;
second @1 :T2;
}
+
+struct StringIntPair {
+ first @0 :Text;
+ second @1 :Int32;
+}
diff --git a/test/mp/test/foo.h b/test/mp/test/foo.h
index 5b66b85e..779c8db1 100644
--- a/test/mp/test/foo.h
+++ b/test/mp/test/foo.h
@@ -22,9 +22,10 @@ struct FooStruct
{
std::string name;
std::set<int> set_int;
- std::vector<bool> v_bool;
+ std::vector<bool> vector_bool;
std::optional<int> optional_int;
std::unordered_set<int> unordered_set_int;
+ std::map<std::string, int> map_string_int;
};
enum class FooEnum : uint8_t { ONE = 1, TWO = 2, };
@@ -83,6 +84,7 @@ public:
int callbackExtended(ExtendedCallback& callback, int arg) { return callback.callExtended(arg); }
FooCustom passCustom(FooCustom foo) { return foo; }
FooEmpty passEmpty(FooEmpty foo) { return foo; }
+ FooData passData(FooData foo) { return foo; }
FooMessage passMessage(FooMessage foo) { foo.message += " call"; return foo; }
void passMutable(FooMutable& foo) { foo.message += " call"; }
FooEnum passEnum(FooEnum foo) { return foo; }
diff --git a/test/mp/test/test.cpp b/test/mp/test/test.cpp
index 1fc30691..7a0940c8 100644
--- a/test/mp/test/test.cpp
+++ b/test/mp/test/test.cpp
@@ -23,6 +23,7 @@
#include <kj/memory.h>
#include <kj/string.h>
#include <kj/test.h>
+#include <map>
#include <memory>
#include <mp/proxy.h>
#include <mp/proxy.capnp.h>
@@ -157,10 +158,12 @@ KJ_TEST("Call FooInterface methods")
in.set_int.insert(1);
in.unordered_set_int.insert(2);
in.unordered_set_int.insert(1);
- in.v_bool.push_back(false);
- in.v_bool.push_back(true);
- in.v_bool.push_back(false);
+ in.vector_bool.push_back(false);
+ in.vector_bool.push_back(true);
+ in.vector_bool.push_back(false);
in.optional_int = 3;
+ in.map_string_int.emplace("a", 1);
+ in.map_string_int.emplace("b", 2);
FooStruct out = foo->pass(in);
KJ_EXPECT(in.name == out.name);
KJ_EXPECT(in.set_int.size() == out.set_int.size());
@@ -171,11 +174,16 @@ KJ_TEST("Call FooInterface methods")
for (const auto& elem : in.unordered_set_int) {
KJ_EXPECT(out.unordered_set_int.count(elem) == 1);
}
- KJ_EXPECT(in.v_bool.size() == out.v_bool.size());
- for (size_t i = 0; i < in.v_bool.size(); ++i) {
- KJ_EXPECT(in.v_bool[i] == out.v_bool[i]);
+ KJ_EXPECT(in.vector_bool.size() == out.vector_bool.size());
+ for (size_t i = 0; i < in.vector_bool.size(); ++i) {
+ KJ_EXPECT(in.vector_bool[i] == out.vector_bool[i]);
}
KJ_EXPECT(in.optional_int == out.optional_int);
+ KJ_EXPECT(in.map_string_int.size() == out.map_string_int.size());
+ for (auto init{in.map_string_int.begin()}, outit{out.map_string_int.begin()}; init != in.map_string_int.end() && outit != out.map_string_int.end(); ++init, ++outit) {
+ KJ_EXPECT(init->first == outit->first);
+ KJ_EXPECT(init->second == outit->second);
+ }
// Additional checks for std::optional member
KJ_EXPECT(foo->pass(in).optional_int == 3);
@@ -231,6 +239,9 @@ KJ_TEST("Call FooInterface methods")
foo->passEmpty(FooEmpty{});
+ FooData empty_data_out = foo->passData(FooData{});
+ KJ_EXPECT(empty_data_out.empty());
+
FooMessage message1;
message1.message = "init";
FooMessage message2{foo->passMessage(message1)};
Why this scored 19/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.