Fix ARM32 secure delegate bug (#13922)
authorJan Vorlicek <janvorli@microsoft.com>
Wed, 13 Sep 2017 00:30:55 +0000 (02:30 +0200)
committerJan Kotas <jkotas@microsoft.com>
Wed, 13 Sep 2017 00:30:55 +0000 (17:30 -0700)
This change fixes a bug that causes crashes when secure delegate is
invoked on ARM32 with legacy codegen. Register R4 was loaded with
indirection slot address and immediatelly marked as trashed, so the JIT
compiler reused it before the call that was supposed to have that value
in R4.
The fix was to move the reg trashing after the call.
There was also an incorrect marking of that address as EA_PTRSIZE
while it should be EA_BYREF, so I've fixed that too.

src/jit/codegenlegacy.cpp

index c39d174..091f3b1 100644 (file)
@@ -18660,12 +18660,20 @@ regMaskTP CodeGen::genCodeForCall(GenTreeCall* call, bool valUsed)
         firstTgtOffs = pInfo->offsetOfDelegateFirstTarget;
 
 #ifdef _TARGET_ARM_
+        // Ensure that we don't trash any of these registers if we have to load
+        // the helper call target into a register to invoke it.
+        regMaskTP regsUsed;
+
         if ((call->gtCallMoreFlags & GTF_CALL_M_SECURE_DELEGATE_INV))
         {
-            getEmitter()->emitIns_R_R_I(INS_add, EA_PTRSIZE, compiler->virtualStubParamInfo->GetReg(), regThis,
+            getEmitter()->emitIns_R_R_I(INS_add, EA_BYREF, compiler->virtualStubParamInfo->GetReg(), regThis,
                                         pInfo->offsetOfSecureDelegateIndirectCell);
             regTracker.rsTrackRegTrash(compiler->virtualStubParamInfo->GetReg());
+
+            // Ensure that the virtual stub param info register doesn't get reused before the call is taken
+            regSet.rsLockReg(compiler->virtualStubParamInfo->GetRegMask(), &regsUsed);
         }
+
 #endif // _TARGET_ARM_
 
         // Grab an available register to use for the CALL indirection
@@ -18689,6 +18697,13 @@ regMaskTP CodeGen::genCodeForCall(GenTreeCall* call, bool valUsed)
                                    INDEBUG_LDISASM_COMMA(sigInfo) NULL, // addr
                                    args, retSize, gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur,
                                    gcInfo.gcRegByrefSetCur, ilOffset, indCallReg);
+
+#ifdef _TARGET_ARM_
+        if ((call->gtCallMoreFlags & GTF_CALL_M_SECURE_DELEGATE_INV))
+        {
+            regSet.rsUnlockReg(compiler->virtualStubParamInfo->GetRegMask(), regsUsed);
+        }
+#endif // _TARGET_ARM_
     }
     else