Merge branch 'main' of https://github.com/github/codeql into oscarsj/merge-back-rc-3.20

This commit is contained in:
Óscar San José
2025-12-05 19:31:47 +01:00
602 changed files with 25261 additions and 3631 deletions

View File

@@ -75,6 +75,9 @@ module MakeImplContentDataFlow<LocationSig Location, InputSig<Location> Lang> {
/** Gets a limit on the number of reads out of sources and number of stores into sinks. */
default int accessPathLimit() { result = Lang::accessPathLimit() }
/** Gets the access path limit used in the internal invocation of the standard data flow library. */
default int accessPathLimitInternal() { result = Lang::accessPathLimit() }
/** Holds if `c` is relevant for reads out of sources or stores into sinks. */
default predicate isRelevantContent(ContentSet c) { any() }
}
@@ -110,7 +113,7 @@ module MakeImplContentDataFlow<LocationSig Location, InputSig<Location> Lang> {
FlowFeature getAFeature() { result = ContentConfig::getAFeature() }
predicate accessPathLimit = ContentConfig::accessPathLimit/0;
predicate accessPathLimit = ContentConfig::accessPathLimitInternal/0;
// needed to record reads/stores inside summarized callables
predicate includeHiddenNodes() { any() }
@@ -274,6 +277,16 @@ module MakeImplContentDataFlow<LocationSig Location, InputSig<Location> Lang> {
)
}
/**
* Gets the length of this access path.
*/
int length() {
this = TAccessPathNil() and
result = 0
or
result = this.getTail().length() + 1
}
/**
* Gets the content set at index `i` in this access path, if any.
*/

View File

@@ -207,6 +207,28 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
flowLocal(source, sink) and Config::observeOverlayInformedIncrementalMode()
}
/**
* Holds if data can flow from `source` to some sink.
* This is a local predicate that only has results local to the overlay/base database.
*/
predicate flowFromLocal(Node source) = forceLocal(Flow::flowFrom/1)(source)
/**
* Holds if data can flow from `source` to some sink.
*/
predicate flowFrom(Node source) {
Flow::flowFrom(source)
or
// If we are overlay informed (i.e. we are not diff-informed), we
// merge in the local results which includes the base database results.
flowFromLocal(source) and Config::observeOverlayInformedIncrementalMode()
}
/**
* Holds if data can flow from `source` to some sink.
*/
predicate flowFromExpr(Lang::DataFlowExpr source) { flowFrom(exprNode(source)) }
/**
* Holds if data can flow from some source to `sink`.
* This is a local predicate that only has results local to the overlay/base database.
@@ -3501,6 +3523,16 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
)
}
/**
* Holds if data can flow from `source` to some sink.
*/
predicate flowFrom(Node source) { exists(PathNode n | n.isSource() and n.getNode() = source) }
/**
* Holds if data can flow from `source` to some sink.
*/
predicate flowFromExpr(Expr source) { flowFrom(exprNode(source)) }
/**
* Holds if data can flow from some source to `sink`.
*/

View File

