Skip to content

Commit e0b469f

Browse files
committed
[clang-cl][sanitizer] Add -fsanitize-address-use-after-return to clang.
Also: - add driver test (fsanitize-use-after-return.c) - add basic IR test (asan-use-after-return.cpp) - (NFC) cleaned up logic for generating table of __asan_stack_malloc depending on flag. for issue: google/sanitizers#1394 Reviewed By: vitalybuka Differential Revision: https://reviews.llvm.org/D104076
1 parent c0c5a98 commit e0b469f

File tree

12 files changed

+193
-53
lines changed

12 files changed

+193
-53
lines changed

clang/include/clang/Basic/CodeGenOptions.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,10 @@ CODEGENOPT(NewStructPathTBAA , 1, 0) ///< Whether or not to use enhanced struct-
212212
CODEGENOPT(SaveTempLabels , 1, 0) ///< Save temporary labels.
213213
CODEGENOPT(SanitizeAddressUseAfterScope , 1, 0) ///< Enable use-after-scope detection
214214
///< in AddressSanitizer
215+
ENUM_CODEGENOPT(SanitizeAddressUseAfterReturn,
216+
llvm::AsanDetectStackUseAfterReturnMode, 2,
217+
llvm::AsanDetectStackUseAfterReturnMode::Runtime
218+
) ///< Set detection mode for stack-use-after-return.
215219
CODEGENOPT(SanitizeAddressPoisonCustomArrayCookie, 1,
216220
0) ///< Enable poisoning operator new[] which is not a replaceable
217221
///< global allocation function in AddressSanitizer

clang/include/clang/Basic/Sanitizers.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,12 @@ StringRef AsanDtorKindToString(llvm::AsanDtorKind kind);
192192

193193
llvm::AsanDtorKind AsanDtorKindFromString(StringRef kind);
194194

195+
StringRef AsanDetectStackUseAfterReturnModeToString(
196+
llvm::AsanDetectStackUseAfterReturnMode mode);
197+
198+
llvm::AsanDetectStackUseAfterReturnMode
199+
AsanDetectStackUseAfterReturnModeFromString(StringRef modeStr);
200+
195201
} // namespace clang
196202

197203
#endif // LLVM_CLANG_BASIC_SANITIZERS_H

clang/include/clang/Driver/Options.td

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1587,6 +1587,16 @@ defm sanitize_address_use_after_scope : BoolOption<"f", "sanitize-address-use-af
15871587
PosFlag<SetTrue, [], "Enable">, NegFlag<SetFalse, [CoreOption, NoXarchOption], "Disable">,
15881588
BothFlags<[], " use-after-scope detection in AddressSanitizer">>,
15891589
Group<f_clang_Group>;
1590+
def sanitize_address_use_after_return_EQ
1591+
: Joined<["-"], "fsanitize-address-use-after-return=">,
1592+
MetaVarName<"<mode>">,
1593+
Flags<[CC1Option]>,
1594+
HelpText<"Select the mode of detecting stack use-after-return in AddressSanitizer">,
1595+
Group<f_clang_Group>,
1596+
Values<"never,runtime,always">,
1597+
NormalizedValuesScope<"llvm::AsanDetectStackUseAfterReturnMode">,
1598+
NormalizedValues<["Never", "Runtime", "Always"]>,
1599+
MarshallingInfoEnum<CodeGenOpts<"SanitizeAddressUseAfterReturn">, "Runtime">;
15901600
defm sanitize_address_poison_custom_array_cookie : BoolOption<"f", "sanitize-address-poison-custom-array-cookie",
15911601
CodeGenOpts<"SanitizeAddressPoisonCustomArrayCookie">, DefaultFalse,
15921602
PosFlag<SetTrue, [], "Enable">, NegFlag<SetFalse, [], "Disable">,

