#34603 wallet: Fix detection of symlinks on Windows
| Reviewability | Reviews | Agreement | Size | |||||||
|---|---|---|---|---|---|---|---|---|---|---|
| #34603 wallet: Fix detection of symlinks on Windows | Author silent 159d | 0 | Strong | 30 + 27 tests | ||||||
|
|
|
| |||||||
Reviewability: ReadyStalePaused Agreement: StrongPositivePositive w/ caveatsNeutralMildDisputedBlockedCrickets Reviews: current code-review ACKs, then (+stale ACKs) and -NACKs; greener = more ACKs. Size: lines added or modified outside tests, then in tests; greener = smaller. | ||||||||||
Goal
Adds an `IsSymlink` filesystem helper that checks for `FILE_ATTRIBUTE_REPARSE_POINT` on Windows while delegating to `std::filesystem::is_symlink` on other platforms. It uses this helper in `ListDatabases` to prevent recursively traversing symlinked directories on Windows, and in `GetWalletPath` to reject symlinks passed as wallet files. It also re-enables symlink test coverage on Windows in `wallet_multiwallet.py`.
Problem: GCC's `libstdc++` on Windows does not implement symlink detection. Because of this, Windows builds fail to identify symlinks in wallet paths, allowing `ListDatabases` to follow directory symlinks unintentionally and causing `GetWalletPath` to misclassify file symlinks as regular files.
Evidence of importance:
- The PR references GCC's `libstdc++` source where Windows symlink detection remains a FIXME, causing `std::filesystem::is_symlink` and recursive directory iterators to fail on Windows cross-builds.
- Previously, `wallet_multiwallet.py` explicitly disabled symlink tests under Windows because symlink detection did not work as expected on cross-built Windows binaries.
Reviewability
Stale · Author silent 159d
No author activity for 159 days; a review may wait a long time for a response.
Waiting on (from the thread read):
- author: response to molnard's suggestion to add a nested-wallet junction test case 2026-09-22
- reviewer: review from hebasto after ping 2026-09-22
Agreement
Strong
substantive support, no open objection (molnard)
Thread notes: Added molnard's Concept ACK with Windows 11 testing across MinGW, MSVC, and clang-cl. Noted pending review from hebasto following sedited's ping and author response to molnard's test suggestion.
Objections, suggestions, and questions:
| Reviewer | Type | Harm, request, or question | Status | Must be | Author replied | Quote |
|---|---|---|---|---|---|---|
| luke-jr (contributor) | objection, maintenance | redundant filesystem checks by calling IsSymlink twice | fixed · fix pushed · duplicate call eliminated in refactoring · v1, not yet re-checked | answered | yes | 2026-02-18: 'This calls IsSymlink twice in some cases.' Status from: 2026-02-24: achow101: 'No longer relevant with https://github.com/bitcoin/bitcoin/pull/34603#discussion_r2824027663' |
Support:
- sedited (member) (ACK, 2026-06-07): The changes seem fine to me, but I would suggest adding a note in the description about hebasto's comment https://github.com/bitcoin/bitcoin/pull/34603#discussion_r2822782155 about why we're gating WI [not substantive]
- molnard (none) (Concept ACK, 2026-09-22) [tested: test/functional/wallet_multiwallet.py]: tested tip against base on Windows 11 across MinGW/GCC, MSVC, and clang-cl, confirming that recursive descent into junction subdirectories is resolved on MinGW while multiwallet tests pass
Participants:
- fanquake (member, question, 1 statements 2026-02-17 to 2026-02-17): asked whether symlinks work with LLVM/Clang on Windows
- hebasto (member, question, 3 statements 2026-02-18 to 2026-02-18): explained MSVC/clang-cl symlink and junction behavior, and asked if reparse point tags should be filtered
- luke-jr (contributor, objection, 5 statements 2026-02-18 to 2026-02-18): noted redundant IsSymlink calls and unnecessary directory checks, which were removed
- maflcko (member, neutral, 1 statements 2026-03-16 to 2026-03-16): spelling and capitalization nits
- sedited (member, support, 2 statements 2026-06-07 to 2026-09-22): utACKed and pinged hebasto for review
- molnard (none, support, 2 statements 2026-09-22 to 2026-09-22): cACK; tested on Windows 11 across MinGW, MSVC, and clang-cl, confirming the fix and suggesting an additional test case
Files
66 lines under test/bench/ci.
- test/functional/wallet_multiwallet.py +27/-39
- src/util/fs_helpers.cpp +14/-0
- src/util/fs_helpers.h +7/-0
- src/wallet/db.cpp +6/-0
- src/wallet/wallet.cpp +3/-1
Card
The short text the ranking pass compares across PRs.
Adds Windows symlink and reparse point detection via the Win32 API to work around GCC libstdc++'s lack of Windows symlink support. This fixes wallet directory traversal in ListDatabases so it avoids recursing into directory symlinks on Windows, and ensures GetWalletPath rejects symlinks to wallet files. It re-enables previously skipped symlink test assertions in the multiwallet functional test suite on Windows.
Data
thread read through 2026-09-22 (23 statements), head b127cde3f4
Discussion read under schema 1 rules: suggestions and questions may be missing, and an objection may combine several harms (schema history).
labels: Wallet
Categories
Utilities (logging, arguments, libraries)
P3 · platform fix (ranking pass: Moved up: a supported-platform filesystem defect ranks above internal refactors.)
Adds a platform-specific filesystem primitive to correctly detect symlinks on Windows. While useful shared infrastructure, the utility function is straightforward and primarily created to serve wallet path checks.
Membership: Adds a new `IsSymlink` filesystem helper in `src/util/fs_helpers.cpp` and `src/util/fs_helpers.h` to work around MinGW/GCC `libstdc++` limitations on Windows.
Factors: security/stability 1, bug 1, performance 0, user value 1, leverage 0
Wallet
P3 · bug fix
Fixes Windows wallet path resolution where missing symlink detection causes `ListDatabases` to recursively traverse symlinked directories and `GetWalletPath` to treat symlinks as regular files. This resolves an ongoing platform inconsistency that previously required disabling multiwallet symlink tests on Windows.
Membership: Carries the Wallet label, modifies `src/wallet/db.cpp` and `src/wallet/wallet.cpp`, and updates `test/functional/wallet_multiwallet.py`.
Factors: security/stability 1, bug 1, performance 0, user value 1, leverage 0