Skip to content

Commit 25b2d11

Browse files
authored
Merge pull request github#11635 from hvitved/dataflow/approx-content
Data flow: Introduce `ApproxContent` in a new pruning stage between stages 2 and 3
2 parents 6023a12 + 39fea37 commit 25b2d11

File tree

93 files changed

+17216
-6234
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+17216
-6234
lines changed

cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll

Lines changed: 410 additions & 158 deletions
Large diffs are not rendered by default.

cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll

Lines changed: 410 additions & 158 deletions
Large diffs are not rendered by default.

cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll

Lines changed: 410 additions & 158 deletions
Large diffs are not rendered by default.

cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll

Lines changed: 410 additions & 158 deletions
Large diffs are not rendered by default.

cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll

Lines changed: 100 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -926,18 +926,46 @@ private module Cached {
926926
TReturnCtxNoFlowThrough() or
927927
TReturnCtxMaybeFlowThrough(ReturnKindExt kind)
928928

929+
cached
930+
newtype TTypedContentApprox =
931+
MkTypedContentApprox(ContentApprox c, DataFlowType t) {
932+
exists(Content cont |
933+
c = getContentApprox(cont) and
934+
store(_, cont, _, _, t)
935+
)
936+
}
937+
929938
cached
930939
newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, _, t) }
931940

941+
cached
942+
TypedContent getATypedContent(TypedContentApprox c) {
943+
exists(ContentApprox cls, DataFlowType t, Content cont |
944+
c = MkTypedContentApprox(cls, pragma[only_bind_into](t)) and
945+
result = MkTypedContent(cont, pragma[only_bind_into](t)) and
946+
cls = getContentApprox(cont)
947+
)
948+
}
949+
932950
cached
933951
newtype TAccessPathFront =
934952
TFrontNil(DataFlowType t) or
935953
TFrontHead(TypedContent tc)
936954

955+
cached
956+
newtype TApproxAccessPathFront =
957+
TApproxFrontNil(DataFlowType t) or
958+
TApproxFrontHead(TypedContentApprox tc)
959+
937960
cached
938961
newtype TAccessPathFrontOption =
939962
TAccessPathFrontNone() or
940963
TAccessPathFrontSome(AccessPathFront apf)
964+
965+
cached
966+
newtype TApproxAccessPathFrontOption =
967+
TApproxAccessPathFrontNone() or
968+
TApproxAccessPathFrontSome(ApproxAccessPathFront apf)
941969
}
942970

943971
/**
@@ -1353,6 +1381,75 @@ class ReturnCtx extends TReturnCtx {
13531381
}
13541382
}
13551383

1384+
/** An approximated `Content` tagged with the type of a containing object. */
1385+
class TypedContentApprox extends MkTypedContentApprox {
1386+
private ContentApprox c;
1387+
private DataFlowType t;
1388+
1389+
TypedContentApprox() { this = MkTypedContentApprox(c, t) }
1390+
1391+
/** Gets a typed content approximated by this value. */
1392+
TypedContent getATypedContent() { result = getATypedContent(this) }
1393+
1394+
/** Gets the container type. */
1395+
DataFlowType getContainerType() { result = t }
1396+
1397+
/** Gets a textual representation of this approximated content. */
1398+
string toString() { result = c.toString() }
1399+
}
1400+
1401+
/**
1402+
* The front of an approximated access path. This is either a head or a nil.
1403+
*/
1404+
abstract class ApproxAccessPathFront extends TApproxAccessPathFront {
1405+
abstract string toString();
1406+
1407+
abstract DataFlowType getType();
1408+
1409+
abstract boolean toBoolNonEmpty();
1410+
1411+
pragma[nomagic]
1412+
TypedContent getAHead() {
1413+
exists(TypedContentApprox cont |
1414+
this = TApproxFrontHead(cont) and
1415+
result = cont.getATypedContent()
1416+
)
1417+
}
1418+
}
1419+
1420+
class ApproxAccessPathFrontNil extends ApproxAccessPathFront, TApproxFrontNil {
1421+
private DataFlowType t;
1422+
1423+
ApproxAccessPathFrontNil() { this = TApproxFrontNil(t) }
1424+
1425+
override string toString() { result = ppReprType(t) }
1426+
1427+
override DataFlowType getType() { result = t }
1428+
1429+
override boolean toBoolNonEmpty() { result = false }
1430+
}
1431+
1432+
class ApproxAccessPathFrontHead extends ApproxAccessPathFront, TApproxFrontHead {
1433+
private TypedContentApprox tc;
1434+
1435+
ApproxAccessPathFrontHead() { this = TApproxFrontHead(tc) }
1436+
1437+
override string toString() { result = tc.toString() }
1438+
1439+
override DataFlowType getType() { result = tc.getContainerType() }
1440+
1441+
override boolean toBoolNonEmpty() { result = true }
1442+
}
1443+
1444+
/** An optional approximated access path front. */
1445+
class ApproxAccessPathFrontOption extends TApproxAccessPathFrontOption {
1446+
string toString() {
1447+
this = TApproxAccessPathFrontNone() and result = "<none>"
1448+
or
1449+
this = TApproxAccessPathFrontSome(any(ApproxAccessPathFront apf | result = apf.toString()))
1450+
}
1451+
}
1452+
13561453
/** A `Content` tagged with the type of a containing object. */
13571454
class TypedContent extends MkTypedContent {
13581455
private Content c;
@@ -1385,7 +1482,7 @@ abstract class AccessPathFront extends TAccessPathFront {
13851482

13861483
abstract DataFlowType getType();
13871484

1388-
abstract boolean toBoolNonEmpty();
1485+
abstract ApproxAccessPathFront toApprox();
13891486

13901487
TypedContent getHead() { this = TFrontHead(result) }
13911488
}
@@ -1399,7 +1496,7 @@ class AccessPathFrontNil extends AccessPathFront, TFrontNil {
13991496

14001497
override DataFlowType getType() { result = t }
14011498

1402-
override boolean toBoolNonEmpty() { result = false }
1499+
override ApproxAccessPathFront toApprox() { result = TApproxFrontNil(t) }
14031500
}
14041501

14051502
class AccessPathFrontHead extends AccessPathFront, TFrontHead {
@@ -1411,7 +1508,7 @@ class AccessPathFrontHead extends AccessPathFront, TFrontHead {
14111508

14121509
override DataFlowType getType() { result = tc.getContainerType() }
14131510

1414-
override boolean toBoolNonEmpty() { result = true }
1511+
override ApproxAccessPathFront toApprox() { result.getAHead() = tc }
14151512
}
14161513

14171514
/** An optional access path front. */

cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,4 +260,9 @@ module Consistency {
260260
not exists(unique(ParameterPosition pos0 | isParameterNode(p, c, pos0))) and
261261
msg = "Parameter node with multiple positions."
262262
}
263+
264+
query predicate uniqueContentApprox(Content c, string msg) {
265+
not exists(unique(ContentApprox approx | approx = getContentApprox(c))) and
266+
msg = "Non-unique content approximation."
267+
}
263268
}

cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,13 @@ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preserves
551551
*/
552552
predicate allowParameterReturnInSelf(ParameterNode p) { none() }
553553

554+
/** An approximated `Content`. */
555+
class ContentApprox = Unit;
556+
557+
/** Gets an approximated value for content `c`. */
558+
pragma[inline]
559+
ContentApprox getContentApprox(Content c) { any() }
560+
554561
private class MyConsistencyConfiguration extends Consistency::ConsistencyConfiguration {
555562
override predicate argHasPostUpdateExclude(ArgumentNode n) {
556563
// The rules for whether an IR argument gets a post-update node are too

0 commit comments

Comments
 (0)