Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,30 @@ auto IFDSTaintAnalysis::getNormalFlowFunction(n_t Curr,
});
}

// A select yields one of its two value operands: if either is tainted, the
// result may be tainted. (The condition is not tracked; that would be an
// implicit flow.)
if (const auto *Select = llvm::dyn_cast<llvm::SelectInst>(Curr)) {
return lambdaFlow([Select](d_t Source) -> container_type {
if (Source == Select->getTrueValue() ||
Source == Select->getFalseValue()) {
return {Source, Select};
}
return {Source};
});
}

// A phi merges values from predecessor blocks: if any incoming value is
// tainted, the merged value may be tainted.
if (const auto *Phi = llvm::dyn_cast<llvm::PHINode>(Curr)) {
return lambdaFlow([Phi](d_t Source) -> container_type {
if (llvm::is_contained(Phi->incoming_values(), Source)) {
return {Source, Phi};
}
return {Source};
});
}

// Otherwise we do not care and leave everything as it is
return identityFlow();
}
Expand Down
6 changes: 3 additions & 3 deletions test/llvm_test_code/taint_analysis/double_free/df_ctx_01.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ int main() {
// xtaint: /taint_analysis/double_free/df_ctx_01.c:10:3:

// RUN: %phasar-cli --data-flow-analysis=ifds-taint --module %llvm_test_code/taint_analysis/double_free/df_ctx_01_c_dbg.ll --analysis-config %config/double-free-config.json | FileCheck %s -check-prefix=ifds-taint
// ifds-taint: No leaks found!
// ifds-taint: /taint_analysis/double_free/df_ctx_01.c:10:3:

// RUN: %phasar-cli --data-flow-analysis=ifds-fieldsens-taint --module %llvm_test_code/taint_analysis/double_free/df_ctx_01_c_dbg.ll --analysis-config %config/double-free-config.json | FileCheck %s -check-prefix=ifds-fieldsens-taint
// ifds-fieldsens-taint: No leaks found!
// ifds-fieldsens-taint: /taint_analysis/double_free/df_ctx_01.c:10:3:

// RUN: %phasar-cli --data-flow-analysis=monoifds-taint --module %llvm_test_code/taint_analysis/double_free/df_ctx_01_c_dbg.ll --analysis-config %config/double-free-config.json | FileCheck %s -check-prefix=monoifds-taint
// monoifds-taint: /taint_analysis/double_free/df_ctx_01.c:10:3:

// RUN: %phasar-cli --data-flow-analysis=sparse-ifds-taint --module %llvm_test_code/taint_analysis/double_free/df_ctx_01_c_dbg.ll --analysis-config %config/double-free-config.json | FileCheck %s -check-prefix=sparse-ifds-taint
// sparse-ifds-taint: No leaks found!
// sparse-ifds-taint: /taint_analysis/double_free/df_ctx_01.c:10:3:
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ set(taint_tests_mem2reg
taint_01.cpp
taint_06.cpp
taint_exception_01.cpp
taint_select_01.cpp
)

# Compiled with -O1, so that SimplifyCFG turns branches into select
# instructions
set(taint_tests_opt
taint_select_01.cpp
taint_select_02.cpp
taint_select_03.cpp
)


Expand All @@ -33,3 +42,7 @@ endforeach(TEST_SRC)
foreach(TEST_SRC ${taint_tests_mem2reg})
generate_ll_file(FILE ${TEST_SRC} MEM2REG DEBUG)
endforeach(TEST_SRC)

foreach(TEST_SRC ${taint_tests_opt})
generate_ll_file(FILE ${TEST_SRC} DEBUG O1)
endforeach(TEST_SRC)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
extern int source(); // dummy source
extern void sink(int p); // dummy sink

int main(int argc, char **argv) {
int a = source();
int b = argc > 1 ? a : 0;
sink(b);
return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
extern int source(); // dummy source
extern void sink(int p); // dummy sink

int main(int argc, char **argv) {
int a = source();
int b = 0;
if (argc > 1) {
b = a;
}
sink(b);
return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
extern int source(); // dummy source
extern void sink(int p); // dummy sink

int main(int argc, char **argv) {
int a = source();
int b = argc > 1 ? 1 : 2;
sink(b);
sink(a);
return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,65 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_06) {
compare(TaintProblem->Leaks, GroundTruth);
}

// Ternary operator, compiled with -O1: the tainted value reaches the sink
// through a select instruction
TEST_F(IFDSTaintAnalysisTest, TaintTest_Select_01) {
initialize({PathToLlFiles + "dummy_source_sink/taint_select_01_cpp_dbg.ll"});
IFDSSolver TaintSolver(&*TaintProblem, &HA->getICFG());
TaintSolver.solve();

auto Entry = LineColFun{7, 3, "main"};
auto EntryTwo = LineColFunOp{6, 11, "main", llvm::Instruction::Select};
GroundTruthTy GroundTruth{{Entry, {EntryTwo}}};

compare(TaintProblem->Leaks, GroundTruth);
}

// Same ternary operator after mem2reg: the tainted value reaches the sink
// through a phi instruction
TEST_F(IFDSTaintAnalysisTest, TaintTest_Select_01_m2r) {
initialize(
{PathToLlFiles + "dummy_source_sink/taint_select_01_cpp_m2r_dbg.ll"});
IFDSSolver TaintSolver(&*TaintProblem, &HA->getICFG());
TaintSolver.solve();

auto Entry = LineColFun{7, 3, "main"};
auto EntryTwo = LineColFunOp{6, 11, "main", llvm::Instruction::PHI};
GroundTruthTy GroundTruth{{Entry, {EntryTwo}}};

compare(TaintProblem->Leaks, GroundTruth);
}

// Conditional assignment, compiled with -O1: SimplifyCFG turns the if into a
// select instruction
TEST_F(IFDSTaintAnalysisTest, TaintTest_Select_02) {
initialize({PathToLlFiles + "dummy_source_sink/taint_select_02_cpp_dbg.ll"});
IFDSSolver TaintSolver(&*TaintProblem, &HA->getICFG());
TaintSolver.solve();

auto Entry = LineColFun{10, 3, "main"};
// Column 0 matches any column: LLVM versions attach the select to either
// the `if` or the condition on line 7
auto EntryTwo = LineColFunOp{7, 0, "main", llvm::Instruction::Select};
GroundTruthTy GroundTruth{{Entry, {EntryTwo}}};

compare(TaintProblem->Leaks, GroundTruth);
}

// A select between two constants must not be tainted, even if a tainted value
// exists. Only the direct flow into the second sink is a leak.
TEST_F(IFDSTaintAnalysisTest, TaintTest_Select_03) {
initialize({PathToLlFiles + "dummy_source_sink/taint_select_03_cpp_dbg.ll"});
IFDSSolver TaintSolver(&*TaintProblem, &HA->getICFG());
TaintSolver.solve();

auto Entry = LineColFun{8, 3, "main"};
auto EntryTwo = LineColFunOp{5, 11, "main", llvm::Instruction::Call};
GroundTruthTy GroundTruth{{Entry, {EntryTwo}}};

compare(TaintProblem->Leaks, GroundTruth);
}

TEST_F(IFDSTaintAnalysisTest, SRetTest_01) {
initialize({PathToLlFiles + "dummy_source_sink/sret_c_dbg.ll"});
IFDSSolver TaintSolver(&*TaintProblem, &HA->getICFG());
Expand Down
Loading