This commit is contained in:
Owen Mansel-Chan 2023-11-22 16:50:41 +00:00 коммит произвёл GitHub
Родитель 9e5a80ac59 98ddbe0d83
Коммит a130c0f6b3
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
1886 изменённых файлов: 47276 добавлений и 3602 удалений

Просмотреть файл

@ -8,6 +8,8 @@
/swift/ @github/codeql-swift
/misc/codegen/ @github/codeql-swift
/java/kotlin-extractor/ @github/codeql-kotlin
/java/ql/test-kotlin1/ @github/codeql-kotlin
/java/ql/test-kotlin2/ @github/codeql-kotlin
# ML-powered queries
/javascript/ql/experimental/adaptivethreatmodeling/ @github/codeql-ml-powered-queries-reviewers

Просмотреть файл

@ -1,7 +1,7 @@
provide:
- "*/ql/src/qlpack.yml"
- "*/ql/lib/qlpack.yml"
- "*/ql/test/qlpack.yml"
- "*/ql/test*/qlpack.yml"
- "*/ql/examples/qlpack.yml"
- "*/ql/consistency-queries/qlpack.yml"
- "*/ql/automodel/src/qlpack.yml"

Просмотреть файл

@ -1,3 +1,17 @@
## 0.12.0
### Breaking Changes
* The expressions `AssignPointerAddExpr` and `AssignPointerSubExpr` are no longer subtypes of `AssignBitwiseOperation`.
### Minor Analysis Improvements
* The "Returning stack-allocated memory" (`cpp/return-stack-allocated-memory`) query now also detects returning stack-allocated memory allocated by calls to `alloca`, `strdupa`, and `strndupa`.
* Added models for `strlcpy` and `strlcat`.
* Added models for the `sprintf` variants from the `StrSafe.h` header.
* Added SQL API models for `ODBC`.
* Added taint models for `realloc` and related functions.
## 0.11.0
### Breaking Changes

Просмотреть файл

@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Added taint models for `realloc` and related functions.

Просмотреть файл

@ -1,4 +0,0 @@
---
category: breaking
---
* The expressions `AssignPointerAddExpr` and `AssignPointerSubExpr` are no longer subtypes of `AssignBitwiseOperation`.

Просмотреть файл

@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Added models for the `sprintf` variants from the `StrSafe.h` header.

Просмотреть файл

@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Added models for `strlcpy` and `strlcat`.

Просмотреть файл

@ -0,0 +1,13 @@
## 0.12.0
### Breaking Changes
* The expressions `AssignPointerAddExpr` and `AssignPointerSubExpr` are no longer subtypes of `AssignBitwiseOperation`.
### Minor Analysis Improvements
* The "Returning stack-allocated memory" (`cpp/return-stack-allocated-memory`) query now also detects returning stack-allocated memory allocated by calls to `alloca`, `strdupa`, and `strndupa`.
* Added models for `strlcpy` and `strlcat`.
* Added models for the `sprintf` variants from the `StrSafe.h` header.
* Added SQL API models for `ODBC`.
* Added taint models for `realloc` and related functions.

Просмотреть файл

@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.11.0
lastReleaseVersion: 0.12.0

Просмотреть файл

@ -1,5 +1,5 @@
name: codeql/cpp-all
version: 0.11.1-dev
version: 0.12.1-dev
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp

Просмотреть файл

