Merge branch 'main' into LoadClassNoSignatureCheck

This commit is contained in:
masterofnow
2023-11-30 10:05:00 +08:00
committed by GitHub
2661 changed files with 111110 additions and 6363 deletions

View File

@@ -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

View File

@@ -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"

View File

@@ -145,9 +145,9 @@ namespace Semmle.Autobuild.Cpp.Tests
bool IBuildActions.IsMacOs() => IsMacOs;
public bool IsArm { get; set; }
public bool IsRunningOnAppleSilicon { get; set; }
bool IBuildActions.IsArm() => IsArm;
bool IBuildActions.IsRunningOnAppleSilicon() => IsRunningOnAppleSilicon;
string IBuildActions.PathCombine(params string[] parts)
{

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
description: Expose whether a function was prototyped or not
compatibility: backwards
function_prototyped.rel: delete

View File

@@ -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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* Added an `isPrototyped` predicate to `Function` that holds when the function has a prototype.

View File

@@ -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.

View File

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

View File

@@ -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

View File

@@ -112,6 +112,16 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
*/
predicate isDeleted() { function_deleted(underlyingElement(this)) }
/**
* Holds if this function has a prototyped interface.
*
* Functions generally have a prototyped interface, unless they are
* K&R-style functions either without any forward function declaration,
* or with all the forward declarations omitting the parameters of the
* function.
*/
predicate isPrototyped() { function_prototyped(underlyingElement(this)) }
/**
* Holds if this function is explicitly defaulted with the `= default`
* specifier.

View File

@@ -30,11 +30,6 @@ class GuardCondition extends Expr {
or
// no binary operators in the IR
this.(BinaryLogicalOperation).getAnOperand() instanceof GuardCondition
or
// the IR short-circuits if(!x)
// don't produce a guard condition for `y = !x` and other non-short-circuited cases
not exists(Instruction inst | this.getFullyConverted() = inst.getAst()) and
exists(IRGuardCondition ir | this.(NotExpr).getOperand() = ir.getAst())
}
/**
@@ -140,39 +135,6 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
}
}
/**
* A `!` operator in the AST that guards one or more basic blocks, and does not have a corresponding
* IR instruction.
*/
private class GuardConditionFromShortCircuitNot extends GuardCondition, NotExpr {
GuardConditionFromShortCircuitNot() {
not exists(Instruction inst | this.getFullyConverted() = inst.getAst()) and
exists(IRGuardCondition ir | this.getOperand() = ir.getAst())
}
override predicate controls(BasicBlock controlled, boolean testIsTrue) {
this.getOperand().(GuardCondition).controls(controlled, testIsTrue.booleanNot())
}
override predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) {
this.getOperand()
.(GuardCondition)
.comparesLt(left, right, k, isLessThan, testIsTrue.booleanNot())
}
override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) {
this.getOperand().(GuardCondition).ensuresLt(left, right, k, block, isLessThan.booleanNot())
}
override predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) {
this.getOperand().(GuardCondition).comparesEq(left, right, k, areEqual, testIsTrue.booleanNot())
}
override predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) {
this.getOperand().(GuardCondition).ensuresEq(left, right, k, block, areEqual.booleanNot())
}
}
/**
* A Boolean condition in the AST that guards one or more basic blocks and has a corresponding IR
* instruction.

View File

@@ -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())

View File

@@ -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)
}
}

View File

@@ -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() {

View File

@@ -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, _)))
)
}

View File

@@ -72,6 +72,16 @@ private predicate operandToInstructionTaintStep(Operand opFrom, Instruction inst
or
instrTo.(FieldAddressInstruction).getField().getDeclaringType() instanceof Union
)
or
// Taint from int to boolean casts. This ensures that we have flow to `!x` in:
// ```cpp
// x = integer_source();
// if(!x) { ... }
// ```
exists(Operand zero |
zero.getDef().(ConstantValueInstruction).getValue() = "0" and
instrTo.(CompareNEInstruction).hasOperands(opFrom, zero)
)
}
/**

View File

@@ -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() {

View File

@@ -12,6 +12,9 @@ int getConstantValue(Instruction instr) {
or
result = getConstantValue(instr.(CopyInstruction).getSourceValue())
or
getConstantValue(instr.(LogicalNotInstruction).getUnary()) != 0 and
result = 0
or
exists(PhiInstruction phi |
phi = instr and
result = unique(Operand op | op = phi.getAnInputOperand() | getConstantValue(op.getDef()))
@@ -26,28 +29,25 @@ private predicate binaryInstructionOperands(BinaryInstruction instr, int left, i
pragma[noinline]
private int getBinaryInstructionValue(BinaryInstruction instr) {
exists(int left, int right |
binaryInstructionOperands(instr, left, right) and
(
instr instanceof AddInstruction and result = add(left, right)
or
instr instanceof SubInstruction and result = sub(left, right)
or
instr instanceof MulInstruction and result = mul(left, right)
or
instr instanceof DivInstruction and result = div(left, right)
or
instr instanceof CompareEQInstruction and result = compareEQ(left, right)
or
instr instanceof CompareNEInstruction and result = compareNE(left, right)
or
instr instanceof CompareLTInstruction and result = compareLT(left, right)
or
instr instanceof CompareGTInstruction and result = compareGT(left, right)
or
instr instanceof CompareLEInstruction and result = compareLE(left, right)
or
instr instanceof CompareGEInstruction and result = compareGE(left, right)
)
exists(int left, int right | binaryInstructionOperands(instr, left, right) |
instr instanceof AddInstruction and result = add(left, right)
or
instr instanceof SubInstruction and result = sub(left, right)
or
instr instanceof MulInstruction and result = mul(left, right)
or
instr instanceof DivInstruction and result = div(left, right)
or
instr instanceof CompareEQInstruction and result = compareEQ(left, right)
or
instr instanceof CompareNEInstruction and result = compareNE(left, right)
or
instr instanceof CompareLTInstruction and result = compareLT(left, right)
or
instr instanceof CompareGTInstruction and result = compareGT(left, right)
or
instr instanceof CompareLEInstruction and result = compareLE(left, right)
or
instr instanceof CompareGEInstruction and result = compareGE(left, right)
)
}

View File

@@ -12,6 +12,9 @@ int getConstantValue(Instruction instr) {
or
result = getConstantValue(instr.(CopyInstruction).getSourceValue())
or
getConstantValue(instr.(LogicalNotInstruction).getUnary()) != 0 and
result = 0
or
exists(PhiInstruction phi |
phi = instr and
result = unique(Operand op | op = phi.getAnInputOperand() | getConstantValue(op.getDef()))
@@ -26,28 +29,25 @@ private predicate binaryInstructionOperands(BinaryInstruction instr, int left, i
pragma[noinline]
private int getBinaryInstructionValue(BinaryInstruction instr) {
exists(int left, int right |
binaryInstructionOperands(instr, left, right) and
(
instr instanceof AddInstruction and result = add(left, right)
or
instr instanceof SubInstruction and result = sub(left, right)
or
instr instanceof MulInstruction and result = mul(left, right)
or
instr instanceof DivInstruction and result = div(left, right)
or
instr instanceof CompareEQInstruction and result = compareEQ(left, right)
or
instr instanceof CompareNEInstruction and result = compareNE(left, right)
or
instr instanceof CompareLTInstruction and result = compareLT(left, right)
or
instr instanceof CompareGTInstruction and result = compareGT(left, right)
or
instr instanceof CompareLEInstruction and result = compareLE(left, right)
or
instr instanceof CompareGEInstruction and result = compareGE(left, right)
)
exists(int left, int right | binaryInstructionOperands(instr, left, right) |
instr instanceof AddInstruction and result = add(left, right)
or
instr instanceof SubInstruction and result = sub(left, right)
or
instr instanceof MulInstruction and result = mul(left, right)
or
instr instanceof DivInstruction and result = div(left, right)
or
instr instanceof CompareEQInstruction and result = compareEQ(left, right)
or
instr instanceof CompareNEInstruction and result = compareNE(left, right)
or
instr instanceof CompareLTInstruction and result = compareLT(left, right)
or
instr instanceof CompareGTInstruction and result = compareGT(left, right)
or
instr instanceof CompareLEInstruction and result = compareLE(left, right)
or
instr instanceof CompareGEInstruction and result = compareGE(left, right)
)
}

View File

@@ -77,24 +77,6 @@ class TranslatedParenthesisCondition extends TranslatedFlexibleCondition {
}
}
class TranslatedNotCondition extends TranslatedFlexibleCondition {
override NotExpr expr;
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
child = this.getOperand() and
result = this.getConditionContext().getChildFalseSuccessor(this)
}
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
child = this.getOperand() and
result = this.getConditionContext().getChildTrueSuccessor(this)
}
override TranslatedCondition getOperand() {
result = getTranslatedCondition(expr.getOperand().getFullyConverted())
}
}
abstract class TranslatedNativeCondition extends TranslatedCondition, TTranslatedNativeCondition {
TranslatedNativeCondition() { this = TTranslatedNativeCondition(expr) }

View File

@@ -190,10 +190,7 @@ private predicate isNativeCondition(Expr expr) {
* depending on context.
*/
private predicate isFlexibleCondition(Expr expr) {
(
expr instanceof ParenthesisExpr or
expr instanceof NotExpr
) and
expr instanceof ParenthesisExpr and
usedAsCondition(expr) and
not isIRConstant(expr)
}
@@ -218,11 +215,6 @@ private predicate usedAsCondition(Expr expr) {
condExpr.getCondition().getFullyConverted() = expr and not condExpr.isTwoOperand()
)
or
exists(NotExpr notExpr |
notExpr.getOperand().getFullyConverted() = expr and
usedAsCondition(notExpr)
)
or
exists(ParenthesisExpr paren |
paren.getExpr() = expr and
usedAsCondition(paren)

View File

@@ -12,6 +12,9 @@ int getConstantValue(Instruction instr) {
or
result = getConstantValue(instr.(CopyInstruction).getSourceValue())
or
getConstantValue(instr.(LogicalNotInstruction).getUnary()) != 0 and
result = 0
or
exists(PhiInstruction phi |
phi = instr and
result = unique(Operand op | op = phi.getAnInputOperand() | getConstantValue(op.getDef()))
@@ -26,28 +29,25 @@ private predicate binaryInstructionOperands(BinaryInstruction instr, int left, i
pragma[noinline]
private int getBinaryInstructionValue(BinaryInstruction instr) {
exists(int left, int right |
binaryInstructionOperands(instr, left, right) and
(
instr instanceof AddInstruction and result = add(left, right)
or
instr instanceof SubInstruction and result = sub(left, right)
or
instr instanceof MulInstruction and result = mul(left, right)
or
instr instanceof DivInstruction and result = div(left, right)
or
instr instanceof CompareEQInstruction and result = compareEQ(left, right)
or
instr instanceof CompareNEInstruction and result = compareNE(left, right)
or
instr instanceof CompareLTInstruction and result = compareLT(left, right)
or
instr instanceof CompareGTInstruction and result = compareGT(left, right)
or
instr instanceof CompareLEInstruction and result = compareLE(left, right)
or
instr instanceof CompareGEInstruction and result = compareGE(left, right)
)
exists(int left, int right | binaryInstructionOperands(instr, left, right) |
instr instanceof AddInstruction and result = add(left, right)
or
instr instanceof SubInstruction and result = sub(left, right)
or
instr instanceof MulInstruction and result = mul(left, right)
or
instr instanceof DivInstruction and result = div(left, right)
or
instr instanceof CompareEQInstruction and result = compareEQ(left, right)
or
instr instanceof CompareNEInstruction and result = compareNE(left, right)
or
instr instanceof CompareLTInstruction and result = compareLT(left, right)
or
instr instanceof CompareGTInstruction and result = compareGT(left, right)
or
instr instanceof CompareLEInstruction and result = compareLE(left, right)
or
instr instanceof CompareGEInstruction and result = compareGE(left, right)
)
}

View File

@@ -16,10 +16,7 @@ class Getenv extends LocalFlowSourceFunction {
}
override predicate hasLocalFlowSource(FunctionOutput output, string description) {
(
output.isReturnValueDeref() or
output.isReturnValue()
) and
output.isReturnValueDeref() and
description = "an environment variable"
}
}

View File

@@ -51,7 +51,6 @@ private class FgetsFunction extends DataFlowFunction, TaintFunction, ArrayFuncti
override predicate hasRemoteFlowSource(FunctionOutput output, string description) {
(
output.isParameterDeref(0) or
output.isReturnValue() or
output.isReturnValueDeref()
) and
description = "string read by " + this.getName()
@@ -102,7 +101,6 @@ private class GetsFunction extends DataFlowFunction, ArrayFunction, AliasFunctio
override predicate hasLocalFlowSource(FunctionOutput output, string description) {
(
output.isParameterDeref(0) or
output.isReturnValue() or
output.isReturnValueDeref()
) and
description = "string read by " + this.getName()

View File

@@ -123,7 +123,7 @@ private class StdSequenceContainerData extends TaintFunction {
/**
* The standard container functions `push_back` and `push_front`.
*/
private class StdSequenceContainerPush extends TaintFunction {
class StdSequenceContainerPush extends MemberFunction {
StdSequenceContainerPush() {
this.getClassAndName("push_back") instanceof Vector or
this.getClassAndName(["push_back", "push_front"]) instanceof Deque or
@@ -131,6 +131,17 @@ private class StdSequenceContainerPush extends TaintFunction {
this.getClassAndName(["push_back", "push_front"]) instanceof List
}
/**
* Gets the index of a parameter to this function that is a reference to the
* value type of the container.
*/
int getAValueTypeParameterIndex() {
this.getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() =
this.getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector<T>`
}
}
private class StdSequenceContainerPushModel extends StdSequenceContainerPush, TaintFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from parameter to qualifier
input.isParameterDeref(0) and
@@ -160,7 +171,7 @@ private class StdSequenceContainerFrontBack extends TaintFunction {
/**
* The standard container functions `insert` and `insert_after`.
*/
private class StdSequenceContainerInsert extends TaintFunction {
class StdSequenceContainerInsert extends MemberFunction {
StdSequenceContainerInsert() {
this.getClassAndName("insert") instanceof Deque or
this.getClassAndName("insert") instanceof List or
@@ -181,7 +192,9 @@ private class StdSequenceContainerInsert extends TaintFunction {
* Gets the index of a parameter to this function that is an iterator.
*/
int getAnIteratorParameterIndex() { this.getParameter(result).getType() instanceof Iterator }
}
private class StdSequenceContainerInsertModel extends StdSequenceContainerInsert, TaintFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from parameter to container itself (qualifier) and return value
(
@@ -253,11 +266,28 @@ private class StdSequenceContainerAt extends TaintFunction {
}
/**
* The standard vector `emplace` function.
* The standard `emplace` function.
*/
class StdVectorEmplace extends TaintFunction {
StdVectorEmplace() { this.getClassAndName("emplace") instanceof Vector }
class StdSequenceEmplace extends MemberFunction {
StdSequenceEmplace() {
this.getClassAndName("emplace") instanceof Vector
or
this.getClassAndName("emplace") instanceof List
or
this.getClassAndName("emplace") instanceof Deque
}
/**
* Gets the index of a parameter to this function that is a reference to the
* value type of the container.
*/
int getAValueTypeParameterIndex() {
this.getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() =
this.getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector<T>`
}
}
private class StdSequenceEmplaceModel extends StdSequenceEmplace, TaintFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from any parameter except the position iterator to qualifier and return value
// (here we assume taint flow from any constructor parameter to the constructed object)
@@ -269,12 +299,36 @@ class StdVectorEmplace extends TaintFunction {
}
}
/**
* The standard vector `emplace` function.
*/
class StdVectorEmplace extends StdSequenceEmplace {
StdVectorEmplace() { this.getDeclaringType() instanceof Vector }
}
/**
* The standard vector `emplace_back` function.
*/
class StdVectorEmplaceBack extends TaintFunction {
StdVectorEmplaceBack() { this.getClassAndName("emplace_back") instanceof Vector }
class StdSequenceEmplaceBack extends MemberFunction {
StdSequenceEmplaceBack() {
this.getClassAndName("emplace_back") instanceof Vector
or
this.getClassAndName("emplace_back") instanceof List
or
this.getClassAndName("emplace_back") instanceof Deque
}
/**
* Gets the index of a parameter to this function that is a reference to the
* value type of the container.
*/
int getAValueTypeParameterIndex() {
this.getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() =
this.getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector<T>`
}
}
private class StdSequenceEmplaceBackModel extends StdSequenceEmplaceBack, TaintFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from any parameter to qualifier
// (here we assume taint flow from any constructor parameter to the constructed object)
@@ -282,3 +336,10 @@ class StdVectorEmplaceBack extends TaintFunction {
output.isQualifierObject()
}
}
/**
* The standard vector `emplace_back` function.
*/
class StdVectorEmplaceBack extends StdSequenceEmplaceBack {
StdVectorEmplaceBack() { this.getDeclaringType() instanceof Vector }
}

View File

@@ -99,9 +99,11 @@ private class StdStringConstructor extends Constructor, StdStringTaintFunction {
/**
* The `std::string` function `c_str`.
*/
private class StdStringCStr extends StdStringTaintFunction {
class StdStringCStr extends MemberFunction {
StdStringCStr() { this.getClassAndName("c_str") instanceof StdBasicString }
}
private class StdStringCStrModel extends StdStringCStr, StdStringTaintFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from string itself (qualifier) to return value
input.isQualifierObject() and
@@ -112,9 +114,11 @@ private class StdStringCStr extends StdStringTaintFunction {
/**
* The `std::string` function `data`.
*/
private class StdStringData extends StdStringTaintFunction {
class StdStringData extends MemberFunction {
StdStringData() { this.getClassAndName("data") instanceof StdBasicString }
}
private class StdStringDataModel extends StdStringData, StdStringTaintFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from string itself (qualifier) to return value
input.isQualifierObject() and

View File

@@ -405,6 +405,8 @@ function_deleted(unique int id: @function ref);
function_defaulted(unique int id: @function ref);
function_prototyped(unique int id: @function ref)
member_function_this_type(
unique int id: @function ref,
int this_type: @type ref

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Expose whether a function was prototyped or not
compatibility: partial

View File

@@ -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.

View File

@@ -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()

View File

@@ -14,25 +14,44 @@
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) { sourceType = source.getSourceType() }
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
}
}
from string processOperation, Expr arg, Expr source, PathNode sourceNode, PathNode sinkNode
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

View File

@@ -52,16 +52,17 @@ predicate isUnboundedWrite(BufferWrite bw) {
* Holds if `e` is a source buffer going into an unbounded write `bw` or a
* qualifier of (a qualifier of ...) such a source.
*/
predicate unboundedWriteSource(Expr e, BufferWrite bw) {
isUnboundedWrite(bw) and e = bw.getASource()
predicate unboundedWriteSource(Expr e, BufferWrite bw, boolean qualifier) {
isUnboundedWrite(bw) and e = bw.getASource() and qualifier = false
or
exists(FieldAccess fa | unboundedWriteSource(fa, bw) and e = fa.getQualifier())
exists(FieldAccess fa | unboundedWriteSource(fa, bw, _) and e = fa.getQualifier()) and
qualifier = true
}
predicate isSource(FS::FlowSource source, string sourceType) { source.getSourceType() = sourceType }
predicate isSink(DataFlow::Node sink, BufferWrite bw) {
unboundedWriteSource(sink.asIndirectExpr(), bw)
predicate isSink(DataFlow::Node sink, BufferWrite bw, boolean qualifier) {
unboundedWriteSource(sink.asIndirectExpr(), bw, qualifier)
or
// `gets` and `scanf` reads from stdin so there's no real input.
// The `BufferWrite` library models this as the call itself being
@@ -69,7 +70,7 @@ predicate isSink(DataFlow::Node sink, BufferWrite bw) {
// the sink so that we report a path where source = sink (because
// the same output argument is also included in `isSource`).
bw.getASource() = bw and
unboundedWriteSource(sink.asDefiningArgument(), bw)
unboundedWriteSource(sink.asDefiningArgument(), bw, qualifier)
}
predicate lessThanOrEqual(IRGuardCondition g, Expr e, boolean branch) {
@@ -84,9 +85,9 @@ predicate lessThanOrEqual(IRGuardCondition g, Expr e, boolean branch) {
module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { isSource(source, _) }
predicate isSink(DataFlow::Node sink) { isSink(sink, _) }
predicate isSink(DataFlow::Node sink) { isSink(sink, _, _) }
predicate isBarrierOut(DataFlow::Node node) { isSink(node) }
predicate isBarrierOut(DataFlow::Node node) { isSink(node, _, false) }
predicate isBarrier(DataFlow::Node node) {
// Block flow if the node is guarded by any <, <= or = operations.
@@ -116,7 +117,7 @@ from BufferWrite bw, Flow::PathNode source, Flow::PathNode sink, string sourceTy
where
Flow::flowPath(source, sink) and
isSource(source.getNode(), sourceType) and
isSink(sink.getNode(), bw)
isSink(sink.getNode(), bw, _)
select bw, source, sink,
"This '" + bw.getBWDesc() + "' with input from $@ may overflow the destination.",
source.getNode(), sourceType

View File

@@ -16,22 +16,47 @@
import cpp
import semmle.code.cpp.security.Security
import semmle.code.cpp.security.FunctionWithWrappers
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
class Configuration extends TaintTrackingConfiguration {
override predicate isSink(Element tainted) {
exists(PrintfLikeFunction printf | printf.outermostWrapperFunctionCall(tainted, _))
predicate isSource(FlowSource source, string sourceType) { sourceType = source.getSourceType() }
module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { isSource(node, _) }
predicate isSink(DataFlow::Node node) {
exists(PrintfLikeFunction printf |
printf.outermostWrapperFunctionCall([node.asExpr(), node.asIndirectExpr()], _)
)
}
private predicate isArithmeticNonCharType(ArithmeticType type) {
not type instanceof CharType and
not type instanceof Char8Type and
not type instanceof Char16Type and
not type instanceof Char32Type
}
predicate isBarrier(DataFlow::Node node) {
isSink(node) and isArithmeticNonCharType(node.asExpr().getUnspecifiedType())
or
isArithmeticNonCharType(node.asInstruction().(StoreInstruction).getResultType())
}
}
module Flow = TaintTracking::Global<Config>;
from
PrintfLikeFunction printf, Expr arg, PathNode sourceNode, PathNode sinkNode,
string printfFunction, Expr userValue, string cause
PrintfLikeFunction printf, string printfFunction, string sourceType, DataFlow::Node source,
DataFlow::Node sink, Flow::PathNode sourceNode, Flow::PathNode sinkNode
where
printf.outermostWrapperFunctionCall(arg, printfFunction) and
taintedWithPath(userValue, arg, sourceNode, sinkNode) and
isUserInput(userValue, cause)
select arg, sourceNode, sinkNode,
source = sourceNode.getNode() and
sink = sinkNode.getNode() and
isSource(source, sourceType) and
printf.outermostWrapperFunctionCall([sink.asExpr(), sink.asIndirectExpr()], printfFunction) and
Flow::flowPath(sourceNode, sinkNode)
select sink, sourceNode, sinkNode,
"The value of this argument may come from $@ and is being used as a formatting argument to " +
printfFunction + ".", userValue, cause
printfFunction + ".", source, sourceType

View File

@@ -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);
}

View File

@@ -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>

View File

@@ -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

View File

@@ -12,79 +12,44 @@
import cpp
import semmle.code.cpp.commons.NullTermination
import semmle.code.cpp.ir.dataflow.internal.DefaultTaintTrackingImpl
import semmle.code.cpp.security.FlowSources as FS
import semmle.code.cpp.dataflow.new.TaintTracking
import semmle.code.cpp.ir.IR
/** A user-controlled expression that may not be null terminated. */
class TaintSource extends VariableAccess {
TaintSource() {
exists(SecurityOptions x, string cause |
this.getTarget() instanceof SemanticStackVariable and
x.isUserInput(this, cause)
|
cause = ["read", "fread", "recv", "recvfrom", "recvmsg"]
)
}
/**
* Holds if `sink` is a tainted variable access that must be null
* terminated.
*/
private predicate isSink(VariableAccess sink) {
tainted(this, sink) and
variableMustBeNullTerminated(sink)
}
/**
* Holds if this source can reach `va`, possibly using intermediate
* reassignments.
*/
private predicate sourceReaches(VariableAccess va) {
definitionUsePair(_, this, va)
or
exists(VariableAccess mid, Expr def |
this.sourceReaches(mid) and
exprDefinition(_, def, mid) and
definitionUsePair(_, def, va)
)
}
/**
* Holds if the sink `sink` is reachable both from this source and
* from `va`, possibly using intermediate reassignments.
*/
private predicate reachesSink(VariableAccess va, VariableAccess sink) {
this.isSink(sink) and
va = sink
or
exists(VariableAccess mid, Expr def |
this.reachesSink(mid, sink) and
exprDefinition(_, def, va) and
definitionUsePair(_, def, mid)
)
}
/**
* Holds if `sink` is a tainted variable access that must be null
* terminated, and no access which null terminates its contents can
* either reach the sink or be reached from the source. (Ideally,
* we should instead look for such accesses only on the path from
* this source to `sink` found via `tainted(source, sink)`.)
*/
predicate reaches(VariableAccess sink) {
this.isSink(sink) and
not exists(VariableAccess va |
va != this and
va != sink and
mayAddNullTerminator(_, va)
|
this.sourceReaches(va)
or
this.reachesSink(va, sink)
)
}
predicate isSource(FS::FlowSource source, string sourceType) {
sourceType = source.getSourceType() and
exists(VariableAccess va, Call call |
va = source.asDefiningArgument() and
call.getAnArgument() = va and
va.getTarget() instanceof SemanticStackVariable and
call.getTarget().hasGlobalName(["read", "fread", "recv", "recvfrom", "recvmsg"])
)
}
from TaintSource source, VariableAccess sink
where source.reaches(sink)
select sink, "String operation depends on a $@ that may not be null terminated.", source,
"user-provided value"
predicate isSink(DataFlow::Node sink, VariableAccess va) {
va = [sink.asExpr(), sink.asIndirectExpr()] and
variableMustBeNullTerminated(va)
}
private module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { isSource(source, _) }
predicate isBarrier(DataFlow::Node node) {
isSink(node) and node.asExpr().getUnspecifiedType() instanceof ArithmeticType
or
node.asInstruction().(StoreInstruction).getResultType() instanceof ArithmeticType
or
mayAddNullTerminator(_, node.asIndirectExpr())
}
predicate isSink(DataFlow::Node sink) { isSink(sink, _) }
}
module Flow = TaintTracking::Global<Config>;
from DataFlow::Node source, DataFlow::Node sink, VariableAccess va, string sourceType
where
Flow::flow(source, sink) and
isSource(source, sourceType) and
isSink(sink, va)
select va, "String operation depends on $@ that may not be null terminated.", source, sourceType

View File

@@ -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

View File

@@ -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"

View File

@@ -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

View File

@@ -12,8 +12,10 @@
* external/cwe/cwe-290
*/
import semmle.code.cpp.ir.dataflow.internal.DefaultTaintTrackingImpl
import TaintedWithPath
import cpp
import semmle.code.cpp.dataflow.new.TaintTracking
import semmle.code.cpp.security.FlowSources as FS
import Flow::PathGraph
string getATopLevelDomain() {
result =
@@ -60,13 +62,26 @@ predicate hardCodedAddressInCondition(Expr subexpression, Expr condition) {
condition = any(IfStmt ifStmt).getCondition()
}
class Configuration extends TaintTrackingConfiguration {
override predicate isSink(Element sink) { hardCodedAddressInCondition(sink, _) }
predicate isSource(FS::FlowSource source, string sourceType) { source.getSourceType() = sourceType }
predicate isSink(DataFlow::Node sink, Expr condition) {
hardCodedAddressInCondition([sink.asExpr(), sink.asIndirectExpr()], condition)
}
from Expr subexpression, Expr source, Expr condition, PathNode sourceNode, PathNode sinkNode
module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { isSource(source, _) }
predicate isSink(DataFlow::Node sink) { isSink(sink, _) }
}
module Flow = TaintTracking::Global<Config>;
from
Expr subexpression, Expr condition, Flow::PathNode source, Flow::PathNode sink, string sourceType
where
hardCodedAddressInCondition(subexpression, condition) and
taintedWithPath(source, subexpression, sourceNode, sinkNode)
select condition, sourceNode, sinkNode,
"Untrusted input $@ might be vulnerable to a spoofing attack.", source, source.toString()
isSource(source.getNode(), sourceType) and
Flow::flowPath(source, sink) and
isSink(sink.getNode(), condition)
select condition, source, sink, "Untrusted input $@ might be vulnerable to a spoofing attack.",
source, sourceType

View File

@@ -0,0 +1,44 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Calling <code>c_str</code> on a <code>std::string</code> object returns a pointer to the underlying character array.
When the <code>std::string</code> object is destroyed, the pointer returned by <code>c_str</code> is no
longer valid. If the pointer is used after the <code>std::string</code> object is destroyed, then the behavior is undefined.
</p>
</overview>
<recommendation>
<p>
Ensure that the pointer returned by <code>c_str</code> does not outlive the underlying <code>std::string</code> object.
</p>
</recommendation>
<example>
<p>
The following example concatenates two <code>std::string</code> objects, and then converts the resulting string to a
C string using <code>c_str</code> so that it can be passed to the <code>work</code> function.
However, the underlying <code>std::string</code> object that represents the concatenated string is destroyed as soon as the call
to <code>c_str</code> returns. This means that <code>work</code> is given a pointer to invalid memory.
</p>
<sample src="UseOfStringAfterLifetimeEndsBad.cpp" />
<p>
The following example fixes the above code by ensuring that the pointer returned by the call to <code>c_str</code> does
not outlive the underlying <code>std::string</code> objects. This ensures that the pointer passed to <code>work</code>
points to valid memory.
</p>
<sample src="UseOfStringAfterLifetimeEndsGood.cpp" />
</example>
<references>
<li><a href="https://wiki.sei.cmu.edu/confluence/display/cplusplus/MEM50-CPP.+Do+not+access+freed+memory">MEM50-CPP. Do not access freed memory</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,100 @@
/**
* @name Use of string after lifetime ends
* @description If the value of a call to 'c_str' outlives the underlying object it may lead to unexpected behavior.
* @kind problem
* @precision high
* @id cpp/use-of-string-after-lifetime-ends
* @problem.severity warning
* @security-severity 8.8
* @tags reliability
* security
* external/cwe/cwe-416
* external/cwe/cwe-664
*/
import cpp
import semmle.code.cpp.models.implementations.StdString
import semmle.code.cpp.models.implementations.StdContainer
/**
* Holds if `e` will be consumed by its parent as a glvalue and does not have
* an lvalue-to-rvalue conversion. This means that it will be materialized into
* a temporary object.
*/
predicate isTemporary(Expr e) {
e instanceof TemporaryObjectExpr
or
e.isPRValueCategory() and
e.getUnspecifiedType() instanceof Class and
not e.hasLValueToRValueConversion()
}
/** Holds if `e` is written to a container. */
predicate isStoredInContainer(Expr e) {
exists(StdSequenceContainerInsert insert, Call call, int index |
call = insert.getACallToThisFunction() and
index = insert.getAValueTypeParameterIndex() and
call.getArgument(index) = e
)
or
exists(StdSequenceContainerPush push, Call call, int index |
call = push.getACallToThisFunction() and
index = push.getAValueTypeParameterIndex() and
call.getArgument(index) = e
)
or
exists(StdSequenceEmplace emplace, Call call, int index |
call = emplace.getACallToThisFunction() and
index = emplace.getAValueTypeParameterIndex() and
call.getArgument(index) = e
)
or
exists(StdSequenceEmplaceBack emplaceBack, Call call, int index |
call = emplaceBack.getACallToThisFunction() and
index = emplaceBack.getAValueTypeParameterIndex() and
call.getArgument(index) = e
)
}
/**
* Holds if the value of `e` outlives the enclosing full expression. For
* example, because the value is stored in a local variable.
*/
predicate outlivesFullExpr(Expr e) {
any(Assignment assign).getRValue() = e
or
any(Variable v).getInitializer().getExpr() = e
or
any(ReturnStmt ret).getExpr() = e
or
exists(ConditionalExpr cond |
outlivesFullExpr(cond) and
[cond.getThen(), cond.getElse()] = e
)
or
exists(BinaryOperation bin |
outlivesFullExpr(bin) and
bin.getAnOperand() = e
)
or
exists(ClassAggregateLiteral aggr |
outlivesFullExpr(aggr) and
aggr.getAFieldExpr(_) = e
)
or
exists(ArrayAggregateLiteral aggr |
outlivesFullExpr(aggr) and
aggr.getAnElementExpr(_) = e
)
or
isStoredInContainer(e)
}
from Call c
where
outlivesFullExpr(c) and
not c.isFromUninstantiatedTemplate(_) and
(c.getTarget() instanceof StdStringCStr or c.getTarget() instanceof StdStringData) and
isTemporary(c.getQualifier().getFullyConverted())
select c,
"The underlying string object is destroyed after the call to '" + c.getTarget() + "' returns."

View File

@@ -0,0 +1,9 @@
#include <string>
void work(const char*);
// BAD: the concatenated string is deallocated when `c_str` returns. So `work`
// is given a pointer to invalid memory.
void work_with_combined_string_bad(std::string s1, std::string s2) {
const char* combined_string = (s1 + s2).c_str();
work(combined_string);
}

View File

@@ -0,0 +1,9 @@
#include <string>
void work(const char*);
// GOOD: the concatenated string outlives the call to `work`. So the pointer
// obtainted from `c_str` is valid.
void work_with_combined_string_good(std::string s1, std::string s2) {
auto combined_string = s1 + s2;
work(combined_string.c_str());
}

View File

@@ -12,8 +12,12 @@
* external/cwe/cwe-807
*/
import semmle.code.cpp.ir.dataflow.internal.DefaultTaintTrackingImpl
import TaintedWithPath
import cpp
import semmle.code.cpp.security.Security
import semmle.code.cpp.security.FlowSources
import semmle.code.cpp.ir.dataflow.TaintTracking
import semmle.code.cpp.ir.IR
import Flow::PathGraph
predicate sensitiveCondition(Expr condition, Expr raise) {
raisesPrivilege(raise) and
@@ -23,19 +27,62 @@ predicate sensitiveCondition(Expr condition, Expr raise) {
)
}
class Configuration extends TaintTrackingConfiguration {
override predicate isSink(Element tainted) { sensitiveCondition(tainted, _) }
private predicate constantInstruction(Instruction instr) {
instr instanceof ConstantInstruction
or
instr instanceof StringConstantInstruction
or
constantInstruction(instr.(UnaryInstruction).getUnary())
}
predicate isSource(FlowSource source, string sourceType) { sourceType = source.getSourceType() }
module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { isSource(node, _) }
predicate isSink(DataFlow::Node node) {
sensitiveCondition([node.asExpr(), node.asIndirectExpr()], _)
}
predicate isBarrier(DataFlow::Node node) {
// Block flow into binary instructions if both operands are non-constant
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 constant-ness
not iTo instanceof PointerArithmeticInstruction
)
or
// Block flow through calls to pure functions if two or more operands are non-constant
exists(Instruction iFrom1, Instruction iFrom2, CallInstruction iTo |
iTo = node.asInstruction() and
isPureFunction(iTo.getStaticCallTarget().getName()) and
iFrom1 = iTo.getAnArgument() and
iFrom2 = iTo.getAnArgument() and
not constantInstruction(iFrom1) and
not constantInstruction(iFrom2) and
iFrom1 != iFrom2
)
}
}
module Flow = TaintTracking::Global<Config>;
/*
* Produce an alert if there is an 'if' statement whose condition `condition`
* is influenced by tainted data `source`, and the body contains
* `raise` which escalates privilege.
*/
from Expr source, Expr condition, Expr raise, PathNode sourceNode, PathNode sinkNode
from
Expr raise, string sourceType, DataFlow::Node source, DataFlow::Node sink,
Flow::PathNode sourceNode, Flow::PathNode sinkNode
where
taintedWithPath(source, condition, sourceNode, sinkNode) and
sensitiveCondition(condition, raise)
select condition, sourceNode, sinkNode, "Reliance on untrusted input $@ to raise privilege at $@.",
source, source.toString(), raise, raise.toString()
source = sourceNode.getNode() and
sink = sinkNode.getNode() and
isSource(source, sourceType) and
sensitiveCondition([sink.asExpr(), sink.asIndirectExpr()], raise) and
Flow::flowPath(sourceNode, sinkNode)
select sink, sourceNode, sinkNode, "Reliance on $@ to raise privilege at $@.", source, sourceType,
raise, raise.toString()

View File

@@ -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

View File

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

View File

@@ -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`.

View File

@@ -0,0 +1,4 @@
---
category: newQuery
---
* Added a new query, `cpp/use-of-string-after-lifetime-ends`, to detect calls to `c_str` on strings that will be destroyed immediately.

View File

@@ -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.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -450,6 +450,7 @@ irGuards
| test.c:126:12:126:26 | Call: call to test3_condition |
| test.c:131:7:131:7 | Load: b |
| test.c:137:7:137:7 | Constant: 0 |
| test.c:146:7:146:8 | LogicalNot: ! ... |
| test.c:146:8:146:8 | Load: x |
| test.c:152:10:152:10 | Load: x |
| test.c:152:15:152:15 | Load: y |
@@ -640,6 +641,7 @@ irGuardsControl
| test.c:126:12:126:26 | Call: call to test3_condition | true | 127 | 127 |
| test.c:131:7:131:7 | Load: b | true | 132 | 132 |
| test.c:137:7:137:7 | Constant: 0 | false | 142 | 142 |
| test.c:146:7:146:8 | LogicalNot: ! ... | true | 147 | 147 |
| test.c:146:8:146:8 | Load: x | false | 147 | 147 |
| test.c:152:10:152:10 | Load: x | true | 152 | 152 |
| test.c:152:15:152:15 | Load: y | true | 152 | 152 |

View File

@@ -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>;
}

View File

@@ -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. |

View File

@@ -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 |

View File

@@ -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)
}

View File

@@ -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
}
}

View File

@@ -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

View File

@@ -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>>>

View File

@@ -2770,43 +2770,65 @@ ir.cpp:
# 462| m462_2(int) = Uninitialized[x] : &:r462_1
# 463| r463_1(glval<bool>) = VariableAddress[a] :
# 463| r463_2(bool) = Load[a] : &:r463_1, m461_6
# 463| v463_3(void) = ConditionalBranch : r463_2
#-----| False -> Block 1
#-----| True -> Block 2
# 463| r463_3(bool) = LogicalNot : r463_2
# 463| v463_4(void) = ConditionalBranch : r463_3
#-----| False -> Block 5
#-----| True -> Block 1
# 464| Block 1
# 464| r464_1(int) = Constant[1] :
# 464| r464_2(glval<int>) = VariableAddress[x] :
# 464| m464_3(int) = Store[x] : &:r464_2, r464_1
#-----| Goto -> Block 2
#-----| Goto -> Block 5
# 467| Block 2
# 467| r467_1(glval<bool>) = VariableAddress[a] :
# 467| r467_2(bool) = Load[a] : &:r467_1, m461_6
# 467| v467_3(void) = ConditionalBranch : r467_2
#-----| False -> Block 4
#-----| True -> Block 3
# 467| r467_1(glval<bool>) = VariableAddress[#temp467:11] :
# 467| r467_2(bool) = Constant[0] :
# 467| m467_3(bool) = Store[#temp467:11] : &:r467_1, r467_2
#-----| Goto -> Block 3
# 467| Block 3
# 467| r467_4(glval<bool>) = VariableAddress[b] :
# 467| r467_5(bool) = Load[b] : &:r467_4, m461_8
# 467| v467_6(void) = ConditionalBranch : r467_5
#-----| False -> Block 4
#-----| True -> Block 5
# 467| m467_4(bool) = Phi : from 2:m467_3, from 4:m467_11
# 467| r467_5(glval<bool>) = VariableAddress[#temp467:11] :
# 467| r467_6(bool) = Load[#temp467:11] : &:r467_5, m467_4
# 467| r467_7(bool) = LogicalNot : r467_6
# 467| v467_8(void) = ConditionalBranch : r467_7
#-----| False -> Block 8
#-----| True -> Block 7
# 468| Block 4
# 467| Block 4
# 467| r467_9(glval<bool>) = VariableAddress[#temp467:11] :
# 467| r467_10(bool) = Constant[1] :
# 467| m467_11(bool) = Store[#temp467:11] : &:r467_9, r467_10
#-----| Goto -> Block 3
# 467| Block 5
# 467| r467_12(glval<bool>) = VariableAddress[a] :
# 467| r467_13(bool) = Load[a] : &:r467_12, m461_6
# 467| v467_14(void) = ConditionalBranch : r467_13
#-----| False -> Block 2
#-----| True -> Block 6
# 467| Block 6
# 467| r467_15(glval<bool>) = VariableAddress[b] :
# 467| r467_16(bool) = Load[b] : &:r467_15, m461_8
# 467| v467_17(void) = ConditionalBranch : r467_16
#-----| False -> Block 2
#-----| True -> Block 4
# 468| Block 7
# 468| r468_1(int) = Constant[2] :
# 468| r468_2(glval<int>) = VariableAddress[x] :
# 468| m468_3(int) = Store[x] : &:r468_2, r468_1
#-----| Goto -> Block 6
#-----| Goto -> Block 9
# 471| Block 5
# 471| Block 8
# 471| r471_1(int) = Constant[3] :
# 471| r471_2(glval<int>) = VariableAddress[x] :
# 471| m471_3(int) = Store[x] : &:r471_2, r471_1
#-----| Goto -> Block 6
#-----| Goto -> Block 9
# 473| Block 6
# 473| Block 9
# 473| v473_1(void) = NoOp :
# 461| v461_9(void) = ReturnVoid :
# 461| v461_10(void) = AliasedUse : m461_3

View File

@@ -2398,16 +2398,27 @@
| ir.cpp:461:22:461:22 | Address | &:r461_5 |
| ir.cpp:461:30:461:30 | Address | &:r461_7 |
| ir.cpp:462:9:462:9 | Address | &:r462_1 |
| ir.cpp:463:9:463:10 | Condition | r463_3 |
| ir.cpp:463:10:463:10 | Address | &:r463_1 |
| ir.cpp:463:10:463:10 | Condition | r463_2 |
| ir.cpp:463:10:463:10 | Load | m461_6 |
| ir.cpp:463:10:463:10 | Unary | r463_2 |
| ir.cpp:464:9:464:9 | Address | &:r464_2 |
| ir.cpp:464:13:464:13 | StoreValue | r464_1 |
| ir.cpp:467:11:467:11 | Address | &:r467_1 |
| ir.cpp:467:11:467:11 | Condition | r467_2 |
| ir.cpp:467:9:467:17 | Condition | r467_7 |
| ir.cpp:467:11:467:11 | Address | &:r467_12 |
| ir.cpp:467:11:467:11 | Condition | r467_13 |
| ir.cpp:467:11:467:11 | Load | m461_6 |
| ir.cpp:467:16:467:16 | Address | &:r467_4 |
| ir.cpp:467:16:467:16 | Condition | r467_5 |
| ir.cpp:467:11:467:16 | Address | &:r467_1 |
| ir.cpp:467:11:467:16 | Address | &:r467_5 |
| ir.cpp:467:11:467:16 | Address | &:r467_9 |
| ir.cpp:467:11:467:16 | Load | m467_4 |
| ir.cpp:467:11:467:16 | Phi | from 2:m467_3 |
| ir.cpp:467:11:467:16 | Phi | from 4:m467_11 |
| ir.cpp:467:11:467:16 | StoreValue | r467_2 |
| ir.cpp:467:11:467:16 | StoreValue | r467_10 |
| ir.cpp:467:11:467:16 | Unary | r467_6 |
| ir.cpp:467:16:467:16 | Address | &:r467_15 |
| ir.cpp:467:16:467:16 | Condition | r467_16 |
| ir.cpp:467:16:467:16 | Load | m461_8 |
| ir.cpp:468:9:468:9 | Address | &:r468_2 |
| ir.cpp:468:13:468:13 | StoreValue | r468_1 |

View File

@@ -2725,43 +2725,64 @@ ir.cpp:
# 462| mu462_2(int) = Uninitialized[x] : &:r462_1
# 463| r463_1(glval<bool>) = VariableAddress[a] :
# 463| r463_2(bool) = Load[a] : &:r463_1, ~m?
# 463| v463_3(void) = ConditionalBranch : r463_2
#-----| False -> Block 1
#-----| True -> Block 2
# 463| r463_3(bool) = LogicalNot : r463_2
# 463| v463_4(void) = ConditionalBranch : r463_3
#-----| False -> Block 5
#-----| True -> Block 1
# 464| Block 1
# 464| r464_1(int) = Constant[1] :
# 464| r464_2(glval<int>) = VariableAddress[x] :
# 464| mu464_3(int) = Store[x] : &:r464_2, r464_1
#-----| Goto -> Block 2
#-----| Goto -> Block 5
# 467| Block 2
# 467| r467_1(glval<bool>) = VariableAddress[a] :
# 467| r467_2(bool) = Load[a] : &:r467_1, ~m?
# 467| v467_3(void) = ConditionalBranch : r467_2
#-----| False -> Block 4
#-----| True -> Block 3
# 467| r467_1(glval<bool>) = VariableAddress[#temp467:11] :
# 467| r467_2(bool) = Constant[0] :
# 467| mu467_3(bool) = Store[#temp467:11] : &:r467_1, r467_2
#-----| Goto -> Block 3
# 467| Block 3
# 467| r467_4(glval<bool>) = VariableAddress[b] :
# 467| r467_5(bool) = Load[b] : &:r467_4, ~m?
# 467| v467_6(void) = ConditionalBranch : r467_5
#-----| False -> Block 4
#-----| True -> Block 5
# 467| r467_4(glval<bool>) = VariableAddress[#temp467:11] :
# 467| r467_5(bool) = Load[#temp467:11] : &:r467_4, ~m?
# 467| r467_6(bool) = LogicalNot : r467_5
# 467| v467_7(void) = ConditionalBranch : r467_6
#-----| False -> Block 8
#-----| True -> Block 7
# 468| Block 4
# 467| Block 4
# 467| r467_8(glval<bool>) = VariableAddress[#temp467:11] :
# 467| r467_9(bool) = Constant[1] :
# 467| mu467_10(bool) = Store[#temp467:11] : &:r467_8, r467_9
#-----| Goto -> Block 3
# 467| Block 5
# 467| r467_11(glval<bool>) = VariableAddress[a] :
# 467| r467_12(bool) = Load[a] : &:r467_11, ~m?
# 467| v467_13(void) = ConditionalBranch : r467_12
#-----| False -> Block 2
#-----| True -> Block 6
# 467| Block 6
# 467| r467_14(glval<bool>) = VariableAddress[b] :
# 467| r467_15(bool) = Load[b] : &:r467_14, ~m?
# 467| v467_16(void) = ConditionalBranch : r467_15
#-----| False -> Block 2
#-----| True -> Block 4
# 468| Block 7
# 468| r468_1(int) = Constant[2] :
# 468| r468_2(glval<int>) = VariableAddress[x] :
# 468| mu468_3(int) = Store[x] : &:r468_2, r468_1
#-----| Goto -> Block 6
#-----| Goto -> Block 9
# 471| Block 5
# 471| Block 8
# 471| r471_1(int) = Constant[3] :
# 471| r471_2(glval<int>) = VariableAddress[x] :
# 471| mu471_3(int) = Store[x] : &:r471_2, r471_1
#-----| Goto -> Block 6
#-----| Goto -> Block 9
# 473| Block 6
# 473| Block 9
# 473| v473_1(void) = NoOp :
# 461| v461_8(void) = ReturnVoid :
# 461| v461_9(void) = AliasedUse : ~m?

View File

@@ -1,2 +1,2 @@
| test.cpp:466:10:466:15 | buffer | String operation depends on a $@ that may not be null terminated. | test.cpp:465:18:465:23 | buffer | user-provided value |
| test.cpp:481:10:481:15 | buffer | String operation depends on a $@ that may not be null terminated. | test.cpp:480:9:480:14 | buffer | user-provided value |
| test.cpp:466:10:466:15 | buffer | String operation depends on $@ that may not be null terminated. | test.cpp:465:18:465:23 | read output argument | buffer read by read |
| test.cpp:481:10:481:15 | buffer | String operation depends on $@ that may not be null terminated. | test.cpp:480:9:480:14 | fread output argument | string read by fread |

View File

@@ -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 |

View File

@@ -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
}

View File

@@ -14,18 +14,15 @@ edges
| test.cpp:91:9:91:16 | fread output argument | test.cpp:93:17:93:24 | filename indirection |
| test.cpp:93:11:93:14 | strncat output argument | test.cpp:94:45:94:48 | path indirection |
| test.cpp:93:17:93:24 | filename indirection | test.cpp:93:11:93:14 | strncat output argument |
| test.cpp:106:20:106:38 | call to getenv | test.cpp:107:33:107:36 | path indirection |
| test.cpp:106:20:106:38 | call to getenv indirection | test.cpp:107:33:107:36 | path indirection |
| test.cpp:107:31:107:31 | call to operator+ | test.cpp:108:18:108:22 | call to c_str indirection |
| test.cpp:107:33:107:36 | path indirection | test.cpp:107:31:107:31 | call to operator+ |
| test.cpp:113:20:113:38 | call to getenv | test.cpp:114:19:114:22 | path indirection |
| test.cpp:113:20:113:38 | call to getenv indirection | test.cpp:114:19:114:22 | path indirection |
| test.cpp:114:10:114:23 | call to operator+ | test.cpp:114:25:114:29 | call to c_str indirection |
| test.cpp:114:10:114:23 | call to operator+ | test.cpp:114:25:114:29 | call to c_str indirection |
| test.cpp:114:17:114:17 | call to operator+ | test.cpp:114:10:114:23 | call to operator+ |
| test.cpp:114:19:114:22 | path indirection | test.cpp:114:10:114:23 | call to operator+ |
| test.cpp:114:19:114:22 | path indirection | test.cpp:114:17:114:17 | call to operator+ |
| test.cpp:119:20:119:38 | call to getenv | test.cpp:120:19:120:22 | path indirection |
| test.cpp:119:20:119:38 | call to getenv indirection | test.cpp:120:19:120:22 | path indirection |
| test.cpp:120:17:120:17 | call to operator+ | test.cpp:120:10:120:30 | call to data indirection |
| test.cpp:120:19:120:22 | path indirection | test.cpp:120:17:120:17 | call to operator+ |
@@ -89,12 +86,10 @@ nodes
| test.cpp:93:11:93:14 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:93:17:93:24 | filename indirection | semmle.label | filename indirection |
| test.cpp:94:45:94:48 | path indirection | semmle.label | path indirection |
| test.cpp:106:20:106:38 | call to getenv | semmle.label | call to getenv |
| test.cpp:106:20:106:38 | call to getenv indirection | semmle.label | call to getenv indirection |
| test.cpp:107:31:107:31 | call to operator+ | semmle.label | call to operator+ |
| test.cpp:107:33:107:36 | path indirection | semmle.label | path indirection |
| test.cpp:108:18:108:22 | call to c_str indirection | semmle.label | call to c_str indirection |
| test.cpp:113:20:113:38 | call to getenv | semmle.label | call to getenv |
| test.cpp:113:20:113:38 | call to getenv indirection | semmle.label | call to getenv indirection |
| test.cpp:114:10:114:23 | call to operator+ | semmle.label | call to operator+ |
| test.cpp:114:10:114:23 | call to operator+ | semmle.label | call to operator+ |
@@ -102,7 +97,6 @@ nodes
| test.cpp:114:19:114:22 | path indirection | semmle.label | path indirection |
| test.cpp:114:25:114:29 | call to c_str indirection | semmle.label | call to c_str indirection |
| test.cpp:114:25:114:29 | call to c_str indirection | semmle.label | call to c_str indirection |
| test.cpp:119:20:119:38 | call to getenv | semmle.label | call to getenv |
| test.cpp:119:20:119:38 | call to getenv indirection | semmle.label | call to getenv indirection |
| test.cpp:120:10:120:30 | call to data indirection | semmle.label | call to data indirection |
| test.cpp:120:17:120:17 | call to operator+ | semmle.label | call to operator+ |
@@ -156,13 +150,9 @@ subpaths
| test.cpp:65:10:65:16 | command | test.cpp:62:9:62:16 | fread output argument | test.cpp:65:10:65:16 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:62:9:62:16 | fread output argument | user input (string read by fread) | test.cpp:64:11:64:17 | strncat output argument | strncat output argument |
| test.cpp:85:32:85:38 | command | test.cpp:82:9:82:16 | fread output argument | test.cpp:85:32:85:38 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:82:9:82:16 | fread output argument | user input (string read by fread) | test.cpp:84:11:84:17 | strncat output argument | strncat output argument |
| test.cpp:94:45:94:48 | path | test.cpp:91:9:91:16 | fread output argument | test.cpp:94:45:94:48 | path indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:91:9:91:16 | fread output argument | user input (string read by fread) | test.cpp:93:11:93:14 | strncat output argument | strncat output argument |
| test.cpp:108:18:108:22 | call to c_str | test.cpp:106:20:106:38 | call to getenv | test.cpp:108:18:108:22 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:106:20:106:38 | call to getenv | user input (an environment variable) | test.cpp:107:31:107:31 | call to operator+ | call to operator+ |
| test.cpp:108:18:108:22 | call to c_str | test.cpp:106:20:106:38 | call to getenv indirection | test.cpp:108:18:108:22 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:106:20:106:38 | call to getenv indirection | user input (an environment variable) | test.cpp:107:31:107:31 | call to operator+ | call to operator+ |
| test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:38 | call to getenv | test.cpp:114:25:114:29 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:38 | call to getenv | user input (an environment variable) | test.cpp:114:10:114:23 | call to operator+ | call to operator+ |
| test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:38 | call to getenv | test.cpp:114:25:114:29 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:38 | call to getenv | user input (an environment variable) | test.cpp:114:17:114:17 | call to operator+ | call to operator+ |
| test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:38 | call to getenv indirection | test.cpp:114:25:114:29 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:38 | call to getenv indirection | user input (an environment variable) | test.cpp:114:10:114:23 | call to operator+ | call to operator+ |
| test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:38 | call to getenv indirection | test.cpp:114:25:114:29 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:38 | call to getenv indirection | user input (an environment variable) | test.cpp:114:17:114:17 | call to operator+ | call to operator+ |
| test.cpp:120:25:120:28 | call to data | test.cpp:119:20:119:38 | call to getenv | test.cpp:120:10:120:30 | call to data indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:119:20:119:38 | call to getenv | user input (an environment variable) | test.cpp:120:17:120:17 | call to operator+ | call to operator+ |
| test.cpp:120:25:120:28 | call to data | test.cpp:119:20:119:38 | call to getenv indirection | test.cpp:120:10:120:30 | call to data indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:119:20:119:38 | call to getenv indirection | user input (an environment variable) | test.cpp:120:17:120:17 | call to operator+ | call to operator+ |
| test.cpp:143:10:143:16 | command | test.cpp:140:9:140:11 | fread output argument | test.cpp:143:10:143:16 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:140:9:140:11 | fread output argument | user input (string read by fread) | test.cpp:142:11:142:17 | sprintf output argument | sprintf output argument |
| test.cpp:183:32:183:38 | command | test.cpp:174:9:174:16 | fread output argument | test.cpp:183:32:183:38 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:174:9:174:16 | fread output argument | user input (string read by fread) | test.cpp:177:13:177:17 | strncat output argument | strncat output argument |

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -1,16 +1,32 @@
edges
| main.cpp:6:27:6:30 | argv indirection | main.cpp:10:20:10:23 | argv indirection |
| main.cpp:10:20:10:23 | argv indirection | tests.cpp:618:32:618:35 | argv indirection |
| main.cpp:10:20:10:23 | argv indirection | tests.cpp:631:32:631:35 | argv indirection |
| tests.cpp:613:19:613:24 | source indirection | tests.cpp:615:17:615:22 | source indirection |
| tests.cpp:618:32:618:35 | argv indirection | tests.cpp:643:9:643:15 | access to array indirection |
| tests.cpp:643:9:643:15 | access to array indirection | tests.cpp:613:19:613:24 | source indirection |
| tests.cpp:622:19:622:24 | source indirection | tests.cpp:625:2:625:16 | ... = ... indirection |
| tests.cpp:625:2:625:16 | ... = ... indirection | tests.cpp:625:4:625:7 | s indirection [post update] [home indirection] |
| tests.cpp:625:4:625:7 | s indirection [post update] [home indirection] | tests.cpp:628:14:628:14 | s indirection [home indirection] |
| tests.cpp:628:14:628:14 | s indirection [home indirection] | tests.cpp:628:14:628:19 | home indirection |
| tests.cpp:628:14:628:14 | s indirection [home indirection] | tests.cpp:628:16:628:19 | home indirection |
| tests.cpp:628:16:628:19 | home indirection | tests.cpp:628:14:628:19 | home indirection |
| tests.cpp:631:32:631:35 | argv indirection | tests.cpp:656:9:656:15 | access to array indirection |
| tests.cpp:631:32:631:35 | argv indirection | tests.cpp:657:9:657:15 | access to array indirection |
| tests.cpp:656:9:656:15 | access to array indirection | tests.cpp:613:19:613:24 | source indirection |
| tests.cpp:657:9:657:15 | access to array indirection | tests.cpp:622:19:622:24 | source indirection |
nodes
| main.cpp:6:27:6:30 | argv indirection | semmle.label | argv indirection |
| main.cpp:10:20:10:23 | argv indirection | semmle.label | argv indirection |
| tests.cpp:613:19:613:24 | source indirection | semmle.label | source indirection |
| tests.cpp:615:17:615:22 | source indirection | semmle.label | source indirection |
| tests.cpp:618:32:618:35 | argv indirection | semmle.label | argv indirection |
| tests.cpp:643:9:643:15 | access to array indirection | semmle.label | access to array indirection |
| tests.cpp:622:19:622:24 | source indirection | semmle.label | source indirection |
| tests.cpp:625:2:625:16 | ... = ... indirection | semmle.label | ... = ... indirection |
| tests.cpp:625:4:625:7 | s indirection [post update] [home indirection] | semmle.label | s indirection [post update] [home indirection] |
| tests.cpp:628:14:628:14 | s indirection [home indirection] | semmle.label | s indirection [home indirection] |
| tests.cpp:628:14:628:19 | home indirection | semmle.label | home indirection |
| tests.cpp:628:16:628:19 | home indirection | semmle.label | home indirection |
| tests.cpp:631:32:631:35 | argv indirection | semmle.label | argv indirection |
| tests.cpp:656:9:656:15 | access to array indirection | semmle.label | access to array indirection |
| tests.cpp:657:9:657:15 | access to array indirection | semmle.label | access to array indirection |
subpaths
#select
| tests.cpp:615:2:615:7 | call to strcpy | main.cpp:6:27:6:30 | argv indirection | tests.cpp:615:17:615:22 | source indirection | This 'call to strcpy' with input from $@ may overflow the destination. | main.cpp:6:27:6:30 | argv indirection | a command-line argument |
| tests.cpp:628:2:628:7 | call to strcpy | main.cpp:6:27:6:30 | argv indirection | tests.cpp:628:14:628:19 | home indirection | This 'call to strcpy' with input from $@ may overflow the destination. | main.cpp:6:27:6:30 | argv indirection | a command-line argument |

View File

@@ -615,6 +615,19 @@ void test24(char* source) {
strcpy(buffer, source); // BAD
}
struct my_struct {
char* home;
};
void test25(char* source) {
my_struct s;
s.home = source;
char buf[100];
strcpy(buf, s.home); // BAD
}
int tests_main(int argc, char *argv[])
{
long long arr17[19];
@@ -641,6 +654,7 @@ int tests_main(int argc, char *argv[])
test22(argc == 0, argv[0]);
test23();
test24(argv[0]);
test25(argv[0]);
return 0;
}

View File

@@ -1,31 +1,16 @@
edges
| char_connect_socket_w32_vsnprintf_01_bad.c:94:46:94:69 | recv output argument | char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data |
| char_connect_socket_w32_vsnprintf_01_bad.c:94:46:94:69 | recv output argument | char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data |
| char_connect_socket_w32_vsnprintf_01_bad.c:94:55:94:68 | ... + ... | char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data |
| char_connect_socket_w32_vsnprintf_01_bad.c:94:55:94:68 | ... + ... | char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data |
| char_console_fprintf_01_bad.c:30:23:30:35 | ... + ... | char_console_fprintf_01_bad.c:49:21:49:24 | data |
| char_console_fprintf_01_bad.c:30:23:30:35 | ... + ... | char_console_fprintf_01_bad.c:49:21:49:24 | data |
| char_console_fprintf_01_bad.c:30:23:30:35 | fgets output argument | char_console_fprintf_01_bad.c:49:21:49:24 | data |
| char_console_fprintf_01_bad.c:30:23:30:35 | fgets output argument | char_console_fprintf_01_bad.c:49:21:49:24 | data |
| char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | char_environment_fprintf_01_bad.c:36:21:36:24 | data |
| char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | char_environment_fprintf_01_bad.c:36:21:36:24 | data |
| char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | char_environment_fprintf_01_bad.c:36:21:36:24 | data |
| char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | char_environment_fprintf_01_bad.c:36:21:36:24 | data |
subpaths
| char_connect_socket_w32_vsnprintf_01_bad.c:94:46:94:69 | recv output argument | char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data indirection |
| char_console_fprintf_01_bad.c:30:23:30:35 | fgets output argument | char_console_fprintf_01_bad.c:49:21:49:24 | data indirection |
| char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv indirection | char_environment_fprintf_01_bad.c:36:21:36:24 | data indirection |
nodes
| char_connect_socket_w32_vsnprintf_01_bad.c:94:46:94:69 | recv output argument | semmle.label | recv output argument |
| char_connect_socket_w32_vsnprintf_01_bad.c:94:55:94:68 | ... + ... | semmle.label | ... + ... |
| char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data | semmle.label | data |
| char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data | semmle.label | data |
| char_console_fprintf_01_bad.c:30:23:30:35 | ... + ... | semmle.label | ... + ... |
| char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data indirection | semmle.label | data indirection |
| char_console_fprintf_01_bad.c:30:23:30:35 | fgets output argument | semmle.label | fgets output argument |
| char_console_fprintf_01_bad.c:49:21:49:24 | data | semmle.label | data |
| char_console_fprintf_01_bad.c:49:21:49:24 | data | semmle.label | data |
| char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | semmle.label | call to getenv |
| char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | semmle.label | call to getenv |
| char_environment_fprintf_01_bad.c:36:21:36:24 | data | semmle.label | data |
| char_environment_fprintf_01_bad.c:36:21:36:24 | data | semmle.label | data |
| char_console_fprintf_01_bad.c:49:21:49:24 | data indirection | semmle.label | data indirection |
| char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv indirection | semmle.label | call to getenv indirection |
| char_environment_fprintf_01_bad.c:36:21:36:24 | data indirection | semmle.label | data indirection |
subpaths
#select
| char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data | char_connect_socket_w32_vsnprintf_01_bad.c:94:55:94:68 | ... + ... | char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data | The value of this argument may come from $@ and is being used as a formatting argument to badVaSink(data), which calls vsnprintf(format). | char_connect_socket_w32_vsnprintf_01_bad.c:94:55:94:68 | ... + ... | recv |
| char_console_fprintf_01_bad.c:49:21:49:24 | data | char_console_fprintf_01_bad.c:30:23:30:35 | ... + ... | char_console_fprintf_01_bad.c:49:21:49:24 | data | The value of this argument may come from $@ and is being used as a formatting argument to fprintf(format). | char_console_fprintf_01_bad.c:30:23:30:35 | ... + ... | fgets |
| char_environment_fprintf_01_bad.c:36:21:36:24 | data | char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | char_environment_fprintf_01_bad.c:36:21:36:24 | data | The value of this argument may come from $@ and is being used as a formatting argument to fprintf(format). | char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | getenv |
| char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data indirection | char_connect_socket_w32_vsnprintf_01_bad.c:94:46:94:69 | recv output argument | char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data indirection | The value of this argument may come from $@ and is being used as a formatting argument to badVaSink(data), which calls vsnprintf(format). | char_connect_socket_w32_vsnprintf_01_bad.c:94:46:94:69 | recv output argument | buffer read by recv |
| char_console_fprintf_01_bad.c:49:21:49:24 | data indirection | char_console_fprintf_01_bad.c:30:23:30:35 | fgets output argument | char_console_fprintf_01_bad.c:49:21:49:24 | data indirection | The value of this argument may come from $@ and is being used as a formatting argument to fprintf(format). | char_console_fprintf_01_bad.c:30:23:30:35 | fgets output argument | string read by fgets |
| char_environment_fprintf_01_bad.c:36:21:36:24 | data indirection | char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv indirection | char_environment_fprintf_01_bad.c:36:21:36:24 | data indirection | The value of this argument may come from $@ and is being used as a formatting argument to fprintf(format). | char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv indirection | an environment variable |

View File

@@ -164,7 +164,7 @@ int main(int argc, char **argv) {
printf(i91);
printWrapper(i91);
// BAD: i10 value comes from argv
// BAD: i10 value comes from argv [NOT DETECTED]
int i10 = (int) argv[1];
printf((char *) i10);
printWrapper((char *) i10);

View File

@@ -1,211 +1,80 @@
edges
| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array |
| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array |
| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array |
| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array |
| argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array |
| argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array |
| argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array |
| argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array |
| argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 |
| argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 |
| argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 |
| argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 |
| argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 |
| argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 |
| argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 |
| argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 |
| argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 |
| argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 |
| argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 |
| argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 |
| argvLocal.c:100:7:100:10 | argv | argvLocal.c:145:15:145:16 | i7 |
| argvLocal.c:100:7:100:10 | argv | argvLocal.c:145:15:145:16 | i7 |
| argvLocal.c:100:7:100:10 | argv | argvLocal.c:145:15:145:16 | i7 |
| argvLocal.c:100:7:100:10 | argv | argvLocal.c:145:15:145:16 | i7 |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:10 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:10 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:17:136:18 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:17:136:18 | i4 |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | i5 |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | i5 |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | i5 |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | i5 |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | i5 |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | i5 |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | i5 |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | i5 |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | ... + ... |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | ... + ... |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | ... + ... |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | ... + ... |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:139:9:139:26 | ... ? ... : ... |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:139:9:139:26 | ... ? ... : ... |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:139:9:139:26 | ... ? ... : ... |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:139:9:139:26 | ... ? ... : ... |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:140:15:140:32 | ... ? ... : ... |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:140:15:140:32 | ... ? ... : ... |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:140:15:140:32 | ... ? ... : ... |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:140:15:140:32 | ... ? ... : ... |
| argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 |
| argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 |
| argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 |
| argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 |
| argvLocal.c:149:11:149:14 | argv | argvLocal.c:151:15:151:16 | i8 |
| argvLocal.c:149:11:149:14 | argv | argvLocal.c:151:15:151:16 | i8 |
| argvLocal.c:149:11:149:14 | argv | argvLocal.c:151:15:151:16 | i8 |
| argvLocal.c:149:11:149:14 | argv | argvLocal.c:151:15:151:16 | i8 |
| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:9:169:20 | i10 |
| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:9:169:20 | i10 |
| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:18:169:20 | i10 |
| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:18:169:20 | i10 |
| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:15:170:26 | i10 |
| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:15:170:26 | i10 |
| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 |
| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 |
subpaths
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:95:9:95:15 | access to array indirection |
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:96:15:96:21 | access to array indirection |
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:101:9:101:10 | i1 indirection |
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:102:15:102:16 | i1 indirection |
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:106:9:106:13 | access to array indirection |
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:107:15:107:19 | access to array indirection |
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:110:9:110:11 | * ... indirection |
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:111:15:111:17 | * ... indirection |
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:116:9:116:10 | i3 indirection |
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:117:15:117:16 | i3 indirection |
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:121:9:121:10 | i4 indirection |
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:122:15:122:16 | i4 indirection |
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:127:9:127:10 | i5 indirection |
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:128:15:128:16 | i5 indirection |
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:131:9:131:14 | ... + ... indirection |
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:132:15:132:20 | ... + ... indirection |
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:135:9:135:12 | ... ++ indirection |
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:135:9:135:12 | ... ++ indirection |
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:136:15:136:18 | -- ... indirection |
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:139:9:139:26 | ... ? ... : ... indirection |
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:140:15:140:32 | ... ? ... : ... indirection |
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:144:9:144:10 | i7 indirection |
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:145:15:145:16 | i7 indirection |
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:150:9:150:10 | i8 indirection |
| argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:151:15:151:16 | i8 indirection |
nodes
| argvLocal.c:95:9:95:12 | argv | semmle.label | argv |
| argvLocal.c:95:9:95:12 | argv | semmle.label | argv |
| argvLocal.c:95:9:95:15 | access to array | semmle.label | access to array |
| argvLocal.c:95:9:95:15 | access to array | semmle.label | access to array |
| argvLocal.c:96:15:96:18 | argv | semmle.label | argv |
| argvLocal.c:96:15:96:18 | argv | semmle.label | argv |
| argvLocal.c:96:15:96:21 | access to array | semmle.label | access to array |
| argvLocal.c:96:15:96:21 | access to array | semmle.label | access to array |
| argvLocal.c:100:7:100:10 | argv | semmle.label | argv |
| argvLocal.c:100:7:100:10 | argv | semmle.label | argv |
| argvLocal.c:101:9:101:10 | i1 | semmle.label | i1 |
| argvLocal.c:101:9:101:10 | i1 | semmle.label | i1 |
| argvLocal.c:102:15:102:16 | i1 | semmle.label | i1 |
| argvLocal.c:102:15:102:16 | i1 | semmle.label | i1 |
| argvLocal.c:105:14:105:17 | argv | semmle.label | argv |
| argvLocal.c:105:14:105:17 | argv | semmle.label | argv |
| argvLocal.c:106:9:106:13 | access to array | semmle.label | access to array |
| argvLocal.c:106:9:106:13 | access to array | semmle.label | access to array |
| argvLocal.c:107:15:107:19 | access to array | semmle.label | access to array |
| argvLocal.c:107:15:107:19 | access to array | semmle.label | access to array |
| argvLocal.c:110:9:110:11 | * ... | semmle.label | * ... |
| argvLocal.c:110:9:110:11 | * ... | semmle.label | * ... |
| argvLocal.c:111:15:111:17 | * ... | semmle.label | * ... |
| argvLocal.c:111:15:111:17 | * ... | semmle.label | * ... |
| argvLocal.c:115:13:115:16 | argv | semmle.label | argv |
| argvLocal.c:115:13:115:16 | argv | semmle.label | argv |
| argvLocal.c:116:9:116:10 | i3 | semmle.label | i3 |
| argvLocal.c:116:9:116:10 | i3 | semmle.label | i3 |
| argvLocal.c:117:15:117:16 | i3 | semmle.label | i3 |
| argvLocal.c:117:15:117:16 | i3 | semmle.label | i3 |
| argvLocal.c:121:9:121:10 | i4 | semmle.label | i4 |
| argvLocal.c:121:9:121:10 | i4 | semmle.label | i4 |
| argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 |
| argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 |
| argvLocal.c:126:10:126:13 | argv | semmle.label | argv |
| argvLocal.c:126:10:126:13 | argv | semmle.label | argv |
| argvLocal.c:127:9:127:10 | i5 | semmle.label | i5 |
| argvLocal.c:127:9:127:10 | i5 | semmle.label | i5 |
| argvLocal.c:128:15:128:16 | i5 | semmle.label | i5 |
| argvLocal.c:128:15:128:16 | i5 | semmle.label | i5 |
| argvLocal.c:131:9:131:14 | ... + ... | semmle.label | ... + ... |
| argvLocal.c:131:9:131:14 | ... + ... | semmle.label | ... + ... |
| argvLocal.c:132:15:132:20 | ... + ... | semmle.label | ... + ... |
| argvLocal.c:132:15:132:20 | ... + ... | semmle.label | ... + ... |
| argvLocal.c:135:9:135:10 | i4 | semmle.label | i4 |
| argvLocal.c:135:9:135:12 | ... ++ | semmle.label | ... ++ |
| argvLocal.c:135:9:135:12 | ... ++ | semmle.label | ... ++ |
| argvLocal.c:135:9:135:12 | ... ++ | semmle.label | ... ++ |
| argvLocal.c:136:15:136:18 | -- ... | semmle.label | -- ... |
| argvLocal.c:136:15:136:18 | -- ... | semmle.label | -- ... |
| argvLocal.c:136:17:136:18 | i4 | semmle.label | i4 |
| argvLocal.c:139:9:139:26 | ... ? ... : ... | semmle.label | ... ? ... : ... |
| argvLocal.c:139:9:139:26 | ... ? ... : ... | semmle.label | ... ? ... : ... |
| argvLocal.c:140:15:140:32 | ... ? ... : ... | semmle.label | ... ? ... : ... |
| argvLocal.c:140:15:140:32 | ... ? ... : ... | semmle.label | ... ? ... : ... |
| argvLocal.c:144:9:144:10 | i7 | semmle.label | i7 |
| argvLocal.c:144:9:144:10 | i7 | semmle.label | i7 |
| argvLocal.c:145:15:145:16 | i7 | semmle.label | i7 |
| argvLocal.c:145:15:145:16 | i7 | semmle.label | i7 |
| argvLocal.c:149:11:149:14 | argv | semmle.label | argv |
| argvLocal.c:149:11:149:14 | argv | semmle.label | argv |
| argvLocal.c:150:9:150:10 | i8 | semmle.label | i8 |
| argvLocal.c:150:9:150:10 | i8 | semmle.label | i8 |
| argvLocal.c:151:15:151:16 | i8 | semmle.label | i8 |
| argvLocal.c:151:15:151:16 | i8 | semmle.label | i8 |
| argvLocal.c:168:18:168:21 | argv | semmle.label | argv |
| argvLocal.c:168:18:168:21 | argv | semmle.label | argv |
| argvLocal.c:169:9:169:20 | i10 | semmle.label | i10 |
| argvLocal.c:169:18:169:20 | i10 | semmle.label | i10 |
| argvLocal.c:170:15:170:26 | i10 | semmle.label | i10 |
| argvLocal.c:170:24:170:26 | i10 | semmle.label | i10 |
| argvLocal.c:13:27:13:30 | argv indirection | semmle.label | argv indirection |
| argvLocal.c:95:9:95:15 | access to array indirection | semmle.label | access to array indirection |
| argvLocal.c:96:15:96:21 | access to array indirection | semmle.label | access to array indirection |
| argvLocal.c:101:9:101:10 | i1 indirection | semmle.label | i1 indirection |
| argvLocal.c:102:15:102:16 | i1 indirection | semmle.label | i1 indirection |
| argvLocal.c:106:9:106:13 | access to array indirection | semmle.label | access to array indirection |
| argvLocal.c:107:15:107:19 | access to array indirection | semmle.label | access to array indirection |
| argvLocal.c:110:9:110:11 | * ... indirection | semmle.label | * ... indirection |
| argvLocal.c:111:15:111:17 | * ... indirection | semmle.label | * ... indirection |
| argvLocal.c:116:9:116:10 | i3 indirection | semmle.label | i3 indirection |
| argvLocal.c:117:15:117:16 | i3 indirection | semmle.label | i3 indirection |
| argvLocal.c:121:9:121:10 | i4 indirection | semmle.label | i4 indirection |
| argvLocal.c:122:15:122:16 | i4 indirection | semmle.label | i4 indirection |
| argvLocal.c:127:9:127:10 | i5 indirection | semmle.label | i5 indirection |
| argvLocal.c:128:15:128:16 | i5 indirection | semmle.label | i5 indirection |
| argvLocal.c:131:9:131:14 | ... + ... indirection | semmle.label | ... + ... indirection |
| argvLocal.c:132:15:132:20 | ... + ... indirection | semmle.label | ... + ... indirection |
| argvLocal.c:135:9:135:12 | ... ++ indirection | semmle.label | ... ++ indirection |
| argvLocal.c:135:9:135:12 | ... ++ indirection | semmle.label | ... ++ indirection |
| argvLocal.c:136:15:136:18 | -- ... indirection | semmle.label | -- ... indirection |
| argvLocal.c:139:9:139:26 | ... ? ... : ... indirection | semmle.label | ... ? ... : ... indirection |
| argvLocal.c:140:15:140:32 | ... ? ... : ... indirection | semmle.label | ... ? ... : ... indirection |
| argvLocal.c:144:9:144:10 | i7 indirection | semmle.label | i7 indirection |
| argvLocal.c:145:15:145:16 | i7 indirection | semmle.label | i7 indirection |
| argvLocal.c:150:9:150:10 | i8 indirection | semmle.label | i8 indirection |
| argvLocal.c:151:15:151:16 | i8 indirection | semmle.label | i8 indirection |
subpaths
#select
| argvLocal.c:95:9:95:15 | access to array | argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:95:9:95:12 | argv | argv |
| argvLocal.c:96:15:96:21 | access to array | argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:96:15:96:18 | argv | argv |
| argvLocal.c:101:9:101:10 | i1 | argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:100:7:100:10 | argv | argv |
| argvLocal.c:102:15:102:16 | i1 | argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:100:7:100:10 | argv | argv |
| argvLocal.c:106:9:106:13 | access to array | argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:105:14:105:17 | argv | argv |
| argvLocal.c:107:15:107:19 | access to array | argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:105:14:105:17 | argv | argv |
| argvLocal.c:110:9:110:11 | * ... | argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:105:14:105:17 | argv | argv |
| argvLocal.c:111:15:111:17 | * ... | argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:105:14:105:17 | argv | argv |
| argvLocal.c:116:9:116:10 | i3 | argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:115:13:115:16 | argv | argv |
| argvLocal.c:117:15:117:16 | i3 | argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:115:13:115:16 | argv | argv |
| argvLocal.c:121:9:121:10 | i4 | argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:115:13:115:16 | argv | argv |
| argvLocal.c:122:15:122:16 | i4 | argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:115:13:115:16 | argv | argv |
| argvLocal.c:127:9:127:10 | i5 | argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:126:10:126:13 | argv | argv |
| argvLocal.c:128:15:128:16 | i5 | argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:126:10:126:13 | argv | argv |
| argvLocal.c:131:9:131:14 | ... + ... | argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | ... + ... | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:126:10:126:13 | argv | argv |
| argvLocal.c:132:15:132:20 | ... + ... | argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:126:10:126:13 | argv | argv |
| argvLocal.c:135:9:135:12 | ... ++ | argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:115:13:115:16 | argv | argv |
| argvLocal.c:136:15:136:18 | -- ... | argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:115:13:115:16 | argv | argv |
| argvLocal.c:139:9:139:26 | ... ? ... : ... | argvLocal.c:126:10:126:13 | argv | argvLocal.c:139:9:139:26 | ... ? ... : ... | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:126:10:126:13 | argv | argv |
| argvLocal.c:140:15:140:32 | ... ? ... : ... | argvLocal.c:126:10:126:13 | argv | argvLocal.c:140:15:140:32 | ... ? ... : ... | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:126:10:126:13 | argv | argv |
| argvLocal.c:144:9:144:10 | i7 | argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:100:7:100:10 | argv | argv |
| argvLocal.c:145:15:145:16 | i7 | argvLocal.c:100:7:100:10 | argv | argvLocal.c:145:15:145:16 | i7 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:100:7:100:10 | argv | argv |
| argvLocal.c:150:9:150:10 | i8 | argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:149:11:149:14 | argv | argv |
| argvLocal.c:151:15:151:16 | i8 | argvLocal.c:149:11:149:14 | argv | argvLocal.c:151:15:151:16 | i8 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:149:11:149:14 | argv | argv |
| argvLocal.c:169:18:169:20 | i10 | argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:18:169:20 | i10 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:168:18:168:21 | argv | argv |
| argvLocal.c:170:24:170:26 | i10 | argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:168:18:168:21 | argv | argv |
| argvLocal.c:95:9:95:15 | access to array indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:95:9:95:15 | access to array indirection | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |
| argvLocal.c:96:15:96:21 | access to array indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:96:15:96:21 | access to array indirection | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |
| argvLocal.c:101:9:101:10 | i1 indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:101:9:101:10 | i1 indirection | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |
| argvLocal.c:102:15:102:16 | i1 indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:102:15:102:16 | i1 indirection | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |
| argvLocal.c:106:9:106:13 | access to array indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:106:9:106:13 | access to array indirection | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |
| argvLocal.c:107:15:107:19 | access to array indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:107:15:107:19 | access to array indirection | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |
| argvLocal.c:110:9:110:11 | * ... indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:110:9:110:11 | * ... indirection | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |
| argvLocal.c:111:15:111:17 | * ... indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:111:15:111:17 | * ... indirection | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |
| argvLocal.c:116:9:116:10 | i3 indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:116:9:116:10 | i3 indirection | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |
| argvLocal.c:117:15:117:16 | i3 indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:117:15:117:16 | i3 indirection | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |
| argvLocal.c:121:9:121:10 | i4 indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:121:9:121:10 | i4 indirection | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |
| argvLocal.c:122:15:122:16 | i4 indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:122:15:122:16 | i4 indirection | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |
| argvLocal.c:127:9:127:10 | i5 indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:127:9:127:10 | i5 indirection | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |
| argvLocal.c:128:15:128:16 | i5 indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:128:15:128:16 | i5 indirection | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |
| argvLocal.c:131:9:131:14 | ... + ... indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:131:9:131:14 | ... + ... indirection | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |
| argvLocal.c:132:15:132:20 | ... + ... indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:132:15:132:20 | ... + ... indirection | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |
| argvLocal.c:135:9:135:12 | ... ++ indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:135:9:135:12 | ... ++ indirection | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |
| argvLocal.c:135:9:135:12 | ... ++ indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:135:9:135:12 | ... ++ indirection | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |
| argvLocal.c:136:15:136:18 | -- ... indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:136:15:136:18 | -- ... indirection | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |
| argvLocal.c:139:9:139:26 | ... ? ... : ... indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:139:9:139:26 | ... ? ... : ... indirection | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |
| argvLocal.c:140:15:140:32 | ... ? ... : ... indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:140:15:140:32 | ... ? ... : ... indirection | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |
| argvLocal.c:144:9:144:10 | i7 indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:144:9:144:10 | i7 indirection | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |
| argvLocal.c:145:15:145:16 | i7 indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:145:15:145:16 | i7 indirection | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |
| argvLocal.c:150:9:150:10 | i8 indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:150:9:150:10 | i8 indirection | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |
| argvLocal.c:151:15:151:16 | i8 indirection | argvLocal.c:13:27:13:30 | argv indirection | argvLocal.c:151:15:151:16 | i8 indirection | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:13:27:13:30 | argv indirection | a command-line argument |

View File

@@ -1,88 +1,35 @@
edges
| funcsLocal.c:16:8:16:9 | fread output argument | funcsLocal.c:17:9:17:10 | i1 |
| funcsLocal.c:16:8:16:9 | fread output argument | funcsLocal.c:17:9:17:10 | i1 |
| funcsLocal.c:16:8:16:9 | fread output argument | funcsLocal.c:58:9:58:10 | e1 |
| funcsLocal.c:16:8:16:9 | fread output argument | funcsLocal.c:58:9:58:10 | e1 |
| funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:17:9:17:10 | i1 |
| funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:17:9:17:10 | i1 |
| funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:17:9:17:10 | i1 |
| funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:17:9:17:10 | i1 |
| funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:58:9:58:10 | e1 |
| funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:58:9:58:10 | e1 |
| funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:58:9:58:10 | e1 |
| funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:58:9:58:10 | e1 |
| funcsLocal.c:26:8:26:9 | fgets output argument | funcsLocal.c:27:9:27:10 | i3 |
| funcsLocal.c:26:8:26:9 | fgets output argument | funcsLocal.c:27:9:27:10 | i3 |
| funcsLocal.c:26:8:26:9 | i3 | funcsLocal.c:27:9:27:10 | i3 |
| funcsLocal.c:26:8:26:9 | i3 | funcsLocal.c:27:9:27:10 | i3 |
| funcsLocal.c:26:8:26:9 | i3 | funcsLocal.c:27:9:27:10 | i3 |
| funcsLocal.c:26:8:26:9 | i3 | funcsLocal.c:27:9:27:10 | i3 |
| funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 |
| funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 |
| funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 |
| funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 |
| funcsLocal.c:36:7:36:8 | gets output argument | funcsLocal.c:37:9:37:10 | i5 |
| funcsLocal.c:36:7:36:8 | gets output argument | funcsLocal.c:37:9:37:10 | i5 |
| funcsLocal.c:36:7:36:8 | i5 | funcsLocal.c:37:9:37:10 | i5 |
| funcsLocal.c:36:7:36:8 | i5 | funcsLocal.c:37:9:37:10 | i5 |
| funcsLocal.c:36:7:36:8 | i5 | funcsLocal.c:37:9:37:10 | i5 |
| funcsLocal.c:36:7:36:8 | i5 | funcsLocal.c:37:9:37:10 | i5 |
| funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 |
| funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 |
| funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 |
| funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 |
| funcsLocal.c:46:7:46:9 | * ... | funcsLocal.c:47:9:47:11 | * ... |
| funcsLocal.c:46:7:46:9 | * ... | funcsLocal.c:47:9:47:11 | * ... |
| funcsLocal.c:46:7:46:9 | * ... | funcsLocal.c:47:9:47:11 | * ... |
| funcsLocal.c:46:7:46:9 | * ... | funcsLocal.c:47:9:47:11 | * ... |
| funcsLocal.c:46:7:46:9 | gets output argument | funcsLocal.c:47:9:47:11 | * ... |
| funcsLocal.c:46:7:46:9 | gets output argument | funcsLocal.c:47:9:47:11 | * ... |
| funcsLocal.c:52:8:52:11 | call to gets | funcsLocal.c:53:9:53:11 | * ... |
| funcsLocal.c:52:8:52:11 | call to gets | funcsLocal.c:53:9:53:11 | * ... |
| funcsLocal.c:52:8:52:11 | call to gets | funcsLocal.c:53:9:53:11 | * ... |
| funcsLocal.c:52:8:52:11 | call to gets | funcsLocal.c:53:9:53:11 | * ... |
subpaths
| funcsLocal.c:16:8:16:9 | fread output argument | funcsLocal.c:17:9:17:10 | i1 indirection |
| funcsLocal.c:16:8:16:9 | fread output argument | funcsLocal.c:58:9:58:10 | e1 indirection |
| funcsLocal.c:26:8:26:9 | fgets output argument | funcsLocal.c:27:9:27:10 | i3 indirection |
| funcsLocal.c:31:13:31:17 | call to fgets indirection | funcsLocal.c:32:9:32:10 | i4 indirection |
| funcsLocal.c:36:7:36:8 | gets output argument | funcsLocal.c:37:9:37:10 | i5 indirection |
| funcsLocal.c:41:13:41:16 | call to gets indirection | funcsLocal.c:42:9:42:10 | i6 indirection |
| funcsLocal.c:46:7:46:9 | gets output argument | funcsLocal.c:47:9:47:11 | * ... indirection |
| funcsLocal.c:52:8:52:11 | call to gets indirection | funcsLocal.c:53:9:53:11 | * ... indirection |
nodes
| funcsLocal.c:16:8:16:9 | fread output argument | semmle.label | fread output argument |
| funcsLocal.c:16:8:16:9 | i1 | semmle.label | i1 |
| funcsLocal.c:16:8:16:9 | i1 | semmle.label | i1 |
| funcsLocal.c:17:9:17:10 | i1 | semmle.label | i1 |
| funcsLocal.c:17:9:17:10 | i1 | semmle.label | i1 |
| funcsLocal.c:17:9:17:10 | i1 indirection | semmle.label | i1 indirection |
| funcsLocal.c:26:8:26:9 | fgets output argument | semmle.label | fgets output argument |
| funcsLocal.c:26:8:26:9 | i3 | semmle.label | i3 |
| funcsLocal.c:26:8:26:9 | i3 | semmle.label | i3 |
| funcsLocal.c:27:9:27:10 | i3 | semmle.label | i3 |
| funcsLocal.c:27:9:27:10 | i3 | semmle.label | i3 |
| funcsLocal.c:31:13:31:17 | call to fgets | semmle.label | call to fgets |
| funcsLocal.c:31:13:31:17 | call to fgets | semmle.label | call to fgets |
| funcsLocal.c:32:9:32:10 | i4 | semmle.label | i4 |
| funcsLocal.c:32:9:32:10 | i4 | semmle.label | i4 |
| funcsLocal.c:27:9:27:10 | i3 indirection | semmle.label | i3 indirection |
| funcsLocal.c:31:13:31:17 | call to fgets indirection | semmle.label | call to fgets indirection |
| funcsLocal.c:32:9:32:10 | i4 indirection | semmle.label | i4 indirection |
| funcsLocal.c:36:7:36:8 | gets output argument | semmle.label | gets output argument |
| funcsLocal.c:36:7:36:8 | i5 | semmle.label | i5 |
| funcsLocal.c:36:7:36:8 | i5 | semmle.label | i5 |
| funcsLocal.c:37:9:37:10 | i5 | semmle.label | i5 |
| funcsLocal.c:37:9:37:10 | i5 | semmle.label | i5 |
| funcsLocal.c:41:13:41:16 | call to gets | semmle.label | call to gets |
| funcsLocal.c:41:13:41:16 | call to gets | semmle.label | call to gets |
| funcsLocal.c:42:9:42:10 | i6 | semmle.label | i6 |
| funcsLocal.c:42:9:42:10 | i6 | semmle.label | i6 |
| funcsLocal.c:46:7:46:9 | * ... | semmle.label | * ... |
| funcsLocal.c:46:7:46:9 | * ... | semmle.label | * ... |
| funcsLocal.c:37:9:37:10 | i5 indirection | semmle.label | i5 indirection |
| funcsLocal.c:41:13:41:16 | call to gets indirection | semmle.label | call to gets indirection |
| funcsLocal.c:42:9:42:10 | i6 indirection | semmle.label | i6 indirection |
| funcsLocal.c:46:7:46:9 | gets output argument | semmle.label | gets output argument |
| funcsLocal.c:47:9:47:11 | * ... | semmle.label | * ... |
| funcsLocal.c:47:9:47:11 | * ... | semmle.label | * ... |
| funcsLocal.c:52:8:52:11 | call to gets | semmle.label | call to gets |
| funcsLocal.c:52:8:52:11 | call to gets | semmle.label | call to gets |
| funcsLocal.c:53:9:53:11 | * ... | semmle.label | * ... |
| funcsLocal.c:53:9:53:11 | * ... | semmle.label | * ... |
| funcsLocal.c:58:9:58:10 | e1 | semmle.label | e1 |
| funcsLocal.c:58:9:58:10 | e1 | semmle.label | e1 |
| funcsLocal.c:47:9:47:11 | * ... indirection | semmle.label | * ... indirection |
| funcsLocal.c:52:8:52:11 | call to gets indirection | semmle.label | call to gets indirection |
| funcsLocal.c:53:9:53:11 | * ... indirection | semmle.label | * ... indirection |
| funcsLocal.c:58:9:58:10 | e1 indirection | semmle.label | e1 indirection |
subpaths
#select
| funcsLocal.c:17:9:17:10 | i1 | funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:17:9:17:10 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:16:8:16:9 | i1 | fread |
| funcsLocal.c:27:9:27:10 | i3 | funcsLocal.c:26:8:26:9 | i3 | funcsLocal.c:27:9:27:10 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:26:8:26:9 | i3 | fgets |
| funcsLocal.c:32:9:32:10 | i4 | funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:31:13:31:17 | call to fgets | fgets |
| funcsLocal.c:37:9:37:10 | i5 | funcsLocal.c:36:7:36:8 | i5 | funcsLocal.c:37:9:37:10 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:36:7:36:8 | i5 | gets |
| funcsLocal.c:42:9:42:10 | i6 | funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:41:13:41:16 | call to gets | gets |
| funcsLocal.c:47:9:47:11 | * ... | funcsLocal.c:46:7:46:9 | * ... | funcsLocal.c:47:9:47:11 | * ... | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:46:7:46:9 | * ... | gets |
| funcsLocal.c:53:9:53:11 | * ... | funcsLocal.c:52:8:52:11 | call to gets | funcsLocal.c:53:9:53:11 | * ... | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:52:8:52:11 | call to gets | gets |
| funcsLocal.c:58:9:58:10 | e1 | funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:58:9:58:10 | e1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:16:8:16:9 | i1 | fread |
| funcsLocal.c:17:9:17:10 | i1 indirection | funcsLocal.c:16:8:16:9 | fread output argument | funcsLocal.c:17:9:17:10 | i1 indirection | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:16:8:16:9 | fread output argument | string read by fread |
| funcsLocal.c:27:9:27:10 | i3 indirection | funcsLocal.c:26:8:26:9 | fgets output argument | funcsLocal.c:27:9:27:10 | i3 indirection | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:26:8:26:9 | fgets output argument | string read by fgets |
| funcsLocal.c:32:9:32:10 | i4 indirection | funcsLocal.c:31:13:31:17 | call to fgets indirection | funcsLocal.c:32:9:32:10 | i4 indirection | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:31:13:31:17 | call to fgets indirection | string read by fgets |
| funcsLocal.c:37:9:37:10 | i5 indirection | funcsLocal.c:36:7:36:8 | gets output argument | funcsLocal.c:37:9:37:10 | i5 indirection | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:36:7:36:8 | gets output argument | string read by gets |
| funcsLocal.c:42:9:42:10 | i6 indirection | funcsLocal.c:41:13:41:16 | call to gets indirection | funcsLocal.c:42:9:42:10 | i6 indirection | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:41:13:41:16 | call to gets indirection | string read by gets |
| funcsLocal.c:47:9:47:11 | * ... indirection | funcsLocal.c:46:7:46:9 | gets output argument | funcsLocal.c:47:9:47:11 | * ... indirection | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:46:7:46:9 | gets output argument | string read by gets |
| funcsLocal.c:53:9:53:11 | * ... indirection | funcsLocal.c:52:8:52:11 | call to gets indirection | funcsLocal.c:53:9:53:11 | * ... indirection | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:52:8:52:11 | call to gets indirection | string read by gets |
| funcsLocal.c:58:9:58:10 | e1 indirection | funcsLocal.c:16:8:16:9 | fread output argument | funcsLocal.c:58:9:58:10 | e1 indirection | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:16:8:16:9 | fread output argument | string read by fread |

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