@@ -74,6 +74,9 @@ signature module InputSig<LocationSig Location, DF::InputSig<Location> DataFlowL
) {
none()
}
/** Holds if `(n1, n2)` should be excluded from the consistency test `localFlowIsLocal`. */
default predicate localFlowIsLocalExclude(DataFlowLang::Node n1, DataFlowLang::Node n2) { none() }
}
module MakeConsistency<
@@ -169,6 +172,7 @@ module MakeConsistency<
query predicate localFlowIsLocal(Node n1, Node n2, string msg) {
simpleLocalFlowStep(n1, n2, _) and
nodeGetEnclosingCallable(n1) != nodeGetEnclosingCallable(n2) and
not Input::localFlowIsLocalExclude(n1, n2) and
msg = "Local flow step does not preserve enclosing callable."
}
@@ -240,6 +244,13 @@ module MakeConsistency<
private predicate hasPost(Node n) { exists(PostUpdateNode post | post.getPreUpdateNode() = n) }
/**
* Consider code like `a.b.f = source()`. There is flow from `source()` to
* `[post] a.b` (with an appropriate access path), but we also want there to
* be flow to `[post] a` (with an appropriate access path). The data flow
* library is able to infer this step because there is a read step from `a`
* to `a.b`, as long as the post-update node for `a` exists.
*/
query predicate reverseRead(Node n, string msg) {
exists(Node n2 | readStep(n, _, n2) and hasPost(n2) and not hasPost(n)) and
not Input::reverseReadExclude(n) and

View File

@@ -277,6 +277,16 @@ module MakeModelGeneratorFactory<
*/
predicate isAdditionalContentFlowStep(Lang::Node nodeFrom, Lang::Node nodeTo);
/**
* Gets the access path limit for content flow analysis.
*/
default int contentAccessPathLimit() { result = 2 }
/**
* Gets the internal access path limit for content flow analysis.
*/
default int contentAccessPathLimitInternal() { result = Lang::accessPathLimit() }
/**
* Holds if the content set `c` is field like.
*/
@@ -650,7 +660,10 @@ module MakeModelGeneratorFactory<
exists(Type t | t = n.(NodeExtended).getType() and not isRelevantType(t))
}
int accessPathLimit() { result = 2 }
predicate accessPathLimit = SummaryModelGeneratorInput::contentAccessPathLimit/0;
predicate accessPathLimitInternal =
SummaryModelGeneratorInput::contentAccessPathLimitInternal/0;
predicate isRelevantContent(DataFlow::ContentSet s) { isRelevantContent0(s) }
@@ -703,14 +716,17 @@ module MakeModelGeneratorFactory<
}
/**
* Holds if the access path `ap` is not a parameter or returnvalue of a callback
* stored in a field.
* Holds if `ap` is valid for generating summary models.
*
* That is, we currently don't include summaries that rely on parameters or return values
* of callbacks stored in fields.
* We currently don't include summaries that rely on parameters or return values
* of callbacks stored in fields, as those are not supported by the data flow
* library.
*
* We also exclude access paths with contents not supported by `printContent`.
*/
private predicate validateAccessPath(PropagateContentFlow::AccessPath ap) {
not (mentionsField(ap) and mentionsCallback(ap))
not (mentionsField(ap) and mentionsCallback(ap)) and
forall(int i | i in [0 .. ap.length() - 1] | exists(getContent(ap, i)))
}
private predicate apiFlow(
@@ -720,7 +736,9 @@ module MakeModelGeneratorFactory<
) {
PropagateContentFlow::flow(p, reads, returnNodeExt, stores, preservesValue) and
getEnclosingCallable(returnNodeExt) = api and
getEnclosingCallable(p) = api
getEnclosingCallable(p) = api and
validateAccessPath(reads) and
validateAccessPath(stores)
}
/**
@@ -763,9 +781,7 @@ module MakeModelGeneratorFactory<
PropagateContentFlow::AccessPath reads, ReturnNodeExt returnNodeExt,
PropagateContentFlow::AccessPath stores, boolean preservesValue
) {
PropagateContentFlow::flow(p, reads, returnNodeExt, stores, preservesValue) and
getEnclosingCallable(returnNodeExt) = api and
getEnclosingCallable(p) = api and
apiFlow(api, p, reads, returnNodeExt, stores, preservesValue) and
p = api.getARelevantParameterNode()
}
@@ -956,8 +972,6 @@ module MakeModelGeneratorFactory<
input = parameterNodeAsExactInput(p) + printReadAccessPath(reads) and
output = getExactOutput(returnNodeExt) + printStoreAccessPath(stores) and
input != output and
validateAccessPath(reads) and
validateAccessPath(stores) and
(
if mentionsField(reads) or mentionsField(stores)
then lift = false and api.isRelevant()