diff --git a/compiler-rt/test/dfsan/gep.c b/compiler-rt/test/dfsan/gep.c new file mode 100644 --- /dev/null +++ b/compiler-rt/test/dfsan/gep.c @@ -0,0 +1,28 @@ +// RUN: %clang_dfsan %s -mllvm -dfsan-combine-offset-labels-on-gep=false -o %t && %run %t +// RUN: %clang_dfsan %s -DPROP_OFFSET_LABELS -o %t && %run %t +// +// REQUIRES: x86_64-target-arch + +// Tests that labels are propagated through GEP. + +#include +#include + +int main(void) { + int i = 1; + int *p = &i; + int j = 2; + // test that pointer arithmetic propagates labels in terms of the flag. + dfsan_set_label(1, &i, sizeof(i)); + p += i; +#ifdef PROP_OFFSET_LABELS + assert(dfsan_get_label(p) == 1); +#else + assert(dfsan_get_label(p) == 0); +#endif + // test that non-pointer operations always propagate labels. + dfsan_set_label(2, &j, sizeof(j)); + j += i; + assert(dfsan_get_label(j) == 3); + return 0; +} diff --git a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp @@ -201,6 +201,14 @@ "storing in memory."), cl::Hidden, cl::init(false)); +// Controls whether the pass propagates labels of offsets in GEP instructions. +static cl::opt ClCombineOffsetLabelsOnGEP( + "dfsan-combine-offset-labels-on-gep", + cl::desc( + "Combine the label of the offset with the label of the pointer when " + "doing pointer arithmetic."), + cl::Hidden, cl::init(true)); + static cl::opt ClDebugNonzeroLabels( "dfsan-debug-nonzero-labels", cl::desc("Insert calls to __dfsan_nonzero_label on observing a parameter, " @@ -2778,7 +2786,17 @@ } void DFSanVisitor::visitGetElementPtrInst(GetElementPtrInst &GEPI) { - visitInstOperands(GEPI); + if (ClCombineOffsetLabelsOnGEP) { + visitInstOperands(GEPI); + return; + } + + // Only propagate shadow/origin of base pointer value but ignore those of + // offset operands. + Value *BasePointer = GEPI.getPointerOperand(); + DFSF.setShadow(&GEPI, DFSF.getShadow(BasePointer)); + if (DFSF.DFS.shouldTrackOrigins()) + DFSF.setOrigin(&GEPI, DFSF.getOrigin(BasePointer)); } void DFSanVisitor::visitExtractElementInst(ExtractElementInst &I) { diff --git a/llvm/test/Instrumentation/DataFlowSanitizer/dont_combine_offset_labels_on_gep.ll b/llvm/test/Instrumentation/DataFlowSanitizer/dont_combine_offset_labels_on_gep.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Instrumentation/DataFlowSanitizer/dont_combine_offset_labels_on_gep.ll @@ -0,0 +1,21 @@ +; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-combine-offset-labels-on-gep=false -dfsan-fast-8-labels=true -S | FileCheck %s --check-prefixes=CHECK,CHECK_ORIGIN +; RUN: opt < %s -dfsan -dfsan-combine-offset-labels-on-gep=false -dfsan-fast-8-labels=true -S | FileCheck %s +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; CHECK: @__dfsan_arg_tls = external thread_local(initialexec) global [[TLS_ARR:\[100 x i64\]]] +; CHECK: @__dfsan_retval_tls = external thread_local(initialexec) global [[TLS_ARR]] +; CHECK: @__dfsan_shadow_width_bits = weak_odr constant i32 [[#SBITS:]] + +define i32* @gepop([10 x [20 x i32]]* %p, i32 %a, i32 %b, i32 %c) { + ; CHECK: @"dfs$gepop" + ; CHECK_ORIGIN: %[[#PO:]] = load i32, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__dfsan_arg_origin_tls, i64 0, i64 0), align [[ALIGN_O:4]] + ; CHECK: %[[#PS:]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN_S:2]] + ; CHECK: %e = getelementptr [10 x [20 x i32]], [10 x [20 x i32]]* %p, i32 %a, i32 %b, i32 %c + ; CHECK: store i[[#SBITS]] %[[#PS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN_S]] + ; CHECK_ORIGIN: store i32 %[[#PO]], i32* @__dfsan_retval_origin_tls, align [[ALIGN_O]] + + %e = getelementptr [10 x [20 x i32]], [10 x [20 x i32]]* %p, i32 %a, i32 %b, i32 %c + ret i32* %e +} +