Skip to content

Fix KeyPath with 16-byte-aligned subscript traps on 32-bit targets#88725

Merged
MaxDesiatov merged 3 commits into
swiftlang:mainfrom
MaxDesiatov:maxd/32bit-keypath
Apr 30, 2026
Merged

Fix KeyPath with 16-byte-aligned subscript traps on 32-bit targets#88725
MaxDesiatov merged 3 commits into
swiftlang:mainfrom
MaxDesiatov:maxd/32bit-keypath

Conversation

@MaxDesiatov
Copy link
Copy Markdown
Contributor

@MaxDesiatov MaxDesiatov commented Apr 28, 2026

  • Explanation: Fixes a crash with key paths on 32-bit platforms reproducible for types that have 16-byte alignment.
    The intended bit layout of ComputedArgumentSize in KeyPath on 32-bit is:
 ┌───────┬───────────┐
 │ bits  │   field   │
 ├───────┼───────────┤
 │ 0–27  │ size      │
 ├───────┼───────────┤
 │ 28–29 │ padding   │
 ├───────┼───────────┤
 │ 30–31 │ alignment │
 └───────┴───────────┘

Currently, alignmentMask = 0x6000_0000, i.e. bits 29–30, not 30–31. It overlaps paddingMask (bits 28–29) at bit 29, meaning that alignment and padding unintentionally share a bit. With alignmentShift = 30, storing shift = 2 << 30 places 1 at bit 31, which the mask doesn't cover.

Correct value is 0xC000_0000 covers bits 30–31, which matches alignmentShift = 30 so both shift = 1 and shift = 2 round-trip, and it does not overlap with paddingMask = 0x3000_0000 (bits 28–29). It also mirrors the 64-bit layout (top bits of the word reserved for alignment, just 2 of them instead of 1).

  • Scope: Limited to 32-bit platforms.
  • Issues: rdar://175799967
  • Risk: Low due to increased test coverage.
  • Testing: Previously crashing on 32-bit platforms sample code is now added to the test suite.

@MaxDesiatov
Copy link
Copy Markdown
Contributor Author

@swift-ci smoke test

Comment thread test/stdlib/KeyPath32Bit.swift Outdated
Comment thread test/stdlib/KeyPath32Bit.swift Outdated
Co-authored-by: Max Desiatov <m_desiatov@apple.com>
@MaxDesiatov
Copy link
Copy Markdown
Contributor Author

@swift-ci smoke test linux

@MaxDesiatov
Copy link
Copy Markdown
Contributor Author

swiftlang/swift-package-manager#10002
@swift-ci smoke test linux

1 similar comment
@MaxDesiatov
Copy link
Copy Markdown
Contributor Author

swiftlang/swift-package-manager#10002
@swift-ci smoke test linux

@MaxDesiatov MaxDesiatov added 32 bit only WebAssembly Platform: WebAssembly labels Apr 29, 2026
@MaxDesiatov MaxDesiatov marked this pull request as ready for review April 29, 2026 20:51
@MaxDesiatov MaxDesiatov requested a review from a team as a code owner April 29, 2026 20:51
`test/stdlib/KeyPath32Bit.swift` crashes without this fix
rdar://175799967
@MaxDesiatov
Copy link
Copy Markdown
Contributor Author

@swift-ci smoke test

@MaxDesiatov MaxDesiatov requested a review from Azoy April 29, 2026 20:52
@MaxDesiatov MaxDesiatov changed the title KeyPath with 16-byte-aligned subscript argument traps on 32-bit targets Fix KeyPath with 16-byte-aligned subscript traps on 32-bit targets Apr 29, 2026
Copy link
Copy Markdown
Member

@kateinoigakukun kateinoigakukun left a comment

Choose a reason for hiding this comment

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

good catch!

@MaxDesiatov MaxDesiatov requested review from al45tair and tbkka April 29, 2026 20:57
@MaxDesiatov MaxDesiatov added bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. run-time crash Bug → crash: Swift code crashed during execution key paths Feature: key paths (both native and Objective-C) labels Apr 29, 2026
@MaxDesiatov
Copy link
Copy Markdown
Contributor Author

Verified that the test crashes without the fix in https://ci.swift.org/job/swift-PR-Linux-smoke-test/27272:

18:27:32  # executed command: /home/build-user/swift/utils/wasm-run.py /home/build-user/build/buildbot_linux/wasistdlib-linux-x86_64/test-wasi-wasm32/stdlib/Output/KeyPath32Bit.swift.tmp/a.out
18:27:32  # .---command stdout------------
18:27:32  # | [ RUN      ] KeyPath32Bit.appended keypath with 16-byte-aligned subscript argument
18:27:32  # `-----------------------------
18:27:32  # .---command stderr------------
18:27:32  # | Swift/UnsafeBufferPointer.swift:1207: Fatal error
18:27:32  # | Error: Trap: unreachable
18:27:32  # |     0: (0x00007f9ec9808c18) $ss17_assertionFailure__4file4line5flagss5NeverOs12StaticStringV_A2HSus6UInt32VtFySRys5UInt8VGXEfU_
18:27:32  # |     1: (0x00007f9ec979ceb8) $ss17_assertionFailure__4file4line5flagss5NeverOs12StaticStringV_A2HSus6UInt32VtF
18:27:32  # |     2: (0x00007f9ec980b2a8) $ss18_fatalErrorMessage__4file4line5flagss5NeverOs12StaticStringV_A2HSus6UInt32VtF
18:27:32  # |     3: (0x00007f9ec980a3d8) $ss7KeyPathC16_projectReadOnly4fromq_x_tFq_s0aB6BufferVXEfU0_q_SwXEfU0_TA
18:27:32  # |     4: (0x00007f9ec9810de0) $ss41_withUnprotectedUnsafeTemporaryAllocation9byteCount9alignment_xSi_SixSwq_YKXEtq_YKs5ErrorR_Ri_zr0_lFs6ResultOyxq_GBpXEfU_BpSiSwq_xRi_zRi0_zRi__Ri0__r0_lys5NeverOxIsgyrzr_AFyxAIGAIRs_Ri_zr0_lIetyygr_Tp5
18:27:32  # |     5: (0x00007f9ec96acdd8) $ss7KeyPathC16_projectReadOnly4fromq_x_tF
18:27:32  # |     6: (0x00007f9ec97ef740) swift_getAtKeyPath
18:27:32  # |     7: (0x00007f9ec97e9500) $s4mainyycfU_
18:27:32  # |     8: (0x00007f9ec97c0ce8) $s14StdlibUnittest9TestSuiteC04_runC04name9parameterySS_SiSgtF
18:27:32  # |     9: (0x00007f9ec97c73d0) $s14StdlibUnittest14_ParentProcessC10runOneTest04fullG4Name9testSuite0J00J9ParameterAC01_G6StatusOSS_AA0gK0CAL01_G0VSiSgtF
18:27:32  # |     10: (0x00007f9ec97a3238) $s14StdlibUnittest14_ParentProcessC3runyyF
18:27:32  # |     11: (0x00007f9ec96419f8) $s14StdlibUnittest11runAllTestsyyF
18:27:32  # |     12: (0x00007f9ec861b670) main
18:27:32  # |     13: (0x00007f9ec81ebb18) __main_void
18:27:32  # |     14: (0x00007f9ecf323738) _start
18:27:32  # | Traceback (most recent call last):
18:27:32  # |   File "/home/build-user/swift/utils/wasm-run.py", line 54, in <module>
18:27:32  # |     main()
18:27:32  # |   File "/home/build-user/swift/utils/wasm-run.py", line 50, in main
18:27:32  # |     runner.run(args)
18:27:32  # |   File "/home/build-user/swift/utils/wasm-run.py", line 24, in run
18:27:32  # |     subprocess.check_call(command)
18:27:32  # |   File "/usr/lib/python3.10/subprocess.py", line 369, in check_call
18:27:32  # |     raise CalledProcessError(retcode, cmd)
18:27:32  # | subprocess.CalledProcessError: Command '['wasmkit', 'run', '--env', 'SWIFT_DETERMINISTIC_HASHING=1', '--env', 'SWIFT_DEBUG_ENABLE_MALLOC_SCRIBBLE=YES', '--', '/home/build-user/build/buildbot_linux/wasistdlib-linux-x86_64/test-wasi-wasm32/stdlib/Output/KeyPath32Bit.swift.tmp/a.out']' returned non-zero exit status 1.
18:27:32  # `-----------------------------
18:27:32  # error: command failed with exit status: 1
[...]
18:32:00  Failed Tests (1):
18:32:00    Swift(wasi-wasm32) :: stdlib/KeyPath32Bit.swift

@MaxDesiatov MaxDesiatov enabled auto-merge (squash) April 29, 2026 22:05
@MaxDesiatov MaxDesiatov moved this to In Progress in Swift for Wasm Apr 29, 2026
@MaxDesiatov MaxDesiatov merged commit 5b97cb7 into swiftlang:main Apr 30, 2026
3 checks passed
@MaxDesiatov MaxDesiatov deleted the maxd/32bit-keypath branch April 30, 2026 03:25
@github-project-automation github-project-automation Bot moved this from In Progress to Done in Swift for Wasm Apr 30, 2026
@MaxDesiatov MaxDesiatov restored the maxd/32bit-keypath branch April 30, 2026 16:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

32 bit only bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. key paths Feature: key paths (both native and Objective-C) run-time crash Bug → crash: Swift code crashed during execution WebAssembly Platform: WebAssembly

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants