commit f66e98a34416cbf8f5a8bc7c8193de5382b38bc7
parent 58c63e037805555270aeedcd49dcb19673287f05
Author: Jared Tobin <jared@jtobin.io>
Date: Tue, 10 Feb 2026 14:07:49 +0400
fix: handle adds/subs and post-indexed stores for SP invalidation
- adds/subs now use updateWithSpCheck like add/sub
- Post-indexed stores ([sp], #imm) now clear the stack map
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat:
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/lib/Audit/AArch64/Taint.hs b/lib/Audit/AArch64/Taint.hs
@@ -121,8 +121,8 @@ transfer instr st = case instr of
-- Clear stack map if SP is modified (offsets become stale)
Add dst r1 op -> updateWithSpCheck dst (join2 (getTaint r1 st) (operandTaint op st)) st
Sub dst r1 op -> updateWithSpCheck dst (join2 (getTaint r1 st) (operandTaint op st)) st
- Adds dst r1 op -> setTaint dst (join2 (getTaint r1 st) (operandTaint op st)) st
- Subs dst r1 op -> setTaint dst (join2 (getTaint r1 st) (operandTaint op st)) st
+ Adds dst r1 op -> updateWithSpCheck dst (join2 (getTaint r1 st) (operandTaint op st)) st
+ Subs dst r1 op -> updateWithSpCheck dst (join2 (getTaint r1 st) (operandTaint op st)) st
Adc dst r1 r2 -> setTaint dst (join2 (getTaint r1 st) (getTaint r2 st)) st
Adcs dst r1 r2 -> setTaint dst (join2 (getTaint r1 st) (getTaint r2 st)) st
Sbc dst r1 r2 -> setTaint dst (join2 (getTaint r1 st) (getTaint r2 st)) st
@@ -250,18 +250,21 @@ updateWithSpCheck dst t st
| otherwise = setTaint dst t st
-- | Track a store to stack if address is [sp, #imm].
--- Pre-indexed addressing modifies SP, invalidating the stack map.
+-- Pre/post-indexed addressing modifies SP, invalidating the stack map.
storeToStack :: Reg -> AddrMode -> TaintState -> TaintState
storeToStack src addr st = case addr of
BaseImm SP imm -> setStackTaint (fromInteger imm) (getTaint src st) st
PreIndex SP imm ->
- -- Store first, then clear (SP changes after access)
+ -- Store at sp+imm, then SP changes
clearStackMap (setStackTaint (fromInteger imm) (getTaint src st) st)
+ PostIndex SP _ ->
+ -- Store at sp, then SP changes (offset 0)
+ clearStackMap (setStackTaint 0 (getTaint src st) st)
_ -> st -- Non-SP stores don't affect stack tracking
-- | Track a store pair to stack if address is [sp, #imm].
-- Stores src1 at offset and src2 at offset+8.
--- Pre-indexed addressing modifies SP, invalidating the stack map.
+-- Pre/post-indexed addressing modifies SP, invalidating the stack map.
storePairToStack :: Reg -> Reg -> AddrMode -> TaintState -> TaintState
storePairToStack src1 src2 addr st = case addr of
BaseImm SP imm ->
@@ -269,11 +272,16 @@ storePairToStack src1 src2 addr st = case addr of
in setStackTaint off (getTaint src1 st)
(setStackTaint (off + 8) (getTaint src2 st) st)
PreIndex SP imm ->
- -- Store first, then clear (SP changes after access)
+ -- Store at sp+imm and sp+imm+8, then SP changes
let off = fromInteger imm
st' = setStackTaint off (getTaint src1 st)
(setStackTaint (off + 8) (getTaint src2 st) st)
in clearStackMap st'
+ PostIndex SP _ ->
+ -- Store at sp and sp+8, then SP changes
+ let st' = setStackTaint 0 (getTaint src1 st)
+ (setStackTaint 8 (getTaint src2 st) st)
+ in clearStackMap st'
_ -> st
-- | Load from memory, handling special cases: