Skip to content

Conversation

hebasto
Copy link
Member

@hebasto hebasto commented Sep 18, 2025

In Bitcoin Core, the "MSan" CI jobs use the latest tagged Clang available from http://apt.llvm.org.

This PR applies similar changes and switches the "MSan" CI jobs to clang-snapshot.

This exposes problematic code that was reported in bitcoin/bitcoin#33284.

@hebasto
Copy link
Member Author

hebasto commented Sep 18, 2025

From https://github.com/bitcoin-core/secp256k1/actions/runs/17829295048/job/50691626826:

   CC       src/noverify_tests-tests.o
src/tests.c:6051:34: error: variable 'pubkey' is uninitialized when passed as a const pointer argument here [-Werror,-Wuninitialized-const-pointer]
 6051 |     SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey));
      |                                  ^~~~~~
1 error generated.

@hebasto hebasto marked this pull request as ready for review September 18, 2025 15:15
@hebasto
Copy link
Member Author

hebasto commented Sep 18, 2025

From https://github.com/bitcoin-core/secp256k1/actions/runs/17829295048/job/50691626826:

   CC       src/noverify_tests-tests.o
src/tests.c:6051:34: error: variable 'pubkey' is uninitialized when passed as a const pointer argument here [-Werror,-Wuninitialized-const-pointer]
 6051 |     SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey));
      |                                  ^~~~~~
1 error generated.

Added a commit to silence the -Wuninitialized-const-pointer warning.

@real-or-random
Copy link
Contributor

I think that's a Clang bug.

SECP256K1_CHECKMEM_UNDEFINE expands to __msan_allocated_memory with signature:

/* Tell MSan about newly allocated memory (ex.: custom allocator).
   Memory will be marked uninitialized, with origin at the call site. */
void SANITIZER_CDECL __msan_allocated_memory(const volatile void *data,
                                             size_t size);

https://github.com/llvm/llvm-project/blob/24b03d3217e41536cee7c868860b5930160ad526/compiler-rt/include/sanitizer/msan_interface.h#L93-L96

So yes, we're passing a const pointer to an uninitialized portion of memory, which is typically pointless: the callee can't read it (UB) and it is not allowed to write it either.

But __msan_allocated_memory is special in this regard. The call is meaningful. And since it's a part of the Clang runtime, Clang should understand that this is meaningful.

Are you willing to report this upstream?


On our side, I think there are some nicer options:

  1. Drop the call entirely (it's a noop because pubkey is already uninitialized). But it's easy to overlook in the future.
  2. Initialize the variable.
  3. Wrap the suppression inside the macro to make sure we always avoid this bug.

I tend to 3. It's perhaps the most complex option, but also the most future-proof?

@hebasto
Copy link
Member Author

hebasto commented Sep 19, 2025

I think that's a Clang bug.

I agree with your analysis. That's why I chose to suppress the warning rather than take another approach.

  1. Wrap the suppression inside the macro to make sure we always avoid this bug.

I tend to 3. It's perhaps the most complex option, but also the most future-proof?

That was my initial approach, but I didn’t manage to implement it properly. Could you suggest your patch?

@real-or-random
Copy link
Contributor

That was my initial approach, but I didn’t manage to implement it properly. Could you suggest your patch?

Can you try this in checkmem.h?

#if defined(__has_feature)
#  if __has_feature(memory_sanitizer)
#    include <sanitizer/msan_interface.h>
#    define SECP256K1_CHECKMEM_ENABLED 1
#    if defined(__clang__)
#      define SECP256K1_CHECKMEM_UNDEFINE(p, len) do { \
         _Pragma("clang diagnostic push") \
         _Pragma("clang diagnostic ignored \"-Wuninitialized-const-pointer\"") \
         __msan_allocated_memory((p), (len)); \
         _Pragma("clang diagnostic pop") \
         } while(0)
#    else
#      define SECP256K1_CHECKMEM_UNDEFINE(p, len) __msan_allocated_memory((p), (len))
#    endif
#    define SECP256K1_CHECKMEM_DEFINE(p, len) __msan_unpoison((p), (len))
#    define SECP256K1_CHECKMEM_MSAN_DEFINE(p, len) __msan_unpoison((p), (len))
#    define SECP256K1_CHECKMEM_CHECK(p, len) __msan_check_mem_is_initialized((p), (len))
#    define SECP256K1_CHECKMEM_RUNNING() (1)
#  endif
#endif

I think that's a Clang bug.

I agree with your analysis. That's why I chose to suppress the warning rather than take another approach.