clang/include/clang/Driver/SanitizerArgs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "clang/Driver/Types.h"
1313
#include "llvm/Option/Arg.h"
1414
#include "llvm/Option/ArgList.h"
15+
#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
1516
#include <string>
1617
#include <vector>
1718

@@ -58,6 +59,8 @@ class SanitizerArgs {
5859
bool ImplicitCfiRuntime = false;
5960
bool NeedsMemProfRt = false;
6061
bool HwasanUseAliases = false;
62+
llvm::AsanDetectStackUseAfterReturnMode AsanUseAfterReturn =
63+
llvm::AsanDetectStackUseAfterReturnMode::Invalid;
6164

6265
public:
6366
/// Parses the sanitizer arguments from an argument list.

clang/lib/Basic/Sanitizers.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,28 @@ llvm::AsanDtorKind AsanDtorKindFromString(StringRef kindStr) {
8888
.Default(llvm::AsanDtorKind::Invalid);
8989
}
9090

91+
StringRef AsanDetectStackUseAfterReturnModeToString(
92+
llvm::AsanDetectStackUseAfterReturnMode mode) {
93+
switch (mode) {
94+
case llvm::AsanDetectStackUseAfterReturnMode::Always:
95+
return "always";
96+
case llvm::AsanDetectStackUseAfterReturnMode::Runtime:
97+
return "runtime";
98+
case llvm::AsanDetectStackUseAfterReturnMode::Never:
99+
return "never";
100+
case llvm::AsanDetectStackUseAfterReturnMode::Invalid:
101+
return "invalid";
102+
}
103+
return "invalid";
104+
}
105+
106+
llvm::AsanDetectStackUseAfterReturnMode
107+
AsanDetectStackUseAfterReturnModeFromString(StringRef modeStr) {
108+
return llvm::StringSwitch<llvm::AsanDetectStackUseAfterReturnMode>(modeStr)
109+
.Case("always", llvm::AsanDetectStackUseAfterReturnMode::Always)
110+
.Case("runtime", llvm::AsanDetectStackUseAfterReturnMode::Runtime)
111+
.Case("never", llvm::AsanDetectStackUseAfterReturnMode::Never)
112+
.Default(llvm::AsanDetectStackUseAfterReturnMode::Invalid);
113+
}
114+
91115
} // namespace clang

clang/lib/CodeGen/BackendUtil.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
#include "llvm/Transforms/InstCombine/InstCombine.h"
6666
#include "llvm/Transforms/Instrumentation.h"
6767
#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
68+
#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
6869
#include "llvm/Transforms/Instrumentation/BoundsChecking.h"
6970
#include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h"
7071
#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
@@ -288,8 +289,10 @@ static void addAddressSanitizerPasses(const PassManagerBuilder &Builder,
288289
bool UseOdrIndicator = CGOpts.SanitizeAddressUseOdrIndicator;
289290
bool UseGlobalsGC = asanUseGlobalsGC(T, CGOpts);
290291
llvm::AsanDtorKind DestructorKind = CGOpts.getSanitizeAddressDtor();
292+
llvm::AsanDetectStackUseAfterReturnMode UseAfterReturn =
293+
CGOpts.getSanitizeAddressUseAfterReturn();
291294
PM.add(createAddressSanitizerFunctionPass(/*CompileKernel*/ false, Recover,
292-
UseAfterScope));
295+
UseAfterScope, UseAfterReturn));
293296
PM.add(createModuleAddressSanitizerLegacyPassPass(
294297
/*CompileKernel*/ false, Recover, UseGlobalsGC, UseOdrIndicator,
295298
DestructorKind));
@@ -298,7 +301,8 @@ static void addAddressSanitizerPasses(const PassManagerBuilder &Builder,
298301
static void addKernelAddressSanitizerPasses(const PassManagerBuilder &Builder,
299302
legacy::PassManagerBase &PM) {
300303
PM.add(createAddressSanitizerFunctionPass(
301-
/*CompileKernel*/ true, /*Recover*/ true, /*UseAfterScope*/ false));
304+
/*CompileKernel*/ true, /*Recover*/ true, /*UseAfterScope*/ false,
305+
/*UseAfterReturn*/ llvm::AsanDetectStackUseAfterReturnMode::Never));
302306
PM.add(createModuleAddressSanitizerLegacyPassPass(
303307
/*CompileKernel*/ true, /*Recover*/ true, /*UseGlobalsGC*/ true,
304308
/*UseOdrIndicator*/ false));
@@ -1144,12 +1148,14 @@ static void addSanitizers(const Triple &TargetTriple,
11441148
bool UseOdrIndicator = CodeGenOpts.SanitizeAddressUseOdrIndicator;
11451149
llvm::AsanDtorKind DestructorKind =
11461150
CodeGenOpts.getSanitizeAddressDtor();
1151+
llvm::AsanDetectStackUseAfterReturnMode UseAfterReturn =
1152+
CodeGenOpts.getSanitizeAddressUseAfterReturn();
11471153
MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
11481154
MPM.addPass(ModuleAddressSanitizerPass(
11491155
CompileKernel, Recover, ModuleUseAfterScope, UseOdrIndicator,
11501156
DestructorKind));
1151-
MPM.addPass(createModuleToFunctionPassAdaptor(
1152-
AddressSanitizerPass(CompileKernel, Recover, UseAfterScope)));
1157+
MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass(
1158+
CompileKernel, Recover, UseAfterScope, UseAfterReturn)));
11531159
}
11541160
};
11551161
ASanPass(SanitizerKind::Address, false);

