Merge branch 'main' into mbg/go/semver-type

This commit is contained in:
Michael B. Gale
2024-06-07 12:09:10 +00:00
committed by GitHub
151 changed files with 4706 additions and 3283 deletions

2
.gitattributes vendored
View File

@@ -83,7 +83,7 @@
/csharp/paket.main_extension.bzl linguist-generated=true
# ripunzip tool
/misc/bazel/internal/ripunzip/ripunzip-* filter=lfs diff=lfs merge=lfs -text
/misc/ripunzip/ripunzip-* filter=lfs diff=lfs merge=lfs -text
# swift prebuilt resources
/swift/third_party/resource-dir/*.zip filter=lfs diff=lfs merge=lfs -text

View File

@@ -118,19 +118,19 @@ lfs_files = use_repo_rule("//misc/bazel:lfs.bzl", "lfs_files")
lfs_files(
name = "ripunzip-linux",
srcs = ["//misc/bazel/internal/ripunzip:ripunzip-linux"],
srcs = ["//misc/ripunzip:ripunzip-linux"],
executable = True,
)
lfs_files(
name = "ripunzip-windows",
srcs = ["//misc/bazel/internal/ripunzip:ripunzip-windows.exe"],
srcs = ["//misc/ripunzip:ripunzip-windows.exe"],
executable = True,
)
lfs_files(
name = "ripunzip-macos",
srcs = ["//misc/bazel/internal/ripunzip:ripunzip-macos"],
srcs = ["//misc/ripunzip:ripunzip-macos"],
executable = True,
)

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* A partial model for the `Boost.Asio` network library has been added. This includes sources, sinks and summaries for certain functions in `Boost.Asio`, such as `read_until` and `write`.

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* Data models can now be added with data extensions. In this way source, sink and summary models can be added in extension `.model.yml` files, rather than by writing classes in QL code. New models should be added in the `lib/ext` folder.

View File

@@ -0,0 +1,26 @@
extensions:
# partial model of the Boost::Asio network library
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: sourceModel
data: # namespace, type, subtypes, name, signature, ext, output, kind, provenance
- ["boost::asio", "", False, "read", "", "", "Argument[*1]", "remote", "manual"]
- ["boost::asio", "", False, "read_at", "", "", "Argument[*2]", "remote", "manual"]
- ["boost::asio", "", False, "read_until", "", "", "Argument[*1]", "remote", "manual"]
- ["boost::asio", "", False, "async_read", "", "", "Argument[*1]", "remote", "manual"]
- ["boost::asio", "", False, "async_read_at", "", "", "Argument[*2]", "remote", "manual"]
- ["boost::asio", "", False, "async_read_until", "", "", "Argument[*1]", "remote", "manual"]
- addsTo:
pack: codeql/cpp-all
extensible: sinkModel
data: # namespace, type, subtypes, name, signature, ext, input, kind, provenance
- ["boost::asio", "", False, "write", "", "", "Argument[*1]", "remote-sink", "manual"]
- ["boost::asio", "", False, "write_at", "", "", "Argument[*2]", "remote-sink", "manual"]
- ["boost::asio", "", False, "async_write", "", "", "Argument[*1]", "remote-sink", "manual"]
- ["boost::asio", "", False, "async_write_at", "", "", "Argument[*2]", "remote-sink", "manual"]
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
- ["boost::asio", "", False, "buffer", "", "", "Argument[*0]", "ReturnValue", "taint", "manual"]

View File

@@ -0,0 +1,15 @@
extensions:
# Make sure that the extensible model predicates have at least one definition
# to avoid errors about undefined extensionals.
- addsTo:
pack: codeql/cpp-all
extensible: sourceModel
data: []
- addsTo:
pack: codeql/cpp-all
extensible: sinkModel
data: []
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data: []

View File

@@ -14,4 +14,6 @@ dependencies:
codeql/tutorial: ${workspace}
codeql/util: ${workspace}
codeql/xml: ${workspace}
dataExtensions:
- ext/*.model.yml
warnOnImplicitThis: true

View File

@@ -410,6 +410,10 @@ class LocalVariable extends LocalScopeVariable, @localvariable {
or
orphaned_variables(underlyingElement(this), unresolveElement(result))
}
override predicate isStatic() {
super.isStatic() or orphaned_variables(underlyingElement(this), _)
}
}
/**

View File

@@ -78,6 +78,7 @@ private import internal.FlowSummaryImpl
private import internal.FlowSummaryImpl::Public
private import internal.FlowSummaryImpl::Private
private import internal.FlowSummaryImpl::Private::External
private import internal.ExternalFlowExtensions as Extensions
private import codeql.mad.ModelValidation as SharedModelVal
private import codeql.util.Unit
@@ -138,6 +139,9 @@ predicate sourceModel(
row.splitAt(";", 7) = kind
) and
provenance = "manual"
or
Extensions::sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance,
_)
}
/** Holds if a sink model exists for the given parameters. */
@@ -158,6 +162,8 @@ predicate sinkModel(
row.splitAt(";", 7) = kind
) and
provenance = "manual"
or
Extensions::sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance, _)
}
/** Holds if a summary model exists for the given parameters. */
@@ -179,6 +185,9 @@ predicate summaryModel(
row.splitAt(";", 8) = kind
) and
provenance = "manual"
or
Extensions::summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind,
provenance, _)
}
private predicate relevantNamespace(string namespace) {
@@ -203,8 +212,10 @@ private predicate canonicalNamespaceLink(string namespace, string subns) {
}
/**
* Holds if CSV framework coverage of `namespace` is `n` api endpoints of the
* kind `(kind, part)`.
* Holds if MaD framework coverage of `namespace` is `n` api endpoints of the
* kind `(kind, part)`, and `namespaces` is the number of subnamespaces of
* `namespace` which have MaD framework coverage (including `namespace`
* itself).
*/
predicate modelCoverage(string namespace, int namespaces, string kind, string part, int n) {
namespaces = strictcount(string subns | canonicalNamespaceLink(namespace, subns)) and
@@ -321,10 +332,10 @@ module CsvValidation {
or
summaryModel(namespace, type, _, name, signature, ext, _, _, _, _) and pred = "summary"
|
not namespace.regexpMatch("[a-zA-Z0-9_\\.]+") and
not namespace.regexpMatch("[a-zA-Z0-9_\\.:]*") and
result = "Dubious namespace \"" + namespace + "\" in " + pred + " model."
or
not type.regexpMatch("[a-zA-Z0-9_<>,\\+]+") and
not type.regexpMatch("[a-zA-Z0-9_<>,\\+]*") and
result = "Dubious type \"" + type + "\" in " + pred + " model."
or
not name.regexpMatch("[a-zA-Z0-9_<>,]*") and

View File

@@ -0,0 +1,27 @@
/**
* This module provides extensible predicates for defining MaD models.
*/
/**
* Holds if an external source model exists for the given parameters.
*/
extensible predicate sourceModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string output, string kind, string provenance, QlBuiltins::ExtensionId madId
);
/**
* Holds if an external sink model exists for the given parameters.
*/
extensible predicate sinkModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string kind, string provenance, QlBuiltins::ExtensionId madId
);
/**
* Holds if an external summary model exists for the given parameters.
*/
extensible predicate summaryModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string output, string kind, string provenance, QlBuiltins::ExtensionId madId
);

View File

