Skip to content

Commit 5251c65

Browse files
committed
C++: Add MaD support for models that specify argument forwarding.
1 parent 8560e34 commit 5251c65

5 files changed

Lines changed: 90 additions & 1 deletion

File tree

cpp/ql/lib/ext/empty.model.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,7 @@ extensions:
2121
pack: codeql/cpp-all
2222
extensible: summaryModel
2323
data: []
24+
- addsTo:
25+
pack: codeql/cpp-all
26+
extensible: forwardsModel
27+
data: []

cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
* `namespace; type; subtypes; name; signature; ext; output; kind; provenance`
1616
* - BarrierGuards:
1717
* `namespace; type; subtypes; name; signature; ext; input; acceptingValue; kind; provenance`
18+
* - Forwards:
19+
* `namespace; type; subtypes; name; signature; ext; start; constructor; provenance`
1820
*
1921
* The interpretation of a row is similar to API-graphs with a left-to-right
2022
* reading.
@@ -160,6 +162,20 @@ predicate summaryModel(
160162
)
161163
}
162164

165+
/**
166+
* Holds if a forward model exists for the given parameters.
167+
*/
168+
predicate forwardsModel(
169+
string namespace, string type, boolean subtypes, string name, string signature, string ext,
170+
string start, string constructor, string provenance, string model
171+
) {
172+
exists(QlBuiltins::ExtensionId madId |
173+
Extensions::forwardsModel(namespace, type, subtypes, name, signature, ext, start, constructor,
174+
provenance, madId) and
175+
model = madId.toString()
176+
)
177+
}
178+
163179
/** Provides a query predicate to check the data for validation errors. */
164180
module ModelValidation {
165181
private string getInvalidModelInput() {
@@ -259,7 +275,8 @@ private predicate elementSpec(
259275
sinkModel(namespace, type, subtypes, name, signature, ext, _, _, _, _) or
260276
barrierModel(namespace, type, subtypes, name, signature, ext, _, _, _, _) or
261277
barrierGuardModel(namespace, type, subtypes, name, signature, ext, _, _, _, _, _) or
262-
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _, _, _)
278+
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _, _, _) or
279+
forwardsModel(namespace, type, subtypes, name, signature, ext, _, _, _, _)
263280
}
264281

265282
/**
@@ -1054,6 +1071,46 @@ private module Cached {
10541071

10551072
import Cached
10561073

1074+
/** Gets the constructor type selected by `constructorType` in a forwarding model. */
1075+
bindingset[forwarder, type, name, constructorType]
1076+
private Type getForwardedConstructorType(
1077+
Function forwarder, string type, string name, string constructorType
1078+
) {
1079+
exists(string typeArguments, int index |
1080+
parseAngles(type, _, typeArguments, "") and
1081+
constructorType = getAtIndex(typeArguments, index) and
1082+
result = forwarder.getDeclaringType().getTemplateArgument(index)
1083+
)
1084+
or
1085+
exists(string nameArguments, int index |
1086+
parseAngles(name, _, nameArguments, "") and
1087+
constructorType = getAtIndex(nameArguments, index) and
1088+
result = forwarder.getTemplateArgument(index)
1089+
)
1090+
}
1091+
1092+
/** Holds if `forwarder` forwards its arguments starting at `start` to `constructor`. */
1093+
predicate forwards(Function forwarder, Constructor constructor, int start) {
1094+
exists(
1095+
string namespace, string type, boolean subtypes, string name, string signature, string ext,
1096+
string startString, string constructorType
1097+
|
1098+
forwardsModel(namespace, type, subtypes, name, signature, ext, startString, constructorType, _,
1099+
_) and
1100+
forwarder = interpretElement(namespace, type, subtypes, name, signature, ext) and
1101+
start = startString.toInt()
1102+
|
1103+
// Either the row specifies forwarding to a type given by the type or
1104+
// function template, in which case we need to resolve that from the type
1105+
// or function name.
1106+
constructor.getDeclaringType() =
1107+
getForwardedConstructorType(forwarder, type, name, constructorType).getUnspecifiedType()
1108+
or
1109+
// Or the row specifies forwarding to a specific type.
1110+
classHasQualifiedName(constructor.getDeclaringType(), namespace, constructorType)
1111+
)
1112+
}
1113+
10571114
/**
10581115
* Holds if `node` is specified as a source with the given kind in a MaD flow
10591116
* model.

cpp/ql/lib/semmle/code/cpp/dataflow/internal/ExternalFlowExtensions.qll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@ extensible predicate summaryModel(
4444
string input, string output, string kind, string provenance, QlBuiltins::ExtensionId madId
4545
);
4646

47+
/**
48+
* Holds if an external constructor forwarding model exists for the given parameters.
49+
*/
50+
extensible predicate forwardsModel(
51+
string namespace, string type, boolean subtypes, string name, string signature, string ext,
52+
string start, string constructor, string provenance, QlBuiltins::ExtensionId madId
53+
);
54+
4755
/**
4856
* Holds if a neutral model exists for the given parameters.
4957
*/

cpp/ql/lib/semmle/code/cpp/dataflow/internal/FlowSummaryImpl.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
111111
pos = -1 and result = TIndirectionPosition(pos, indirection + 1)
112112
)
113113
)
114+
or
115+
argString = "forward" and
116+
result = TForwardPosition()
114117
}
115118

116119
bindingset[token]

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,12 @@ abstract class Position extends TPosition {
672672
this.getArgumentIndex() = -1 and
673673
result = call.getQualifier()
674674
}
675+
676+
/**
677+
* Holds if this position is the synthetic argument for an address of a
678+
* constructor used for functions which perform "perfect forwarding".
679+
*/
680+
predicate isForward() { none() }
675681
}
676682

677683
class DirectPosition extends Position, TDirectPosition {
@@ -721,6 +727,16 @@ class FlowSummaryPosition extends Position, TFlowSummaryPosition {
721727
final override int getIndirectionIndex() { result = rk.getIndirectionIndex() }
722728
}
723729

730+
class ForwardPosition extends Position, TForwardPosition {
731+
final override predicate isForward() { any() }
732+
733+
override int getArgumentIndex() { none() }
734+
735+
final override int getIndirectionIndex() { result = 0 }
736+
737+
override string toString() { result = "forward" }
738+
}
739+
724740
newtype TPosition =
725741
TDirectPosition(int argumentIndex) {
726742
exists(any(CallInstruction c).getArgument(argumentIndex))
@@ -740,6 +756,7 @@ newtype TPosition =
740756
indirectionIndex = [1 .. Ssa::getMaxIndirectionsForType(p.getUnspecifiedType()) - 1]
741757
)
742758
} or
759+
TForwardPosition() or
743760
TFlowSummaryPosition(ReturnKind rk) { FlowSummaryImpl::Private::relevantFlowSummaryPosition(rk) }
744761

745762
private newtype TReturnKind =

0 commit comments

Comments
 (0)