clang/lib/Driver/SanitizerArgs.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "llvm/Support/SpecialCaseList.h"
1919
#include "llvm/Support/TargetParser.h"
2020
#include "llvm/Support/VirtualFileSystem.h"
21+
#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
2122
#include <memory>
2223

2324
using namespace clang;
@@ -841,6 +842,18 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
841842
AsanDtorKind = parsedAsanDtorKind;
842843
}
843844

845+
if (const auto *Arg = Args.getLastArg(
846+
options::OPT_sanitize_address_use_after_return_EQ)) {
847+
auto parsedAsanUseAfterReturn =
848+
AsanDetectStackUseAfterReturnModeFromString(Arg->getValue());
849+
if (parsedAsanUseAfterReturn ==
850+
llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
851+
TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)
852+
<< Arg->getOption().getName() << Arg->getValue();
853+
}
854+
AsanUseAfterReturn = parsedAsanUseAfterReturn;
855+
}
856+
844857
} else {
845858
AsanUseAfterScope = false;
846859
// -fsanitize=pointer-compare/pointer-subtract requires -fsanitize=address.
@@ -1112,6 +1125,12 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
11121125
AsanDtorKindToString(AsanDtorKind)));
11131126
}
11141127

1128+
if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
1129+
CmdArgs.push_back(Args.MakeArgString(
1130+
"-fsanitize-address-use-after-return=" +
1131+
AsanDetectStackUseAfterReturnModeToString(AsanUseAfterReturn)));
1132+
}
1133+
11151134
if (!HwasanAbi.empty()) {
11161135
CmdArgs.push_back("-default-function-attr");
11171136
CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi));
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - -triple x86_64-linux %s \
2+
// RUN: | FileCheck %s --check-prefixes=CHECK-RUNTIME \
3+
// RUN: --implicit-check-not="__asan_stack_malloc_always_"
4+
// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - -triple x86_64-linux %s \
5+
// RUN: -fsanitize-address-use-after-return=runtime \
6+
// RUN: | FileCheck %s --check-prefixes=CHECK-RUNTIME \
7+
// RUN: --implicit-check-not="__asan_stack_malloc_always_"
8+
// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - -triple x86_64-linux %s \
9+
// RUN: -fsanitize-address-use-after-return=always \
10+
// RUN: | FileCheck %s --check-prefixes=CHECK-ALWAYS \
11+
// RUN: --implicit-check-not=__asan_option_detect_stack_use_after_return \
12+
// RUN: --implicit-check-not="__asan_stack_malloc_{{[0-9]}}"
13+
// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - -triple x86_64-linux %s \
14+
// RUN: -fsanitize-address-use-after-return=never \
15+
// RUN: | FileCheck %s \
16+
// RUN: --implicit-check-not=__asan_option_detect_stack_use_after_return \
17+
// RUN: --implicit-check-not="__asan_stack_malloc_"
18+
19+
// CHECK-RUNTIME: load{{.*}}@__asan_option_detect_stack_use_after_return
20+
// CHECK-RUNTIME: call{{.*}}__asan_stack_malloc_0
21+
// CHECK-ALWAYS: call{{.*}}__asan_stack_malloc_always_0
22+
23+
int *function1() {
24+
int x = 0;
25+
26+
#pragma clang diagnostic ignored "-Wreturn-stack-address"
27+
return &x;
28+
}
29+
30+
int main() {
31+
auto px = function1();
32+
return 0;
33+
}

