@@ -795,8 +795,6 @@ struct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> {
795
795
Value *ShadowBase, bool DoPoison);
796
796
void poisonAlloca (Value *V, uint64_t Size, IRBuilder<> &IRB, bool DoPoison);
797
797
798
- void SetShadowToStackAfterReturnInlined (IRBuilder<> &IRB, Value *ShadowBase,
799
- int Size);
800
798
Value *createAllocaForLayout (IRBuilder<> &IRB, const ASanStackFrameLayout &L,
801
799
bool Dynamic);
802
800
PHINode *createPHI (IRBuilder<> &IRB, Value *Cond, Value *ValueIfTrue,
@@ -1926,30 +1924,62 @@ void FunctionStackPoisoner::initializeCallbacks(Module &M) {
1926
1924
kAsanAllocasUnpoison , IRB.getVoidTy (), IntptrTy, IntptrTy, nullptr ));
1927
1925
}
1928
1926
1927
+ // If DoPoison is true function copies ShadowBytes into shadow memory.
1928
+ // If DoPoison is false function sets 0s into shadow memory.
1929
+ // Function assumes that if ShadowBytes[i] is 0, then corresponding shadow
1930
+ // memory is constant for duration of the function and it contains 0s. So we
1931
+ // will try to minimize writes into corresponding addresses of the real shadow
1932
+ // memory.
1929
1933
void FunctionStackPoisoner::poisonRedZones (ArrayRef<uint8_t > ShadowBytes,
1930
1934
IRBuilder<> &IRB, Value *ShadowBase,
1931
1935
bool DoPoison) {
1932
- size_t n = ShadowBytes.size ();
1933
- size_t i = 0 ;
1934
- // We need to (un)poison n bytes of stack shadow. Poison as many as we can
1935
- // using 64-bit stores (if we are on 64-bit arch), then poison the rest
1936
- // with 32-bit stores, then with 16-byte stores, then with 8-byte stores.
1937
- for (size_t LargeStoreSizeInBytes = ASan.LongSize / 8 ;
1938
- LargeStoreSizeInBytes != 0 ; LargeStoreSizeInBytes /= 2 ) {
1939
- for (; i + LargeStoreSizeInBytes - 1 < n; i += LargeStoreSizeInBytes) {
1940
- uint64_t Val = 0 ;
1941
- for (size_t j = 0 ; j < LargeStoreSizeInBytes; j++) {
1942
- if (F.getParent ()->getDataLayout ().isLittleEndian ())
1936
+ const size_t End = ShadowBytes.size ();
1937
+
1938
+ const size_t LargestStoreSizeInBytes =
1939
+ std::min<size_t >(sizeof (uint64_t ), ASan.LongSize / 8 );
1940
+
1941
+ const bool IsLittleEndian = F.getParent ()->getDataLayout ().isLittleEndian ();
1942
+
1943
+ // Poison given range in shadow using larges store size with out leading and
1944
+ // trailing zeros. Zeros never change, so they need neither poisoning nor
1945
+ // up-poisoning, but we don't mind if some of them get into a middle of a
1946
+ // store.
1947
+ for (size_t i = 0 ; i < End;) {
1948
+ if (!ShadowBytes[i]) {
1949
+ ++i;
1950
+ continue ;
1951
+ }
1952
+
1953
+ size_t StoreSizeInBytes = LargestStoreSizeInBytes;
1954
+ // Fit store size into the range.
1955
+ while (StoreSizeInBytes > End - i)
1956
+ StoreSizeInBytes /= 2 ;
1957
+
1958
+ // Minimize store size by trimming trailing zeros.
1959
+ for (size_t j = StoreSizeInBytes - 1 ; j && !ShadowBytes[i + j]; --j) {
1960
+ while (j <= StoreSizeInBytes / 2 )
1961
+ StoreSizeInBytes /= 2 ;
1962
+ }
1963
+
1964
+ uint64_t Val = 0 ;
1965
+ if (DoPoison) {
1966
+ for (size_t j = 0 ; j < StoreSizeInBytes; j++) {
1967
+ if (IsLittleEndian)
1943
1968
Val |= (uint64_t )ShadowBytes[i + j] << (8 * j);
1944
1969
else
1945
1970
Val = (Val << 8 ) | ShadowBytes[i + j];
1946
1971
}
1947
- if (!Val) continue ;
1948
- Value *Ptr = IRB.CreateAdd (ShadowBase, ConstantInt::get (IntptrTy, i));
1949
- Type *StoreTy = Type::getIntNTy (*C, LargeStoreSizeInBytes * 8 );
1950
- Value *Poison = ConstantInt::get (StoreTy, DoPoison ? Val : 0 );
1951
- IRB.CreateStore (Poison, IRB.CreateIntToPtr (Ptr, StoreTy->getPointerTo ()));
1972
+ assert (Val); // Impossible because ShadowBytes[i] != 0
1973
+ } else {
1974
+ Val = 0 ;
1952
1975
}
1976
+
1977
+ Value *Ptr = IRB.CreateAdd (ShadowBase, ConstantInt::get (IntptrTy, i));
1978
+ Value *Poison = IRB.getIntN (StoreSizeInBytes * 8 , Val);
1979
+ IRB.CreateStore (Poison,
1980
+ IRB.CreateIntToPtr (Ptr, Poison->getType ()->getPointerTo ()));
1981
+
1982
+ i += StoreSizeInBytes;
1953
1983
}
1954
1984
}
1955
1985
@@ -1963,26 +1993,6 @@ static int StackMallocSizeClass(uint64_t LocalStackSize) {
1963
1993
llvm_unreachable (" impossible LocalStackSize" );
1964
1994
}
1965
1995
1966
- // Set Size bytes starting from ShadowBase to kAsanStackAfterReturnMagic.
1967
- // We can not use MemSet intrinsic because it may end up calling the actual
1968
- // memset. Size is a multiple of 8.
1969
- // Currently this generates 8-byte stores on x86_64; it may be better to
1970
- // generate wider stores.
1971
- void FunctionStackPoisoner::SetShadowToStackAfterReturnInlined (
1972
- IRBuilder<> &IRB, Value *ShadowBase, int Size) {
1973
- assert (!(Size % 8 ));
1974
-
1975
- // kAsanStackAfterReturnMagic is 0xf5.
1976
- const uint64_t kAsanStackAfterReturnMagic64 = 0xf5f5f5f5f5f5f5f5ULL ;
1977
-
1978
- for (int i = 0 ; i < Size; i += 8 ) {
1979
- Value *p = IRB.CreateAdd (ShadowBase, ConstantInt::get (IntptrTy, i));
1980
- IRB.CreateStore (
1981
- ConstantInt::get (IRB.getInt64Ty (), kAsanStackAfterReturnMagic64 ),
1982
- IRB.CreateIntToPtr (p, IRB.getInt64Ty ()->getPointerTo ()));
1983
- }
1984
- }
1985
-
1986
1996
PHINode *FunctionStackPoisoner::createPHI (IRBuilder<> &IRB, Value *Cond,
1987
1997
Value *ValueIfTrue,
1988
1998
Instruction *ThenTerm,
@@ -2199,6 +2209,8 @@ void FunctionStackPoisoner::poisonStack() {
2199
2209
}
2200
2210
};
2201
2211
2212
+ SmallVector<uint8_t , 64 > ShadowBytesAfterReturn;
2213
+
2202
2214
// (Un)poison the stack before all ret instructions.
2203
2215
for (auto Ret : RetVec) {
2204
2216
IRBuilder<> IRBRet (Ret);
@@ -2225,8 +2237,11 @@ void FunctionStackPoisoner::poisonStack() {
2225
2237
IRBuilder<> IRBPoison (ThenTerm);
2226
2238
if (StackMallocIdx <= 4 ) {
2227
2239
int ClassSize = kMinStackMallocSize << StackMallocIdx;
2228
- SetShadowToStackAfterReturnInlined (IRBPoison, ShadowBase,
2229
- ClassSize >> Mapping.Scale );
2240
+ if ((int )ShadowBytesAfterReturn.size () != ClassSize) {
2241
+ ShadowBytesAfterReturn.resize (ClassSize,
2242
+ kAsanStackUseAfterReturnMagic );
2243
+ }
2244
+ poisonRedZones (ShadowBytesAfterReturn, IRBPoison, ShadowBase, true );
2230
2245
Value *SavedFlagPtrPtr = IRBPoison.CreateAdd (
2231
2246
FakeStack,
2232
2247
ConstantInt::get (IntptrTy, ClassSize - ASan.LongSize / 8 ));
0 commit comments