Would you be willing to report it upstream? Perhaps it will be fixed before the release of clang 21 and then we'll be able to drop this workaround.

@hebasto
Copy link
Member Author

hebasto commented Sep 22, 2025

That was my initial approach, but I didn’t manage to implement it properly. Could you suggest your patch?

Can you try this in checkmem.h?

Thanks! Taken.

UPD. _Pragma(...) is a C99 feature.

Would you be willing to report it upstream?

llvm/llvm-project#160094.

Perhaps it will be fixed before the release of clang 21 and then we'll be able to drop this workaround.

https://github.com/llvm/llvm-project/releases/tag/llvmorg-21.1.1

@hebasto
Copy link
Member Author

hebasto commented Sep 22, 2025

The feedback from @real-or-random has been addressed.

@real-or-random
Copy link
Contributor

UPD. _Pragma(...) is a C99 feature.

Indeed. If I read correctly, clang has always supported it. https://clang.llvm.org/c_status.html

Copy link
Contributor

@real-or-random real-or-random left a comment

Choose a reason for hiding this comment

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

utACK mod nit

Copy link
Contributor

@real-or-random real-or-random left a comment

Choose a reason for hiding this comment

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

This PR is nice because it's an alternative to the Valgrind tests on clang-snapshot. That is, we can run the constant-time tests on clang-snapshot without Valgrind support.

MUSIG: 'yes'
ELLSWIFT: 'yes'
CC: 'clang'
CC: 'clang-snapshot'
Copy link
Contributor

Choose a reason for hiding this comment

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

Now that I think about it, why not run these three CI jobs on both clang and clang-snapshot?

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks! Reworked.

@hebasto
Copy link
Member Author

hebasto commented Oct 14, 2025

Rebased to resolve a conflict with the merged #1756 and taken @real-or-random's suggestion.

Copy link
Contributor

@real-or-random real-or-random left a comment

Choose a reason for hiding this comment

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

utACK ed9ea88 but let's see if CI succeeds

@hebasto
Copy link
Member Author

hebasto commented Oct 14, 2025

... but let's see if CI succeeds

"Old" clang doesn't understand "-Wuninitialized-const-pointer"...

@hebasto
Copy link
Member Author

hebasto commented Oct 14, 2025

... but let's see if CI succeeds

It's green now :)

Copy link
Contributor

@real-or-random real-or-random left a comment

Choose a reason for hiding this comment

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

utACK 53585f9