@ -645,6 +645,24 @@ class GlobalLikeVariable extends Variable {
}
}
/**
* Returns the smallest indirection for the type `t`.
*
* For most types this is `1`, but for `ArrayType`s (which are allocated on
* the stack) this is `0`
*/
int getMinIndirectionsForType(Type t) {
if t.getUnspecifiedType() instanceof Cpp::ArrayType then result = 0 else result = 1
}
private int getMinIndirectionForGlobalUse(Ssa::GlobalUse use) {
result = getMinIndirectionsForType(use.getUnspecifiedType())
}
private int getMinIndirectionForGlobalDef(Ssa::GlobalDef def) {
result = getMinIndirectionsForType(def.getUnspecifiedType())
}
/**
* Holds if data can flow from `node1` to `node2` in a way that loses the
* calling context. For example, this would happen with flow through a
@ -656,7 +674,7 @@ predicate jumpStep(Node n1, Node n2) {
v = globalUse.getVariable() and
n1.(FinalGlobalValue).getGlobalUse() = globalUse
|
globalUse.getIndirection() = 1 and
globalUse.getIndirection() = getMinIndirectionForGlobalUse(globalUse) and
v = n2.asVariable()
or
v = n2.asIndirectVariable(globalUse.getIndirection())
@ -666,7 +684,7 @@ predicate jumpStep(Node n1, Node n2) {
v = globalDef.getVariable() and
n2.(InitialGlobalValue).getGlobalDef() = globalDef
|
globalDef.getIndirection() = 1 and
globalDef.getIndirection() = getMinIndirectionForGlobalDef(globalDef) and
v = n1.asVariable()
or
v = n1.asIndirectVariable(globalDef.getIndirection())

Просмотреть файл

@ -34,7 +34,8 @@ cached
private newtype TIRDataFlowNode =
TNode0(Node0Impl node) { DataFlowImplCommon::forceCachingInSameStage() } or
TVariableNode(Variable var, int indirectionIndex) {
indirectionIndex = [1 .. Ssa::getMaxIndirectionsForType(var.getUnspecifiedType())]
indirectionIndex =
[getMinIndirectionsForType(var.getUnspecifiedType()) .. Ssa::getMaxIndirectionsForType(var.getUnspecifiedType())]
} or
TPostFieldUpdateNode(FieldAddress operand, int indirectionIndex) {
indirectionIndex =
@ -346,7 +347,9 @@ class Node extends TIRDataFlowNode {
* Gets the variable corresponding to this node, if any. This can be used for
* modeling flow in and out of global variables.
*/
Variable asVariable() { this = TVariableNode(result, 1) }
Variable asVariable() {
this = TVariableNode(result, getMinIndirectionsForType(result.getUnspecifiedType()))
}
/**
* Gets the `indirectionIndex`'th indirection of this node's underlying variable, if any.
@ -354,7 +357,7 @@ class Node extends TIRDataFlowNode {
* This can be used for modeling flow in and out of global variables.
*/
Variable asIndirectVariable(int indirectionIndex) {
indirectionIndex > 1 and
indirectionIndex > getMinIndirectionsForType(result.getUnspecifiedType()) and
this = TVariableNode(result, indirectionIndex)
}
@ -1273,31 +1276,90 @@ abstract private class IndirectExprNodeBase extends Node {
}
}
private class IndirectOperandIndirectExprNode extends IndirectExprNodeBase instanceof IndirectOperand
{
IndirectOperandIndirectExprNode() {
exists(Expr e, int n, int indirectionIndex |
indirectExprNodeShouldBeIndirectOperand(this, e, n, indirectionIndex) and
not indirectExprNodeShouldBeIndirectOperand(_, e, n + 1, indirectionIndex)
)
/** A signature for converting an indirect node to an expression. */
private signature module IndirectNodeToIndirectExprSig {
/** The indirect node class to be converted to an expression */
class IndirectNode;
/**
* Holds if the indirect expression at indirection index `indirectionIndex`
* of `node` is `e`. The integer `n` specifies how many conversions has been
* applied to `node`.
*/
predicate indirectNodeHasIndirectExpr(IndirectNode node, Expr e, int n, int indirectionIndex);
}
/**
* A module that implements the logic for deciding whether an indirect node
* should be an `IndirectExprNode`.
*/
private module IndirectNodeToIndirectExpr<IndirectNodeToIndirectExprSig Sig> {
import Sig
/**
* This predicate shifts the indirection index by one when `conv` is a
* `ReferenceDereferenceExpr`.
*
* This is necessary because `ReferenceDereferenceExpr` is a conversion
* in the AST, but appears as a `LoadInstruction` in the IR.
*/
bindingset[e, indirectionIndex]
private predicate adjustForReference(
Expr e, int indirectionIndex, Expr conv, int adjustedIndirectionIndex
) {
conv.(ReferenceDereferenceExpr).getExpr() = e and
adjustedIndirectionIndex = indirectionIndex - 1
or
not conv instanceof ReferenceDereferenceExpr and
conv = e and
adjustedIndirectionIndex = indirectionIndex
}
final override Expr getConvertedExpr(int n, int index) {
indirectExprNodeShouldBeIndirectOperand(this, result, n, index)
/** Holds if `node` should be an `IndirectExprNode`. */
predicate charpred(IndirectNode node) {
exists(Expr e, int n, int indirectionIndex |
indirectNodeHasIndirectExpr(node, e, n, indirectionIndex) and
not exists(Expr conv, int adjustedIndirectionIndex |
adjustForReference(e, indirectionIndex, conv, adjustedIndirectionIndex) and
indirectNodeHasIndirectExpr(_, conv, n + 1, adjustedIndirectionIndex)
)
)
}
}
private class IndirectInstructionIndirectExprNode extends IndirectExprNodeBase instanceof IndirectInstruction
private module IndirectOperandIndirectExprNodeImpl implements IndirectNodeToIndirectExprSig {
class IndirectNode = IndirectOperand;
predicate indirectNodeHasIndirectExpr = indirectExprNodeShouldBeIndirectOperand/4;
}
module IndirectOperandToIndirectExpr =
IndirectNodeToIndirectExpr<IndirectOperandIndirectExprNodeImpl>;
private class IndirectOperandIndirectExprNode extends IndirectExprNodeBase instanceof IndirectOperand
{
IndirectInstructionIndirectExprNode() {
exists(Expr e, int n, int indirectionIndex |
indirectExprNodeShouldBeIndirectInstruction(this, e, n, indirectionIndex) and
not indirectExprNodeShouldBeIndirectInstruction(_, e, n + 1, indirectionIndex)
)
}
IndirectOperandIndirectExprNode() { IndirectOperandToIndirectExpr::charpred(this) }
final override Expr getConvertedExpr(int n, int index) {
indirectExprNodeShouldBeIndirectInstruction(this, result, n, index)
IndirectOperandToIndirectExpr::indirectNodeHasIndirectExpr(this, result, n, index)
}
}
private module IndirectInstructionIndirectExprNodeImpl implements IndirectNodeToIndirectExprSig {
class IndirectNode = IndirectInstruction;
predicate indirectNodeHasIndirectExpr = indirectExprNodeShouldBeIndirectInstruction/4;
}
module IndirectInstructionToIndirectExpr =
IndirectNodeToIndirectExpr<IndirectInstructionIndirectExprNodeImpl>;
private class IndirectInstructionIndirectExprNode extends IndirectExprNodeBase instanceof IndirectInstruction
{
IndirectInstructionIndirectExprNode() { IndirectInstructionToIndirectExpr::charpred(this) }
final override Expr getConvertedExpr(int n, int index) {
IndirectInstructionToIndirectExpr::indirectNodeHasIndirectExpr(this, result, n, index)
}
}

Просмотреть файл

@ -59,6 +59,9 @@ private module SourceVariables {
then result = base.getType()
else result = getTypeImpl(base.getType(), ind - 1)
}
/** Gets the location of this variable. */
Location getLocation() { result = this.getBaseVariable().getLocation() }
}
}
@ -869,7 +872,7 @@ private predicate sourceVariableIsGlobal(
)
}
private module SsaInput implements SsaImplCommon::InputSig {
private module SsaInput implements SsaImplCommon::InputSig<Location> {
import InputSigCommon
import SourceVariables
@ -1092,7 +1095,7 @@ class Def extends DefOrUse {
predicate isCertain() { defOrUse.isCertain() }
}
private module SsaImpl = SsaImplCommon::Make<SsaInput>;
private module SsaImpl = SsaImplCommon::Make<Location, SsaInput>;
class PhiNode extends SsaImpl::DefinitionExt {
PhiNode() {

Просмотреть файл

@ -377,6 +377,9 @@ abstract private class AbstractBaseSourceVariable extends TBaseSourceVariable {
/** Gets a textual representation of this element. */
abstract string toString();
/** Gets the location of this variable. */
abstract Location getLocation();
/** Gets the type of this base source variable. */
final DataFlowType getType() { this.getLanguageType().hasUnspecifiedType(result, _) }
@ -395,6 +398,8 @@ class BaseIRVariable extends AbstractBaseSourceVariable, TBaseIRVariable {
override string toString() { result = var.toString() }
override Location getLocation() { result = var.getLocation() }
override CppType getLanguageType() { result = var.getLanguageType() }
}
@ -407,6 +412,8 @@ class BaseCallVariable extends AbstractBaseSourceVariable, TBaseCallVariable {
override string toString() { result = call.toString() }
override Location getLocation() { result = call.getLocation() }
override CppType getLanguageType() { result = getResultLanguageType(call) }
}
@ -872,7 +879,7 @@ private module Cached {
upper = countIndirectionsForCppType(type) and
ind = ind0 + [lower .. upper] and
indirectionIndex = ind - (ind0 + lower) and
(if type.hasType(any(Cpp::ArrayType arrayType), true) then lower = 0 else lower = 1)
lower = getMinIndirectionsForType(any(Type t | type.hasUnspecifiedType(t, _)))
)
}

Просмотреть файл

@ -229,7 +229,7 @@ private class FinalParameterUse extends UseImpl, TFinalParameterUse {
override predicate isCertain() { any() }
}
private module SsaInput implements SsaImplCommon::InputSig {
private module SsaInput implements SsaImplCommon::InputSig<Location> {
import InputSigCommon
import SourceVariables
@ -335,7 +335,7 @@ class Def extends DefOrUse {
predicate isIteratorDef() { defOrUse instanceof IteratorDef }
}
private module SsaImpl = SsaImplCommon::Make<SsaInput>;
private module SsaImpl = SsaImplCommon::Make<Location, SsaInput>;
class PhiNode extends SsaImpl::DefinitionExt {
PhiNode() {

Просмотреть файл

@ -1,3 +1,9 @@
## 0.8.3
### Minor Analysis Improvements
* The `cpp/uninitialized-local` query has been improved to produce fewer false positives.
## 0.8.2
No user-facing changes.

Просмотреть файл

@ -27,16 +27,26 @@ class ReturnStackAllocatedMemoryConfig extends MustFlowConfiguration {
ReturnStackAllocatedMemoryConfig() { this = "ReturnStackAllocatedMemoryConfig" }
override predicate isSource(Instruction source) {
// Holds if `source` is a node that represents the use of a stack variable
exists(VariableAddressInstruction var, Function func |
var = source and
func = source.getEnclosingFunction() and
var.getAstVariable() instanceof StackVariable and
// Pointer-to-member types aren't properly handled in the dbscheme.
not var.getResultType() instanceof PointerToMemberType and
exists(Function func |
// Rule out FPs caused by extraction errors.
not any(ErrorExpr e).getEnclosingFunction() = func and
not intentionallyReturnsStackPointer(func)
not intentionallyReturnsStackPointer(func) and
func = source.getEnclosingFunction()
|
// `source` is an instruction that represents the use of a stack variable
exists(VariableAddressInstruction var |
var = source and
var.getAstVariable() instanceof StackVariable and
// Pointer-to-member types aren't properly handled in the dbscheme.
not var.getResultType() instanceof PointerToMemberType
)
or
// `source` is an instruction that represents the return value of a
// function that is known to return stack-allocated memory.
exists(Call call |
call.getTarget().hasGlobalName(["alloca", "strdupa", "strndupa", "_alloca", "_malloca"]) and
source.getUnconvertedResultExpression() = call
)
)
}
@ -85,10 +95,10 @@ class ReturnStackAllocatedMemoryConfig extends MustFlowConfiguration {
}
from
MustFlowPathNode source, MustFlowPathNode sink, VariableAddressInstruction var,
MustFlowPathNode source, MustFlowPathNode sink, Instruction instr,
ReturnStackAllocatedMemoryConfig conf
where
conf.hasFlowPath(pragma[only_bind_into](source), pragma[only_bind_into](sink)) and
source.getInstruction() = var
source.getInstruction() = instr
select sink.getInstruction(), source, sink, "May return stack-allocated memory from $@.",
var.getAst(), var.getAst().toString()
instr.getAst(), instr.getAst().toString()

Просмотреть файл

@ -14,25 +14,47 @@
import cpp
import semmle.code.cpp.security.Security
import semmle.code.cpp.ir.dataflow.internal.DefaultTaintTrackingImpl
import TaintedWithPath
import semmle.code.cpp.security.FlowSources
import semmle.code.cpp.ir.dataflow.TaintTracking
import semmle.code.cpp.ir.IR
import Flow::PathGraph
predicate isProcessOperationExplanation(Expr arg, string processOperation) {
predicate isProcessOperationExplanation(DataFlow::Node arg, string processOperation) {
exists(int processOperationArg, FunctionCall call |
isProcessOperationArgument(processOperation, processOperationArg) and
call.getTarget().getName() = processOperation and
call.getArgument(processOperationArg) = arg
call.getArgument(processOperationArg) = [arg.asExpr(), arg.asIndirectExpr()]
)
}
class Configuration extends TaintTrackingConfiguration {
override predicate isSink(Element arg) { isProcessOperationExplanation(arg, _) }
predicate isSource(FlowSource source, string sourceType) {
not source instanceof DataFlow::ExprNode and
sourceType = source.getSourceType()
}
from string processOperation, Expr arg, Expr source, PathNode sourceNode, PathNode sinkNode
module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { isSource(node, _) }
predicate isSink(DataFlow::Node node) { isProcessOperationExplanation(node, _) }
predicate isBarrier(DataFlow::Node node) {
isSink(node) and node.asExpr().getUnspecifiedType() instanceof ArithmeticType
or
node.asInstruction().(StoreInstruction).getResultType() instanceof ArithmeticType
}
}
module Flow = TaintTracking::Global<Config>;
from
string processOperation, string sourceType, DataFlow::Node source, DataFlow::Node sink,
Flow::PathNode sourceNode, Flow::PathNode sinkNode
where
isProcessOperationExplanation(arg, processOperation) and
taintedWithPath(source, arg, sourceNode, sinkNode)
select arg, sourceNode, sinkNode,
source = sourceNode.getNode() and
sink = sinkNode.getNode() and
isSource(source, sourceType) and
isProcessOperationExplanation(sink, processOperation) and
Flow::flowPath(sourceNode, sinkNode)
select sink, sourceNode, sinkNode,
"The value of this argument may come from $@ and is being passed to " + processOperation + ".",
source, source.toString()
source, sourceType

Просмотреть файл

@ -1,24 +0,0 @@
#include <stdio.h>
char *copy;
void copyArgv(char **argv) {
copy = argv[1];
}
void printWrapper(char *str) {
printf(str);
}
int main(int argc, char **argv) {
copyArgv(argv);
// This should be avoided
printf(copy);
// This should be avoided too, because it has the same effect
printWrapper(copy);
// This is fine
printf("%s", copy);
}

Просмотреть файл

@ -1,36 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>The program uses input from the user, propagated via a global variable, as a format string for <code>printf</code> style functions.
This can lead to buffer overflows or data representation problems. An attacker can exploit this weakness to crash the program,
disclose information or even execute arbitrary code.</p>
<p>This rule only identifies inputs from the user that are transferred through global variables before being used in <code>printf</code> style functions.
Analyzing the flow of data through global variables is more prone to errors and so this rule may identify some examples of code where
the input is not really from the user. For example, when a global variable is set in two places, one that comes from the user and one that does not.
In this case we would mark all usages of the global variable as input from the user, but the input from the user may always came after the call to the
<code>printf</code> style functions.</p>
<p>The results of this rule should be considered alongside the related rule "Uncontrolled format string" which tracks the flow of the
values input by a user, excluding global variables, until the values are used as the format argument for a <code>printf</code> like function call.</p>
</overview>
<recommendation>
<p>Use constant expressions as the format strings. If you need to print a value from the user, use <code>printf("%s", value_from_user)</code>.</p>
</recommendation>
<example>
<sample src="UncontrolledFormatStringThroughGlobalVar.c" />
</example>
<references>
<li>CERT C Coding
Standard: <a href="https://www.securecoding.cert.org/confluence/display/c/FIO30-C.+Exclude+user+input+from+format+strings">FIO30-C. Exclude
user input from format strings</a>.</li>
</references>
</qhelp>

Просмотреть файл

@ -1,40 +0,0 @@
/**
* @name Uncontrolled format string (through global variable)
* @description Using externally-controlled format strings in
* printf-style functions can lead to buffer overflows
* or data representation problems.
* @kind path-problem
* @problem.severity warning
* @security-severity 9.3
* @precision high
* @id cpp/tainted-format-string-through-global
* @tags reliability
* security
* external/cwe/cwe-134
*/
import cpp
import semmle.code.cpp.security.FunctionWithWrappers
import semmle.code.cpp.security.Security
import semmle.code.cpp.ir.dataflow.internal.DefaultTaintTrackingImpl
import TaintedWithPath
class Configuration extends TaintTrackingConfiguration {
override predicate isSink(Element tainted) {
exists(PrintfLikeFunction printf | printf.outermostWrapperFunctionCall(tainted, _))
}
override predicate taintThroughGlobals() { any() }
}
from
PrintfLikeFunction printf, Expr arg, PathNode sourceNode, PathNode sinkNode,
string printfFunction, Expr userValue, string cause
where
printf.outermostWrapperFunctionCall(arg, printfFunction) and
not taintedWithoutGlobals(arg) and
taintedWithPath(userValue, arg, sourceNode, sinkNode) and
isUserInput(userValue, cause)
select arg, sourceNode, sinkNode,
"The value of this argument may come from $@ and is being used as a formatting argument to " +
printfFunction + ".", userValue, cause

Просмотреть файл

@ -14,10 +14,13 @@
import cpp
import semmle.code.cpp.security.Overflow
import semmle.code.cpp.security.Security
import semmle.code.cpp.ir.dataflow.internal.DefaultTaintTrackingImpl
import TaintedWithPath
import semmle.code.cpp.dataflow.new.TaintTracking
import semmle.code.cpp.dataflow.new.DataFlow
import semmle.code.cpp.ir.IR
import semmle.code.cpp.controlflow.IRGuards as IRGuards
import semmle.code.cpp.security.FlowSources as FS
import Bounded
import Flow::PathGraph
bindingset[op]
predicate missingGuard(Operation op, Expr e, string effect) {
@ -28,28 +31,90 @@ predicate missingGuard(Operation op, Expr e, string effect) {
not e instanceof VariableAccess and effect = "overflow"
}
class Configuration extends TaintTrackingConfiguration {
override predicate isSink(Element e) {
exists(Operation op |
missingGuard(op, e, _) and
op.getAnOperand() = e
|
op instanceof UnaryArithmeticOperation or
op instanceof BinaryArithmeticOperation or
op instanceof AssignArithmeticOperation
)
}
predicate isSource(FS::FlowSource source, string sourceType) { sourceType = source.getSourceType() }
override predicate isBarrier(Expr e) {
super.isBarrier(e) or bounded(e) or e.getUnspecifiedType().(IntegralType).getSize() <= 1
predicate isSink(DataFlow::Node sink, Operation op, Expr e) {
e = sink.asExpr() and
missingGuard(op, e, _) and
op.getAnOperand() = e and
(
op instanceof UnaryArithmeticOperation or
op instanceof BinaryArithmeticOperation or
op instanceof AssignArithmeticOperation
)
}
predicate hasUpperBoundsCheck(Variable var) {
exists(RelationalOperation oper, VariableAccess access |
oper.getAnOperand() = access and
access.getTarget() = var and
// Comparing to 0 is not an upper bound check
not oper.getAnOperand().getValue() = "0"
)
}
predicate constantInstruction(Instruction instr) {
instr instanceof ConstantInstruction or
constantInstruction(instr.(UnaryInstruction).getUnary())
}
predicate readsVariable(LoadInstruction load, Variable var) {
load.getSourceAddress().(VariableAddressInstruction).getAstVariable() = var
}
predicate nodeIsBarrierEqualityCandidate(DataFlow::Node node, Operand access, Variable checkedVar) {
exists(Instruction instr | instr = node.asInstruction() |
readsVariable(instr, checkedVar) and
any(IRGuards::IRGuardCondition guard).ensuresEq(access, _, _, instr.getBlock(), true)
)
}
module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { isSource(source, _) }
predicate isSink(DataFlow::Node sink) { isSink(sink, _, _) }
predicate isBarrier(DataFlow::Node node) {
exists(StoreInstruction store | store = node.asInstruction() |
// Block flow to "likely small expressions"
bounded(store.getSourceValue().getUnconvertedResultExpression())
or
// Block flow to "small types"
store.getResultType().getUnspecifiedType().(IntegralType).getSize() <= 1
)
or
// Block flow if there's an upper bound check of the variable anywhere in the program
exists(Variable checkedVar, Instruction instr | instr = node.asInstruction() |
readsVariable(instr, checkedVar) and
hasUpperBoundsCheck(checkedVar)
)
or
// Block flow if the node is guarded by an equality check
exists(Variable checkedVar, Operand access |
nodeIsBarrierEqualityCandidate(node, access, checkedVar) and
readsVariable(access.getDef(), checkedVar)
)
or
// Block flow to any binary instruction whose operands are both non-constants.
exists(BinaryInstruction iTo |
iTo = node.asInstruction() and
not constantInstruction(iTo.getLeft()) and
not constantInstruction(iTo.getRight()) and
// propagate taint from either the pointer or the offset, regardless of constantness
not iTo instanceof PointerArithmeticInstruction
)
}
}
from Expr origin, Expr e, string effect, PathNode sourceNode, PathNode sinkNode, Operation op
module Flow = TaintTracking::Global<Config>;
from
Expr e, string effect, Flow::PathNode source, Flow::PathNode sink, Operation op, string sourceType
where
taintedWithPath(origin, e, sourceNode, sinkNode) and
op.getAnOperand() = e and
Flow::flowPath(source, sink) and
isSource(source.getNode(), sourceType) and
isSink(sink.getNode(), op, e) and
missingGuard(op, e, effect)
select e, sourceNode, sinkNode,
select e, source, sink,
"$@ flows to an operand of an arithmetic expression, potentially causing an " + effect + ".",
origin, "User-provided value"
source, sourceType

Просмотреть файл

@ -16,45 +16,30 @@
import cpp
import semmle.code.cpp.security.Overflow
import semmle.code.cpp.security.Security
import semmle.code.cpp.ir.dataflow.internal.DefaultTaintTrackingImpl
import semmle.code.cpp.dataflow.new.TaintTracking
import semmle.code.cpp.ir.IR
import semmle.code.cpp.controlflow.IRGuards as IRGuards
predicate isMaxValue(Expr mie) {
exists(MacroInvocation mi |
mi.getExpr() = mie and
(
mi.getMacroName() = "CHAR_MAX" or
mi.getMacroName() = "LLONG_MAX" or
mi.getMacroName() = "INT_MAX" or
mi.getMacroName() = "SHRT_MAX" or
mi.getMacroName() = "UINT_MAX"
)
mi.getMacroName() = ["CHAR_MAX", "LLONG_MAX", "INT_MAX", "SHRT_MAX", "UINT_MAX"]
)
}
predicate isMinValue(Expr mie) {
exists(MacroInvocation mi |
mi.getExpr() = mie and
(
mi.getMacroName() = "CHAR_MIN" or
mi.getMacroName() = "LLONG_MIN" or
mi.getMacroName() = "INT_MIN" or
mi.getMacroName() = "SHRT_MIN"
)
mi.getMacroName() = ["CHAR_MIN", "LLONG_MIN", "INT_MIN", "SHRT_MIN"]
)
}
class SecurityOptionsArith extends SecurityOptions {
override predicate isUserInput(Expr expr, string cause) {
predicate isSource(DataFlow::Node source, string cause) {
exists(Expr expr | expr = source.asExpr() |
isMaxValue(expr) and cause = "max value"
or
isMinValue(expr) and cause = "min value"
}
}
predicate taintedVarAccess(Expr origin, VariableAccess va, string cause) {
isUserInput(origin, cause) and
tainted(origin, va)
)
}
predicate causeEffectCorrespond(string cause, string effect) {
@ -65,16 +50,79 @@ predicate causeEffectCorrespond(string cause, string effect) {
effect = "underflow"
}
from Expr origin, Operation op, VariableAccess va, string cause, string effect
where
taintedVarAccess(origin, va, cause) and
op.getAnOperand() = va and
(
predicate isSink(DataFlow::Node sink, VariableAccess va, string effect) {
exists(Operation op |
sink.asExpr() = va and
op.getAnOperand() = va
|
missingGuardAgainstUnderflow(op, va) and effect = "underflow"
or
missingGuardAgainstOverflow(op, va) and effect = "overflow"
) and
causeEffectCorrespond(cause, effect)
)
}
predicate hasUpperBoundsCheck(Variable var) {
exists(RelationalOperation oper, VariableAccess access |
oper.getAnOperand() = access and
access.getTarget() = var and
// Comparing to 0 is not an upper bound check
not oper.getAnOperand().getValue() = "0"
)
}
predicate constantInstruction(Instruction instr) {
instr instanceof ConstantInstruction or
constantInstruction(instr.(UnaryInstruction).getUnary())
}
predicate readsVariable(LoadInstruction load, Variable var) {
load.getSourceAddress().(VariableAddressInstruction).getAstVariable() = var
}
predicate nodeIsBarrierEqualityCandidate(DataFlow::Node node, Operand access, Variable checkedVar) {
exists(Instruction instr | instr = node.asInstruction() |
readsVariable(instr, checkedVar) and
any(IRGuards::IRGuardCondition guard).ensuresEq(access, _, _, instr.getBlock(), true)
)
}
module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { isSource(source, _) }
predicate isSink(DataFlow::Node sink) { isSink(sink, _, _) }
predicate isBarrier(DataFlow::Node node) {
// Block flow if there's an upper bound check of the variable anywhere in the program
exists(Variable checkedVar, Instruction instr | instr = node.asInstruction() |
readsVariable(instr, checkedVar) and
hasUpperBoundsCheck(checkedVar)
)
or
// Block flow if the node is guarded by an equality check
exists(Variable checkedVar, Operand access |
nodeIsBarrierEqualityCandidate(node, access, checkedVar) and
readsVariable(access.getDef(), checkedVar)
)
or
// Block flow to any binary instruction whose operands are both non-constants.
exists(BinaryInstruction iTo |
iTo = node.asInstruction() and
not constantInstruction(iTo.getLeft()) and
not constantInstruction(iTo.getRight()) and
// propagate taint from either the pointer or the offset, regardless of constantness
not iTo instanceof PointerArithmeticInstruction
)
}
}
module Flow = TaintTracking::Global<Config>;
from DataFlow::Node source, DataFlow::Node sink, VariableAccess va, string cause, string effect
where
Flow::flow(source, sink) and
isSource(source, cause) and
causeEffectCorrespond(cause, effect) and
isSink(sink, va, effect)
select va,
"$@ flows to an operand of an arithmetic expression, potentially causing an " + effect + ".",
origin, "Extreme value"
source, "Extreme value"

Просмотреть файл

@ -15,7 +15,11 @@
import cpp
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
import semmle.code.cpp.ir.dataflow.internal.DefaultTaintTrackingImpl
import semmle.code.cpp.dataflow.new.DataFlow
import semmle.code.cpp.security.FlowSources as FS
import semmle.code.cpp.dataflow.new.TaintTracking
import semmle.code.cpp.ir.IR
import semmle.code.cpp.controlflow.IRGuards as IRGuards
/** Holds if `expr` might overflow. */
predicate outOfBoundsExpr(Expr expr, string kind) {
@ -27,13 +31,76 @@ predicate outOfBoundsExpr(Expr expr, string kind) {
else none()
}
from Expr use, Expr origin, string kind
predicate isSource(FS::FlowSource source, string sourceType) { sourceType = source.getSourceType() }
predicate isSink(DataFlow::Node sink, string kind) {
exists(Expr use |
use = sink.asExpr() and
not use.getUnspecifiedType() instanceof PointerType and
outOfBoundsExpr(use, kind) and
not inSystemMacroExpansion(use)
)
}
predicate hasUpperBoundsCheck(Variable var) {
exists(RelationalOperation oper, VariableAccess access |
oper.getAnOperand() = access and
access.getTarget() = var and
// Comparing to 0 is not an upper bound check
not oper.getAnOperand().getValue() = "0"
)
}
predicate constantInstruction(Instruction instr) {
instr instanceof ConstantInstruction or
constantInstruction(instr.(UnaryInstruction).getUnary())
}
predicate readsVariable(LoadInstruction load, Variable var) {
load.getSourceAddress().(VariableAddressInstruction).getAstVariable() = var
}
predicate nodeIsBarrierEqualityCandidate(DataFlow::Node node, Operand access, Variable checkedVar) {
exists(Instruction instr | instr = node.asInstruction() |
readsVariable(instr, checkedVar) and
any(IRGuards::IRGuardCondition guard).ensuresEq(access, _, _, instr.getBlock(), true)
)
}
module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { isSource(source, _) }
predicate isSink(DataFlow::Node sink) { isSink(sink, _) }
predicate isBarrier(DataFlow::Node node) {
// Block flow if there's an upper bound check of the variable anywhere in the program
exists(Variable checkedVar, Instruction instr | instr = node.asInstruction() |
readsVariable(instr, checkedVar) and
hasUpperBoundsCheck(checkedVar)
)
or
// Block flow if the node is guarded by an equality check
exists(Variable checkedVar, Operand access |
nodeIsBarrierEqualityCandidate(node, access, checkedVar) and
readsVariable(access.getDef(), checkedVar)
)
or
// Block flow to any binary instruction whose operands are both non-constants.
exists(BinaryInstruction iTo |
iTo = node.asInstruction() and
not constantInstruction(iTo.getLeft()) and
not constantInstruction(iTo.getRight()) and
// propagate taint from either the pointer or the offset, regardless of constantness
not iTo instanceof PointerArithmeticInstruction
)
}
}
module Flow = TaintTracking::Global<Config>;
from DataFlow::Node source, DataFlow::Node sink, string kind, string sourceType
where
not use.getUnspecifiedType() instanceof PointerType and
outOfBoundsExpr(use, kind) and
tainted(origin, use) and
origin != use and
not inSystemMacroExpansion(use) and
// Avoid double-counting: don't include all the conversions of `use`.
not use instanceof Conversion
select use, "$@ flows an expression which might " + kind + ".", origin, "User-provided value"
Flow::flow(source, sink) and
isSource(source, sourceType) and
isSink(sink, kind)
select sink, "$@ flows an expression which might " + kind + ".", source, sourceType

Просмотреть файл

@ -4,6 +4,7 @@
* @description The total number of lines of C/C++ code across all files, including system headers, libraries, and auto-generated files. This is a useful metric of the size of a database. For all files that were seen during the build, this query counts the lines of code, excluding whitespace or comments.
* @kind metric
* @tags summary
* telemetry
*/
import cpp

Просмотреть файл

@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Added SQL API models for `ODBC`.

Просмотреть файл

@ -0,0 +1,4 @@
---
category: breaking
---
* The `cpp/tainted-format-string-through-global` query has been deleted. This does not lead to a loss of relevant alerts, as the query duplicated a subset of the alerts from `cpp/tainted-format-string`.

Просмотреть файл

@ -1,4 +1,5 @@
---
category: minorAnalysis
---
## 0.8.3
### Minor Analysis Improvements
* The `cpp/uninitialized-local` query has been improved to produce fewer false positives.

Просмотреть файл

@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.8.2
lastReleaseVersion: 0.8.3

Просмотреть файл

@ -4,7 +4,6 @@
* @kind problem
* @id cpp/quantum-readiness/cbom/all-asymmetric-algorithms
* @problem.severity error
* @precision high
* @tags cbom
* cryptography
*/

Просмотреть файл

@ -4,7 +4,6 @@
* @kind problem
* @id cpp/quantum-readiness/cbom/all-cryptographic-algorithms
* @problem.severity error
* @precision high
* @tags cbom
* cryptography
*/

Просмотреть файл

@ -4,7 +4,6 @@
* @kind problem
* @id cpp/quantum-readiness/cbom/all-asymmetric-encryption-algorithms
* @problem.severity error
* @precision high
* @tags cbom
* cryptography
*/

Просмотреть файл

@ -4,7 +4,6 @@
* @kind problem
* @id cpp/quantum-readiness/cbom/authenticated-encryption-algorithms
* @problem.severity error
* @precision high
* @tags cbom
* cryptography
*/

Просмотреть файл

@ -4,7 +4,6 @@
* @kind problem
* @id cpp/quantum-readiness/cbom/block-cipher-mode
* @problem.severity error
* @precision high
* @tags cbom
* cryptography
*/

Просмотреть файл

@ -4,7 +4,6 @@
* @kind problem
* @id cpp/quantum-readiness/cbom/iv-sources
* @problem.severity error
* @precision high
* @tags cbom
* cryptography
*/

Просмотреть файл

@ -4,7 +4,6 @@
* @kind problem
* @id cpp/quantum-readiness/cbom/unkown-iv-sources
* @problem.severity error
* @precision high
* @tags cbom
* cryptography
*/

Просмотреть файл

@ -4,7 +4,6 @@
* @kind problem
* @id cpp/quantum-readiness/cbom/elliptic-curve-key-length
* @problem.severity error
* @precision high
* @tags cbom
* cryptography
*/

Просмотреть файл

@ -4,7 +4,6 @@
* @kind problem
* @id cpp/quantum-readiness/cbom/elliptic-curve-algorithms
* @problem.severity error
* @precision high
* @tags cbom
* cryptography
*/

Просмотреть файл

@ -4,7 +4,6 @@
* @kind problem
* @id cpp/quantum-readiness/cbom/hash-algorithms
* @problem.severity error
* @precision high
* @tags cbom
* cryptography
*/

Просмотреть файл

@ -4,7 +4,6 @@
* @kind problem
* @id cpp/quantum-readiness/cbom/key-exchange
* @problem.severity error
* @precision high
* @tags cbom
* cryptography
*/

Просмотреть файл

@ -4,7 +4,6 @@
* @kind problem
* @id cpp/quantum-readiness/cbom/asymmetric-key-generation
* @problem.severity error
* @precision high
* @tags cbom
* cryptography
*/

Просмотреть файл

@ -4,7 +4,6 @@
* @kind problem
* @id cpp/quantum-readiness/cbom/signing-algorithms
* @problem.severity error
* @precision high
* @tags cbom
* cryptography
*/

Просмотреть файл

@ -4,7 +4,6 @@
* @kind problem
* @id cpp/quantum-readiness/cbom/symmetric-encryption-algorithms
* @problem.severity error
* @precision high
* @tags cbom
* cryptography
*/

Просмотреть файл

@ -4,7 +4,6 @@
* @kind problem
* @id cpp/quantum-readiness/cbom/unkwon-asymmetric-key-generation
* @problem.severity error
* @precision high
* @tags cbom
* cryptography
*/

Просмотреть файл

@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 0.8.3-dev
version: 0.8.4-dev
groups:
- cpp
- queries

Просмотреть файл

@ -0,0 +1,111 @@
module AstTest {
import semmle.code.cpp.dataflow.DataFlow
private import semmle.code.cpp.controlflow.Guards
/**
* A `BarrierGuard` that stops flow to all occurrences of `x` within statement
* S in `if (guarded(x)) S`.
*/
// This is tested in `BarrierGuard.cpp`.
predicate testBarrierGuard(GuardCondition g, Expr checked, boolean isTrue) {
g.(FunctionCall).getTarget().getName() = "guarded" and
checked = g.(FunctionCall).getArgument(0) and
isTrue = true
}
/** Common data flow configuration to be used by tests. */
module AstTestAllocationConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.asExpr().(FunctionCall).getTarget().getName() = "source"
or
source.asParameter().getName().matches("source%")
or
source.asExpr().(FunctionCall).getTarget().getName() = "indirect_source"
or
source.(DataFlow::DefinitionByReferenceNode).getParameter().getName().matches("ref_source%")
or
// Track uninitialized variables
exists(source.asUninitialized())
}
predicate isSink(DataFlow::Node sink) {
exists(FunctionCall call |
call.getTarget().getName() = ["sink", "indirect_sink"] and
sink.asExpr() = call.getAnArgument()
)
}
predicate isBarrier(DataFlow::Node barrier) {
barrier.asExpr().(VariableAccess).getTarget().hasName("barrier") or
barrier = DataFlow::BarrierGuard<testBarrierGuard/3>::getABarrierNode()
}
}
module AstFlow = DataFlow::Global<AstTestAllocationConfig>;
}
module IRTest {
private import cpp
import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.controlflow.IRGuards
/**
* A `BarrierGuard` that stops flow to all occurrences of `x` within statement
* S in `if (guarded(x)) S`.
*/
// This is tested in `BarrierGuard.cpp`.
predicate testBarrierGuard(IRGuardCondition g, Expr checked, boolean isTrue) {
exists(Call call |
call = g.getUnconvertedResultExpression() and
call.getTarget().hasName("guarded") and
checked = call.getArgument(0) and
isTrue = true
)
}
/** Common data flow configuration to be used by tests. */
module IRTestAllocationConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.asExpr().(FunctionCall).getTarget().getName() = "source"
or
source.asIndirectExpr(1).(FunctionCall).getTarget().getName() = "indirect_source"
or
source.asExpr().(StringLiteral).getValue() = "source"
or
// indirect_source(n) gives the dataflow node representing the indirect node after n dereferences.
exists(int n, string s |
n = s.regexpCapture("indirect_source\\((\\d)\\)", 1).toInt() and
source.asIndirectExpr(n).(StringLiteral).getValue() = s
)
or
source.asParameter().getName().matches("source%")
or
source.(DataFlow::DefinitionByReferenceNode).getParameter().getName().matches("ref_source%")
or
exists(source.asUninitialized())
}
predicate isSink(DataFlow::Node sink) {
exists(FunctionCall call, Expr e | e = call.getAnArgument() |
call.getTarget().getName() = "sink" and
sink.asExpr() = e
or
call.getTarget().getName() = "indirect_sink" and
sink.asIndirectExpr() = e
)
}
predicate isBarrier(DataFlow::Node barrier) {
exists(Expr barrierExpr | barrierExpr in [barrier.asExpr(), barrier.asIndirectExpr()] |
barrierExpr.(VariableAccess).getTarget().hasName("barrier")
)
or
barrier = DataFlow::BarrierGuard<testBarrierGuard/3>::getABarrierNode()
or
barrier = DataFlow::BarrierGuard<testBarrierGuard/3>::getAnIndirectBarrierNode()
}
}
module IRFlow = DataFlow::Global<IRTestAllocationConfig>;
}

Просмотреть файл

@ -1,5 +1,11 @@
uniqueEnclosingCallable
| test.cpp:864:44:864:58 | {...} | Node should have one enclosing callable but has 0. |
| test.cpp:864:47:864:54 | call to source | Node should have one enclosing callable but has 0. |
| test.cpp:872:46:872:51 | call to source | Node should have one enclosing callable but has 0. |
| test.cpp:872:53:872:56 | 1 | Node should have one enclosing callable but has 0. |
uniqueCallEnclosingCallable
| test.cpp:864:47:864:54 | call to source | Call should have one enclosing callable but has 0. |
| test.cpp:872:46:872:51 | call to source | Call should have one enclosing callable but has 0. |
uniqueType
uniqueNodeLocation
missingLocation
@ -24,6 +30,7 @@ argHasPostUpdate
| lambdas.cpp:45:2:45:2 | e | ArgumentNode is missing PostUpdateNode. |
| test.cpp:67:29:67:35 | source1 | ArgumentNode is missing PostUpdateNode. |
| test.cpp:813:19:813:35 | * ... | ArgumentNode is missing PostUpdateNode. |
| test.cpp:848:23:848:25 | rpx | ArgumentNode is missing PostUpdateNode. |
postWithInFlow
| BarrierGuard.cpp:49:6:49:6 | x [post update] | PostUpdateNode should not be the target of local flow. |
| BarrierGuard.cpp:60:7:60:7 | x [post update] | PostUpdateNode should not be the target of local flow. |

Просмотреть файл

@ -0,0 +1,306 @@
WARNING: Module DataFlow has been deprecated and may be removed in future (test-source-sink.ql:3,25-42)
WARNING: Module DataFlow has been deprecated and may be removed in future (test-source-sink.ql:3,57-74)
astFlow
| BarrierGuard.cpp:5:19:5:24 | source | BarrierGuard.cpp:9:10:9:15 | source |
| BarrierGuard.cpp:13:17:13:22 | source | BarrierGuard.cpp:15:10:15:15 | source |
| BarrierGuard.cpp:21:17:21:22 | source | BarrierGuard.cpp:25:10:25:15 | source |
| BarrierGuard.cpp:29:16:29:21 | source | BarrierGuard.cpp:31:10:31:15 | source |
| BarrierGuard.cpp:29:16:29:21 | source | BarrierGuard.cpp:33:10:33:15 | source |
| BarrierGuard.cpp:49:10:49:15 | call to source | BarrierGuard.cpp:51:13:51:13 | x |
| BarrierGuard.cpp:49:10:49:15 | call to source | BarrierGuard.cpp:53:13:53:13 | x |
| 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: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 |
| 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 | & ... |
| clang.cpp:12:9:12:20 | sourceArray1 | clang.cpp:23:17:23:29 | & ... |
| clang.cpp:29:27:29:32 | call to source | clang.cpp:30:27:30:28 | m1 |
| clang.cpp:29:27:29:32 | call to source | clang.cpp:31:27:31:34 | call to getFirst |
| clang.cpp:35:32:35:37 | call to source | clang.cpp:38:10:38:11 | m2 |
| clang.cpp:44:35:44:40 | call to source | clang.cpp:46:17:46:18 | m2 |
| clang.cpp:51:19:51:24 | call to source | clang.cpp:52:8:52:17 | stackArray |
| clang.cpp:51:19:51:24 | call to source | clang.cpp:53:17:53:26 | stackArray |
| 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 |
| dispatch.cpp:10:37:10:42 | call to source | dispatch.cpp:44:15:44:24 | call to notSource2 |
| dispatch.cpp:37:19:37:24 | call to source | dispatch.cpp:11:38:11:38 | x |
| dispatch.cpp:45:18:45:23 | call to source | dispatch.cpp:11:38:11:38 | x |
| globals.cpp:5:17:5:22 | call to source | globals.cpp:6:10:6:14 | local |
| lambdas.cpp:8:10:8:15 | call to source | lambdas.cpp:14:3:14:6 | t |
| lambdas.cpp:8:10:8:15 | call to source | lambdas.cpp:18:8:18:8 | call to operator() |
| lambdas.cpp:8:10:8:15 | call to source | lambdas.cpp:21:3:21:6 | t |
| lambdas.cpp:8:10:8:15 | call to source | lambdas.cpp:29:3:29:6 | t |
| lambdas.cpp:8:10:8:15 | call to source | lambdas.cpp:35:8:35:8 | a |
| lambdas.cpp:8:10:8:15 | call to source | lambdas.cpp:41:8:41:8 | a |
| lambdas.cpp:43:7:43:12 | call to source | lambdas.cpp:46:7:46:7 | w |
| ref.cpp:29:11:29:16 | call to source | ref.cpp:62:10:62:11 | x3 |
| ref.cpp:53:9:53:10 | x1 | ref.cpp:56:10:56:11 | x1 |
| ref.cpp:53:13:53:14 | x2 | ref.cpp:59:10:59:11 | x2 |
| ref.cpp:53:17:53:18 | x3 | ref.cpp:62:10:62:11 | x3 |
| ref.cpp:53:21:53:22 | x4 | ref.cpp:65:10:65:11 | x4 |
| ref.cpp:55:23:55:28 | call to source | ref.cpp:56:10:56:11 | x1 |
| ref.cpp:94:15:94:20 | call to source | ref.cpp:129:13:129:15 | val |
| ref.cpp:109:15:109:20 | call to source | ref.cpp:132:13:132:15 | val |
| ref.cpp:122:23:122:28 | call to source | ref.cpp:123:13:123:15 | val |
| ref.cpp:125:19:125:24 | call to source | ref.cpp:126:13:126:15 | val |
| self-Iterator.cpp:19:23:19:28 | call to source | self-Iterator.cpp:20:10:20:10 | x |
| test.cpp:6:12:6:17 | call to source | test.cpp:7:8:7:9 | t1 |
| test.cpp:6:12:6:17 | call to source | test.cpp:9:8:9:9 | t1 |
| test.cpp:6:12:6:17 | call to source | test.cpp:10:8:10:9 | t2 |
| test.cpp:6:12:6:17 | call to source | test.cpp:15:8:15:9 | t2 |
| test.cpp:6:12:6:17 | call to source | test.cpp:26:8:26:9 | t1 |
| test.cpp:35:10:35:15 | call to source | test.cpp:30:8:30:8 | t |
| test.cpp:36:13:36:18 | call to source | test.cpp:31:8:31:8 | c |
| test.cpp:50:14:50:19 | call to source | test.cpp:58:10:58:10 | t |
| test.cpp:66:30:66:36 | source1 | test.cpp:71:8:71:9 | x4 |
| test.cpp:75:7:75:8 | u1 | test.cpp:76:8:76:9 | u1 |
| test.cpp:83:7:83:8 | u2 | test.cpp:84:8:84:18 | ... ? ... : ... |
| test.cpp:83:7:83:8 | u2 | test.cpp:86:8:86:9 | i1 |
| test.cpp:89:28:89:34 | source1 | test.cpp:90:8:90:14 | source1 |
| test.cpp:100:13:100:18 | call to source | test.cpp:103:10:103:12 | ref |
| test.cpp:138:27:138:32 | call to source | test.cpp:140:8:140:8 | y |
| test.cpp:151:33:151:38 | call to source | test.cpp:144:8:144:8 | s |
| test.cpp:151:33:151:38 | call to source | test.cpp:152:8:152:8 | y |
| test.cpp:164:34:164:39 | call to source | test.cpp:157:8:157:8 | x |
| test.cpp:164:34:164:39 | call to source | test.cpp:165:8:165:8 | y |
| test.cpp:171:11:171:16 | call to source | test.cpp:178:8:178:8 | y |
| test.cpp:245:14:245:19 | call to source | test.cpp:260:12:260:12 | x |
| test.cpp:265:22:265:27 | call to source | test.cpp:266:12:266:12 | x |
| test.cpp:305:17:305:22 | call to source | test.cpp:289:14:289:14 | x |
| test.cpp:314:4:314:9 | call to source | test.cpp:318:7:318:7 | x |
| test.cpp:347:17:347:22 | call to source | test.cpp:349:10:349:18 | globalVar |
| test.cpp:359:13:359:18 | call to source | test.cpp:365:10:365:14 | field |
| test.cpp:373:13:373:18 | call to source | test.cpp:369:10:369:14 | field |
| test.cpp:373:13:373:18 | call to source | test.cpp:375:10:375:14 | field |
| test.cpp:382:48:382:54 | source1 | test.cpp:385:8:385:10 | tmp |
| test.cpp:388:53:388:59 | source1 | test.cpp:392:8:392:10 | tmp |
| test.cpp:388:53:388:59 | source1 | test.cpp:394:10:394:12 | tmp |
| test.cpp:399:7:399:9 | tmp | test.cpp:401:8:401:10 | tmp |
| test.cpp:405:7:405:9 | tmp | test.cpp:408:8:408:10 | tmp |
| test.cpp:416:7:416:11 | local | test.cpp:418:8:418:12 | local |
| test.cpp:417:16:417:20 | ref arg local | test.cpp:418:8:418:12 | local |
| test.cpp:422:7:422:11 | local | test.cpp:424:8:424:12 | local |
| test.cpp:423:20:423:25 | ref arg & ... | test.cpp:424:8:424:12 | local |
| test.cpp:433:7:433:11 | local | test.cpp:435:8:435:12 | local |
| test.cpp:433:7:433:11 | local | test.cpp:436:8:436:13 | * ... |
| test.cpp:434:20:434:24 | ref arg local | test.cpp:435:8:435:12 | local |
| test.cpp:434:20:434:24 | ref arg local | test.cpp:436:8:436:13 | * ... |
| test.cpp:440:7:440:11 | local | test.cpp:442:8:442:12 | local |
| test.cpp:441:18:441:23 | ref arg & ... | test.cpp:442:8:442:12 | local |
| test.cpp:448:7:448:11 | local | test.cpp:450:8:450:12 | local |
| test.cpp:448:7:448:11 | local | test.cpp:451:8:451:13 | * ... |
| test.cpp:449:18:449:22 | ref arg local | test.cpp:450:8:450:12 | local |
| test.cpp:449:18:449:22 | ref arg local | test.cpp:451:8:451:13 | * ... |
| test.cpp:456:26:456:32 | source1 | test.cpp:457:9:457:22 | (statement expression) |
| test.cpp:456:26:456:32 | source1 | test.cpp:468:8:468:12 | local |
| test.cpp:472:8:472:13 | call to source | test.cpp:478:8:478:8 | x |
| test.cpp:506:8:506:13 | call to source | test.cpp:513:8:513:8 | x |
| test.cpp:517:7:517:16 | stackArray | test.cpp:521:8:521:20 | access to array |
| test.cpp:519:19:519:24 | call to source | test.cpp:521:8:521:20 | access to array |
| test.cpp:551:9:551:9 | y | test.cpp:541:10:541:10 | y |
| test.cpp:583:11:583:16 | call to source | test.cpp:590:8:590:8 | x |
| test.cpp:628:20:628:25 | ref arg buffer | test.cpp:629:17:629:22 | buffer |
| test.cpp:633:18:633:23 | call to source | test.cpp:634:8:634:8 | x |
| test.cpp:702:38:702:43 | source | test.cpp:695:8:695:10 | buf |
| test.cpp:726:11:726:16 | call to source | test.cpp:735:8:735:8 | x |
| test.cpp:733:7:733:7 | x | test.cpp:735:8:735:8 | x |
| test.cpp:749:27:749:32 | call to source | test.cpp:740:10:740:10 | x |
| test.cpp:751:27:751:32 | call to source | test.cpp:740:10:740:10 | x |
| test.cpp:753:32:753:37 | call to source | test.cpp:740:10:740:10 | x |
| test.cpp:755:32:755:37 | call to source | test.cpp:740:10:740:10 | x |
| test.cpp:769:27:769:32 | call to source | test.cpp:760:10:760:10 | x |
| test.cpp:771:27:771:32 | call to source | test.cpp:760:10:760:10 | x |
| test.cpp:773:32:773:37 | call to source | test.cpp:760:10:760:10 | x |
| test.cpp:775:32:775:37 | call to source | test.cpp:760:10:760:10 | x |
| test.cpp:788:31:788:36 | call to source | test.cpp:782:12:782:12 | x |
| test.cpp:790:31:790:36 | call to source | test.cpp:782:12:782:12 | x |
| test.cpp:797:22:797:28 | ref arg content | test.cpp:798:19:798:25 | content |
| test.cpp:842:11:842:16 | call to source | test.cpp:844:8:844:8 | y |
| test.cpp:846:13:846:27 | call to indirect_source | test.cpp:848:23:848:25 | rpx |
| test.cpp:860:54:860:59 | call to source | test.cpp:861:10:861:37 | static_local_pointer_dynamic |
| true_upon_entry.cpp:17:11:17:16 | call to source | true_upon_entry.cpp:21:8:21:8 | x |
| true_upon_entry.cpp:27:9:27:14 | call to source | true_upon_entry.cpp:29:8:29:8 | x |
| true_upon_entry.cpp:33:11:33:16 | call to source | true_upon_entry.cpp:39:8:39:8 | x |
| true_upon_entry.cpp:43:11:43:16 | call to source | true_upon_entry.cpp:49:8:49:8 | x |
| true_upon_entry.cpp:54:11:54:16 | call to source | true_upon_entry.cpp:57:8:57:8 | x |
| true_upon_entry.cpp:70:11:70:16 | call to source | true_upon_entry.cpp:78:8:78:8 | x |
| true_upon_entry.cpp:83:11:83:16 | call to source | true_upon_entry.cpp:86:8:86:8 | x |
irFlow
| BarrierGuard.cpp:5:19:5:24 | source | BarrierGuard.cpp:9:10:9:15 | source |
| BarrierGuard.cpp:13:17:13:22 | source | BarrierGuard.cpp:15:10:15:15 | source |
| BarrierGuard.cpp:21:17:21:22 | source | BarrierGuard.cpp:25:10:25:15 | source |
| BarrierGuard.cpp:29:16:29:21 | source | BarrierGuard.cpp:31:10:31:15 | source |
| BarrierGuard.cpp:29:16:29:21 | source | BarrierGuard.cpp:33:10:33:15 | source |
| BarrierGuard.cpp:49:10:49:15 | call to source | BarrierGuard.cpp:53:13:53:13 | x |
| 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 |
| 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 | & ... indirection |
| clang.cpp:29:27:29:32 | call to source | clang.cpp:30:27:30:28 | m1 |
| clang.cpp:29:27:29:32 | call to source | clang.cpp:31:27:31:34 | call to getFirst |
| clang.cpp:35:32:35:37 | call to source | clang.cpp:38:10:38:11 | m2 |
| clang.cpp:40:42:40:47 | call to source | clang.cpp:42:18:42:19 | m2 |
| clang.cpp:44:35:44:40 | call to source | clang.cpp:46:17:46:18 | m2 |
| clang.cpp:50:7:50:16 | definition of stackArray | clang.cpp:52:8:52:17 | stackArray |
| clang.cpp:50:25:50:30 | call to source | clang.cpp:53:17:53:26 | stackArray indirection |
| clang.cpp:50:35:50:40 | call to source | clang.cpp:53:17:53:26 | stackArray indirection |
| clang.cpp:51:19:51:24 | call to source | clang.cpp:53:17:53:26 | stackArray indirection |
| 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 |
| dispatch.cpp:10:37:10:42 | call to source | dispatch.cpp:44:15:44:24 | call to notSource2 |
| dispatch.cpp:16:37:16:42 | call to source | dispatch.cpp:32:16:32:24 | call to isSource2 |
| dispatch.cpp:16:37:16:42 | call to source | dispatch.cpp:40:15:40:23 | call to isSource2 |
| dispatch.cpp:22:37:22:42 | call to source | dispatch.cpp:31:16:31:24 | call to isSource1 |
| dispatch.cpp:22:37:22:42 | call to source | dispatch.cpp:39:15:39:23 | call to isSource1 |
| dispatch.cpp:22:37:22:42 | call to source | dispatch.cpp:55:22:55:30 | call to isSource1 |
| dispatch.cpp:22:37:22:42 | call to source | dispatch.cpp:58:28:58:36 | call to isSource1 |
| dispatch.cpp:33:18:33:23 | call to source | dispatch.cpp:23:38:23:38 | x |
| dispatch.cpp:37:19:37:24 | call to source | dispatch.cpp:11:38:11:38 | x |
| dispatch.cpp:41:17:41:22 | call to source | dispatch.cpp:23:38:23:38 | x |
| dispatch.cpp:45:18:45:23 | call to source | dispatch.cpp:11:38:11:38 | x |
| dispatch.cpp:69:15:69:20 | call to source | dispatch.cpp:23:38:23:38 | x |
| dispatch.cpp:73:14:73:19 | call to source | dispatch.cpp:23:38:23:38 | x |
| dispatch.cpp:81:13:81:18 | call to source | dispatch.cpp:23:38:23:38 | x |
| dispatch.cpp:107:17:107:22 | call to source | dispatch.cpp:96:8:96:8 | x |
| dispatch.cpp:140:8:140:13 | call to source | dispatch.cpp:96:8:96:8 | x |
| dispatch.cpp:144:8:144:13 | call to source | dispatch.cpp:96:8:96:8 | x |
| flowOut.cpp:5:16:5:21 | call to source | flowOut.cpp:19:9:19:9 | x |
| globals.cpp:5:17:5:22 | call to source | globals.cpp:6:10:6:14 | local |
| globals.cpp:13:23:13:28 | call to source | globals.cpp:12:10:12:24 | flowTestGlobal1 |
| globals.cpp:23:23:23:28 | call to source | globals.cpp:19:10:19:24 | flowTestGlobal2 |
| lambdas.cpp:8:10:8:15 | call to source | lambdas.cpp:14:8:14:8 | t |
| lambdas.cpp:8:10:8:15 | call to source | lambdas.cpp:18:8:18:8 | call to operator() |
| lambdas.cpp:8:10:8:15 | call to source | lambdas.cpp:21:8:21:8 | t |
| lambdas.cpp:8:10:8:15 | call to source | lambdas.cpp:29:8:29:8 | t |
| lambdas.cpp:8:10:8:15 | call to source | lambdas.cpp:35:8:35:8 | a |
| lambdas.cpp:8:10:8:15 | call to source | lambdas.cpp:41:8:41:8 | a |
| lambdas.cpp:43:7:43:12 | call to source | lambdas.cpp:46:7:46:7 | w |
| ref.cpp:29:11:29:16 | call to source | ref.cpp:62:10:62:11 | x3 |
| ref.cpp:53:9:53:10 | definition of x1 | ref.cpp:56:10:56:11 | x1 |
| ref.cpp:53:13:53:14 | definition of x2 | ref.cpp:59:10:59:11 | x2 |
| ref.cpp:53:17:53:18 | definition of x3 | ref.cpp:62:10:62:11 | x3 |
| ref.cpp:53:21:53:22 | definition of x4 | ref.cpp:65:10:65:11 | x4 |
| ref.cpp:55:23:55:28 | call to source | ref.cpp:56:10:56:11 | x1 |
| ref.cpp:94:15:94:20 | call to source | ref.cpp:129:13:129:15 | val |
| ref.cpp:109:15:109:20 | call to source | ref.cpp:132:13:132:15 | val |
| ref.cpp:122:23:122:28 | call to source | ref.cpp:123:13:123:15 | val |
| ref.cpp:125:19:125:24 | call to source | ref.cpp:126:13:126:15 | val |
| self-Iterator.cpp:19:23:19:30 | call to source | self-Iterator.cpp:20:10:20:10 | x |
| test.cpp:6:12:6:17 | call to source | test.cpp:7:8:7:9 | t1 |
| test.cpp:6:12:6:17 | call to source | test.cpp:9:8:9:9 | t1 |
| test.cpp:6:12:6:17 | call to source | test.cpp:10:8:10:9 | t2 |
| test.cpp:6:12:6:17 | call to source | test.cpp:15:8:15:9 | t2 |
| test.cpp:6:12:6:17 | call to source | test.cpp:26:8:26:9 | t1 |
| test.cpp:35:10:35:15 | call to source | test.cpp:30:8:30:8 | t |
| test.cpp:36:13:36:18 | call to source | test.cpp:31:8:31:8 | c |
| test.cpp:50:14:50:19 | call to source | test.cpp:58:10:58:10 | t |
| test.cpp:66:30:66:36 | source1 | test.cpp:71:8:71:9 | x4 |
| test.cpp:75:7:75:8 | definition of u1 | test.cpp:76:8:76:9 | u1 |
| test.cpp:83:7:83:8 | definition of u2 | test.cpp:84:8:84:18 | ... ? ... : ... |
| test.cpp:83:7:83:8 | definition of u2 | test.cpp:86:8:86:9 | i1 |
| test.cpp:89:28:89:34 | source1 indirection | test.cpp:90:8:90:14 | source1 |
| test.cpp:100:13:100:18 | call to source | test.cpp:103:10:103:12 | ref |
| test.cpp:138:27:138:32 | call to source | test.cpp:140:8:140:8 | y |
| test.cpp:151:33:151:38 | call to source | test.cpp:144:8:144:8 | s |
| test.cpp:151:33:151:38 | call to source | test.cpp:152:8:152:8 | y |
| test.cpp:164:34:164:39 | call to source | test.cpp:157:8:157:8 | x |
| test.cpp:164:34:164:39 | call to source | test.cpp:165:8:165:8 | y |
| test.cpp:171:11:171:16 | call to source | test.cpp:178:8:178:8 | y |
| test.cpp:245:14:245:19 | call to source | test.cpp:260:12:260:12 | x |
| test.cpp:265:22:265:27 | call to source | test.cpp:266:12:266:12 | x |
| test.cpp:305:17:305:22 | call to source | test.cpp:289:14:289:14 | x |
| test.cpp:314:4:314:9 | call to source | test.cpp:318:7:318:7 | x |
| test.cpp:333:17:333:22 | call to source | test.cpp:337:10:337:18 | globalVar |
| test.cpp:333:17:333:22 | call to source | test.cpp:339:10:339:18 | globalVar |
| test.cpp:333:17:333:22 | call to source | test.cpp:343:10:343:18 | globalVar |
| test.cpp:333:17:333:22 | call to source | test.cpp:349:10:349:18 | globalVar |
| test.cpp:347:17:347:22 | call to source | test.cpp:337:10:337:18 | globalVar |
| test.cpp:347:17:347:22 | call to source | test.cpp:339:10:339:18 | globalVar |
| test.cpp:347:17:347:22 | call to source | test.cpp:343:10:343:18 | globalVar |
| test.cpp:347:17:347:22 | call to source | test.cpp:349:10:349:18 | globalVar |
| test.cpp:359:13:359:18 | call to source | test.cpp:365:10:365:14 | field |
| test.cpp:373:13:373:18 | call to source | test.cpp:369:10:369:14 | field |
| test.cpp:373:13:373:18 | call to source | test.cpp:375:10:375:14 | field |
| test.cpp:382:48:382:54 | source1 | test.cpp:385:8:385:10 | tmp |
| test.cpp:388:53:388:59 | source1 | test.cpp:392:8:392:10 | tmp |
| test.cpp:388:53:388:59 | source1 | test.cpp:394:10:394:12 | tmp |
| test.cpp:399:7:399:9 | definition of tmp | test.cpp:401:8:401:10 | tmp |
| test.cpp:405:7:405:9 | definition of tmp | test.cpp:408:8:408:10 | tmp |
| test.cpp:416:7:416:11 | definition of local | test.cpp:418:8:418:12 | local |
| test.cpp:417:16:417:20 | intRefSource output argument | test.cpp:418:8:418:12 | local |
| test.cpp:422:7:422:11 | definition of local | test.cpp:424:8:424:12 | local |
| test.cpp:423:20:423:25 | intPointerSource output argument | test.cpp:424:8:424:12 | local |
| test.cpp:433:7:433:11 | definition of local | test.cpp:435:8:435:12 | local |
| test.cpp:434:20:434:24 | intPointerSource output argument | test.cpp:436:8:436:13 | * ... |
| test.cpp:440:7:440:11 | definition of local | test.cpp:442:8:442:12 | local |
| test.cpp:441:18:441:23 | intArraySource output argument | test.cpp:442:8:442:12 | local |
| test.cpp:448:7:448:11 | definition of local | test.cpp:450:8:450:12 | local |
| test.cpp:449:18:449:22 | intArraySource output argument | test.cpp:451:8:451:13 | * ... |
| test.cpp:456:26:456:32 | source1 | test.cpp:457:9:457:22 | (statement expression) |
| test.cpp:456:26:456:32 | source1 | test.cpp:468:8:468:12 | local |
| test.cpp:472:8:472:13 | call to source | test.cpp:478:8:478:8 | x |
| test.cpp:506:8:506:13 | call to source | test.cpp:513:8:513:8 | x |
| test.cpp:519:19:519:24 | call to source | test.cpp:521:8:521:20 | access to array |
| test.cpp:531:29:531:34 | call to source | test.cpp:532:8:532:9 | * ... |
| test.cpp:547:9:547:9 | definition of x | test.cpp:536:10:536:11 | * ... |
| test.cpp:551:9:551:9 | definition of y | test.cpp:541:10:541:10 | y |
| test.cpp:562:17:562:31 | call to indirect_source indirection | test.cpp:566:10:566:19 | * ... |
| test.cpp:562:17:562:31 | call to indirect_source indirection | test.cpp:568:10:568:19 | * ... |
| test.cpp:562:17:562:31 | call to indirect_source indirection | test.cpp:572:10:572:19 | * ... |
| test.cpp:562:17:562:31 | call to indirect_source indirection | test.cpp:578:10:578:19 | * ... |
| test.cpp:576:17:576:31 | call to indirect_source indirection | test.cpp:566:10:566:19 | * ... |
| test.cpp:576:17:576:31 | call to indirect_source indirection | test.cpp:568:10:568:19 | * ... |
| test.cpp:576:17:576:31 | call to indirect_source indirection | test.cpp:572:10:572:19 | * ... |
| test.cpp:576:17:576:31 | call to indirect_source indirection | test.cpp:578:10:578:19 | * ... |
| test.cpp:594:12:594:26 | call to indirect_source indirection | test.cpp:597:8:597:13 | * ... |
| test.cpp:601:20:601:20 | intPointerSource output argument | test.cpp:603:8:603:9 | * ... |
| test.cpp:607:20:607:20 | intPointerSource output argument | test.cpp:609:8:609:9 | * ... |
| test.cpp:614:20:614:20 | intPointerSource output argument | test.cpp:616:8:616:17 | * ... |
| test.cpp:628:20:628:25 | intPointerSource output argument | test.cpp:629:17:629:22 | buffer indirection |
| test.cpp:633:18:633:23 | call to source | test.cpp:634:8:634:8 | x |
| test.cpp:646:7:646:12 | call to source | test.cpp:645:8:645:8 | x |
| test.cpp:660:7:660:12 | call to source | test.cpp:658:8:658:8 | x |
| test.cpp:664:18:664:23 | call to source | test.cpp:666:8:666:16 | * ... |
| test.cpp:681:7:681:12 | call to source | test.cpp:679:8:679:16 | * ... |
| test.cpp:733:7:733:7 | definition of x | test.cpp:735:8:735:8 | x |
| test.cpp:751:27:751:32 | call to source | test.cpp:740:10:740:10 | x |
| test.cpp:753:32:753:37 | call to source | test.cpp:740:10:740:10 | x |
| test.cpp:755:32:755:37 | call to source | test.cpp:740:10:740:10 | x |
| test.cpp:771:27:771:32 | call to source | test.cpp:760:10:760:10 | x |
| test.cpp:773:32:773:37 | call to source | test.cpp:760:10:760:10 | x |
| test.cpp:775:32:775:37 | call to source | test.cpp:760:10:760:10 | x |
| test.cpp:788:31:788:36 | call to source | test.cpp:782:12:782:12 | x |
| test.cpp:790:31:790:36 | call to source | test.cpp:782:12:782:12 | x |
| test.cpp:797:22:797:28 | intPointerSource output argument | test.cpp:798:19:798:25 | content indirection |
| test.cpp:808:25:808:39 | call to indirect_source indirection | test.cpp:813:19:813:35 | * ... indirection |
| test.cpp:818:26:818:31 | call to source | test.cpp:823:10:823:27 | * ... |
| test.cpp:832:21:832:26 | call to source | test.cpp:836:10:836:22 | global_direct |
| test.cpp:842:11:842:16 | call to source | test.cpp:844:8:844:8 | y |
| test.cpp:846:13:846:27 | call to indirect_source indirection | test.cpp:848:17:848:25 | rpx indirection |
| test.cpp:853:55:853:62 | call to source | test.cpp:854:10:854:36 | * ... |
| test.cpp:860:54:860:59 | call to source | test.cpp:861:10:861:37 | static_local_pointer_dynamic |
| test.cpp:872:46:872:51 | call to source | test.cpp:875:10:875:31 | global_pointer_dynamic |
| test.cpp:880:64:880:83 | indirect_source(1) indirection | test.cpp:883:10:883:45 | static_local_array_static_indirect_1 |
| test.cpp:881:64:881:83 | indirect_source(2) indirection | test.cpp:886:19:886:54 | static_local_array_static_indirect_2 indirection |
| test.cpp:890:54:890:61 | source | test.cpp:893:10:893:36 | static_local_pointer_static |
| test.cpp:891:65:891:84 | indirect_source(1) indirection | test.cpp:895:19:895:56 | static_local_pointer_static_indirect_1 indirection |
| test.cpp:901:56:901:75 | indirect_source(1) indirection | test.cpp:907:10:907:39 | global_array_static_indirect_1 |
| test.cpp:902:56:902:75 | indirect_source(2) indirection | test.cpp:911:19:911:48 | global_array_static_indirect_2 indirection |
| test.cpp:914:46:914:53 | source | test.cpp:919:10:919:30 | global_pointer_static |
| test.cpp:915:57:915:76 | indirect_source(1) indirection | test.cpp:921:19:921:50 | global_pointer_static_indirect_1 indirection |
| true_upon_entry.cpp:9:11:9:16 | call to source | true_upon_entry.cpp:13:8:13:8 | x |
| true_upon_entry.cpp:17:11:17:16 | call to source | true_upon_entry.cpp:21:8:21:8 | x |
| true_upon_entry.cpp:27:9:27:14 | call to source | true_upon_entry.cpp:29:8:29:8 | x |
| true_upon_entry.cpp:33:11:33:16 | call to source | true_upon_entry.cpp:39:8:39:8 | x |
| true_upon_entry.cpp:43:11:43:16 | call to source | true_upon_entry.cpp:49:8:49:8 | x |
| true_upon_entry.cpp:54:11:54:16 | call to source | true_upon_entry.cpp:57:8:57:8 | x |
| true_upon_entry.cpp:62:11:62:16 | call to source | true_upon_entry.cpp:66:8:66:8 | x |
| true_upon_entry.cpp:70:11:70:16 | call to source | true_upon_entry.cpp:78:8:78:8 | x |
| true_upon_entry.cpp:83:11:83:16 | call to source | true_upon_entry.cpp:86:8:86:8 | x |
| true_upon_entry.cpp:98:11:98:16 | call to source | true_upon_entry.cpp:105:8:105:8 | x |

Просмотреть файл

@ -0,0 +1,9 @@
import TestBase
query predicate astFlow(AstTest::DataFlow::Node source, AstTest::DataFlow::Node sink) {
AstTest::AstFlow::flow(source, sink)
}
query predicate irFlow(IRTest::DataFlow::Node source, IRTest::DataFlow::Node sink) {
IRTest::IRFlow::flow(source, sink)
}

Просмотреть файл

@ -1,5 +1,5 @@
int source();
void sink(int); void sink(const int *); void sink(int **); void indirect_sink(...);
void sink(...); void indirect_sink(...);
void intraprocedural_with_local_flow() {
int t2;
@ -836,4 +836,90 @@ namespace MoreGlobalTests {
sink(global_direct); // $ ir MISSING: ast
indirect_sink(global_direct); // clean
}
}
void test_references() {
int x = source();
int &y = x;
sink(y); // $ ast,ir
int* px = indirect_source();
int*& rpx = px;
indirect_sink((int*)rpx); // $ ast,ir
}
namespace GlobalArrays {
void test1() {
static const int static_local_array_dynamic[] = { ::source() };
sink(*static_local_array_dynamic); // $ ir MISSING: ast
}
const int* source(bool);
void test2() {
static const int* static_local_pointer_dynamic = source(true);
sink(static_local_pointer_dynamic); // $ ast,ir
}
static const int global_array_dynamic[] = { ::source() };
void test3() {
sink(*global_array_dynamic); // $ MISSING: ir,ast // Missing in IR because no 'IRFunction' for global_array is generated because the type of global_array_dynamic is "deeply const".
}
const int* source(bool);
static const int* global_pointer_dynamic = source(true);
void test4() {
sink(global_pointer_dynamic); // $ ir MISSING: ast
}
void test5() {
static const char static_local_array_static[] = "source";
static const char static_local_array_static_indirect_1[] = "indirect_source(1)";
static const char static_local_array_static_indirect_2[] = "indirect_source(2)";
sink(static_local_array_static); // clean
sink(static_local_array_static_indirect_1); // $ ir MISSING: ast
indirect_sink(static_local_array_static_indirect_1); // clean
sink(static_local_array_static_indirect_2); // clean
indirect_sink(static_local_array_static_indirect_2); // $ ir MISSING: ast
}
void test6() {
static const char* static_local_pointer_static = "source";
static const char* static_local_pointer_static_indirect_1 = "indirect_source(1)";
static const char* static_local_pointer_static_indirect_2 = "indirect_source(2)";
sink(static_local_pointer_static); // $ ir MISSING: ast
sink(static_local_pointer_static_indirect_1); // clean
indirect_sink(static_local_pointer_static_indirect_1); // $ ir MISSING: ast
sink(static_local_pointer_static_indirect_2); // clean: static_local_pointer_static_indirect_2 does not have 2 indirections
indirect_sink(static_local_pointer_static_indirect_2); // clean: static_local_pointer_static_indirect_2 does not have 2 indirections
}
static const char global_array_static[] = "source";
static const char global_array_static_indirect_1[] = "indirect_source(1)";
static const char global_array_static_indirect_2[] = "indirect_source(2)";
void test7() {
sink(global_array_static); // clean
sink(*global_array_static); // clean
sink(global_array_static_indirect_1); // $ ir MISSING: ast
sink(*global_array_static_indirect_1); // clean
indirect_sink(global_array_static); // clean
indirect_sink(global_array_static_indirect_1); // clean
indirect_sink(global_array_static_indirect_2); // $ ir MISSING: ast
}
static const char* global_pointer_static = "source";
static const char* global_pointer_static_indirect_1 = "indirect_source(1)";
static const char* global_pointer_static_indirect_2 = "indirect_source(2)";
void test8() {
sink(global_pointer_static); // $ ir MISSING: ast
sink(global_pointer_static_indirect_1); // clean
indirect_sink(global_pointer_static_indirect_1); // $ ir MISSING: ast
sink(global_pointer_static_indirect_2); // clean: global_pointer_static_indirect_2 does not have 2 indirections
indirect_sink(global_pointer_static_indirect_2); // clean: global_pointer_static_indirect_2 does not have 2 indirections
}
}

Просмотреть файл

@ -1,9 +1,2 @@
WARNING: Module DataFlow has been deprecated and may be removed in future (test.ql:19,45-53)
WARNING: Module DataFlow has been deprecated and may be removed in future (test.ql:20,24-32)
WARNING: Module DataFlow has been deprecated and may be removed in future (test.ql:27,15-23)
WARNING: Module DataFlow has been deprecated and may be removed in future (test.ql:33,22-30)
WARNING: Module DataFlow has been deprecated and may be removed in future (test.ql:40,25-33)
WARNING: Module DataFlow has been deprecated and may be removed in future (test.ql:42,17-25)
WARNING: Module DataFlow has been deprecated and may be removed in future (test.ql:46,20-28)
testFailures
failures

Просмотреть файл

@ -1,107 +1,3 @@
import TestBase
import TestUtilities.dataflow.FlowTestCommon
module AstTest {
private import semmle.code.cpp.dataflow.DataFlow
private import semmle.code.cpp.controlflow.Guards
/**
* A `BarrierGuard` that stops flow to all occurrences of `x` within statement
* S in `if (guarded(x)) S`.
*/
// This is tested in `BarrierGuard.cpp`.
predicate testBarrierGuard(GuardCondition g, Expr checked, boolean isTrue) {
g.(FunctionCall).getTarget().getName() = "guarded" and
checked = g.(FunctionCall).getArgument(0) and
isTrue = true
}
/** Common data flow configuration to be used by tests. */
module AstTestAllocationConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.asExpr().(FunctionCall).getTarget().getName() = "source"
or
source.asParameter().getName().matches("source%")
or
source.asExpr().(FunctionCall).getTarget().getName() = "indirect_source"
or
source.(DataFlow::DefinitionByReferenceNode).getParameter().getName().matches("ref_source%")
or
// Track uninitialized variables
exists(source.asUninitialized())
}
predicate isSink(DataFlow::Node sink) {
exists(FunctionCall call |
call.getTarget().getName() = ["sink", "indirect_sink"] and
sink.asExpr() = call.getAnArgument()
)
}
predicate isBarrier(DataFlow::Node barrier) {
barrier.asExpr().(VariableAccess).getTarget().hasName("barrier") or
barrier = DataFlow::BarrierGuard<testBarrierGuard/3>::getABarrierNode()
}
}
module AstFlow = DataFlow::Global<AstTestAllocationConfig>;
}
module IRTest {
private import cpp
private import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.controlflow.IRGuards
/**
* A `BarrierGuard` that stops flow to all occurrences of `x` within statement
* S in `if (guarded(x)) S`.
*/
// This is tested in `BarrierGuard.cpp`.
predicate testBarrierGuard(IRGuardCondition g, Expr checked, boolean isTrue) {
exists(Call call |
call = g.getUnconvertedResultExpression() and
call.getTarget().hasName("guarded") and
checked = call.getArgument(0) and
isTrue = true
)
}
/** Common data flow configuration to be used by tests. */
module IRTestAllocationConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.asExpr().(FunctionCall).getTarget().getName() = "source"
or
source.asIndirectExpr(1).(FunctionCall).getTarget().getName() = "indirect_source"
or
source.asParameter().getName().matches("source%")
or
source.(DataFlow::DefinitionByReferenceNode).getParameter().getName().matches("ref_source%")
or
exists(source.asUninitialized())
}
predicate isSink(DataFlow::Node sink) {
exists(FunctionCall call, Expr e | e = call.getAnArgument() |
call.getTarget().getName() = "sink" and
sink.asExpr() = e
or
call.getTarget().getName() = "indirect_sink" and
sink.asIndirectExpr() = e
)
}
predicate isBarrier(DataFlow::Node barrier) {
exists(Expr barrierExpr | barrierExpr in [barrier.asExpr(), barrier.asIndirectExpr()] |
barrierExpr.(VariableAccess).getTarget().hasName("barrier")
)
or
barrier = DataFlow::BarrierGuard<testBarrierGuard/3>::getABarrierNode()
or
barrier = DataFlow::BarrierGuard<testBarrierGuard/3>::getAnIndirectBarrierNode()
}
}
module IRFlow = DataFlow::Global<IRTestAllocationConfig>;
}
import MakeTest<MergeTests<AstFlowTest<AstTest::AstFlow>, IRFlowTest<IRTest::IRFlow>>>

Просмотреть файл

@ -43,6 +43,11 @@ edges
| test.cpp:189:16:189:16 | p | test.cpp:189:16:189:16 | (reference to) |
| test.cpp:190:10:190:13 | (reference dereference) | test.cpp:190:10:190:13 | (reference to) |
| test.cpp:190:10:190:13 | pRef | test.cpp:190:10:190:13 | (reference dereference) |
| test.cpp:237:12:237:17 | call to alloca | test.cpp:237:12:237:17 | call to alloca |
| test.cpp:237:12:237:17 | call to alloca | test.cpp:238:9:238:9 | p |
| test.cpp:249:13:249:20 | call to strndupa | test.cpp:249:13:249:20 | call to strndupa |
| test.cpp:249:13:249:20 | call to strndupa | test.cpp:250:9:250:10 | s2 |
| test.cpp:250:9:250:10 | s2 | test.cpp:250:9:250:10 | (void *)... |
nodes
| test.cpp:17:9:17:11 | & ... | semmle.label | & ... |
| test.cpp:17:10:17:11 | mc | semmle.label | mc |
@ -101,6 +106,14 @@ nodes
| test.cpp:190:10:190:13 | (reference dereference) | semmle.label | (reference dereference) |
| test.cpp:190:10:190:13 | (reference to) | semmle.label | (reference to) |
| test.cpp:190:10:190:13 | pRef | semmle.label | pRef |
| test.cpp:237:12:237:17 | call to alloca | semmle.label | call to alloca |
| test.cpp:237:12:237:17 | call to alloca | semmle.label | call to alloca |
| test.cpp:238:9:238:9 | p | semmle.label | p |
| test.cpp:245:9:245:15 | call to strdupa | semmle.label | call to strdupa |
| test.cpp:249:13:249:20 | call to strndupa | semmle.label | call to strndupa |
| test.cpp:249:13:249:20 | call to strndupa | semmle.label | call to strndupa |
| test.cpp:250:9:250:10 | (void *)... | semmle.label | (void *)... |
| test.cpp:250:9:250:10 | s2 | semmle.label | s2 |
#select
| test.cpp:17:9:17:11 | CopyValue: & ... | test.cpp:17:10:17:11 | mc | test.cpp:17:9:17:11 | & ... | May return stack-allocated memory from $@. | test.cpp:17:10:17:11 | mc | mc |
| test.cpp:25:9:25:11 | Load: ptr | test.cpp:23:18:23:19 | mc | test.cpp:25:9:25:11 | ptr | May return stack-allocated memory from $@. | test.cpp:23:18:23:19 | mc | mc |
@ -115,3 +128,6 @@ nodes
| test.cpp:177:10:177:23 | Convert: (void *)... | test.cpp:176:25:176:34 | localArray | test.cpp:177:10:177:23 | (void *)... | May return stack-allocated memory from $@. | test.cpp:176:25:176:34 | localArray | localArray |
| test.cpp:183:10:183:19 | CopyValue: (reference to) | test.cpp:182:21:182:27 | myLocal | test.cpp:183:10:183:19 | (reference to) | May return stack-allocated memory from $@. | test.cpp:182:21:182:27 | myLocal | myLocal |
| test.cpp:190:10:190:13 | CopyValue: (reference to) | test.cpp:189:16:189:16 | p | test.cpp:190:10:190:13 | (reference to) | May return stack-allocated memory from $@. | test.cpp:189:16:189:16 | p | p |
| test.cpp:238:9:238:9 | Load: p | test.cpp:237:12:237:17 | call to alloca | test.cpp:238:9:238:9 | p | May return stack-allocated memory from $@. | test.cpp:237:12:237:17 | call to alloca | call to alloca |
| test.cpp:245:9:245:15 | Call: call to strdupa | test.cpp:245:9:245:15 | call to strdupa | test.cpp:245:9:245:15 | call to strdupa | May return stack-allocated memory from $@. | test.cpp:245:9:245:15 | call to strdupa | call to strdupa |
| test.cpp:250:9:250:10 | Convert: (void *)... | test.cpp:249:13:249:20 | call to strndupa | test.cpp:250:9:250:10 | (void *)... | May return stack-allocated memory from $@. | test.cpp:249:13:249:20 | call to strndupa | call to strndupa |

Просмотреть файл

@ -229,4 +229,23 @@ int* id(int* px) {
void f() {
int x;
int* px = id(&x); // GOOD
}
void *alloca(size_t);
void* test_alloca() {
void* p = alloca(10);
return p; // BAD
}
char *strdupa(const char *);
char *strndupa(const char *, size_t);
char* test_strdupa(const char* s) {
return strdupa(s); // BAD
}
void* test_strndupa(const char* s, size_t size) {
char* s2 = strndupa(s, size);
return s2; // BAD
}

Просмотреть файл

@ -1,23 +1,12 @@
edges
| test.cpp:37:73:37:76 | data | test.cpp:43:32:43:35 | data |
| test.cpp:37:73:37:76 | data | test.cpp:43:32:43:35 | data |
| test.cpp:37:73:37:76 | data indirection | test.cpp:43:32:43:35 | data |
| test.cpp:37:73:37:76 | data indirection | test.cpp:43:32:43:35 | data |
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data |
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data |
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data indirection |
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data indirection |
| test.cpp:73:24:73:27 | data | test.cpp:37:73:37:76 | data |
| test.cpp:37:73:37:76 | data indirection | test.cpp:43:32:43:35 | data indirection |
| test.cpp:64:30:64:35 | call to getenv indirection | test.cpp:73:24:73:27 | data indirection |
| test.cpp:73:24:73:27 | data indirection | test.cpp:37:73:37:76 | data indirection |
subpaths
nodes
| test.cpp:37:73:37:76 | data | semmle.label | data |
| test.cpp:37:73:37:76 | data indirection | semmle.label | data indirection |
| test.cpp:43:32:43:35 | data | semmle.label | data |
| test.cpp:43:32:43:35 | data | semmle.label | data |
| test.cpp:64:30:64:35 | call to getenv | semmle.label | call to getenv |
| test.cpp:64:30:64:35 | call to getenv | semmle.label | call to getenv |
| test.cpp:73:24:73:27 | data | semmle.label | data |
| test.cpp:43:32:43:35 | data indirection | semmle.label | data indirection |
| test.cpp:64:30:64:35 | call to getenv indirection | semmle.label | call to getenv indirection |
| test.cpp:73:24:73:27 | data indirection | semmle.label | data indirection |
subpaths
#select
| test.cpp:43:32:43:35 | data | test.cpp:64:30:64:35 | call to getenv | test.cpp:43:32:43:35 | data | The value of this argument may come from $@ and is being passed to LoadLibraryA. | test.cpp:64:30:64:35 | call to getenv | call to getenv |
| test.cpp:43:32:43:35 | data indirection | test.cpp:64:30:64:35 | call to getenv indirection | test.cpp:43:32:43:35 | data indirection | The value of this argument may come from $@ and is being passed to LoadLibraryA. | test.cpp:64:30:64:35 | call to getenv indirection | an environment variable |

Просмотреть файл

@ -1,112 +1,45 @@
edges
| test.cpp:24:30:24:36 | command | test.cpp:26:10:26:16 | command |
| test.cpp:24:30:24:36 | command | test.cpp:26:10:26:16 | command |
| test.cpp:29:30:29:36 | command | test.cpp:31:10:31:16 | command |
| test.cpp:29:30:29:36 | command | test.cpp:31:10:31:16 | command |
| test.cpp:42:18:42:23 | call to getenv | test.cpp:24:30:24:36 | command |
| test.cpp:42:18:42:34 | call to getenv | test.cpp:24:30:24:36 | command |
| test.cpp:43:18:43:23 | call to getenv | test.cpp:29:30:29:36 | command |
| test.cpp:43:18:43:34 | call to getenv | test.cpp:29:30:29:36 | command |
| test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer |
| test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer |
| test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer |
| test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer |
| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data |
| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data |
| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data |
| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data |
| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref |
| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref |
| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref |
| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref |
| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref |
| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref |
| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 |
| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 |
| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 |
| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | buffer |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | buffer |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 |
| test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer |
| test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer |
| test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer |
| test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer |
| test.cpp:76:12:76:17 | fgets output argument | test.cpp:78:10:78:15 | buffer |
| test.cpp:76:12:76:17 | fgets output argument | test.cpp:78:10:78:15 | buffer |
| test.cpp:98:17:98:22 | buffer | test.cpp:99:15:99:20 | buffer |
| test.cpp:98:17:98:22 | buffer | test.cpp:99:15:99:20 | buffer |
| test.cpp:98:17:98:22 | buffer | test.cpp:99:15:99:20 | buffer |
| test.cpp:98:17:98:22 | buffer | test.cpp:99:15:99:20 | buffer |
| test.cpp:98:17:98:22 | recv output argument | test.cpp:99:15:99:20 | buffer |
| test.cpp:98:17:98:22 | recv output argument | test.cpp:99:15:99:20 | buffer |
| test.cpp:106:17:106:22 | buffer | test.cpp:107:15:107:20 | buffer |
| test.cpp:106:17:106:22 | buffer | test.cpp:107:15:107:20 | buffer |
| test.cpp:106:17:106:22 | buffer | test.cpp:107:15:107:20 | buffer |
| test.cpp:106:17:106:22 | buffer | test.cpp:107:15:107:20 | buffer |
| test.cpp:106:17:106:22 | recv output argument | test.cpp:107:15:107:20 | buffer |
| test.cpp:106:17:106:22 | recv output argument | test.cpp:107:15:107:20 | buffer |
| test.cpp:113:8:113:12 | call to fgets | test.cpp:114:9:114:11 | ptr |
| test.cpp:113:8:113:12 | call to fgets | test.cpp:114:9:114:11 | ptr |
| test.cpp:113:8:113:12 | call to fgets | test.cpp:114:9:114:11 | ptr |
| test.cpp:113:8:113:12 | call to fgets | test.cpp:114:9:114:11 | ptr |
subpaths
| test.cpp:24:30:24:36 | command indirection | test.cpp:26:10:26:16 | command indirection |
| test.cpp:29:30:29:36 | command indirection | test.cpp:31:10:31:16 | command indirection |
| test.cpp:42:18:42:34 | call to getenv indirection | test.cpp:24:30:24:36 | command indirection |
| test.cpp:43:18:43:34 | call to getenv indirection | test.cpp:29:30:29:36 | command indirection |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | buffer indirection |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data indirection |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref indirection |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 indirection |
| test.cpp:76:12:76:17 | fgets output argument | test.cpp:78:10:78:15 | buffer indirection |
| test.cpp:98:17:98:22 | recv output argument | test.cpp:99:15:99:20 | buffer indirection |
| test.cpp:106:17:106:22 | recv output argument | test.cpp:107:15:107:20 | buffer indirection |
| test.cpp:113:8:113:12 | call to fgets indirection | test.cpp:114:9:114:11 | ptr indirection |
nodes
| test.cpp:24:30:24:36 | command | semmle.label | command |
| test.cpp:26:10:26:16 | command | semmle.label | command |
| test.cpp:26:10:26:16 | command | semmle.label | command |
| test.cpp:29:30:29:36 | command | semmle.label | command |
| test.cpp:31:10:31:16 | command | semmle.label | command |
| test.cpp:31:10:31:16 | command | semmle.label | command |
| test.cpp:42:18:42:23 | call to getenv | semmle.label | call to getenv |
| test.cpp:42:18:42:34 | call to getenv | semmle.label | call to getenv |
| test.cpp:43:18:43:23 | call to getenv | semmle.label | call to getenv |
| test.cpp:43:18:43:34 | call to getenv | semmle.label | call to getenv |
| test.cpp:56:12:56:17 | buffer | semmle.label | buffer |
| test.cpp:56:12:56:17 | buffer | semmle.label | buffer |
| test.cpp:24:30:24:36 | command indirection | semmle.label | command indirection |
| test.cpp:26:10:26:16 | command indirection | semmle.label | command indirection |
| test.cpp:29:30:29:36 | command indirection | semmle.label | command indirection |
| test.cpp:31:10:31:16 | command indirection | semmle.label | command indirection |
| test.cpp:42:18:42:34 | call to getenv indirection | semmle.label | call to getenv indirection |
| test.cpp:43:18:43:34 | call to getenv indirection | semmle.label | call to getenv indirection |
| test.cpp:56:12:56:17 | fgets output argument | semmle.label | fgets output argument |
| test.cpp:62:10:62:15 | buffer | semmle.label | buffer |
| test.cpp:62:10:62:15 | buffer | semmle.label | buffer |
| test.cpp:63:10:63:13 | data | semmle.label | data |
| test.cpp:63:10:63:13 | data | semmle.label | data |
| test.cpp:64:10:64:16 | dataref | semmle.label | dataref |
| test.cpp:64:10:64:16 | dataref | semmle.label | dataref |
| test.cpp:64:10:64:16 | dataref | semmle.label | dataref |
| test.cpp:65:10:65:14 | data2 | semmle.label | data2 |
| test.cpp:65:10:65:14 | data2 | semmle.label | data2 |
| test.cpp:76:12:76:17 | buffer | semmle.label | buffer |
| test.cpp:76:12:76:17 | buffer | semmle.label | buffer |
| test.cpp:62:10:62:15 | buffer indirection | semmle.label | buffer indirection |
| test.cpp:63:10:63:13 | data indirection | semmle.label | data indirection |
| test.cpp:64:10:64:16 | dataref indirection | semmle.label | dataref indirection |
| test.cpp:65:10:65:14 | data2 indirection | semmle.label | data2 indirection |
| test.cpp:76:12:76:17 | fgets output argument | semmle.label | fgets output argument |
| test.cpp:78:10:78:15 | buffer | semmle.label | buffer |
| test.cpp:78:10:78:15 | buffer | semmle.label | buffer |
| test.cpp:98:17:98:22 | buffer | semmle.label | buffer |
| test.cpp:98:17:98:22 | buffer | semmle.label | buffer |
| test.cpp:78:10:78:15 | buffer indirection | semmle.label | buffer indirection |
| test.cpp:98:17:98:22 | recv output argument | semmle.label | recv output argument |
| test.cpp:99:15:99:20 | buffer | semmle.label | buffer |
| test.cpp:99:15:99:20 | buffer | semmle.label | buffer |
| test.cpp:106:17:106:22 | buffer | semmle.label | buffer |
| test.cpp:106:17:106:22 | buffer | semmle.label | buffer |
| test.cpp:99:15:99:20 | buffer indirection | semmle.label | buffer indirection |
| test.cpp:106:17:106:22 | recv output argument | semmle.label | recv output argument |
| test.cpp:107:15:107:20 | buffer | semmle.label | buffer |
| test.cpp:107:15:107:20 | buffer | semmle.label | buffer |
| test.cpp:113:8:113:12 | call to fgets | semmle.label | call to fgets |
| test.cpp:113:8:113:12 | call to fgets | semmle.label | call to fgets |
| test.cpp:114:9:114:11 | ptr | semmle.label | ptr |
| test.cpp:114:9:114:11 | ptr | semmle.label | ptr |
| test.cpp:107:15:107:20 | buffer indirection | semmle.label | buffer indirection |
| test.cpp:113:8:113:12 | call to fgets indirection | semmle.label | call to fgets indirection |
| test.cpp:114:9:114:11 | ptr indirection | semmle.label | ptr indirection |
subpaths
#select
| test.cpp:26:10:26:16 | command | test.cpp:42:18:42:23 | call to getenv | test.cpp:26:10:26:16 | command | The value of this argument may come from $@ and is being passed to system. | test.cpp:42:18:42:23 | call to getenv | call to getenv |
| test.cpp:31:10:31:16 | command | test.cpp:43:18:43:23 | call to getenv | test.cpp:31:10:31:16 | command | The value of this argument may come from $@ and is being passed to system. | test.cpp:43:18:43:23 | call to getenv | call to getenv |
| test.cpp:62:10:62:15 | buffer | test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | buffer | buffer |
| test.cpp:63:10:63:13 | data | test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | buffer | buffer |
| test.cpp:64:10:64:16 | dataref | test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | buffer | buffer |
| test.cpp:65:10:65:14 | data2 | test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | buffer | buffer |
| test.cpp:78:10:78:15 | buffer | test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer | The value of this argument may come from $@ and is being passed to system. | test.cpp:76:12:76:17 | buffer | buffer |
| test.cpp:99:15:99:20 | buffer | test.cpp:98:17:98:22 | buffer | test.cpp:99:15:99:20 | buffer | The value of this argument may come from $@ and is being passed to LoadLibrary. | test.cpp:98:17:98:22 | buffer | buffer |
| test.cpp:107:15:107:20 | buffer | test.cpp:106:17:106:22 | buffer | test.cpp:107:15:107:20 | buffer | The value of this argument may come from $@ and is being passed to LoadLibrary. | test.cpp:106:17:106:22 | buffer | buffer |
| test.cpp:114:9:114:11 | ptr | test.cpp:113:8:113:12 | call to fgets | test.cpp:114:9:114:11 | ptr | The value of this argument may come from $@ and is being passed to system. | test.cpp:113:8:113:12 | call to fgets | call to fgets |
| test.cpp:26:10:26:16 | command indirection | test.cpp:42:18:42:34 | call to getenv indirection | test.cpp:26:10:26:16 | command indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:42:18:42:34 | call to getenv indirection | an environment variable |
| test.cpp:31:10:31:16 | command indirection | test.cpp:43:18:43:34 | call to getenv indirection | test.cpp:31:10:31:16 | command indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:43:18:43:34 | call to getenv indirection | an environment variable |
| test.cpp:62:10:62:15 | buffer indirection | test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | buffer indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | fgets output argument | string read by fgets |
| test.cpp:63:10:63:13 | data indirection | test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | fgets output argument | string read by fgets |
| test.cpp:64:10:64:16 | dataref indirection | test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | fgets output argument | string read by fgets |
| test.cpp:65:10:65:14 | data2 indirection | test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | fgets output argument | string read by fgets |
| test.cpp:78:10:78:15 | buffer indirection | test.cpp:76:12:76:17 | fgets output argument | test.cpp:78:10:78:15 | buffer indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:76:12:76:17 | fgets output argument | string read by fgets |
| test.cpp:99:15:99:20 | buffer indirection | test.cpp:98:17:98:22 | recv output argument | test.cpp:99:15:99:20 | buffer indirection | The value of this argument may come from $@ and is being passed to LoadLibrary. | test.cpp:98:17:98:22 | recv output argument | buffer read by recv |
| test.cpp:107:15:107:20 | buffer indirection | test.cpp:106:17:106:22 | recv output argument | test.cpp:107:15:107:20 | buffer indirection | The value of this argument may come from $@ and is being passed to LoadLibrary. | test.cpp:106:17:106:22 | recv output argument | buffer read by recv |
| test.cpp:114:9:114:11 | ptr indirection | test.cpp:113:8:113:12 | call to fgets indirection | test.cpp:114:9:114:11 | ptr indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:113:8:113:12 | call to fgets indirection | string read by fgets |

Просмотреть файл

@ -1,69 +0,0 @@
edges
| globalVars.c:8:7:8:10 | copy | globalVars.c:27:9:27:12 | copy |
| globalVars.c:8:7:8:10 | copy | globalVars.c:27:9:27:12 | copy |
| globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy |
| globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy |
| globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy |
| globalVars.c:8:7:8:10 | copy | globalVars.c:33:15:33:18 | copy |
| globalVars.c:8:7:8:10 | copy | globalVars.c:35:11:35:14 | copy |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:44:15:44:19 | copy2 |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 |
| globalVars.c:11:22:11:25 | argv | globalVars.c:8:7:8:10 | copy |
| globalVars.c:11:22:11:25 | argv | globalVars.c:12:2:12:15 | ... = ... |
| globalVars.c:12:2:12:15 | ... = ... | globalVars.c:8:7:8:10 | copy |
| globalVars.c:15:21:15:23 | val | globalVars.c:9:7:9:11 | copy2 |
| globalVars.c:15:21:15:23 | val | globalVars.c:16:2:16:12 | ... = ... |
| globalVars.c:16:2:16:12 | ... = ... | globalVars.c:9:7:9:11 | copy2 |
| globalVars.c:24:11:24:14 | argv | globalVars.c:11:22:11:25 | argv |
| globalVars.c:24:11:24:14 | argv | globalVars.c:11:22:11:25 | argv |
| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy |
| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy |
| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy |
| globalVars.c:30:15:30:18 | copy | globalVars.c:35:11:35:14 | copy |
| globalVars.c:33:15:33:18 | copy | globalVars.c:35:11:35:14 | copy |
| globalVars.c:35:11:35:14 | copy | globalVars.c:15:21:15:23 | val |
| globalVars.c:35:11:35:14 | copy | globalVars.c:35:11:35:14 | copy |
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 |
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 |
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 |
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:50:9:50:13 | copy2 |
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:50:9:50:13 | copy2 |
| globalVars.c:44:15:44:19 | copy2 | globalVars.c:50:9:50:13 | copy2 |
| globalVars.c:44:15:44:19 | copy2 | globalVars.c:50:9:50:13 | copy2 |
subpaths
nodes
| globalVars.c:8:7:8:10 | copy | semmle.label | copy |
| globalVars.c:9:7:9:11 | copy2 | semmle.label | copy2 |
| globalVars.c:11:22:11:25 | argv | semmle.label | argv |
| globalVars.c:12:2:12:15 | ... = ... | semmle.label | ... = ... |
| globalVars.c:15:21:15:23 | val | semmle.label | val |
| globalVars.c:16:2:16:12 | ... = ... | semmle.label | ... = ... |
| globalVars.c:24:11:24:14 | argv | semmle.label | argv |
| globalVars.c:24:11:24:14 | argv | semmle.label | argv |
| globalVars.c:27:9:27:12 | copy | semmle.label | copy |
| globalVars.c:27:9:27:12 | copy | semmle.label | copy |
| globalVars.c:30:15:30:18 | copy | semmle.label | copy |
| globalVars.c:30:15:30:18 | copy | semmle.label | copy |
| globalVars.c:30:15:30:18 | copy | semmle.label | copy |
| globalVars.c:33:15:33:18 | copy | semmle.label | copy |
| globalVars.c:35:11:35:14 | copy | semmle.label | copy |
| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 |
| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 |
| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 |
| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 |
| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 |
| globalVars.c:44:15:44:19 | copy2 | semmle.label | copy2 |
| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 |
| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 |
#select
| globalVars.c:27:9:27:12 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:27:9:27:12 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | globalVars.c:24:11:24:14 | argv | argv |
| globalVars.c:30:15:30:18 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:30:15:30:18 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format). | globalVars.c:24:11:24:14 | argv | argv |
| globalVars.c:38:9:38:13 | copy2 | globalVars.c:24:11:24:14 | argv | globalVars.c:38:9:38:13 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | globalVars.c:24:11:24:14 | argv | argv |
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:24:11:24:14 | argv | globalVars.c:41:15:41:19 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format). | globalVars.c:24:11:24:14 | argv | argv |
| globalVars.c:50:9:50:13 | copy2 | globalVars.c:24:11:24:14 | argv | globalVars.c:50:9:50:13 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | globalVars.c:24:11:24:14 | argv | argv |

Просмотреть файл

@ -1 +0,0 @@
Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql

Просмотреть файл

@ -1,13 +1,8 @@
edges
| examples.cpp:63:26:63:30 | & ... | examples.cpp:66:11:66:14 | data |
| examples.cpp:63:26:63:30 | & ... | examples.cpp:66:11:66:14 | data |
| examples.cpp:63:26:63:30 | fscanf output argument | examples.cpp:66:11:66:14 | data |
| examples.cpp:63:26:63:30 | fscanf output argument | examples.cpp:66:11:66:14 | data |
subpaths
nodes
| examples.cpp:63:26:63:30 | & ... | semmle.label | & ... |
| examples.cpp:63:26:63:30 | fscanf output argument | semmle.label | fscanf output argument |
| examples.cpp:66:11:66:14 | data | semmle.label | data |
| examples.cpp:66:11:66:14 | data | semmle.label | data |
subpaths
#select
| examples.cpp:66:11:66:14 | data | examples.cpp:63:26:63:30 | & ... | examples.cpp:66:11:66:14 | data | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | examples.cpp:63:26:63:30 | & ... | User-provided value |
| examples.cpp:66:11:66:14 | data | examples.cpp:63:26:63:30 | fscanf output argument | examples.cpp:66:11:66:14 | data | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | examples.cpp:63:26:63:30 | fscanf output argument | value read by fscanf |

Просмотреть файл

@ -1 +1 @@
| examples.cpp:66:9:66:14 | -- ... | $@ flows an expression which might overflow negatively. | examples.cpp:63:26:63:30 | & ... | User-provided value |
| examples.cpp:66:9:66:14 | -- ... | $@ flows an expression which might overflow negatively. | examples.cpp:63:26:63:30 | fscanf output argument | value read by fscanf |

Просмотреть файл

@ -1,86 +1,59 @@
edges
| test2.cpp:12:21:12:21 | v | test2.cpp:14:11:14:11 | v |
| test2.cpp:12:21:12:21 | v | test2.cpp:14:11:14:11 | v |
| test2.cpp:25:22:25:23 | & ... | test2.cpp:27:13:27:13 | v |
| test2.cpp:25:22:25:23 | fscanf output argument | test2.cpp:27:13:27:13 | v |
| test2.cpp:27:13:27:13 | v | test2.cpp:12:21:12:21 | v |
| test2.cpp:36:9:36:14 | buffer | test2.cpp:39:9:39:11 | num |
| test2.cpp:36:9:36:14 | buffer | test2.cpp:39:9:39:11 | num |
| test2.cpp:36:9:36:14 | buffer | test2.cpp:39:9:39:11 | num |
| test2.cpp:36:9:36:14 | buffer | test2.cpp:39:9:39:11 | num |
| test2.cpp:36:9:36:14 | buffer | test2.cpp:40:3:40:5 | num |
| test2.cpp:36:9:36:14 | buffer | test2.cpp:40:3:40:5 | num |
| test2.cpp:36:9:36:14 | buffer | test2.cpp:40:3:40:5 | num |
| test2.cpp:36:9:36:14 | buffer | test2.cpp:40:3:40:5 | num |
| test2.cpp:36:9:36:14 | fgets output argument | test2.cpp:39:9:39:11 | num |
| test2.cpp:36:9:36:14 | fgets output argument | test2.cpp:39:9:39:11 | num |
| test2.cpp:36:9:36:14 | fgets output argument | test2.cpp:40:3:40:5 | num |
| test2.cpp:36:9:36:14 | fgets output argument | test2.cpp:40:3:40:5 | num |
| test5.cpp:5:5:5:17 | getTaintedInt indirection | test5.cpp:17:6:17:18 | call to getTaintedInt |
| test3.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections |
| test3.c:10:27:10:30 | argv indirection | test.c:44:7:44:10 | len2 |
| test3.c:10:27:10:30 | argv indirection | test.c:54:7:54:10 | len3 |
| test5.cpp:5:5:5:17 | getTaintedInt indirection | test5.cpp:17:6:17:18 | call to getTaintedInt |
| test5.cpp:5:5:5:17 | getTaintedInt indirection | test5.cpp:18:6:18:18 | call to getTaintedInt |
| test5.cpp:9:7:9:9 | buf | test5.cpp:5:5:5:17 | getTaintedInt indirection |
| test5.cpp:9:7:9:9 | buf | test5.cpp:5:5:5:17 | getTaintedInt indirection |
| test5.cpp:9:7:9:9 | gets output argument | test5.cpp:5:5:5:17 | getTaintedInt indirection |
| test5.cpp:18:6:18:18 | call to getTaintedInt | test5.cpp:19:6:19:6 | y |
| test5.cpp:18:6:18:18 | call to getTaintedInt | test5.cpp:19:6:19:6 | y |
| test.c:11:29:11:32 | argv | test.c:14:15:14:28 | maxConnections |
| test.c:11:29:11:32 | argv | test.c:14:15:14:28 | maxConnections |
| test.c:11:29:11:32 | argv | test.c:14:15:14:28 | maxConnections |
| test.c:11:29:11:32 | argv | test.c:14:15:14:28 | maxConnections |
| test.c:41:17:41:20 | argv | test.c:44:7:44:10 | len2 |
| test.c:41:17:41:20 | argv | test.c:44:7:44:10 | len2 |
| test.c:41:17:41:20 | argv | test.c:44:7:44:10 | len2 |
| test.c:41:17:41:20 | argv | test.c:44:7:44:10 | len2 |
| test.c:51:17:51:20 | argv | test.c:54:7:54:10 | len3 |
| test.c:51:17:51:20 | argv | test.c:54:7:54:10 | len3 |
| test.c:51:17:51:20 | argv | test.c:54:7:54:10 | len3 |
| test.c:51:17:51:20 | argv | test.c:54:7:54:10 | len3 |
subpaths
| test.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections |
| test.c:10:27:10:30 | argv indirection | test.c:44:7:44:10 | len2 |
| test.c:10:27:10:30 | argv indirection | test.c:54:7:54:10 | len3 |
nodes
| test2.cpp:12:21:12:21 | v | semmle.label | v |
| test2.cpp:14:11:14:11 | v | semmle.label | v |
| test2.cpp:14:11:14:11 | v | semmle.label | v |
| test2.cpp:25:22:25:23 | & ... | semmle.label | & ... |
| test2.cpp:25:22:25:23 | fscanf output argument | semmle.label | fscanf output argument |
| test2.cpp:27:13:27:13 | v | semmle.label | v |
| test2.cpp:36:9:36:14 | buffer | semmle.label | buffer |
| test2.cpp:36:9:36:14 | buffer | semmle.label | buffer |
| test2.cpp:36:9:36:14 | fgets output argument | semmle.label | fgets output argument |
| test2.cpp:39:9:39:11 | num | semmle.label | num |
| test2.cpp:39:9:39:11 | num | semmle.label | num |
| test2.cpp:40:3:40:5 | num | semmle.label | num |
| test2.cpp:40:3:40:5 | num | semmle.label | num |
| test3.c:10:27:10:30 | argv indirection | semmle.label | argv indirection |
| test5.cpp:5:5:5:17 | getTaintedInt indirection | semmle.label | getTaintedInt indirection |
| test5.cpp:9:7:9:9 | buf | semmle.label | buf |
| test5.cpp:9:7:9:9 | buf | semmle.label | buf |
| test5.cpp:9:7:9:9 | gets output argument | semmle.label | gets output argument |
| test5.cpp:17:6:17:18 | call to getTaintedInt | semmle.label | call to getTaintedInt |
| test5.cpp:17:6:17:18 | call to getTaintedInt | semmle.label | call to getTaintedInt |
| test5.cpp:18:6:18:18 | call to getTaintedInt | semmle.label | call to getTaintedInt |
| test5.cpp:19:6:19:6 | y | semmle.label | y |
| test5.cpp:19:6:19:6 | y | semmle.label | y |
| test.c:11:29:11:32 | argv | semmle.label | argv |
| test.c:11:29:11:32 | argv | semmle.label | argv |
| test.c:10:27:10:30 | argv indirection | semmle.label | argv indirection |
| test.c:14:15:14:28 | maxConnections | semmle.label | maxConnections |
| test.c:14:15:14:28 | maxConnections | semmle.label | maxConnections |
| test.c:41:17:41:20 | argv | semmle.label | argv |
| test.c:41:17:41:20 | argv | semmle.label | argv |
| test.c:44:7:44:10 | len2 | semmle.label | len2 |
| test.c:44:7:44:10 | len2 | semmle.label | len2 |
| test.c:51:17:51:20 | argv | semmle.label | argv |
| test.c:51:17:51:20 | argv | semmle.label | argv |
| test.c:54:7:54:10 | len3 | semmle.label | len3 |
| test.c:54:7:54:10 | len3 | semmle.label | len3 |
subpaths
#select
| test2.cpp:14:11:14:11 | v | test2.cpp:25:22:25:23 | & ... | test2.cpp:14:11:14:11 | v | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test2.cpp:25:22:25:23 | & ... | User-provided value |
| test2.cpp:14:11:14:11 | v | test2.cpp:25:22:25:23 | & ... | test2.cpp:14:11:14:11 | v | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test2.cpp:25:22:25:23 | & ... | User-provided value |
| test2.cpp:39:9:39:11 | num | test2.cpp:36:9:36:14 | buffer | test2.cpp:39:9:39:11 | num | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test2.cpp:36:9:36:14 | buffer | User-provided value |
| test2.cpp:40:3:40:5 | num | test2.cpp:36:9:36:14 | buffer | test2.cpp:40:3:40:5 | num | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test2.cpp:36:9:36:14 | buffer | User-provided value |
| test5.cpp:17:6:17:18 | call to getTaintedInt | test5.cpp:9:7:9:9 | buf | test5.cpp:17:6:17:18 | call to getTaintedInt | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
| test5.cpp:19:6:19:6 | y | test5.cpp:9:7:9:9 | buf | test5.cpp:19:6:19:6 | y | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
| test5.cpp:19:6:19:6 | y | test5.cpp:9:7:9:9 | buf | test5.cpp:19:6:19:6 | y | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
| test.c:14:15:14:28 | maxConnections | test.c:11:29:11:32 | argv | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test.c:11:29:11:32 | argv | User-provided value |
| test.c:14:15:14:28 | maxConnections | test.c:11:29:11:32 | argv | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:11:29:11:32 | argv | User-provided value |
| test.c:44:7:44:10 | len2 | test.c:41:17:41:20 | argv | test.c:44:7:44:10 | len2 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:41:17:41:20 | argv | User-provided value |
| test.c:54:7:54:10 | len3 | test.c:51:17:51:20 | argv | test.c:54:7:54:10 | len3 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:51:17:51:20 | argv | User-provided value |
| test2.cpp:14:11:14:11 | v | test2.cpp:25:22:25:23 | fscanf output argument | test2.cpp:14:11:14:11 | v | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test2.cpp:25:22:25:23 | fscanf output argument | value read by fscanf |
| test2.cpp:14:11:14:11 | v | test2.cpp:25:22:25:23 | fscanf output argument | test2.cpp:14:11:14:11 | v | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test2.cpp:25:22:25:23 | fscanf output argument | value read by fscanf |
| test2.cpp:39:9:39:11 | num | test2.cpp:36:9:36:14 | fgets output argument | test2.cpp:39:9:39:11 | num | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test2.cpp:36:9:36:14 | fgets output argument | string read by fgets |
| test2.cpp:40:3:40:5 | num | test2.cpp:36:9:36:14 | fgets output argument | test2.cpp:40:3:40:5 | num | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test2.cpp:36:9:36:14 | fgets output argument | string read by fgets |
| test5.cpp:17:6:17:18 | call to getTaintedInt | test5.cpp:9:7:9:9 | gets output argument | test5.cpp:17:6:17:18 | call to getTaintedInt | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test5.cpp:9:7:9:9 | gets output argument | string read by gets |
| test5.cpp:19:6:19:6 | y | test5.cpp:9:7:9:9 | gets output argument | test5.cpp:19:6:19:6 | y | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test5.cpp:9:7:9:9 | gets output argument | string read by gets |
| test5.cpp:19:6:19:6 | y | test5.cpp:9:7:9:9 | gets output argument | test5.cpp:19:6:19:6 | y | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test5.cpp:9:7:9:9 | gets output argument | string read by gets |
| test.c:14:15:14:28 | maxConnections | test3.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:14:15:14:28 | maxConnections | test3.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:14:15:14:28 | maxConnections | test3.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:14:15:14:28 | maxConnections | test3.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:14:15:14:28 | maxConnections | test.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:14:15:14:28 | maxConnections | test.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:14:15:14:28 | maxConnections | test.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:14:15:14:28 | maxConnections | test.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:44:7:44:10 | len2 | test3.c:10:27:10:30 | argv indirection | test.c:44:7:44:10 | len2 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:44:7:44:10 | len2 | test3.c:10:27:10:30 | argv indirection | test.c:44:7:44:10 | len2 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:44:7:44:10 | len2 | test.c:10:27:10:30 | argv indirection | test.c:44:7:44:10 | len2 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:44:7:44:10 | len2 | test.c:10:27:10:30 | argv indirection | test.c:44:7:44:10 | len2 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:54:7:54:10 | len3 | test3.c:10:27:10:30 | argv indirection | test.c:54:7:54:10 | len3 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:54:7:54:10 | len3 | test3.c:10:27:10:30 | argv indirection | test.c:54:7:54:10 | len3 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:54:7:54:10 | len3 | test.c:10:27:10:30 | argv indirection | test.c:54:7:54:10 | len3 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:54:7:54:10 | len3 | test.c:10:27:10:30 | argv indirection | test.c:54:7:54:10 | len3 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |

Просмотреть файл

@ -1,18 +1,23 @@
| test2.cpp:14:11:14:15 | ... * ... | $@ flows an expression which might overflow. | test2.cpp:25:22:25:23 | & ... | User-provided value |
| test2.cpp:15:11:15:19 | ... * ... | $@ flows an expression which might overflow. | test2.cpp:25:22:25:23 | & ... | User-provided value |
| test2.cpp:16:11:16:21 | ... * ... | $@ flows an expression which might overflow. | test2.cpp:25:22:25:23 | & ... | User-provided value |
| test2.cpp:17:11:17:22 | ... * ... | $@ flows an expression which might overflow. | test2.cpp:25:22:25:23 | & ... | User-provided value |
| test2.cpp:39:9:39:18 | ... + ... | $@ flows an expression which might overflow. | test2.cpp:36:9:36:14 | buffer | User-provided value |
| test2.cpp:40:3:40:13 | ... += ... | $@ flows an expression which might overflow. | test2.cpp:36:9:36:14 | buffer | User-provided value |
| test3.c:12:31:12:34 | * ... | $@ flows an expression which might overflow negatively. | test3.c:11:15:11:18 | argv | User-provided value |
| test3.c:13:16:13:19 | * ... | $@ flows an expression which might overflow negatively. | test3.c:11:15:11:18 | argv | User-provided value |
| test4.cpp:13:17:13:20 | access to array | $@ flows an expression which might overflow negatively. | test4.cpp:9:13:9:16 | argv | User-provided value |
| test5.cpp:10:9:10:15 | call to strtoul | $@ flows an expression which might overflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
| test5.cpp:17:6:17:27 | ... * ... | $@ flows an expression which might overflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
| test5.cpp:19:6:19:13 | ... * ... | $@ flows an expression which might overflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
| test6.cpp:11:15:11:15 | s | $@ flows an expression which might overflow. | test6.cpp:39:23:39:24 | & ... | User-provided value |
| test6.cpp:16:15:16:15 | s | $@ flows an expression which might overflow. | test6.cpp:39:23:39:24 | & ... | User-provided value |
| test6.cpp:30:16:30:16 | s | $@ flows an expression which might overflow. | test6.cpp:39:23:39:24 | & ... | User-provided value |
| test.c:14:15:14:35 | ... * ... | $@ flows an expression which might overflow. | test.c:11:29:11:32 | argv | User-provided value |
| test.c:44:7:44:12 | ... -- | $@ flows an expression which might overflow negatively. | test.c:41:17:41:20 | argv | User-provided value |
| test.c:54:7:54:12 | ... -- | $@ flows an expression which might overflow negatively. | test.c:51:17:51:20 | argv | User-provided value |
| test2.cpp:14:11:14:15 | ... * ... | $@ flows an expression which might overflow. | test2.cpp:25:22:25:23 | fscanf output argument | value read by fscanf |
| test2.cpp:15:11:15:19 | ... * ... | $@ flows an expression which might overflow. | test2.cpp:25:22:25:23 | fscanf output argument | value read by fscanf |
| test2.cpp:16:11:16:21 | ... * ... | $@ flows an expression which might overflow. | test2.cpp:25:22:25:23 | fscanf output argument | value read by fscanf |
| test2.cpp:17:11:17:22 | ... * ... | $@ flows an expression which might overflow. | test2.cpp:25:22:25:23 | fscanf output argument | value read by fscanf |
| test2.cpp:39:9:39:18 | ... + ... | $@ flows an expression which might overflow. | test2.cpp:36:9:36:14 | fgets output argument | string read by fgets |
| test2.cpp:40:3:40:13 | ... += ... | $@ flows an expression which might overflow. | test2.cpp:36:9:36:14 | fgets output argument | string read by fgets |
| test3.c:12:11:12:34 | * ... | $@ flows an expression which might overflow negatively. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
| test3.c:12:11:12:34 | * ... | $@ flows an expression which might overflow negatively. | test.c:10:27:10:30 | argv indirection | a command-line argument |
| test3.c:13:11:13:20 | * ... | $@ flows an expression which might overflow negatively. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
| test3.c:13:11:13:20 | * ... | $@ flows an expression which might overflow negatively. | test.c:10:27:10:30 | argv indirection | a command-line argument |
| test4.cpp:13:7:13:20 | access to array | $@ flows an expression which might overflow negatively. | test4.cpp:8:27:8:30 | argv indirection | a command-line argument |
| test5.cpp:10:9:10:27 | call to strtoul | $@ flows an expression which might overflow. | test5.cpp:9:7:9:9 | gets output argument | string read by gets |
| test5.cpp:17:6:17:27 | ... * ... | $@ flows an expression which might overflow. | test5.cpp:9:7:9:9 | gets output argument | string read by gets |
| test5.cpp:19:6:19:13 | ... * ... | $@ flows an expression which might overflow. | test5.cpp:9:7:9:9 | gets output argument | string read by gets |
| test6.cpp:11:10:11:15 | s | $@ flows an expression which might overflow. | test6.cpp:39:23:39:24 | fscanf output argument | value read by fscanf |
| test6.cpp:16:10:16:15 | s | $@ flows an expression which might overflow. | test6.cpp:39:23:39:24 | fscanf output argument | value read by fscanf |
| test6.cpp:30:11:30:16 | s | $@ flows an expression which might overflow. | test6.cpp:39:23:39:24 | fscanf output argument | value read by fscanf |
| test.c:14:15:14:35 | ... * ... | $@ flows an expression which might overflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:14:15:14:35 | ... * ... | $@ flows an expression which might overflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:44:7:44:12 | ... -- | $@ flows an expression which might overflow negatively. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:44:7:44:12 | ... -- | $@ flows an expression which might overflow negatively. | test.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:54:7:54:12 | ... -- | $@ flows an expression which might overflow negatively. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
| test.c:54:7:54:12 | ... -- | $@ flows an expression which might overflow negatively. | test.c:10:27:10:30 | argv indirection | a command-line argument |

Просмотреть файл

@ -1 +1 @@
| tests.cpp:38:31:38:34 | data | $@ flows an expression which might overflow. | tests.cpp:57:27:57:31 | & ... | User-provided value |
| tests.cpp:38:25:38:34 | data | $@ flows an expression which might overflow. | tests.cpp:57:27:57:31 | fscanf output argument | value read by fscanf |

Просмотреть файл

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using Newtonsoft.Json.Linq;
@ -14,14 +15,6 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
{
private readonly ProgressMonitor progressMonitor;
private static readonly string[] netFrameworks = new[] {
"microsoft.aspnetcore.app.ref",
"microsoft.netcore.app.ref",
"microsoft.netframework.referenceassemblies",
"microsoft.windowsdesktop.app.ref",
"netstandard.library.ref"
};
internal Assets(ProgressMonitor progressMonitor)
{
this.progressMonitor = progressMonitor;
@ -68,19 +61,19 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
/// }
/// }
///
/// Returns dependencies
/// RequiredPaths = {
/// Adds the following dependencies
/// Paths: {
/// "castle.core/4.4.1/lib/netstandard1.5/Castle.Core.dll",
/// "json.net/1.0.33/lib/netstandard2.0/Json.Net.dll"
/// }
/// UsedPackages = {
/// Packages: {
/// "castle.core",
/// "json.net"
/// }
/// </summary>
private DependencyContainer AddPackageDependencies(JObject json, DependencyContainer dependencies)
private void AddPackageDependencies(JObject json, DependencyContainer dependencies)
{
// If there are more than one framework we need to pick just one.
// If there is more than one framework we need to pick just one.
// To ensure stability we pick one based on the lexicographic order of
// the framework names.
var references = json
@ -93,7 +86,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
if (references is null)
{
progressMonitor.LogDebug("No references found in the targets section in the assets file.");
return dependencies;
return;
}
// Find all the compile dependencies for each reference and
@ -108,19 +101,83 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
return;
}
// If this is a .NET framework reference then include everything.
if (netFrameworks.Any(framework => name.StartsWith(framework)))
if (info.Compile is null || !info.Compile.Any())
{
dependencies.Add(name);
}
else
{
info.Compile?
.ForEach(r => dependencies.Add(name, r.Key));
// If this is a framework reference then include everything.
if (FrameworkPackageNames.AllFrameworks.Any(framework => name.StartsWith(framework)))
{
dependencies.AddFramework(name);
}
return;
}
info.Compile
.ForEach(r => dependencies.Add(name, r.Key));
});
return dependencies;
return;
}
/// <summary>
/// Add the framework dependencies from the assets file to dependencies.
///
/// Example:
/// "project": {
// "version": "1.0.0",
// "frameworks": {
// "net7.0": {
// "frameworkReferences": {
// "Microsoft.AspNetCore.App": {
// "privateAssets": "none"
// },
// "Microsoft.NETCore.App": {
// "privateAssets": "all"
// }
// }
// }
// }
// }
//
/// Adds the following dependencies
/// Paths: {
/// "microsoft.aspnetcore.app.ref",
/// "microsoft.netcore.app.ref"
/// }
/// Packages: {
/// "microsoft.aspnetcore.app.ref",
/// "microsoft.netcore.app.ref"
/// }
/// </summary>
private void AddFrameworkDependencies(JObject json, DependencyContainer dependencies)
{
var frameworks = json
.GetProperty("project")?
.GetProperty("frameworks");
if (frameworks is null)
{
progressMonitor.LogDebug("No framework section in assets.json.");
return;
}
// If there is more than one framework we need to pick just one.
// To ensure stability we pick one based on the lexicographic order of
// the framework names.
var references = frameworks
.Properties()?
.MaxBy(p => p.Name)?
.Value["frameworkReferences"] as JObject;
if (references is null)
{
progressMonitor.LogDebug("No framework references in assets.json.");
return;
}
references
.Properties()
.ForEach(f => dependencies.AddFramework($"{f.Name}.Ref".ToLowerInvariant()));
}
/// <summary>
@ -134,6 +191,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
{
var obj = JObject.Parse(json);
AddPackageDependencies(obj, dependencies);
AddFrameworkDependencies(obj, dependencies);
return true;
}
catch (Exception e)
@ -143,14 +201,31 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
}
}
private static bool TryReadAllText(string path, ProgressMonitor progressMonitor, [NotNullWhen(returnValue: true)] out string? content)
{
try
{
content = File.ReadAllText(path);
return true;
}
catch (Exception e)
{
progressMonitor.LogInfo($"Failed to read assets file '{path}': {e.Message}");
content = null;
return false;
}
}
public static DependencyContainer GetCompilationDependencies(ProgressMonitor progressMonitor, IEnumerable<string> assets)
{
var parser = new Assets(progressMonitor);
var dependencies = new DependencyContainer();
assets.ForEach(asset =>
{
var json = File.ReadAllText(asset);
parser.TryParse(json, dependencies);
if (TryReadAllText(asset, progressMonitor, out var json))
{
parser.TryParse(json, dependencies);
}
});
return dependencies;
}

Просмотреть файл

@ -9,14 +9,19 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
/// </summary>
internal class DependencyContainer
{
private readonly List<string> requiredPaths = new();
private readonly HashSet<string> usedPackages = new();
/// <summary>
/// Paths to dependencies required for compilation.
/// </summary>
public List<string> Paths { get; } = new();
/// <summary>
/// In most cases paths in asset files point to dll's or the empty _._ file, which
/// is sometimes there to avoid the directory being empty.
/// That is, if the path specifically adds a .dll we use that, otherwise we as a fallback
/// add the entire directory (which should be fine in case of _._ as well).
/// Packages that are used as a part of the required dependencies.
/// </summary>
public HashSet<string> Packages { get; } = new();
/// <summary>
/// If the path specifically adds a .dll we use that, otherwise we as a fallback
/// add the entire directory.
/// </summary>
private static string ParseFilePath(string path)
{
@ -32,16 +37,6 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
.Split(Path.DirectorySeparatorChar)
.First();
/// <summary>
/// Paths to dependencies required for compilation.
/// </summary>
public IEnumerable<string> RequiredPaths => requiredPaths;
/// <summary>
/// Packages that are used as a part of the required dependencies.
/// </summary>
public HashSet<string> UsedPackages => usedPackages;
/// <summary>
/// Add a dependency inside a package.
/// </summary>
@ -50,20 +45,27 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
var p = package.Replace('/', Path.DirectorySeparatorChar);
var d = dependency.Replace('/', Path.DirectorySeparatorChar);
// In most cases paths in asset files point to dll's or the empty _._ file.
// That is, for _._ we don't need to add anything.
if (Path.GetFileName(d) == "_._")
{
return;
}
var path = Path.Combine(p, ParseFilePath(d));
requiredPaths.Add(path);
usedPackages.Add(GetPackageName(p));
Paths.Add(path);
Packages.Add(GetPackageName(p));
}
/// <summary>
/// Add a dependency to an entire package
/// Add a dependency to an entire framework package.
/// </summary>
public void Add(string package)
public void AddFramework(string framework)
{
var p = package.Replace('/', Path.DirectorySeparatorChar);
var p = framework.Replace('/', Path.DirectorySeparatorChar);
requiredPaths.Add(p);
usedPackages.Add(GetPackageName(p));
Paths.Add(p);
Packages.Add(GetPackageName(p));
}
}
}

Просмотреть файл

@ -119,7 +119,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
var dependencies = Assets.GetCompilationDependencies(progressMonitor, assets1.Union(assets2));
var paths = dependencies
.RequiredPaths
.Paths
.Select(d => Path.Combine(packageDirectory.DirInfo.FullName, d))
.ToList();
dllPaths.UnionWith(paths);
@ -232,13 +232,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
{
// Multiple dotnet framework packages could be present.
// The order of the packages is important, we're adding the first one that is present in the nuget cache.
var packagesInPrioOrder = new string[]
{
"microsoft.netcore.app.ref", // net7.0, ... net5.0, netcoreapp3.1, netcoreapp3.0
"microsoft.netframework.referenceassemblies.", // net48, ..., net20
"netstandard.library.ref", // netstandard2.1
"netstandard.library" // netstandard2.0
};
var packagesInPrioOrder = FrameworkPackageNames.NetFrameworks;
var frameworkPath = packagesInPrioOrder
.Select((s, index) => (Index: index, Path: GetPackageDirectory(s)))
@ -308,7 +302,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
}
// First try to find ASP.NET Core assemblies in the NuGet packages
if (GetPackageDirectory("microsoft.aspnetcore.app.ref") is string aspNetCorePackage)
if (GetPackageDirectory(FrameworkPackageNames.AspNetCoreFramework) is string aspNetCorePackage)
{
progressMonitor.LogInfo($"Found ASP.NET Core in NuGet packages. Not adding installation directory.");
dllPaths.Add(aspNetCorePackage);
@ -322,7 +316,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
private void AddMicrosoftWindowsDesktopDlls(ISet<string> dllPaths)
{
if (GetPackageDirectory("microsoft.windowsdesktop.app.ref") is string windowsDesktopApp)
if (GetPackageDirectory(FrameworkPackageNames.WindowsDesktopFramework) is string windowsDesktopApp)
{
progressMonitor.LogInfo($"Found Windows Desktop App in NuGet packages.");
dllPaths.Add(windowsDesktopApp);
@ -356,7 +350,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
private void LogAllUnusedPackages(DependencyContainer dependencies) =>
GetAllPackageDirectories()
.Where(package => !dependencies.UsedPackages.Contains(package))
.Where(package => !dependencies.Packages.Contains(package))
.ForEach(package => progressMonitor.LogInfo($"Unused package: {package}"));
private void GenerateSourceFileFromImplicitUsings()

Просмотреть файл

@ -128,7 +128,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
[GeneratedRegex("Restored\\s+(.+\\.csproj)", RegexOptions.Compiled)]
private static partial Regex RestoredProjectRegex();
[GeneratedRegex("[Assets\\sfile\\shas\\snot\\schanged.\\sSkipping\\sassets\\sfile\\swriting.|Writing\\sassets\\sfile\\sto\\sdisk.]\\sPath:\\s(.*)", RegexOptions.Compiled)]
[GeneratedRegex("[Assets\\sfile\\shas\\snot\\schanged.\\sSkipping\\sassets\\sfile\\swriting.|Writing\\sassets\\sfile\\sto\\sdisk.]\\sPath:\\s(.+)", RegexOptions.Compiled)]
private static partial Regex AssetsFileRegex();
}
}

Просмотреть файл

@ -0,0 +1,25 @@
using System.Collections.Generic;
using System.Linq;
namespace Semmle.Extraction.CSharp.DependencyFetching
{
internal static class FrameworkPackageNames
{
public static string AspNetCoreFramework { get; } = "microsoft.aspnetcore.app.ref";
public static string WindowsDesktopFramework { get; } = "microsoft.windowsdesktop.app.ref";
// The order of the packages is important.
public static string[] NetFrameworks { get; } = new string[]
{
"microsoft.netcore.app.ref", // net7.0, ... net5.0, netcoreapp3.1, netcoreapp3.0
"microsoft.netframework.referenceassemblies.", // net48, ..., net20
"netstandard.library.ref", // netstandard2.1
"netstandard.library" // netstandard2.0
};
public static IEnumerable<string> AllFrameworks { get; } =
NetFrameworks
.Union(new string[] { AspNetCoreFramework, WindowsDesktopFramework });
}
}

Просмотреть файл

@ -89,8 +89,10 @@ namespace Semmle.Extraction.CSharp.Populators
SyntaxKind.ModuleKeyword => Entities.AttributeKind.Module,
_ => throw new InternalError(node, "Unhandled global target")
};
foreach (var attribute in node.Attributes)
var attributes = node.Attributes;
for (var i = 0; i < attributes.Count; i++)
{
var attribute = attributes[i];
if (attributeLookup.Value(attribute) is AttributeData attributeData)
{
var ae = Entities.Attribute.Create(Cx, attributeData, outputAssembly, kind);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,3 +1,7 @@
## 1.7.3
No user-facing changes.
## 1.7.2
No user-facing changes.

Просмотреть файл

@ -0,0 +1,3 @@
## 1.7.3
No user-facing changes.

Просмотреть файл

@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.7.2
lastReleaseVersion: 1.7.3

Просмотреть файл

@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-all
version: 1.7.3-dev
version: 1.7.4-dev
groups:
- csharp
- solorigate

Просмотреть файл

@ -1,3 +1,7 @@
## 1.7.3
No user-facing changes.
## 1.7.2
No user-facing changes.

Просмотреть файл

@ -0,0 +1,3 @@
## 1.7.3
No user-facing changes.

Просмотреть файл

@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.7.2
lastReleaseVersion: 1.7.3

Просмотреть файл

@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-queries
version: 1.7.3-dev
version: 1.7.4-dev
groups:
- csharp
- solorigate

Просмотреть файл

@ -2,10 +2,10 @@ import os
from create_database_utils import *
from diagnostics_test_utils import *
run_codeql_database_create(['dotnet pack'], db=None, lang="csharp")
run_codeql_database_create(['dotnet pack -o nugetpackage'], db=None, lang="csharp")
## Check that the NuGet package is created.
if not os.path.isfile("bin/Debug/dotnet_pack.1.0.0.nupkg"):
if not os.path.isfile("nugetpackage/dotnet_pack.1.0.0.nupkg"):
raise Exception("The NuGet package was not created.")
check_diagnostics()

Просмотреть файл

@ -7,6 +7,7 @@
<IsPackable>false</IsPackable>
<OutputType>Exe</OutputType>
<SelfContained>false</SelfContained>
</PropertyGroup>
<ItemGroup>

Просмотреть файл

@ -1,3 +1,49 @@
## 0.8.3
### Minor Analysis Improvements
* The predicate `UnboundGeneric::getName` now prints the number of type parameters as a `` `N`` suffix, instead of a `<,...,>` suffix. For example, the unbound generic type
`System.Collections.Generic.IList<T>` is printed as ``IList`1`` instead of `IList<>`.
* The predicates `hasQualifiedName`, `getQualifiedName`, and `getQualifiedNameWithTypes` have been deprecated, and are instead replaced by `hasFullyQualifiedName`, `getFullyQualifiedName`, and `getFullyQualifiedNameWithTypes`, respectively. The new predicates use the same format for unbound generic types as mentioned above.
* These changes also affect models-as-data rows that refer to a field or a property belonging to a generic type. For example, instead of writing
```yml
extensions:
- addsTo:
pack: codeql/csharp-all
extensible: summaryModel
data:
- ["System.Collections.Generic", "Dictionary<TKey,TValue>", False, "Add", "(System.Collections.Generic.KeyValuePair<TKey,TValue>)", "", "Argument[0].Property[System.Collections.Generic.KeyValuePair<,>.Key]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "value", "manual"]
```
one now writes
```yml
extensions:
- addsTo:
pack: codeql/csharp-all
extensible: summaryModel
data:
- ["System.Collections.Generic", "Dictionary<TKey,TValue>", False, "Add", "(System.Collections.Generic.KeyValuePair<TKey,TValue>)", "", "Argument[0].Property[System.Collections.Generic.KeyValuePair`2.Key]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair`2.Key]", "value", "manual"]
```
* The models-as-data format for types and methods with type parameters has been changed to include the names of the type parameters. For example, instead of writing
```yml
extensions:
- addsTo:
pack: codeql/csharp-all
extensible: summaryModel
data:
- ["System.Collections.Generic", "IList<>", True, "Insert", "(System.Int32,T)", "", "Argument[1]", "Argument[this].Element", "value", "manual"]
- ["System.Linq", "Enumerable", False, "Select<,>", "(System.Collections.Generic.IEnumerable<TSource>,System.Func<TSource,System.Int32,TResult>)", "", "Argument[0].Element", "Argument[1].Parameter[0]", "value", "manual"]
```
one now writes
```yml
extensions:
- addsTo:
pack: codeql/csharp-all
extensible: summaryModel
data:
- ["System.Collections.Generic", "IList<T>", True, "Insert", "(System.Int32,T)", "", "Argument[1]", "Argument[this].Element", "value", "manual"]
- ["System.Linq", "Enumerable", False, "Select<TSource,TResult>", "(System.Collections.Generic.IEnumerable<TSource>,System.Func<TSource,System.Int32,TResult>)", "", "Argument[0].Element", "Argument[1].Parameter[0]", "value", "manual"]
```
## 0.8.2
No user-facing changes.

Просмотреть файл

@ -1,24 +0,0 @@
---
category: minorAnalysis
---
* The models-as-data format for types and methods with type parameters has been changed to include the names of the type parameters. For example, instead of writing
```yml
extensions:
- addsTo:
pack: codeql/csharp-all
extensible: summaryModel
data:
- ["System.Collections.Generic", "IList<>", True, "Insert", "(System.Int32,T)", "", "Argument[1]", "Argument[this].Element", "value", "manual"]
- ["System.Linq", "Enumerable", False, "Select<,>", "(System.Collections.Generic.IEnumerable<TSource>,System.Func<TSource,System.Int32,TResult>)", "", "Argument[0].Element", "Argument[1].Parameter[0]", "value", "manual"]
```
one now writes
```yml
extensions:
- addsTo:
pack: codeql/csharp-all
extensible: summaryModel
data:
- ["System.Collections.Generic", "IList<T>", True, "Insert", "(System.Int32,T)", "", "Argument[1]", "Argument[this].Element", "value", "manual"]
- ["System.Linq", "Enumerable", False, "Select<TSource,TResult>", "(System.Collections.Generic.IEnumerable<TSource>,System.Func<TSource,System.Int32,TResult>)", "", "Argument[0].Element", "Argument[1].Parameter[0]", "value", "manual"]
```

Просмотреть файл

@ -1,6 +1,6 @@
---
category: minorAnalysis
---
## 0.8.3
### Minor Analysis Improvements
* The predicate `UnboundGeneric::getName` now prints the number of type parameters as a `` `N`` suffix, instead of a `<,...,>` suffix. For example, the unbound generic type
`System.Collections.Generic.IList<T>` is printed as ``IList`1`` instead of `IList<>`.
@ -23,3 +23,23 @@ extensions:
data:
- ["System.Collections.Generic", "Dictionary<TKey,TValue>", False, "Add", "(System.Collections.Generic.KeyValuePair<TKey,TValue>)", "", "Argument[0].Property[System.Collections.Generic.KeyValuePair`2.Key]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair`2.Key]", "value", "manual"]
```
* The models-as-data format for types and methods with type parameters has been changed to include the names of the type parameters. For example, instead of writing
```yml
extensions:
- addsTo:
pack: codeql/csharp-all
extensible: summaryModel
data:
- ["System.Collections.Generic", "IList<>", True, "Insert", "(System.Int32,T)", "", "Argument[1]", "Argument[this].Element", "value", "manual"]
- ["System.Linq", "Enumerable", False, "Select<,>", "(System.Collections.Generic.IEnumerable<TSource>,System.Func<TSource,System.Int32,TResult>)", "", "Argument[0].Element", "Argument[1].Parameter[0]", "value", "manual"]
```
one now writes
```yml
extensions:
- addsTo:
pack: codeql/csharp-all
extensible: summaryModel
data:
- ["System.Collections.Generic", "IList<T>", True, "Insert", "(System.Int32,T)", "", "Argument[1]", "Argument[this].Element", "value", "manual"]
- ["System.Linq", "Enumerable", False, "Select<TSource,TResult>", "(System.Collections.Generic.IEnumerable<TSource>,System.Func<TSource,System.Int32,TResult>)", "", "Argument[0].Element", "Argument[1].Parameter[0]", "value", "manual"]
```

Просмотреть файл

@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.8.2
lastReleaseVersion: 0.8.3

Просмотреть файл

@ -1,5 +1,5 @@
name: codeql/csharp-all
version: 0.8.3-dev
version: 0.8.4-dev
groups: csharp
dbscheme: semmlecode.csharp.dbscheme
extractor: csharp

Просмотреть файл

@ -1,7 +1,7 @@
private import cil
private import codeql.ssa.Ssa as SsaImplCommon
private module SsaInput implements SsaImplCommon::InputSig {
private module SsaInput implements SsaImplCommon::InputSig<CIL::Location> {
class BasicBlock = CIL::BasicBlock;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result = bb.getImmediateDominator() }
@ -29,7 +29,7 @@ private module SsaInput implements SsaImplCommon::InputSig {
}
}
import SsaImplCommon::Make<SsaInput>
import SsaImplCommon::Make<CIL::Location, SsaInput>
cached
private module Cached {

Просмотреть файл

@ -36,7 +36,7 @@ module PreSsa {
scopeFirst(c, bb)
}
module SsaInput implements SsaImplCommon::InputSig {
module SsaInput implements SsaImplCommon::InputSig<Location> {
class BasicBlock = PreBasicBlocks::PreBasicBlock;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result.immediatelyDominates(bb) }
@ -137,7 +137,7 @@ module PreSsa {
}
}
private module SsaImpl = SsaImplCommon::Make<SsaInput>;
private module SsaImpl = SsaImplCommon::Make<Location, SsaInput>;
class Definition extends SsaImpl::Definition {
final AssignableRead getARead() {

Просмотреть файл

@ -24,7 +24,7 @@ module BaseSsa {
)
}
private module SsaInput implements SsaImplCommon::InputSig {
private module SsaInput implements SsaImplCommon::InputSig<Location> {
class BasicBlock = ControlFlow::BasicBlock;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) {
@ -60,7 +60,7 @@ module BaseSsa {
}
}
private module SsaImpl = SsaImplCommon::Make<SsaInput>;
private module SsaImpl = SsaImplCommon::Make<Location, SsaInput>;
class Definition extends SsaImpl::Definition {
final AssignableRead getARead() {

Просмотреть файл

@ -6,7 +6,7 @@ import csharp
private import codeql.ssa.Ssa as SsaImplCommon
private import AssignableDefinitions
private module SsaInput implements SsaImplCommon::InputSig {
private module SsaInput implements SsaImplCommon::InputSig<Location> {
class BasicBlock = ControlFlow::BasicBlock;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result = bb.getImmediateDominator() }
@ -49,7 +49,7 @@ private module SsaInput implements SsaImplCommon::InputSig {
}
}
private import SsaImplCommon::Make<SsaInput> as Impl
private import SsaImplCommon::Make<Location, SsaInput> as Impl
class Definition = Impl::Definition;

Просмотреть файл

@ -27,8 +27,9 @@ private class ExternalModelSink extends ExternalLocationSink {
*/
class LogMessageSink extends ExternalLocationSink {
LogMessageSink() {
this.getExpr() = any(LoggerType i).getAMethod().getACall().getAnArgument()
or
this.getExpr() = any(LoggerType i).getAMethod().getACall().getAnArgument() or
this.getExpr() =
any(MethodCall call | call.getQualifier().getType() instanceof LoggerType).getAnArgument() or
this.getExpr() =
any(ExtensionMethodCall call |
call.getTarget().(ExtensionMethod).getExtendedType() instanceof LoggerType

Просмотреть файл

@ -1,3 +1,9 @@
## 0.8.3
### Minor Analysis Improvements
* CIL extraction is now disabled by default. It is still possible to turn on CIL extraction by setting the `cil` extractor option to `true` or by setting the environment variable `$CODEQL_EXTRACTOR_CSHARP_OPTION_CIL` to `true`. This is the first step towards sun-setting the CIL extractor entirely.
## 0.8.2
No user-facing changes.

Просмотреть файл

@ -29,11 +29,6 @@ number generator. <code>Random</code> is not cryptographically secure, and shoul
security contexts. For contexts which are not security sensitive, <code>Random</code> may be
preferable as it has a more convenient interface, and is likely to be faster.
</p>
<p>
For the specific use-case of generating passwords, consider
<code>System.Web.Security.Membership.GeneratePassword</code>, which provides a cryptographically
secure method of generating random passwords.
</p>
</recommendation>
@ -54,10 +49,7 @@ purpose. In this case, it is much harder to predict the generated integers.
</p>
<p>
In the final example, the password is generated using the <code>Membership.GeneratePassword</code>
library method, which uses a cryptographically secure random number generator to generate a random
series of characters. This method should be preferred when generating passwords, if possible, as it
avoids potential pitfalls when converting the output of a random number generator (usually an int or
a byte) to a series of permitted characters.
library method, which generates a password with a bias, therefore should be avoided.
</p>
<sample src="InsecureRandomness.cs" />

Просмотреть файл

@ -1,4 +1,5 @@
---
category: minorAnalysis
---
* CIL extraction is now disabled by default. It is still possible to turn on CIL extraction by setting the `cil` extractor option to `true` or by setting the environment variable `$CODEQL_EXTRACTOR_CSHARP_OPTION_CIL` to `true`. This is the first step towards sun-setting the CIL extractor entirely.
## 0.8.3
### Minor Analysis Improvements
* CIL extraction is now disabled by default. It is still possible to turn on CIL extraction by setting the `cil` extractor option to `true` or by setting the environment variable `$CODEQL_EXTRACTOR_CSHARP_OPTION_CIL` to `true`. This is the first step towards sun-setting the CIL extractor entirely.

Просмотреть файл

@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.8.2
lastReleaseVersion: 0.8.3

Просмотреть файл

@ -1,5 +1,5 @@
name: codeql/csharp-queries
version: 0.8.3-dev
version: 0.8.4-dev
groups:
- csharp
- queries

Просмотреть файл

@ -0,0 +1,2 @@
| standalone.cs:3:12:3:29 | [assembly: Attribute1(...)] |
| standalone.cs:9:2:9:11 | [Attribute1(...)] |

Просмотреть файл

@ -0,0 +1,5 @@
import csharp
from Attribute a
where a.getType().getName() = "Attribute1Attribute"
select a

Просмотреть файл

@ -0,0 +1 @@
semmle-extractor-options: --standalone

Просмотреть файл

@ -0,0 +1,12 @@
using System;
[assembly: global::Attribute1]
class Attribute1Attribute : Attribute
{
}
[Attribute1]
class A
{
}

Просмотреть файл

@ -0,0 +1,8 @@
#select
| standalone.cs:20:20:20:20 | access to parameter s | standalone.cs:20:20:20:20 | access to parameter s |
| standalone.cs:25:28:25:32 | "abc" | standalone.cs:25:28:25:32 | "abc" |
compilationErrors
| standalone.cs:16:12:16:18 | CS0104: 'ILogger' is an ambiguous reference between 'A.ILogger' and 'B.ILogger' |
methodCalls
| standalone.cs:20:9:20:21 | call to method |
| standalone.cs:25:9:25:33 | call to method |

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше