mirror of
https://github.com/github/codeql.git
synced 2026-04-21 23:14:03 +02:00
Merge pull request #19295 from MathiasVP/cpp-add-mad-generation-library
C++: Instantiate model generation library
This commit is contained in:
5
cpp/ql/lib/ext/generated/empty.model.yml
Normal file
5
cpp/ql/lib/ext/generated/empty.model.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: summaryModel
|
||||
data: []
|
||||
@@ -16,6 +16,7 @@ dependencies:
|
||||
codeql/xml: ${workspace}
|
||||
dataExtensions:
|
||||
- ext/*.model.yml
|
||||
- ext/generated/*.model.yml
|
||||
- ext/deallocation/*.model.yml
|
||||
- ext/allocation/*.model.yml
|
||||
warnOnImplicitThis: true
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* @name Capture content based summary models.
|
||||
* @description Finds applicable content based summary models to be used by other queries.
|
||||
* @kind diagnostic
|
||||
* @id cpp/utils/modelgenerator/contentbased-summary-models
|
||||
* @tags modelgenerator
|
||||
*/
|
||||
|
||||
import internal.CaptureModels
|
||||
|
||||
from DataFlowSummaryTargetApi api, string flow
|
||||
where flow = ContentSensitive::captureFlow(api, _)
|
||||
select flow order by flow
|
||||
13
cpp/ql/src/utils/modelgenerator/CaptureMixedNeutralModels.ql
Normal file
13
cpp/ql/src/utils/modelgenerator/CaptureMixedNeutralModels.ql
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* @name Capture mixed neutral models.
|
||||
* @description Finds neutral models to be used by other queries.
|
||||
* @kind diagnostic
|
||||
* @id cpp/utils/modelgenerator/mixed-neutral-models
|
||||
* @tags modelgenerator
|
||||
*/
|
||||
|
||||
import internal.CaptureModels
|
||||
|
||||
from DataFlowSummaryTargetApi api, string noflow
|
||||
where noflow = captureMixedNeutral(api)
|
||||
select noflow order by noflow
|
||||
13
cpp/ql/src/utils/modelgenerator/CaptureMixedSummaryModels.ql
Normal file
13
cpp/ql/src/utils/modelgenerator/CaptureMixedSummaryModels.ql
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* @name Capture mixed summary models.
|
||||
* @description Finds applicable summary models to be used by other queries.
|
||||
* @kind diagnostic
|
||||
* @id cpp/utils/modelgenerator/mixed-summary-models
|
||||
* @tags modelgenerator
|
||||
*/
|
||||
|
||||
import internal.CaptureModels
|
||||
|
||||
from DataFlowSummaryTargetApi api, string flow
|
||||
where flow = captureMixedFlow(api, _)
|
||||
select flow order by flow
|
||||
13
cpp/ql/src/utils/modelgenerator/CaptureNeutralModels.ql
Normal file
13
cpp/ql/src/utils/modelgenerator/CaptureNeutralModels.ql
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* @name Capture neutral models.
|
||||
* @description Finds neutral models to be used by other queries.
|
||||
* @kind diagnostic
|
||||
* @id cpp/utils/modelgenerator/neutral-models
|
||||
* @tags modelgenerator
|
||||
*/
|
||||
|
||||
import internal.CaptureModels
|
||||
|
||||
from DataFlowSummaryTargetApi api, string noflow
|
||||
where noflow = captureNoFlow(api)
|
||||
select noflow order by noflow
|
||||
13
cpp/ql/src/utils/modelgenerator/CaptureSinkModels.ql
Normal file
13
cpp/ql/src/utils/modelgenerator/CaptureSinkModels.ql
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* @name Capture sink models.
|
||||
* @description Finds public methods that act as sinks as they flow into a known sink.
|
||||
* @kind diagnostic
|
||||
* @id cpp/utils/modelgenerator/sink-models
|
||||
* @tags modelgenerator
|
||||
*/
|
||||
|
||||
import internal.CaptureModels
|
||||
|
||||
from DataFlowSinkTargetApi api, string sink
|
||||
where sink = captureSink(api)
|
||||
select sink order by sink
|
||||
13
cpp/ql/src/utils/modelgenerator/CaptureSourceModels.ql
Normal file
13
cpp/ql/src/utils/modelgenerator/CaptureSourceModels.ql
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* @name Capture source models.
|
||||
* @description Finds APIs that act as sources as they expose already known sources.
|
||||
* @kind diagnostic
|
||||
* @id cpp/utils/modelgenerator/source-models
|
||||
* @tags modelgenerator
|
||||
*/
|
||||
|
||||
import internal.CaptureModels
|
||||
|
||||
from DataFlowSourceTargetApi api, string source
|
||||
where source = captureSource(api)
|
||||
select source order by source
|
||||
13
cpp/ql/src/utils/modelgenerator/CaptureSummaryModels.ql
Normal file
13
cpp/ql/src/utils/modelgenerator/CaptureSummaryModels.ql
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* @name Capture summary models.
|
||||
* @description Finds applicable summary models to be used by other queries.
|
||||
* @kind diagnostic
|
||||
* @id cpp/utils/modelgenerator/summary-models
|
||||
* @tags modelgenerator
|
||||
*/
|
||||
|
||||
import internal.CaptureModels
|
||||
|
||||
from DataFlowSummaryTargetApi api, string flow
|
||||
where flow = captureFlow(api)
|
||||
select flow order by flow
|
||||
15
cpp/ql/src/utils/modelgenerator/GenerateFlowModel.py
Normal file
15
cpp/ql/src/utils/modelgenerator/GenerateFlowModel.py
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import sys
|
||||
import os.path
|
||||
import subprocess
|
||||
|
||||
# Add Model as Data script directory to sys.path.
|
||||
gitroot = subprocess.check_output(["git", "rev-parse", "--show-toplevel"]).decode("utf-8").strip()
|
||||
madpath = os.path.join(gitroot, "misc/scripts/models-as-data/")
|
||||
sys.path.append(madpath)
|
||||
|
||||
import generate_flow_model as model
|
||||
|
||||
language = "cpp"
|
||||
model.Generator.make(language).run()
|
||||
404
cpp/ql/src/utils/modelgenerator/internal/CaptureModels.qll
Normal file
404
cpp/ql/src/utils/modelgenerator/internal/CaptureModels.qll
Normal file
@@ -0,0 +1,404 @@
|
||||
/**
|
||||
* Provides predicates related to capturing summary models of the Standard or a 3rd party library.
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.dataflow.ExternalFlow as ExternalFlow
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplSpecific
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate as DataFlowPrivate
|
||||
private import semmle.code.cpp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
|
||||
private import semmle.code.cpp.ir.dataflow.internal.TaintTrackingImplSpecific
|
||||
private import semmle.code.cpp.dataflow.new.TaintTracking
|
||||
private import codeql.mad.modelgenerator.internal.ModelGeneratorImpl
|
||||
|
||||
module ModelGeneratorInput implements ModelGeneratorInputSig<Location, CppDataFlow> {
|
||||
class Type = DataFlowPrivate::DataFlowType;
|
||||
|
||||
// Note: This also includes `this`
|
||||
class Parameter = DataFlow::ParameterNode;
|
||||
|
||||
class Callable = Declaration;
|
||||
|
||||
class NodeExtended extends DataFlow::Node {
|
||||
Callable getAsExprEnclosingCallable() { result = this.asExpr().getEnclosingDeclaration() }
|
||||
}
|
||||
|
||||
Parameter asParameter(NodeExtended n) { result = n }
|
||||
|
||||
Callable getEnclosingCallable(NodeExtended n) {
|
||||
result = n.getEnclosingCallable().asSourceCallable()
|
||||
}
|
||||
|
||||
Callable getAsExprEnclosingCallable(NodeExtended n) {
|
||||
result = n.asExpr().getEnclosingDeclaration()
|
||||
}
|
||||
|
||||
/** Gets `api` if it is relevant. */
|
||||
private Callable liftedImpl(Callable api) { result = api and relevant(api) }
|
||||
|
||||
private predicate hasManualSummaryModel(Callable api) {
|
||||
api = any(FlowSummaryImpl::Public::SummarizedCallable sc | sc.applyManualModel()) or
|
||||
api = any(FlowSummaryImpl::Public::NeutralSummaryCallable sc | sc.hasManualModel())
|
||||
}
|
||||
|
||||
private predicate hasManualSourceModel(Callable api) {
|
||||
api = any(FlowSummaryImpl::Public::NeutralSourceCallable sc | sc.hasManualModel())
|
||||
}
|
||||
|
||||
private predicate hasManualSinkModel(Callable api) {
|
||||
api = any(FlowSummaryImpl::Public::NeutralSinkCallable sc | sc.hasManualModel())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `f` is a "private" function.
|
||||
*
|
||||
* A "private" function does not contribute any models as it is assumed
|
||||
* to be an implementation detail of some other "public" function for which
|
||||
* we will generate a summary.
|
||||
*/
|
||||
private predicate isPrivateOrProtected(Function f) {
|
||||
f.getNamespace().getParentNamespace*().isAnonymous()
|
||||
or
|
||||
exists(MemberFunction mf | mf = f |
|
||||
mf.isPrivate()
|
||||
or
|
||||
mf.isProtected()
|
||||
)
|
||||
or
|
||||
f.isStatic()
|
||||
}
|
||||
|
||||
private predicate isUninterestingForModels(Callable api) {
|
||||
// Note: This also makes all global/static-local variables
|
||||
// not relevant (which is good!)
|
||||
not api.(Function).hasDefinition()
|
||||
or
|
||||
isPrivateOrProtected(api)
|
||||
or
|
||||
api instanceof Destructor
|
||||
or
|
||||
api = any(LambdaExpression lambda).getLambdaFunction()
|
||||
or
|
||||
api.isFromUninstantiatedTemplate(_)
|
||||
}
|
||||
|
||||
private predicate relevant(Callable api) {
|
||||
api.fromSource() and
|
||||
not isUninterestingForModels(api)
|
||||
}
|
||||
|
||||
class SummaryTargetApi extends Callable {
|
||||
private Callable lift;
|
||||
|
||||
SummaryTargetApi() {
|
||||
lift = liftedImpl(this) and
|
||||
not hasManualSummaryModel(lift)
|
||||
}
|
||||
|
||||
Callable lift() { result = lift }
|
||||
|
||||
predicate isRelevant() {
|
||||
relevant(this) and
|
||||
not hasManualSummaryModel(this)
|
||||
}
|
||||
}
|
||||
|
||||
class SourceOrSinkTargetApi extends Callable {
|
||||
SourceOrSinkTargetApi() { relevant(this) }
|
||||
}
|
||||
|
||||
class SinkTargetApi extends SourceOrSinkTargetApi {
|
||||
SinkTargetApi() { not hasManualSinkModel(this) }
|
||||
}
|
||||
|
||||
class SourceTargetApi extends SourceOrSinkTargetApi {
|
||||
SourceTargetApi() { not hasManualSourceModel(this) }
|
||||
}
|
||||
|
||||
class InstanceParameterNode extends DataFlow::ParameterNode {
|
||||
InstanceParameterNode() {
|
||||
DataFlowPrivate::nodeHasInstruction(this,
|
||||
any(InitializeParameterInstruction i | i.hasIndex(-1)), 1)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate isFinalMemberFunction(MemberFunction mf) {
|
||||
mf.isFinal()
|
||||
or
|
||||
mf.getDeclaringType().isFinal()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the summary generated for `c` should also apply to overrides
|
||||
* of `c`.
|
||||
*/
|
||||
private string isExtensible(Callable c) {
|
||||
if isFinalMemberFunction(c) then result = "false" else result = "true"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the string representing the list of template parameters declared
|
||||
* by `template`.
|
||||
*
|
||||
* `template` must either be:
|
||||
* - An uninstantiated template, or
|
||||
* - A declaration that is not from a template instantiation.
|
||||
*/
|
||||
private string templateParams(Declaration template) {
|
||||
exists(string params |
|
||||
params =
|
||||
concat(int i |
|
||||
|
|
||||
template.getTemplateArgument(i).(TypeTemplateParameter).getName(), "," order by i
|
||||
)
|
||||
|
|
||||
if params = "" then result = "" else result = "<" + params + ">"
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the string representing the list of parameters declared
|
||||
* by `functionTemplate`.
|
||||
*
|
||||
* `functionTemplate` must either be:
|
||||
* - An uninstantiated template, or
|
||||
* - A declaration that is not from a template instantiation.
|
||||
*/
|
||||
private string params(Function functionTemplate) {
|
||||
exists(string params |
|
||||
params =
|
||||
concat(int i |
|
||||
|
|
||||
ExternalFlow::getParameterTypeWithoutTemplateArguments(functionTemplate, i, true), ","
|
||||
order by
|
||||
i
|
||||
) and
|
||||
result = "(" + params + ")"
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the callable `c` is:
|
||||
* - In the namespace represented by `namespace`, and
|
||||
* - Has a declaring type represented by `type`, and
|
||||
* - Has the name `name`, and
|
||||
* - Has a list of parameters represented by `params`
|
||||
*
|
||||
* This is the predicate that computes the columns that it put into the MaD
|
||||
* row for `callable`.
|
||||
*/
|
||||
private predicate qualifiedName(
|
||||
Callable callable, string namespace, string type, string name, string params
|
||||
) {
|
||||
exists(
|
||||
Function functionTemplate, string typeWithoutTemplateArgs, string nameWithoutTemplateArgs
|
||||
|
|
||||
functionTemplate = ExternalFlow::getFullyTemplatedFunction(callable) and
|
||||
functionTemplate.hasQualifiedName(namespace, typeWithoutTemplateArgs, nameWithoutTemplateArgs) and
|
||||
nameWithoutTemplateArgs = functionTemplate.getName() and
|
||||
name = nameWithoutTemplateArgs + templateParams(functionTemplate) and
|
||||
params = params(functionTemplate)
|
||||
|
|
||||
exists(Class classTemplate |
|
||||
classTemplate = functionTemplate.getDeclaringType() and
|
||||
type = typeWithoutTemplateArgs + templateParams(classTemplate)
|
||||
)
|
||||
or
|
||||
not exists(functionTemplate.getDeclaringType()) and
|
||||
type = ""
|
||||
)
|
||||
}
|
||||
|
||||
predicate isRelevantType(Type t) { any() }
|
||||
|
||||
Type getUnderlyingContentType(DataFlow::ContentSet c) {
|
||||
result = c.(DataFlow::FieldContent).getField().getUnspecifiedType() or
|
||||
result = c.(DataFlow::UnionContent).getUnion().getUnspecifiedType()
|
||||
}
|
||||
|
||||
string qualifierString() { result = "Argument[-1]" }
|
||||
|
||||
private predicate parameterContentAccessImpl(Parameter p, string argument) {
|
||||
exists(int indirectionIndex, int argumentIndex, DataFlowPrivate::Position pos |
|
||||
p.isSourceParameterOf(_, pos) and
|
||||
pos.getArgumentIndex() = argumentIndex and
|
||||
argumentIndex != -1 and // handled elsewhere
|
||||
pos.getIndirectionIndex() = indirectionIndex
|
||||
|
|
||||
indirectionIndex = 0 and
|
||||
argument = "Argument[" + argumentIndex + "]"
|
||||
or
|
||||
indirectionIndex > 0 and
|
||||
argument = "Argument[" + DataFlow::repeatStars(indirectionIndex) + argumentIndex + "]"
|
||||
)
|
||||
}
|
||||
|
||||
string parameterAccess(Parameter p) { parameterContentAccessImpl(p, result) }
|
||||
|
||||
string parameterContentAccess(Parameter p) { parameterContentAccessImpl(p, result) }
|
||||
|
||||
bindingset[c]
|
||||
string paramReturnNodeAsOutput(Callable c, DataFlowPrivate::Position pos) {
|
||||
exists(Parameter p |
|
||||
p.isSourceParameterOf(c, pos) and
|
||||
result = parameterAccess(p)
|
||||
)
|
||||
or
|
||||
pos.getArgumentIndex() = -1 and
|
||||
result = qualifierString() and
|
||||
pos.getIndirectionIndex() = 1
|
||||
}
|
||||
|
||||
bindingset[c]
|
||||
string paramReturnNodeAsContentOutput(Callable c, DataFlowPrivate::ParameterPosition pos) {
|
||||
result = paramReturnNodeAsOutput(c, pos)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
Callable returnNodeEnclosingCallable(DataFlow::Node ret) {
|
||||
result = DataFlowImplCommon::getNodeEnclosingCallable(ret).asSourceCallable()
|
||||
}
|
||||
|
||||
/** Holds if this instance access is to an enclosing instance of type `t`. */
|
||||
pragma[nomagic]
|
||||
private predicate isEnclosingInstanceAccess(DataFlowPrivate::ReturnNode n, Class t) {
|
||||
n.getKind().isIndirectReturn(-1) and
|
||||
t = n.getType().stripType() and
|
||||
t != n.getEnclosingCallable().asSourceCallable().(Function).getDeclaringType()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate isOwnInstanceAccessNode(DataFlowPrivate::ReturnNode node) {
|
||||
node.getKind().isIndirectReturn(-1) and
|
||||
not isEnclosingInstanceAccess(node, _)
|
||||
}
|
||||
|
||||
predicate sinkModelSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
predicate apiSource(DataFlow::Node source) {
|
||||
DataFlowPrivate::nodeHasOperand(source, any(DataFlow::FieldAddress fa), 1)
|
||||
or
|
||||
source instanceof DataFlow::ParameterNode
|
||||
}
|
||||
|
||||
string getInputArgument(DataFlow::Node source) {
|
||||
exists(DataFlowPrivate::Position pos, int argumentIndex, int indirectionIndex |
|
||||
source.(DataFlow::ParameterNode).isParameterOf(_, pos) and
|
||||
argumentIndex = pos.getArgumentIndex() and
|
||||
indirectionIndex = pos.getIndirectionIndex() and
|
||||
result = "Argument[" + DataFlow::repeatStars(indirectionIndex) + argumentIndex + "]"
|
||||
)
|
||||
or
|
||||
DataFlowPrivate::nodeHasOperand(source, any(DataFlow::FieldAddress fa), 1) and
|
||||
result = qualifierString()
|
||||
}
|
||||
|
||||
string getReturnValueString(DataFlowPrivate::ReturnKind k) {
|
||||
k.isNormalReturn() and
|
||||
exists(int indirectionIndex | indirectionIndex = k.getIndirectionIndex() |
|
||||
indirectionIndex = 0 and
|
||||
result = "ReturnValue"
|
||||
or
|
||||
indirectionIndex > 0 and
|
||||
result = "ReturnValue[" + DataFlow::repeatStars(indirectionIndex) + "]"
|
||||
)
|
||||
}
|
||||
|
||||
predicate irrelevantSourceSinkApi(Callable source, SourceTargetApi api) { none() }
|
||||
|
||||
bindingset[kind]
|
||||
predicate isRelevantSourceKind(string kind) { any() }
|
||||
|
||||
bindingset[kind]
|
||||
predicate isRelevantSinkKind(string kind) { any() }
|
||||
|
||||
predicate containerContent(DataFlow::ContentSet cs) { cs instanceof DataFlow::ElementContent }
|
||||
|
||||
predicate isAdditionalContentFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
TaintTracking::defaultAdditionalTaintStep(node1, node2, _) and
|
||||
not exists(DataFlow::Content f |
|
||||
DataFlowPrivate::readStep(node1, f, node2) and containerContent(f)
|
||||
)
|
||||
}
|
||||
|
||||
predicate isField(DataFlow::ContentSet cs) {
|
||||
exists(DataFlow::Content c | cs.isSingleton(c) |
|
||||
c instanceof DataFlow::FieldContent or
|
||||
c instanceof DataFlow::UnionContent
|
||||
)
|
||||
}
|
||||
|
||||
predicate isCallback(DataFlow::ContentSet c) { none() }
|
||||
|
||||
string getSyntheticName(DataFlow::ContentSet c) {
|
||||
exists(Field f |
|
||||
not f.isPublic() and
|
||||
f = c.(DataFlow::FieldContent).getField() and
|
||||
result = f.getName()
|
||||
)
|
||||
}
|
||||
|
||||
string printContent(DataFlow::ContentSet c) {
|
||||
exists(int indirectionIndex, string name, string kind |
|
||||
exists(DataFlow::UnionContent uc |
|
||||
c.isSingleton(uc) and
|
||||
name = uc.getUnion().getName() and
|
||||
indirectionIndex = uc.getIndirectionIndex() and
|
||||
// Note: We don't actually support the union string in MaD, but we should do that eventually
|
||||
kind = "Union["
|
||||
)
|
||||
or
|
||||
exists(DataFlow::FieldContent fc |
|
||||
c.isSingleton(fc) and
|
||||
name = fc.getField().getName() and
|
||||
indirectionIndex = fc.getIndirectionIndex() and
|
||||
kind = "Field["
|
||||
)
|
||||
|
|
||||
result = kind + DataFlow::repeatStars(indirectionIndex) + name + "]"
|
||||
)
|
||||
or
|
||||
exists(DataFlow::ElementContent ec |
|
||||
c.isSingleton(ec) and
|
||||
result = "Element[" + ec.getIndirectionIndex() + "]"
|
||||
)
|
||||
}
|
||||
|
||||
predicate isUninterestingForDataFlowModels(Callable api) { none() }
|
||||
|
||||
predicate isUninterestingForHeuristicDataFlowModels(Callable api) {
|
||||
isUninterestingForDataFlowModels(api)
|
||||
}
|
||||
|
||||
string partialModelRow(Callable api, int i) {
|
||||
i = 0 and qualifiedName(api, result, _, _, _) // namespace
|
||||
or
|
||||
i = 1 and qualifiedName(api, _, result, _, _) // type
|
||||
or
|
||||
i = 2 and result = isExtensible(api) // extensible
|
||||
or
|
||||
i = 3 and qualifiedName(api, _, _, result, _) // name
|
||||
or
|
||||
i = 4 and qualifiedName(api, _, _, _, result) // parameters
|
||||
or
|
||||
i = 5 and result = "" and exists(api) // ext
|
||||
}
|
||||
|
||||
string partialNeutralModelRow(Callable api, int i) {
|
||||
i = 0 and qualifiedName(api, result, _, _, _) // namespace
|
||||
or
|
||||
i = 1 and qualifiedName(api, _, result, _, _) // type
|
||||
or
|
||||
i = 2 and qualifiedName(api, _, _, result, _) // name
|
||||
or
|
||||
i = 3 and qualifiedName(api, _, _, _, result) // parameters
|
||||
}
|
||||
|
||||
predicate sourceNode = ExternalFlow::sourceNode/2;
|
||||
|
||||
predicate sinkNode = ExternalFlow::sinkNode/2;
|
||||
}
|
||||
|
||||
import MakeModelGenerator<Location, CppDataFlow, CppTaintTracking, ModelGeneratorInput>
|
||||
@@ -0,0 +1,13 @@
|
||||
private import cpp as Cpp
|
||||
private import codeql.mad.modelgenerator.internal.ModelPrinting
|
||||
private import CaptureModels::ModelGeneratorInput as ModelGeneratorInput
|
||||
|
||||
private module ModelPrintingLang implements ModelPrintingLangSig {
|
||||
class Callable = Cpp::Declaration;
|
||||
|
||||
predicate partialModelRow = ModelGeneratorInput::partialModelRow/2;
|
||||
|
||||
predicate partialNeutralModelRow = ModelGeneratorInput::partialNeutralModelRow/2;
|
||||
}
|
||||
|
||||
import ModelPrintingImpl<ModelPrintingLang>
|
||||
@@ -0,0 +1,2 @@
|
||||
unexpectedModel
|
||||
expectedModel
|
||||
@@ -0,0 +1,6 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- [ "models", "ManuallyModelled", False, "hasSummary", "(void *)", "", "Argument[0]", "ReturnValue", "value", "manual"]
|
||||
@@ -0,0 +1,11 @@
|
||||
import cpp
|
||||
import utils.modelgenerator.internal.CaptureModels
|
||||
import InlineModelsAsDataTest
|
||||
|
||||
module InlineMadTestConfig implements InlineMadTestConfigSig {
|
||||
string getCapturedModel(MadRelevantFunction c) { result = ContentSensitive::captureFlow(c, _) }
|
||||
|
||||
string getKind() { result = "contentbased-summary" }
|
||||
}
|
||||
|
||||
import InlineMadTest<InlineMadTestConfig>
|
||||
@@ -0,0 +1,2 @@
|
||||
unexpectedModel
|
||||
expectedModel
|
||||
@@ -0,0 +1,6 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- [ "Models", "ManuallyModelled", False, "hasSummary", "(void *)", "", "Argument[0]", "ReturnValue", "value", "manual"]
|
||||
@@ -0,0 +1,11 @@
|
||||
import cpp
|
||||
import utils.modelgenerator.internal.CaptureModels
|
||||
import InlineModelsAsDataTest
|
||||
|
||||
module InlineMadTestConfig implements InlineMadTestConfigSig {
|
||||
string getCapturedModel(MadRelevantFunction c) { result = captureFlow(c) }
|
||||
|
||||
string getKind() { result = "summary" }
|
||||
}
|
||||
|
||||
import InlineMadTest<InlineMadTestConfig>
|
||||
@@ -0,0 +1,34 @@
|
||||
private import cpp
|
||||
private import codeql.mad.test.InlineMadTest
|
||||
|
||||
class MadRelevantFunction extends Function {
|
||||
MadRelevantFunction() { not this.isFromUninstantiatedTemplate(_) }
|
||||
}
|
||||
|
||||
private module InlineMadTestLang implements InlineMadTestLangSig {
|
||||
class Callable = MadRelevantFunction;
|
||||
|
||||
/**
|
||||
* Holds if `c` is the closest `Callable` that succeeds `comment` in the file.
|
||||
*/
|
||||
private predicate hasClosestCallable(CppStyleComment comment, Callable c) {
|
||||
c =
|
||||
min(Callable cand, int dist |
|
||||
// This has no good join order, but should hopefully be good enough for tests.
|
||||
cand.getFile() = comment.getFile() and
|
||||
dist = cand.getLocation().getStartLine() - comment.getLocation().getStartLine() and
|
||||
dist > 0
|
||||
|
|
||||
cand order by dist
|
||||
)
|
||||
}
|
||||
|
||||
string getComment(Callable c) {
|
||||
exists(CppStyleComment comment |
|
||||
hasClosestCallable(comment, c) and
|
||||
result = comment.getContents().suffix(2)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import InlineMadTestImpl<InlineMadTestLang>
|
||||
@@ -0,0 +1,201 @@
|
||||
using size_t = decltype(sizeof(int));
|
||||
|
||||
size_t strlen(const char* str);
|
||||
char* strcpy(char* dest, const char* src);
|
||||
|
||||
namespace Models {
|
||||
struct BasicFlow {
|
||||
int* tainted;
|
||||
|
||||
//No model as destructors are excluded from model generation.
|
||||
~BasicFlow() = default;
|
||||
|
||||
//summary=Models;BasicFlow;true;returnThis;(int *);;Argument[-1];ReturnValue[*];taint;df-generated
|
||||
//contentbased-summary=Models;BasicFlow;true;returnThis;(int *);;Argument[-1];ReturnValue[*];value;dfc-generated
|
||||
BasicFlow* returnThis(int* input) {
|
||||
return this;
|
||||
}
|
||||
|
||||
//summary=Models;BasicFlow;true;returnParam0;(int *,int *);;Argument[0];ReturnValue;taint;df-generated
|
||||
//summary=Models;BasicFlow;true;returnParam0;(int *,int *);;Argument[*0];ReturnValue[*];taint;df-generated
|
||||
//contentbased-summary=Models;BasicFlow;true;returnParam0;(int *,int *);;Argument[0];ReturnValue;value;dfc-generated
|
||||
//contentbased-summary=Models;BasicFlow;true;returnParam0;(int *,int *);;Argument[*0];ReturnValue[*];value;dfc-generated
|
||||
int* returnParam0(int* input0, int* input1) {
|
||||
return input0;
|
||||
}
|
||||
|
||||
//summary=Models;BasicFlow;true;returnParam1;(int *,int *);;Argument[1];ReturnValue;taint;df-generated
|
||||
//summary=Models;BasicFlow;true;returnParam1;(int *,int *);;Argument[*1];ReturnValue[*];taint;df-generated
|
||||
//contentbased-summary=Models;BasicFlow;true;returnParam1;(int *,int *);;Argument[1];ReturnValue;value;dfc-generated
|
||||
//contentbased-summary=Models;BasicFlow;true;returnParam1;(int *,int *);;Argument[*1];ReturnValue[*];value;dfc-generated
|
||||
int* returnParam1(int* input0, int* input1) {
|
||||
return input1;
|
||||
}
|
||||
|
||||
//summary=Models;BasicFlow;true;returnParamMultiple;(bool,int *,int *);;Argument[1];ReturnValue;taint;df-generated
|
||||
//summary=Models;BasicFlow;true;returnParamMultiple;(bool,int *,int *);;Argument[*1];ReturnValue[*];taint;df-generated
|
||||
//summary=Models;BasicFlow;true;returnParamMultiple;(bool,int *,int *);;Argument[2];ReturnValue;taint;df-generated
|
||||
//summary=Models;BasicFlow;true;returnParamMultiple;(bool,int *,int *);;Argument[*2];ReturnValue[*];taint;df-generated
|
||||
//contentbased-summary=Models;BasicFlow;true;returnParamMultiple;(bool,int *,int *);;Argument[1];ReturnValue;value;dfc-generated
|
||||
//contentbased-summary=Models;BasicFlow;true;returnParamMultiple;(bool,int *,int *);;Argument[*1];ReturnValue[*];value;dfc-generated
|
||||
//contentbased-summary=Models;BasicFlow;true;returnParamMultiple;(bool,int *,int *);;Argument[2];ReturnValue;value;dfc-generated
|
||||
//contentbased-summary=Models;BasicFlow;true;returnParamMultiple;(bool,int *,int *);;Argument[*2];ReturnValue[*];value;dfc-generated
|
||||
int* returnParamMultiple(bool b, int* input0, int* input1) {
|
||||
return b ? input0 : input1;
|
||||
}
|
||||
|
||||
//summary=Models;BasicFlow;true;returnSubstring;(const char *,char *);;Argument[0];Argument[*1];taint;df-generated
|
||||
//summary=Models;BasicFlow;true;returnSubstring;(const char *,char *);;Argument[0];ReturnValue[*];taint;df-generated
|
||||
//summary=Models;BasicFlow;true;returnSubstring;(const char *,char *);;Argument[*0];ReturnValue[*];taint;df-generated
|
||||
//summary=Models;BasicFlow;true;returnSubstring;(const char *,char *);;Argument[1];ReturnValue;taint;df-generated
|
||||
//summary=Models;BasicFlow;true;returnSubstring;(const char *,char *);;Argument[*0];Argument[*1];taint;df-generated
|
||||
//contentbased-summary=Models;BasicFlow;true;returnSubstring;(const char *,char *);;Argument[0];Argument[*1];taint;dfc-generated
|
||||
//contentbased-summary=Models;BasicFlow;true;returnSubstring;(const char *,char *);;Argument[0];ReturnValue[*];taint;dfc-generated
|
||||
//contentbased-summary=Models;BasicFlow;true;returnSubstring;(const char *,char *);;Argument[*0];ReturnValue[*];value;dfc-generated
|
||||
//contentbased-summary=Models;BasicFlow;true;returnSubstring;(const char *,char *);;Argument[1];ReturnValue;value;dfc-generated
|
||||
//contentbased-summary=Models;BasicFlow;true;returnSubstring;(const char *,char *);;Argument[*0];Argument[*1];value;dfc-generated
|
||||
char* returnSubstring(const char* source, char* dest) {
|
||||
return strcpy(dest, source + 1);
|
||||
}
|
||||
|
||||
//summary=Models;BasicFlow;true;setField;(int *);;Argument[0];Argument[-1];taint;df-generated
|
||||
//summary=Models;BasicFlow;true;setField;(int *);;Argument[*0];Argument[-1];taint;df-generated
|
||||
//contentbased-summary=Models;BasicFlow;true;setField;(int *);;Argument[0];Argument[-1].Field[*tainted];value;dfc-generated
|
||||
//contentbased-summary=Models;BasicFlow;true;setField;(int *);;Argument[*0];Argument[-1].Field[**tainted];value;dfc-generated
|
||||
void setField(int* s) {
|
||||
tainted = s;
|
||||
}
|
||||
|
||||
//summary=Models;BasicFlow;true;returnField;();;Argument[-1];ReturnValue;taint;df-generated
|
||||
//summary=Models;BasicFlow;true;returnField;();;Argument[-1];ReturnValue[*];taint;df-generated
|
||||
//contentbased-summary=Models;BasicFlow;true;returnField;();;Argument[-1].Field[*tainted];ReturnValue;value;dfc-generated
|
||||
//contentbased-summary=Models;BasicFlow;true;returnField;();;Argument[-1].Field[**tainted];ReturnValue[*];value;dfc-generated
|
||||
int* returnField() {
|
||||
return tainted;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct TemplatedFlow {
|
||||
T tainted;
|
||||
|
||||
//summary=Models;TemplatedFlow<T>;true;template_returnThis;(T);;Argument[-1];ReturnValue[*];taint;df-generated
|
||||
//contentbased-summary=Models;TemplatedFlow<T>;true;template_returnThis;(T);;Argument[-1];ReturnValue[*];value;dfc-generated
|
||||
TemplatedFlow<T>* template_returnThis(T input) {
|
||||
return this;
|
||||
}
|
||||
|
||||
//summary=Models;TemplatedFlow<T>;true;template_returnParam0;(T *,T *);;Argument[0];ReturnValue;taint;df-generated
|
||||
//summary=Models;TemplatedFlow<T>;true;template_returnParam0;(T *,T *);;Argument[*0];ReturnValue[*];taint;df-generated
|
||||
//contentbased-summary=Models;TemplatedFlow<T>;true;template_returnParam0;(T *,T *);;Argument[0];ReturnValue;value;dfc-generated
|
||||
//contentbased-summary=Models;TemplatedFlow<T>;true;template_returnParam0;(T *,T *);;Argument[*0];ReturnValue[*];value;dfc-generated
|
||||
T* template_returnParam0(T* input0, T* input1) {
|
||||
return input0;
|
||||
}
|
||||
|
||||
//summary=Models;TemplatedFlow<T>;true;template_setField;(T);;Argument[0];Argument[-1];taint;df-generated
|
||||
//contentbased-summary=Models;TemplatedFlow<T>;true;template_setField;(T);;Argument[0];Argument[-1].Field[*tainted];value;dfc-generated
|
||||
void template_setField(T s) {
|
||||
tainted = s;
|
||||
}
|
||||
|
||||
//summary=Models;TemplatedFlow<T>;true;template_returnField;();;Argument[-1];ReturnValue[*];taint;df-generated
|
||||
//contentbased-summary=Models;TemplatedFlow<T>;true;template_returnField;();;Argument[-1].Field[*tainted];ReturnValue[*];value;dfc-generated
|
||||
T& template_returnField() {
|
||||
return tainted;
|
||||
}
|
||||
|
||||
//summary=Models;TemplatedFlow<T>;true;templated_function<U>;(U *,T *);;Argument[0];ReturnValue;taint;df-generated
|
||||
//summary=Models;TemplatedFlow<T>;true;templated_function<U>;(U *,T *);;Argument[*0];ReturnValue[*];taint;df-generated
|
||||
//contentbased-summary=Models;TemplatedFlow<T>;true;templated_function<U>;(U *,T *);;Argument[0];ReturnValue;value;dfc-generated
|
||||
//contentbased-summary=Models;TemplatedFlow<T>;true;templated_function<U>;(U *,T *);;Argument[*0];ReturnValue[*];value;dfc-generated
|
||||
template<typename U>
|
||||
U* templated_function(U* u, T* t) {
|
||||
return u;
|
||||
}
|
||||
};
|
||||
|
||||
void test_templated_flow() {
|
||||
// Ensure that we have an instantiation of the templated class
|
||||
TemplatedFlow<int> intFlow;
|
||||
intFlow.template_returnThis(0);
|
||||
|
||||
intFlow.template_returnParam0(nullptr, nullptr);
|
||||
|
||||
intFlow.template_setField(0);
|
||||
intFlow.template_returnField();
|
||||
|
||||
intFlow.templated_function<int>(nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
//summary=;;true;toplevel_function;(int *);;Argument[0];ReturnValue;taint;df-generated
|
||||
//summary=;;true;toplevel_function;(int *);;Argument[*0];ReturnValue;taint;df-generated
|
||||
//contentbased-summary=;;true;toplevel_function;(int *);;Argument[0];ReturnValue;taint;dfc-generated
|
||||
//contentbased-summary=;;true;toplevel_function;(int *);;Argument[*0];ReturnValue;value;dfc-generated
|
||||
int toplevel_function(int* p) {
|
||||
return *p;
|
||||
}
|
||||
|
||||
//No model as static functions are excluded from model generation.
|
||||
static int static_toplevel_function(int* p) {
|
||||
return *p;
|
||||
}
|
||||
|
||||
struct NonFinalStruct {
|
||||
//summary=;NonFinalStruct;true;public_not_final_member_function;(int);;Argument[0];ReturnValue;taint;df-generated
|
||||
//contentbased-summary=;NonFinalStruct;true;public_not_final_member_function;(int);;Argument[0];ReturnValue;value;dfc-generated
|
||||
virtual int public_not_final_member_function(int x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
//summary=;NonFinalStruct;false;public_final_member_function;(int);;Argument[0];ReturnValue;taint;df-generated
|
||||
//contentbased-summary=;NonFinalStruct;false;public_final_member_function;(int);;Argument[0];ReturnValue;value;dfc-generated
|
||||
virtual int public_final_member_function(int x) final {
|
||||
return x;
|
||||
}
|
||||
|
||||
private:
|
||||
//No model as private members are excluded from model generation.
|
||||
int private_member_function(int x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
protected:
|
||||
//No model as protected members are excluded from model generation.
|
||||
int protected_member_function(int x) {
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
struct FinalStruct final {
|
||||
//summary=;FinalStruct;false;public_not_final_member_function_2;(int);;Argument[0];ReturnValue;taint;df-generated
|
||||
//contentbased-summary=;FinalStruct;false;public_not_final_member_function_2;(int);;Argument[0];ReturnValue;value;dfc-generated
|
||||
virtual int public_not_final_member_function_2(int x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
//summary=;FinalStruct;false;public_final_member_function_2;(int);;Argument[0];ReturnValue;taint;df-generated
|
||||
//contentbased-summary=;FinalStruct;false;public_final_member_function_2;(int);;Argument[0];ReturnValue;value;dfc-generated
|
||||
virtual int public_final_member_function_2(int x) final {
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
union U {
|
||||
int x, y;
|
||||
};
|
||||
|
||||
//summary=;;true;get_x_from_union;(U *);;Argument[0];ReturnValue;taint;df-generated
|
||||
//summary=;;true;get_x_from_union;(U *);;Argument[*0];ReturnValue;taint;df-generated
|
||||
//contentbased-summary=;;true;get_x_from_union;(U *);;Argument[0];ReturnValue;taint;dfc-generated
|
||||
//contentbased-summary=;;true;get_x_from_union;(U *);;Argument[*0].Union[*U];ReturnValue;value;dfc-generated
|
||||
int get_x_from_union(U* u) {
|
||||
return u->x;
|
||||
}
|
||||
|
||||
//summary=;;true;set_x_in_union;(U *,int);;Argument[1];Argument[*0];taint;df-generated
|
||||
//contentbased-summary=;;true;set_x_in_union;(U *,int);;Argument[1];Argument[*0].Union[*U];value;dfc-generated
|
||||
void set_x_in_union(U* u, int x) {
|
||||
u->x = x;
|
||||
}
|
||||
Reference in New Issue
Block a user