@real-or-random real-or-random merged commit a44a339 into bitcoin-core:master Oct 14, 2025
122 checks passed
@hebasto hebasto deleted the 250918-msan-ci branch October 14, 2025 11:39
fanquake added a commit to fanquake/bitcoin that referenced this pull request Oct 14, 2025
a44a339384 Merge bitcoin-core/secp256k1#1750: ci: Use clang-snapshot in "MSan" job
53585f93b7 ci: Use clang-snapshot in "MSan" job
6894c964f3 Fix Clang 21+ `-Wuninitialized-const-pointer` warning when using MSan
2b7337f63a Merge bitcoin-core/secp256k1#1756: ci: Fix image caching and apply other improvements
f163c35897 ci: Set `DEBIAN_FRONTEND=noninteractive`
70ae177ca0 ci: Bump `docker/build-push-action` version
b2a95a420f ci: Drop `tags` input for `docker/build-push-action`
122014edb3 ci: Add `scope` parameter to `cache-{to,from}` options
baa265429f Merge bitcoin-core/secp256k1#1727: docs: Clarify that callback can be called more than once
4d90585fea docs: Improve API docs of _context_set_illegal_callback
895f53d1cf docs: Clarify that callback can be called more than once
de6af6ae35 Merge bitcoin-core/secp256k1#1748: bench: improve context creation in ECDH benchmark
5817885153 Merge bitcoin-core/secp256k1#1749: build: Fix warnings in x86_64 assembly check
ab560078aa build: Fix warnings in x86_64 assembly check
10dab907e7 Merge bitcoin-core/secp256k1#1741: doc: clarify API doc of `secp256k1_ecdsa_recover` return value
dfe284ed2d bench: improve context creation in ECDH benchmark
7321bdf27b doc: clarify API doc of `secp256k1_ecdsa_recover` return value
b475654302 Merge bitcoin-core/secp256k1#1745: test: introduce group order byte-array constant for deduplication
0c91c56041 test: introduce group order byte-array constant for deduplication
88be4e8d86 Merge bitcoin-core/secp256k1#1735: musig: Invalidate secnonce in secp256k1_musig_partial_sign
36e76952cb Merge bitcoin-core/secp256k1#1738: check-abi: remove support for obsolete CMake library output location (src/libsecp256k1.so)
399b582a5f Split memclear into two versions
4985ac0f89 Merge bitcoin-core/secp256k1#1737: doc: mention ctx requirement for `_ellswift_create` (not secp256k1_context_static)
7ebaa134a7 check-abi: remove support for obsolete CMake library output location (src/libsecp256k1.so)
806de38bfc doc: mention ctx requirement for `_ellswift_create` (not secp256k1_context_static)
03fb60ad2e Merge bitcoin-core/secp256k1#1681: doc: Recommend clang-cl when building on Windows
d93380fb35 Merge bitcoin-core/secp256k1#1731: schnorrsig: Securely clear buf containing k or its negation
8113671f80 Merge bitcoin-core/secp256k1#1729: hash: Use size_t instead of int for RFC6979 outlen copy
325d65a8cf Rename and clear var containing k or -k
960ba5f9c6 Use size_t instead of int for RFC6979 outlen copy
737912430d ci: Add more tests for clang-cl
7379a5bed3 doc: Recommend clang-cl when building on Windows
f36afb8b3d Merge bitcoin-core/secp256k1#1725: tests: refactor tagged hash verification
5153cf1c91 tests: refactor tagged hash tests
d2dcf52091 Merge bitcoin-core/secp256k1#1726: docs: fix broken link to Tromer's cache.pdf paper
489a43d1bf docs: fix broken link to eprint cache.pdf paper
d599714147 Merge bitcoin-core/secp256k1#1722: docs: Exclude modules' `bench_impl.h` headers from coverage report
0458def51e doc: Add `--gcov-ignore-parse-errors=all` option to `gcovr` invocations
1aecce5936 doc: Add `--merge-mode-functions=separate` option to `gcovr` invocations
106a7cbf41 doc: Exclude modules' `bench_impl.h` headers from coverage report
a9e955d3ea autotools, docs: Adjust help string for `--enable-coverage` option
e523e4f90e Merge bitcoin-core/secp256k1#1720: chore(ci): Fix typo in Dockerfile comment
24ba8ff168 chore(ci): Fix typo in Dockerfile comment
74b8068c5d Merge bitcoin-core/secp256k1#1717: test: update wycheproof test vectors
c25c3c8a88 test: update wycheproof test vectors
20e3b44746 Merge bitcoin-core/secp256k1#1688: cmake: Avoid contaminating parent project's cache with `BUILD_SHARED_LIBS`
2c076d907a Merge bitcoin-core/secp256k1#1711: tests: update Wycheproof
7b07b22957 cmake: Avoid contaminating parent project's cache with BUILD_SHARED_LIBS
5433648ca0 Fix typos and spellings
9ea54c69b7 tests: update Wycheproof files

