-
Notifications
You must be signed in to change notification settings - Fork 10.6k
Add the experimental attribute @sensitive
for struct declarations
#72850
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a980452
3097cce
ce33d47
1b1d5ed
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2825,6 +2825,20 @@ FUNCTION(ExceptionPersonality, | |
EFFECT(NoEffect), | ||
UNKNOWN_MEMEFFECTS) | ||
|
||
FUNCTION(ClearSensitive, swift_clearSensitive, C_CC, ClearSensitiveAvailability, | ||
RETURNS(VoidTy), | ||
ARGS(PtrTy, SizeTy), | ||
ATTRS(NoUnwind), | ||
EFFECT(NoEffect), | ||
UNKNOWN_MEMEFFECTS) | ||
|
||
FUNCTION(MemsetS, memset_s, C_CC, AlwaysAvailable, | ||
RETURNS(Int32Ty), | ||
ARGS(PtrTy, SizeTy, Int32Ty, SizeTy), | ||
ATTRS(NoUnwind), | ||
EFFECT(NoEffect), | ||
UNKNOWN_MEMEFFECTS) | ||
|
||
Comment on lines
+2835
to
+2841
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did you mean to leave the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, it's used as a fallback if the |
||
#undef RETURNS | ||
#undef ARGS | ||
#undef ATTRS | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1474,7 +1474,7 @@ void SignatureExpansion::expandExternalSignatureTypes() { | |
bool formalIndirectResult = FnType->getNumResults() > 0 && | ||
FnType->getSingleResult().isFormalIndirect(); | ||
assert( | ||
(cxxCtorDecl || !formalIndirectResult || returnInfo.isIndirect()) && | ||
(cxxCtorDecl || !formalIndirectResult || returnInfo.isIndirect() || SILResultTy.isSensitive()) && | ||
"swift and clang disagree on whether the result is returned indirectly"); | ||
#endif | ||
|
||
|
@@ -2392,10 +2392,6 @@ std::pair<llvm::Value *, llvm::Value *> irgen::getAsyncFunctionAndSize( | |
return {fn, size}; | ||
} | ||
|
||
static void externalizeArguments(IRGenFunction &IGF, const Callee &callee, | ||
Explosion &in, Explosion &out, | ||
TemporarySet &temporaries, bool isOutlined); | ||
|
||
namespace { | ||
|
||
class SyncCallEmission final : public CallEmission { | ||
|
@@ -2634,11 +2630,19 @@ class SyncCallEmission final : public CallEmission { | |
return; | ||
} | ||
|
||
// Get the natural IR type in the body of the function that makes | ||
// the call. This may be different than the IR type returned by the | ||
// call itself due to ABI type coercion. | ||
auto resultType = | ||
fnConv.getSILResultType(IGF.IGM.getMaximalTypeExpansionContext()); | ||
SILType resultType; | ||
if (convertDirectToIndirectReturn) { | ||
resultType = SILType::getPrimitiveObjectType( | ||
origFnType->getSingleResult().getReturnValueType( | ||
IGF.IGM.getSILModule(), origFnType, TypeExpansionContext::minimal())); | ||
} else { | ||
// Get the natural IR type in the body of the function that makes | ||
// the call. This may be different than the IR type returned by the | ||
// call itself due to ABI type coercion. | ||
resultType = | ||
fnConv.getSILResultType(IGF.IGM.getMaximalTypeExpansionContext()); | ||
} | ||
|
||
auto &nativeSchema = IGF.IGM.getTypeInfo(resultType).nativeReturnValueSchema(IGF.IGM); | ||
|
||
// For ABI reasons the result type of the call might not actually match the | ||
|
@@ -2654,6 +2658,10 @@ class SyncCallEmission final : public CallEmission { | |
result = | ||
IGF.coerceValue(result, expectedNativeResultType, IGF.IGM.DataLayout); | ||
} | ||
if (convertDirectToIndirectReturn) { | ||
IGF.Builder.CreateStore(result, indirectReturnAddress); | ||
return; | ||
} | ||
|
||
// Gather the values. | ||
Explosion nativeExplosion; | ||
|
@@ -3983,7 +3991,7 @@ Address getForwardableAlloca(const TypeInfo &TI, bool isForwardableArgument, | |
return TI.getAddressForPointer(alloca); | ||
} | ||
|
||
static void externalizeArguments(IRGenFunction &IGF, const Callee &callee, | ||
void CallEmission::externalizeArguments(IRGenFunction &IGF, const Callee &callee, | ||
Explosion &in, Explosion &out, | ||
TemporarySet &temporaries, | ||
bool isOutlined) { | ||
|
@@ -4020,11 +4028,26 @@ static void externalizeArguments(IRGenFunction &IGF, const Callee &callee, | |
|
||
bool formalIndirectResult = fnType->getNumResults() > 0 && | ||
fnType->getSingleResult().isFormalIndirect(); | ||
|
||
// If clang returns directly and swift returns indirectly, this must be a c++ | ||
// constructor call. In that case, skip the "self" param. | ||
if (!FI.getReturnInfo().isIndirect() && formalIndirectResult) | ||
firstParam += 1; | ||
if (!FI.getReturnInfo().isIndirect() && formalIndirectResult) { | ||
// clang returns directly and swift returns indirectly | ||
|
||
SILType returnTy = SILType::getPrimitiveObjectType( | ||
fnType->getSingleResult().getReturnValueType( | ||
IGF.IGM.getSILModule(), fnType, TypeExpansionContext::minimal())); | ||
|
||
if (returnTy.isSensitive()) { | ||
// Sensitive return types are represented as indirect return value in SIL, | ||
// but are returned as values (if small) in LLVM IR. | ||
assert(out.size() == 1 && "expect a single address for the return value"); | ||
llvm::Value *returnAddr = out.claimNext(); | ||
out.reset(); | ||
assert(returnAddr == indirectReturnAddress.getAddress()); | ||
convertDirectToIndirectReturn = true; | ||
} else { | ||
// This must be a constructor call. In that case, skip the "self" param. | ||
firstParam += 1; | ||
} | ||
} | ||
|
||
for (unsigned i = firstParam; i != paramEnd; ++i) { | ||
auto clangParamTy = FI.arg_begin()[i].type; | ||
|
@@ -4039,8 +4062,9 @@ static void externalizeArguments(IRGenFunction &IGF, const Callee &callee, | |
if (auto *padType = AI.getPaddingType()) | ||
out.add(llvm::UndefValue::get(padType)); | ||
|
||
const SILParameterInfo ¶mInfo = params[i - firstParam]; | ||
SILType paramType = silConv.getSILType( | ||
params[i - firstParam], IGF.IGM.getMaximalTypeExpansionContext()); | ||
paramInfo, IGF.IGM.getMaximalTypeExpansionContext()); | ||
|
||
bool isForwardableArgument = IGF.isForwardableArgument(i - firstParam); | ||
|
||
|
@@ -4060,6 +4084,35 @@ static void externalizeArguments(IRGenFunction &IGF, const Callee &callee, | |
continue; | ||
} | ||
|
||
bool passIndirectToDirect = paramInfo.isIndirectInGuaranteed() && paramType.isSensitive(); | ||
if (passIndirectToDirect) { | ||
llvm::Value *ptr = in.claimNext(); | ||
|
||
if (AI.getKind() == clang::CodeGen::ABIArgInfo::Indirect) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the case where the SIL claimed the C function took it We pass the pointer to a C function that that lowers that argument indirect. It depends on the platform ABI whether the callee may modify that memory or not. You need to create a temporary copy unless there would be some other guarantee in SIL that the SIL address passed to the C function call is not used after the call. |
||
// It's a large struct which is also passed indirectl in LLVM IR. | ||
// The C function (= the callee) is allowed to modify the memory used | ||
// for passing arguments, therefore we need to copy the argument value | ||
// to a temporary. | ||
// TODO: avoid the temporary if the SIL parameter value in memory is | ||
// not used anymore after the call. | ||
auto &ti = cast<LoadableTypeInfo>(IGF.getTypeInfo(paramType)); | ||
auto temp = ti.allocateStack(IGF, paramType, "indirect-temporary"); | ||
Address tempAddr = temp.getAddress(); | ||
temporaries.add({temp, paramType}); | ||
Address paramAddr = ti.getAddressForPointer(ptr); | ||
ti.initializeWithCopy(IGF, tempAddr, paramAddr, paramType, isOutlined); | ||
|
||
out.add(tempAddr.getAddress()); | ||
continue; | ||
} | ||
|
||
auto &ti = cast<LoadableTypeInfo>(IGF.getTypeInfo(paramType)); | ||
Explosion loadedValue; | ||
ti.loadAsCopy(IGF, ti.getAddressForPointer(ptr), loadedValue); | ||
in.transferInto(loadedValue, in.size()); | ||
in = std::move(loadedValue); | ||
} | ||
|
||
switch (AI.getKind()) { | ||
case clang::CodeGen::ABIArgInfo::Extend: { | ||
bool signExt = clangParamTy->hasSignedIntegerRepresentation(); | ||
|
@@ -4072,7 +4125,7 @@ static void externalizeArguments(IRGenFunction &IGF, const Callee &callee, | |
auto toTy = AI.getCoerceToType(); | ||
|
||
// Indirect parameters are bridged as Clang pointer types. | ||
if (silConv.isSILIndirect(params[i - firstParam])) { | ||
if (silConv.isSILIndirect(params[i - firstParam]) && !passIndirectToDirect) { | ||
assert(paramType.isAddress() && "SIL type is not an address?"); | ||
|
||
auto addr = in.claimNext(); | ||
|
@@ -4111,7 +4164,8 @@ static void externalizeArguments(IRGenFunction &IGF, const Callee &callee, | |
// preceeding the apply. | ||
if (isForwardableArgument && forwardFromAddr.isValid()) { | ||
ti.initializeWithTake(IGF, addr, forwardFromAddr, | ||
paramType.getAddressType(), isOutlined); | ||
paramType.getAddressType(), isOutlined, | ||
/*zeroizeIfSensitive=*/ true); | ||
(void)in.claim(ti.getSchema().size()); | ||
} else { | ||
ti.initialize(IGF, in, addr, isOutlined); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps this should be a stdlib-defined runtime function so different platforms can bring their own memset_s/memset_explicit/explicit_bzero/SecureZeroMemory
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. This makes sense