Windows ARM64 (PE) `ontop_fcontext`: epilog deallocates 0xc0 of the 0xd0 bytes the prolog allocates — 16-byte SP skew, breaks /GS and SEH-based unwind on resume
まだ誰も着手していません。
評価
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 初心者へのやさしさ
- 72/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 静か
調査の方向性
src/asm/ontop_arm64_aapcs_pe_armasm.asm と src/asm/ontop_arm64_aapcs_pe_armclang.S の指定された行にあるエピローグから始め、プロローグおよび修正済みの jump_fcontext 実装と比較してください。利用可能であれば、Windows ARM64 環境で libs/context/test をビルドまたは実行してください。両方の PE 実装が issue に記載されたフレームサイズを一貫して復元すれば完了です。
索引モデルが issue の本文から書いたものです。
説明
Summary
Both PE-target ARM64 assembly implementations of ontop_fcontext
(src/asm/ontop_arm64_aapcs_pe_armasm.asm, MSVC ARMASM64 syntax, and
src/asm/ontop_arm64_aapcs_pe_armclang.S, Clang/GAS syntax) have an asymmetric
prolog/epilog: the prolog reserves 0xd0 (208) bytes of stack, but the epilog releases
only 0xc0 (192) before tail-jumping into the ontop-function. The missing 0x10 (16)
bytes are never reclaimed, so sp sits 16 bytes below where it should be for the
remainder of the resumed context's execution.
Confirmed present, byte-for-byte, on develop @ d2142b6925… (current HEAD as of this
report). Confirmed not present in either of the two structurally analogous,
already-correct siblings on the same target:
src/asm/jump_arm64_aapcs_pe_armasm.asm— symmetric,0xd0/0xd0.src/asm/ontop_arm64_aapcs_elf_gas.S(the ELF/GAS target'sontop_fcontext) —
symmetric,0xb0/0xb0(smaller frame: no Windows TEB/TIB save/restore, but internally
consistent).
This is a structural, input-independent skew — every invocation of the ontop path on
Windows ARM64 hits it, not a data-dependent corruption.
Where it bites: /GS and SEH-based unwind, downstream
ontop_fcontext is reached via a tail-jump (ret x2, not a call), and the
ontop-function it jumps to eventually returns via the target context's own restored
LR, back into that target's original suspended call site — a site that expects sp
restored to its pre-suspend value, exactly as the symmetric jump_fcontext epilog would
leave it. The asymmetric ontop_fcontext epilog leaves sp 16 bytes below that value
instead, for the remaining lifetime of the resumed frame.
Any caller built with /GS (MSVC, on by default) or -fstack-protector-all (Clang) that
stores a stack cookie in a frame which gets resumed via this path will have its
__security_check_cookie read the wrong stack slot on that frame's own exit, and fail
fast with STATUS_STACK_BUFFER_OVERRUN (0xc0000409) — a __fastfail, not a catchable
SEH/C++ exception. A related failure mode hits boost::context::fiber's
forced_unwind-driven teardown (which also uses the ontop path to inject an unwind
marker into the target context): Windows' _CxxFrameHandler3 walks frames using static
.pdata/.xdata unwind metadata that encodes each frame's expected SP delta, and a
frame that's silently 16 bytes off from that expectation can make the unwinder
misidentify frame boundaries mid-walk.
We hit this downstream, three vendoring hops removed from this repo: hermes-windows
(Microsoft's Windows fork of Meta's Hermes JS engine, used by react-native-windows)
vendors boost_1_86_0 wholesale, including this exact file pair, unmodified. On Windows
ARM64, running Hermes' interpreter on a custom fiber stack, this produces a deterministic
crash in a production React Native app under load (root-caused from 8 crash dumps across
2 engine builds and 4 ASLR bases — all module-relative-identical, confirming the
structural nature of the bug). Full writeup and a downstream fix for hermes-windows:
the companion downstream fix for hermes-windows (link added below once posted).
Anyone else running boost::context::fiber (or anything built on it — Boost.Fiber,
Boost.Coroutine2) on Windows ARM64 under /GS or -fstack-protector-all, exercising the
ontop/resume_with/fiber-teardown path under load, is exposed to the same defect.
History: where this was introduced
The asymmetry was introduced in
#201 "Windows arm64 fcontext support"
(merged 2022-07-05), specifically in commit abf8e04e23cf05a499594e674d1c90db39117662
("Spport Windows arm64 cpp exception", 2022-06-26). That commit extended the frame from
0xb0 to 0xd0 to save/restore four TEB fields (TeStackBase, TeStackLimit,
TeDeallocationStack, TeFiberData) so C++ exception unwinding sees a consistent TIB
across a fiber switch — a good and necessary change. It correctly rewired every other
offset in the function (the PC-save slot moved 0xa0→0xc0, the new TIB fields landed
at 0xa0/0xb0, the prolog's sub moved 0xb0→0xd0) but only bumped the epilog's
add from 0xb0 to 0xc0 — a 0x10 step, not the 0x20 step every other offset in
the same commit got. The diff (against
src/asm/ontop_arm64_aapcs_pe_armasm.asm) makes the off-by-one-constant plain:
ontop_fcontext proc BOOST_CONTEXT_EXPORT
; prepare stack for GP + FPU
- sub sp, sp, #0xb0
+ sub sp, sp, #0xd0
...
; save LR as PC
- str x30, [sp, #0xa0]
+ str x30, [sp, #0xc0]
+
+ ; save current stack base and limit
+ ldp x5, x6, [x18, #0x08]
+ stp x5, x6, [sp, #0xa0]
+ ; save current fiber data and deallocation stack
+ ldr x5, [x18, #0x1478]
+ ldr x6, [x18, #0x20]
+ stp x5, x6, [sp, #0xb0]
...
+ ; restore stack base and limit
+ ldp x5, x6, [sp, #0xa0]
+ stp x5, x6, [x18, #0x08]
+ ; restore fiber data and deallocation stack
+ ldp x5, x6, [sp, #0xb0]
+ str x5, [x18, #0x1478]
+ str x6, [x18, #0x20]
...
; skip pc
; restore stack from GP + FPU
- add sp, sp, #0xb0
+ add sp, sp, #0xc0
A second commit, e878e8edb2b2… ("Convert ARM64 armasm to armclang for Windows clang",
2024-06-19), mechanically transcribed this file's ARMASM64 syntax into the Clang/GAS
syntax now at src/asm/ontop_arm64_aapcs_pe_armclang.S, carrying the same 0x10
shortfall forward verbatim into the second file. Neither commit touched
jump_fcontext's analogous epilog, which is why it stayed correct throughout.
Proposed fix
Make the epilog symmetric with the prolog (add sp, sp, #0xd0) in both files, matching
jump_fcontext on the same target and ontop_fcontext on the ELF target. No other
register logic changes.
--- a/src/asm/ontop_arm64_aapcs_pe_armasm.asm
+++ b/src/asm/ontop_arm64_aapcs_pe_armasm.asm
@@ -122,7 +122,7 @@ ontop_fcontext proc BOOST_CONTEXT_EXPORT
; skip pc
; restore stack from GP + FPU
- add sp, sp, #0xc0
+ add sp, sp, #0xd0
; jump to ontop-function
ret x2
--- a/src/asm/ontop_arm64_aapcs_pe_armclang.S
+++ b/src/asm/ontop_arm64_aapcs_pe_armclang.S
@@ -128,7 +128,7 @@ ontop_fcontext:
// skip pc
// restore stack from GP + FPU
- add sp, sp, #0xc0
+ add sp, sp, #0xd0
// jump to ontop-function
ret x2
(Exact line numbers as of develop @ d2142b6925…: src/asm/ontop_arm64_aapcs_pe_armasm.asm
prolog at line 65, epilog at line 127; src/asm/ontop_arm64_aapcs_pe_armclang.S prolog
at line 71, epilog at line 133.)
Validation status
- Root cause: confirmed by direct inspection of
developHEAD (both files, both
currently0xd0/0xc0) and by disassembly of a downstream production crash (8 dumps,
hermes-windows on Windows ARM64 — see linked report above). The skew is structural and
input-independent: it does not depend on data, timing, or heap state, only on whether
theontoppath is taken. - Fix: validated by symmetry against the two already-correct sibling implementations in
this same file family (jump_fcontextPE variant,ontop_fcontextELF variant), and
independently against a downstream engine that carries an identical fix — see the
linked hermes-windows PR for that fix's own validation status (empirical repro or
build+inspection, whichever applies at time of reading). - We have not run this repo's own test suite (
libs/context/test) against the fix —
we don't have a boost ARM64-on-Windows test harness in our environment. If maintainers
want a PR rather than (or in addition to) this issue, we're happy to open one with the
diff above; it's a minimal, mechanical, two-line change and should be straightforward
to verify against existingBoost.Context/Boost.FiberARM64 CI if one exists.
- 主要言語
- Assembly
- スター
- 371
- フォーク
- 185
- 平均マージ
- 4日 13時間
- マージ済み PR(30日)
- 1
コントリビューションガイド
このリポジトリのコントリビューションガイドは索引されていません
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
boostorg/context のほかの issue
-
Support for the PAC オープン
難易度 5/5 1週間以上 初心者へのやさしさ 25/100
-
難易度 4/5 3〜5日 初心者へのやさしさ 45/100
-
難易度 3/5 1〜2日 初心者へのやさしさ 42/100
-
難易度 4/5 3〜5日 初心者へのやさしさ 35/100
-
難易度 4/5 3〜5日 初心者へのやさしさ 35/100
boostorg/context の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
-
module/agent platform/macos type/bug/regression
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
Azure/WALinuxAgent#3686 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100