Skip to content

Commit 2830739

Browse files
committed
Data flow: Sync files
1 parent bc6c474 commit 2830739

18 files changed

Lines changed: 612 additions & 1260 deletions

File tree

cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll

Lines changed: 34 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1647,9 +1647,6 @@ abstract private class AccessPath extends TAccessPath {
16471647
* Holds if this access path has `head` at the front and may be followed by `tail`.
16481648
*/
16491649
abstract predicate pop(Content head, AccessPath tail);
1650-
1651-
/** Gets the untyped version of this access path. */
1652-
UntypedAccessPath getUntyped() { result.getATyped() = this }
16531650
}
16541651

16551652
private class AccessPathNil extends AccessPath, TNil {
@@ -2001,50 +1998,10 @@ private Configuration unbind(Configuration conf) { result >= conf and result <=
20011998

20021999
private predicate flow(Node n, Configuration config) { flow(TNormalNode(n), _, _, config) }
20032000

2004-
private newtype TUntypedAccessPath =
2005-
TNilUntyped() or
2006-
TConsNilUntyped(Content f) { exists(TConsNil(f, _)) } or
2007-
TConsConsUntyped(Content f1, Content f2, int len) { exists(TConsCons(f1, f2, len)) }
2008-
2009-
/**
2010-
* An untyped access path.
2011-
*
2012-
* Untyped access paths are only used when reconstructing flow summaries,
2013-
* where the extra type information is redundant.
2014-
*/
2015-
private class UntypedAccessPath extends TUntypedAccessPath {
2016-
/** Gets a typed version of this untyped access path. */
2017-
AccessPath getATyped() {
2018-
this = TNilUntyped() and result = TNil(_)
2019-
or
2020-
exists(Content f | this = TConsNilUntyped(f) | result = TConsNil(f, _))
2021-
or
2022-
exists(Content f1, Content f2, int len | this = TConsConsUntyped(f1, f2, len) |
2023-
result = TConsCons(f1, f2, len)
2024-
)
2025-
}
2026-
2027-
string toString() {
2028-
this = TNilUntyped() and
2029-
result = "<nil>"
2030-
or
2031-
exists(Content f | this = TConsNilUntyped(f) | result = "[" + f + "]")
2032-
or
2033-
exists(Content f1, Content f2, int len | this = TConsConsUntyped(f1, f2, len) |
2034-
if len = 2
2035-
then result = "[" + f1.toString() + ", " + f2.toString() + "]"
2036-
else result = "[" + f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")]"
2037-
)
2038-
}
2039-
}
2040-
20412001
private newtype TSummaryCtx =
20422002
TSummaryCtxNone() or
2043-
TSummaryCtxSome(ParameterNode p, UntypedAccessPath uap) {
2044-
exists(ReturnNodeExt ret, Configuration config, AccessPath ap |
2045-
ap = uap.getATyped() and
2046-
flow(TNormalNode(p), true, ap, config)
2047-
|
2003+
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
2004+
exists(ReturnNodeExt ret, Configuration config | flow(TNormalNode(p), true, ap, config) |
20482005
exists(Summary summary |
20492006
parameterFlowReturn(p, ret, _, _, _, summary, config) and
20502007
flow(ret, unbind(config))
@@ -2080,12 +2037,30 @@ private newtype TSummaryCtx =
20802037
*
20812038
* Summaries are only created for parameters that may flow through.
20822039
*/
2083-
private class SummaryCtx extends TSummaryCtx {
2084-
string toString() { result = "SummaryCtx" }
2040+
abstract private class SummaryCtx extends TSummaryCtx {
2041+
abstract string toString();
20852042
}
20862043

20872044
/** A summary context from which no flow summary can be generated. */
2088-
private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { }
2045+
private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
2046+
override string toString() { result = "<none>" }
2047+
}
2048+
2049+
/** A summary context from which a flow summary can be generated. */
2050+
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
2051+
private ParameterNode p;
2052+
private AccessPath ap;
2053+
2054+
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
2055+
2056+
override string toString() { result = p + ": " + ap }
2057+
2058+
predicate hasLocationInfo(
2059+
string filepath, int startline, int startcolumn, int endline, int endcolumn
2060+
) {
2061+
p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
2062+
}
2063+
}
20892064

20902065
private newtype TPathNode =
20912066
TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) {
@@ -2399,30 +2374,30 @@ private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) {
23992374
*/
24002375
pragma[noinline]
24012376
private predicate pathIntoArg(
2402-
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, UntypedAccessPath ap
2377+
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap
24032378
) {
24042379
exists(ArgumentNode arg |
24052380
arg = mid.getNode() and
24062381
cc = mid.getCallContext() and
24072382
arg.argumentOf(call, i) and
2408-
ap = mid.getAp().getUntyped()
2383+
ap = mid.getAp()
24092384
)
24102385
}
24112386

24122387
pragma[noinline]
24132388
private predicate parameterCand(
2414-
DataFlowCallable callable, int i, UntypedAccessPath ap, Configuration config
2389+
DataFlowCallable callable, int i, AccessPath ap, Configuration config
24152390
) {
24162391
exists(ParameterNode p |
2417-
flow(TNormalNode(p), _, ap.getATyped(), config) and
2392+
flow(TNormalNode(p), _, ap, config) and
24182393
p.isParameterOf(callable, i)
24192394
)
24202395
}
24212396

24222397
pragma[nomagic]
24232398
private predicate pathIntoCallable0(
24242399
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
2425-
UntypedAccessPath ap
2400+
AccessPath ap
24262401
) {
24272402
pathIntoArg(mid, i, outercc, call, ap) and
24282403
callable = resolveCall(call, outercc) and
@@ -2438,7 +2413,7 @@ private predicate pathIntoCallable(
24382413
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
24392414
DataFlowCall call
24402415
) {
2441-
exists(int i, DataFlowCallable callable, UntypedAccessPath ap |
2416+
exists(int i, DataFlowCallable callable, AccessPath ap |
24422417
pathIntoCallable0(mid, callable, i, outercc, call, ap) and
24432418
p.isParameterOf(callable, i) and
24442419
(
@@ -2457,7 +2432,7 @@ private predicate pathIntoCallable(
24572432
/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */
24582433
pragma[nomagic]
24592434
private predicate paramFlowsThrough(
2460-
ReturnKindExt kind, CallContextCall cc, TSummaryCtxSome sc, AccessPath ap, Configuration config
2435+
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config
24612436
) {
24622437
exists(PathNodeMid mid, ReturnNodeExt ret |
24632438
mid.getNode() = ret and
@@ -2635,14 +2610,7 @@ private module FlowExploration {
26352610

26362611
private newtype TSummaryCtx2 =
26372612
TSummaryCtx2None() or
2638-
TSummaryCtx2Nil() or
2639-
TSummaryCtx2ConsNil(Content f)
2640-
2641-
private TSummaryCtx2 getSummaryCtx2(PartialAccessPath ap) {
2642-
result = TSummaryCtx2Nil() and ap instanceof PartialAccessPathNil
2643-
or
2644-
exists(Content f | result = TSummaryCtx2ConsNil(f) and ap = TPartialCons(f, 1))
2645-
}
2613+
TSummaryCtx2Some(PartialAccessPath ap)
26462614

26472615
private newtype TPartialPathNode =
26482616
TPartialPathNodeMk(
@@ -2929,11 +2897,8 @@ private module FlowExploration {
29292897
exists(int i, DataFlowCallable callable |
29302898
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
29312899
p.isParameterOf(callable, i) and
2932-
(
2933-
sc1 = TSummaryCtx1Param(p) and sc2 = getSummaryCtx2(ap)
2934-
or
2935-
sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and not exists(getSummaryCtx2(ap))
2936-
)
2900+
sc1 = TSummaryCtx1Param(p) and
2901+
sc2 = TSummaryCtx2Some(ap)
29372902
|
29382903
if recordDataFlowCallSite(call, callable)
29392904
then innercc = TSpecificCall(call)
@@ -2953,8 +2918,7 @@ private module FlowExploration {
29532918
sc1 = mid.getSummaryCtx1() and
29542919
sc2 = mid.getSummaryCtx2() and
29552920
config = mid.getConfiguration() and
2956-
ap = mid.getAp() and
2957-
ap.len() in [0 .. 1]
2921+
ap = mid.getAp()
29582922
)
29592923
}
29602924

cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll

Lines changed: 34 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1647,9 +1647,6 @@ abstract private class AccessPath extends TAccessPath {
16471647
* Holds if this access path has `head` at the front and may be followed by `tail`.
16481648
*/
16491649
abstract predicate pop(Content head, AccessPath tail);
1650-
1651-
/** Gets the untyped version of this access path. */
1652-
UntypedAccessPath getUntyped() { result.getATyped() = this }
16531650
}
16541651

16551652
private class AccessPathNil extends AccessPath, TNil {
@@ -2001,50 +1998,10 @@ private Configuration unbind(Configuration conf) { result >= conf and result <=
20011998

20021999
private predicate flow(Node n, Configuration config) { flow(TNormalNode(n), _, _, config) }
20032000

2004-
private newtype TUntypedAccessPath =
2005-
TNilUntyped() or
2006-
TConsNilUntyped(Content f) { exists(TConsNil(f, _)) } or
2007-
TConsConsUntyped(Content f1, Content f2, int len) { exists(TConsCons(f1, f2, len)) }
2008-
2009-
/**
2010-
* An untyped access path.
2011-
*
2012-
* Untyped access paths are only used when reconstructing flow summaries,
2013-
* where the extra type information is redundant.
2014-
*/
2015-
private class UntypedAccessPath extends TUntypedAccessPath {
2016-
/** Gets a typed version of this untyped access path. */
2017-
AccessPath getATyped() {
2018-
this = TNilUntyped() and result = TNil(_)
2019-
or
2020-
exists(Content f | this = TConsNilUntyped(f) | result = TConsNil(f, _))
2021-
or
2022-
exists(Content f1, Content f2, int len | this = TConsConsUntyped(f1, f2, len) |
2023-
result = TConsCons(f1, f2, len)
2024-
)
2025-
}
2026-
2027-
string toString() {
2028-
this = TNilUntyped() and
2029-
result = "<nil>"
2030-
or
2031-
exists(Content f | this = TConsNilUntyped(f) | result = "[" + f + "]")
2032-
or
2033-
exists(Content f1, Content f2, int len | this = TConsConsUntyped(f1, f2, len) |
2034-
if len = 2
2035-
then result = "[" + f1.toString() + ", " + f2.toString() + "]"
2036-
else result = "[" + f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")]"
2037-
)
2038-
}
2039-
}
2040-
20412001
private newtype TSummaryCtx =
20422002
TSummaryCtxNone() or
2043-
TSummaryCtxSome(ParameterNode p, UntypedAccessPath uap) {
2044-
exists(ReturnNodeExt ret, Configuration config, AccessPath ap |
2045-
ap = uap.getATyped() and
2046-
flow(TNormalNode(p), true, ap, config)
2047-
|
2003+
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
2004+
exists(ReturnNodeExt ret, Configuration config | flow(TNormalNode(p), true, ap, config) |
20482005
exists(Summary summary |
20492006
parameterFlowReturn(p, ret, _, _, _, summary, config) and
20502007
flow(ret, unbind(config))
@@ -2080,12 +2037,30 @@ private newtype TSummaryCtx =
20802037
*
20812038
* Summaries are only created for parameters that may flow through.
20822039
*/
2083-
private class SummaryCtx extends TSummaryCtx {
2084-
string toString() { result = "SummaryCtx" }
2040+
abstract private class SummaryCtx extends TSummaryCtx {
2041+
abstract string toString();
20852042
}
20862043

20872044
/** A summary context from which no flow summary can be generated. */
2088-
private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { }
2045+
private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
2046+
override string toString() { result = "<none>" }
2047+
}
2048+
2049+
/** A summary context from which a flow summary can be generated. */
2050+
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
2051+
private ParameterNode p;
2052+
private AccessPath ap;
2053+
2054+
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
2055+
2056+
override string toString() { result = p + ": " + ap }
2057+
2058+
predicate hasLocationInfo(
2059+
string filepath, int startline, int startcolumn, int endline, int endcolumn
2060+
) {
2061+
p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
2062+
}
2063+
}
20892064

20902065
private newtype TPathNode =
20912066
TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) {
@@ -2399,30 +2374,30 @@ private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) {
23992374
*/
24002375
pragma[noinline]
24012376
private predicate pathIntoArg(
2402-
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, UntypedAccessPath ap
2377+
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap
24032378
) {
24042379
exists(ArgumentNode arg |
24052380
arg = mid.getNode() and
24062381
cc = mid.getCallContext() and
24072382
arg.argumentOf(call, i) and
2408-
ap = mid.getAp().getUntyped()
2383+
ap = mid.getAp()
24092384
)
24102385
}
24112386

24122387
pragma[noinline]
24132388
private predicate parameterCand(
2414-
DataFlowCallable callable, int i, UntypedAccessPath ap, Configuration config
2389+
DataFlowCallable callable, int i, AccessPath ap, Configuration config
24152390
) {
24162391
exists(ParameterNode p |
2417-
flow(TNormalNode(p), _, ap.getATyped(), config) and
2392+
flow(TNormalNode(p), _, ap, config) and
24182393
p.isParameterOf(callable, i)
24192394
)
24202395
}
24212396

24222397
pragma[nomagic]
24232398
private predicate pathIntoCallable0(
24242399
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
2425-
UntypedAccessPath ap
2400+
AccessPath ap
24262401
) {
24272402
pathIntoArg(mid, i, outercc, call, ap) and
24282403
callable = resolveCall(call, outercc) and
@@ -2438,7 +2413,7 @@ private predicate pathIntoCallable(
24382413
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
24392414
DataFlowCall call
24402415
) {
2441-
exists(int i, DataFlowCallable callable, UntypedAccessPath ap |
2416+
exists(int i, DataFlowCallable callable, AccessPath ap |
24422417
pathIntoCallable0(mid, callable, i, outercc, call, ap) and
24432418
p.isParameterOf(callable, i) and
24442419
(
@@ -2457,7 +2432,7 @@ private predicate pathIntoCallable(
24572432
/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */
24582433
pragma[nomagic]
24592434
private predicate paramFlowsThrough(
2460-
ReturnKindExt kind, CallContextCall cc, TSummaryCtxSome sc, AccessPath ap, Configuration config
2435+
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config
24612436
) {
24622437
exists(PathNodeMid mid, ReturnNodeExt ret |
24632438
mid.getNode() = ret and
@@ -2635,14 +2610,7 @@ private module FlowExploration {
26352610

26362611
private newtype TSummaryCtx2 =
26372612
TSummaryCtx2None() or
2638-
TSummaryCtx2Nil() or
2639-
TSummaryCtx2ConsNil(Content f)
2640-
2641-
private TSummaryCtx2 getSummaryCtx2(PartialAccessPath ap) {
2642-
result = TSummaryCtx2Nil() and ap instanceof PartialAccessPathNil
2643-
or
2644-
exists(Content f | result = TSummaryCtx2ConsNil(f) and ap = TPartialCons(f, 1))
2645-
}
2613+
TSummaryCtx2Some(PartialAccessPath ap)
26462614

26472615
private newtype TPartialPathNode =
26482616
TPartialPathNodeMk(
@@ -2929,11 +2897,8 @@ private module FlowExploration {
29292897
exists(int i, DataFlowCallable callable |
29302898
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
29312899
p.isParameterOf(callable, i) and
2932-
(
2933-
sc1 = TSummaryCtx1Param(p) and sc2 = getSummaryCtx2(ap)
2934-
or
2935-
sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and not exists(getSummaryCtx2(ap))
2936-
)
2900+
sc1 = TSummaryCtx1Param(p) and
2901+
sc2 = TSummaryCtx2Some(ap)
29372902
|
29382903
if recordDataFlowCallSite(call, callable)
29392904
then innercc = TSpecificCall(call)
@@ -2953,8 +2918,7 @@ private module FlowExploration {
29532918
sc1 = mid.getSummaryCtx1() and
29542919
sc2 = mid.getSummaryCtx2() and
29552920
config = mid.getConfiguration() and
2956-
ap = mid.getAp() and
2957-
ap.len() in [0 .. 1]
2921+
ap = mid.getAp()
29582922
)
29592923
}
29602924

0 commit comments

Comments
 (0)