@@ -1336,6 +1336,8 @@ predicate nodeIsHidden(Node n) {
n instanceof FinalGlobalValue
or
n instanceof InitialGlobalValue
or
n instanceof SsaPhiInputNode
}
predicate neverSkipInPathGraph(Node n) {
@@ -1634,6 +1636,8 @@ private Instruction getAnInstruction(Node n) {
or
result = n.(SsaPhiNode).getPhiNode().getBasicBlock().getFirstInstruction()
or
result = n.(SsaPhiInputNode).getBasicBlock().getFirstInstruction()
or
n.(IndirectInstruction).hasInstructionAndIndirectionIndex(result, _)
or
not n instanceof IndirectInstruction and
@@ -1763,7 +1767,7 @@ module IteratorFlow {
crementCall = def.getValue().asInstruction().(StoreInstruction).getSourceValue() and
sv = def.getSourceVariable() and
bb.getInstruction(i) = crementCall and
Ssa::ssaDefReachesRead(sv, result.asDef(), bb, i)
Ssa::ssaDefReachesReadExt(sv, result.asDef(), bb, i)
)
}
@@ -1797,7 +1801,7 @@ module IteratorFlow {
isIteratorWrite(writeToDeref, address) and
operandForFullyConvertedCall(address, starCall) and
bbStar.getInstruction(iStar) = starCall and
Ssa::ssaDefReachesRead(_, def.asDef(), bbStar, iStar) and
Ssa::ssaDefReachesReadExt(_, def.asDef(), bbStar, iStar) and
ultimate = getAnUltimateDefinition*(def) and
beginStore = ultimate.getValue().asInstruction() and
operandForFullyConvertedCall(beginStore.getSourceValueOperand(), beginCall)

View File

@@ -45,6 +45,7 @@ private newtype TIRDataFlowNode =
or
Ssa::isModifiableByCall(operand, indirectionIndex)
} or
TSsaPhiInputNode(Ssa::PhiNode phi, IRBlock input) { phi.hasInputFromBlock(_, _, _, _, input) } or
TSsaPhiNode(Ssa::PhiNode phi) or
TSsaIteratorNode(IteratorFlow::IteratorFlowNode n) or
TRawIndirectOperand0(Node0Impl node, int indirectionIndex) {
@@ -114,6 +115,13 @@ predicate conversionFlow(
instrTo.(CheckedConvertOrNullInstruction).getUnaryOperand() = opFrom
or
instrTo.(InheritanceConversionInstruction).getUnaryOperand() = opFrom
or
exists(BuiltInInstruction builtIn |
builtIn = instrTo and
// __builtin_bit_cast
builtIn.getBuiltInOperation() instanceof BuiltInBitCast and
opFrom = builtIn.getAnOperand()
)
)
or
additional = true and
@@ -158,6 +166,12 @@ class Node extends TIRDataFlowNode {
/** Gets the operands corresponding to this node, if any. */
Operand asOperand() { result = this.(OperandNode).getOperand() }
/**
* Gets the operand that is indirectly tracked by this node behind `index`
* number of indirections.
*/
Operand asIndirectOperand(int index) { hasOperandAndIndex(this, result, index) }
/**
* Holds if this node is at index `i` in basic block `block`.
*
@@ -170,6 +184,9 @@ class Node extends TIRDataFlowNode {
or
this.(SsaPhiNode).getPhiNode().getBasicBlock() = block and i = -1
or
this.(SsaPhiInputNode).getBlock() = block and
i = block.getInstructionCount()
or
this.(RawIndirectOperand).getOperand().getUse() = block.getInstruction(i)
or
this.(RawIndirectInstruction).getInstruction() = block.getInstruction(i)
@@ -622,7 +639,7 @@ class SsaPhiNode extends Node, TSsaPhiNode {
final override Location getLocationImpl() { result = phi.getBasicBlock().getLocation() }
override string toStringImpl() { result = "Phi" }
override string toStringImpl() { result = phi.toString() }
/**
* Gets a node that is used as input to this phi node.
@@ -631,7 +648,7 @@ class SsaPhiNode extends Node, TSsaPhiNode {
*/
cached
final Node getAnInput(boolean fromBackEdge) {
localFlowStep(result, this) and
result.(SsaPhiInputNode).getPhiNode() = phi and
exists(IRBlock bPhi, IRBlock bResult |
bPhi = phi.getBasicBlock() and bResult = result.getBasicBlock()
|
@@ -654,6 +671,58 @@ class SsaPhiNode extends Node, TSsaPhiNode {
predicate isPhiRead() { phi.isPhiRead() }
}
/**
* INTERNAL: Do not use.
*
* A node that is used as an input to a phi node.
*
* This class exists to allow more powerful barrier guards. Consider this
* example:
*
* ```cpp
* int x = source();
* if(!safe(x)) {
* x = clear();
* }
* // phi node for x here
* sink(x);
* ```
*
* At the phi node for `x` it is neither the case that `x` is dominated by
* `safe(x)`, or is the case that the phi is dominated by a clearing of `x`.
*
* By inserting a "phi input" node as the last entry in the basic block that
* defines the inputs to the phi we can conclude that each of those inputs are
* safe to pass to `sink`.
*/
class SsaPhiInputNode extends Node, TSsaPhiInputNode {
Ssa::PhiNode phi;
IRBlock block;
SsaPhiInputNode() { this = TSsaPhiInputNode(phi, block) }
/** Gets the phi node associated with this node. */
Ssa::PhiNode getPhiNode() { result = phi }
/** Gets the basic block in which this input originates. */
IRBlock getBlock() { result = block }
override Declaration getEnclosingCallable() { result = this.getFunction() }
override Declaration getFunction() { result = phi.getBasicBlock().getEnclosingFunction() }
override DataFlowType getType() { result = this.getSourceVariable().getType() }
override predicate isGLValue() { phi.getSourceVariable().isGLValue() }
final override Location getLocationImpl() { result = block.getLastInstruction().getLocation() }
override string toStringImpl() { result = "Phi input" }
/** Gets the source variable underlying this phi node. */
Ssa::SourceVariable getSourceVariable() { result = phi.getSourceVariable() }
}
/**
* INTERNAL: do not use.
*
@@ -2176,6 +2245,9 @@ private module Cached {
// Def-use/Use-use flow
Ssa::ssaFlow(nodeFrom, nodeTo)
or
// Phi input -> Phi
nodeFrom.(SsaPhiInputNode).getPhiNode() = nodeTo.(SsaPhiNode).getPhiNode()
or
IteratorFlow::localFlowStep(nodeFrom, nodeTo)
or
// Operand -> Instruction flow
@@ -2614,6 +2686,22 @@ class ContentSet instanceof Content {
}
}
pragma[nomagic]
private predicate guardControlsPhiInput(
IRGuardCondition g, boolean branch, Ssa::Definition def, IRBlock input, Ssa::PhiNode phi
) {
phi.hasInputFromBlock(def, _, _, _, input) and
(
g.controls(input, branch)
or
exists(EdgeKind kind |
g.getBlock() = input and
kind = getConditionalEdge(branch) and
input.getSuccessor(kind) = phi.getBasicBlock()
)
)
}
/**
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
*
@@ -2662,13 +2750,21 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
*
* NOTE: If an indirect expression is tracked, use `getAnIndirectBarrierNode` instead.
*/
ExprNode getABarrierNode() {
Node getABarrierNode() {
exists(IRGuardCondition g, Expr e, ValueNumber value, boolean edge |
e = value.getAnInstruction().getConvertedResultExpression() and
result.getConvertedExpr() = e and
result.asConvertedExpr() = e and
guardChecks(g, value.getAnInstruction().getConvertedResultExpression(), edge) and
g.controls(result.getBasicBlock(), edge)
)
or
exists(
IRGuardCondition g, boolean branch, Ssa::DefinitionExt def, IRBlock input, Ssa::PhiNode phi
|
guardChecks(g, def.getARead().asOperand().getDef().getConvertedResultExpression(), branch) and
guardControlsPhiInput(g, branch, def, input, phi) and
result = TSsaPhiInputNode(phi, input)
)
}
/**
@@ -2704,7 +2800,7 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
*
* NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
*/
IndirectExprNode getAnIndirectBarrierNode() { result = getAnIndirectBarrierNode(_) }
Node getAnIndirectBarrierNode() { result = getAnIndirectBarrierNode(_) }
/**
* Gets an indirect expression node with indirection index `indirectionIndex` that is
@@ -2740,13 +2836,23 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
*
* NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
*/
IndirectExprNode getAnIndirectBarrierNode(int indirectionIndex) {
Node getAnIndirectBarrierNode(int indirectionIndex) {
exists(IRGuardCondition g, Expr e, ValueNumber value, boolean edge |
e = value.getAnInstruction().getConvertedResultExpression() and
result.getConvertedExpr(indirectionIndex) = e and
result.asIndirectConvertedExpr(indirectionIndex) = e and
guardChecks(g, value.getAnInstruction().getConvertedResultExpression(), edge) and
g.controls(result.getBasicBlock(), edge)
)
or
exists(
IRGuardCondition g, boolean branch, Ssa::DefinitionExt def, IRBlock input, Ssa::PhiNode phi
|
guardChecks(g,
def.getARead().asIndirectOperand(indirectionIndex).getDef().getConvertedResultExpression(),
branch) and
guardControlsPhiInput(g, branch, def, input, phi) and
result = TSsaPhiInputNode(phi, input)
)
}
}
@@ -2755,6 +2861,14 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
*/
signature predicate instructionGuardChecksSig(IRGuardCondition g, Instruction instr, boolean branch);
private EdgeKind getConditionalEdge(boolean branch) {
branch = true and
result instanceof TrueEdge
or
branch = false and
result instanceof FalseEdge
}
/**
* Provides a set of barrier nodes for a guard that validates an instruction.
*
@@ -2763,12 +2877,20 @@ signature predicate instructionGuardChecksSig(IRGuardCondition g, Instruction in
*/
module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardChecks> {
/** Gets a node that is safely guarded by the given guard check. */
ExprNode getABarrierNode() {
Node getABarrierNode() {
exists(IRGuardCondition g, ValueNumber value, boolean edge, Operand use |
instructionGuardChecks(g, value.getAnInstruction(), edge) and
use = value.getAnInstruction().getAUse() and
result.asOperand() = use and
g.controls(use.getDef().getBlock(), edge)
g.controls(result.getBasicBlock(), edge)
)
or
exists(
IRGuardCondition g, boolean branch, Ssa::DefinitionExt def, IRBlock input, Ssa::PhiNode phi
|
instructionGuardChecks(g, def.getARead().asOperand().getDef(), branch) and
guardControlsPhiInput(g, branch, def, input, phi) and
result = TSsaPhiInputNode(phi, input)
)
}
}

View File

@@ -657,19 +657,9 @@ class GlobalDefImpl extends DefImpl, TGlobalDefImpl {
*/
predicate adjacentDefRead(IRBlock bb1, int i1, SourceVariable sv, IRBlock bb2, int i2) {
adjacentDefReadExt(_, sv, bb1, i1, bb2, i2)
or
exists(PhiNode phi |
lastRefRedefExt(_, sv, bb1, i1, phi) and
phi.definesAt(sv, bb2, i2, _)
)
}
predicate useToNode(IRBlock bb, int i, SourceVariable sv, Node nodeTo) {
exists(Phi phi |
phi.asPhi().definesAt(sv, bb, i, _) and
nodeTo = phi.getNode()
)
or
exists(UseImpl use |
use.hasIndexInBlock(bb, i, sv) and
nodeTo = use.getNode()
@@ -723,46 +713,26 @@ predicate nodeToDefOrUse(Node node, SourceVariable sv, IRBlock bb, int i, boolea
*/
private predicate indirectConversionFlowStep(Node nFrom, Node nTo) {
not exists(SourceVariable sv, IRBlock bb2, int i2 |
nodeToDefOrUse(nTo, sv, bb2, i2, _) and
useToNode(bb2, i2, sv, nTo) and
adjacentDefRead(bb2, i2, sv, _, _)
) and
(
exists(Operand op1, Operand op2, int indirectionIndex, Instruction instr |
hasOperandAndIndex(nFrom, op1, pragma[only_bind_into](indirectionIndex)) and
hasOperandAndIndex(nTo, op2, pragma[only_bind_into](indirectionIndex)) and
instr = op2.getDef() and
conversionFlow(op1, instr, _, _)
)
or
exists(Operand op1, Operand op2, int indirectionIndex, Instruction instr |
hasOperandAndIndex(nFrom, op1, pragma[only_bind_into](indirectionIndex)) and
hasOperandAndIndex(nTo, op2, indirectionIndex - 1) and
instr = op2.getDef() and
isDereference(instr, op1, _)
)
exists(Operand op1, Operand op2, int indirectionIndex, Instruction instr |
hasOperandAndIndex(nFrom, op1, pragma[only_bind_into](indirectionIndex)) and
hasOperandAndIndex(nTo, op2, pragma[only_bind_into](indirectionIndex)) and
instr = op2.getDef() and
conversionFlow(op1, instr, _, _)
)
}
/**
* The reason for this predicate is a bit annoying:
* We cannot mark a `PointerArithmeticInstruction` that computes an offset based on some SSA
* variable `x` as a use of `x` since this creates taint-flow in the following example:
* ```c
* int x = array[source]
* sink(*array)
* ```
* This is because `source` would flow from the operand of `PointerArithmeticInstruction` to the
* result of the instruction, and into the `IndirectOperand` that represents the value of `*array`.
* Then, via use-use flow, flow will arrive at `*array` in `sink(*array)`.
*
* So this predicate recurses back along conversions and `PointerArithmeticInstruction`s to find the
* first use that has provides use-use flow, and uses that target as the target of the `nodeFrom`.
* Holds if `node` is a phi input node that should receive flow from the
* definition to (or use of) `sv` at `(bb1, i1)`.
*/
private predicate adjustForPointerArith(PostUpdateNode pun, SourceVariable sv, IRBlock bb2, int i2) {
exists(IRBlock bb1, int i1, Node adjusted |
indirectConversionFlowStep*(adjusted, pun.getPreUpdateNode()) and
nodeToDefOrUse(adjusted, sv, bb1, i1, _) and
adjacentDefRead(bb1, i1, sv, bb2, i2)
private predicate phiToNode(SsaPhiInputNode node, SourceVariable sv, IRBlock bb1, int i1) {
exists(PhiNode phi, IRBlock input |
phi.hasInputFromBlock(_, sv, bb1, i1, input) and
node.getPhiNode() = phi and
node.getBlock() = input
)
}
@@ -777,10 +747,14 @@ private predicate adjustForPointerArith(PostUpdateNode pun, SourceVariable sv, I
private predicate ssaFlowImpl(
IRBlock bb1, int i1, SourceVariable sv, Node nodeFrom, Node nodeTo, boolean uncertain
) {
exists(IRBlock bb2, int i2 |
nodeToDefOrUse(nodeFrom, sv, bb1, i1, uncertain) and
adjacentDefRead(bb1, i1, sv, bb2, i2) and
useToNode(bb2, i2, sv, nodeTo)
nodeToDefOrUse(nodeFrom, sv, bb1, i1, uncertain) and
(
exists(IRBlock bb2, int i2 |
adjacentDefRead(bb1, i1, sv, bb2, i2) and
useToNode(bb2, i2, sv, nodeTo)
)
or
phiToNode(nodeTo, sv, bb1, i1)
) and
nodeFrom != nodeTo
}
@@ -789,7 +763,7 @@ private predicate ssaFlowImpl(
private Node getAPriorDefinition(DefinitionExt next) {
exists(IRBlock bb, int i, SourceVariable sv |
lastRefRedefExt(_, pragma[only_bind_into](sv), pragma[only_bind_into](bb),
pragma[only_bind_into](i), next) and
pragma[only_bind_into](i), _, next) and
nodeToDefOrUse(result, sv, bb, i, _)
)
}
@@ -896,9 +870,31 @@ private predicate isArgumentOfCallable(DataFlowCall call, Node n) {
* Holds if there is use-use flow from `pun`'s pre-update node to `n`.
*/
private predicate postUpdateNodeToFirstUse(PostUpdateNode pun, Node n) {
exists(SourceVariable sv, IRBlock bb2, int i2 |
adjustForPointerArith(pun, sv, bb2, i2) and
useToNode(bb2, i2, sv, n)
// We cannot mark a `PointerArithmeticInstruction` that computes an offset
// based on some SSA
// variable `x` as a use of `x` since this creates taint-flow in the
// following example:
// ```c
// int x = array[source]
// sink(*array)
// ```
// This is because `source` would flow from the operand of `PointerArithmetic`
// instruction to the result of the instruction, and into the `IndirectOperand`
// that represents the value of `*array`. Then, via use-use flow, flow will
// arrive at `*array` in `sink(*array)`.
// So this predicate recurses back along conversions and `PointerArithmetic`
// instructions to find the first use that has provides use-use flow, and
// uses that target as the target of the `nodeFrom`.
exists(Node adjusted, IRBlock bb1, int i1, SourceVariable sv |
indirectConversionFlowStep*(adjusted, pun.getPreUpdateNode()) and
useToNode(bb1, i1, sv, adjusted)
|
exists(IRBlock bb2, int i2 |
adjacentDefRead(bb1, i1, sv, bb2, i2) and
useToNode(bb2, i2, sv, n)
)
or
phiToNode(n, sv, bb1, i1)
)
}
@@ -953,11 +949,16 @@ predicate postUpdateFlow(PostUpdateNode pun, Node nodeTo) {
/** Holds if `nodeTo` receives flow from the phi node `nodeFrom`. */
predicate fromPhiNode(SsaPhiNode nodeFrom, Node nodeTo) {
exists(PhiNode phi, SourceVariable sv, IRBlock bb1, int i1, IRBlock bb2, int i2 |
exists(PhiNode phi, SourceVariable sv, IRBlock bb1, int i1 |
phi = nodeFrom.getPhiNode() and
phi.definesAt(sv, bb1, i1, _) and
adjacentDefRead(bb1, i1, sv, bb2, i2) and
useToNode(bb2, i2, sv, nodeTo)
phi.definesAt(sv, bb1, i1, _)
|
exists(IRBlock bb2, int i2 |
adjacentDefRead(bb1, i1, sv, bb2, i2) and
useToNode(bb2, i2, sv, nodeTo)
)
or
phiToNode(nodeTo, sv, bb1, i1)
)
}
@@ -1031,22 +1032,26 @@ module SsaCached {
* Holds if the node at index `i` in `bb` is a last reference to SSA definition
* `def`. The reference is last because it can reach another write `next`,
* without passing through another read or write.
*
* The path from node `i` in `bb` to `next` goes via basic block `input`,
* which is either a predecessor of the basic block of `next`, or `input` =
* `bb` in case `next` occurs in basic block `bb`.
*/
cached
predicate lastRefRedefExt(
DefinitionExt def, SourceVariable sv, IRBlock bb, int i, DefinitionExt next
DefinitionExt def, SourceVariable sv, IRBlock bb, int i, IRBlock input, DefinitionExt next
) {
SsaImpl::lastRefRedefExt(def, sv, bb, i, next)
SsaImpl::lastRefRedefExt(def, sv, bb, i, input, next)
}
cached
Definition phiHasInputFromBlock(PhiNode phi, IRBlock bb) {
SsaImpl::phiHasInputFromBlock(phi, result, bb)
Definition phiHasInputFromBlockExt(PhiNode phi, IRBlock bb) {
SsaImpl::phiHasInputFromBlockExt(phi, result, bb)
}
cached
predicate ssaDefReachesRead(SourceVariable v, Definition def, IRBlock bb, int i) {
SsaImpl::ssaDefReachesRead(v, def, bb, i)
predicate ssaDefReachesReadExt(SourceVariable v, DefinitionExt def, IRBlock bb, int i) {
SsaImpl::ssaDefReachesReadExt(v, def, bb, i)
}
predicate variableRead = SsaInput::variableRead/4;
@@ -1198,11 +1203,11 @@ class Phi extends TPhi, SsaDef {
final override Location getLocation() { result = phi.getBasicBlock().getLocation() }
override string toString() { result = "Phi" }
override string toString() { result = phi.toString() }
SsaPhiNode getNode() { result.getPhiNode() = phi }
SsaPhiInputNode getNode(IRBlock block) { result.getPhiNode() = phi and result.getBlock() = block }
predicate hasInputFromBlock(Definition inp, IRBlock bb) { inp = phiHasInputFromBlock(phi, bb) }
predicate hasInputFromBlock(Definition inp, IRBlock bb) { inp = phiHasInputFromBlockExt(phi, bb) }
final Definition getAnInput() { this.hasInputFromBlock(result, _) }
}
@@ -1228,13 +1233,21 @@ class PhiNode extends SsaImpl::DefinitionExt {
*/
predicate isPhiRead() { this instanceof SsaImpl::PhiReadNode }
/** Holds if `inp` is an input to this phi node along the edge originating in `bb`. */
predicate hasInputFromBlock(Definition inp, IRBlock bb) {
inp = SsaCached::phiHasInputFromBlock(this, bb)
/**
* Holds if the node at index `i` in `bb` is a last reference to SSA
* definition `def` of `sv`. The reference is last because it can reach
* this phi node, without passing through another read or write.
*
* The path from node `i` in `bb` to this phi node goes via basic block
* `input`, which is either a predecessor of the basic block of this phi
* node, or `input` = `bb` in case this phi node occurs in basic block `bb`.
*/
predicate hasInputFromBlock(DefinitionExt def, SourceVariable sv, IRBlock bb, int i, IRBlock input) {
SsaCached::lastRefRedefExt(def, sv, bb, i, input, this)
}
/** Gets a definition that is an input to this phi node. */
final Definition getAnInput() { this.hasInputFromBlock(result, _) }
final Definition getAnInput() { this.hasInputFromBlock(result, _, _, _, _) }
}
/** An static single assignment (SSA) definition. */
@@ -1249,6 +1262,15 @@ class DefinitionExt extends SsaImpl::DefinitionExt {
result = this.getAPhiInputOrPriorDefinition*() and
not result instanceof PhiNode
}
/** Gets a node that represents a read of this SSA definition. */
Node getARead() {
exists(SourceVariable sv, IRBlock bb, int i | SsaCached::ssaDefReachesReadExt(sv, this, bb, i) |
useToNode(bb, i, sv, result)
or
phiToNode(result, sv, bb, i)
)
}
}
class Definition = SsaImpl::Definition;

View File

@@ -3208,9 +3208,20 @@ class TranslatedBuiltInOperation extends TranslatedNonConstantExpr {
final override Instruction getResult() { result = this.getInstruction(OnlyInstructionTag()) }
/**
* Gets the rnk'th (0-indexed) child for which a `TranslatedElement` exists.
*
* We use this predicate to filter out `TypeName` expressions that sometimes
* occur in builtin operations since the IR doesn't have an instruction to
* represent a reference to a type.
*/
private TranslatedElement getRankedChild(int rnk) {
result = rank[rnk + 1](int id, TranslatedElement te | te = this.getChild(id) | te order by id)
}
final override Instruction getFirstInstruction(EdgeKind kind) {
if exists(this.getChild(0))
then result = this.getChild(0).getFirstInstruction(kind)
if exists(this.getRankedChild(0))
then result = this.getRankedChild(0).getFirstInstruction(kind)
else (
kind instanceof GotoEdge and result = this.getInstruction(OnlyInstructionTag())
)
@@ -3230,11 +3241,11 @@ class TranslatedBuiltInOperation extends TranslatedNonConstantExpr {
}
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
exists(int id | child = this.getChild(id) |
result = this.getChild(id + 1).getFirstInstruction(kind)
exists(int id | child = this.getRankedChild(id) |
result = this.getRankedChild(id + 1).getFirstInstruction(kind)
or
kind instanceof GotoEdge and
not exists(this.getChild(id + 1)) and
not exists(this.getRankedChild(id + 1)) and
result = this.getInstruction(OnlyInstructionTag())
)
}
@@ -3249,7 +3260,7 @@ class TranslatedBuiltInOperation extends TranslatedNonConstantExpr {
tag = OnlyInstructionTag() and
exists(int index |
operandTag = positionalArgumentOperand(index) and
result = this.getChild(index).(TranslatedExpr).getResult()
result = this.getRankedChild(index).(TranslatedExpr).getResult()
)
}

View File

@@ -209,6 +209,7 @@ class LoopWithAlloca extends Stmt {
DataFlow::localFlow(result, DataFlow::exprNode(va)) and
// Phi nodes will be preceded by nodes that represent actual definitions
not result instanceof DataFlow::SsaPhiNode and
not result instanceof DataFlow::SsaPhiInputNode and
// A source is outside the loop if it's not inside the loop
not exists(Expr e | e = getExpr(result) | this = getAnEnclosingLoopOfExpr(e))
)

View File

@@ -75,4 +75,54 @@ void bg_indirect_expr() {
if (guarded(buf)) {
sink(buf);
}
}
void test_guard_and_reassign() {
int x = source();
if(!guarded(x)) {
x = 0;
}
sink(x); // $ SPURIOUS: ast,ir
}
void test_phi_read_guard(bool b) {
int x = source();
if(b) {
if(!guarded(x))
return;
}
else {
if(!guarded(x))
return;
}
sink(x); // $ SPURIOUS: ast,ir
}
bool unsafe(int);
void test_guard_and_reassign_2() {
int x = source();
if(unsafe(x)) {
x = 0;
}
sink(x); // $ SPURIOUS: ast
}
void test_phi_read_guard_2(bool b) {
int x = source();
if(b) {
if(unsafe(x))
return;
}
else {
if(unsafe(x))
return;
}
sink(x); // $ SPURIOUS: ast
}

View File

@@ -11,6 +11,10 @@ module AstTest {
g.(FunctionCall).getTarget().getName() = "guarded" and
checked = g.(FunctionCall).getArgument(0) and
isTrue = true
or
g.(FunctionCall).getTarget().getName() = "unsafe" and
checked = g.(FunctionCall).getArgument(0) and
isTrue = false
}
/** Common data flow configuration to be used by tests. */
@@ -105,9 +109,13 @@ module IRTest {
predicate testBarrierGuard(IRGuardCondition g, Expr checked, boolean isTrue) {
exists(Call call |
call = g.getUnconvertedResultExpression() and
checked = call.getArgument(0)
|
call.getTarget().hasName("guarded") and
checked = call.getArgument(0) and
isTrue = true
or
call.getTarget().hasName("unsafe") and
isTrue = false
)
}

View File

@@ -52,3 +52,9 @@ void following_pointers( // $ ast-def=sourceStruct1_ptr ir-def=*cleanArray1 ir-d
sink(stackArray); // $ ast,ir
indirect_sink(stackArray); // $ ast ir=50:25 ir=50:35 ir=51:19
}
void test_bitcast() {
unsigned long x = source();
double d = __builtin_bit_cast(double, x);
sink(d); // $ ir MISSING: ast
}

View File

@@ -69,45 +69,61 @@
| test.cpp:8:8:8:9 | t1 | test.cpp:9:8:9:9 | t1 |
| test.cpp:9:8:9:9 | t1 | test.cpp:11:7:11:8 | t1 |
| test.cpp:9:8:9:9 | t1 | test.cpp:11:7:11:8 | t1 |
| test.cpp:10:8:10:9 | t2 | test.cpp:11:7:11:8 | Phi input |
| test.cpp:10:8:10:9 | t2 | test.cpp:11:7:11:8 | Phi input |
| test.cpp:10:8:10:9 | t2 | test.cpp:13:10:13:11 | t2 |
| test.cpp:10:8:10:9 | t2 | test.cpp:15:3:15:6 | Phi |
| test.cpp:10:8:10:9 | t2 | test.cpp:15:3:15:6 | Phi |
| test.cpp:11:7:11:8 | Phi input | test.cpp:15:3:15:6 | SSA phi read(t2) |
| test.cpp:11:7:11:8 | Phi input | test.cpp:15:3:15:6 | SSA phi(*t2) |
| test.cpp:11:7:11:8 | t1 | test.cpp:21:8:21:9 | t1 |
| test.cpp:12:5:12:10 | ... = ... | test.cpp:13:10:13:11 | t2 |
| test.cpp:12:10:12:10 | 0 | test.cpp:12:5:12:10 | ... = ... |
| test.cpp:13:10:13:11 | t2 | test.cpp:15:3:15:6 | Phi |
| test.cpp:13:10:13:11 | t2 | test.cpp:15:3:15:6 | Phi |
| test.cpp:15:3:15:6 | Phi | test.cpp:15:8:15:9 | t2 |
| test.cpp:15:3:15:6 | Phi | test.cpp:15:8:15:9 | t2 |
| test.cpp:15:8:15:9 | t2 | test.cpp:23:19:23:19 | Phi |
| test.cpp:15:8:15:9 | t2 | test.cpp:23:19:23:19 | Phi |
| test.cpp:13:5:13:8 | Phi input | test.cpp:15:3:15:6 | SSA phi read(t2) |
| test.cpp:13:5:13:8 | Phi input | test.cpp:15:3:15:6 | SSA phi(*t2) |
| test.cpp:13:10:13:11 | t2 | test.cpp:13:5:13:8 | Phi input |
| test.cpp:13:10:13:11 | t2 | test.cpp:13:5:13:8 | Phi input |
| test.cpp:15:3:15:6 | SSA phi read(t2) | test.cpp:15:8:15:9 | t2 |
| test.cpp:15:3:15:6 | SSA phi(*t2) | test.cpp:15:8:15:9 | t2 |
| test.cpp:15:8:15:9 | t2 | test.cpp:23:15:23:16 | Phi input |
| test.cpp:15:8:15:9 | t2 | test.cpp:23:15:23:16 | Phi input |
| test.cpp:17:3:17:8 | ... = ... | test.cpp:21:8:21:9 | t1 |
| test.cpp:17:8:17:8 | 0 | test.cpp:17:3:17:8 | ... = ... |
| test.cpp:21:8:21:9 | t1 | test.cpp:23:19:23:19 | Phi |
| test.cpp:21:8:21:9 | t1 | test.cpp:23:19:23:19 | Phi |
| test.cpp:21:8:21:9 | t1 | test.cpp:23:15:23:16 | Phi input |
| test.cpp:21:8:21:9 | t1 | test.cpp:23:15:23:16 | Phi input |
| test.cpp:23:15:23:16 | 0 | test.cpp:23:15:23:16 | 0 |
| test.cpp:23:15:23:16 | 0 | test.cpp:23:19:23:19 | Phi |
| test.cpp:23:19:23:19 | Phi | test.cpp:23:19:23:19 | i |
| test.cpp:23:19:23:19 | Phi | test.cpp:23:19:23:19 | i |
| test.cpp:23:19:23:19 | Phi | test.cpp:23:23:23:24 | t1 |
| test.cpp:23:19:23:19 | Phi | test.cpp:23:23:23:24 | t1 |
| test.cpp:23:19:23:19 | Phi | test.cpp:24:10:24:11 | t2 |
| test.cpp:23:19:23:19 | Phi | test.cpp:24:10:24:11 | t2 |
| test.cpp:23:15:23:16 | 0 | test.cpp:23:15:23:16 | Phi input |
| test.cpp:23:15:23:16 | Phi input | test.cpp:23:19:23:19 | SSA phi read(*t2) |
| test.cpp:23:15:23:16 | Phi input | test.cpp:23:19:23:19 | SSA phi read(i) |
| test.cpp:23:15:23:16 | Phi input | test.cpp:23:19:23:19 | SSA phi read(t1) |
| test.cpp:23:15:23:16 | Phi input | test.cpp:23:19:23:19 | SSA phi read(t2) |
| test.cpp:23:15:23:16 | Phi input | test.cpp:23:19:23:19 | SSA phi(*i) |
| test.cpp:23:15:23:16 | Phi input | test.cpp:23:19:23:19 | SSA phi(*t1) |
| test.cpp:23:19:23:19 | SSA phi read(*t2) | test.cpp:24:10:24:11 | t2 |
| test.cpp:23:19:23:19 | SSA phi read(i) | test.cpp:23:19:23:19 | i |
| test.cpp:23:19:23:19 | SSA phi read(t1) | test.cpp:23:23:23:24 | t1 |
| test.cpp:23:19:23:19 | SSA phi read(t2) | test.cpp:24:10:24:11 | t2 |
| test.cpp:23:19:23:19 | SSA phi(*i) | test.cpp:23:19:23:19 | i |
| test.cpp:23:19:23:19 | SSA phi(*t1) | test.cpp:23:23:23:24 | t1 |
| test.cpp:23:19:23:19 | i | test.cpp:23:27:23:27 | i |
| test.cpp:23:19:23:19 | i | test.cpp:23:27:23:27 | i |
| test.cpp:23:23:23:24 | t1 | test.cpp:23:19:23:19 | Phi |
| test.cpp:23:23:23:24 | t1 | test.cpp:23:27:23:29 | Phi input |
| test.cpp:23:23:23:24 | t1 | test.cpp:26:8:26:9 | t1 |
| test.cpp:23:23:23:24 | t1 | test.cpp:26:8:26:9 | t1 |
| test.cpp:23:27:23:27 | *i | test.cpp:23:27:23:27 | *i |
| test.cpp:23:27:23:27 | *i | test.cpp:23:27:23:27 | i |
| test.cpp:23:27:23:27 | i | test.cpp:23:19:23:19 | Phi |
| test.cpp:23:27:23:27 | i | test.cpp:23:27:23:27 | i |
| test.cpp:23:27:23:27 | i | test.cpp:23:27:23:27 | i |
| test.cpp:23:27:23:29 | ... ++ | test.cpp:23:19:23:19 | Phi |
| test.cpp:23:27:23:27 | i | test.cpp:23:27:23:29 | Phi input |
| test.cpp:23:27:23:29 | ... ++ | test.cpp:23:27:23:29 | ... ++ |
| test.cpp:24:5:24:11 | ... = ... | test.cpp:23:19:23:19 | Phi |
| test.cpp:24:10:24:11 | t2 | test.cpp:23:19:23:19 | Phi |
| test.cpp:24:10:24:11 | t2 | test.cpp:23:19:23:19 | Phi |
| test.cpp:23:27:23:29 | ... ++ | test.cpp:23:27:23:29 | Phi input |
| test.cpp:23:27:23:29 | Phi input | test.cpp:23:19:23:19 | SSA phi read(*t2) |
| test.cpp:23:27:23:29 | Phi input | test.cpp:23:19:23:19 | SSA phi read(i) |
| test.cpp:23:27:23:29 | Phi input | test.cpp:23:19:23:19 | SSA phi read(t1) |
| test.cpp:23:27:23:29 | Phi input | test.cpp:23:19:23:19 | SSA phi read(t2) |
| test.cpp:23:27:23:29 | Phi input | test.cpp:23:19:23:19 | SSA phi(*i) |
| test.cpp:23:27:23:29 | Phi input | test.cpp:23:19:23:19 | SSA phi(*t1) |
| test.cpp:24:5:24:11 | ... = ... | test.cpp:23:27:23:29 | Phi input |
| test.cpp:24:10:24:11 | t2 | test.cpp:23:27:23:29 | Phi input |
| test.cpp:24:10:24:11 | t2 | test.cpp:23:27:23:29 | Phi input |
| test.cpp:24:10:24:11 | t2 | test.cpp:24:5:24:11 | ... = ... |
| test.cpp:382:48:382:54 | source1 | test.cpp:384:16:384:23 | *& ... |
| test.cpp:383:12:383:13 | 0 | test.cpp:383:12:383:13 | 0 |

View File

@@ -12,6 +12,10 @@ astFlow
| BarrierGuard.cpp:60:11:60:16 | call to source | BarrierGuard.cpp:62:14:62:14 | x |
| BarrierGuard.cpp:60:11:60:16 | call to source | BarrierGuard.cpp:64:14:64:14 | x |
| BarrierGuard.cpp:60:11:60:16 | call to source | BarrierGuard.cpp:66:14:66:14 | x |
| BarrierGuard.cpp:81:11:81:16 | call to source | BarrierGuard.cpp:86:8:86:8 | x |
| BarrierGuard.cpp:90:11:90:16 | call to source | BarrierGuard.cpp:101:8:101:8 | x |
| BarrierGuard.cpp:107:11:107:16 | call to source | BarrierGuard.cpp:112:8:112:8 | x |
| BarrierGuard.cpp:116:11:116:16 | call to source | BarrierGuard.cpp:127:8:127:8 | x |
| acrossLinkTargets.cpp:19:27:19:32 | call to source | acrossLinkTargets.cpp:12:8:12:8 | x |
| clang.cpp:12:9:12:20 | sourceArray1 | clang.cpp:18:8:18:19 | sourceArray1 |
| clang.cpp:12:9:12:20 | sourceArray1 | clang.cpp:22:8:22:20 | & ... |
@@ -141,6 +145,8 @@ irFlow
| BarrierGuard.cpp:49:10:49:15 | call to source | BarrierGuard.cpp:55:13:55:13 | x |
| BarrierGuard.cpp:60:11:60:16 | call to source | BarrierGuard.cpp:64:14:64:14 | x |
| BarrierGuard.cpp:60:11:60:16 | call to source | BarrierGuard.cpp:66:14:66:14 | x |
| BarrierGuard.cpp:81:11:81:16 | call to source | BarrierGuard.cpp:86:8:86:8 | x |
| BarrierGuard.cpp:90:11:90:16 | call to source | BarrierGuard.cpp:101:8:101:8 | x |
| acrossLinkTargets.cpp:19:27:19:32 | call to source | acrossLinkTargets.cpp:12:8:12:8 | x |
| clang.cpp:12:9:12:20 | sourceArray1 | clang.cpp:18:8:18:19 | sourceArray1 |
| clang.cpp:12:9:12:20 | sourceArray1 | clang.cpp:23:17:23:29 | *& ... |
@@ -153,6 +159,7 @@ irFlow
| clang.cpp:50:25:50:30 | call to source | clang.cpp:53:17:53:26 | *stackArray |
| clang.cpp:50:35:50:40 | call to source | clang.cpp:53:17:53:26 | *stackArray |
| clang.cpp:51:19:51:24 | call to source | clang.cpp:53:17:53:26 | *stackArray |
| clang.cpp:57:21:57:28 | call to source | clang.cpp:59:8:59:8 | d |
| dispatch.cpp:9:37:9:42 | call to source | dispatch.cpp:35:16:35:25 | call to notSource1 |
| dispatch.cpp:9:37:9:42 | call to source | dispatch.cpp:43:15:43:24 | call to notSource1 |
| dispatch.cpp:10:37:10:42 | call to source | dispatch.cpp:36:16:36:25 | call to notSource2 |

View File

@@ -0,0 +1,107 @@
// --- stub library headers ---
namespace std {
typedef unsigned long size_t;
#define SIZE_MAX 0xFFFFFFFF
template <class T> class allocator {
};
template<class charT> struct char_traits {
};
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
class basic_string {
public:
basic_string(const charT* s, const Allocator& a = Allocator());
};
typedef basic_string<char> string;
};
namespace boost {
namespace system {
class error_code {
public:
operator bool() const;
};
};
namespace asio {
template<typename Protocol/*, typename Executor*/>
class basic_stream_socket /*: public basic_socket<Protocol, Executor>*/ {
};
namespace ip {
class tcp {
public:
typedef basic_stream_socket<tcp> socket;
};
};
template<typename Allocator = std::allocator<char>> class basic_streambuf {
public:
basic_streambuf(
std::size_t maximum_size = SIZE_MAX,
const Allocator &allocator = Allocator());
};
typedef basic_streambuf<> streambuf;
class mutable_buffer {
};
template<typename Elem, typename Traits, typename Allocator>
mutable_buffer buffer(std::basic_string<Elem, Traits, Allocator> & data);
template<typename SyncReadStream, typename Allocator> std::size_t read_until(
SyncReadStream &s,
asio::basic_streambuf<Allocator> &b,
char delim,
boost::system::error_code &ec);
template<typename SyncWriteStream, typename ConstBufferSequence> std::size_t write(
SyncWriteStream &s,
const ConstBufferSequence &buffers,
boost::system::error_code &ec,
int constraint = 0); // simplified
};
};
// --- test code ---
char *source();
void sink(char *);
void sink(std::string);
void sink(boost::asio::streambuf);
void sink(boost::asio::mutable_buffer);
char *getenv(const char *name);
int send(int, const void*, int, int);
void test(boost::asio::ip::tcp::socket &socket) {
boost::asio::streambuf recv_buffer;
boost::system::error_code error;
boost::asio::read_until(socket, recv_buffer, '\0', error);
if (error) {
// ...
}
sink(recv_buffer); // $ ir
boost::asio::write(socket, recv_buffer, error); // $ ir
// ---
std::string send_str = std::string(source());
sink(send_str); // $ ir
boost::asio::mutable_buffer send_buffer = boost::asio::buffer(send_str);
sink(send_buffer); // $ ir
boost::asio::write(socket, send_buffer, error); // $ ir
if (error) {
// ...
}
}

View File

@@ -0,0 +1,2 @@
testFailures
failures

View File

@@ -0,0 +1,16 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: sourceModel
data: # namespace, type, subtypes, name, signature, ext, output, kind, provenance
- ["", "", False, "ymlSource", "", "", "ReturnValue", "local", "manual"]
- addsTo:
pack: codeql/cpp-all
extensible: sinkModel
data: # namespace, type, subtypes, name, signature, ext, input, kind, provenance
- ["", "", False, "ymlSink", "", "", "Argument[0]", "test-sink", "manual"]
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
- ["", "", False, "ymlStep", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]

View File

@@ -0,0 +1,34 @@
import TestUtilities.dataflow.FlowTestCommon
import cpp
import semmle.code.cpp.security.FlowSources
module IRTest {
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.ir.dataflow.TaintTracking
/** Common data flow configuration to be used by tests. */
module TestAllocationConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
// external flow source node
sourceNode(source, _)
or
// test source function
source.asExpr().(FunctionCall).getTarget().getName() = "source"
}
predicate isSink(DataFlow::Node sink) {
// external flow sink node
sinkNode(sink, _)
or
// test sink function
exists(FunctionCall call |
call.getTarget().getName() = "sink" and
sink.asExpr() = call.getAnArgument()
)
}
}
module IRFlow = TaintTracking::Global<TestAllocationConfig>;
}
import MakeTest<IRFlowTest<IRTest::IRFlow>>

View File

@@ -0,0 +1,5 @@
| asio_streams.cpp:93:29:93:39 | *recv_buffer | remote-sink |
| asio_streams.cpp:103:29:103:39 | *send_buffer | remote-sink |
| test.cpp:9:10:9:10 | 0 | test-sink |
| test.cpp:11:10:11:10 | x | test-sink |
| test.cpp:15:10:15:10 | y | test-sink |

View File

@@ -0,0 +1,6 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: sinkModel
data: # namespace, type, subtypes, name, signature, ext, input, kind, provenance
- ["", "", False, "ymlSink", "", "", "Argument[0]", "test-sink", "manual"]

View File

@@ -0,0 +1,7 @@
import cpp
import semmle.code.cpp.ir.dataflow.DataFlow
import semmle.code.cpp.dataflow.ExternalFlow
from DataFlow::Node node, string kind
where sinkNode(node, kind)
select node, kind

View File

@@ -0,0 +1,2 @@
| asio_streams.cpp:87:34:87:44 | read_until output argument | remote |
| test.cpp:7:10:7:18 | call to ymlSource | local |

View File

@@ -0,0 +1,6 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: sourceModel
data: # namespace, type, subtypes, name, signature, ext, output, kind, provenance
- ["", "", False, "ymlSource", "", "", "ReturnValue", "local", "manual"]

View File

@@ -0,0 +1,7 @@
import cpp
import semmle.code.cpp.ir.dataflow.DataFlow
import semmle.code.cpp.dataflow.ExternalFlow
from DataFlow::Node node, string kind
where sourceNode(node, kind)
select node, kind

View File

@@ -0,0 +1,2 @@
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer |
| test.cpp:13:18:13:18 | x | test.cpp:13:10:13:16 | call to ymlStep |

View File

@@ -0,0 +1,6 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
- ["", "", False, "ymlStep", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]

View File

@@ -0,0 +1,8 @@
import cpp
import semmle.code.cpp.ir.dataflow.DataFlow
import semmle.code.cpp.dataflow.ExternalFlow
import semmle.code.cpp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
from DataFlow::Node node1, DataFlow::Node node2
where FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(node1, node2, _)
select node1, node2

View File

@@ -0,0 +1,16 @@
int ymlSource();
void ymlSink(int value);
int ymlStep(int value);
void test() {
int x = ymlSource();
ymlSink(0);
ymlSink(x); // $ ir
int y = ymlStep(x);
ymlSink(y); // $ ir
}

View File

@@ -0,0 +1,2 @@
import cpp
import semmle.code.cpp.dataflow.ExternalFlow::CsvValidation

View File

@@ -184,6 +184,7 @@ postWithInFlow
| simple.cpp:65:7:65:7 | i [post update] | PostUpdateNode should not be the target of local flow. |
| simple.cpp:83:12:83:13 | f1 [post update] | PostUpdateNode should not be the target of local flow. |
| simple.cpp:92:7:92:7 | i [post update] | PostUpdateNode should not be the target of local flow. |
| simple.cpp:118:7:118:7 | i [post update] | PostUpdateNode should not be the target of local flow. |
| struct_init.c:24:11:24:12 | ab [inner post update] | PostUpdateNode should not be the target of local flow. |
| struct_init.c:36:17:36:24 | nestedAB [inner post update] | PostUpdateNode should not be the target of local flow. |
viableImplInCallContextTooLarge

View File

@@ -842,6 +842,10 @@ edges
| simple.cpp:108:17:108:26 | call to user_input | simple.cpp:108:17:108:26 | call to user_input | provenance | |
| simple.cpp:108:17:108:26 | call to user_input | simple.cpp:109:43:109:43 | x | provenance | |
| simple.cpp:109:43:109:43 | x | simple.cpp:103:24:103:24 | x | provenance | |
| simple.cpp:118:5:118:5 | *a [post update] [i] | simple.cpp:120:8:120:8 | *a [i] | provenance | |
| simple.cpp:118:5:118:22 | ... = ... | simple.cpp:118:5:118:5 | *a [post update] [i] | provenance | |
| simple.cpp:118:11:118:20 | call to user_input | simple.cpp:118:5:118:22 | ... = ... | provenance | |
| simple.cpp:120:8:120:8 | *a [i] | simple.cpp:120:10:120:10 | i | provenance | |
| struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:14:24:14:25 | *ab [a] | provenance | |
| struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:15:8:15:9 | *ab [a] | provenance | |
| struct_init.c:15:8:15:9 | *ab [a] | struct_init.c:15:12:15:12 | a | provenance | |
@@ -1747,6 +1751,11 @@ nodes
| simple.cpp:108:17:108:26 | call to user_input | semmle.label | call to user_input |
| simple.cpp:108:17:108:26 | call to user_input | semmle.label | call to user_input |
| simple.cpp:109:43:109:43 | x | semmle.label | x |
| simple.cpp:118:5:118:5 | *a [post update] [i] | semmle.label | *a [post update] [i] |
| simple.cpp:118:5:118:22 | ... = ... | semmle.label | ... = ... |
| simple.cpp:118:11:118:20 | call to user_input | semmle.label | call to user_input |
| simple.cpp:120:8:120:8 | *a [i] | semmle.label | *a [i] |
| simple.cpp:120:10:120:10 | i | semmle.label | i |
| struct_init.c:14:24:14:25 | *ab [a] | semmle.label | *ab [a] |
| struct_init.c:14:24:14:25 | *ab [a] | semmle.label | *ab [a] |
| struct_init.c:15:8:15:9 | *ab [a] | semmle.label | *ab [a] |
@@ -1957,6 +1966,7 @@ subpaths
| simple.cpp:84:14:84:20 | call to getf2f1 | simple.cpp:83:17:83:26 | call to user_input | simple.cpp:84:14:84:20 | call to getf2f1 | call to getf2f1 flows from $@ | simple.cpp:83:17:83:26 | call to user_input | call to user_input |
| simple.cpp:94:13:94:13 | i | simple.cpp:92:11:92:20 | call to user_input | simple.cpp:94:13:94:13 | i | i flows from $@ | simple.cpp:92:11:92:20 | call to user_input | call to user_input |
| simple.cpp:104:14:104:14 | x | simple.cpp:108:17:108:26 | call to user_input | simple.cpp:104:14:104:14 | x | x flows from $@ | simple.cpp:108:17:108:26 | call to user_input | call to user_input |
| simple.cpp:120:10:120:10 | i | simple.cpp:118:11:118:20 | call to user_input | simple.cpp:120:10:120:10 | i | i flows from $@ | simple.cpp:118:11:118:20 | call to user_input | call to user_input |
| struct_init.c:15:12:15:12 | a | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input | call to user_input |
| struct_init.c:15:12:15:12 | a | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:27:7:27:16 | call to user_input | call to user_input |
| struct_init.c:15:12:15:12 | a | struct_init.c:40:20:40:29 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:40:20:40:29 | call to user_input | call to user_input |

View File

@@ -289,3 +289,5 @@ WARNING: Module DataFlow has been deprecated and may be removed in future (parti
| simple.cpp:83:12:83:13 | f1 | AST only |
| simple.cpp:92:7:92:7 | i | AST only |
| simple.cpp:94:10:94:11 | a2 | IR only |
| simple.cpp:118:7:118:7 | i | AST only |
| simple.cpp:120:8:120:8 | a | IR only |

View File

@@ -649,6 +649,8 @@
| simple.cpp:84:14:84:20 | this |
| simple.cpp:92:5:92:5 | a |
| simple.cpp:94:10:94:11 | a2 |
| simple.cpp:118:5:118:5 | a |
| simple.cpp:120:8:120:8 | a |
| struct_init.c:15:8:15:9 | ab |
| struct_init.c:15:12:15:12 | a |
| struct_init.c:16:8:16:9 | ab |

View File

@@ -579,6 +579,8 @@ WARNING: Module DataFlow has been deprecated and may be removed in future (parti
| simple.cpp:84:14:84:20 | this |
| simple.cpp:92:5:92:5 | a |
| simple.cpp:92:7:92:7 | i |
| simple.cpp:118:5:118:5 | a |
| simple.cpp:118:7:118:7 | i |
| struct_init.c:15:8:15:9 | ab |
| struct_init.c:15:12:15:12 | a |
| struct_init.c:16:8:16:9 | ab |

View File

@@ -731,6 +731,10 @@ edges
| simple.cpp:92:5:92:22 | ... = ... | simple.cpp:92:5:92:5 | a [post update] [i] | provenance | |
| simple.cpp:92:11:92:20 | call to user_input | simple.cpp:92:5:92:22 | ... = ... | provenance | |
| simple.cpp:94:10:94:11 | a2 [i] | simple.cpp:94:13:94:13 | i | provenance | |
| simple.cpp:118:5:118:5 | a [post update] [i] | simple.cpp:120:8:120:8 | a [i] | provenance | |
| simple.cpp:118:5:118:22 | ... = ... | simple.cpp:118:5:118:5 | a [post update] [i] | provenance | |
| simple.cpp:118:11:118:20 | call to user_input | simple.cpp:118:5:118:22 | ... = ... | provenance | |
| simple.cpp:120:8:120:8 | a [i] | simple.cpp:120:10:120:10 | i | provenance | |
| struct_init.c:14:24:14:25 | ab [a] | struct_init.c:14:24:14:25 | ab [a] | provenance | |
| struct_init.c:14:24:14:25 | ab [a] | struct_init.c:15:8:15:9 | ab [a] | provenance | |
| struct_init.c:15:8:15:9 | ab [a] | struct_init.c:15:12:15:12 | a | provenance | |
@@ -1538,6 +1542,11 @@ nodes
| simple.cpp:92:11:92:20 | call to user_input | semmle.label | call to user_input |
| simple.cpp:94:10:94:11 | a2 [i] | semmle.label | a2 [i] |
| simple.cpp:94:13:94:13 | i | semmle.label | i |
| simple.cpp:118:5:118:5 | a [post update] [i] | semmle.label | a [post update] [i] |
| simple.cpp:118:5:118:22 | ... = ... | semmle.label | ... = ... |
| simple.cpp:118:11:118:20 | call to user_input | semmle.label | call to user_input |
| simple.cpp:120:8:120:8 | a [i] | semmle.label | a [i] |
| simple.cpp:120:10:120:10 | i | semmle.label | i |
| struct_init.c:14:24:14:25 | ab [a] | semmle.label | ab [a] |
| struct_init.c:14:24:14:25 | ab [a] | semmle.label | ab [a] |
| struct_init.c:15:8:15:9 | ab [a] | semmle.label | ab [a] |
@@ -1751,6 +1760,7 @@ subpaths
| simple.cpp:67:13:67:13 | i | simple.cpp:65:11:65:20 | call to user_input | simple.cpp:67:13:67:13 | i | i flows from $@ | simple.cpp:65:11:65:20 | call to user_input | call to user_input |
| simple.cpp:84:14:84:20 | call to getf2f1 | simple.cpp:83:17:83:26 | call to user_input | simple.cpp:84:14:84:20 | call to getf2f1 | call to getf2f1 flows from $@ | simple.cpp:83:17:83:26 | call to user_input | call to user_input |
| simple.cpp:94:13:94:13 | i | simple.cpp:92:11:92:20 | call to user_input | simple.cpp:94:13:94:13 | i | i flows from $@ | simple.cpp:92:11:92:20 | call to user_input | call to user_input |
| simple.cpp:120:10:120:10 | i | simple.cpp:118:11:118:20 | call to user_input | simple.cpp:120:10:120:10 | i | i flows from $@ | simple.cpp:118:11:118:20 | call to user_input | call to user_input |
| struct_init.c:15:12:15:12 | a | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input | call to user_input |
| struct_init.c:15:12:15:12 | a | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:27:7:27:16 | call to user_input | call to user_input |
| struct_init.c:15:12:15:12 | a | struct_init.c:40:20:40:29 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:40:20:40:29 | call to user_input | call to user_input |

View File

@@ -111,4 +111,13 @@ namespace TestAdditionalCallTargets {
}
void post_update_to_phi_input(bool b)
{
A a;
if(b) {
a.i = user_input();
}
sink(a.i); // $ ast,ir
}
} // namespace Simple

View File

@@ -0,0 +1,89 @@
// --- stub library headers ---
namespace std {
typedef unsigned long size_t;
#define SIZE_MAX 0xFFFFFFFF
template <class T> class allocator {
};
template<class charT> struct char_traits {
};
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
class basic_string {
public:
basic_string(const charT* s, const Allocator& a = Allocator());
};
typedef basic_string<char> string;
};
namespace boost {
namespace system {
class error_code {
public:
operator bool() const;
};
};
namespace asio {
template<typename Protocol/*, typename Executor*/>
class basic_stream_socket /*: public basic_socket<Protocol, Executor>*/ {
};
namespace ip {
class tcp {
public:
typedef basic_stream_socket<tcp> socket;
};
};
template<typename Allocator = std::allocator<char>> class basic_streambuf {
public:
basic_streambuf(
std::size_t maximum_size = SIZE_MAX,
const Allocator &allocator = Allocator());
};
typedef basic_streambuf<> streambuf;
class mutable_buffer {
};
template<typename Elem, typename Traits, typename Allocator>
mutable_buffer buffer(std::basic_string<Elem, Traits, Allocator> & data);
template<typename SyncReadStream, typename Allocator> std::size_t read_until(
SyncReadStream &s,
asio::basic_streambuf<Allocator> &b,
char delim,
boost::system::error_code &ec);
template<typename SyncWriteStream, typename ConstBufferSequence> std::size_t write(
SyncWriteStream &s,
const ConstBufferSequence &buffers,
boost::system::error_code &ec,
int constraint = 0); // simplified
};
};
// --- test code ---
void test(boost::asio::ip::tcp::socket &socket) {
boost::asio::streambuf recv_buffer;
boost::system::error_code error;
boost::asio::read_until(socket, recv_buffer, '\0', error); // $ remote_source
if (error) {
// ...
}
std::string send_str = std::string("message");
boost::asio::mutable_buffer send_buffer = boost::asio::buffer(send_str);
boost::asio::write(socket, send_buffer, error); // $ remote_sink
if (error) {
// ...
}
}

View File

@@ -22734,6 +22734,25 @@ ir.cpp:
# 2552| Type = [Class] ClassWithDestructor
# 2552| ValueCategory = xvalue
# 2553| getStmt(1): [ReturnStmt] return ...
# 2555| [TopLevelFunction] void builtin_bitcast(unsigned long)
# 2555| <params>:
# 2555| getParameter(0): [Parameter] ul
# 2555| Type = [LongType] unsigned long
# 2555| getEntryPoint(): [BlockStmt] { ... }
# 2556| getStmt(0): [DeclStmt] declaration
# 2556| getDeclarationEntry(0): [VariableDeclarationEntry] definition of d
# 2556| Type = [DoubleType] double
# 2556| getVariable().getInitializer(): [Initializer] initializer for d
# 2556| getExpr(): [BuiltInBitCast] __builtin_bit_cast
# 2556| Type = [DoubleType] double
# 2556| ValueCategory = prvalue
# 2556| getChild(0): [TypeName] double
# 2556| Type = [DoubleType] double
# 2556| ValueCategory = prvalue
# 2556| getChild(1): [VariableAccess] ul
# 2556| Type = [LongType] unsigned long
# 2556| ValueCategory = prvalue(load)
# 2557| getStmt(1): [ReturnStmt] return ...
perf-regression.cpp:
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
# 4| <params>:

View File

@@ -13430,6 +13430,32 @@ ir.cpp:
# 1898| v1898_6(void) = AliasedUse : m1898_3
# 1898| v1898_7(void) = ExitFunction :
# 1899| const char[17] __PRETTY_FUNCTION__
# 1899| Block 0
# 1899| v1899_1(void) = EnterFunction :
# 1899| m1899_2(unknown) = AliasedDefinition :
# 1899| r1899_3(glval<char[17]>) = VariableAddress[__PRETTY_FUNCTION__] :
# 1899| r1899_4(glval<char[17]>) = StringConstant[__PRETTY_FUNCTION__] :
# 1899| r1899_5(char[17]) = Load[?] : &:r1899_4, ~m?
# 1899| m1899_6(char[17]) = Store[__PRETTY_FUNCTION__] : &:r1899_3, r1899_5
# 1899| m1899_7(unknown) = Chi : total:m1899_2, partial:m1899_6
# 1899| v1899_8(void) = ReturnVoid :
# 1899| v1899_9(void) = AliasedUse : ~m1899_7
# 1899| v1899_10(void) = ExitFunction :
# 1900| const char[10] __func__
# 1900| Block 0
# 1900| v1900_1(void) = EnterFunction :
# 1900| m1900_2(unknown) = AliasedDefinition :
# 1900| r1900_3(glval<char[10]>) = VariableAddress[__func__] :
# 1900| r1900_4(glval<char[10]>) = StringConstant[__func__] :
# 1900| r1900_5(char[10]) = Load[?] : &:r1900_4, ~m?
# 1900| m1900_6(char[10]) = Store[__func__] : &:r1900_3, r1900_5
# 1900| m1900_7(unknown) = Chi : total:m1900_2, partial:m1900_6
# 1900| v1900_8(void) = ReturnVoid :
# 1900| v1900_9(void) = AliasedUse : ~m1900_7
# 1900| v1900_10(void) = ExitFunction :
# 1911| void* missing_declaration_entries::Bar1<int>::missing_type_decl_entry(missing_declaration_entries::Bar1<int>::pointer)
# 1911| Block 0
# 1911| v1911_1(void) = EnterFunction :
@@ -18351,6 +18377,24 @@ ir.cpp:
# 2550| Block 2
# 2550| v2550_10(void) = Unreached :
# 2555| void builtin_bitcast(unsigned long)
# 2555| Block 0
# 2555| v2555_1(void) = EnterFunction :
# 2555| m2555_2(unknown) = AliasedDefinition :
# 2555| m2555_3(unknown) = InitializeNonLocal :
# 2555| m2555_4(unknown) = Chi : total:m2555_2, partial:m2555_3
# 2555| r2555_5(glval<unsigned long>) = VariableAddress[ul] :
# 2555| m2555_6(unsigned long) = InitializeParameter[ul] : &:r2555_5
# 2556| r2556_1(glval<double>) = VariableAddress[d] :
# 2556| r2556_2(glval<unsigned long>) = VariableAddress[ul] :
# 2556| r2556_3(unsigned long) = Load[ul] : &:r2556_2, m2555_6
# 2556| r2556_4(double) = BuiltIn[__builtin_bit_cast] : 0:r2556_3
# 2556| m2556_5(double) = Store[d] : &:r2556_1, r2556_4
# 2557| v2557_1(void) = NoOp :
# 2555| v2555_7(void) = ReturnVoid :
# 2555| v2555_8(void) = AliasedUse : m2555_3
# 2555| v2555_9(void) = ExitFunction :
perf-regression.cpp:
# 6| void Big::Big()
# 6| Block 0

View File

@@ -2552,4 +2552,8 @@ void constexpr_inconsistency(bool b) {
;
}
void builtin_bitcast(unsigned long ul) {
double d = __builtin_bit_cast(double, ul);
}
// semmle-extractor-options: -std=c++20 --clang

View File

@@ -12384,6 +12384,30 @@ ir.cpp:
# 1898| v1898_5(void) = AliasedUse : ~m?
# 1898| v1898_6(void) = ExitFunction :
# 1899| const char[17] __PRETTY_FUNCTION__
# 1899| Block 0
# 1899| v1899_1(void) = EnterFunction :
# 1899| mu1899_2(unknown) = AliasedDefinition :
# 1899| r1899_3(glval<char[17]>) = VariableAddress[__PRETTY_FUNCTION__] :
# 1899| r1899_4(glval<char[17]>) = StringConstant[__PRETTY_FUNCTION__] :
# 1899| r1899_5(char[17]) = Load[?] : &:r1899_4, ~m?
# 1899| mu1899_6(char[17]) = Store[__PRETTY_FUNCTION__] : &:r1899_3, r1899_5
# 1899| v1899_7(void) = ReturnVoid :
# 1899| v1899_8(void) = AliasedUse : ~m?
# 1899| v1899_9(void) = ExitFunction :
# 1900| const char[10] __func__
# 1900| Block 0
# 1900| v1900_1(void) = EnterFunction :
# 1900| mu1900_2(unknown) = AliasedDefinition :
# 1900| r1900_3(glval<char[10]>) = VariableAddress[__func__] :
# 1900| r1900_4(glval<char[10]>) = StringConstant[__func__] :
# 1900| r1900_5(char[10]) = Load[?] : &:r1900_4, ~m?
# 1900| mu1900_6(char[10]) = Store[__func__] : &:r1900_3, r1900_5
# 1900| v1900_7(void) = ReturnVoid :
# 1900| v1900_8(void) = AliasedUse : ~m?
# 1900| v1900_9(void) = ExitFunction :
# 1911| void* missing_declaration_entries::Bar1<int>::missing_type_decl_entry(missing_declaration_entries::Bar1<int>::pointer)
# 1911| Block 0
# 1911| v1911_1(void) = EnterFunction :
@@ -16693,6 +16717,23 @@ ir.cpp:
# 2550| v2550_7(void) = AliasedUse : ~m?
# 2550| v2550_8(void) = ExitFunction :
# 2555| void builtin_bitcast(unsigned long)
# 2555| Block 0
# 2555| v2555_1(void) = EnterFunction :
# 2555| mu2555_2(unknown) = AliasedDefinition :
# 2555| mu2555_3(unknown) = InitializeNonLocal :
# 2555| r2555_4(glval<unsigned long>) = VariableAddress[ul] :
# 2555| mu2555_5(unsigned long) = InitializeParameter[ul] : &:r2555_4
# 2556| r2556_1(glval<double>) = VariableAddress[d] :
# 2556| r2556_2(glval<unsigned long>) = VariableAddress[ul] :
# 2556| r2556_3(unsigned long) = Load[ul] : &:r2556_2, ~m?
# 2556| r2556_4(double) = BuiltIn[__builtin_bit_cast] : 0:r2556_3
# 2556| mu2556_5(double) = Store[d] : &:r2556_1, r2556_4
# 2557| v2557_1(void) = NoOp :
# 2555| v2555_6(void) = ReturnVoid :
# 2555| v2555_7(void) = AliasedUse : ~m?
# 2555| v2555_8(void) = ExitFunction :
perf-regression.cpp:
# 6| void Big::Big()
# 6| Block 0

View File

@@ -39,3 +39,4 @@
| variables.cpp:51:9:51:12 | town | file://:0:0:0:0 | char * | Field | | |
| variables.cpp:52:16:52:22 | country | file://:0:0:0:0 | char * | MemberVariable, StaticStorageDurationVariable | | static |
| variables.cpp:56:14:56:29 | externInFunction | file://:0:0:0:0 | int | GlobalLikeVariable, GlobalVariable, StaticStorageDurationVariable | | |
| variables.cpp:60:10:60:17 | __func__ | file://:0:0:0:0 | const char[9] | GlobalLikeVariable, StaticInitializedStaticLocalVariable | | static |

View File

@@ -55,3 +55,7 @@ struct address {
void hasExtern() {
extern int externInFunction;
}
const char* isStatic() {
return __func__;
}

View File

@@ -12,7 +12,7 @@ namespace Semmle.Autobuild.CSharp
public class CSharpAutobuildOptions : AutobuildOptionsShared
{
private const string buildModeEnvironmentVariable = "CODEQL_EXTRACTOR_CSHARP_BUILD_MODE";
private const string extractorOptionPrefix = "CODEQL_EXTRACTOR_CSHARP_OPTION_";
internal const string ExtractorOptionBuildless = "CODEQL_EXTRACTOR_CSHARP_OPTION_BUILDLESS";
public bool Buildless { get; }
@@ -26,7 +26,7 @@ namespace Semmle.Autobuild.CSharp
public CSharpAutobuildOptions(IBuildActions actions) : base(actions)
{
Buildless =
actions.GetEnvironmentVariable(extractorOptionPrefix + "BUILDLESS").AsBool("buildless", false) ||
actions.GetEnvironmentVariable(ExtractorOptionBuildless).AsBool("buildless", false) ||
actions.GetEnvironmentVariable(buildModeEnvironmentVariable)?.ToLower() == "none";
@@ -51,7 +51,7 @@ namespace Semmle.Autobuild.CSharp
case CSharpBuildStrategy.Buildless:
// No need to check that the extractor has been executed in buildless mode
attempt = BuildScript.Bind(
AddBuildlessStartedDiagnostic() & new StandaloneBuildRule().Analyse(this, false),
AddBuildlessWronglyConfiguredWarning() & AddBuildlessStartedDiagnostic() & new StandaloneBuildRule().Analyse(this, false),
AddBuildlessEndedDiagnostic);
break;
case CSharpBuildStrategy.Auto:
@@ -81,6 +81,27 @@ namespace Semmle.Autobuild.CSharp
return 1;
});
private BuildScript AddBuildlessWronglyConfiguredWarning()
{
return BuildScript.Create(actions =>
{
if (actions.GetEnvironmentVariable(CSharpAutobuildOptions.ExtractorOptionBuildless) is null)
{
return 0;
}
AddDiagnostic(new DiagnosticMessage(
Options.Language,
"buildless/use-build-mode",
"C# was extracted with the deprecated 'buildless' option, use build-mode instead",
visibility: new DiagnosticMessage.TspVisibility(statusPage: true, cliSummaryTable: true, telemetry: true),
markdownMessage: "C# was extracted with the deprecated 'buildless' option, use build-mode instead.",
severity: DiagnosticMessage.TspSeverity.Warning
));
return 0;
});
}
private BuildScript AddBuildlessStartedDiagnostic()
{
return BuildScript.Create(actions =>

View File

@@ -312,8 +312,6 @@ namespace Semmle.Extraction.CSharp
else
Logger.Log(Severity.Info, "EXTRACTION SUCCEEDED in {0}", stopWatch.Elapsed);
Logger.Dispose();
compilationTrapFile?.Dispose();
}

View File

@@ -0,0 +1 @@
var dummy = "dummy";

View File

@@ -0,0 +1,42 @@
{
"markdownMessage": "C# analysis with build-mode 'none' completed.",
"severity": "unknown",
"source": {
"extractorName": "csharp",
"id": "csharp/autobuilder/buildless/complete",
"name": "C# analysis with build-mode 'none' completed"
},
"visibility": {
"cliSummaryTable": true,
"statusPage": false,
"telemetry": true
}
}
{
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as Nuget and Dotnet CLIs, only contributing information about external dependencies.",
"severity": "note",
"source": {
"extractorName": "csharp",
"id": "csharp/autobuilder/buildless/mode-active",
"name": "C# was extracted with build-mode set to 'none'"
},
"visibility": {
"cliSummaryTable": true,
"statusPage": true,
"telemetry": true
}
}
{
"markdownMessage": "C# was extracted with the deprecated 'buildless' option, use build-mode instead.",
"severity": "warning",
"source": {
"extractorName": "csharp",
"id": "csharp/autobuilder/buildless/use-build-mode",
"name": "C# was extracted with the deprecated 'buildless' option, use build-mode instead"
},
"visibility": {
"cliSummaryTable": true,
"statusPage": true,
"telemetry": true
}
}

View File

@@ -0,0 +1,5 @@
{
"sdk": {
"version": "8.0.101"
}
}

View File

@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,8 @@
import os
from create_database_utils import *
from diagnostics_test_utils import *
os.environ['CODEQL_EXTRACTOR_CSHARP_OPTION_BUILDLESS'] = 'true'
run_codeql_database_create([], lang="csharp")
check_diagnostics()

View File

@@ -10,8 +10,8 @@ private import semmle.code.csharp.frameworks.system.Collections
private import semmle.code.csharp.frameworks.system.collections.Generic
/**
* Gets a source declaration of callable `c` that has a body or has
* a flow summary.
* Gets a source declaration of callable `c` that has a body and is
* defined in source.
*/
Callable getCallableForDataFlow(Callable c) {
result = c.getUnboundDeclaration() and
@@ -269,13 +269,19 @@ class NonDelegateDataFlowCall extends DataFlowCall, TNonDelegateCall {
override DataFlowCallable getARuntimeTarget() {
result.asCallable() = getCallableForDataFlow(dc.getADynamicTarget())
or
exists(Callable c, boolean static |
result.asSummarizedCallable() = c and
c = this.getATarget(static)
// Only use summarized callables with generated summaries in case
// we are not able to dispatch to a source declaration.
exists(FlowSummary::SummarizedCallable sc, boolean static |
result.asSummarizedCallable() = sc and
sc = this.getATarget(static) and
not (
sc.applyGeneratedModel() and
dc.getADynamicTarget().getUnboundDeclaration().getFile().fromSource()
)
|
static = false
or
static = true and not c instanceof RuntimeCallable
static = true and not sc instanceof RuntimeCallable
)
}

View File

@@ -121,7 +121,9 @@ private predicate canonicalNamespaceLink(string namespace, string subns) {
/**
* Holds if MaD framework coverage of `namespace` is `n` api endpoints of the
* kind `(kind, part)`.
* kind `(kind, part)`, and `namespaces` is the number of subnamespaces of
* `namespace` which have MaD framework coverage (including `namespace`
* itself).
*/
predicate modelCoverage(string namespace, int namespaces, string kind, string part, int n) {
namespaces = strictcount(string subns | canonicalNamespaceLink(namespace, subns)) and
@@ -554,9 +556,9 @@ private predicate interpretNeutral(UnboundCallable c, string kind, string proven
private class SummarizedCallableAdapter extends SummarizedCallable {
SummarizedCallableAdapter() {
exists(Provenance provenance | interpretSummary(this, _, _, _, provenance, _) |
not this.hasBody()
not this.fromSource()
or
this.hasBody() and provenance.isManual()
this.fromSource() and provenance.isManual()
)
}

View File

@@ -32,6 +32,11 @@ module InsecureSqlConnectionConfig implements DataFlow::ConfigSig {
oc.getType().getName() = "SqlConnectionStringBuilder"
or
oc.getType().getName() = "SqlConnection"
) and
not exists(MemberInitializer mi |
mi = oc.getInitializer().(ObjectInitializer).getAMemberInitializer() and
mi.getLValue().(PropertyAccess).getTarget().getName() = "Encrypt" and
mi.getRValue().(BoolLiteral).getValue() = "true"
)
)
}

View File

@@ -200,31 +200,25 @@ namespace My.Qltest
void M3()
{
var o1 = new object();
Sink(MixedFlowArgs(o1, null));
Sink(Library.MixedFlowArgs(o1, null));
var o2 = new object();
Sink(MixedFlowArgs(null, o2));
Sink(Library.MixedFlowArgs(null, o2));
}
void M4()
{
var o1 = new object();
Sink(GeneratedFlowWithGeneratedNeutral(o1));
Sink(Library.GeneratedFlowWithGeneratedNeutral(o1));
var o2 = new object();
Sink(GeneratedFlowWithManualNeutral(o2)); // no flow because the modelled method has a manual neutral summary model
Sink(Library.GeneratedFlowWithManualNeutral(o2)); // no flow because the modelled method has a manual neutral summary model
}
object GeneratedFlow(object o) => throw null;
object GeneratedFlowArgs(object o1, object o2) => throw null;
object MixedFlowArgs(object o1, object o2) => throw null;
object GeneratedFlowWithGeneratedNeutral(object o) => throw null;
object GeneratedFlowWithManualNeutral(object o) => throw null;
static void Sink(object o) { }
}
@@ -268,4 +262,33 @@ namespace My.Qltest
static void Sink(object o) { }
}
public class J
{
public virtual object Prop1 { get; }
public virtual void SetProp1(object o) => throw null;
public virtual object Prop2 { get; }
public virtual void SetProp2(object o) => throw null;
void M1()
{
var j = new object();
SetProp1(j);
// flow as there is a manual summary.
Sink(this.Prop1);
}
void M2()
{
var j = new object();
SetProp2(j);
// no flow as there is only a generated summary and source code is available.
Sink(this.Prop2);
}
static void Sink(object o) { }
}
}

View File

@@ -0,0 +1,17 @@
using System;
namespace My.Qltest
{
public class Library
{
public static object MixedFlowArgs(object o1, object o2) => throw null;
public static object GeneratedFlowWithGeneratedNeutral(object o) => throw null;
public static object GeneratedFlowWithManualNeutral(object o) => throw null;
public static object StepArgReturnGenerated(object x) => throw null;
public static object StepArgReturnGeneratedIgnored(object x) => throw null;
}
}

View File

@@ -75,22 +75,27 @@ edges
| ExternalFlow.cs:118:21:118:30 | call to method Reverse : null [element] : Object | ExternalFlow.cs:118:17:118:17 | access to local variable b : null [element] : Object | provenance | |
| ExternalFlow.cs:118:29:118:29 | access to local variable a : null [element] : Object | ExternalFlow.cs:118:21:118:30 | call to method Reverse : null [element] : Object | provenance | MaD:17 |
| ExternalFlow.cs:120:18:120:18 | access to local variable b : null [element] : Object | ExternalFlow.cs:120:18:120:21 | access to array element | provenance | |
| ExternalFlow.cs:205:17:205:18 | access to local variable o2 : Object | ExternalFlow.cs:206:38:206:39 | access to local variable o2 : Object | provenance | |
| ExternalFlow.cs:205:17:205:18 | access to local variable o2 : Object | ExternalFlow.cs:206:46:206:47 | access to local variable o2 : Object | provenance | |
| ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | ExternalFlow.cs:205:17:205:18 | access to local variable o2 : Object | provenance | |
| ExternalFlow.cs:206:38:206:39 | access to local variable o2 : Object | ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs | provenance | MaD:24 |
| ExternalFlow.cs:211:17:211:18 | access to local variable o1 : Object | ExternalFlow.cs:212:52:212:53 | access to local variable o1 : Object | provenance | |
| ExternalFlow.cs:206:46:206:47 | access to local variable o2 : Object | ExternalFlow.cs:206:18:206:48 | call to method MixedFlowArgs | provenance | MaD:24 |
| ExternalFlow.cs:211:17:211:18 | access to local variable o1 : Object | ExternalFlow.cs:212:60:212:61 | access to local variable o1 : Object | provenance | |
| ExternalFlow.cs:211:22:211:33 | object creation of type Object : Object | ExternalFlow.cs:211:17:211:18 | access to local variable o1 : Object | provenance | |
| ExternalFlow.cs:212:52:212:53 | access to local variable o1 : Object | ExternalFlow.cs:212:18:212:54 | call to method GeneratedFlowWithGeneratedNeutral | provenance | MaD:25 |
| ExternalFlow.cs:244:17:244:17 | access to local variable h : HC | ExternalFlow.cs:245:21:245:21 | access to local variable h : HC | provenance | |
| ExternalFlow.cs:244:21:244:28 | object creation of type HC : HC | ExternalFlow.cs:244:17:244:17 | access to local variable h : HC | provenance | |
| ExternalFlow.cs:245:17:245:17 | access to local variable o : HC | ExternalFlow.cs:246:18:246:18 | access to local variable o | provenance | |
| ExternalFlow.cs:245:21:245:21 | access to local variable h : HC | ExternalFlow.cs:245:21:245:39 | call to method ExtensionMethod : HC | provenance | MaD:27 |
| ExternalFlow.cs:245:21:245:39 | call to method ExtensionMethod : HC | ExternalFlow.cs:245:17:245:17 | access to local variable o : HC | provenance | |
| ExternalFlow.cs:262:13:262:13 | [post] access to parameter a : MyInlineArray [element] : Object | ExternalFlow.cs:263:30:263:30 | access to parameter a : MyInlineArray [element] : Object | provenance | |
| ExternalFlow.cs:262:20:262:31 | object creation of type Object : Object | ExternalFlow.cs:262:13:262:13 | [post] access to parameter a : MyInlineArray [element] : Object | provenance | |
| ExternalFlow.cs:263:17:263:17 | access to local variable b : Object | ExternalFlow.cs:264:18:264:18 | access to local variable b | provenance | |
| ExternalFlow.cs:263:21:263:31 | call to method GetFirst : Object | ExternalFlow.cs:263:17:263:17 | access to local variable b : Object | provenance | |
| ExternalFlow.cs:263:30:263:30 | access to parameter a : MyInlineArray [element] : Object | ExternalFlow.cs:263:21:263:31 | call to method GetFirst : Object | provenance | MaD:28 |
| ExternalFlow.cs:212:60:212:61 | access to local variable o1 : Object | ExternalFlow.cs:212:18:212:62 | call to method GeneratedFlowWithGeneratedNeutral | provenance | MaD:25 |
| ExternalFlow.cs:238:17:238:17 | access to local variable h : HC | ExternalFlow.cs:239:21:239:21 | access to local variable h : HC | provenance | |
| ExternalFlow.cs:238:21:238:28 | object creation of type HC : HC | ExternalFlow.cs:238:17:238:17 | access to local variable h : HC | provenance | |
| ExternalFlow.cs:239:17:239:17 | access to local variable o : HC | ExternalFlow.cs:240:18:240:18 | access to local variable o | provenance | |
| ExternalFlow.cs:239:21:239:21 | access to local variable h : HC | ExternalFlow.cs:239:21:239:39 | call to method ExtensionMethod : HC | provenance | MaD:27 |
| ExternalFlow.cs:239:21:239:39 | call to method ExtensionMethod : HC | ExternalFlow.cs:239:17:239:17 | access to local variable o : HC | provenance | |
| ExternalFlow.cs:256:13:256:13 | [post] access to parameter a : MyInlineArray [element] : Object | ExternalFlow.cs:257:30:257:30 | access to parameter a : MyInlineArray [element] : Object | provenance | |
| ExternalFlow.cs:256:20:256:31 | object creation of type Object : Object | ExternalFlow.cs:256:13:256:13 | [post] access to parameter a : MyInlineArray [element] : Object | provenance | |
| ExternalFlow.cs:257:17:257:17 | access to local variable b : Object | ExternalFlow.cs:258:18:258:18 | access to local variable b | provenance | |
| ExternalFlow.cs:257:21:257:31 | call to method GetFirst : Object | ExternalFlow.cs:257:17:257:17 | access to local variable b : Object | provenance | |
| ExternalFlow.cs:257:30:257:30 | access to parameter a : MyInlineArray [element] : Object | ExternalFlow.cs:257:21:257:31 | call to method GetFirst : Object | provenance | MaD:28 |
| ExternalFlow.cs:278:17:278:17 | access to local variable j : Object | ExternalFlow.cs:279:22:279:22 | access to local variable j : Object | provenance | |
| ExternalFlow.cs:278:21:278:32 | object creation of type Object : Object | ExternalFlow.cs:278:17:278:17 | access to local variable j : Object | provenance | |
| ExternalFlow.cs:279:13:279:23 | [post] this access : J | ExternalFlow.cs:281:18:281:21 | this access : J | provenance | |
| ExternalFlow.cs:279:22:279:22 | access to local variable j : Object | ExternalFlow.cs:279:13:279:23 | [post] this access : J | provenance | MaD:30 |
| ExternalFlow.cs:281:18:281:21 | this access : J | ExternalFlow.cs:281:18:281:27 | access to property Prop1 | provenance | MaD:29 |
nodes
| ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | semmle.label | access to local variable arg1 : Object |
| ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
@@ -186,24 +191,30 @@ nodes
| ExternalFlow.cs:120:18:120:21 | access to array element | semmle.label | access to array element |
| ExternalFlow.cs:205:17:205:18 | access to local variable o2 : Object | semmle.label | access to local variable o2 : Object |
| ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
| ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs | semmle.label | call to method MixedFlowArgs |
| ExternalFlow.cs:206:38:206:39 | access to local variable o2 : Object | semmle.label | access to local variable o2 : Object |
| ExternalFlow.cs:206:18:206:48 | call to method MixedFlowArgs | semmle.label | call to method MixedFlowArgs |
| ExternalFlow.cs:206:46:206:47 | access to local variable o2 : Object | semmle.label | access to local variable o2 : Object |
| ExternalFlow.cs:211:17:211:18 | access to local variable o1 : Object | semmle.label | access to local variable o1 : Object |
| ExternalFlow.cs:211:22:211:33 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
| ExternalFlow.cs:212:18:212:54 | call to method GeneratedFlowWithGeneratedNeutral | semmle.label | call to method GeneratedFlowWithGeneratedNeutral |
| ExternalFlow.cs:212:52:212:53 | access to local variable o1 : Object | semmle.label | access to local variable o1 : Object |
| ExternalFlow.cs:244:17:244:17 | access to local variable h : HC | semmle.label | access to local variable h : HC |
| ExternalFlow.cs:244:21:244:28 | object creation of type HC : HC | semmle.label | object creation of type HC : HC |
| ExternalFlow.cs:245:17:245:17 | access to local variable o : HC | semmle.label | access to local variable o : HC |
| ExternalFlow.cs:245:21:245:21 | access to local variable h : HC | semmle.label | access to local variable h : HC |
| ExternalFlow.cs:245:21:245:39 | call to method ExtensionMethod : HC | semmle.label | call to method ExtensionMethod : HC |
| ExternalFlow.cs:246:18:246:18 | access to local variable o | semmle.label | access to local variable o |
| ExternalFlow.cs:262:13:262:13 | [post] access to parameter a : MyInlineArray [element] : Object | semmle.label | [post] access to parameter a : MyInlineArray [element] : Object |
| ExternalFlow.cs:262:20:262:31 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
| ExternalFlow.cs:263:17:263:17 | access to local variable b : Object | semmle.label | access to local variable b : Object |
| ExternalFlow.cs:263:21:263:31 | call to method GetFirst : Object | semmle.label | call to method GetFirst : Object |
| ExternalFlow.cs:263:30:263:30 | access to parameter a : MyInlineArray [element] : Object | semmle.label | access to parameter a : MyInlineArray [element] : Object |
| ExternalFlow.cs:264:18:264:18 | access to local variable b | semmle.label | access to local variable b |
| ExternalFlow.cs:212:18:212:62 | call to method GeneratedFlowWithGeneratedNeutral | semmle.label | call to method GeneratedFlowWithGeneratedNeutral |
| ExternalFlow.cs:212:60:212:61 | access to local variable o1 : Object | semmle.label | access to local variable o1 : Object |
| ExternalFlow.cs:238:17:238:17 | access to local variable h : HC | semmle.label | access to local variable h : HC |
| ExternalFlow.cs:238:21:238:28 | object creation of type HC : HC | semmle.label | object creation of type HC : HC |
| ExternalFlow.cs:239:17:239:17 | access to local variable o : HC | semmle.label | access to local variable o : HC |
| ExternalFlow.cs:239:21:239:21 | access to local variable h : HC | semmle.label | access to local variable h : HC |
| ExternalFlow.cs:239:21:239:39 | call to method ExtensionMethod : HC | semmle.label | call to method ExtensionMethod : HC |
| ExternalFlow.cs:240:18:240:18 | access to local variable o | semmle.label | access to local variable o |
| ExternalFlow.cs:256:13:256:13 | [post] access to parameter a : MyInlineArray [element] : Object | semmle.label | [post] access to parameter a : MyInlineArray [element] : Object |
| ExternalFlow.cs:256:20:256:31 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
| ExternalFlow.cs:257:17:257:17 | access to local variable b : Object | semmle.label | access to local variable b : Object |
| ExternalFlow.cs:257:21:257:31 | call to method GetFirst : Object | semmle.label | call to method GetFirst : Object |
| ExternalFlow.cs:257:30:257:30 | access to parameter a : MyInlineArray [element] : Object | semmle.label | access to parameter a : MyInlineArray [element] : Object |
| ExternalFlow.cs:258:18:258:18 | access to local variable b | semmle.label | access to local variable b |
| ExternalFlow.cs:278:17:278:17 | access to local variable j : Object | semmle.label | access to local variable j : Object |
| ExternalFlow.cs:278:21:278:32 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
| ExternalFlow.cs:279:13:279:23 | [post] this access : J | semmle.label | [post] this access : J |
| ExternalFlow.cs:279:22:279:22 | access to local variable j : Object | semmle.label | access to local variable j : Object |
| ExternalFlow.cs:281:18:281:21 | this access : J | semmle.label | this access : J |
| ExternalFlow.cs:281:18:281:27 | access to property Prop1 | semmle.label | access to property Prop1 |
subpaths
| ExternalFlow.cs:84:29:84:32 | access to local variable objs : null [element] : Object | ExternalFlow.cs:84:35:84:35 | o : Object | ExternalFlow.cs:84:40:84:40 | access to parameter o : Object | ExternalFlow.cs:84:25:84:41 | call to method Map<Object,Object> : T[] [element] : Object |
#select
@@ -227,7 +238,8 @@ subpaths
| ExternalFlow.cs:104:18:104:25 | access to field Field | ExternalFlow.cs:98:24:98:35 | object creation of type Object : Object | ExternalFlow.cs:104:18:104:25 | access to field Field | $@ | ExternalFlow.cs:98:24:98:35 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:112:18:112:25 | access to property MyProp | ExternalFlow.cs:111:24:111:35 | object creation of type Object : Object | ExternalFlow.cs:112:18:112:25 | access to property MyProp | $@ | ExternalFlow.cs:111:24:111:35 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:120:18:120:21 | access to array element | ExternalFlow.cs:117:36:117:47 | object creation of type Object : Object | ExternalFlow.cs:120:18:120:21 | access to array element | $@ | ExternalFlow.cs:117:36:117:47 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs | ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs | $@ | ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:212:18:212:54 | call to method GeneratedFlowWithGeneratedNeutral | ExternalFlow.cs:211:22:211:33 | object creation of type Object : Object | ExternalFlow.cs:212:18:212:54 | call to method GeneratedFlowWithGeneratedNeutral | $@ | ExternalFlow.cs:211:22:211:33 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:246:18:246:18 | access to local variable o | ExternalFlow.cs:244:21:244:28 | object creation of type HC : HC | ExternalFlow.cs:246:18:246:18 | access to local variable o | $@ | ExternalFlow.cs:244:21:244:28 | object creation of type HC : HC | object creation of type HC : HC |
| ExternalFlow.cs:264:18:264:18 | access to local variable b | ExternalFlow.cs:262:20:262:31 | object creation of type Object : Object | ExternalFlow.cs:264:18:264:18 | access to local variable b | $@ | ExternalFlow.cs:262:20:262:31 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:206:18:206:48 | call to method MixedFlowArgs | ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | ExternalFlow.cs:206:18:206:48 | call to method MixedFlowArgs | $@ | ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:212:18:212:62 | call to method GeneratedFlowWithGeneratedNeutral | ExternalFlow.cs:211:22:211:33 | object creation of type Object : Object | ExternalFlow.cs:212:18:212:62 | call to method GeneratedFlowWithGeneratedNeutral | $@ | ExternalFlow.cs:211:22:211:33 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:240:18:240:18 | access to local variable o | ExternalFlow.cs:238:21:238:28 | object creation of type HC : HC | ExternalFlow.cs:240:18:240:18 | access to local variable o | $@ | ExternalFlow.cs:238:21:238:28 | object creation of type HC : HC | object creation of type HC : HC |
| ExternalFlow.cs:258:18:258:18 | access to local variable b | ExternalFlow.cs:256:20:256:31 | object creation of type Object : Object | ExternalFlow.cs:258:18:258:18 | access to local variable b | $@ | ExternalFlow.cs:256:20:256:31 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:281:18:281:27 | access to property Prop1 | ExternalFlow.cs:278:21:278:32 | object creation of type Object : Object | ExternalFlow.cs:281:18:281:27 | access to property Prop1 | $@ | ExternalFlow.cs:278:21:278:32 | object creation of type Object : Object | object creation of type Object : Object |

View File

@@ -27,16 +27,20 @@ extensions:
- ["My.Qltest", "G", false, "GeneratedFlow", "(System.Object)", "", "Argument[0]", "ReturnValue", "value", "df-generated"]
- ["My.Qltest", "G", false, "GeneratedFlowArgs", "(System.Object,System.Object)", "", "Argument[0]", "ReturnValue", "value", "df-generated"]
- ["My.Qltest", "G", false, "GeneratedFlowArgs", "(System.Object,System.Object)", "", "Argument[1]", "ReturnValue", "value", "df-generated"]
- ["My.Qltest", "G", false, "MixedFlowArgs", "(System.Object,System.Object)", "", "Argument[0]", "ReturnValue", "value", "df-generated"]
- ["My.Qltest", "G", false, "MixedFlowArgs", "(System.Object,System.Object)", "", "Argument[1]", "ReturnValue", "value", "manual"]
- ["My.Qltest", "G", false, "GeneratedFlowWithGeneratedNeutral", "(System.Object)", "", "Argument[0]", "ReturnValue", "value", "df-generated"]
- ["My.Qltest", "G", false, "GeneratedFlowWithManualNeutral", "(System.Object)", "", "Argument[0]", "ReturnValue", "value", "df-generated"]
- ["My.Qltest", "Library", false, "MixedFlowArgs", "(System.Object,System.Object)", "", "Argument[0]", "ReturnValue", "value", "df-generated"]
- ["My.Qltest", "Library", false, "MixedFlowArgs", "(System.Object,System.Object)", "", "Argument[1]", "ReturnValue", "value", "manual"]
- ["My.Qltest", "Library", false, "GeneratedFlowWithGeneratedNeutral", "(System.Object)", "", "Argument[0]", "ReturnValue", "value", "df-generated"]
- ["My.Qltest", "Library", false, "GeneratedFlowWithManualNeutral", "(System.Object)", "", "Argument[0]", "ReturnValue", "value", "df-generated"]
- ["My.Qltest", "HE", false, "ExtensionMethod", "(My.Qltest.HI)", "", "Argument[0]", "ReturnValue", "value", "manual"]
- ["My.Qltest", "I", false, "GetFirst", "(My.Qltest.MyInlineArray)", "", "Argument[0].Element", "ReturnValue", "value", "manual"]
- ["My.Qltest", "J", false, "get_Prop1", "()", "", "Argument[this]", "ReturnValue", "value", "manual"]
- ["My.Qltest", "J", false, "SetProp1", "(System.Object)", "", "Argument[0]", "Argument[this]", "value", "manual"]
- ["My.Qltest", "J", false, "get_Prop2", "()", "", "Argument[this]", "ReturnValue", "value", "df-generated"]
- ["My.Qltest", "J", false, "SetProp2", "(System.Object)", "", "Argument[0]", "Argument[this]", "value", "manual"]
- addsTo:
pack: codeql/csharp-all
extensible: neutralModel
# "namespace", "type", "name", "signature", "kind", "provenance"
data:
- ["My.Qltest", "G", "GeneratedFlowWithGeneratedNeutral", "(System.Object)", "summary", "df-generated"]
- ["My.Qltest", "G", "GeneratedFlowWithManualNeutral", "(System.Object)", "summary", "manual"]
- ["My.Qltest", "Library", "GeneratedFlowWithGeneratedNeutral", "(System.Object)", "summary", "df-generated"]
- ["My.Qltest", "Library", "GeneratedFlowWithManualNeutral", "(System.Object)", "summary", "manual"]

View File

@@ -20,21 +20,6 @@ module TaintConfig implements DataFlow::ConfigSig {
module Taint = TaintTracking::Global<TaintConfig>;
/**
* Emulate that methods with summaries do not have a body.
* This is relevant for dataflow analysis using summaries with a generated like
* provenance as generated summaries are only applied, if a
* callable does not have a body.
*/
private class MethodsWithGeneratedModels extends Method {
MethodsWithGeneratedModels() {
this.hasFullyQualifiedName("My.Qltest", "G",
["MixedFlowArgs", "GeneratedFlowWithGeneratedNeutral", "GeneratedFlowWithManualNeutral"])
}
override predicate hasBody() { none() }
}
from Taint::PathNode source, Taint::PathNode sink
where Taint::flowPath(source, sink)
select sink, source, sink, "$@", source, source.toString()

View File

@@ -44,10 +44,10 @@ namespace My.Qltest
new Sub().StepOverride("string");
object arg4 = new object();
this.StepArgQualGenerated(arg4);
Library.StepArgReturnGenerated(arg4);
object arg5 = new object();
this.StepArgQualGeneratedIgnored(arg5);
Library.StepArgReturnGeneratedIgnored(arg5);
}
object StepArgRes(object x) { return null; }
@@ -56,10 +56,6 @@ namespace My.Qltest
void StepArgQual(object x) { }
void StepArgQualGenerated(object x) { }
void StepArgQualGeneratedIgnored(object x) { }
object StepQualRes() { return null; }
void StepQualArg(object @out) { }

View File

@@ -11,12 +11,12 @@ summaryThroughStep
| Steps.cs:41:29:41:29 | 0 | Steps.cs:41:13:41:30 | call to method StepGeneric | true |
| Steps.cs:42:30:42:34 | false | Steps.cs:42:13:42:35 | call to method StepGeneric2<Boolean> | true |
| Steps.cs:44:36:44:43 | "string" | Steps.cs:44:13:44:44 | call to method StepOverride | true |
| Steps.cs:47:39:47:42 | access to local variable arg4 | Steps.cs:47:13:47:16 | [post] this access | false |
| Steps.cs:47:44:47:47 | access to local variable arg4 | Steps.cs:47:13:47:48 | call to method StepArgReturnGenerated | false |
summaryGetterStep
| Steps.cs:28:13:28:16 | this access | Steps.cs:28:13:28:34 | call to method StepFieldGetter | Steps.cs:67:13:67:17 | field Field |
| Steps.cs:32:13:32:16 | this access | Steps.cs:32:13:32:37 | call to method StepPropertyGetter | Steps.cs:73:13:73:20 | property Property |
| Steps.cs:28:13:28:16 | this access | Steps.cs:28:13:28:34 | call to method StepFieldGetter | Steps.cs:63:13:63:17 | field Field |
| Steps.cs:32:13:32:16 | this access | Steps.cs:32:13:32:37 | call to method StepPropertyGetter | Steps.cs:69:13:69:20 | property Property |
| Steps.cs:36:13:36:16 | this access | Steps.cs:36:13:36:36 | call to method StepElementGetter | file://:0:0:0:0 | element |
summarySetterStep
| Steps.cs:30:34:30:34 | 0 | Steps.cs:30:13:30:16 | [post] this access | Steps.cs:67:13:67:17 | field Field |
| Steps.cs:34:37:34:37 | 0 | Steps.cs:34:13:34:16 | [post] this access | Steps.cs:73:13:73:20 | property Property |
| Steps.cs:30:34:30:34 | 0 | Steps.cs:30:13:30:16 | [post] this access | Steps.cs:63:13:63:17 | field Field |
| Steps.cs:34:37:34:37 | 0 | Steps.cs:34:13:34:16 | [post] this access | Steps.cs:69:13:69:20 | property Property |
| Steps.cs:38:36:38:36 | 0 | Steps.cs:38:13:38:16 | [post] this access | file://:0:0:0:0 | element |

View File

@@ -18,13 +18,13 @@ extensions:
- ["My.Qltest", "C+Generic<T,U>", false, "StepGeneric", "(T)", "", "Argument[0]", "ReturnValue", "value", "manual"]
- ["My.Qltest", "C+Generic<T,U>", false, "StepGeneric2<S>", "(S)", "", "Argument[0]", "ReturnValue", "value", "manual"]
- ["My.Qltest", "C+Base<T>", true, "StepOverride", "(T)", "", "Argument[0]", "ReturnValue", "value", "manual"]
- ["My.Qltest", "C", false, "StepArgQualGenerated", "(System.Object)", "", "Argument[0]", "Argument[this]", "taint", "df-generated"]
- ["My.Qltest", "C", false, "StepArgQualGeneratedIgnored", "(System.Object)", "", "Argument[0]", "Argument[this]", "taint", "df-generated"]
- ["My.Qltest", "Library", false, "StepArgReturnGenerated", "(System.Object)", "", "Argument[0]", "ReturnValue", "taint", "df-generated"]
- ["My.Qltest", "Library", false, "StepArgReturnGeneratedIgnored", "(System.Object)", "", "Argument[0]", "ReturnValue", "taint", "df-generated"]
- addsTo:
pack: codeql/csharp-all
extensible: neutralModel
# "namespace", "type", "name", "signature", "kind", "provenance"
data:
- ["My.Qltest", "C", "StepArgQualGenerated", "(System.Object)", "summary", "df-generated"]
- ["My.Qltest", "C", "StepArgQualGeneratedIgnored", "(System.Object)", "summary", "manual"]
- ["My.Qltest", "Library", "StepArgReturnGenerated", "(System.Object)", "summary", "df-generated"]
- ["My.Qltest", "Library", "StepArgReturnGeneratedIgnored", "(System.Object)", "summary", "manual"]

View File

@@ -6,22 +6,6 @@ import semmle.code.csharp.dataflow.FlowSummary
import semmle.code.csharp.dataflow.internal.DataFlowDispatch as DataFlowDispatch
import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
/**
* Emulate that methods with summaries do not have a body.
* This is relevant for dataflow analysis using summaries with a generated like
* provenance as generated summaries are only applied, if a
* callable does not have a body.
*/
private class StepArgQualGenerated extends Method {
StepArgQualGenerated() {
exists(string name |
this.hasFullyQualifiedName("My.Qltest", "C", name) and name.matches("StepArgQualGenerated%")
)
}
override predicate hasBody() { none() }
}
query predicate summaryThroughStep(
DataFlow::Node node1, DataFlow::Node node2, boolean preservesValue
) {

View File

@@ -29,9 +29,15 @@ namespace InsecureSQLConnection
conBuilder.Encrypt = true;
SqlConnection conn = new SqlConnection();
conn.ConnectionString = conBuilder.ToString();
}
public void StringInInitializer()
{
string connectString = "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd;Encrypt=false";
SqlConnectionStringBuilder conBuilder = new SqlConnectionStringBuilder(connectString) { Encrypt = true};
}
public void TriggerThis()
{
// BAD, Encrypt not specified

View File

@@ -1,18 +1,18 @@
edges
| InsecureSQLConnection.cs:43:20:43:32 | access to local variable connectString : String | InsecureSQLConnection.cs:46:81:46:93 | access to local variable connectString | provenance | |
| InsecureSQLConnection.cs:44:17:44:64 | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd" : String | InsecureSQLConnection.cs:43:20:43:32 | access to local variable connectString : String | provenance | |
| InsecureSQLConnection.cs:52:20:52:32 | access to local variable connectString : String | InsecureSQLConnection.cs:55:81:55:93 | access to local variable connectString | provenance | |
| InsecureSQLConnection.cs:53:17:53:78 | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd;Encrypt=false" : String | InsecureSQLConnection.cs:52:20:52:32 | access to local variable connectString : String | provenance | |
| InsecureSQLConnection.cs:49:20:49:32 | access to local variable connectString : String | InsecureSQLConnection.cs:52:81:52:93 | access to local variable connectString | provenance | |
| InsecureSQLConnection.cs:50:17:50:64 | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd" : String | InsecureSQLConnection.cs:49:20:49:32 | access to local variable connectString : String | provenance | |
| InsecureSQLConnection.cs:58:20:58:32 | access to local variable connectString : String | InsecureSQLConnection.cs:61:81:61:93 | access to local variable connectString | provenance | |
| InsecureSQLConnection.cs:59:17:59:78 | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd;Encrypt=false" : String | InsecureSQLConnection.cs:58:20:58:32 | access to local variable connectString : String | provenance | |
nodes
| InsecureSQLConnection.cs:38:52:38:128 | "Server=myServerName\\myInstanceName;Database=myDataBase;User Id=myUsername;" | semmle.label | "Server=myServerName\\myInstanceName;Database=myDataBase;User Id=myUsername;" |
| InsecureSQLConnection.cs:43:20:43:32 | access to local variable connectString : String | semmle.label | access to local variable connectString : String |
| InsecureSQLConnection.cs:44:17:44:64 | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd" : String | semmle.label | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd" : String |
| InsecureSQLConnection.cs:46:81:46:93 | access to local variable connectString | semmle.label | access to local variable connectString |
| InsecureSQLConnection.cs:52:20:52:32 | access to local variable connectString : String | semmle.label | access to local variable connectString : String |
| InsecureSQLConnection.cs:53:17:53:78 | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd;Encrypt=false" : String | semmle.label | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd;Encrypt=false" : String |
| InsecureSQLConnection.cs:55:81:55:93 | access to local variable connectString | semmle.label | access to local variable connectString |
| InsecureSQLConnection.cs:44:52:44:128 | "Server=myServerName\\myInstanceName;Database=myDataBase;User Id=myUsername;" | semmle.label | "Server=myServerName\\myInstanceName;Database=myDataBase;User Id=myUsername;" |
| InsecureSQLConnection.cs:49:20:49:32 | access to local variable connectString : String | semmle.label | access to local variable connectString : String |
| InsecureSQLConnection.cs:50:17:50:64 | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd" : String | semmle.label | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd" : String |
| InsecureSQLConnection.cs:52:81:52:93 | access to local variable connectString | semmle.label | access to local variable connectString |
| InsecureSQLConnection.cs:58:20:58:32 | access to local variable connectString : String | semmle.label | access to local variable connectString : String |
| InsecureSQLConnection.cs:59:17:59:78 | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd;Encrypt=false" : String | semmle.label | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd;Encrypt=false" : String |
| InsecureSQLConnection.cs:61:81:61:93 | access to local variable connectString | semmle.label | access to local variable connectString |
subpaths
#select
| InsecureSQLConnection.cs:38:52:38:128 | "Server=myServerName\\myInstanceName;Database=myDataBase;User Id=myUsername;" | InsecureSQLConnection.cs:38:52:38:128 | "Server=myServerName\\myInstanceName;Database=myDataBase;User Id=myUsername;" | InsecureSQLConnection.cs:38:52:38:128 | "Server=myServerName\\myInstanceName;Database=myDataBase;User Id=myUsername;" | $@ flows to this SQL connection and does not specify `Encrypt=True`. | InsecureSQLConnection.cs:38:52:38:128 | "Server=myServerName\\myInstanceName;Database=myDataBase;User Id=myUsername;" | Connection string |
| InsecureSQLConnection.cs:46:81:46:93 | access to local variable connectString | InsecureSQLConnection.cs:44:17:44:64 | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd" : String | InsecureSQLConnection.cs:46:81:46:93 | access to local variable connectString | $@ flows to this SQL connection and does not specify `Encrypt=True`. | InsecureSQLConnection.cs:44:17:44:64 | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd" | Connection string |
| InsecureSQLConnection.cs:55:81:55:93 | access to local variable connectString | InsecureSQLConnection.cs:53:17:53:78 | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd;Encrypt=false" : String | InsecureSQLConnection.cs:55:81:55:93 | access to local variable connectString | $@ flows to this SQL connection and does not specify `Encrypt=True`. | InsecureSQLConnection.cs:53:17:53:78 | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd;Encrypt=false" | Connection string |
| InsecureSQLConnection.cs:44:52:44:128 | "Server=myServerName\\myInstanceName;Database=myDataBase;User Id=myUsername;" | InsecureSQLConnection.cs:44:52:44:128 | "Server=myServerName\\myInstanceName;Database=myDataBase;User Id=myUsername;" | InsecureSQLConnection.cs:44:52:44:128 | "Server=myServerName\\myInstanceName;Database=myDataBase;User Id=myUsername;" | $@ flows to this SQL connection and does not specify `Encrypt=True`. | InsecureSQLConnection.cs:44:52:44:128 | "Server=myServerName\\myInstanceName;Database=myDataBase;User Id=myUsername;" | Connection string |
| InsecureSQLConnection.cs:52:81:52:93 | access to local variable connectString | InsecureSQLConnection.cs:50:17:50:64 | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd" : String | InsecureSQLConnection.cs:52:81:52:93 | access to local variable connectString | $@ flows to this SQL connection and does not specify `Encrypt=True`. | InsecureSQLConnection.cs:50:17:50:64 | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd" | Connection string |
| InsecureSQLConnection.cs:61:81:61:93 | access to local variable connectString | InsecureSQLConnection.cs:59:17:59:78 | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd;Encrypt=false" : String | InsecureSQLConnection.cs:61:81:61:93 | access to local variable connectString | $@ flows to this SQL connection and does not specify `Encrypt=True`. | InsecureSQLConnection.cs:59:17:59:78 | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd;Encrypt=false" | Connection string |

View File

@@ -575,3 +575,4 @@ public class Inheritance
public override string Prop { get { return tainted; } }
}
}

View File

@@ -21,6 +21,8 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat
using-range-analsis-in-cpp
hash-consing-and-value-numbering
advanced-dataflow-scenarios-cpp
customizing-library-models-for-cpp
- :doc:`Basic query for C and C++ code <basic-query-for-cpp-code>`: Learn to write and run a simple CodeQL query.
@@ -46,3 +48,5 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat
- :doc:`Hash consing and value numbering <hash-consing-and-value-numbering>`: You can use specialized CodeQL libraries to recognize expressions that are syntactically identical or compute the same value at runtime in C and C++ codebases.
- :doc:`Advanced C/C++ dataflow scenarios <advanced-dataflow-scenarios-cpp>`: You can track precise data flow in C and C++ codebases by distinguishing between a pointer and its indirection(s).
- :doc:`Customizing library models for C and C++ <customizing-library-models-for-cpp>`: You can model frameworks and libraries that your codebase depends on using data extensions and publish them as CodeQL model packs.

View File

@@ -0,0 +1,184 @@
.. _customizing-library-models-for-cpp:
Customizing library models for C and C++
========================================
You can model the methods and callables that control data flow in any framework or library. This is especially useful for custom frameworks or niche libraries, that are not supported by the standard CodeQL libraries.
.. include:: ../reusables/beta-note-customizing-library-models.rst
About this article
------------------
This article contains reference material about how to define custom models for sources, sinks, and flow summaries for C and C++ dependencies in data extension files.
About data extensions
---------------------
You can customize analysis by defining models (summaries, sinks, and sources) of your code's C and C++ dependencies in data extension files. Each model defines the behavior of one or more elements of your library or framework, such as callables. When you run dataflow analysis, these models expand the potential sources and sinks tracked by dataflow analysis and improve the precision of results.
Many of the security queries search for paths from a source of untrusted input to a sink that represents a vulnerability. This is known as taint tracking. Each source is a starting point for dataflow analysis to track tainted data and each sink is an end point.
Taint tracking queries also need to know how data can flow through elements that are not included in the source code. These are modeled as summaries. A summary model enables queries to synthesize the flow behavior through elements in dependency code that is not stored in your repository.
Syntax used to define an element in an extension file
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Each model of an element is defined using a data extension where each tuple constitutes a model.
A data extension file to extend the standard CPP queries included with CodeQL is a YAML file with the form:
.. code-block:: yaml
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: <name of extensible predicate>
data:
- <tuple1>
- <tuple2>
- ...
Each YAML file may contain one or more top-level extensions.
- ``addsTo`` defines the CodeQL pack name and extensible predicate that the extension is injected into.
- ``data`` defines one or more rows of tuples that are injected as values into the extensible predicate. The number of columns and their types must match the definition of the extensible predicate.
Data extensions use union semantics, which means that the tuples of all extensions for a single extensible predicate are combined, duplicates are removed, and all of the remaining tuples are queryable by referencing the extensible predicate.
Publish data extension files in a CodeQL model pack to share
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can group one or more data extension files into a CodeQL model pack and publish it to the GitHub Container Registry. This makes it easy for anyone to download the model pack and use it to extend their analysis. For more information, see `Creating a CodeQL model pack <https://docs.github.com/en/code-security/codeql-cli/using-the-advanced-functionality-of-the-codeql-cli/creating-and-working-with-codeql-packs#creating-a-codeql-model-pack>`__ and `Publishing and using CodeQL packs <https://docs.github.com/en/code-security/codeql-cli/using-the-advanced-functionality-of-the-codeql-cli/publishing-and-using-codeql-packs/>`__ in the CodeQL CLI documentation.
Extensible predicates used to create custom models in C and C++
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The CodeQL library for CPP analysis exposes the following extensible predicates:
- ``sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance)``. This is used to model sources of potentially tainted data. The ``kind`` of the sources defined using this predicate determine which threat model they are associated with. Different threat models can be used to customize the sources used in an analysis. For more information, see ":ref:`Threat models <threat-models-cpp>`."
- ``sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance)``. This is used to model sinks where tainted data may be used in a way that makes the code vulnerable.
- ``summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, provenance)``. This is used to model flow through elements.
The extensible predicates are populated using the models defined in data extension files.
Example of custom model definitions
------------------------------------
The examples in this section are taken from the standard CodeQL CPP query pack published by GitHub. They demonstrate how to add tuples to extend extensible predicates that are used by the standard queries.
Example: Taint source from the ``boost::asio`` namespace
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This example shows how the CPP query pack models the return value from the ``read_until`` function as a ``remote`` source.
.. code-block:: cpp
boost::asio::read_until(socket, recv_buffer, '\0', error);
We need to add a tuple to the ``sourceModel``\(namespace, type, subtypes, name, signature, ext, output, kind, provenance) extensible predicate by updating a data extension file.
.. code-block:: yaml
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: sourceModel
data:
- ["boost::asio", "", False, "read_until", "", "", "Argument[*1]", "remote", "manual"]
Since we are adding a new source, we need to add a tuple to the ``sourceModel`` extensible predicate.
The first five values identify the callable (in this case a free function) to be modeled as a source.
- The first value ``"boost::asio"`` is the namespace name.
- The second value ``""`` is the name of the type (class) that contains the method. Because we're modelling a free function, the type is left blank.
- The third value ``False`` is a flag that indicates whether or not the sink also applies to all overrides of the method. For a free function, this should be ``False``.
- The fourth value ``"read_until"`` is the function name.
- The fifth value is the function input type signature, which can be used to narrow down between functions that have the same name. In this case, we want the model to include all functions in ``boost::asio`` called ``read_until``.
The sixth value should be left empty and is out of scope for this documentation.
The remaining values are used to define the output specification, the ``kind``, and the ``provenance`` (origin) of the source.
- The seventh value ``"Argument[*1]"`` is the output specification, which means in this case that the sink is the first indirection (or pointed-to value, ``*``) of the second argument (``Argument[1]``) passed to the function.
- The eighth value ``"remote"`` is the kind of the source. The source kind is used to define the threat model where the source is in scope. ``remote`` applies to many of the security related queries as it means a remote source of untrusted data. For more information, see ":ref:`Threat models <threat-models-cpp>`."
- The ninth value ``"manual"`` is the provenance of the source, which is used to identify the origin of the source model.
Example: Taint sink in the ``boost::asio`` namespace
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This example shows how the CPP query pack models the second argument of the ``boost::asio::write`` function as a remote flow sink. A remote flow sink is where data is transmitted to other machines across a network, which is used for example by the "Cleartext transmission of sensitive information" (`cpp/cleartext-transmission`) query.
.. code-block:: cpp
boost::asio::write(socket, send_buffer, error);
We need to add a tuple to the ``sinkModel``\(namespace, type, subtypes, name, signature, ext, input, kind, provenance) extensible predicate by updating a data extension file.
.. code-block:: yaml
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: sinkModel
data:
- ["boost::asio", "", False, "write", "", "", "Argument[*1]", "remote-sink", "manual"]
Since we want to add a new sink, we need to add a tuple to the ``sinkModel`` extensible predicate.
The first five values identify the callable (in this case a free function) to be modeled as a sink.
- The first value ``"boost::asio"`` is the namespace name.
- The second value ``""`` is the name of the type (class) that contains the method. Because we're modelling a free function, the type is left blank.
- The third value ``False`` is a flag that indicates whether or not the sink also applies to all overrides of the method. For a free function, this should be ``False``.
- The fourth value ``"write"`` is the function name.
- The fifth value is the function input type signature, which can be used to narrow down between functions that have the same name. In this case, we want the model to include all functions in ``boost::asio`` called ``write``.
The sixth value should be left empty and is out of scope for this documentation.
The remaining values are used to define the output specification, the ``kind``, and the ``provenance`` (origin) of the sink.
- The seventh value ``"Argument[*1]"`` is the output specification, which means in this case that the sink is the first indirection (or pointed-to value, ``*``) of the second argument (``Argument[1]``) passed to the function.
- The eighth value ``"remote-sink"`` is the kind of the sink. The sink kind is used to define the queries where the sink is in scope.
- The ninth value ``"manual"`` is the provenance of the sink, which is used to identify the origin of the sink model.
Example: Add flow through the ``boost::asio::buffer`` method
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This example shows how the CPP query pack models flow through a function for a simple case.
.. code-block:: cpp
boost::asio::write(socket, boost::asio::buffer(send_str), error);
We need to add tuples to the ``summaryModel``\(namespace, type, subtypes, name, signature, ext, input, output, kind, provenance) extensible predicate by updating a data extension file:
.. code-block:: yaml
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data:
- ["boost::asio", "", False, "buffer", "", "", "Argument[*0]", "ReturnValue", "taint", "manual"]
Since we are adding flow through a function, we need to add tuples to the ``summaryModel`` extensible predicate.
The first five values identify the callable (in this case free function) to be modeled as a summary.
- The first value ``"boost::asio"`` is the namespace name.
- The second value ``""`` is the name of the type (class) that contains the method. Because we're modelling a free function, the type is left blank.
- The third value ``False`` is a flag that indicates whether or not the sink also applies to all overrides of the method. For a free function, this should be ``False``.
- The fourth value ``"buffer"`` is the function name.
- The fifth value is the function input type signature, which can be used to narrow down between functions that have the same name. In this case, we want the model to include all functions in ``boost::asio`` called ``buffer``.
The sixth value should be left empty and is out of scope for this documentation.
The remaining values are used to define the input and output specifications, the ``kind``, and the ``provenance`` (origin) of the summary.
- The seventh value is the input specification (where data flows from). ``Argument[*0]`` specifies the first indirection (or pointed-to value, ``*``) of the first argument (``Argument[0]``) passed to the function.
- The eighth value ``"ReturnValue"`` is the output specification (where data flows to), in this case the return value.
- The ninth value ``"taint"`` is the kind of the flow. ``taint`` means that taint is propagated through the call.
- The tenth value ``"manual"`` is the provenance of the summary, which is used to identify the origin of the summary model.
.. _threat-models-cpp:
Threat models
-------------
.. include:: ../reusables/threat-model-description.rst

View File

@@ -0,0 +1,127 @@
.. _codeql-cli-2.17.4:
==========================
CodeQL 2.17.4 (2024-06-03)
==========================
.. contents:: Contents
:depth: 2
:local:
:backlinks: none
This is an overview of changes in the CodeQL CLI and relevant CodeQL query and library packs. For additional updates on changes to the CodeQL code scanning experience, check out the `code scanning section on the GitHub blog <https://github.blog/tag/code-scanning/>`__, `relevant GitHub Changelog updates <https://github.blog/changelog/label/code-scanning/>`__, `changes in the CodeQL extension for Visual Studio Code <https://marketplace.visualstudio.com/items/GitHub.vscode-codeql/changelog>`__, and the `CodeQL Action changelog <https://github.com/github/codeql-action/blob/main/CHANGELOG.md>`__.
Security Coverage
-----------------
CodeQL 2.17.4 runs a total of 414 security queries when configured with the Default suite (covering 161 CWE). The Extended suite enables an additional 131 queries (covering 35 more CWE).
CodeQL CLI
----------
There are no user-facing CLI changes in this release.
Query Packs
-----------
Breaking Changes
~~~~~~~~~~~~~~~~
Java
""""
* Removed :code:`local` query variants. The results pertaining to local sources can be found using the non-local counterpart query. As an example, the results previously found by :code:`java/unvalidated-url-redirection-local` can be found by :code:`java/unvalidated-url-redirection`, if the :code:`local` threat model is enabled. The removed queries are :code:`java/path-injection-local`, :code:`java/command-line-injection-local`, :code:`java/xss-local`, :code:`java/sql-injection-local`, :code:`java/http-response-splitting-local`, :code:`java/improper-validation-of-array-construction-local`, :code:`java/improper-validation-of-array-index-local`, :code:`java/tainted-format-string-local`, :code:`java/tainted-arithmetic-local`, :code:`java/unvalidated-url-redirection-local`, :code:`java/xxe-local` and :code:`java/tainted-numeric-cast-local`.
Minor Analysis Improvements
~~~~~~~~~~~~~~~~~~~~~~~~~~~
C/C++
"""""
* The "Use of unique pointer after lifetime ends" query (:code:`cpp/use-of-unique-pointer-after-lifetime-ends`) no longer reports an alert when the pointer is converted to a boolean
* The "Variable not initialized before use" query (:code:`cpp/not-initialised`) no longer reports an alert on static variables.
Golang
""""""
* The query :code:`go/incorrect-integer-conversion` has now been restricted to only use flow through value-preserving steps. This reduces false positives, especially around type switches.
Java
""""
* The alert message for the query "Trust boundary violation" (:code:`java/trust-boundary-violation`) has been updated to include a link to the remote source.
* The sanitizer of the query :code:`java/zipslip` has been improved to include nodes that are safe due to having certain safe types. This reduces false positives.
Python
""""""
* Added models of :code:`gradio` PyPI package.
Language Libraries
------------------
Bug Fixes
~~~~~~~~~
JavaScript/TypeScript
"""""""""""""""""""""
* Fixed a bug where very large TypeScript files would cause database creation to crash. Large files over 10MB were already excluded from analysis, but the file size check was not applied to TypeScript files.
Major Analysis Improvements
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Java
""""
* Added support for data flow through side-effects on static fields. For example, when a static field containing an array is updated.
Minor Analysis Improvements
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Golang
""""""
* A bug has been fixed which meant that the query :code:`go/incorrect-integer-conversion` did not consider type assertions and type switches which use a defined type whose underlying type is an integer type. This may lead to fewer false positive alerts.
* A bug has been fixed which meant flow was not followed through some ranged for loops. This may lead to more alerts being found.
* Added value flow models for the built-in functions :code:`append`, :code:`copy`, :code:`max` and :code:`min` using Models-as-Data. Removed the old-style models for :code:`max` and :code:`min`.
Java
""""
* JDK version detection based on Gradle projects has been improved. Java extraction using build-modes :code:`autobuild` or :code:`none` is more likely to pick an appropriate JDK version, particularly when the Android Gradle Plugin or Spring Boot Plugin are in use.
JavaScript/TypeScript
"""""""""""""""""""""
* Additional heuristics for a new sensitive data classification for private information (e.g. credit card numbers) have been added to the shared :code:`SensitiveDataHeuristics.qll` library. This may result in additional results for queries that use sensitive data such as :code:`js/clear-text-storage-sensitive-data` and :code:`js/clear-text-logging`.
Python
""""""
* The :code:`request` parameter of Flask :code:`SessionInterface.open_session` method is now modeled as a remote flow source.
* Additional heuristics for a new sensitive data classification for private information (e.g. credit card numbers) have been added to the shared :code:`SensitiveDataHeuristics.qll` library. This may result in additional results for queries that use sensitive data such as :code:`py/clear-text-storage-sensitive-data` and :code:`py/clear-text-logging-sensitive-data`.
Ruby
""""
* Additional heuristics for a new sensitive data classification for private information (e.g. credit card numbers) have been added to the shared :code:`SensitiveDataHeuristics.qll` library. This may result in additional results for queries that use sensitive data such as :code:`rb/sensitive-get-query`.
New Features
~~~~~~~~~~~~
Python
""""""
* A Python MaD (Models as Data) row may now contain a dotted path in the :code:`type` column. Like in Ruby, a path to a class will refer to instances of that class. This means that the summary :code:`["foo", "Member[MyClass].Instance.Member[instance_method]", "Argument[0]", "ReturnValue", "value"]` can now be written :code:`["foo.MS_Class", "Member[instance_method]", "Argument[0]", "ReturnValue", "value"]`. To refer to an actual class, one may add a :code:`!` at the end of the path.
Shared Libraries
----------------
Minor Analysis Improvements
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Dataflow Analysis
"""""""""""""""""
* The data flow library now adds intermediate nodes when data flows out of a function via a parameter, in order to make path explanations easier to follow. The intermediate nodes have the same location as the underlying parameter, but must be accessed via :code:`PathNode.asParameterReturnNode` instead of :code:`PathNode.asNode`.

View File

@@ -11,6 +11,7 @@ A list of queries for each suite and language `is available here <https://docs.g
.. toctree::
:maxdepth: 1
codeql-cli-2.17.4
codeql-cli-2.17.3
codeql-cli-2.17.2
codeql-cli-2.17.1

View File

@@ -152,16 +152,9 @@ func (l *Labeler) ScopedObjectID(object types.Object, getTypeLabel func() Label)
panic(fmt.Sprintf("Object has no scope: %v :: %v.\n", object,
l.tw.Package.Fset.Position(object.Pos())))
} else {
// associate method receiver objects to special keys, because those can be
// referenced from other files via their method
meth := findMethodWithGivenReceiver(object.Type(), object)
if meth == nil {
if pointerType, ok := object.Type().(*types.Pointer); ok {
meth = findMethodWithGivenReceiver(pointerType.Elem(), object)
}
}
if meth != nil {
if meth := findMethodWithGivenReceiver(object); meth != nil {
// associate method receiver objects to special keys, because those can be
// referenced from other files via their method
methlbl, _ := l.MethodID(meth, getTypeLabel())
label, _ = l.ReceiverObjectID(object, methlbl)
} else {
@@ -174,7 +167,20 @@ func (l *Labeler) ScopedObjectID(object types.Object, getTypeLabel func() Label)
return label, exists
}
func findMethodWithGivenReceiver(tp types.Type, object types.Object) *types.Func {
// findMethodWithGivenReceiver finds a method with `object` as its receiver, if one exists
func findMethodWithGivenReceiver(object types.Object) *types.Func {
meth := findMethodOnTypeWithGivenReceiver(object.Type(), object)
if meth != nil {
return meth
}
if pointerType, ok := object.Type().(*types.Pointer); ok {
meth = findMethodOnTypeWithGivenReceiver(pointerType.Elem(), object)
}
return meth
}
// findMethodWithGivenReceiver finds a method on type `tp` with `object` as its receiver, if one exists
func findMethodOnTypeWithGivenReceiver(tp types.Type, object types.Object) *types.Func {
if namedType, ok := tp.(*types.Named); ok {
for i := 0; i < namedType.NumMethods(); i++ {
meth := namedType.Method(i)

View File

@@ -1,3 +1,6 @@
#select
| project/build/generated/source/buildConfig/release/com/github/androidsample/BuildConfig.java:0:0:0:0 | BuildConfig |
| project/src/main/java/com/github/androidsample/Main.java:0:0:0:0 | Main |
xmlFiles
| project/build/intermediates/incremental/lintVitalAnalyzeRelease/module.xml:0:0:0:0 | project/build/intermediates/incremental/lintVitalAnalyzeRelease/module.xml |
| project/build/intermediates/incremental/lintVitalAnalyzeRelease/release-mainArtifact-dependencies.xml:0:0:0:0 | project/build/intermediates/incremental/lintVitalAnalyzeRelease/release-mainArtifact-dependencies.xml |
@@ -15,6 +18,3 @@ xmlFiles
| project/build/intermediates/merged_manifests/release/AndroidManifest.xml:0:0:0:0 | project/build/intermediates/merged_manifests/release/AndroidManifest.xml |
| project/build/intermediates/packaged_manifests/release/AndroidManifest.xml:0:0:0:0 | project/build/intermediates/packaged_manifests/release/AndroidManifest.xml |
| project/src/main/AndroidManifest.xml:0:0:0:0 | project/src/main/AndroidManifest.xml |
#select
| project/build/generated/source/buildConfig/release/com/github/androidsample/BuildConfig.java:0:0:0:0 | BuildConfig |
| project/src/main/java/com/github/androidsample/Main.java:0:0:0:0 | Main |

View File

@@ -1,3 +1,6 @@
#select
| project/build/generated/source/buildConfig/release/com/github/androidsample/BuildConfig.java:0:0:0:0 | BuildConfig |
| project/src/main/java/com/github/androidsample/Main.java:0:0:0:0 | Main |
xmlFiles
| project/build/intermediates/incremental/lintVitalAnalyzeRelease/module.xml:0:0:0:0 | project/build/intermediates/incremental/lintVitalAnalyzeRelease/module.xml |
| project/build/intermediates/incremental/lintVitalAnalyzeRelease/release-mainArtifact-dependencies.xml:0:0:0:0 | project/build/intermediates/incremental/lintVitalAnalyzeRelease/release-mainArtifact-dependencies.xml |
@@ -15,6 +18,3 @@ xmlFiles
| project/build/intermediates/merged_manifests/release/AndroidManifest.xml:0:0:0:0 | project/build/intermediates/merged_manifests/release/AndroidManifest.xml |
| project/build/intermediates/packaged_manifests/release/AndroidManifest.xml:0:0:0:0 | project/build/intermediates/packaged_manifests/release/AndroidManifest.xml |
| project/src/main/AndroidManifest.xml:0:0:0:0 | project/src/main/AndroidManifest.xml |
#select
| project/build/generated/source/buildConfig/release/com/github/androidsample/BuildConfig.java:0:0:0:0 | BuildConfig |
| project/src/main/java/com/github/androidsample/Main.java:0:0:0:0 | Main |

View File

@@ -1,3 +1,6 @@
#select
| project/build/generated/source/buildConfig/release/com/github/androidsample/BuildConfig.java:0:0:0:0 | BuildConfig |
| project/src/main/java/com/github/androidsample/Main.java:0:0:0:0 | Main |
xmlFiles
| project/build/intermediates/incremental/lintVitalAnalyzeRelease/module.xml:0:0:0:0 | project/build/intermediates/incremental/lintVitalAnalyzeRelease/module.xml |
| project/build/intermediates/incremental/lintVitalAnalyzeRelease/release-mainArtifact-dependencies.xml:0:0:0:0 | project/build/intermediates/incremental/lintVitalAnalyzeRelease/release-mainArtifact-dependencies.xml |
@@ -15,6 +18,3 @@ xmlFiles
| project/build/intermediates/merged_manifests/release/AndroidManifest.xml:0:0:0:0 | project/build/intermediates/merged_manifests/release/AndroidManifest.xml |
| project/build/intermediates/packaged_manifests/release/AndroidManifest.xml:0:0:0:0 | project/build/intermediates/packaged_manifests/release/AndroidManifest.xml |
| project/src/main/AndroidManifest.xml:0:0:0:0 | project/src/main/AndroidManifest.xml |
#select
| project/build/generated/source/buildConfig/release/com/github/androidsample/BuildConfig.java:0:0:0:0 | BuildConfig |
| project/src/main/java/com/github/androidsample/Main.java:0:0:0:0 | Main |

View File

@@ -1,3 +1,6 @@
#select
| project/build/generated/source/buildConfig/release/com/github/androidsample/BuildConfig.java:0:0:0:0 | BuildConfig |
| project/src/main/java/com/github/androidsample/Main.java:0:0:0:0 | Main |
xmlFiles
| project/build/intermediates/incremental/lintVitalAnalyzeRelease/module.xml:0:0:0:0 | project/build/intermediates/incremental/lintVitalAnalyzeRelease/module.xml |
| project/build/intermediates/incremental/lintVitalAnalyzeRelease/release-mainArtifact-dependencies.xml:0:0:0:0 | project/build/intermediates/incremental/lintVitalAnalyzeRelease/release-mainArtifact-dependencies.xml |
@@ -18,6 +21,3 @@ xmlFiles
| project/build/intermediates/merged_manifests/release/AndroidManifest.xml:0:0:0:0 | project/build/intermediates/merged_manifests/release/AndroidManifest.xml |
| project/build/intermediates/packaged_manifests/release/AndroidManifest.xml:0:0:0:0 | project/build/intermediates/packaged_manifests/release/AndroidManifest.xml |
| project/src/main/AndroidManifest.xml:0:0:0:0 | project/src/main/AndroidManifest.xml |
#select
| project/build/generated/source/buildConfig/release/com/github/androidsample/BuildConfig.java:0:0:0:0 | BuildConfig |
| project/src/main/java/com/github/androidsample/Main.java:0:0:0:0 | Main |

View File

@@ -1,3 +1,6 @@
#select
| project/build/generated/source/buildConfig/release/com/github/androidsample/BuildConfig.java:0:0:0:0 | BuildConfig |
| project/src/main/java/com/github/androidsample/Main.java:0:0:0:0 | Main |
xmlFiles
| project/build/intermediates/incremental/lintVitalAnalyzeRelease/module.xml:0:0:0:0 | project/build/intermediates/incremental/lintVitalAnalyzeRelease/module.xml |
| project/build/intermediates/incremental/lintVitalAnalyzeRelease/release-mainArtifact-dependencies.xml:0:0:0:0 | project/build/intermediates/incremental/lintVitalAnalyzeRelease/release-mainArtifact-dependencies.xml |
@@ -18,6 +21,3 @@ xmlFiles
| project/build/intermediates/merged_manifests/release/AndroidManifest.xml:0:0:0:0 | project/build/intermediates/merged_manifests/release/AndroidManifest.xml |
| project/build/intermediates/packaged_manifests/release/AndroidManifest.xml:0:0:0:0 | project/build/intermediates/packaged_manifests/release/AndroidManifest.xml |
| project/src/main/AndroidManifest.xml:0:0:0:0 | project/src/main/AndroidManifest.xml |
#select
| project/build/generated/source/buildConfig/release/com/github/androidsample/BuildConfig.java:0:0:0:0 | BuildConfig |
| project/src/main/java/com/github/androidsample/Main.java:0:0:0:0 | Main |

View File

@@ -1,3 +1,6 @@
#select
| project/build/generated/source/buildConfig/release/com/github/androidsample/BuildConfig.java:0:0:0:0 | BuildConfig |
| project/src/main/java/com/github/androidsample/Main.java:0:0:0:0 | Main |
xmlFiles
| project/build/intermediates/incremental/lintVitalAnalyzeRelease/module.xml:0:0:0:0 | project/build/intermediates/incremental/lintVitalAnalyzeRelease/module.xml |
| project/build/intermediates/incremental/lintVitalAnalyzeRelease/release-mainArtifact-dependencies.xml:0:0:0:0 | project/build/intermediates/incremental/lintVitalAnalyzeRelease/release-mainArtifact-dependencies.xml |
@@ -18,6 +21,3 @@ xmlFiles
| project/build/intermediates/merged_manifests/release/AndroidManifest.xml:0:0:0:0 | project/build/intermediates/merged_manifests/release/AndroidManifest.xml |
| project/build/intermediates/packaged_manifests/release/AndroidManifest.xml:0:0:0:0 | project/build/intermediates/packaged_manifests/release/AndroidManifest.xml |
| project/src/main/AndroidManifest.xml:0:0:0:0 | project/src/main/AndroidManifest.xml |
#select
| project/build/generated/source/buildConfig/release/com/github/androidsample/BuildConfig.java:0:0:0:0 | BuildConfig |
| project/src/main/java/com/github/androidsample/Main.java:0:0:0:0 | Main |

View File

@@ -1,3 +1,6 @@
#select
| project/build/generated/source/buildConfig/release/com/github/androidsample/BuildConfig.java:0:0:0:0 | BuildConfig |
| project/src/main/java/com/github/androidsample/Main.java:0:0:0:0 | Main |
xmlFiles
| project/build/intermediates/incremental/lintVitalAnalyzeRelease/module.xml:0:0:0:0 | project/build/intermediates/incremental/lintVitalAnalyzeRelease/module.xml |
| project/build/intermediates/incremental/lintVitalAnalyzeRelease/release-mainArtifact-dependencies.xml:0:0:0:0 | project/build/intermediates/incremental/lintVitalAnalyzeRelease/release-mainArtifact-dependencies.xml |
@@ -18,6 +21,3 @@ xmlFiles
| project/build/intermediates/merged_manifests/release/AndroidManifest.xml:0:0:0:0 | project/build/intermediates/merged_manifests/release/AndroidManifest.xml |
| project/build/intermediates/packaged_manifests/release/AndroidManifest.xml:0:0:0:0 | project/build/intermediates/packaged_manifests/release/AndroidManifest.xml |
| project/src/main/AndroidManifest.xml:0:0:0:0 | project/src/main/AndroidManifest.xml |
#select
| project/build/generated/source/buildConfig/release/com/github/androidsample/BuildConfig.java:0:0:0:0 | BuildConfig |
| project/src/main/java/com/github/androidsample/Main.java:0:0:0:0 | Main |

View File

@@ -1,3 +1,6 @@
#select
| project/build/generated/source/buildConfig/release/com/github/androidsample/BuildConfig.java:0:0:0:0 | BuildConfig |
| project/src/main/java/com/github/androidsample/Main.java:0:0:0:0 | Main |
xmlFiles
| project/build/intermediates/incremental/lintVitalAnalyzeRelease/module.xml:0:0:0:0 | project/build/intermediates/incremental/lintVitalAnalyzeRelease/module.xml |
| project/build/intermediates/incremental/lintVitalAnalyzeRelease/release-mainArtifact-dependencies.xml:0:0:0:0 | project/build/intermediates/incremental/lintVitalAnalyzeRelease/release-mainArtifact-dependencies.xml |
@@ -15,6 +18,3 @@ xmlFiles
| project/build/intermediates/merged_manifests/release/AndroidManifest.xml:0:0:0:0 | project/build/intermediates/merged_manifests/release/AndroidManifest.xml |
| project/build/intermediates/packaged_manifests/release/AndroidManifest.xml:0:0:0:0 | project/build/intermediates/packaged_manifests/release/AndroidManifest.xml |
| project/src/main/AndroidManifest.xml:0:0:0:0 | project/src/main/AndroidManifest.xml |
#select
| project/build/generated/source/buildConfig/release/com/github/androidsample/BuildConfig.java:0:0:0:0 | BuildConfig |
| project/src/main/java/com/github/androidsample/Main.java:0:0:0:0 | Main |

View File

@@ -1,4 +1,4 @@
xmlFiles
| build.xml:0:0:0:0 | build.xml |
#select
| src/main/java/com/example/App.java:0:0:0:0 | App |
xmlFiles
| build.xml:0:0:0:0 | build.xml |

View File

@@ -1,5 +1,5 @@
xmlFiles
| gradle/verification-metadata.xml:0:0:0:0 | gradle/verification-metadata.xml |
#select
| src/main/java/com/example/App.java:0:0:0:0 | App |
| src/test/java/com/example/AppTest.java:0:0:0:0 | AppTest |
xmlFiles
| gradle/verification-metadata.xml:0:0:0:0 | gradle/verification-metadata.xml |

View File

@@ -1,4 +1,4 @@
xmlFiles
#select
| app/src/main/java/test/App.java:0:0:0:0 | App |
| app/src/test/java/test/AppTest.java:0:0:0:0 | AppTest |
xmlFiles

View File

@@ -1,5 +1,5 @@
xmlFiles
| gradle/verification-metadata.xml:0:0:0:0 | gradle/verification-metadata.xml |
#select
| src/main/java/com/example/App.java:0:0:0:0 | App |
| src/test/java/com/example/AppTest.java:0:0:0:0 | AppTest |
xmlFiles
| gradle/verification-metadata.xml:0:0:0:0 | gradle/verification-metadata.xml |

View File

@@ -1,15 +1,3 @@
xmlFiles
| pom.xml:0:0:0:0 | pom.xml |
| spotbugs-security-exclude.xml:0:0:0:0 | spotbugs-security-exclude.xml |
| spotbugs-security-include.xml:0:0:0:0 | spotbugs-security-include.xml |
| src/main/webapp/WEB-INF/applicationContext.xml:0:0:0:0 | src/main/webapp/WEB-INF/applicationContext.xml |
| src/main/webapp/WEB-INF/web.xml:0:0:0:0 | src/main/webapp/WEB-INF/web.xml |
| src/main/webapp/WEB-INF/weblogic.xml:0:0:0:0 | src/main/webapp/WEB-INF/weblogic.xml |
| target/vulnerable-jsp-app-1.0.0-SNAPSHOT/WEB-INF/applicationContext.xml:0:0:0:0 | target/vulnerable-jsp-app-1.0.0-SNAPSHOT/WEB-INF/applicationContext.xml |
| target/vulnerable-jsp-app-1.0.0-SNAPSHOT/WEB-INF/web.xml:0:0:0:0 | target/vulnerable-jsp-app-1.0.0-SNAPSHOT/WEB-INF/web.xml |
| target/vulnerable-jsp-app-1.0.0-SNAPSHOT/WEB-INF/weblogic.xml:0:0:0:0 | target/vulnerable-jsp-app-1.0.0-SNAPSHOT/WEB-INF/weblogic.xml |
| target/web.xml:0:0:0:0 | target/web.xml |
| target/webfrag.xml:0:0:0:0 | target/webfrag.xml |
#select
| src/main/java/com/acme/Counter.java:0:0:0:0 | Counter |
| src/main/java/com/acme/Date2Tag.java:0:0:0:0 | Date2Tag |
@@ -56,3 +44,15 @@ xmlFiles
| target/classes/jsp/xss/xss4_jsp.java:0:0:0:0 | xss4_jsp |
| target/classes/jsp/xss/xss5_jsp.java:0:0:0:0 | xss5_jsp |
| target/classes/org/apache/jsp/tag/web/panel_tag.java:0:0:0:0 | panel_tag |
xmlFiles
| pom.xml:0:0:0:0 | pom.xml |
| spotbugs-security-exclude.xml:0:0:0:0 | spotbugs-security-exclude.xml |
| spotbugs-security-include.xml:0:0:0:0 | spotbugs-security-include.xml |
| src/main/webapp/WEB-INF/applicationContext.xml:0:0:0:0 | src/main/webapp/WEB-INF/applicationContext.xml |
| src/main/webapp/WEB-INF/web.xml:0:0:0:0 | src/main/webapp/WEB-INF/web.xml |
| src/main/webapp/WEB-INF/weblogic.xml:0:0:0:0 | src/main/webapp/WEB-INF/weblogic.xml |
| target/vulnerable-jsp-app-1.0.0-SNAPSHOT/WEB-INF/applicationContext.xml:0:0:0:0 | target/vulnerable-jsp-app-1.0.0-SNAPSHOT/WEB-INF/applicationContext.xml |
| target/vulnerable-jsp-app-1.0.0-SNAPSHOT/WEB-INF/web.xml:0:0:0:0 | target/vulnerable-jsp-app-1.0.0-SNAPSHOT/WEB-INF/web.xml |
| target/vulnerable-jsp-app-1.0.0-SNAPSHOT/WEB-INF/weblogic.xml:0:0:0:0 | target/vulnerable-jsp-app-1.0.0-SNAPSHOT/WEB-INF/weblogic.xml |
| target/web.xml:0:0:0:0 | target/web.xml |
| target/webfrag.xml:0:0:0:0 | target/webfrag.xml |

View File

@@ -1,3 +1,6 @@
#select
| src/main/java/com/example/App.java:0:0:0:0 | App |
| src/test/java/com/example/AppTest.java:0:0:0:0 | AppTest |
xmlFiles
| pom.xml:0:0:0:0 | pom.xml |
| src/main/resources/page.xml:0:0:0:0 | src/main/resources/page.xml |
@@ -10,6 +13,3 @@ propertiesFiles
| target/maven-archiver/pom.properties:0:0:0:0 | target/maven-archiver/pom.properties |
| test-db/log/ext/javac-1.properties:0:0:0:0 | test-db/log/ext/javac-1.properties |
| test-db/log/ext/javac.properties:0:0:0:0 | test-db/log/ext/javac.properties |
#select
| src/main/java/com/example/App.java:0:0:0:0 | App |
| src/test/java/com/example/AppTest.java:0:0:0:0 | AppTest |

View File

@@ -1,7 +1,7 @@
#select
| src/main/java/com/example/App.java:0:0:0:0 | App |
| src/test/java/com/example/AppTest.java:0:0:0:0 | AppTest |
xmlFiles
| pom.xml:0:0:0:0 | pom.xml |
| src/main/resources/struts.xml:0:0:0:0 | src/main/resources/struts.xml |
| target/classes/struts.xml:0:0:0:0 | target/classes/struts.xml |
#select
| src/main/java/com/example/App.java:0:0:0:0 | App |
| src/test/java/com/example/AppTest.java:0:0:0:0 | AppTest |

View File

@@ -1,3 +1,6 @@
#select
| src/main/java/com/example/App.java:0:0:0:0 | App |
| src/test/java/com/example/AppTest.java:0:0:0:0 | AppTest |
xmlFiles
| generated-0.xml:0:0:0:0 | generated-0.xml |
| generated-1.xml:0:0:0:0 | generated-1.xml |
@@ -9,6 +12,3 @@ xmlFiles
| src/main/resources/struts.xml:0:0:0:0 | src/main/resources/struts.xml |
| target/classes/page.xml:0:0:0:0 | target/classes/page.xml |
| target/classes/struts.xml:0:0:0:0 | target/classes/struts.xml |
#select
| src/main/java/com/example/App.java:0:0:0:0 | App |
| src/test/java/com/example/AppTest.java:0:0:0:0 | AppTest |

View File

@@ -1,9 +1,9 @@
#select
| src/main/java/com/example/App.java:0:0:0:0 | App |
| src/test/java/com/example/AppTest.java:0:0:0:0 | AppTest |
xmlFiles
| pom.xml:0:0:0:0 | pom.xml |
| src/main/resources/page.xml:0:0:0:0 | src/main/resources/page.xml |
| src/main/resources/struts.xml:0:0:0:0 | src/main/resources/struts.xml |
| target/classes/page.xml:0:0:0:0 | target/classes/page.xml |
| target/classes/struts.xml:0:0:0:0 | target/classes/struts.xml |
#select
| src/main/java/com/example/App.java:0:0:0:0 | App |
| src/test/java/com/example/AppTest.java:0:0:0:0 | AppTest |

View File

@@ -1,7 +1,7 @@
#select
| src/main/java/com/example/App.java:0:0:0:0 | App |
| src/test/java/com/example/AppTest.java:0:0:0:0 | AppTest |
xmlFiles
| pom.xml:0:0:0:0 | pom.xml |
| src/main/resources/struts.xml:0:0:0:0 | src/main/resources/struts.xml |
| target/classes/struts.xml:0:0:0:0 | target/classes/struts.xml |
#select
| src/main/java/com/example/App.java:0:0:0:0 | App |
| src/test/java/com/example/AppTest.java:0:0:0:0 | AppTest |

View File

@@ -1,4 +1,4 @@
xmlFiles
#select
| src/main/java/com/example/App.java:0:0:0:0 | App |
| src/test/java/com/example/AppTest.java:0:0:0:0 | AppTest |
xmlFiles

View File

@@ -1,7 +1,7 @@
#select
| src/main/java/com/example/App.java:0:0:0:0 | App |
| src/test/java/com/example/AppTest.java:0:0:0:0 | AppTest |
xmlFiles
| pom.xml:0:0:0:0 | pom.xml |
| src/main/resources/struts.xml:0:0:0:0 | src/main/resources/struts.xml |
| target/classes/struts.xml:0:0:0:0 | target/classes/struts.xml |
#select
| src/main/java/com/example/App.java:0:0:0:0 | App |
| src/test/java/com/example/AppTest.java:0:0:0:0 | AppTest |

View File

@@ -1,5 +1,5 @@
xmlFiles
| gradle/verification-metadata.xml:0:0:0:0 | gradle/verification-metadata.xml |
#select
| src/main/java/com/example/App.java:0:0:0:0 | App |
| src/test/java/com/example/AppTest.java:0:0:0:0 | AppTest |
xmlFiles
| gradle/verification-metadata.xml:0:0:0:0 | gradle/verification-metadata.xml |

View File

@@ -1,5 +1,5 @@
xmlFiles
| gradle/verification-metadata.xml:0:0:0:0 | gradle/verification-metadata.xml |
#select
| src/main/java/com/example/App.java:0:0:0:0 | App |
| src/test/java/com/example/AppTest.java:0:0:0:0 | AppTest |
xmlFiles
| gradle/verification-metadata.xml:0:0:0:0 | gradle/verification-metadata.xml |

Some files were not shown because too many files have changed in this diff Show More