C++: Block flow by default.

This commit is contained in:
Mathias Vorreiter Pedersen
2024-02-15 10:17:20 +01:00
parent 625c47fa9c
commit 24a63ae94d
9 changed files with 97 additions and 59 deletions

View File

@@ -4,7 +4,10 @@ private import DataFlowUtil
private import DataFlowImplCommon as DataFlowImplCommon
private import semmle.code.cpp.models.interfaces.Allocation as Alloc
private import semmle.code.cpp.models.interfaces.DataFlow as DataFlow
private import semmle.code.cpp.models.interfaces.Taint as Taint
private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs as FIO
private import semmle.code.cpp.ir.internal.IRCppLanguage
private import semmle.code.cpp.ir.dataflow.internal.ModelUtil
private import DataFlowPrivate
private import ssa0.SsaInternals as SsaInternals0
import SsaInternalsCommon
@@ -796,10 +799,47 @@ private Node getAPriorDefinition(SsaDefOrUse defOrUse) {
)
}
private predicate inOut(FIO::FunctionInput input, FIO::FunctionOutput output) {
exists(int indirectionIndex |
input.isQualifierObject(indirectionIndex) and
output.isQualifierObject(indirectionIndex)
or
exists(int i |
input.isParameterDeref(i, indirectionIndex) and
output.isParameterDeref(i, indirectionIndex)
)
)
}
/**
* Holds if there should not be use-use flow out of `n` (or a conversion that
* flows to `n`).
*/
private predicate modeledFlowBarrier(Node n) {
exists(FIO::FunctionInput input, FIO::FunctionOutput output, CallInstruction call |
n = callInput(call, input) and
inOut(input, output) and
exists(callOutput(call, output))
|
call.getStaticCallTarget().(DataFlow::DataFlowFunction).hasDataFlow(_, output)
or
call.getStaticCallTarget().(Taint::TaintFunction).hasTaintFlow(_, output)
)
or
exists(Operand operand, Instruction instr, Node n0, int indirectionIndex |
modeledFlowBarrier(n0) and
nodeHasInstruction(n0, instr, indirectionIndex) and
conversionFlow(operand, instr, false, _) and
nodeHasOperand(n, operand, indirectionIndex)
)
}
/** Holds if there is def-use or use-use flow from `nodeFrom` to `nodeTo`. */
predicate ssaFlow(Node nodeFrom, Node nodeTo) {
exists(Node nFrom, boolean uncertain, SsaDefOrUse defOrUse |
ssaFlowImpl(defOrUse, nFrom, nodeTo, uncertain) and nodeFrom != nodeTo
ssaFlowImpl(defOrUse, nFrom, nodeTo, uncertain) and
not modeledFlowBarrier(nFrom) and
nodeFrom != nodeTo
|
if uncertain = true then nodeFrom = [nFrom, getAPriorDefinition(defOrUse)] else nodeFrom = nFrom
)

View File

@@ -238,8 +238,6 @@ irFlow
| test.cpp:382:48:382:54 | source1 | test.cpp:385:8:385:10 | tmp |
| test.cpp:388:53:388:59 | source1 | test.cpp:392:8:392:10 | tmp |
| test.cpp:388:53:388:59 | source1 | test.cpp:394:10:394:12 | tmp |
| test.cpp:399:7:399:9 | definition of tmp | test.cpp:401:8:401:10 | tmp |
| test.cpp:405:7:405:9 | definition of tmp | test.cpp:408:8:408:10 | tmp |
| test.cpp:416:7:416:11 | definition of local | test.cpp:418:8:418:12 | local |
| test.cpp:417:16:417:20 | intRefSource output argument | test.cpp:418:8:418:12 | local |
| test.cpp:422:7:422:11 | definition of local | test.cpp:424:8:424:12 | local |

View File

@@ -398,14 +398,14 @@ void flowThroughMemcpy_blockvar_with_local_flow(int source1, int b) {
void cleanedByMemcpy_ssa(int clean1) { // currently modeled with BlockVar, not SSA
int tmp;
memcpy(&tmp, &clean1, sizeof tmp);
sink(tmp); // $ SPURIOUS: ast,ir
sink(tmp); // $ SPURIOUS: ast
}
void cleanedByMemcpy_blockvar(int clean1) {
int tmp;
int *capture = &tmp;
memcpy(&tmp, &clean1, sizeof tmp);
sink(tmp); // $ SPURIOUS: ast,ir
sink(tmp); // $ SPURIOUS: ast
}
void intRefSource(int &ref_source);

View File

@@ -71,11 +71,11 @@ void test_pair()
sink(i.second); // $ MISSING: ast,ir
sink(i); // $ ast,ir
sink(j.first);
sink(j.second); // $ SPURIOUS: ast,ir
sink(j); // $ SPURIOUS: ast,ir
sink(j.second); // $ SPURIOUS: ast
sink(j); // $ SPURIOUS: ast
sink(k.first);
sink(k.second); // $ SPURIOUS: ast,ir
sink(k); // $ SPURIOUS: ast,ir
sink(k.second); // $ SPURIOUS: ast
sink(k); // $ SPURIOUS: ast
sink(l.first);
sink(l.second); // $ MISSING: ast,ir
sink(l); // $ ast,ir
@@ -179,11 +179,11 @@ void test_map()
m14.insert(std::make_pair("b", source()));
m14.insert(std::make_pair("c", source()));
m14.insert(std::make_pair("d", "d"));
sink(m14.lower_bound("b")); // $ ast,ir=179:33 ast,ir=180:33
sink(m14.upper_bound("b")); // $ ast,ir=179:33 ast,ir=180:33
sink(m14.lower_bound("b")); // $ ast=179:33 ast=180:33 MISSING: ir=179:33 ir=180:33
sink(m14.upper_bound("b")); // $ ast=179:33 ast=180:33 MISSING: ir=179:33 ir=180:33
sink(m14.equal_range("b").first); // $ MISSING: ast,ir
sink(m14.equal_range("b").second); // $ MISSING: ast,ir
sink(m14.upper_bound("c")); // $ SPURIOUS: ast,ir=179:33 ast,ir=180:33
sink(m14.upper_bound("c")); // $ SPURIOUS: ast=179:33 ast=180:33
sink(m14.equal_range("c").second);
// swap
@@ -196,10 +196,10 @@ void test_map()
sink(m18); // $ ast,ir
m15.swap(m16);
m17.swap(m18);
sink(m15); // $ SPURIOUS: ast,ir
sink(m15); // $ SPURIOUS: ast
sink(m16); // $ ast,ir
sink(m17); // $ ast,ir
sink(m18); // $ SPURIOUS: ast,ir
sink(m18); // $ SPURIOUS: ast
// merge
std::map<char *, char *> m19, m20, m21, m22;
@@ -213,7 +213,7 @@ void test_map()
sink(m22); // $ ast,ir
m19.merge(m20);
m21.merge(m22);
sink(m19); // $ ast,ir
sink(m19); // $ ast
sink(m20);
sink(m21); // $ ast,ir
sink(m22); // $ ast,ir
@@ -222,11 +222,11 @@ void test_map()
std::map<char *, char *> m23;
m23.insert(std::pair<char *, char *>(source(), source()));
m23.insert(std::pair<char *, char *>(source(), source()));
sink(m23); // $ ast,ir=223:49 ast,ir=224:49
sink(m23.erase(m23.begin())); // $ ast,ir=223:49 ast,ir=224:49
sink(m23); // $ ast,ir=223:49 ast,ir=224:49
sink(m23); // $ ast=223:49 ast=224:49 ir MISSING: ir=223:49 ir=224:49
sink(m23.erase(m23.begin())); // $ ast=223:49 ast=224:49 ir MISSING: ir=223:49 ir=224:49
sink(m23); // $ ast=223:49 ast=224:49 ir MISSING: ir=223:49 ir=224:49
m23.clear();
sink(m23); // $ SPURIOUS: ast,ir=223:49 ast,ir=224:49
sink(m23); // $ SPURIOUS: ast=223:49 ast=224:49 ir
// emplace, emplace_hint
std::map<char *, char *> m24, m25;
@@ -345,10 +345,10 @@ void test_unordered_map()
sink(m18); // $ ast,ir
m15.swap(m16);
m17.swap(m18);
sink(m15); // $ SPURIOUS: ast,ir
sink(m15); // $ SPURIOUS: ast
sink(m16); // $ ast,ir
sink(m17); // $ ast,ir
sink(m18); // $ SPURIOUS: ast,ir
sink(m18); // $ SPURIOUS: ast
// merge
std::unordered_map<char *, char *> m19, m20, m21, m22;
@@ -362,7 +362,7 @@ void test_unordered_map()
sink(m22); // $ ast,ir
m19.merge(m20);
m21.merge(m22);
sink(m19); // $ ast,ir
sink(m19); // $ ast MISSING: ir
sink(m20);
sink(m21); // $ ast,ir
sink(m22); // $ ast,ir
@@ -371,11 +371,11 @@ void test_unordered_map()
std::unordered_map<char *, char *> m23;
m23.insert(std::pair<char *, char *>(source(), source()));
m23.insert(std::pair<char *, char *>(source(), source()));
sink(m23); // $ ast,ir=372:49 ast,ir=373:49
sink(m23.erase(m23.begin())); // $ ast,ir=372:49 ast,ir=373:49
sink(m23); // $ ast,ir=372:49 ast,ir=373:49
sink(m23); // $ ast=372:49 ast=373:49 ir MISSING: ir=372:49 ir=373:49
sink(m23.erase(m23.begin())); // $ ast=372:49 ast=373:49 ir MISSING: ir=372:49 ir=373:49
sink(m23); // $ ast=372:49 ast=373:49 ir MISSING: ir=372:49 ir=373:49
m23.clear();
sink(m23); // $ SPURIOUS: ast,ir=372:49 ast,ir=373:49
sink(m23); // $ SPURIOUS: ast=372:49 ast=373:49 ir
// emplace, emplace_hint
std::unordered_map<char *, char *> m24, m25;
@@ -395,7 +395,7 @@ void test_unordered_map()
sink(m26);
sink(m26.try_emplace("abc", source()).first);
sink(m26.try_emplace("abc", source()).second); // $ MISSING: ast,ir=396:30
sink(m26); // $ ast,ir=396:30 SPURIOUS: ast,ir=397:30
sink(m26); // $ ast=396:30 ir MISSING: ir=396:30 SPURIOUS: ast=397:30
sink(m27.try_emplace(m27.begin(), "abc", "def"));
sink(m27);
sink(m27.try_emplace(m27.begin(), "abc", source())); // $ ast,ir

View File

@@ -66,8 +66,8 @@ void test_set()
s11.insert("a");
s11.insert(source());
s11.insert("c");
sink(s11.lower_bound("b")); // $ ast,ir
sink(s11.upper_bound("b")); // $ ast,ir
sink(s11.lower_bound("b")); // $ ast MISSING: ir
sink(s11.upper_bound("b")); // $ ast MISSING: ir
sink(s11.equal_range("b").first); // $ MISSING: ast,ir
sink(s11.equal_range("b").second); // $ MISSING: ast,ir
@@ -81,10 +81,10 @@ void test_set()
sink(s15); // $ ast,ir
s12.swap(s13);
s14.swap(s15);
sink(s12); // $ SPURIOUS: ast,ir
sink(s12); // $ SPURIOUS: ast
sink(s13); // $ ast,ir
sink(s14); // $ ast,ir
sink(s15); // $ SPURIOUS: ast,ir
sink(s15); // $ SPURIOUS: ast
// merge
std::set<char *> s16, s17, s18, s19;
@@ -98,7 +98,7 @@ void test_set()
sink(s19); // $ ast,ir
s16.merge(s17);
s18.merge(s19);
sink(s16); // $ ast,ir
sink(s16); // $ ast MISSING: ir
sink(s17);
sink(s18); // $ ast,ir
sink(s19); // $ ast,ir
@@ -107,11 +107,11 @@ void test_set()
std::set<char *> s20;
s20.insert(source());
s20.insert(source());
sink(s20); // $ ast,ir=108:13 ast,ir=109:13
sink(s20.erase(s20.begin())); // $ ast,ir=108:13 ast,ir=109:13
sink(s20); // $ ast,ir=108:13 ast,ir=109:13
sink(s20); // $ ast=108:13 ast=109:13 ir MISSING: ir=108:13 ir=109:13
sink(s20.erase(s20.begin())); // $ ast=108:13 ast=109:13 ir MISSING: ir=108:13 ir=109:13
sink(s20); // $ ir ast=108:13 ast=109:13 MISSING: ir=108:13 ir=109:13
s20.clear();
sink(s20); // $ SPURIOUS: ast,ir=108:13 ast,ir=109:13
sink(s20); // $ SPURIOUS: ir ast=108:13 ast=109:13
// emplace, emplace_hint
std::set<char *> s21, s22;
@@ -193,10 +193,10 @@ void test_unordered_set()
sink(s15); // $ ast,ir
s12.swap(s13);
s14.swap(s15);
sink(s12); // $ SPURIOUS: ast,ir
sink(s12); // $ SPURIOUS: ast
sink(s13); // $ ast,ir
sink(s14); // $ ast,ir
sink(s15); // $ SPURIOUS: ast,ir
sink(s15); // $ SPURIOUS: ast
// merge
std::unordered_set<char *> s16, s17, s18, s19;
@@ -210,7 +210,7 @@ void test_unordered_set()
sink(s19); // $ ast,ir
s16.merge(s17);
s18.merge(s19);
sink(s16); // $ ast,ir
sink(s16); // $ ast MISSING: ir
sink(s17);
sink(s18); // $ ast,ir
sink(s19); // $ ast,ir
@@ -219,11 +219,11 @@ void test_unordered_set()
std::unordered_set<char *> s20;
s20.insert(source());
s20.insert(source());
sink(s20); // $ ast,ir=220:13 ast,ir=221:13
sink(s20.erase(s20.begin())); // $ ast,ir=220:13 ast,ir=221:13
sink(s20); // $ ast,ir=220:13 ast,ir=221:13
sink(s20); // $ ir ast=220:13 ast=221:13 MISSING: ir=220:13 ir=221:13
sink(s20.erase(s20.begin())); // $ ast=220:13 ast=221:13 ir MISSING: ir=220:13 ir=221:13
sink(s20); // $ ast=220:13 ast=221:13 ir MISSING: ir=220:13 ir=221:13
s20.clear();
sink(s20); // $ SPURIOUS: ast,ir=220:13 ast,ir=221:13
sink(s20); // $ SPURIOUS: ast=220:13 ast=221:13 ir
// emplace, emplace_hint
std::unordered_set<char *> s21, s22;

View File

@@ -203,7 +203,7 @@ void test_string_assign() {
sink(s5); // $ ast,ir
sink(s6.assign(s1));
sink(s6); // $ SPURIOUS: ast,ir
sink(s6); // $ SPURIOUS: ast
}
void test_string_insert() {
@@ -280,9 +280,9 @@ void test_string_swap() {
s4.swap(s3);
sink(s1); // $ ast,ir
sink(s2); // $ SPURIOUS: ast,ir
sink(s2); // $ SPURIOUS: ast
sink(s3); // $ ast,ir
sink(s4); // $ SPURIOUS: ast,ir
sink(s4); // $ SPURIOUS: ast
}
void test_string_clear() {
@@ -495,7 +495,7 @@ void test_string_iterator_methods()
sink(h); // $ ast,ir
sink(s6.assign(s5.cbegin(), s5.cend()));
sink(s6); // $ SPURIOUS: ast,ir
sink(s6); // $ SPURIOUS: ast
}
}

View File

@@ -50,7 +50,7 @@ void test_stringstream_string(int amount)
ss7.str(source());
ss7.str("abc"); // (overwrites)
sink(ss6); // $ ast,ir
sink(ss7); // $ SPURIOUS: ast,ir
sink(ss7); // $ SPURIOUS: ast
sink(ss8.put('a'));
sink(ss9.put(ns_char::source())); // $ ast,ir
@@ -118,9 +118,9 @@ void test_stringstream_swap()
ss4.swap(ss3);
sink(ss1); // $ ast,ir
sink(ss2); // $ SPURIOUS: ast,ir
sink(ss2); // $ SPURIOUS: ast
sink(ss3); // $ ast,ir
sink(ss4); // $ SPURIOUS: ast,ir
sink(ss4); // $ SPURIOUS: ast
}
void test_stringstream_in()
@@ -217,7 +217,7 @@ void test_getline()
sink(ss1.getline(b3, 1000));
sink(b1);
sink(b2); // $ ast,ir
sink(b3); // $ SPURIOUS: ast,ir
sink(b3); // $ SPURIOUS: ast
sink(ss1.getline(b4, 1000, ' '));
sink(ss2.getline(b5, 1000, ' ')); // $ ast,ir
@@ -225,7 +225,7 @@ void test_getline()
sink(ss1.getline(b6, 1000, ' '));
sink(b4);
sink(b5); // $ ast,ir
sink(b6); // $ SPURIOUS: ast,ir
sink(b6); // $ SPURIOUS: ast
sink(ss2.getline(b7, 1000).getline(b8, 1000)); // $ ast,ir
sink(b7); // $ ast,ir
@@ -237,7 +237,7 @@ void test_getline()
sink(getline(ss1, s3));
sink(s1);
sink(s2); // $ ast,ir
sink(s3); // $ SPURIOUS: ast,ir
sink(s3); // $ SPURIOUS: ast
sink(getline(ss1, s4, ' '));
sink(getline(ss2, s5, ' ')); // $ ast,ir
@@ -245,7 +245,7 @@ void test_getline()
sink(getline(ss1, s6, ' '));
sink(s4);
sink(s5); // $ ast,ir
sink(s6); // $ SPURIOUS: ast,ir
sink(s6); // $ SPURIOUS: ast
sink(getline(getline(ss2, s7), s8)); // $ ast,ir
sink(s7); // $ ast,ir

View File

@@ -212,7 +212,7 @@ void test_swap() {
std::swap(x, y);
sink(x); // $ SPURIOUS: ast,ir
sink(x); // $ SPURIOUS: ast
sink(y); // $ ast,ir
}
@@ -756,5 +756,5 @@ void call_sprintf_twice(char* path, char* data) {
void test_call_sprintf() {
char path[10];
call_sprintf_twice(path, indirect_source());
sink(*path); // $ ir ast
sink(*path); // $ ast MISSING: ir
}

View File

@@ -114,10 +114,10 @@ void test_vector_swap() {
v1.swap(v2);
v3.swap(v4);
sink(v1); // $ SPURIOUS: ast,ir
sink(v1); // $ SPURIOUS: ast
sink(v2); // $ ast,ir
sink(v3); // $ ast,ir
sink(v4); // $ SPURIOUS: ast,ir
sink(v4); // $ SPURIOUS: ast
}
void test_vector_clear() {
@@ -138,7 +138,7 @@ void test_vector_clear() {
sink(v1); // $ SPURIOUS: ast,ir
sink(v2); // $ ast,ir
sink(v3); // $ ast,ir
sink(v3); // $ SPURIOUS: ast
sink(v4);
}