git-subtree-dir: src/secp256k1
git-subtree-split: a44a339384e1e4b1c0ed7fa59e2857b057f075bf
fanquake added a commit to fanquake/bitcoin that referenced this pull request Oct 15, 2025
d543c0d917 Merge bitcoin-core/secp256k1#1734: Introduce (mini) unit test framework
f44c1ebd96 Merge bitcoin-core/secp256k1#1719: ci: DRY workflow using anchors
a44a339384 Merge bitcoin-core/secp256k1#1750: ci: Use clang-snapshot in "MSan" job
15d014804e ci: Drop default for `inputs.command` in `run-in-docker-action`
1decc49a1f ci: Use YAML anchor and aliases for repeated "CI script" steps
dff1bc107d ci, refactor: Generalize use of `matrix.configuration.env_vars`
4b644da199 ci: Use YAML anchor and aliases for repeated "Print logs" steps
a889cd93df ci: Bump `actions/checkout` version
574c2f3080 ci: Use YAML anchor and aliases for repeated "Checkout" steps
53585f93b7 ci: Use clang-snapshot in "MSan" job
6894c964f3 Fix Clang 21+ `-Wuninitialized-const-pointer` warning when using MSan
2b7337f63a Merge bitcoin-core/secp256k1#1756: ci: Fix image caching and apply other improvements
f163c35897 ci: Set `DEBIAN_FRONTEND=noninteractive`
70ae177ca0 ci: Bump `docker/build-push-action` version
b2a95a420f ci: Drop `tags` input for `docker/build-push-action`
122014edb3 ci: Add `scope` parameter to `cache-{to,from}` options
2f4546ce56 test: add --log option to display tests execution
95b9953ea4 test: Add option to display all available tests
953f7b0088 test: support running specific tests/modules targets
0302c1a3d7 test: add --help for command-line options
9ec3bfe22d test: adapt modules to the new test infrastructure
48789dafc2 test: introduce (mini) unit test framework
baa265429f Merge bitcoin-core/secp256k1#1727: docs: Clarify that callback can be called more than once
4d90585fea docs: Improve API docs of _context_set_illegal_callback
895f53d1cf docs: Clarify that callback can be called more than once
de6af6ae35 Merge bitcoin-core/secp256k1#1748: bench: improve context creation in ECDH benchmark
5817885153 Merge bitcoin-core/secp256k1#1749: build: Fix warnings in x86_64 assembly check
ab560078aa build: Fix warnings in x86_64 assembly check
10dab907e7 Merge bitcoin-core/secp256k1#1741: doc: clarify API doc of `secp256k1_ecdsa_recover` return value
dfe284ed2d bench: improve context creation in ECDH benchmark
7321bdf27b doc: clarify API doc of `secp256k1_ecdsa_recover` return value
b475654302 Merge bitcoin-core/secp256k1#1745: test: introduce group order byte-array constant for deduplication
9cce703863 refactor: move 'gettime_i64()' to tests_common.h
0c91c56041 test: introduce group order byte-array constant for deduplication
88be4e8d86 Merge bitcoin-core/secp256k1#1735: musig: Invalidate secnonce in secp256k1_musig_partial_sign
36e76952cb Merge bitcoin-core/secp256k1#1738: check-abi: remove support for obsolete CMake library output location (src/libsecp256k1.so)
399b582a5f Split memclear into two versions
4985ac0f89 Merge bitcoin-core/secp256k1#1737: doc: mention ctx requirement for `_ellswift_create` (not secp256k1_context_static)
7ebaa134a7 check-abi: remove support for obsolete CMake library output location (src/libsecp256k1.so)
806de38bfc doc: mention ctx requirement for `_ellswift_create` (not secp256k1_context_static)
03fb60ad2e Merge bitcoin-core/secp256k1#1681: doc: Recommend clang-cl when building on Windows
d93380fb35 Merge bitcoin-core/secp256k1#1731: schnorrsig: Securely clear buf containing k or its negation
8113671f80 Merge bitcoin-core/secp256k1#1729: hash: Use size_t instead of int for RFC6979 outlen copy
325d65a8cf Rename and clear var containing k or -k
960ba5f9c6 Use size_t instead of int for RFC6979 outlen copy
737912430d ci: Add more tests for clang-cl
7379a5bed3 doc: Recommend clang-cl when building on Windows
f36afb8b3d Merge bitcoin-core/secp256k1#1725: tests: refactor tagged hash verification
5153cf1c91 tests: refactor tagged hash tests
d2dcf52091 Merge bitcoin-core/secp256k1#1726: docs: fix broken link to Tromer's cache.pdf paper
489a43d1bf docs: fix broken link to eprint cache.pdf paper
d599714147 Merge bitcoin-core/secp256k1#1722: docs: Exclude modules' `bench_impl.h` headers from coverage report
0458def51e doc: Add `--gcov-ignore-parse-errors=all` option to `gcovr` invocations
1aecce5936 doc: Add `--merge-mode-functions=separate` option to `gcovr` invocations
106a7cbf41 doc: Exclude modules' `bench_impl.h` headers from coverage report
a9e955d3ea autotools, docs: Adjust help string for `--enable-coverage` option
e523e4f90e Merge bitcoin-core/secp256k1#1720: chore(ci): Fix typo in Dockerfile comment
24ba8ff168 chore(ci): Fix typo in Dockerfile comment
74b8068c5d Merge bitcoin-core/secp256k1#1717: test: update wycheproof test vectors
c25c3c8a88 test: update wycheproof test vectors
20e3b44746 Merge bitcoin-core/secp256k1#1688: cmake: Avoid contaminating parent project's cache with `BUILD_SHARED_LIBS`
2c076d907a Merge bitcoin-core/secp256k1#1711: tests: update Wycheproof
7b07b22957 cmake: Avoid contaminating parent project's cache with BUILD_SHARED_LIBS
5433648ca0 Fix typos and spellings
9ea54c69b7 tests: update Wycheproof files

git-subtree-dir: src/secp256k1
git-subtree-split: d543c0d917a76a201578948701cc30ef336e0fe6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants