#34603 wallet: Fix detection of symlinks on Windows

ReviewabilityReviewsAgreementSize
#34603 achow101 wallet: Fix detection of symlinks on WindowsAuthor silent 159d0Strong30 + 27 tests
  • Detect symlinks properly on Windows builds
  • Prevents wallets from unintentionally traversing symlinked directories or misclassifying symlinks
  • Author has been silent for 121 days so reviews may wait long for a response
  • Concept approval with testing across MinGW, MSVC, and clang-cl on Windows 11 (molnard)
  • Approval without detailed rationale (sedited)
  • Resolved objection regarding redundant filesystem checks (luke-jr)
  • 30 lines added or modified outside tests
  • 27 lines added or modified in tests
  • 40 lines removed in total
  • 5 files, 4 commits
Utilities (logging, arguments, libraries)#30 of 59
P3 · platform fix
  • P3 because it provides a platform-specific filesystem helper to detect symlinks on Windows
  • It acts as a straightforward workaround for GCC libstdc++ limitations primarily serving wallet checks
  • Ranking pass: Moved up: a supported-platform filesystem defect ranks above internal refactors.
Wallet#38 of 92
P3 · bug fix
  • P3 because it fixes unintended recursive traversal of directory symlinks on Windows
  • Resolves platform discrepancies and restores functional test coverage for Windows wallet paths
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:

ReviewerTypeHarm, request, or questionStatusMust beAuthor repliedQuote
luke-jr (contributor)objection, maintenanceredundant filesystem checks by calling IsSymlink twicefixed · fix pushed · duplicate call eliminated in refactoring · v1, not yet re-checkedansweredyes2026-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

dossier JSON · extract JSON · model ledger, generated 2026-09-23T01:21, confidence high, input hash 04e707f9b2514f92
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