clang/test/Driver/cl-options.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,6 @@
452452
// RUN: /FAs \
453453
// RUN: /FAu \
454454
// RUN: /favor:blend \
455-
// RUN: /fsanitize-address-use-after-return \
456455
// RUN: /fno-sanitize-address-vcasan-lib \
457456
// RUN: /Fifoo \
458457
// RUN: /Fmfoo \
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Option should not be passed to the frontend by default.
2+
// RUN: %clang -target x86_64-apple-macosx10.15-gnu -fsanitize=address %s \
3+
// RUN: -### 2>&1 | \
4+
// RUN: FileCheck %s
5+
// CHECK-NOT: -fsanitize-address-use-after-return
6+
7+
// RUN: %clang -target x86_64-apple-macosx10.15-gnu -fsanitize=address \
8+
// RUN: -fsanitize-address-use-after-return=never %s -### 2>&1 | \
9+
// RUN: FileCheck -check-prefix=CHECK-NEVER-ARG %s
10+
// CHECK-NEVER-ARG: "-fsanitize-address-use-after-return=never"
11+
12+
// RUN: %clang -target x86_64-apple-macosx10.15-gnu -fsanitize=address \
13+
// RUN: -fsanitize-address-use-after-return=runtime %s -### 2>&1 | \
14+
// RUN: FileCheck -check-prefix=CHECK-RUNTIME %s
15+
// CHECK-RUNTIME: "-fsanitize-address-use-after-return=runtime"
16+
17+
// RUN: %clang -target x86_64-apple-macosx10.15-gnu -fsanitize=address \
18+
// RUN: -fsanitize-address-use-after-return=always %s -### 2>&1 | \
19+
// RUN: FileCheck -check-prefix=CHECK-ALWAYS-ARG %s
20+
21+
// RUN: %clang -target x86_64-apple-macosx10.15-gnu -fsanitize=address \
22+
// RUN: -fsanitize-address-use-after-return=never \
23+
// RUN: -fsanitize-address-use-after-return=always %s -### 2>&1 | \
24+
// RUN: FileCheck -check-prefix=CHECK-ALWAYS-ARG %s
25+
// CHECK-ALWAYS-ARG: "-fsanitize-address-use-after-return=always"
26+
27+
// RUN: %clang -target x86_64-apple-macosx10.15-gnu -fsanitize=address \
28+
// RUN: -fsanitize-address-use-after-return=bad_arg %s -### 2>&1 | \
29+
// RUN: FileCheck -check-prefix=CHECK-INVALID-ARG %s
30+
// CHECK-INVALID-ARG: error: unsupported argument 'bad_arg' to option 'fsanitize-address-use-after-return='

0 commit comments

Comments
 (0)