Fixed instruction corruption bug for multiple returns.
BUG=https://bugs.chromium.org/p/nativeclient/issues/detail?id=4374
R=kschimpf@google.com
Review URL: https://codereview.chromium.org/2128643002 .
diff --git a/pydir/szbuild.py b/pydir/szbuild.py
index 7333729..3e1722b 100755
--- a/pydir/szbuild.py
+++ b/pydir/szbuild.py
@@ -266,11 +266,6 @@
args = argparser.parse_args()
pexe = args.pexe
exe = args.output
- if args.asan:
- if args.sandbox or args.nonsfi:
- print 'Can only use AddressSanitizer with a native build'
- exit(1)
- args.sz_args.append('-fsanitize-address')
ProcessPexe(args, pexe, exe)
def ProcessPexe(args, pexe, exe):
@@ -307,6 +302,12 @@
opt_level_map = { 'm1':'0', '-1':'0', '0':'0', '1':'1', '2':'2' }
hybrid = args.include or args.exclude
native = not args.sandbox and not args.nonsfi
+ if args.asan:
+ if args.sandbox or args.nonsfi:
+ print 'Can only use AddressSanitizer with a native build'
+ exit(1)
+ if '-fsanitize-address' not in args.sz_args:
+ args.sz_args.append('-fsanitize-address')
if hybrid and (args.force or
NewerThanOrNotThere(pexe, obj_llc) or
diff --git a/src/IceASanInstrumentation.cpp b/src/IceASanInstrumentation.cpp
index bc519bf..a7551a8 100644
--- a/src/IceASanInstrumentation.cpp
+++ b/src/IceASanInstrumentation.cpp
@@ -64,7 +64,6 @@
void ASanInstrumentation::instrumentGlobals(VariableDeclarationList &Globals) {
if (DidProcessGlobals)
return;
-
VariableDeclarationList NewGlobals;
// Global holding pointers to all redzones
auto *RzArray = VariableDeclaration::create(&NewGlobals);
@@ -147,7 +146,6 @@
void ASanInstrumentation::instrumentFuncStart(LoweringContext &Context) {
if (ICE_TLS_GET_FIELD(LocalDtors) == nullptr)
ICE_TLS_SET_FIELD(LocalDtors, new std::vector<InstCall *>());
-
Cfg *Func = Context.getNode()->getCfg();
bool HasLocals = false;
LoweringContext C;
@@ -294,10 +292,21 @@
}
void ASanInstrumentation::instrumentRet(LoweringContext &Context, InstRet *) {
+ Cfg *Func = Context.getNode()->getCfg();
InstList::iterator Next = Context.getNext();
Context.setInsertPoint(Context.getCur());
for (InstCall *RzUnpoison : *ICE_TLS_GET_FIELD(LocalDtors)) {
- Context.insert(RzUnpoison);
+ SizeT NumArgs = RzUnpoison->getNumArgs();
+ Variable *Dest = RzUnpoison->getDest();
+ Operand *CallTarget = RzUnpoison->getCallTarget();
+ bool HasTailCall = RzUnpoison->isTailcall();
+ bool IsTargetHelperCall = RzUnpoison->isTargetHelperCall();
+ auto *RzUnpoisonCpy = InstCall::create(Func, NumArgs, Dest, CallTarget,
+ HasTailCall, IsTargetHelperCall);
+ for (int I = 0, Args = RzUnpoison->getNumArgs(); I < Args; ++I) {
+ RzUnpoisonCpy->addArg(RzUnpoison->getArg(I));
+ }
+ Context.insert(RzUnpoisonCpy);
}
Context.setNext(Next);
}
diff --git a/tests_lit/asan_tests/multiple_returns.ll b/tests_lit/asan_tests/multiple_returns.ll
new file mode 100644
index 0000000..5575c4b
--- /dev/null
+++ b/tests_lit/asan_tests/multiple_returns.ll
@@ -0,0 +1,42 @@
+; Check that functions with multiple returns are correctly instrumented
+
+; REQUIRES: allow_dump
+
+; RUN: %p2i -i %s --args -verbose=inst -threads=0 -fsanitize-address \
+; RUN: | FileCheck --check-prefix=DUMP %s
+
+define internal void @ret_twice(i32 %condarg) {
+ %local1 = alloca i8, i32 4, align 4
+ %local2 = alloca i8, i32 4, align 4
+ %cond = icmp ne i32 %condarg, 0
+ br i1 %cond, label %yes, label %no
+yes:
+ ret void
+no:
+ ret void
+}
+
+; DUMP-LABEL: ================ Instrumented CFG ================
+; DUMP-NEXT: define internal void @ret_twice(i32 %condarg) {
+; DUMP-NEXT: __0:
+; DUMP-NEXT: %local1 = alloca i8, i32 64, align 8
+; DUMP-NEXT: %local2 = alloca i8, i32 64, align 8
+; DUMP-NEXT: %__$rz2 = alloca i8, i32 32, align 8
+; DUMP-NEXT: call void @__asan_poison(i32 %__$rz2, i32 32)
+; DUMP-NEXT: %__$rz0 = add i32 %local1, 4
+; DUMP-NEXT: call void @__asan_poison(i32 %__$rz0, i32 60)
+; DUMP-NEXT: %__$rz1 = add i32 %local2, 4
+; DUMP-NEXT: call void @__asan_poison(i32 %__$rz1, i32 60)
+; DUMP-NEXT: %cond = icmp ne i32 %condarg, 0
+; DUMP-NEXT: br i1 %cond, label %yes, label %no
+; DUMP-NEXT: yes:
+; DUMP-NEXT: call void @__asan_unpoison(i32 %__$rz0, i32 60)
+; DUMP-NEXT: call void @__asan_unpoison(i32 %__$rz1, i32 60)
+; DUMP-NEXT: call void @__asan_unpoison(i32 %__$rz2, i32 32)
+; DUMP-NEXT: ret void
+; DUMP-NEXT: no:
+; DUMP-NEXT: call void @__asan_unpoison(i32 %__$rz0, i32 60)
+; DUMP-NEXT: call void @__asan_unpoison(i32 %__$rz1, i32 60)
+; DUMP-NEXT: call void @__asan_unpoison(i32 %__$rz2, i32 32)
+; DUMP-NEXT: ret void
+; DUMP-NEXT: }
\ No newline at end of file
diff --git a/tests_lit/asan_tests/wideloads.ll b/tests_lit/asan_tests/wideloads.ll
index 626a757..50a9975 100644
--- a/tests_lit/asan_tests/wideloads.ll
+++ b/tests_lit/asan_tests/wideloads.ll
@@ -5,7 +5,7 @@
; check for wide load exception
; RUN: llvm-as %s -o - | pnacl-freeze > %t.pexe && %S/../../pydir/szbuild.py \
; RUN: --fsanitize-address --sz="-allow-externally-defined-symbols" \
-; RUN: %t.pexe -o %t && %t | FileCheck %s --check-prefix=WIDE
+; RUN: %t.pexe -o %t && %t | FileCheck %s --check-prefix=WIDE --allow-empty
; check for error reporting
; RUN: llvm-as %s -o - | pnacl-freeze > %t.pexe && %S/../../pydir/szbuild.py \