mirror of
https://github.com/github/codeql.git
synced 2026-05-30 02:51:24 +02:00
Compare commits
1 Commits
atm-interm
...
esbena/atm
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e4abb0a1d |
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* `hasImplicitCopyConstructor` and `hasImplicitCopyAssignmentOperator` now correctly handle implicitly-deleted operators in templates.
|
||||
@@ -251,16 +251,6 @@ class Class extends UserType {
|
||||
not this.implicitCopyConstructorDeleted() and
|
||||
forall(CopyConstructor cc | cc = this.getAMemberFunction() |
|
||||
cc.isCompilerGenerated() and not cc.isDeleted()
|
||||
) and
|
||||
(
|
||||
not this instanceof ClassTemplateInstantiation
|
||||
or
|
||||
this.(ClassTemplateInstantiation).getTemplate().hasImplicitCopyConstructor()
|
||||
) and
|
||||
(
|
||||
not this instanceof PartialClassTemplateSpecialization
|
||||
or
|
||||
this.(PartialClassTemplateSpecialization).getPrimaryTemplate().hasImplicitCopyConstructor()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -276,18 +266,6 @@ class Class extends UserType {
|
||||
not this.implicitCopyAssignmentOperatorDeleted() and
|
||||
forall(CopyAssignmentOperator ca | ca = this.getAMemberFunction() |
|
||||
ca.isCompilerGenerated() and not ca.isDeleted()
|
||||
) and
|
||||
(
|
||||
not this instanceof ClassTemplateInstantiation
|
||||
or
|
||||
this.(ClassTemplateInstantiation).getTemplate().hasImplicitCopyAssignmentOperator()
|
||||
) and
|
||||
(
|
||||
not this instanceof PartialClassTemplateSpecialization
|
||||
or
|
||||
this.(PartialClassTemplateSpecialization)
|
||||
.getPrimaryTemplate()
|
||||
.hasImplicitCopyAssignmentOperator()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -447,6 +447,26 @@ private predicate skipInitializer(Initializer init) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e` is an expression in a static initializer that must be evaluated
|
||||
* at run time. This predicate computes "is non-const" instead of "is const" in
|
||||
* order to avoid recursion through forall.
|
||||
*/
|
||||
private predicate runtimeExprInStaticInitializer(Expr e) {
|
||||
inStaticInitializer(e) and
|
||||
if e instanceof AggregateLiteral
|
||||
then runtimeExprInStaticInitializer(e.getAChild())
|
||||
else not e.getFullyConverted().isConstant()
|
||||
}
|
||||
|
||||
/** Holds if `e` is part of the initializer of a local static variable. */
|
||||
private predicate inStaticInitializer(Expr e) {
|
||||
exists(LocalVariable local |
|
||||
local.isStatic() and
|
||||
e.getParent+() = local.getInitializer()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `i`th child of `n` in control-flow order, where the `i`-indexes are
|
||||
* contiguous, and the first index is 0.
|
||||
|
||||
@@ -287,6 +287,20 @@ private module SsaDefReaches {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the SSA definition of `v` at `def` reaches uncertain SSA definition
|
||||
* `redef` in the same basic block, without crossing another SSA definition of `v`.
|
||||
*/
|
||||
predicate ssaDefReachesUncertainDefWithinBlock(
|
||||
SourceVariable v, Definition def, UncertainWriteDefinition redef
|
||||
) {
|
||||
exists(BasicBlock bb, int rnk, int i |
|
||||
ssaDefReachesRank(bb, def, rnk, v) and
|
||||
rnk = ssaRefRank(bb, i, v, SsaDef()) - 1 and
|
||||
redef.definesAt(v, bb, i)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as `ssaRefRank()`, but restricted to a particular SSA definition `def`.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
private import ReachableBlock as Reachability
|
||||
|
||||
private module ReachabilityGraph = Reachability::Graph;
|
||||
|
||||
module Graph {
|
||||
import Reachability::Graph
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
private import ReachableBlock as Reachability
|
||||
|
||||
private module ReachabilityGraph = Reachability::Graph;
|
||||
|
||||
module Graph {
|
||||
import Reachability::Graph
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @name Copy function using source size
|
||||
* @description Calling a copy operation with a size derived from the source
|
||||
* buffer instead of the destination buffer may result in a buffer overflow.
|
||||
* @kind path-problem
|
||||
* @kind problem
|
||||
* @id cpp/overflow-destination
|
||||
* @problem.severity warning
|
||||
* @security-severity 9.3
|
||||
@@ -14,10 +14,7 @@
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
import semmle.code.cpp.controlflow.IRGuards
|
||||
import semmle.code.cpp.security.FlowSources
|
||||
import DataFlow::PathGraph
|
||||
import semmle.code.cpp.security.TaintTracking
|
||||
|
||||
/**
|
||||
* Holds if `fc` is a call to a copy operation where the size argument contains
|
||||
@@ -30,9 +27,9 @@ predicate sourceSized(FunctionCall fc, Expr src) {
|
||||
fc.getTarget().hasGlobalOrStdName(["strncpy", "strncat", "memcpy", "memmove"]) and
|
||||
exists(Expr dest, Expr size, Variable v |
|
||||
fc.getArgument(0) = dest and
|
||||
fc.getArgument(1).getFullyConverted() = src and
|
||||
fc.getArgument(1) = src and
|
||||
fc.getArgument(2) = size and
|
||||
src = v.getAnAccess().getFullyConverted() and
|
||||
src = v.getAnAccess() and
|
||||
size.getAChild+() = v.getAnAccess() and
|
||||
// exception: `dest` is also referenced in the size argument
|
||||
not exists(Variable other |
|
||||
@@ -48,49 +45,9 @@ predicate sourceSized(FunctionCall fc, Expr src) {
|
||||
)
|
||||
}
|
||||
|
||||
predicate readsVariable(LoadInstruction load, Variable var) {
|
||||
load.getSourceAddress().(VariableAddressInstruction).getAstVariable() = var
|
||||
}
|
||||
|
||||
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 nodeIsBarrierEqualityCandidate(DataFlow::Node node, Operand access, Variable checkedVar) {
|
||||
readsVariable(node.asInstruction(), checkedVar) and
|
||||
any(IRGuardCondition guard).ensuresEq(access, _, _, node.asInstruction().getBlock(), true)
|
||||
}
|
||||
|
||||
class OverflowDestinationConfig extends TaintTracking::Configuration {
|
||||
OverflowDestinationConfig() { this = "OverflowDestinationConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sourceSized(_, sink.asConvertedExpr()) }
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
exists(Variable checkedVar |
|
||||
readsVariable(node.asInstruction(), checkedVar) and
|
||||
hasUpperBoundsCheck(checkedVar)
|
||||
)
|
||||
or
|
||||
exists(Variable checkedVar, Operand access |
|
||||
readsVariable(access.getDef(), checkedVar) and
|
||||
nodeIsBarrierEqualityCandidate(node, access, checkedVar)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from
|
||||
FunctionCall fc, OverflowDestinationConfig conf, DataFlow::PathNode source,
|
||||
DataFlow::PathNode sink
|
||||
from FunctionCall fc, Expr vuln, Expr taintSource
|
||||
where
|
||||
conf.hasFlowPath(source, sink) and
|
||||
sourceSized(fc, sink.getNode().asConvertedExpr())
|
||||
select fc, source, sink,
|
||||
sourceSized(fc, vuln) and
|
||||
tainted(taintSource, vuln)
|
||||
select fc,
|
||||
"To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size."
|
||||
|
||||
@@ -3,22 +3,18 @@
|
||||
* @description Accessing an array without first checking
|
||||
* that the index is within the bounds of the array can
|
||||
* cause undefined behavior and can also be a security risk.
|
||||
* @kind path-problem
|
||||
* @kind problem
|
||||
* @id cpp/unclear-array-index-validation
|
||||
* @problem.severity warning
|
||||
* @security-severity 8.8
|
||||
* @precision low
|
||||
* @tags security
|
||||
* external/cwe/cwe-129
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.controlflow.IRGuards
|
||||
import semmle.code.cpp.security.FlowSources
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
|
||||
import DataFlow::PathGraph
|
||||
import semmle.code.cpp.security.Security
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
private import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
|
||||
import semmle.code.cpp.security.TaintTracking
|
||||
|
||||
predicate hasUpperBound(VariableAccess offsetExpr) {
|
||||
exists(BasicBlock controlled, StackVariable offsetVar, SsaDefinition def |
|
||||
@@ -36,92 +32,11 @@ predicate linearBoundControls(BasicBlock controlled, SsaDefinition def, StackVar
|
||||
)
|
||||
}
|
||||
|
||||
predicate readsVariable(LoadInstruction load, Variable var) {
|
||||
load.getSourceAddress().(VariableAddressInstruction).getAstVariable() = var
|
||||
}
|
||||
|
||||
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 nodeIsBarrierEqualityCandidate(DataFlow::Node node, Operand access, Variable checkedVar) {
|
||||
readsVariable(node.asInstruction(), checkedVar) and
|
||||
any(IRGuardCondition guard).ensuresEq(access, _, _, node.asInstruction().getBlock(), true)
|
||||
}
|
||||
|
||||
predicate isFlowSource(FlowSource source, string sourceType) { sourceType = source.getSourceType() }
|
||||
|
||||
predicate predictableInstruction(Instruction instr) {
|
||||
instr instanceof ConstantInstruction
|
||||
or
|
||||
instr instanceof StringConstantInstruction
|
||||
or
|
||||
// This could be a conversion on a string literal
|
||||
predictableInstruction(instr.(UnaryInstruction).getUnary())
|
||||
}
|
||||
|
||||
class ImproperArrayIndexValidationConfig extends TaintTracking::Configuration {
|
||||
ImproperArrayIndexValidationConfig() { this = "ImproperArrayIndexValidationConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { isFlowSource(source, _) }
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
hasUpperBound(node.asExpr())
|
||||
or
|
||||
// These barriers are ported from `DefaultTaintTracking` because this query is quite noisy
|
||||
// otherwise.
|
||||
exists(Variable checkedVar |
|
||||
readsVariable(node.asInstruction(), checkedVar) and
|
||||
hasUpperBoundsCheck(checkedVar)
|
||||
)
|
||||
or
|
||||
exists(Variable checkedVar, Operand access |
|
||||
readsVariable(access.getDef(), checkedVar) and
|
||||
nodeIsBarrierEqualityCandidate(node, access, checkedVar)
|
||||
)
|
||||
or
|
||||
// Don't use dataflow into binary instructions if both operands are unpredictable
|
||||
exists(BinaryInstruction iTo |
|
||||
iTo = node.asInstruction() and
|
||||
not predictableInstruction(iTo.getLeft()) and
|
||||
not predictableInstruction(iTo.getRight()) and
|
||||
// propagate taint from either the pointer or the offset, regardless of predictability
|
||||
not iTo instanceof PointerArithmeticInstruction
|
||||
)
|
||||
or
|
||||
// don't use dataflow through calls to pure functions if two or more operands
|
||||
// are unpredictable
|
||||
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 predictableInstruction(iFrom1) and
|
||||
not predictableInstruction(iFrom2) and
|
||||
iFrom1 != iFrom2
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(ArrayExpr arrayExpr, VariableAccess offsetExpr |
|
||||
offsetExpr = arrayExpr.getArrayOffset() and
|
||||
sink.asExpr() = offsetExpr and
|
||||
not hasUpperBound(offsetExpr)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from
|
||||
ImproperArrayIndexValidationConfig conf, DataFlow::PathNode source, DataFlow::PathNode sink,
|
||||
string sourceType
|
||||
from Expr origin, ArrayExpr arrayExpr, VariableAccess offsetExpr
|
||||
where
|
||||
conf.hasFlowPath(source, sink) and
|
||||
isFlowSource(source.getNode(), sourceType)
|
||||
select sink.getNode(), source, sink,
|
||||
tainted(origin, offsetExpr) and
|
||||
offsetExpr = arrayExpr.getArrayOffset() and
|
||||
not hasUpperBound(offsetExpr)
|
||||
select offsetExpr,
|
||||
"$@ flows to here and is used in an array indexing expression, potentially causing an invalid access.",
|
||||
source.getNode(), sourceType
|
||||
origin, "User-provided value"
|
||||
|
||||
@@ -15,89 +15,55 @@
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
import semmle.code.cpp.ir.IR
|
||||
import semmle.code.cpp.controlflow.IRGuards
|
||||
import semmle.code.cpp.security.FlowSources
|
||||
import DataFlow::PathGraph
|
||||
import semmle.code.cpp.security.TaintTracking
|
||||
import TaintedWithPath
|
||||
|
||||
/**
|
||||
* Holds if `alloc` is an allocation, and `tainted` is a child of it that is a
|
||||
* taint sink.
|
||||
*/
|
||||
predicate allocSink(Expr alloc, DataFlow::Node sink) {
|
||||
exists(Expr e | e = sink.asConvertedExpr() |
|
||||
isAllocationExpr(alloc) and
|
||||
e = alloc.getAChild() and
|
||||
e.getUnspecifiedType() instanceof IntegralType
|
||||
)
|
||||
predicate allocSink(Expr alloc, Expr tainted) {
|
||||
isAllocationExpr(alloc) and
|
||||
tainted = alloc.getAChild() and
|
||||
tainted.getUnspecifiedType() instanceof IntegralType
|
||||
}
|
||||
|
||||
predicate readsVariable(LoadInstruction load, Variable var) {
|
||||
load.getSourceAddress().(VariableAddressInstruction).getAstVariable() = var
|
||||
}
|
||||
class TaintedAllocationSizeConfiguration extends TaintTrackingConfiguration {
|
||||
override predicate isSink(Element tainted) { allocSink(_, tainted) }
|
||||
|
||||
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 nodeIsBarrierEqualityCandidate(DataFlow::Node node, Operand access, Variable checkedVar) {
|
||||
readsVariable(node.asInstruction(), checkedVar) and
|
||||
any(IRGuardCondition guard).ensuresEq(access, _, _, node.asInstruction().getBlock(), true)
|
||||
}
|
||||
|
||||
predicate isFlowSource(FlowSource source, string sourceType) { sourceType = source.getSourceType() }
|
||||
|
||||
class TaintedAllocationSizeConfiguration extends TaintTracking::Configuration {
|
||||
TaintedAllocationSizeConfiguration() { this = "TaintedAllocationSizeConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { isFlowSource(source, _) }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { allocSink(_, sink) }
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
exists(Expr e | e = node.asExpr() |
|
||||
// There can be two separate reasons for `convertedExprMightOverflow` not holding:
|
||||
// 1. `e` really cannot overflow.
|
||||
// 2. `e` isn't analyzable.
|
||||
// If we didn't rule out case 2 we would place barriers on anything that isn't analyzable.
|
||||
(
|
||||
e instanceof UnaryArithmeticOperation or
|
||||
e instanceof BinaryArithmeticOperation or
|
||||
e instanceof AssignArithmeticOperation
|
||||
) and
|
||||
not convertedExprMightOverflow(e)
|
||||
or
|
||||
// Subtracting two pointers is either well-defined (and the result will likely be small), or
|
||||
// terribly undefined and dangerous. Here, we assume that the programmer has ensured that the
|
||||
// result is well-defined (i.e., the two pointers point to the same object), and thus the result
|
||||
// will likely be small.
|
||||
e = any(PointerDiffExpr diff).getAnOperand()
|
||||
)
|
||||
override predicate isBarrier(Expr e) {
|
||||
super.isBarrier(e)
|
||||
or
|
||||
exists(Variable checkedVar |
|
||||
readsVariable(node.asInstruction(), checkedVar) and
|
||||
hasUpperBoundsCheck(checkedVar)
|
||||
)
|
||||
// There can be two separate reasons for `convertedExprMightOverflow` not holding:
|
||||
// 1. `e` really cannot overflow.
|
||||
// 2. `e` isn't analyzable.
|
||||
// If we didn't rule out case 2 we would place barriers on anything that isn't analyzable.
|
||||
(
|
||||
e instanceof UnaryArithmeticOperation or
|
||||
e instanceof BinaryArithmeticOperation or
|
||||
e instanceof AssignArithmeticOperation
|
||||
) and
|
||||
not convertedExprMightOverflow(e)
|
||||
or
|
||||
exists(Variable checkedVar, Operand access |
|
||||
readsVariable(access.getDef(), checkedVar) and
|
||||
nodeIsBarrierEqualityCandidate(node, access, checkedVar)
|
||||
)
|
||||
// Subtracting two pointers is either well-defined (and the result will likely be small), or
|
||||
// terribly undefined and dangerous. Here, we assume that the programmer has ensured that the
|
||||
// result is well-defined (i.e., the two pointers point to the same object), and thus the result
|
||||
// will likely be small.
|
||||
e = any(PointerDiffExpr diff).getAnOperand()
|
||||
}
|
||||
}
|
||||
|
||||
from
|
||||
Expr alloc, DataFlow::PathNode source, DataFlow::PathNode sink, string taintCause,
|
||||
TaintedAllocationSizeConfiguration conf
|
||||
where
|
||||
isFlowSource(source.getNode(), taintCause) and
|
||||
conf.hasFlowPath(source, sink) and
|
||||
allocSink(alloc, sink.getNode())
|
||||
select alloc, source, sink, "This allocation size is derived from $@ and might overflow",
|
||||
source.getNode(), "user input (" + taintCause + ")"
|
||||
predicate taintedAllocSize(
|
||||
Expr source, Expr alloc, PathNode sourceNode, PathNode sinkNode, string taintCause
|
||||
) {
|
||||
isUserInput(source, taintCause) and
|
||||
exists(Expr tainted |
|
||||
allocSink(alloc, tainted) and
|
||||
taintedWithPath(source, tainted, sourceNode, sinkNode)
|
||||
)
|
||||
}
|
||||
|
||||
from Expr source, Expr alloc, PathNode sourceNode, PathNode sinkNode, string taintCause
|
||||
where taintedAllocSize(source, alloc, sourceNode, sinkNode, taintCause)
|
||||
select alloc, sourceNode, sinkNode, "This allocation size is derived from $@ and might overflow",
|
||||
source, "user input (" + taintCause + ")"
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* @description Non-HTTPS connections can be intercepted by third parties.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 8.1
|
||||
* @precision high
|
||||
* @id cpp/non-https-url
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
* allow an attacker to compromise security.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 7.5
|
||||
* @precision high
|
||||
* @id cpp/insufficient-key-size
|
||||
* @tags security
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `cpp/overflow-destination`, `cpp/unclear-array-index-validation`, and `cpp/uncontrolled-allocation-size` queries have been modernized and converted to `path-problem` queries and provide more true positive results.
|
||||
@@ -13,6 +13,30 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
|
||||
/** Holds for a function `f` that has an argument at index `apos` used to read the file. */
|
||||
predicate numberArgumentRead(Function f, int apos) {
|
||||
f.hasGlobalOrStdName("fgets") and apos = 2
|
||||
or
|
||||
f.hasGlobalOrStdName("fread") and apos = 3
|
||||
or
|
||||
f.hasGlobalOrStdName("read") and apos = 0
|
||||
or
|
||||
f.hasGlobalOrStdName("fscanf") and apos = 0
|
||||
}
|
||||
|
||||
/** Holds for a function `f` that has an argument at index `apos` used to write to file */
|
||||
predicate numberArgumentWrite(Function f, int apos) {
|
||||
f.hasGlobalOrStdName("fprintf") and apos = 0
|
||||
or
|
||||
f.hasGlobalOrStdName("fputs") and apos = 1
|
||||
or
|
||||
f.hasGlobalOrStdName("write") and apos = 0
|
||||
or
|
||||
f.hasGlobalOrStdName("fwrite") and apos = 3
|
||||
or
|
||||
f.hasGlobalOrStdName("fflush") and apos = 0
|
||||
}
|
||||
|
||||
from FunctionCall fc, string msg
|
||||
where
|
||||
// search for functions for generating a name, without a guarantee of the absence of a file during the period of work with it.
|
||||
@@ -35,4 +59,54 @@ where
|
||||
) and
|
||||
msg =
|
||||
"Finding the name of a file that does not exist does not mean that it will not be exist at the next operation."
|
||||
or
|
||||
// finding places to work with a file without setting permissions, but with predictable names.
|
||||
(
|
||||
fc.getTarget().hasGlobalOrStdName("fopen") or
|
||||
fc.getTarget().hasGlobalOrStdName("open")
|
||||
) and
|
||||
fc.getNumberOfArguments() = 2 and
|
||||
exists(FunctionCall fctmp, int i |
|
||||
numberArgumentWrite(fctmp.getTarget(), i) and
|
||||
globalValueNumber(fc) = globalValueNumber(fctmp.getArgument(i))
|
||||
) and
|
||||
not exists(FunctionCall fctmp, int i |
|
||||
numberArgumentRead(fctmp.getTarget(), i) and
|
||||
globalValueNumber(fc) = globalValueNumber(fctmp.getArgument(i))
|
||||
) and
|
||||
exists(FunctionCall fctmp |
|
||||
(
|
||||
fctmp.getTarget().hasGlobalOrStdName("strcat") or
|
||||
fctmp.getTarget().hasGlobalOrStdName("strcpy")
|
||||
) and
|
||||
globalValueNumber(fc.getArgument(0)) = globalValueNumber(fctmp.getAnArgument())
|
||||
or
|
||||
fctmp.getTarget().hasGlobalOrStdName("getenv") and
|
||||
globalValueNumber(fc.getArgument(0)) = globalValueNumber(fctmp)
|
||||
or
|
||||
(
|
||||
fctmp.getTarget().hasGlobalOrStdName("asprintf") or
|
||||
fctmp.getTarget().hasGlobalOrStdName("vasprintf") or
|
||||
fctmp.getTarget().hasGlobalOrStdName("xasprintf") or
|
||||
fctmp.getTarget().hasGlobalOrStdName("xvasprintf ")
|
||||
) and
|
||||
exists(Variable vrtmp |
|
||||
vrtmp = fc.getArgument(0).(VariableAccess).getTarget() and
|
||||
vrtmp = fctmp.getArgument(0).(AddressOfExpr).getAddressable() and
|
||||
not vrtmp instanceof Field
|
||||
)
|
||||
) and
|
||||
not exists(FunctionCall fctmp |
|
||||
(
|
||||
fctmp.getTarget().hasGlobalOrStdName("umask") or
|
||||
fctmp.getTarget().hasGlobalOrStdName("fchmod") or
|
||||
fctmp.getTarget().hasGlobalOrStdName("chmod")
|
||||
) and
|
||||
(
|
||||
fc.getBasicBlock().getASuccessor*() = fctmp.getBasicBlock() or
|
||||
fctmp.getBasicBlock().getASuccessor*() = fc.getBasicBlock()
|
||||
)
|
||||
) and
|
||||
msg =
|
||||
"Creating a file for writing without evaluating its existence and setting permissions can be unsafe."
|
||||
select fc, msg
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
| test.cpp:16:20:16:25 | call to tmpnam | Finding the name of a file that does not exist does not mean that it will not be exist at the next operation. |
|
||||
| test.cpp:42:8:42:12 | call to fopen | Creating a file for writing without evaluating its existence and setting permissions can be unsafe. |
|
||||
|
||||
@@ -39,7 +39,7 @@ int funcTest3()
|
||||
FILE *fp;
|
||||
char filename[80];
|
||||
strcat(filename, "/tmp/tmp.name");
|
||||
fp = fopen(filename,"w"); // BAD [NOT DETECTED]
|
||||
fp = fopen(filename,"w"); // BAD
|
||||
fprintf(fp,"%s\n","data to file");
|
||||
fclose(fp);
|
||||
return 0;
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
| difference::Base | can | does NOT | have implicit copy assignment |
|
||||
| difference::OnlyAssign | can | does | have implicit copy assignment |
|
||||
| difference::OnlyCtor | can NOT | does NOT | have implicit copy assignment |
|
||||
| instantiated_explicit_ctor::Wrapper<int> | can | does | have implicit copy assignment |
|
||||
| moves::MoveAssign | can NOT | does NOT | have implicit copy assignment |
|
||||
| moves::MoveCtor | can NOT | does NOT | have implicit copy assignment |
|
||||
| private_cc::C | can | does NOT | have implicit copy assignment |
|
||||
|
||||
@@ -131,21 +131,3 @@ namespace difference {
|
||||
class OnlyAssign : Base {
|
||||
};
|
||||
}
|
||||
|
||||
namespace instantiated_explicit_ctor {
|
||||
template<class T>
|
||||
class Wrapper {
|
||||
public:
|
||||
Wrapper(Wrapper<T> &other) {
|
||||
m_t = other.m_t;
|
||||
}
|
||||
|
||||
Wrapper() {
|
||||
m_t = 0;
|
||||
}
|
||||
private:
|
||||
T m_t;
|
||||
};
|
||||
|
||||
Wrapper<int> wrapped_int;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
| difference::Base | can | does NOT | have implicit copy constructor |
|
||||
| difference::OnlyAssign | can NOT | does NOT | have implicit copy constructor |
|
||||
| difference::OnlyCtor | can | does | have implicit copy constructor |
|
||||
| instantiated_explicit_ctor::Wrapper<int> | can | does NOT | have implicit copy constructor |
|
||||
| moves::MoveAssign | can NOT | does NOT | have implicit copy constructor |
|
||||
| moves::MoveCtor | can NOT | does NOT | have implicit copy constructor |
|
||||
| private_cc::C | can | does NOT | have implicit copy constructor |
|
||||
|
||||
@@ -86,9 +86,5 @@
|
||||
| copy.cpp:131:9:131:9 | OnlyAssign | deleted | |
|
||||
| copy.cpp:131:9:131:9 | operator= | | |
|
||||
| copy.cpp:131:9:131:9 | operator= | | |
|
||||
| copy.cpp:137:9:137:9 | operator= | | |
|
||||
| copy.cpp:139:5:139:11 | Wrapper | | |
|
||||
| copy.cpp:143:5:143:5 | Wrapper | | |
|
||||
| copy.cpp:143:5:143:11 | Wrapper | | |
|
||||
| file://:0:0:0:0 | operator= | | |
|
||||
| file://:0:0:0:0 | operator= | | |
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
edges
|
||||
nodes
|
||||
subpaths
|
||||
#select
|
||||
|
||||
@@ -1,43 +1,4 @@
|
||||
edges
|
||||
| overflowdestination.cpp:27:9:27:12 | argv | overflowdestination.cpp:30:17:30:20 | (const char *)... |
|
||||
| overflowdestination.cpp:43:8:43:10 | fgets output argument | overflowdestination.cpp:46:15:46:17 | (const void *)... |
|
||||
| overflowdestination.cpp:50:52:50:54 | *src | overflowdestination.cpp:50:52:50:54 | ReturnIndirection |
|
||||
| overflowdestination.cpp:50:52:50:54 | src | overflowdestination.cpp:53:15:53:17 | (const void *)... |
|
||||
| overflowdestination.cpp:57:52:57:54 | *src | overflowdestination.cpp:64:16:64:19 | (const void *)... |
|
||||
| overflowdestination.cpp:57:52:57:54 | src | overflowdestination.cpp:64:16:64:19 | (const void *)... |
|
||||
| overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:75:30:75:32 | src |
|
||||
| overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:75:30:75:32 | src indirection |
|
||||
| overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:76:30:76:32 | src |
|
||||
| overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:76:30:76:32 | src indirection |
|
||||
| overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument | overflowdestination.cpp:76:30:76:32 | src |
|
||||
| overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument | overflowdestination.cpp:76:30:76:32 | src indirection |
|
||||
| overflowdestination.cpp:75:30:75:32 | src | overflowdestination.cpp:50:52:50:54 | src |
|
||||
| overflowdestination.cpp:75:30:75:32 | src indirection | overflowdestination.cpp:50:52:50:54 | *src |
|
||||
| overflowdestination.cpp:75:30:75:32 | src indirection | overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument |
|
||||
| overflowdestination.cpp:76:30:76:32 | src | overflowdestination.cpp:57:52:57:54 | src |
|
||||
| overflowdestination.cpp:76:30:76:32 | src indirection | overflowdestination.cpp:57:52:57:54 | *src |
|
||||
nodes
|
||||
| overflowdestination.cpp:27:9:27:12 | argv | semmle.label | argv |
|
||||
| overflowdestination.cpp:30:17:30:20 | (const char *)... | semmle.label | (const char *)... |
|
||||
| overflowdestination.cpp:43:8:43:10 | fgets output argument | semmle.label | fgets output argument |
|
||||
| overflowdestination.cpp:46:15:46:17 | (const void *)... | semmle.label | (const void *)... |
|
||||
| overflowdestination.cpp:50:52:50:54 | *src | semmle.label | *src |
|
||||
| overflowdestination.cpp:50:52:50:54 | ReturnIndirection | semmle.label | ReturnIndirection |
|
||||
| overflowdestination.cpp:50:52:50:54 | src | semmle.label | src |
|
||||
| overflowdestination.cpp:53:15:53:17 | (const void *)... | semmle.label | (const void *)... |
|
||||
| overflowdestination.cpp:57:52:57:54 | *src | semmle.label | *src |
|
||||
| overflowdestination.cpp:57:52:57:54 | src | semmle.label | src |
|
||||
| overflowdestination.cpp:64:16:64:19 | (const void *)... | semmle.label | (const void *)... |
|
||||
| overflowdestination.cpp:73:8:73:10 | fgets output argument | semmle.label | fgets output argument |
|
||||
| overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument | semmle.label | overflowdest_test2 output argument |
|
||||
| overflowdestination.cpp:75:30:75:32 | src | semmle.label | src |
|
||||
| overflowdestination.cpp:75:30:75:32 | src indirection | semmle.label | src indirection |
|
||||
| overflowdestination.cpp:76:30:76:32 | src | semmle.label | src |
|
||||
| overflowdestination.cpp:76:30:76:32 | src indirection | semmle.label | src indirection |
|
||||
subpaths
|
||||
| overflowdestination.cpp:75:30:75:32 | src indirection | overflowdestination.cpp:50:52:50:54 | *src | overflowdestination.cpp:50:52:50:54 | ReturnIndirection | overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument |
|
||||
#select
|
||||
| overflowdestination.cpp:30:2:30:8 | call to strncpy | overflowdestination.cpp:27:9:27:12 | argv | overflowdestination.cpp:30:17:30:20 | (const char *)... | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |
|
||||
| overflowdestination.cpp:46:2:46:7 | call to memcpy | overflowdestination.cpp:43:8:43:10 | fgets output argument | overflowdestination.cpp:46:15:46:17 | (const void *)... | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |
|
||||
| overflowdestination.cpp:53:2:53:7 | call to memcpy | overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:53:15:53:17 | (const void *)... | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |
|
||||
| overflowdestination.cpp:64:2:64:7 | call to memcpy | overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:64:16:64:19 | (const void *)... | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |
|
||||
| overflowdestination.cpp:30:2:30:8 | call to strncpy | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |
|
||||
| overflowdestination.cpp:46:2:46:7 | call to memcpy | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |
|
||||
| overflowdestination.cpp:53:2:53:7 | call to memcpy | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |
|
||||
| overflowdestination.cpp:64:2:64:7 | call to memcpy | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |
|
||||
|
||||
@@ -1,8 +1 @@
|
||||
edges
|
||||
| CWE122_Heap_Based_Buffer_Overflow__c_CWE129_fgets_01.c:30:19:30:29 | fgets output argument | CWE122_Heap_Based_Buffer_Overflow__c_CWE129_fgets_01.c:52:20:52:23 | data |
|
||||
nodes
|
||||
| CWE122_Heap_Based_Buffer_Overflow__c_CWE129_fgets_01.c:30:19:30:29 | fgets output argument | semmle.label | fgets output argument |
|
||||
| CWE122_Heap_Based_Buffer_Overflow__c_CWE129_fgets_01.c:52:20:52:23 | data | semmle.label | data |
|
||||
subpaths
|
||||
#select
|
||||
| CWE122_Heap_Based_Buffer_Overflow__c_CWE129_fgets_01.c:52:20:52:23 | data | CWE122_Heap_Based_Buffer_Overflow__c_CWE129_fgets_01.c:30:19:30:29 | fgets output argument | CWE122_Heap_Based_Buffer_Overflow__c_CWE129_fgets_01.c:52:20:52:23 | data | $@ flows to here and is used in an array indexing expression, potentially causing an invalid access. | CWE122_Heap_Based_Buffer_Overflow__c_CWE129_fgets_01.c:30:19:30:29 | fgets output argument | String read by fgets |
|
||||
| CWE122_Heap_Based_Buffer_Overflow__c_CWE129_fgets_01.c:52:20:52:23 | data | $@ flows to here and is used in an array indexing expression, potentially causing an invalid access. | CWE122_Heap_Based_Buffer_Overflow__c_CWE129_fgets_01.c:30:19:30:29 | inputBuffer | User-provided value |
|
||||
|
||||
@@ -1,26 +1,3 @@
|
||||
edges
|
||||
| test1.c:8:16:8:19 | argv | test1.c:9:9:9:9 | i |
|
||||
| test1.c:8:16:8:19 | argv | test1.c:11:9:11:9 | i |
|
||||
| test1.c:8:16:8:19 | argv | test1.c:13:9:13:9 | i |
|
||||
| test1.c:9:9:9:9 | i | test1.c:16:16:16:16 | i |
|
||||
| test1.c:11:9:11:9 | i | test1.c:32:16:32:16 | i |
|
||||
| test1.c:13:9:13:9 | i | test1.c:48:16:48:16 | i |
|
||||
| test1.c:16:16:16:16 | i | test1.c:18:16:18:16 | i |
|
||||
| test1.c:32:16:32:16 | i | test1.c:33:11:33:11 | i |
|
||||
| test1.c:48:16:48:16 | i | test1.c:53:15:53:15 | j |
|
||||
nodes
|
||||
| test1.c:8:16:8:19 | argv | semmle.label | argv |
|
||||
| test1.c:9:9:9:9 | i | semmle.label | i |
|
||||
| test1.c:11:9:11:9 | i | semmle.label | i |
|
||||
| test1.c:13:9:13:9 | i | semmle.label | i |
|
||||
| test1.c:16:16:16:16 | i | semmle.label | i |
|
||||
| test1.c:18:16:18:16 | i | semmle.label | i |
|
||||
| test1.c:32:16:32:16 | i | semmle.label | i |
|
||||
| test1.c:33:11:33:11 | i | semmle.label | i |
|
||||
| test1.c:48:16:48:16 | i | semmle.label | i |
|
||||
| test1.c:53:15:53:15 | j | semmle.label | j |
|
||||
subpaths
|
||||
#select
|
||||
| test1.c:18:16:18:16 | i | test1.c:8:16:8:19 | argv | test1.c:18:16:18:16 | i | $@ flows to here and is used in an array indexing expression, potentially causing an invalid access. | test1.c:8:16:8:19 | argv | a command-line argument |
|
||||
| test1.c:33:11:33:11 | i | test1.c:8:16:8:19 | argv | test1.c:33:11:33:11 | i | $@ flows to here and is used in an array indexing expression, potentially causing an invalid access. | test1.c:8:16:8:19 | argv | a command-line argument |
|
||||
| test1.c:53:15:53:15 | j | test1.c:8:16:8:19 | argv | test1.c:53:15:53:15 | j | $@ flows to here and is used in an array indexing expression, potentially causing an invalid access. | test1.c:8:16:8:19 | argv | a command-line argument |
|
||||
| test1.c:18:16:18:16 | i | $@ flows to here and is used in an array indexing expression, potentially causing an invalid access. | test1.c:8:16:8:19 | argv | User-provided value |
|
||||
| test1.c:33:11:33:11 | i | $@ flows to here and is used in an array indexing expression, potentially causing an invalid access. | test1.c:8:16:8:19 | argv | User-provided value |
|
||||
| test1.c:53:15:53:15 | j | $@ flows to here and is used in an array indexing expression, potentially causing an invalid access. | test1.c:8:16:8:19 | argv | User-provided value |
|
||||
|
||||
@@ -1,20 +1,62 @@
|
||||
edges
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:43:38:43:44 | (size_t)... |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:43:38:43:44 | (size_t)... |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:43:38:43:44 | tainted |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:43:38:43:44 | tainted |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:43:38:43:44 | tainted |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:43:38:43:44 | tainted |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:44:38:44:63 | ... * ... |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:44:38:44:63 | ... * ... |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:44:38:44:63 | ... * ... |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:44:38:44:63 | ... * ... |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:46:38:46:63 | ... + ... |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:46:38:46:63 | ... + ... |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:46:38:46:63 | ... + ... |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:46:38:46:63 | ... + ... |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:49:32:49:35 | (size_t)... |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:49:32:49:35 | (size_t)... |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:49:32:49:35 | size |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:49:32:49:35 | size |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:49:32:49:35 | size |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:49:32:49:35 | size |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:50:26:50:29 | size |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:50:26:50:29 | size |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:50:26:50:29 | size |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:50:26:50:29 | size |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:53:35:53:60 | ... * ... |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:53:35:53:60 | ... * ... |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:53:35:53:60 | ... * ... |
|
||||
| test.cpp:40:21:40:24 | argv | test.cpp:53:35:53:60 | ... * ... |
|
||||
| test.cpp:124:18:124:23 | call to getenv | test.cpp:128:24:128:41 | ... * ... |
|
||||
| test.cpp:124:18:124:23 | call to getenv | test.cpp:128:24:128:41 | ... * ... |
|
||||
| test.cpp:124:18:124:31 | (const char *)... | test.cpp:128:24:128:41 | ... * ... |
|
||||
| test.cpp:124:18:124:31 | (const char *)... | test.cpp:128:24:128:41 | ... * ... |
|
||||
| test.cpp:133:19:133:24 | call to getenv | test.cpp:135:10:135:27 | ... * ... |
|
||||
| test.cpp:133:19:133:24 | call to getenv | test.cpp:135:10:135:27 | ... * ... |
|
||||
| test.cpp:133:19:133:32 | (const char *)... | test.cpp:135:10:135:27 | ... * ... |
|
||||
| test.cpp:133:19:133:32 | (const char *)... | test.cpp:135:10:135:27 | ... * ... |
|
||||
| test.cpp:148:20:148:25 | call to getenv | test.cpp:152:11:152:28 | ... * ... |
|
||||
| test.cpp:148:20:148:25 | call to getenv | test.cpp:152:11:152:28 | ... * ... |
|
||||
| test.cpp:148:20:148:33 | (const char *)... | test.cpp:152:11:152:28 | ... * ... |
|
||||
| test.cpp:148:20:148:33 | (const char *)... | test.cpp:152:11:152:28 | ... * ... |
|
||||
| test.cpp:209:8:209:23 | ReturnValue | test.cpp:241:9:241:24 | call to get_tainted_size |
|
||||
| test.cpp:209:8:209:23 | ReturnValue | test.cpp:241:9:241:24 | call to get_tainted_size |
|
||||
| test.cpp:211:14:211:19 | call to getenv | test.cpp:209:8:209:23 | ReturnValue |
|
||||
| test.cpp:211:14:211:27 | (const char *)... | test.cpp:209:8:209:23 | ReturnValue |
|
||||
| test.cpp:224:23:224:23 | s | test.cpp:225:21:225:21 | s |
|
||||
| test.cpp:224:23:224:23 | s | test.cpp:225:21:225:21 | s |
|
||||
| test.cpp:230:21:230:21 | s | test.cpp:231:21:231:21 | s |
|
||||
| test.cpp:230:21:230:21 | s | test.cpp:231:21:231:21 | s |
|
||||
| test.cpp:237:24:237:29 | call to getenv | test.cpp:239:9:239:18 | (size_t)... |
|
||||
| test.cpp:237:24:237:29 | call to getenv | test.cpp:239:9:239:18 | local_size |
|
||||
| test.cpp:237:24:237:29 | call to getenv | test.cpp:239:9:239:18 | local_size |
|
||||
| test.cpp:237:24:237:29 | call to getenv | test.cpp:245:11:245:20 | local_size |
|
||||
| test.cpp:237:24:237:29 | call to getenv | test.cpp:247:10:247:19 | local_size |
|
||||
| test.cpp:237:24:237:37 | (const char *)... | test.cpp:239:9:239:18 | (size_t)... |
|
||||
| test.cpp:237:24:237:37 | (const char *)... | test.cpp:239:9:239:18 | local_size |
|
||||
| test.cpp:237:24:237:37 | (const char *)... | test.cpp:239:9:239:18 | local_size |
|
||||
| test.cpp:237:24:237:37 | (const char *)... | test.cpp:245:11:245:20 | local_size |
|
||||
| test.cpp:237:24:237:37 | (const char *)... | test.cpp:247:10:247:19 | local_size |
|
||||
| test.cpp:245:11:245:20 | local_size | test.cpp:224:23:224:23 | s |
|
||||
| test.cpp:247:10:247:19 | local_size | test.cpp:230:21:230:21 | s |
|
||||
| test.cpp:251:2:251:9 | (reference dereference) [post update] | test.cpp:289:17:289:20 | size [post update] |
|
||||
@@ -22,57 +64,112 @@ edges
|
||||
| test.cpp:251:18:251:23 | call to getenv | test.cpp:251:2:251:9 | (reference dereference) [post update] |
|
||||
| test.cpp:251:18:251:23 | call to getenv | test.cpp:289:17:289:20 | size [post update] |
|
||||
| test.cpp:251:18:251:23 | call to getenv | test.cpp:305:18:305:21 | size [post update] |
|
||||
| test.cpp:251:18:251:31 | (const char *)... | test.cpp:251:2:251:9 | (reference dereference) [post update] |
|
||||
| test.cpp:251:18:251:31 | (const char *)... | test.cpp:289:17:289:20 | size [post update] |
|
||||
| test.cpp:251:18:251:31 | (const char *)... | test.cpp:305:18:305:21 | size [post update] |
|
||||
| test.cpp:259:20:259:25 | call to getenv | test.cpp:263:11:263:29 | ... * ... |
|
||||
| test.cpp:259:20:259:25 | call to getenv | test.cpp:263:11:263:29 | ... * ... |
|
||||
| test.cpp:259:20:259:33 | (const char *)... | test.cpp:263:11:263:29 | ... * ... |
|
||||
| test.cpp:259:20:259:33 | (const char *)... | test.cpp:263:11:263:29 | ... * ... |
|
||||
| test.cpp:289:17:289:20 | size [post update] | test.cpp:291:11:291:28 | ... * ... |
|
||||
| test.cpp:289:17:289:20 | size [post update] | test.cpp:291:11:291:28 | ... * ... |
|
||||
| test.cpp:305:18:305:21 | size [post update] | test.cpp:308:10:308:27 | ... * ... |
|
||||
| test.cpp:305:18:305:21 | size [post update] | test.cpp:308:10:308:27 | ... * ... |
|
||||
subpaths
|
||||
nodes
|
||||
| test.cpp:40:21:40:24 | argv | semmle.label | argv |
|
||||
| test.cpp:40:21:40:24 | argv | semmle.label | argv |
|
||||
| test.cpp:43:38:43:44 | (size_t)... | semmle.label | (size_t)... |
|
||||
| test.cpp:43:38:43:44 | (size_t)... | semmle.label | (size_t)... |
|
||||
| test.cpp:43:38:43:44 | tainted | semmle.label | tainted |
|
||||
| test.cpp:43:38:43:44 | tainted | semmle.label | tainted |
|
||||
| test.cpp:43:38:43:44 | tainted | semmle.label | tainted |
|
||||
| test.cpp:44:38:44:63 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:44:38:44:63 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:44:38:44:63 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:46:38:46:63 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:46:38:46:63 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:46:38:46:63 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:49:32:49:35 | (size_t)... | semmle.label | (size_t)... |
|
||||
| test.cpp:49:32:49:35 | (size_t)... | semmle.label | (size_t)... |
|
||||
| test.cpp:49:32:49:35 | size | semmle.label | size |
|
||||
| test.cpp:49:32:49:35 | size | semmle.label | size |
|
||||
| test.cpp:49:32:49:35 | size | semmle.label | size |
|
||||
| test.cpp:50:26:50:29 | size | semmle.label | size |
|
||||
| test.cpp:50:26:50:29 | size | semmle.label | size |
|
||||
| test.cpp:50:26:50:29 | size | semmle.label | size |
|
||||
| test.cpp:53:35:53:60 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:53:35:53:60 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:53:35:53:60 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:124:18:124:23 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:124:18:124:31 | (const char *)... | semmle.label | (const char *)... |
|
||||
| test.cpp:128:24:128:41 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:128:24:128:41 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:128:24:128:41 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:133:19:133:24 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:133:19:133:32 | (const char *)... | semmle.label | (const char *)... |
|
||||
| test.cpp:135:10:135:27 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:135:10:135:27 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:135:10:135:27 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:148:20:148:25 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:148:20:148:33 | (const char *)... | semmle.label | (const char *)... |
|
||||
| test.cpp:152:11:152:28 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:152:11:152:28 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:152:11:152:28 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:209:8:209:23 | ReturnValue | semmle.label | ReturnValue |
|
||||
| test.cpp:211:14:211:19 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:211:14:211:27 | (const char *)... | semmle.label | (const char *)... |
|
||||
| test.cpp:224:23:224:23 | s | semmle.label | s |
|
||||
| test.cpp:225:21:225:21 | s | semmle.label | s |
|
||||
| test.cpp:225:21:225:21 | s | semmle.label | s |
|
||||
| test.cpp:225:21:225:21 | s | semmle.label | s |
|
||||
| test.cpp:230:21:230:21 | s | semmle.label | s |
|
||||
| test.cpp:231:21:231:21 | s | semmle.label | s |
|
||||
| test.cpp:231:21:231:21 | s | semmle.label | s |
|
||||
| test.cpp:231:21:231:21 | s | semmle.label | s |
|
||||
| test.cpp:237:24:237:29 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:237:24:237:37 | (const char *)... | semmle.label | (const char *)... |
|
||||
| test.cpp:239:9:239:18 | (size_t)... | semmle.label | (size_t)... |
|
||||
| test.cpp:239:9:239:18 | (size_t)... | semmle.label | (size_t)... |
|
||||
| test.cpp:239:9:239:18 | local_size | semmle.label | local_size |
|
||||
| test.cpp:239:9:239:18 | local_size | semmle.label | local_size |
|
||||
| test.cpp:239:9:239:18 | local_size | semmle.label | local_size |
|
||||
| test.cpp:241:9:241:24 | call to get_tainted_size | semmle.label | call to get_tainted_size |
|
||||
| test.cpp:241:9:241:24 | call to get_tainted_size | semmle.label | call to get_tainted_size |
|
||||
| test.cpp:241:9:241:24 | call to get_tainted_size | semmle.label | call to get_tainted_size |
|
||||
| test.cpp:245:11:245:20 | local_size | semmle.label | local_size |
|
||||
| test.cpp:247:10:247:19 | local_size | semmle.label | local_size |
|
||||
| test.cpp:251:2:251:9 | (reference dereference) [post update] | semmle.label | (reference dereference) [post update] |
|
||||
| test.cpp:251:2:251:9 | out_size [post update] | semmle.label | out_size [post update] |
|
||||
| test.cpp:251:18:251:23 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:251:18:251:31 | (const char *)... | semmle.label | (const char *)... |
|
||||
| test.cpp:259:20:259:25 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:259:20:259:33 | (const char *)... | semmle.label | (const char *)... |
|
||||
| test.cpp:263:11:263:29 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:263:11:263:29 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:263:11:263:29 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:289:17:289:20 | size [post update] | semmle.label | size [post update] |
|
||||
| test.cpp:291:11:291:28 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:291:11:291:28 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:291:11:291:28 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:305:18:305:21 | size [post update] | semmle.label | size [post update] |
|
||||
| test.cpp:308:10:308:27 | ... * ... | semmle.label | ... * ... |
|
||||
subpaths
|
||||
| test.cpp:308:10:308:27 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:308:10:308:27 | ... * ... | semmle.label | ... * ... |
|
||||
#select
|
||||
| test.cpp:43:31:43:36 | call to malloc | test.cpp:40:21:40:24 | argv | test.cpp:43:38:43:44 | tainted | This allocation size is derived from $@ and might overflow | test.cpp:40:21:40:24 | argv | user input (a command-line argument) |
|
||||
| test.cpp:44:31:44:36 | call to malloc | test.cpp:40:21:40:24 | argv | test.cpp:44:38:44:63 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:40:21:40:24 | argv | user input (a command-line argument) |
|
||||
| test.cpp:46:31:46:36 | call to malloc | test.cpp:40:21:40:24 | argv | test.cpp:46:38:46:63 | ... + ... | This allocation size is derived from $@ and might overflow | test.cpp:40:21:40:24 | argv | user input (a command-line argument) |
|
||||
| test.cpp:49:25:49:30 | call to malloc | test.cpp:40:21:40:24 | argv | test.cpp:49:32:49:35 | size | This allocation size is derived from $@ and might overflow | test.cpp:40:21:40:24 | argv | user input (a command-line argument) |
|
||||
| test.cpp:50:17:50:30 | new[] | test.cpp:40:21:40:24 | argv | test.cpp:50:26:50:29 | size | This allocation size is derived from $@ and might overflow | test.cpp:40:21:40:24 | argv | user input (a command-line argument) |
|
||||
| test.cpp:53:21:53:27 | call to realloc | test.cpp:40:21:40:24 | argv | test.cpp:53:35:53:60 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:40:21:40:24 | argv | user input (a command-line argument) |
|
||||
| test.cpp:128:17:128:22 | call to malloc | test.cpp:124:18:124:23 | call to getenv | test.cpp:128:24:128:41 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:124:18:124:23 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:135:3:135:8 | call to malloc | test.cpp:133:19:133:24 | call to getenv | test.cpp:135:10:135:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:133:19:133:24 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:152:4:152:9 | call to malloc | test.cpp:148:20:148:25 | call to getenv | test.cpp:152:11:152:28 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:148:20:148:25 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:225:14:225:19 | call to malloc | test.cpp:237:24:237:29 | call to getenv | test.cpp:225:21:225:21 | s | This allocation size is derived from $@ and might overflow | test.cpp:237:24:237:29 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:231:14:231:19 | call to malloc | test.cpp:237:24:237:29 | call to getenv | test.cpp:231:21:231:21 | s | This allocation size is derived from $@ and might overflow | test.cpp:237:24:237:29 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:239:2:239:7 | call to malloc | test.cpp:237:24:237:29 | call to getenv | test.cpp:239:9:239:18 | local_size | This allocation size is derived from $@ and might overflow | test.cpp:237:24:237:29 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:241:2:241:7 | call to malloc | test.cpp:211:14:211:19 | call to getenv | test.cpp:241:9:241:24 | call to get_tainted_size | This allocation size is derived from $@ and might overflow | test.cpp:211:14:211:19 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:263:4:263:9 | call to malloc | test.cpp:259:20:259:25 | call to getenv | test.cpp:263:11:263:29 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:259:20:259:25 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:291:4:291:9 | call to malloc | test.cpp:251:18:251:23 | call to getenv | test.cpp:291:11:291:28 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:251:18:251:23 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:308:3:308:8 | call to malloc | test.cpp:251:18:251:23 | call to getenv | test.cpp:308:10:308:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:251:18:251:23 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:43:31:43:36 | call to malloc | test.cpp:40:21:40:24 | argv | test.cpp:43:38:43:44 | tainted | This allocation size is derived from $@ and might overflow | test.cpp:40:21:40:24 | argv | user input (argv) |
|
||||
| test.cpp:44:31:44:36 | call to malloc | test.cpp:40:21:40:24 | argv | test.cpp:44:38:44:63 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:40:21:40:24 | argv | user input (argv) |
|
||||
| test.cpp:46:31:46:36 | call to malloc | test.cpp:40:21:40:24 | argv | test.cpp:46:38:46:63 | ... + ... | This allocation size is derived from $@ and might overflow | test.cpp:40:21:40:24 | argv | user input (argv) |
|
||||
| test.cpp:49:25:49:30 | call to malloc | test.cpp:40:21:40:24 | argv | test.cpp:49:32:49:35 | size | This allocation size is derived from $@ and might overflow | test.cpp:40:21:40:24 | argv | user input (argv) |
|
||||
| test.cpp:50:17:50:30 | new[] | test.cpp:40:21:40:24 | argv | test.cpp:50:26:50:29 | size | This allocation size is derived from $@ and might overflow | test.cpp:40:21:40:24 | argv | user input (argv) |
|
||||
| test.cpp:53:21:53:27 | call to realloc | test.cpp:40:21:40:24 | argv | test.cpp:53:35:53:60 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:40:21:40:24 | argv | user input (argv) |
|
||||
| test.cpp:128:17:128:22 | call to malloc | test.cpp:124:18:124:23 | call to getenv | test.cpp:128:24:128:41 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:124:18:124:23 | call to getenv | user input (getenv) |
|
||||
| test.cpp:135:3:135:8 | call to malloc | test.cpp:133:19:133:24 | call to getenv | test.cpp:135:10:135:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:133:19:133:24 | call to getenv | user input (getenv) |
|
||||
| test.cpp:152:4:152:9 | call to malloc | test.cpp:148:20:148:25 | call to getenv | test.cpp:152:11:152:28 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:148:20:148:25 | call to getenv | user input (getenv) |
|
||||
| test.cpp:225:14:225:19 | call to malloc | test.cpp:237:24:237:29 | call to getenv | test.cpp:225:21:225:21 | s | This allocation size is derived from $@ and might overflow | test.cpp:237:24:237:29 | call to getenv | user input (getenv) |
|
||||
| test.cpp:231:14:231:19 | call to malloc | test.cpp:237:24:237:29 | call to getenv | test.cpp:231:21:231:21 | s | This allocation size is derived from $@ and might overflow | test.cpp:237:24:237:29 | call to getenv | user input (getenv) |
|
||||
| test.cpp:239:2:239:7 | call to malloc | test.cpp:237:24:237:29 | call to getenv | test.cpp:239:9:239:18 | local_size | This allocation size is derived from $@ and might overflow | test.cpp:237:24:237:29 | call to getenv | user input (getenv) |
|
||||
| test.cpp:241:2:241:7 | call to malloc | test.cpp:211:14:211:19 | call to getenv | test.cpp:241:9:241:24 | call to get_tainted_size | This allocation size is derived from $@ and might overflow | test.cpp:211:14:211:19 | call to getenv | user input (getenv) |
|
||||
| test.cpp:263:4:263:9 | call to malloc | test.cpp:259:20:259:25 | call to getenv | test.cpp:263:11:263:29 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:259:20:259:25 | call to getenv | user input (getenv) |
|
||||
| test.cpp:291:4:291:9 | call to malloc | test.cpp:251:18:251:23 | call to getenv | test.cpp:291:11:291:28 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:251:18:251:23 | call to getenv | user input (getenv) |
|
||||
| test.cpp:308:3:308:8 | call to malloc | test.cpp:251:18:251:23 | call to getenv | test.cpp:308:10:308:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:251:18:251:23 | call to getenv | user input (getenv) |
|
||||
|
||||
@@ -287,6 +287,20 @@ private module SsaDefReaches {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the SSA definition of `v` at `def` reaches uncertain SSA definition
|
||||
* `redef` in the same basic block, without crossing another SSA definition of `v`.
|
||||
*/
|
||||
predicate ssaDefReachesUncertainDefWithinBlock(
|
||||
SourceVariable v, Definition def, UncertainWriteDefinition redef
|
||||
) {
|
||||
exists(BasicBlock bb, int rnk, int i |
|
||||
ssaDefReachesRank(bb, def, rnk, v) and
|
||||
rnk = ssaRefRank(bb, i, v, SsaDef()) - 1 and
|
||||
redef.definesAt(v, bb, i)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as `ssaRefRank()`, but restricted to a particular SSA definition `def`.
|
||||
*/
|
||||
|
||||
@@ -511,6 +511,13 @@ module FinallySplitting {
|
||||
predicate isEntryNode() { first(try.getFinally(), this) }
|
||||
}
|
||||
|
||||
/** A control flow element that does not belong to a `finally` block. */
|
||||
private class NonFinallyControlFlowElement extends ControlFlowElement {
|
||||
NonFinallyControlFlowElement() {
|
||||
not this = any(Statements::TryStmtTree t).getAFinallyDescendant()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A split for elements belonging to a `finally` block, which determines how to
|
||||
* continue execution after leaving the `finally` block. For example, in
|
||||
|
||||
@@ -287,6 +287,20 @@ private module SsaDefReaches {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the SSA definition of `v` at `def` reaches uncertain SSA definition
|
||||
* `redef` in the same basic block, without crossing another SSA definition of `v`.
|
||||
*/
|
||||
predicate ssaDefReachesUncertainDefWithinBlock(
|
||||
SourceVariable v, Definition def, UncertainWriteDefinition redef
|
||||
) {
|
||||
exists(BasicBlock bb, int rnk, int i |
|
||||
ssaDefReachesRank(bb, def, rnk, v) and
|
||||
rnk = ssaRefRank(bb, i, v, SsaDef()) - 1 and
|
||||
redef.definesAt(v, bb, i)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as `ssaRefRank()`, but restricted to a particular SSA definition `def`.
|
||||
*/
|
||||
|
||||
@@ -287,6 +287,20 @@ private module SsaDefReaches {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the SSA definition of `v` at `def` reaches uncertain SSA definition
|
||||
* `redef` in the same basic block, without crossing another SSA definition of `v`.
|
||||
*/
|
||||
predicate ssaDefReachesUncertainDefWithinBlock(
|
||||
SourceVariable v, Definition def, UncertainWriteDefinition redef
|
||||
) {
|
||||
exists(BasicBlock bb, int rnk, int i |
|
||||
ssaDefReachesRank(bb, def, rnk, v) and
|
||||
rnk = ssaRefRank(bb, i, v, SsaDef()) - 1 and
|
||||
redef.definesAt(v, bb, i)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as `ssaRefRank()`, but restricted to a particular SSA definition `def`.
|
||||
*/
|
||||
|
||||
@@ -287,6 +287,20 @@ private module SsaDefReaches {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the SSA definition of `v` at `def` reaches uncertain SSA definition
|
||||
* `redef` in the same basic block, without crossing another SSA definition of `v`.
|
||||
*/
|
||||
predicate ssaDefReachesUncertainDefWithinBlock(
|
||||
SourceVariable v, Definition def, UncertainWriteDefinition redef
|
||||
) {
|
||||
exists(BasicBlock bb, int rnk, int i |
|
||||
ssaDefReachesRank(bb, def, rnk, v) and
|
||||
rnk = ssaRefRank(bb, i, v, SsaDef()) - 1 and
|
||||
redef.definesAt(v, bb, i)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as `ssaRefRank()`, but restricted to a particular SSA definition `def`.
|
||||
*/
|
||||
|
||||
@@ -24,6 +24,13 @@ private class ServiceClass extends Class {
|
||||
}
|
||||
}
|
||||
|
||||
/** Top-level Request DTO types */
|
||||
private class RequestDTO extends Class {
|
||||
RequestDTO() {
|
||||
this.getABaseType*().getABaseInterface().hasQualifiedName("ServiceStack", "IReturn")
|
||||
}
|
||||
}
|
||||
|
||||
/** Flow sources for the ServiceStack framework */
|
||||
module Sources {
|
||||
private import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
|
||||
@@ -11,6 +11,13 @@
|
||||
|
||||
import csharp
|
||||
|
||||
class ZeroFloatLiteral extends FloatLiteral {
|
||||
ZeroFloatLiteral() {
|
||||
this.getValue() = "0" or
|
||||
this.getValue() = "0.0"
|
||||
}
|
||||
}
|
||||
|
||||
from EqualityOperation e
|
||||
where
|
||||
e.getAnOperand().getType() instanceof FloatingPointType and
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
private import ReachableBlock as Reachability
|
||||
|
||||
private module ReachabilityGraph = Reachability::Graph;
|
||||
|
||||
module Graph {
|
||||
import Reachability::Graph
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
private import ReachableBlock as Reachability
|
||||
|
||||
private module ReachabilityGraph = Reachability::Graph;
|
||||
|
||||
module Graph {
|
||||
import Reachability::Graph
|
||||
|
||||
|
||||
@@ -88,6 +88,15 @@ predicate hasAddressType(int byteSize) {
|
||||
*/
|
||||
predicate hasFunctionAddressType(int byteSize) { byteSize = getTypeSize(any(NullType type)) }
|
||||
|
||||
private int getBaseClassSize(ValueOrRefType type) {
|
||||
if exists(type.getBaseClass()) then result = getContentSize(type.getBaseClass()) else result = 0
|
||||
}
|
||||
|
||||
private int getContentSize(ValueOrRefType type) {
|
||||
result =
|
||||
getBaseClassSize(type) + sum(Field field | not field.isStatic() | getTypeSize(field.getType()))
|
||||
}
|
||||
|
||||
private predicate isOpaqueType(ValueOrRefType type) {
|
||||
type instanceof Struct or
|
||||
type instanceof NullableType or
|
||||
|
||||
@@ -1,116 +1,112 @@
|
||||
package,sink,source,summary,sink:bean-validation,sink:create-file,sink:groovy,sink:header-splitting,sink:information-leak,sink:intent-start,sink:jdbc-url,sink:jexl,sink:jndi-injection,sink:ldap,sink:logging,sink:mvel,sink:ognl-injection,sink:open-url,sink:pending-intent-sent,sink:set-hostname-verifier,sink:sql,sink:url-open-stream,sink:url-redirect,sink:write-file,sink:xpath,sink:xslt,sink:xss,source:android-widget,source:contentprovider,source:remote,summary:taint,summary:value
|
||||
android.app,16,,103,,,,,,7,,,,,,,,,9,,,,,,,,,,,,18,85
|
||||
android.content,24,27,100,,,,,,16,,,,,,,,,,,8,,,,,,,,27,,31,69
|
||||
android.database,59,,30,,,,,,,,,,,,,,,,,59,,,,,,,,,,30,
|
||||
android.net,,,60,,,,,,,,,,,,,,,,,,,,,,,,,,,45,15
|
||||
android.os,,,122,,,,,,,,,,,,,,,,,,,,,,,,,,,41,81
|
||||
android.util,6,16,,,,,,,,,,,,6,,,,,,,,,,,,,,,16,,
|
||||
android.webkit,3,2,,,,,,,,,,,,,,,,,,,,,,,,3,,,2,,
|
||||
android.widget,,1,1,,,,,,,,,,,,,,,,,,,,,,,,1,,,1,
|
||||
androidx.slice,2,5,88,,,,,,,,,,,,,,,2,,,,,,,,,,5,,27,61
|
||||
cn.hutool.core.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.esotericsoftware.kryo5.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.fasterxml.jackson.core,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.fasterxml.jackson.databind,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,6,
|
||||
com.google.common.base,,,85,,,,,,,,,,,,,,,,,,,,,,,,,,,62,23
|
||||
com.google.common.cache,,,17,,,,,,,,,,,,,,,,,,,,,,,,,,,,17
|
||||
com.google.common.collect,,,553,,,,,,,,,,,,,,,,,,,,,,,,,,,2,551
|
||||
com.google.common.flogger,29,,,,,,,,,,,,,29,,,,,,,,,,,,,,,,,
|
||||
com.google.common.io,6,,73,,,,,,,,,,,,,,,,,,6,,,,,,,,,72,1
|
||||
com.opensymphony.xwork2.ognl,3,,,,,,,,,,,,,,,3,,,,,,,,,,,,,,,
|
||||
com.unboundid.ldap.sdk,17,,,,,,,,,,,,17,,,,,,,,,,,,,,,,,,
|
||||
com.zaxxer.hikari,2,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,
|
||||
flexjson,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,1
|
||||
groovy.lang,26,,,,,26,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
groovy.util,5,,,,,5,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
jakarta.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,,,2,,,7,,
|
||||
jakarta.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,,,100,23
|
||||
jakarta.ws.rs.client,1,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,
|
||||
jakarta.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,,,,9,,
|
||||
jakarta.ws.rs.core,2,,149,,,,,,,,,,,,,,,,,,,2,,,,,,,,94,55
|
||||
java.beans,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
java.io,37,,31,,15,,,,,,,,,,,,,,,,,,22,,,,,,,31,
|
||||
java.lang,8,,58,,,,,,,,,,,8,,,,,,,,,,,,,,,,46,12
|
||||
java.net,10,3,7,,,,,,,,,,,,,,10,,,,,,,,,,,,3,7,
|
||||
java.nio,15,,6,,13,,,,,,,,,,,,,,,,,,2,,,,,,,6,
|
||||
java.sql,11,,,,,,,,,4,,,,,,,,,,7,,,,,,,,,,,
|
||||
java.util,34,,438,,,,,,,,,,,34,,,,,,,,,,,,,,,,24,414
|
||||
javax.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,,,2,,,7,,
|
||||
javax.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,,,100,23
|
||||
javax.management.remote,2,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,
|
||||
javax.naming,7,,,,,,,,,,,6,1,,,,,,,,,,,,,,,,,,
|
||||
javax.net.ssl,2,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,
|
||||
javax.script,1,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,
|
||||
javax.servlet,4,21,2,,,,3,1,,,,,,,,,,,,,,,,,,,,,21,2,
|
||||
javax.validation,1,1,,1,,,,,,,,,,,,,,,,,,,,,,,,,1,,
|
||||
javax.ws.rs.client,1,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,
|
||||
javax.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,,,,9,,
|
||||
javax.ws.rs.core,3,,149,,,,1,,,,,,,,,,,,,,,2,,,,,,,,94,55
|
||||
javax.xml.transform,1,,6,,,,,,,,,,,,,,,,,,,,,,1,,,,,6,
|
||||
javax.xml.xpath,3,,,,,,,,,,,,,,,,,,,,,,,3,,,,,,,
|
||||
jodd.json,,,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,10
|
||||
net.sf.saxon.s9api,5,,,,,,,,,,,,,,,,,,,,,,,,5,,,,,,
|
||||
ognl,6,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,
|
||||
org.apache.commons.codec,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,6,
|
||||
org.apache.commons.collections,,,800,,,,,,,,,,,,,,,,,,,,,,,,,,,17,783
|
||||
org.apache.commons.collections4,,,800,,,,,,,,,,,,,,,,,,,,,,,,,,,17,783
|
||||
org.apache.commons.io,93,2,565,,78,,,,,,,,,,,,15,,,,,,,,,,,,2,551,14
|
||||
org.apache.commons.jexl2,15,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.commons.jexl3,15,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.commons.lang3,,,424,,,,,,,,,,,,,,,,,,,,,,,,,,,293,131
|
||||
org.apache.commons.logging,6,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,
|
||||
org.apache.commons.ognl,6,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,
|
||||
org.apache.commons.text,,,272,,,,,,,,,,,,,,,,,,,,,,,,,,,220,52
|
||||
org.apache.directory.ldap.client.api,1,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,
|
||||
org.apache.hc.core5.function,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.apache.hc.core5.http,1,2,39,,,,,,,,,,,,,,,,,,,,,,,1,,,2,39,
|
||||
org.apache.hc.core5.net,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,2,
|
||||
org.apache.hc.core5.util,,,24,,,,,,,,,,,,,,,,,,,,,,,,,,,18,6
|
||||
org.apache.http,27,3,70,,,,,,,,,,,,,,25,,,,,,,,,2,,,3,62,8
|
||||
org.apache.ibatis.jdbc,6,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,
|
||||
org.apache.log4j,11,,,,,,,,,,,,,11,,,,,,,,,,,,,,,,,
|
||||
org.apache.logging.log4j,359,,8,,,,,,,,,,,359,,,,,,,,,,,,,,,,4,4
|
||||
org.apache.shiro.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.apache.shiro.jndi,1,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,
|
||||
org.codehaus.groovy.control,1,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.dom4j,20,,,,,,,,,,,,,,,,,,,,,,,20,,,,,,,
|
||||
org.hibernate,7,,,,,,,,,,,,,,,,,,,7,,,,,,,,,,,
|
||||
org.jboss.logging,324,,,,,,,,,,,,,324,,,,,,,,,,,,,,,,,
|
||||
org.jdbi.v3.core,6,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,
|
||||
org.jooq,1,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,
|
||||
org.json,,,236,,,,,,,,,,,,,,,,,,,,,,,,,,,198,38
|
||||
org.mvel2,16,,,,,,,,,,,,,,16,,,,,,,,,,,,,,,,
|
||||
org.scijava.log,13,,,,,,,,,,,,,13,,,,,,,,,,,,,,,,,
|
||||
org.slf4j,55,,6,,,,,,,,,,,55,,,,,,,,,,,,,,,,2,4
|
||||
org.springframework.beans,,,26,,,,,,,,,,,,,,,,,,,,,,,,,,,,26
|
||||
org.springframework.boot.jdbc,1,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,
|
||||
org.springframework.cache,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,13
|
||||
org.springframework.context,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,3,
|
||||
org.springframework.http,14,,70,,,,,,,,,,,,,,14,,,,,,,,,,,,,60,10
|
||||
org.springframework.jdbc.core,10,,,,,,,,,,,,,,,,,,,10,,,,,,,,,,,
|
||||
org.springframework.jdbc.datasource,4,,,,,,,,,4,,,,,,,,,,,,,,,,,,,,,
|
||||
org.springframework.jdbc.object,9,,,,,,,,,,,,,,,,,,,9,,,,,,,,,,,
|
||||
org.springframework.jndi,1,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,
|
||||
org.springframework.ldap,47,,,,,,,,,,,33,14,,,,,,,,,,,,,,,,,,
|
||||
org.springframework.security.web.savedrequest,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,6,,
|
||||
org.springframework.ui,,,32,,,,,,,,,,,,,,,,,,,,,,,,,,,,32
|
||||
org.springframework.util,,,139,,,,,,,,,,,,,,,,,,,,,,,,,,,87,52
|
||||
org.springframework.validation,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,13,
|
||||
org.springframework.web.client,13,3,,,,,,,,,,,,,,,13,,,,,,,,,,,,3,,
|
||||
org.springframework.web.context.request,,8,,,,,,,,,,,,,,,,,,,,,,,,,,,8,,
|
||||
org.springframework.web.multipart,,12,13,,,,,,,,,,,,,,,,,,,,,,,,,,12,13,
|
||||
org.springframework.web.reactive.function.client,2,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,
|
||||
org.springframework.web.util,,,163,,,,,,,,,,,,,,,,,,,,,,,,,,,138,25
|
||||
org.xml.sax,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.xmlpull.v1,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,
|
||||
play.mvc,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,4,,
|
||||
ratpack.core.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,3,
|
||||
ratpack.core.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,,,,6,4,
|
||||
ratpack.core.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,,,,10,10,
|
||||
ratpack.exec,,,48,,,,,,,,,,,,,,,,,,,,,,,,,,,,48
|
||||
ratpack.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,3,
|
||||
ratpack.func,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,,,35
|
||||
ratpack.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,,,,6,4,
|
||||
ratpack.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,,,,10,10,
|
||||
ratpack.util,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,,,35
|
||||
package,sink,source,summary,sink:bean-validation,sink:create-file,sink:groovy,sink:header-splitting,sink:information-leak,sink:intent-start,sink:jexl,sink:jndi-injection,sink:ldap,sink:logging,sink:mvel,sink:ognl-injection,sink:open-url,sink:pending-intent-sent,sink:set-hostname-verifier,sink:sql,sink:url-open-stream,sink:url-redirect,sink:write-file,sink:xpath,sink:xslt,sink:xss,source:android-widget,source:contentprovider,source:remote,summary:taint,summary:value
|
||||
android.app,16,,103,,,,,,7,,,,,,,,9,,,,,,,,,,,,18,85
|
||||
android.content,24,27,100,,,,,,16,,,,,,,,,,8,,,,,,,,27,,31,69
|
||||
android.database,59,,30,,,,,,,,,,,,,,,,59,,,,,,,,,,30,
|
||||
android.net,,,60,,,,,,,,,,,,,,,,,,,,,,,,,,45,15
|
||||
android.os,,,122,,,,,,,,,,,,,,,,,,,,,,,,,,41,81
|
||||
android.util,6,16,,,,,,,,,,,6,,,,,,,,,,,,,,,16,,
|
||||
android.webkit,3,2,,,,,,,,,,,,,,,,,,,,,,,3,,,2,,
|
||||
android.widget,,1,1,,,,,,,,,,,,,,,,,,,,,,,1,,,1,
|
||||
androidx.slice,2,5,88,,,,,,,,,,,,,,2,,,,,,,,,,5,,27,61
|
||||
cn.hutool.core.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.esotericsoftware.kryo5.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.fasterxml.jackson.core,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.fasterxml.jackson.databind,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,6,
|
||||
com.google.common.base,,,85,,,,,,,,,,,,,,,,,,,,,,,,,,62,23
|
||||
com.google.common.cache,,,17,,,,,,,,,,,,,,,,,,,,,,,,,,,17
|
||||
com.google.common.collect,,,553,,,,,,,,,,,,,,,,,,,,,,,,,,2,551
|
||||
com.google.common.flogger,29,,,,,,,,,,,,29,,,,,,,,,,,,,,,,,
|
||||
com.google.common.io,6,,73,,,,,,,,,,,,,,,,,6,,,,,,,,,72,1
|
||||
com.opensymphony.xwork2.ognl,3,,,,,,,,,,,,,,3,,,,,,,,,,,,,,,
|
||||
com.unboundid.ldap.sdk,17,,,,,,,,,,,17,,,,,,,,,,,,,,,,,,
|
||||
flexjson,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,1
|
||||
groovy.lang,26,,,,,26,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
groovy.util,5,,,,,5,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
jakarta.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,,2,,,7,,
|
||||
jakarta.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,,100,23
|
||||
jakarta.ws.rs.client,1,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,
|
||||
jakarta.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,,,9,,
|
||||
jakarta.ws.rs.core,2,,149,,,,,,,,,,,,,,,,,,2,,,,,,,,94,55
|
||||
java.beans,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
java.io,37,,31,,15,,,,,,,,,,,,,,,,,22,,,,,,,31,
|
||||
java.lang,8,,58,,,,,,,,,,8,,,,,,,,,,,,,,,,46,12
|
||||
java.net,10,3,7,,,,,,,,,,,,,10,,,,,,,,,,,,3,7,
|
||||
java.nio,15,,6,,13,,,,,,,,,,,,,,,,,2,,,,,,,6,
|
||||
java.sql,7,,,,,,,,,,,,,,,,,,7,,,,,,,,,,,
|
||||
java.util,34,,438,,,,,,,,,,34,,,,,,,,,,,,,,,,24,414
|
||||
javax.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,,2,,,7,,
|
||||
javax.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,,100,23
|
||||
javax.management.remote,2,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,
|
||||
javax.naming,7,,,,,,,,,,6,1,,,,,,,,,,,,,,,,,,
|
||||
javax.net.ssl,2,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,
|
||||
javax.script,1,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,
|
||||
javax.servlet,4,21,2,,,,3,1,,,,,,,,,,,,,,,,,,,,21,2,
|
||||
javax.validation,1,1,,1,,,,,,,,,,,,,,,,,,,,,,,,1,,
|
||||
javax.ws.rs.client,1,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,
|
||||
javax.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,,,9,,
|
||||
javax.ws.rs.core,3,,149,,,,1,,,,,,,,,,,,,,2,,,,,,,,94,55
|
||||
javax.xml.transform,1,,6,,,,,,,,,,,,,,,,,,,,,1,,,,,6,
|
||||
javax.xml.xpath,3,,,,,,,,,,,,,,,,,,,,,,3,,,,,,,
|
||||
jodd.json,,,10,,,,,,,,,,,,,,,,,,,,,,,,,,,10
|
||||
net.sf.saxon.s9api,5,,,,,,,,,,,,,,,,,,,,,,,5,,,,,,
|
||||
ognl,6,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,
|
||||
org.apache.commons.codec,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,6,
|
||||
org.apache.commons.collections,,,800,,,,,,,,,,,,,,,,,,,,,,,,,,17,783
|
||||
org.apache.commons.collections4,,,800,,,,,,,,,,,,,,,,,,,,,,,,,,17,783
|
||||
org.apache.commons.io,93,2,565,,78,,,,,,,,,,,15,,,,,,,,,,,,2,551,14
|
||||
org.apache.commons.jexl2,15,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.commons.jexl3,15,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.commons.lang3,,,424,,,,,,,,,,,,,,,,,,,,,,,,,,293,131
|
||||
org.apache.commons.logging,6,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,
|
||||
org.apache.commons.ognl,6,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,
|
||||
org.apache.commons.text,,,272,,,,,,,,,,,,,,,,,,,,,,,,,,220,52
|
||||
org.apache.directory.ldap.client.api,1,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,
|
||||
org.apache.hc.core5.function,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.apache.hc.core5.http,1,2,39,,,,,,,,,,,,,,,,,,,,,,1,,,2,39,
|
||||
org.apache.hc.core5.net,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,2,
|
||||
org.apache.hc.core5.util,,,24,,,,,,,,,,,,,,,,,,,,,,,,,,18,6
|
||||
org.apache.http,27,3,70,,,,,,,,,,,,,25,,,,,,,,,2,,,3,62,8
|
||||
org.apache.ibatis.jdbc,6,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,
|
||||
org.apache.log4j,11,,,,,,,,,,,,11,,,,,,,,,,,,,,,,,
|
||||
org.apache.logging.log4j,359,,8,,,,,,,,,,359,,,,,,,,,,,,,,,,4,4
|
||||
org.apache.shiro.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.apache.shiro.jndi,1,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,
|
||||
org.codehaus.groovy.control,1,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.dom4j,20,,,,,,,,,,,,,,,,,,,,,,20,,,,,,,
|
||||
org.hibernate,7,,,,,,,,,,,,,,,,,,7,,,,,,,,,,,
|
||||
org.jboss.logging,324,,,,,,,,,,,,324,,,,,,,,,,,,,,,,,
|
||||
org.jooq,1,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,
|
||||
org.json,,,236,,,,,,,,,,,,,,,,,,,,,,,,,,198,38
|
||||
org.mvel2,16,,,,,,,,,,,,,16,,,,,,,,,,,,,,,,
|
||||
org.scijava.log,13,,,,,,,,,,,,13,,,,,,,,,,,,,,,,,
|
||||
org.slf4j,55,,6,,,,,,,,,,55,,,,,,,,,,,,,,,,2,4
|
||||
org.springframework.beans,,,26,,,,,,,,,,,,,,,,,,,,,,,,,,,26
|
||||
org.springframework.cache,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,13
|
||||
org.springframework.context,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,3,
|
||||
org.springframework.http,14,,70,,,,,,,,,,,,,14,,,,,,,,,,,,,60,10
|
||||
org.springframework.jdbc.core,10,,,,,,,,,,,,,,,,,,10,,,,,,,,,,,
|
||||
org.springframework.jdbc.object,9,,,,,,,,,,,,,,,,,,9,,,,,,,,,,,
|
||||
org.springframework.jndi,1,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,
|
||||
org.springframework.ldap,47,,,,,,,,,,33,14,,,,,,,,,,,,,,,,,,
|
||||
org.springframework.security.web.savedrequest,,6,,,,,,,,,,,,,,,,,,,,,,,,,,6,,
|
||||
org.springframework.ui,,,32,,,,,,,,,,,,,,,,,,,,,,,,,,,32
|
||||
org.springframework.util,,,139,,,,,,,,,,,,,,,,,,,,,,,,,,87,52
|
||||
org.springframework.validation,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,13,
|
||||
org.springframework.web.client,13,3,,,,,,,,,,,,,,13,,,,,,,,,,,,3,,
|
||||
org.springframework.web.context.request,,8,,,,,,,,,,,,,,,,,,,,,,,,,,8,,
|
||||
org.springframework.web.multipart,,12,13,,,,,,,,,,,,,,,,,,,,,,,,,12,13,
|
||||
org.springframework.web.reactive.function.client,2,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,
|
||||
org.springframework.web.util,,,163,,,,,,,,,,,,,,,,,,,,,,,,,,138,25
|
||||
org.xml.sax,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.xmlpull.v1,,3,,,,,,,,,,,,,,,,,,,,,,,,,,3,,
|
||||
play.mvc,,4,,,,,,,,,,,,,,,,,,,,,,,,,,4,,
|
||||
ratpack.core.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,3,
|
||||
ratpack.core.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,,,6,4,
|
||||
ratpack.core.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,,,10,10,
|
||||
ratpack.exec,,,48,,,,,,,,,,,,,,,,,,,,,,,,,,,48
|
||||
ratpack.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,3,
|
||||
ratpack.func,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,,35
|
||||
ratpack.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,,,6,4,
|
||||
ratpack.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,,,10,10,
|
||||
ratpack.util,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,,35
|
||||
|
||||
|
@@ -15,9 +15,9 @@ Java framework & library support
|
||||
`Apache HttpComponents <https://hc.apache.org/>`_,"``org.apache.hc.core5.*``, ``org.apache.http``",5,136,28,,,3,,,,25
|
||||
`Google Guava <https://guava.dev/>`_,``com.google.common.*``,,728,35,,6,,,,,
|
||||
`JSON-java <https://github.com/stleary/JSON-java>`_,``org.json``,,236,,,,,,,,
|
||||
Java Standard Library,``java.*``,3,541,115,28,,,7,,,10
|
||||
Java Standard Library,``java.*``,3,541,111,28,,,7,,,10
|
||||
Java extensions,"``javax.*``, ``jakarta.*``",54,552,32,,,4,,1,1,2
|
||||
`Spring <https://spring.io/>`_,``org.springframework.*``,29,472,101,,,,19,14,,29
|
||||
Others,"``androidx.slice``, ``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.opensymphony.xwork2.ognl``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``net.sf.saxon.s9api``, ``ognl``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.logging``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.log4j``, ``org.apache.logging.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jboss.logging``, ``org.jdbi.v3.core``, ``org.jooq``, ``org.mvel2``, ``org.scijava.log``, ``org.slf4j``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``",44,283,929,,,,14,18,,
|
||||
Totals,,183,6225,1441,106,6,10,107,33,1,81
|
||||
`Spring <https://spring.io/>`_,``org.springframework.*``,29,472,96,,,,19,14,,29
|
||||
Others,"``androidx.slice``, ``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.opensymphony.xwork2.ognl``, ``com.unboundid.ldap.sdk``, ``flexjson``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``net.sf.saxon.s9api``, ``ognl``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.logging``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.log4j``, ``org.apache.logging.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jboss.logging``, ``org.jooq``, ``org.mvel2``, ``org.scijava.log``, ``org.slf4j``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``",44,283,921,,,,14,18,,
|
||||
Totals,,183,6225,1424,106,6,10,107,33,1,81
|
||||
|
||||
|
||||
@@ -9,6 +9,26 @@ import EJB
|
||||
/** A method or constructor that may not be called from an EJB. */
|
||||
abstract class ForbiddenCallable extends Callable { }
|
||||
|
||||
/**
|
||||
* Specialized version of the `polyCalls(..)` predicate for the use
|
||||
* case of finding "shortest" call chains from EJBs to forbidden
|
||||
* methods. This is the same as `polyCalls(..)`, with two exceptions:
|
||||
*
|
||||
* - It does not consider calls into an EJB method.
|
||||
* - It does not consider calls from "forbidden callables".
|
||||
*/
|
||||
private predicate ejbPolyCalls(Callable origin, Callable target) {
|
||||
origin.polyCalls(target) and
|
||||
not exists(EJB ejb | target = ejb.getACallable()) and
|
||||
not origin instanceof ForbiddenCallable
|
||||
}
|
||||
|
||||
private predicate ejbPolyCallsPlus(Callable origin, Callable target) {
|
||||
exists(EJB ejb | origin = ejb.getACallable() | ejbPolyCalls(origin, target))
|
||||
or
|
||||
exists(Callable mid | ejbPolyCallsPlus(origin, mid) and ejbPolyCalls(mid, target))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there exists a call chain from an EJB-`Callable` `origin` to a `ForbiddenCallable` `target`
|
||||
* that does not contain any intermediate EJB-`Callable` or `ForbiddenCallable`,
|
||||
|
||||
@@ -16,6 +16,13 @@
|
||||
|
||||
import java
|
||||
|
||||
class ReachFromStmt extends Stmt {
|
||||
ReachFromStmt() {
|
||||
exists(Method m | m.getBody() = this) or
|
||||
exists(WhileStmt w | w.getStmt() = this)
|
||||
}
|
||||
}
|
||||
|
||||
class SleepMethod extends Method {
|
||||
SleepMethod() {
|
||||
this.getName() = "sleep" and
|
||||
|
||||
@@ -15,6 +15,11 @@ import semmle.code.java.Expr
|
||||
import semmle.code.java.Statement
|
||||
import semmle.code.java.JDK
|
||||
|
||||
/** A use of `+` that has type `String`. */
|
||||
class StringCat extends AddExpr {
|
||||
StringCat() { this.getType() instanceof TypeString }
|
||||
}
|
||||
|
||||
/**
|
||||
* An assignment of the form
|
||||
*
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
* information to be leaked to an attacker more easily.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 7.5
|
||||
* @precision medium
|
||||
* @id java/sensitive-log
|
||||
* @tags security
|
||||
|
||||
@@ -36,6 +36,16 @@ class MessageDigest extends RefType {
|
||||
MessageDigest() { this.hasQualifiedName("java.security", "MessageDigest") }
|
||||
}
|
||||
|
||||
/** The method call `MessageDigest.getInstance(...)` */
|
||||
class MDConstructor extends StaticMethodAccess {
|
||||
MDConstructor() {
|
||||
exists(Method m | m = this.getMethod() |
|
||||
m.getDeclaringType() instanceof MessageDigest and
|
||||
m.hasName("getInstance")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** The method `digest()` declared in `java.security.MessageDigest`. */
|
||||
class MDDigestMethod extends Method {
|
||||
MDDigestMethod() {
|
||||
|
||||
@@ -55,7 +55,7 @@ class JaxRsTest extends InlineExpectationsTest {
|
||||
or
|
||||
tag = "ResourceMethodOnResourceClass" and
|
||||
exists(JaxRsResourceMethod resourceMethod |
|
||||
resourceMethod = any(JaxRsResourceClass resourceClass).getAResourceMethod()
|
||||
resourceMethod = any(JaxRsResourceClass ResourceClass).getAResourceMethod()
|
||||
|
|
||||
resourceMethod.getLocation() = location and
|
||||
element = resourceMethod.toString() and
|
||||
|
||||
@@ -2,8 +2,8 @@ import semmle.code.java.Type
|
||||
|
||||
predicate typeIsInCU(Type tpe, CompilationUnit cu) { tpe.getCompilationUnit() = cu }
|
||||
|
||||
from Type tpe, CompilationUnit aJava
|
||||
from Type tpe, CompilationUnit Ajava
|
||||
where
|
||||
aJava.hasName("A") and
|
||||
typeIsInCU(tpe, aJava)
|
||||
Ajava.hasName("A") and
|
||||
typeIsInCU(tpe, Ajava)
|
||||
select tpe
|
||||
|
||||
@@ -62,6 +62,28 @@ abstract class AtmConfig extends string {
|
||||
*/
|
||||
predicate isEffectiveSink(raw::DataFlow::Node candidateSink) { none() }
|
||||
|
||||
/**
|
||||
* EXPERIMENTAL. This API may change in the future.
|
||||
*
|
||||
* Holds if the candidate sink `candidateSink` predicted by the machine learning model should be
|
||||
* an effective sink that overrides the score provided by the machine learning model with the
|
||||
* score `score` for reason `why`. The effective sinks identified by this predicate MUST be a
|
||||
* subset of those identified by the `isEffectiveSink` predicate.
|
||||
*
|
||||
* For example, in the ATM external API query, we use this method to ensure the ATM external API
|
||||
* query produces the same results as the standard external API query, but assigns flows
|
||||
* involving sinks that are filtered out by the endpoint filters a score of 0.
|
||||
*
|
||||
* This predicate can be phased out once we no longer need to rely on predicates like
|
||||
* `paddedScore` in the ATM CodeQL libraries to add scores to alert messages in a way that works
|
||||
* with lexical sort orders.
|
||||
*/
|
||||
predicate isEffectiveSinkWithOverridingScore(
|
||||
raw::DataFlow::Node candidateSink, float score, string why
|
||||
) {
|
||||
none()
|
||||
}
|
||||
|
||||
/**
|
||||
* EXPERIMENTAL. This API may change in the future.
|
||||
*
|
||||
|
||||
@@ -62,11 +62,14 @@ private float getScoreForSource(DataFlow::Node source) {
|
||||
private float getScoreForSink(DataFlow::Node sink) {
|
||||
if getCfg().isKnownSink(sink)
|
||||
then result = 1.0
|
||||
else (
|
||||
// This restriction on `sink` has no semantic effect but improves performance.
|
||||
getCfg().isEffectiveSink(sink) and
|
||||
ModelScoring::endpointScores(sink, getCfg().getASinkEndpointType().getEncoding(), result)
|
||||
)
|
||||
else
|
||||
if getCfg().isEffectiveSinkWithOverridingScore(sink, result, _)
|
||||
then any()
|
||||
else (
|
||||
// This restriction on `sink` has no semantic effect but improves performance.
|
||||
getCfg().isEffectiveSink(sink) and
|
||||
ModelScoring::endpointScores(sink, getCfg().getASinkEndpointType().getEncoding(), result)
|
||||
)
|
||||
}
|
||||
|
||||
class EndpointScoringResults extends ScoringResults {
|
||||
@@ -106,6 +109,10 @@ class EndpointScoringResults extends ScoringResults {
|
||||
result = "known" and getCfg().isKnownSink(sink)
|
||||
or
|
||||
not getCfg().isKnownSink(sink) and
|
||||
getCfg().isEffectiveSinkWithOverridingScore(sink, _, result)
|
||||
or
|
||||
not getCfg().isKnownSink(sink) and
|
||||
not getCfg().isEffectiveSinkWithOverridingScore(sink, _, _) and
|
||||
result =
|
||||
"predicted (scores: " +
|
||||
concat(EndpointType type, float score |
|
||||
@@ -120,21 +127,29 @@ class EndpointScoringResults extends ScoringResults {
|
||||
override predicate shouldResultBeIncluded(DataFlow::Node source, DataFlow::Node sink) {
|
||||
if getCfg().isKnownSink(sink)
|
||||
then any()
|
||||
else (
|
||||
// This restriction on `sink` has no semantic effect but improves performance.
|
||||
getCfg().isEffectiveSink(sink) and
|
||||
exists(float sinkScore |
|
||||
ModelScoring::endpointScores(sink, getCfg().getASinkEndpointType().getEncoding(), sinkScore) and
|
||||
// Include the endpoint if (a) the query endpoint type scores higher than all other
|
||||
// endpoint types, or (b) the query endpoint type scores at least
|
||||
// 0.5 - (getCfg().getScoreCutoff() / 2).
|
||||
sinkScore >=
|
||||
[
|
||||
max(float s | ModelScoring::endpointScores(sink, _, s)),
|
||||
0.5 - getCfg().getScoreCutoff() / 2
|
||||
]
|
||||
else
|
||||
if getCfg().isEffectiveSinkWithOverridingScore(sink, _, _)
|
||||
then
|
||||
exists(float score |
|
||||
getCfg().isEffectiveSinkWithOverridingScore(sink, score, _) and
|
||||
score >= getCfg().getScoreCutoff()
|
||||
)
|
||||
else (
|
||||
// This restriction on `sink` has no semantic effect but improves performance.
|
||||
getCfg().isEffectiveSink(sink) and
|
||||
exists(float sinkScore |
|
||||
ModelScoring::endpointScores(sink, getCfg().getASinkEndpointType().getEncoding(),
|
||||
sinkScore) and
|
||||
// Include the endpoint if (a) the query endpoint type scores higher than all other
|
||||
// endpoint types, or (b) the query endpoint type scores at least
|
||||
// 0.5 - (getCfg().getScoreCutoff() / 2).
|
||||
sinkScore >=
|
||||
[
|
||||
max(float s | ModelScoring::endpointScores(sink, _, s)),
|
||||
0.5 - getCfg().getScoreCutoff() / 2
|
||||
]
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,25 +17,24 @@ predicate isIntermediaryDataflowNode(DataFlow::Node n) {
|
||||
|
||||
/** Provides a set of reasons why a given data flow node should be excluded as a sink candidate. */
|
||||
string getAReasonSinkExcluded(DataFlow::Node n) {
|
||||
not isIntermediaryDataflowNode(n) and
|
||||
(
|
||||
isArgumentToModeledFunction(n) and result = "argument to modeled function"
|
||||
or
|
||||
isArgumentToSinklessLibrary(n) and result = "argument to sinkless library"
|
||||
or
|
||||
isSanitizer(n) and result = "sanitizer"
|
||||
or
|
||||
isPredicate(n) and result = "predicate"
|
||||
or
|
||||
isHash(n) and result = "hash"
|
||||
or
|
||||
isNumeric(n) and result = "numeric"
|
||||
or
|
||||
// Ignore candidate sinks within externs, generated, library, and test code
|
||||
exists(string category | category = ["externs", "generated", "library", "test"] |
|
||||
ClassifyFiles::classify(n.getFile(), category) and
|
||||
result = "in " + category + " file"
|
||||
)
|
||||
isIntermediaryDataflowNode(n) and result = "intermediary dataflow node"
|
||||
or
|
||||
isArgumentToModeledFunction(n) and result = "argument to modeled function"
|
||||
or
|
||||
isArgumentToSinklessLibrary(n) and result = "argument to sinkless library"
|
||||
or
|
||||
isSanitizer(n) and result = "sanitizer"
|
||||
or
|
||||
isPredicate(n) and result = "predicate"
|
||||
or
|
||||
isHash(n) and result = "hash"
|
||||
or
|
||||
isNumeric(n) and result = "numeric"
|
||||
or
|
||||
// Ignore candidate sinks within externs, generated, library, and test code
|
||||
exists(string category | category = ["externs", "generated", "library", "test"] |
|
||||
ClassifyFiles::classify(n.getFile(), category) and
|
||||
result = "in " + category + " file"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -132,7 +131,7 @@ private DataFlow::SourceNode getACallback(DataFlow::ParameterNode p, DataFlow::T
|
||||
* Get calls for which we do not have the callee (i.e. the definition of the called function). This
|
||||
* acts as a heuristic for identifying calls to external library functions.
|
||||
*/
|
||||
private DataFlow::InvokeNode getACallWithoutCallee() {
|
||||
private DataFlow::CallNode getACallWithoutCallee() {
|
||||
forall(Function callee | callee = result.getACallee() | callee.getTopLevel().isExterns()) and
|
||||
not exists(DataFlow::ParameterNode param, DataFlow::FunctionNode callback |
|
||||
param.flowsTo(result.getCalleeNode()) and
|
||||
|
||||
@@ -25,40 +25,37 @@ module SinkEndpointFilter {
|
||||
* effective sink.
|
||||
*/
|
||||
string getAReasonSinkExcluded(DataFlow::Node sinkCandidate) {
|
||||
not StandardEndpointFilters::isIntermediaryDataflowNode(sinkCandidate) and
|
||||
(
|
||||
result = StandardEndpointFilters::getAReasonSinkExcluded(sinkCandidate)
|
||||
result = StandardEndpointFilters::getAReasonSinkExcluded(sinkCandidate)
|
||||
or
|
||||
// Require path injection sink candidates to be (a) arguments to external library calls
|
||||
// (possibly indirectly), or (b) heuristic sinks.
|
||||
//
|
||||
// Heuristic sinks are mostly copied from the `HeuristicTaintedPathSink` class defined within
|
||||
// `codeql/javascript/ql/src/semmle/javascript/heuristics/AdditionalSinks.qll`.
|
||||
// We can't reuse the class because importing that file would cause us to treat these
|
||||
// heuristic sinks as known sinks.
|
||||
not StandardEndpointFilters::flowsToArgumentOfLikelyExternalLibraryCall(sinkCandidate) and
|
||||
not (
|
||||
isAssignedToOrConcatenatedWith(sinkCandidate, "(?i)(file|folder|dir|absolute)")
|
||||
or
|
||||
// Require path injection sink candidates to be (a) arguments to external library calls
|
||||
// (possibly indirectly), or (b) heuristic sinks.
|
||||
//
|
||||
// Heuristic sinks are mostly copied from the `HeuristicTaintedPathSink` class defined within
|
||||
// `codeql/javascript/ql/src/semmle/javascript/heuristics/AdditionalSinks.qll`.
|
||||
// We can't reuse the class because importing that file would cause us to treat these
|
||||
// heuristic sinks as known sinks.
|
||||
not StandardEndpointFilters::flowsToArgumentOfLikelyExternalLibraryCall(sinkCandidate) and
|
||||
not (
|
||||
isAssignedToOrConcatenatedWith(sinkCandidate, "(?i)(file|folder|dir|absolute)")
|
||||
or
|
||||
isArgTo(sinkCandidate, "(?i)(get|read)file")
|
||||
or
|
||||
exists(string pathPattern |
|
||||
// paths with at least two parts, and either a trailing or leading slash
|
||||
pathPattern = "(?i)([a-z0-9_.-]+/){2,}" or
|
||||
pathPattern = "(?i)(/[a-z0-9_.-]+){2,}"
|
||||
|
|
||||
isConcatenatedWithString(sinkCandidate, pathPattern)
|
||||
)
|
||||
or
|
||||
isConcatenatedWithStrings(".*/", sinkCandidate, "/.*")
|
||||
or
|
||||
// In addition to the names from `HeuristicTaintedPathSink` in the
|
||||
// `isAssignedToOrConcatenatedWith` predicate call above, we also allow the noisier "path"
|
||||
// name.
|
||||
isAssignedToOrConcatenatedWith(sinkCandidate, "(?i)path")
|
||||
) and
|
||||
result = "not a direct argument to a likely external library call or a heuristic sink"
|
||||
)
|
||||
isArgTo(sinkCandidate, "(?i)(get|read)file")
|
||||
or
|
||||
exists(string pathPattern |
|
||||
// paths with at least two parts, and either a trailing or leading slash
|
||||
pathPattern = "(?i)([a-z0-9_.-]+/){2,}" or
|
||||
pathPattern = "(?i)(/[a-z0-9_.-]+){2,}"
|
||||
|
|
||||
isConcatenatedWithString(sinkCandidate, pathPattern)
|
||||
)
|
||||
or
|
||||
isConcatenatedWithStrings(".*/", sinkCandidate, "/.*")
|
||||
or
|
||||
// In addition to the names from `HeuristicTaintedPathSink` in the
|
||||
// `isAssignedToOrConcatenatedWith` predicate call above, we also allow the noisier "path"
|
||||
// name.
|
||||
isAssignedToOrConcatenatedWith(sinkCandidate, "(?i)path")
|
||||
) and
|
||||
result = "not a direct argument to a likely external library call or a heuristic sink"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,10 @@ private DataFlow::Node getANotASink(NotASinkReason reason) {
|
||||
* specified query.
|
||||
*/
|
||||
private DataFlow::Node getAnUnknown(Query query) {
|
||||
getAtmCfg(query).isEffectiveSink(result) and
|
||||
(
|
||||
getAtmCfg(query).isEffectiveSink(result) or
|
||||
getAtmCfg(query).isEffectiveSinkWithOverridingScore(result, _, _)
|
||||
) and
|
||||
not result = getASink(query) and
|
||||
// Only consider the source code for the project being analyzed.
|
||||
exists(result.getFile().getRelativePath())
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
/*
|
||||
* For internal use only.
|
||||
*
|
||||
* Maps ML-powered queries to their `EndpointType` for clearer labelling while evaluating ML model during training.
|
||||
*/
|
||||
|
||||
import experimental.adaptivethreatmodeling.SqlInjectionATM as SqlInjectionATM
|
||||
import experimental.adaptivethreatmodeling.NosqlInjectionATM as NosqlInjectionATM
|
||||
import experimental.adaptivethreatmodeling.TaintedPathATM as TaintedPathATM
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* Some modules that started with a lowercase letter have been renamed to follow our style-guide.
|
||||
The old name still exists as a deprecated alias.
|
||||
@@ -181,7 +181,16 @@ class DynamicPropRead extends DataFlow::SourceNode, DataFlow::ValueNode {
|
||||
* dst[x][y] = src[y];
|
||||
* ```
|
||||
*/
|
||||
predicate hasDominatingAssignment() { AccessPath::DominatingPaths::hasDominatingWrite(this) }
|
||||
predicate hasDominatingAssignment() {
|
||||
exists(DataFlow::PropWrite write, BasicBlock bb, int i, int j, SsaVariable ssaVar |
|
||||
write = getBase().getALocalSource().getAPropertyWrite() and
|
||||
bb.getNode(i) = write.getWriteNode() and
|
||||
bb.getNode(j) = astNode and
|
||||
i < j and
|
||||
write.getPropertyNameExpr() = ssaVar.getAUse() and
|
||||
astNode.getIndex() = ssaVar.getAUse()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -532,7 +532,7 @@ module AccessPath {
|
||||
*/
|
||||
cached
|
||||
predicate hasDominatingWrite(DataFlow::PropRead read) {
|
||||
Stages::TypeTracking::ref() and
|
||||
Stages::FlowSteps::ref() and
|
||||
// within the same basic block.
|
||||
exists(ReachableBasicBlock bb, Root root, string path, int ranking |
|
||||
read.asExpr() = rankedAccessPath(bb, root, path, ranking, AccessPathRead()) and
|
||||
@@ -544,21 +544,6 @@ module AccessPath {
|
||||
read.asExpr() = getAccessTo(root, path, AccessPathRead()) and
|
||||
getAWriteBlock(root, path).strictlyDominates(read.getBasicBlock())
|
||||
)
|
||||
or
|
||||
// Dynamic write where the same variable is used to index the read and write (in the same basic block)
|
||||
// For example, this is true for `dst[x]` on line 2 below:
|
||||
// ```js
|
||||
// dst[x] = {};
|
||||
// dst[x][y] = src[y];
|
||||
// ```
|
||||
exists(DataFlow::PropWrite write, BasicBlock bb, int i, int j, SsaVariable ssaVar |
|
||||
write = read.getBase().getALocalSource().getAPropertyWrite() and
|
||||
bb.getNode(i) = write.getWriteNode() and
|
||||
bb.getNode(j) = read.asExpr() and
|
||||
i < j and
|
||||
write.getPropertyNameExpr() = ssaVar.getAUse() and
|
||||
read.getPropertyNameExpr() = ssaVar.getAUse()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -534,10 +534,7 @@ module TaintTracking {
|
||||
or
|
||||
// reading from a tainted object yields a tainted result
|
||||
succ.(DataFlow::PropRead).getBase() = pred and
|
||||
not (
|
||||
AccessPath::DominatingPaths::hasDominatingWrite(succ) and
|
||||
exists(succ.(DataFlow::PropRead).getPropertyName())
|
||||
) and
|
||||
not AccessPath::DominatingPaths::hasDominatingWrite(succ) and
|
||||
not isSafeClientSideUrlProperty(succ) and
|
||||
not ClassValidator::isAccessToSanitizedField(succ)
|
||||
or
|
||||
|
||||
@@ -123,7 +123,7 @@ private module Winston {
|
||||
/**
|
||||
* Provides classes for working with [log4js](https://github.com/log4js-node/log4js-node).
|
||||
*/
|
||||
private module Log4js {
|
||||
private module log4js {
|
||||
/**
|
||||
* A call to the log4js logging mechanism.
|
||||
*/
|
||||
|
||||
@@ -14,13 +14,10 @@ abstract deprecated class UriLibraryStep extends DataFlow::ValueNode {
|
||||
predicate step(DataFlow::Node pred, DataFlow::Node succ) { none() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `Urijs` */
|
||||
deprecated module urijs = Urijs;
|
||||
|
||||
/**
|
||||
* Provides classes for working with [urijs](http://medialize.github.io/URI.js/) code.
|
||||
*/
|
||||
module Urijs {
|
||||
module urijs {
|
||||
/**
|
||||
* Gets a data flow source node for the urijs library.
|
||||
*/
|
||||
@@ -83,13 +80,10 @@ module Urijs {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `Uridashjs` */
|
||||
deprecated module uridashjs = Uridashjs;
|
||||
|
||||
/**
|
||||
* Provides classes for working with [uri-js](https://github.com/garycourt/uri-js) code.
|
||||
*/
|
||||
module Uridashjs {
|
||||
module uridashjs {
|
||||
/**
|
||||
* Gets a data flow source node for member `name` of the uridashjs library.
|
||||
*/
|
||||
@@ -111,13 +105,10 @@ module Uridashjs {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `Punycode` */
|
||||
deprecated module punycode = Punycode;
|
||||
|
||||
/**
|
||||
* Provides classes for working with [punycode](https://github.com/bestiejs/punycode.js) code.
|
||||
*/
|
||||
module Punycode {
|
||||
module punycode {
|
||||
/**
|
||||
* Gets a data flow source node for member `name` of the punycode library.
|
||||
*/
|
||||
@@ -139,13 +130,10 @@ module Punycode {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `UrlParse` */
|
||||
deprecated module urlParse = UrlParse;
|
||||
|
||||
/**
|
||||
* Provides classes for working with [url-parse](https://github.com/unshiftio/url-parse) code.
|
||||
*/
|
||||
module UrlParse {
|
||||
module urlParse {
|
||||
/**
|
||||
* Gets a data flow source node for the url-parse library.
|
||||
*/
|
||||
@@ -179,13 +167,10 @@ module UrlParse {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `Querystringify` */
|
||||
deprecated module querystringify = Querystringify;
|
||||
|
||||
/**
|
||||
* Provides classes for working with [querystringify](https://github.com/unshiftio/querystringify) code.
|
||||
*/
|
||||
module Querystringify {
|
||||
module querystringify {
|
||||
/**
|
||||
* Gets a data flow source node for member `name` of the querystringify library.
|
||||
*/
|
||||
@@ -212,13 +197,10 @@ module Querystringify {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `Querydashstring` */
|
||||
deprecated module querydashstring = Querydashstring;
|
||||
|
||||
/**
|
||||
* Provides classes for working with [query-string](https://github.com/sindresorhus/query-string) code.
|
||||
*/
|
||||
module Querydashstring {
|
||||
module querydashstring {
|
||||
/**
|
||||
* Gets a data flow source node for member `name` of the query-string library.
|
||||
*/
|
||||
@@ -240,13 +222,10 @@ module Querydashstring {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `Url` */
|
||||
deprecated module url = Url;
|
||||
|
||||
/**
|
||||
* Provides classes for working with [url](https://nodejs.org/api/url.html) code.
|
||||
*/
|
||||
module Url {
|
||||
module url {
|
||||
/**
|
||||
* Gets a data flow source node for member `name` of the url library.
|
||||
*/
|
||||
@@ -266,13 +245,10 @@ module Url {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `Querystring` */
|
||||
deprecated module querystring = Querystring;
|
||||
|
||||
/**
|
||||
* Provides classes for working with [querystring](https://nodejs.org/api/querystring.html) code.
|
||||
*/
|
||||
module Querystring {
|
||||
module querystring {
|
||||
/**
|
||||
* Gets a data flow source node for member `name` of the querystring library.
|
||||
*/
|
||||
@@ -432,7 +408,7 @@ private module ClosureLibraryUri {
|
||||
/**
|
||||
* Provides classes for working with [path](https://nodejs.org/api/path.html) code.
|
||||
*/
|
||||
module Path {
|
||||
module path {
|
||||
/**
|
||||
* A taint step in the path module.
|
||||
*/
|
||||
|
||||
@@ -212,8 +212,6 @@ module Stages {
|
||||
any(DataFlow::Node node).hasUnderlyingType(_)
|
||||
or
|
||||
any(DataFlow::Node node).hasUnderlyingType(_, _)
|
||||
or
|
||||
AccessPath::DominatingPaths::hasDominatingWrite(_)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,6 +235,8 @@ module Stages {
|
||||
predicate backref() {
|
||||
1 = 1
|
||||
or
|
||||
AccessPath::DominatingPaths::hasDominatingWrite(_)
|
||||
or
|
||||
DataFlow::SharedFlowStep::step(_, _)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,15 @@
|
||||
import javascript
|
||||
import InsecureDownloadCustomizations::InsecureDownload
|
||||
|
||||
// Materialize flow labels
|
||||
private class ConcreteSensitiveInsecureUrl extends Label::SensitiveInsecureUrl {
|
||||
ConcreteSensitiveInsecureUrl() { this = this }
|
||||
}
|
||||
|
||||
private class ConcreteInsecureUrl extends Label::InsecureUrl {
|
||||
ConcreteInsecureUrl() { this = this }
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint tracking configuration for download of sensitive file through insecure connection.
|
||||
*/
|
||||
|
||||
@@ -13,25 +13,26 @@
|
||||
|
||||
import javascript
|
||||
|
||||
/** Gets options argument for a potential TLS connection */
|
||||
DataFlow::InvokeNode tlsInvocation() {
|
||||
result instanceof ClientRequest
|
||||
or
|
||||
result = DataFlow::moduleMember("https", "Agent").getAnInstantiation()
|
||||
or
|
||||
exists(DataFlow::NewNode new |
|
||||
new = DataFlow::moduleMember("tls", "TLSSocket").getAnInstantiation()
|
||||
|
|
||||
result = new or
|
||||
result = new.getAMethodCall("renegotiate")
|
||||
/**
|
||||
* Gets an options object for a TLS connection.
|
||||
*/
|
||||
DataFlow::ObjectLiteralNode tlsOptions() {
|
||||
exists(DataFlow::InvokeNode invk | result.flowsTo(invk.getAnArgument()) |
|
||||
invk instanceof ClientRequest
|
||||
or
|
||||
invk = DataFlow::moduleMember("https", "Agent").getAnInstantiation()
|
||||
or
|
||||
exists(DataFlow::NewNode new |
|
||||
new = DataFlow::moduleMember("tls", "TLSSocket").getAnInstantiation()
|
||||
|
|
||||
invk = new or
|
||||
invk = new.getAMethodCall("renegotiate")
|
||||
)
|
||||
or
|
||||
invk = DataFlow::moduleMember("tls", ["connect", "createServer"]).getACall()
|
||||
)
|
||||
or
|
||||
result = DataFlow::moduleMember("tls", ["connect", "createServer"]).getACall()
|
||||
}
|
||||
|
||||
/** Gets an options object for a TLS connection. */
|
||||
DataFlow::ObjectLiteralNode tlsOptions() { result.flowsTo(tlsInvocation().getAnArgument()) }
|
||||
|
||||
from DataFlow::PropWrite disable
|
||||
where
|
||||
exists(DataFlow::SourceNode env |
|
||||
@@ -40,13 +41,6 @@ where
|
||||
disable.getRhs().mayHaveStringValue("0")
|
||||
)
|
||||
or
|
||||
(
|
||||
disable = tlsOptions().getAPropertyWrite("rejectUnauthorized")
|
||||
or
|
||||
// the same thing, but with API-nodes if they happen to be available
|
||||
exists(API::Node tlsInvk | tlsInvk.getAnInvocation() = tlsInvocation() |
|
||||
disable.getRhs() = tlsInvk.getAParameter().getMember("rejectUnauthorized").getARhs()
|
||||
)
|
||||
) and
|
||||
disable = tlsOptions().getAPropertyWrite("rejectUnauthorized") and
|
||||
disable.getRhs().(AnalyzedNode).getTheBooleanValue() = false
|
||||
select disable, "Disabling certificate validation is strongly discouraged."
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import javascript
|
||||
|
||||
query predicate punycode(DataFlow::Node n) { n = Punycode::punycodeMember(_) }
|
||||
query predicate punycode(DataFlow::Node n) { n = punycode::punycodeMember(_) }
|
||||
|
||||
query predicate querydashstring(DataFlow::Node n) { n = Querydashstring::querydashstringMember(_) }
|
||||
query predicate querydashstring(DataFlow::Node n) { n = querydashstring::querydashstringMember(_) }
|
||||
|
||||
query predicate querystring(DataFlow::Node n) { n = Querystring::querystringMember(_) }
|
||||
query predicate querystring(DataFlow::Node n) { n = querystring::querystringMember(_) }
|
||||
|
||||
query predicate querystringify(DataFlow::Node n) { n = Querystringify::querystringifyMember(_) }
|
||||
query predicate querystringify(DataFlow::Node n) { n = querystringify::querystringifyMember(_) }
|
||||
|
||||
query predicate uridashjs(DataFlow::Node n) { n = Uridashjs::uridashjsMember(_) }
|
||||
query predicate uridashjs(DataFlow::Node n) { n = uridashjs::uridashjsMember(_) }
|
||||
|
||||
query predicate urijs(DataFlow::Node n) { n = Urijs::urijs() }
|
||||
query predicate urijs(DataFlow::Node n) { n = urijs::urijs() }
|
||||
|
||||
query predicate uriLibraryStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
TaintTracking::uriStep(pred, succ)
|
||||
}
|
||||
|
||||
query predicate url(DataFlow::Node n) { n = Url::urlMember(_) }
|
||||
query predicate url(DataFlow::Node n) { n = url::urlMember(_) }
|
||||
|
||||
query predicate urlParse(DataFlow::Node n) { n = UrlParse::urlParse() }
|
||||
query predicate urlParse(DataFlow::Node n) { n = urlParse::urlParse() }
|
||||
|
||||
@@ -8,4 +8,3 @@
|
||||
| tst.js:39:2:39:29 | rejectU ... ndirect | Disabling certificate validation is strongly discouraged. |
|
||||
| tst.js:45:2:45:28 | rejectU ... !!false | Disabling certificate validation is strongly discouraged. |
|
||||
| tst.js:48:2:48:26 | rejectU ... : !true | Disabling certificate validation is strongly discouraged. |
|
||||
| tst.js:74:9:74:33 | rejectU ... : false | Disabling certificate validation is strongly discouraged. |
|
||||
|
||||
@@ -68,10 +68,3 @@ new https.Agent({
|
||||
new https.Agent({
|
||||
rejectUnauthorized: typeof getOptions().rejectUnauthorized === 'boolean' ? getOptions().rejectUnauthorized : undefined // OK
|
||||
});
|
||||
|
||||
function getSomeunsafeOptions() {
|
||||
return {
|
||||
rejectUnauthorized: false // NOT OK
|
||||
}
|
||||
}
|
||||
new https.Agent(getSomeunsafeOptions());
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* Some modules that started with a lowercase letter have been renamed to follow our style-guide.
|
||||
The old name still exists as a deprecated alias.
|
||||
@@ -969,6 +969,12 @@ private module Scopes {
|
||||
scope = n.getEnclosingModule()
|
||||
}
|
||||
|
||||
private predicate maybe_defined(SsaVariable var) {
|
||||
exists(var.getDefinition()) and not py_ssa_phi(var, _) and not var.getDefinition().isDelete()
|
||||
or
|
||||
exists(SsaVariable input | input = var.getAPhiInput() | maybe_defined(input))
|
||||
}
|
||||
|
||||
private predicate maybe_undefined(SsaVariable var) {
|
||||
not exists(var.getDefinition()) and not py_ssa_phi(var, _)
|
||||
or
|
||||
|
||||
@@ -27,9 +27,9 @@ class FunctionMetrics extends Function {
|
||||
* P = the number of connected components, which for a single function is 1.
|
||||
*/
|
||||
int getCyclomaticComplexity() {
|
||||
exists(int e, int n |
|
||||
n = count(BasicBlock b | b = this.getABasicBlock() and b.likelyReachable()) and
|
||||
e =
|
||||
exists(int E, int N |
|
||||
N = count(BasicBlock b | b = this.getABasicBlock() and b.likelyReachable()) and
|
||||
E =
|
||||
count(BasicBlock b1, BasicBlock b2 |
|
||||
b1 = this.getABasicBlock() and
|
||||
b1.likelyReachable() and
|
||||
@@ -39,7 +39,7 @@ class FunctionMetrics extends Function {
|
||||
not b1.unlikelySuccessor(b2)
|
||||
)
|
||||
|
|
||||
result = e - n + 2
|
||||
result = E - N + 2
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -39,11 +39,8 @@ predicate isArgumentNode(ArgumentNode arg, DataFlowCall c, ArgumentPosition pos)
|
||||
//--------
|
||||
predicate isExpressionNode(ControlFlowNode node) { node.getNode() instanceof Expr }
|
||||
|
||||
/** DEPRECATED: Alias for `SyntheticPreUpdateNode` */
|
||||
deprecated module syntheticPreUpdateNode = SyntheticPreUpdateNode;
|
||||
|
||||
/** A module collecting the different reasons for synthesising a pre-update node. */
|
||||
module SyntheticPreUpdateNode {
|
||||
module syntheticPreUpdateNode {
|
||||
class SyntheticPreUpdateNode extends Node, TSyntheticPreUpdateNode {
|
||||
NeedsSyntheticPreUpdateNode post;
|
||||
|
||||
@@ -81,13 +78,10 @@ module SyntheticPreUpdateNode {
|
||||
CfgNode objectCreationNode() { result.getNode().(CallNode) = any(ClassCall c).getNode() }
|
||||
}
|
||||
|
||||
import SyntheticPreUpdateNode
|
||||
|
||||
/** DEPRECATED: Alias for `SyntheticPostUpdateNode` */
|
||||
deprecated module syntheticPostUpdateNode = SyntheticPostUpdateNode;
|
||||
import syntheticPreUpdateNode
|
||||
|
||||
/** A module collecting the different reasons for synthesising a post-update node. */
|
||||
module SyntheticPostUpdateNode {
|
||||
module syntheticPostUpdateNode {
|
||||
/** A post-update node is synthesized for all nodes which satisfy `NeedsSyntheticPostUpdateNode`. */
|
||||
class SyntheticPostUpdateNode extends PostUpdateNode, TSyntheticPostUpdateNode {
|
||||
NeedsSyntheticPostUpdateNode pre;
|
||||
@@ -183,7 +177,7 @@ module SyntheticPostUpdateNode {
|
||||
}
|
||||
}
|
||||
|
||||
import SyntheticPostUpdateNode
|
||||
import syntheticPostUpdateNode
|
||||
|
||||
class DataFlowExpr = Expr;
|
||||
|
||||
|
||||
@@ -900,6 +900,22 @@ private class EssaTaintTracking extends string {
|
||||
or
|
||||
result = this.testEvaluates(defn, not_operand(test), use, src).booleanNot()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `test` is the test in a branch and `use` is that test
|
||||
* with all the `not` prefixes removed.
|
||||
*/
|
||||
private predicate boolean_filter(ControlFlowNode test, ControlFlowNode use) {
|
||||
any(PyEdgeRefinement ref).getTest() = test and
|
||||
(
|
||||
use = test
|
||||
or
|
||||
exists(ControlFlowNode notuse |
|
||||
this.boolean_filter(test, notuse) and
|
||||
use = not_operand(notuse)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate testEvaluatesMaybe(ControlFlowNode test, ControlFlowNode use) {
|
||||
|
||||
@@ -526,11 +526,8 @@ module PrivateDjango {
|
||||
/** Gets a reference to the `django` module. */
|
||||
API::Node django() { result = API::moduleImport("django") }
|
||||
|
||||
/** DEPRECATED: Alias for `DjangoImpl` */
|
||||
deprecated module django = DjangoImpl;
|
||||
|
||||
/** Provides models for the `django` module. */
|
||||
module DjangoImpl {
|
||||
module django {
|
||||
// -------------------------------------------------------------------------
|
||||
// django.db
|
||||
// -------------------------------------------------------------------------
|
||||
@@ -544,11 +541,8 @@ module PrivateDjango {
|
||||
DjangoDb() { this = API::moduleImport("django").getMember("db") }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `DB` */
|
||||
deprecated module db = DB;
|
||||
|
||||
/** Provides models for the `django.db` module. */
|
||||
module DB {
|
||||
module db {
|
||||
/** Gets a reference to the `django.db.connection` object. */
|
||||
API::Node connection() { result = db().getMember("connection") }
|
||||
|
||||
@@ -563,11 +557,8 @@ module PrivateDjango {
|
||||
/** Gets a reference to the `django.db.models` module. */
|
||||
API::Node models() { result = db().getMember("models") }
|
||||
|
||||
/** DEPRECATED: Alias for `Models` */
|
||||
deprecated module models = Models;
|
||||
|
||||
/** Provides models for the `django.db.models` module. */
|
||||
module Models {
|
||||
module models {
|
||||
/**
|
||||
* Provides models for the `django.db.models.Model` class and subclasses.
|
||||
*
|
||||
@@ -617,11 +608,8 @@ module PrivateDjango {
|
||||
/** Gets a reference to the `django.db.models.expressions` module. */
|
||||
API::Node expressions() { result = models().getMember("expressions") }
|
||||
|
||||
/** DEPRECATED: Alias for `Expressions` */
|
||||
deprecated module expressions = Expressions;
|
||||
|
||||
/** Provides models for the `django.db.models.expressions` module. */
|
||||
module Expressions {
|
||||
module expressions {
|
||||
/** Provides models for the `django.db.models.expressions.RawSql` class. */
|
||||
module RawSql {
|
||||
/**
|
||||
@@ -674,8 +662,8 @@ module PrivateDjango {
|
||||
DataFlow::Node sql;
|
||||
|
||||
ObjectsAnnotate() {
|
||||
this = DjangoImpl::DB::Models::querySetReturningMethod("annotate").getACall() and
|
||||
DjangoImpl::DB::Models::Expressions::RawSql::instance(sql) in [
|
||||
this = django::db::models::querySetReturningMethod("annotate").getACall() and
|
||||
django::db::models::expressions::RawSql::instance(sql) in [
|
||||
this.getArg(_), this.getArgByName(_)
|
||||
]
|
||||
}
|
||||
@@ -692,8 +680,8 @@ module PrivateDjango {
|
||||
DataFlow::Node sql;
|
||||
|
||||
ObjectsAlias() {
|
||||
this = DjangoImpl::DB::Models::querySetReturningMethod("alias").getACall() and
|
||||
DjangoImpl::DB::Models::Expressions::RawSql::instance(sql) in [
|
||||
this = django::db::models::querySetReturningMethod("alias").getACall() and
|
||||
django::db::models::expressions::RawSql::instance(sql) in [
|
||||
this.getArg(_), this.getArgByName(_)
|
||||
]
|
||||
}
|
||||
@@ -709,7 +697,7 @@ module PrivateDjango {
|
||||
* - https://docs.djangoproject.com/en/3.1/ref/models/querysets/#raw
|
||||
*/
|
||||
private class ObjectsRaw extends SqlExecution::Range, DataFlow::CallCfgNode {
|
||||
ObjectsRaw() { this = DjangoImpl::DB::Models::querySetReturningMethod("raw").getACall() }
|
||||
ObjectsRaw() { this = django::db::models::querySetReturningMethod("raw").getACall() }
|
||||
|
||||
override DataFlow::Node getSql() { result = this.getArg(0) }
|
||||
}
|
||||
@@ -720,7 +708,7 @@ module PrivateDjango {
|
||||
* See https://docs.djangoproject.com/en/3.1/ref/models/querysets/#extra
|
||||
*/
|
||||
private class ObjectsExtra extends SqlExecution::Range, DataFlow::CallCfgNode {
|
||||
ObjectsExtra() { this = DjangoImpl::DB::Models::querySetReturningMethod("extra").getACall() }
|
||||
ObjectsExtra() { this = django::db::models::querySetReturningMethod("extra").getACall() }
|
||||
|
||||
override DataFlow::Node getSql() {
|
||||
result in [
|
||||
@@ -735,11 +723,8 @@ module PrivateDjango {
|
||||
/** Gets a reference to the `django.urls` module. */
|
||||
API::Node urls() { result = django().getMember("urls") }
|
||||
|
||||
/** DEPRECATED: Alias for `Urls` */
|
||||
deprecated module urls = Urls;
|
||||
|
||||
/** Provides models for the `django.urls` module */
|
||||
module Urls {
|
||||
module urls {
|
||||
/**
|
||||
* Gets a reference to the `django.urls.path` function.
|
||||
* See https://docs.djangoproject.com/en/3.0/ref/urls/#path
|
||||
@@ -759,16 +744,10 @@ module PrivateDjango {
|
||||
/** Gets a reference to the `django.conf` module. */
|
||||
API::Node conf() { result = django().getMember("conf") }
|
||||
|
||||
/** DEPRECATED: Alias for `Conf` */
|
||||
deprecated module conf = Conf;
|
||||
|
||||
/** Provides models for the `django.conf` module */
|
||||
module Conf {
|
||||
/** DEPRECATED: Alias for `ConfUrls` */
|
||||
deprecated module conf_urls = ConfUrls;
|
||||
|
||||
module conf {
|
||||
/** Provides models for the `django.conf.urls` module */
|
||||
module ConfUrls {
|
||||
module conf_urls {
|
||||
// -------------------------------------------------------------------------
|
||||
// django.conf.urls
|
||||
// -------------------------------------------------------------------------
|
||||
@@ -791,22 +770,16 @@ module PrivateDjango {
|
||||
/** Gets a reference to the `django.http` module. */
|
||||
API::Node http() { result = django().getMember("http") }
|
||||
|
||||
/** DEPRECATED: Alias for `Http` */
|
||||
deprecated module http = Http;
|
||||
|
||||
/** Provides models for the `django.http` module */
|
||||
module Http {
|
||||
module http {
|
||||
// ---------------------------------------------------------------------------
|
||||
// django.http.request
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Gets a reference to the `django.http.request` module. */
|
||||
API::Node request() { result = http().getMember("request") }
|
||||
|
||||
/** DEPRECATED: Alias for `Request` */
|
||||
deprecated module request = Request;
|
||||
|
||||
/** Provides models for the `django.http.request` module. */
|
||||
module Request {
|
||||
module request {
|
||||
/**
|
||||
* Provides models for the `django.http.request.HttpRequest` class
|
||||
*
|
||||
@@ -887,7 +860,7 @@ module PrivateDjango {
|
||||
// special handling of the `build_absolute_uri` method, see
|
||||
// https://docs.djangoproject.com/en/3.0/ref/request-response/#django.http.HttpRequest.build_absolute_uri
|
||||
exists(DataFlow::AttrRead attr, DataFlow::CallCfgNode call, DataFlow::Node instance |
|
||||
instance = DjangoImpl::Http::Request::HttpRequest::instance() and
|
||||
instance = django::http::request::HttpRequest::instance() and
|
||||
attr.getObject() = instance
|
||||
|
|
||||
attr.getAttributeName() = "build_absolute_uri" and
|
||||
@@ -964,11 +937,8 @@ module PrivateDjango {
|
||||
/** Gets a reference to the `django.http.response` module. */
|
||||
API::Node response() { result = http().getMember("response") }
|
||||
|
||||
/** DEPRECATED: Alias for `Response` */
|
||||
deprecated module response = Response;
|
||||
|
||||
/** Provides models for the `django.http.response` module */
|
||||
module Response {
|
||||
module response {
|
||||
/**
|
||||
* Provides models for the `django.http.response.HttpResponse` class
|
||||
*
|
||||
@@ -1702,17 +1672,17 @@ module PrivateDjango {
|
||||
|
||||
/** Gets a reference to the `django.http.response.HttpResponse.write` function. */
|
||||
private DataFlow::TypeTrackingNode write(
|
||||
DjangoImpl::Http::Response::HttpResponse::InstanceSource instance, DataFlow::TypeTracker t
|
||||
django::http::response::HttpResponse::InstanceSource instance, DataFlow::TypeTracker t
|
||||
) {
|
||||
t.startInAttr("write") and
|
||||
instance = DjangoImpl::Http::Response::HttpResponse::instance() and
|
||||
instance = django::http::response::HttpResponse::instance() and
|
||||
result = instance
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = write(instance, t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a reference to the `django.http.response.HttpResponse.write` function. */
|
||||
DataFlow::Node write(DjangoImpl::Http::Response::HttpResponse::InstanceSource instance) {
|
||||
DataFlow::Node write(django::http::response::HttpResponse::InstanceSource instance) {
|
||||
write(instance, DataFlow::TypeTracker::end()).flowsTo(result)
|
||||
}
|
||||
|
||||
@@ -1722,7 +1692,7 @@ module PrivateDjango {
|
||||
* See https://docs.djangoproject.com/en/3.1/ref/request-response/#django.http.HttpResponse.write
|
||||
*/
|
||||
class HttpResponseWriteCall extends HTTP::Server::HttpResponse::Range, DataFlow::CallCfgNode {
|
||||
DjangoImpl::Http::Response::HttpResponse::InstanceSource instance;
|
||||
django::http::response::HttpResponse::InstanceSource instance;
|
||||
|
||||
HttpResponseWriteCall() { this.getFunction() = write(instance) }
|
||||
|
||||
@@ -1743,7 +1713,7 @@ module PrivateDjango {
|
||||
class DjangoResponseSetCookieCall extends HTTP::Server::CookieWrite::Range,
|
||||
DataFlow::MethodCallNode {
|
||||
DjangoResponseSetCookieCall() {
|
||||
this.calls(DjangoImpl::Http::Response::HttpResponse::instance(), "set_cookie")
|
||||
this.calls(django::http::response::HttpResponse::instance(), "set_cookie")
|
||||
}
|
||||
|
||||
override DataFlow::Node getHeaderArg() { none() }
|
||||
@@ -1763,7 +1733,7 @@ module PrivateDjango {
|
||||
class DjangoResponseDeleteCookieCall extends HTTP::Server::CookieWrite::Range,
|
||||
DataFlow::MethodCallNode {
|
||||
DjangoResponseDeleteCookieCall() {
|
||||
this.calls(DjangoImpl::Http::Response::HttpResponse::instance(), "delete_cookie")
|
||||
this.calls(django::http::response::HttpResponse::instance(), "delete_cookie")
|
||||
}
|
||||
|
||||
override DataFlow::Node getHeaderArg() { none() }
|
||||
@@ -1790,7 +1760,7 @@ module PrivateDjango {
|
||||
this.asCfgNode() = subscript
|
||||
|
|
||||
cookieLookup.getAttributeName() = "cookies" and
|
||||
cookieLookup.getObject() = DjangoImpl::Http::Response::HttpResponse::instance() and
|
||||
cookieLookup.getObject() = django::http::response::HttpResponse::instance() and
|
||||
exists(DataFlow::Node subscriptObj |
|
||||
subscriptObj.asCfgNode() = subscript.getObject()
|
||||
|
|
||||
@@ -1816,11 +1786,8 @@ module PrivateDjango {
|
||||
/** Gets a reference to the `django.shortcuts` module. */
|
||||
API::Node shortcuts() { result = django().getMember("shortcuts") }
|
||||
|
||||
/** DEPRECATED: Alias for `Shortcuts` */
|
||||
deprecated module shortcuts = Shortcuts;
|
||||
|
||||
/** Provides models for the `django.shortcuts` module */
|
||||
module Shortcuts {
|
||||
module shortcuts {
|
||||
/**
|
||||
* Gets a reference to the `django.shortcuts.redirect` function
|
||||
*
|
||||
@@ -2096,7 +2063,7 @@ module PrivateDjango {
|
||||
* See https://docs.djangoproject.com/en/3.0/ref/urls/#path
|
||||
*/
|
||||
private class DjangoUrlsPathCall extends DjangoRouteSetup, DataFlow::CallCfgNode {
|
||||
DjangoUrlsPathCall() { this = DjangoImpl::Urls::path().getACall() }
|
||||
DjangoUrlsPathCall() { this = django::urls::path().getACall() }
|
||||
|
||||
override DataFlow::Node getUrlPatternArg() {
|
||||
result in [this.getArg(0), this.getArgByName("route")]
|
||||
@@ -2179,7 +2146,7 @@ module PrivateDjango {
|
||||
*/
|
||||
private class DjangoUrlsRePathCall extends DjangoRegexRouteSetup, DataFlow::CallCfgNode {
|
||||
DjangoUrlsRePathCall() {
|
||||
this = DjangoImpl::Urls::re_path().getACall() and
|
||||
this = django::urls::re_path().getACall() and
|
||||
// `django.conf.urls.url` (which we support directly with
|
||||
// `DjangoConfUrlsUrlCall`), is implemented in Django 2+ as backward compatibility
|
||||
// using `django.urls.re_path`. See
|
||||
@@ -2209,7 +2176,7 @@ module PrivateDjango {
|
||||
* See https://docs.djangoproject.com/en/1.11/ref/urls/#django.conf.urls.url
|
||||
*/
|
||||
private class DjangoConfUrlsUrlCall extends DjangoRegexRouteSetup, DataFlow::CallCfgNode {
|
||||
DjangoConfUrlsUrlCall() { this = DjangoImpl::Conf::ConfUrls::url().getACall() }
|
||||
DjangoConfUrlsUrlCall() { this = django::conf::conf_urls::url().getACall() }
|
||||
|
||||
override DataFlow::Node getUrlPatternArg() {
|
||||
result in [this.getArg(0), this.getArgByName("regex")]
|
||||
@@ -2222,7 +2189,7 @@ module PrivateDjango {
|
||||
// HttpRequest taint modeling
|
||||
// ---------------------------------------------------------------------------
|
||||
/** A parameter that will receive the django `HttpRequest` instance when a request handler is invoked. */
|
||||
private class DjangoRequestHandlerRequestParam extends DjangoImpl::Http::Request::HttpRequest::InstanceSource,
|
||||
private class DjangoRequestHandlerRequestParam extends django::http::request::HttpRequest::InstanceSource,
|
||||
RemoteFlowSource::Range, DataFlow::ParameterNode {
|
||||
DjangoRequestHandlerRequestParam() {
|
||||
this.getParameter() = any(DjangoRouteSetup setup).getARequestHandler().getRequestParam()
|
||||
@@ -2239,7 +2206,7 @@ module PrivateDjango {
|
||||
*
|
||||
* See https://docs.djangoproject.com/en/3.1/topics/class-based-views/generic-display/#dynamic-filtering
|
||||
*/
|
||||
private class DjangoViewClassRequestAttributeRead extends DjangoImpl::Http::Request::HttpRequest::InstanceSource,
|
||||
private class DjangoViewClassRequestAttributeRead extends django::http::request::HttpRequest::InstanceSource,
|
||||
RemoteFlowSource::Range, DataFlow::Node {
|
||||
DjangoViewClassRequestAttributeRead() {
|
||||
exists(DataFlow::AttrRead read | this = read |
|
||||
@@ -2286,7 +2253,7 @@ module PrivateDjango {
|
||||
*/
|
||||
private class DjangoShortcutsRedirectCall extends HTTP::Server::HttpRedirectResponse::Range,
|
||||
DataFlow::CallCfgNode {
|
||||
DjangoShortcutsRedirectCall() { this = DjangoImpl::Shortcuts::redirect().getACall() }
|
||||
DjangoShortcutsRedirectCall() { this = django::shortcuts::redirect().getACall() }
|
||||
|
||||
/**
|
||||
* Gets the data-flow node that specifies the location of this HTTP redirect response.
|
||||
|
||||
@@ -24,7 +24,7 @@ private module FabricV1 {
|
||||
API::Node fabric() { result = API::moduleImport("fabric") }
|
||||
|
||||
/** Provides models for the `fabric` module. */
|
||||
module Fabric {
|
||||
module fabric {
|
||||
// -------------------------------------------------------------------------
|
||||
// fabric.api
|
||||
// -------------------------------------------------------------------------
|
||||
@@ -32,7 +32,7 @@ private module FabricV1 {
|
||||
API::Node api() { result = fabric().getMember("api") }
|
||||
|
||||
/** Provides models for the `fabric.api` module */
|
||||
module Api {
|
||||
module api {
|
||||
/**
|
||||
* A call to either
|
||||
* - `fabric.api.local`
|
||||
@@ -66,7 +66,7 @@ private module FabricV2 {
|
||||
API::Node fabric() { result = API::moduleImport("fabric") }
|
||||
|
||||
/** Provides models for the `fabric` module. */
|
||||
module Fabric {
|
||||
module fabric {
|
||||
// -------------------------------------------------------------------------
|
||||
// fabric.connection
|
||||
// -------------------------------------------------------------------------
|
||||
@@ -74,13 +74,13 @@ private module FabricV2 {
|
||||
API::Node connection() { result = fabric().getMember("connection") }
|
||||
|
||||
/** Provides models for the `fabric.connection` module */
|
||||
module Connection {
|
||||
module connection {
|
||||
/**
|
||||
* Provides models for the `fabric.connection.Connection` class
|
||||
*
|
||||
* See https://docs.fabfile.org/en/2.5/api/connection.html#fabric.connection.Connection.
|
||||
*/
|
||||
module ConnectionClass {
|
||||
module Connection {
|
||||
/** Gets a reference to the `fabric.connection.Connection` class. */
|
||||
API::Node classRef() {
|
||||
result = fabric().getMember("Connection")
|
||||
@@ -155,7 +155,7 @@ private module FabricV2 {
|
||||
private class FabricConnectionRunSudoLocalCall extends SystemCommandExecution::Range,
|
||||
DataFlow::CallCfgNode {
|
||||
FabricConnectionRunSudoLocalCall() {
|
||||
this.getFunction() = Fabric::Connection::ConnectionClass::instanceRunMethods()
|
||||
this.getFunction() = fabric::connection::Connection::instanceRunMethods()
|
||||
}
|
||||
|
||||
override DataFlow::Node getCommand() {
|
||||
@@ -170,16 +170,16 @@ private module FabricV2 {
|
||||
API::Node tasks() { result = fabric().getMember("tasks") }
|
||||
|
||||
/** Provides models for the `fabric.tasks` module */
|
||||
module Tasks {
|
||||
module tasks {
|
||||
/** Gets a reference to the `fabric.tasks.task` decorator. */
|
||||
API::Node task() { result in [tasks().getMember("task"), fabric().getMember("task")] }
|
||||
}
|
||||
|
||||
class FabricTaskFirstParamConnectionInstance extends Fabric::Connection::ConnectionClass::InstanceSource,
|
||||
class FabricTaskFirstParamConnectionInstance extends fabric::connection::Connection::InstanceSource,
|
||||
DataFlow::ParameterNode {
|
||||
FabricTaskFirstParamConnectionInstance() {
|
||||
exists(Function func |
|
||||
func.getADecorator() = Fabric::Tasks::task().getAUse().asExpr() and
|
||||
func.getADecorator() = fabric::tasks::task().getAUse().asExpr() and
|
||||
this.getParameter() = func.getArg(0)
|
||||
)
|
||||
}
|
||||
@@ -192,7 +192,7 @@ private module FabricV2 {
|
||||
API::Node group() { result = fabric().getMember("group") }
|
||||
|
||||
/** Provides models for the `fabric.group` module */
|
||||
module Group {
|
||||
module group {
|
||||
/**
|
||||
* Provides models for the `fabric.group.Group` class and its subclasses.
|
||||
*
|
||||
@@ -204,7 +204,7 @@ private module FabricV2 {
|
||||
* - https://docs.fabfile.org/en/2.5/api/group.html#fabric.group.SerialGroup
|
||||
* - https://docs.fabfile.org/en/2.5/api/group.html#fabric.group.ThreadingGroup
|
||||
*/
|
||||
module GroupClass {
|
||||
module Group {
|
||||
/**
|
||||
* A source of instances of a subclass of `fabric.group, extend this class to model new instances.Group`
|
||||
*
|
||||
@@ -236,9 +236,7 @@ private module FabricV2 {
|
||||
* See https://docs.fabfile.org/en/2.5/api/group.html#fabric.group.Group.run
|
||||
*/
|
||||
private class FabricGroupRunCall extends SystemCommandExecution::Range, DataFlow::CallCfgNode {
|
||||
FabricGroupRunCall() {
|
||||
this = Fabric::Group::GroupClass::subclassInstanceRunMethod().getACall()
|
||||
}
|
||||
FabricGroupRunCall() { this = fabric::group::Group::subclassInstanceRunMethod().getACall() }
|
||||
|
||||
override DataFlow::Node getCommand() {
|
||||
result = [this.getArg(0), this.getArgByName("command")]
|
||||
@@ -251,7 +249,7 @@ private module FabricV2 {
|
||||
* See https://docs.fabfile.org/en/2.5/api/group.html#fabric.group.SerialGroup.
|
||||
*/
|
||||
module SerialGroup {
|
||||
private class ClassInstantiation extends GroupClass::ModeledSubclass {
|
||||
private class ClassInstantiation extends Group::ModeledSubclass {
|
||||
ClassInstantiation() {
|
||||
this = group().getMember("SerialGroup")
|
||||
or
|
||||
@@ -266,7 +264,7 @@ private module FabricV2 {
|
||||
* See https://docs.fabfile.org/en/2.5/api/group.html#fabric.group.ThreadingGroup.
|
||||
*/
|
||||
module ThreadingGroup {
|
||||
private class ClassInstantiation extends GroupClass::ModeledSubclass {
|
||||
private class ClassInstantiation extends Group::ModeledSubclass {
|
||||
ClassInstantiation() {
|
||||
this = group().getMember("ThreadingGroup")
|
||||
or
|
||||
|
||||
@@ -20,11 +20,14 @@ private module Invoke {
|
||||
API::Node invoke() { result = API::moduleImport("invoke") }
|
||||
|
||||
/** Provides models for the `invoke` module. */
|
||||
module InvokeModule {
|
||||
module invoke {
|
||||
/** Gets a reference to the `invoke.context` module. */
|
||||
API::Node context() { result = invoke().getMember("context") }
|
||||
|
||||
/** Provides models for the `invoke.context` module */
|
||||
module Context {
|
||||
module context {
|
||||
/** Provides models for the `invoke.context.Context` class */
|
||||
module ContextClass {
|
||||
module Context {
|
||||
/** Gets a reference to the `invoke.context.Context` class. */
|
||||
API::Node classRef() {
|
||||
result = API::moduleImport("invoke").getMember("context").getMember("Context")
|
||||
@@ -36,7 +39,7 @@ private module Invoke {
|
||||
private DataFlow::TypeTrackingNode instance(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
(
|
||||
result = InvokeModule::Context::ContextClass::classRef().getACall()
|
||||
result = invoke::context::Context::classRef().getACall()
|
||||
or
|
||||
exists(Function func |
|
||||
func.getADecorator() = invoke().getMember("task").getAUse().asExpr() and
|
||||
@@ -53,7 +56,7 @@ private module Invoke {
|
||||
/** Gets a reference to the `run` or `sudo` methods on a `invoke.context.Context` instance. */
|
||||
private DataFlow::TypeTrackingNode instanceRunMethods(DataFlow::TypeTracker t) {
|
||||
t.startInAttr(["run", "sudo"]) and
|
||||
result = InvokeModule::Context::ContextClass::instance()
|
||||
result = invoke::context::Context::instance()
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = instanceRunMethods(t2).track(t2, t))
|
||||
}
|
||||
@@ -74,7 +77,7 @@ private module Invoke {
|
||||
private class InvokeRunCommandCall extends SystemCommandExecution::Range, DataFlow::CallCfgNode {
|
||||
InvokeRunCommandCall() {
|
||||
this = invoke().getMember(["run", "sudo"]).getACall() or
|
||||
this.getFunction() = InvokeModule::Context::ContextClass::instanceRunMethods()
|
||||
this.getFunction() = invoke::context::Context::instanceRunMethods()
|
||||
}
|
||||
|
||||
override DataFlow::Node getCommand() {
|
||||
|
||||
@@ -25,7 +25,7 @@ private module Mysql {
|
||||
// mysql
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Provides models for the `mysql` module. */
|
||||
module MysqlMod {
|
||||
module mysql {
|
||||
/**
|
||||
* The mysql.connector module
|
||||
* See https://dev.mysql.com/doc/connector-python/en/connector-python-example-connecting.html
|
||||
|
||||
@@ -220,7 +220,7 @@ private module RestFramework {
|
||||
*
|
||||
* Use the predicate `Request::instance()` to get references to instances of `rest_framework.request.Request`.
|
||||
*/
|
||||
abstract class InstanceSource extends PrivateDjango::DjangoImpl::Http::Request::HttpRequest::InstanceSource {
|
||||
abstract class InstanceSource extends PrivateDjango::django::http::request::HttpRequest::InstanceSource {
|
||||
}
|
||||
|
||||
/** A direct instantiation of `rest_framework.request.Request`. */
|
||||
@@ -295,8 +295,19 @@ private module RestFramework {
|
||||
result = API::moduleImport("rest_framework").getMember("response").getMember("Response")
|
||||
}
|
||||
|
||||
/**
|
||||
* A source of instances of `rest_framework.response.Response`, extend this class to model new instances.
|
||||
*
|
||||
* This can include instantiations of the class, return values from function
|
||||
* calls, or a special parameter that will be set when functions are called by an external
|
||||
* library.
|
||||
*
|
||||
* Use the predicate `Response::instance()` to get references to instances of `rest_framework.response.Response`.
|
||||
*/
|
||||
abstract class InstanceSource extends DataFlow::LocalSourceNode { }
|
||||
|
||||
/** A direct instantiation of `rest_framework.response.Response`. */
|
||||
private class ClassInstantiation extends PrivateDjango::DjangoImpl::Http::Response::HttpResponse::InstanceSource,
|
||||
private class ClassInstantiation extends PrivateDjango::django::http::response::HttpResponse::InstanceSource,
|
||||
DataFlow::CallCfgNode {
|
||||
ClassInstantiation() { this = classRef().getACall() }
|
||||
|
||||
|
||||
@@ -308,7 +308,7 @@ private module StdlibPrivate {
|
||||
API::Node os() { result = API::moduleImport("os") }
|
||||
|
||||
/** Provides models for the `os` module. */
|
||||
module OS {
|
||||
module os {
|
||||
/** Gets a reference to the `os.path` module. */
|
||||
API::Node path() {
|
||||
result = os().getMember("path")
|
||||
@@ -323,7 +323,7 @@ private module StdlibPrivate {
|
||||
}
|
||||
|
||||
/** Provides models for the `os.path` module */
|
||||
module OsPath {
|
||||
module path {
|
||||
/** Gets a reference to the `os.path.join` function. */
|
||||
API::Node join() { result = path().getMember("join") }
|
||||
}
|
||||
@@ -945,7 +945,7 @@ private module StdlibPrivate {
|
||||
// these raise errors if the file does not exist
|
||||
"getatime", "getmtime", "getctime", "getsize"
|
||||
] and
|
||||
this = OS::path().getMember(name).getACall()
|
||||
this = os::path().getMember(name).getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
@@ -961,7 +961,7 @@ private module StdlibPrivate {
|
||||
|
||||
/** A call to `os.path.samefile` will raise an exception if an `os.stat()` call on either pathname fails. */
|
||||
private class OsPathSamefileCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
|
||||
OsPathSamefileCall() { this = OS::path().getMember("samefile").getACall() }
|
||||
OsPathSamefileCall() { this = os::path().getMember("samefile").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result in [
|
||||
@@ -995,7 +995,7 @@ private module StdlibPrivate {
|
||||
|
||||
OsPathComputation() {
|
||||
methodName = pathComputation() and
|
||||
this = OS::path().getMember(methodName).getACall()
|
||||
this = os::path().getMember(methodName).getACall()
|
||||
}
|
||||
|
||||
DataFlow::Node getPathArg() {
|
||||
@@ -1022,7 +1022,7 @@ private module StdlibPrivate {
|
||||
* See https://docs.python.org/3/library/os.path.html#os.path.normpath
|
||||
*/
|
||||
private class OsPathNormpathCall extends Path::PathNormalization::Range, DataFlow::CallCfgNode {
|
||||
OsPathNormpathCall() { this = OS::path().getMember("normpath").getACall() }
|
||||
OsPathNormpathCall() { this = os::path().getMember("normpath").getACall() }
|
||||
|
||||
override DataFlow::Node getPathArg() { result in [this.getArg(0), this.getArgByName("path")] }
|
||||
}
|
||||
@@ -1032,7 +1032,7 @@ private module StdlibPrivate {
|
||||
* See https://docs.python.org/3/library/os.path.html#os.path.abspath
|
||||
*/
|
||||
private class OsPathAbspathCall extends Path::PathNormalization::Range, DataFlow::CallCfgNode {
|
||||
OsPathAbspathCall() { this = OS::path().getMember("abspath").getACall() }
|
||||
OsPathAbspathCall() { this = os::path().getMember("abspath").getACall() }
|
||||
|
||||
override DataFlow::Node getPathArg() { result in [this.getArg(0), this.getArgByName("path")] }
|
||||
}
|
||||
@@ -1042,7 +1042,7 @@ private module StdlibPrivate {
|
||||
* See https://docs.python.org/3/library/os.path.html#os.path.realpath
|
||||
*/
|
||||
private class OsPathRealpathCall extends Path::PathNormalization::Range, DataFlow::CallCfgNode {
|
||||
OsPathRealpathCall() { this = OS::path().getMember("realpath").getACall() }
|
||||
OsPathRealpathCall() { this = os::path().getMember("realpath").getACall() }
|
||||
|
||||
override DataFlow::Node getPathArg() { result in [this.getArg(0), this.getArgByName("path")] }
|
||||
}
|
||||
@@ -1143,7 +1143,7 @@ private module StdlibPrivate {
|
||||
override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
exists(CallNode call |
|
||||
nodeTo.asCfgNode() = call and
|
||||
call = OS::OsPath::join().getACall().asCfgNode() and
|
||||
call = os::path::join().getACall().asCfgNode() and
|
||||
call.getAnArg() = nodeFrom.asCfgNode()
|
||||
)
|
||||
// TODO: Handle pathlib (like we do for os.path.join)
|
||||
@@ -1662,7 +1662,7 @@ private module StdlibPrivate {
|
||||
API::Node cgi() { result = API::moduleImport("cgi") }
|
||||
|
||||
/** Provides models for the `cgi` module. */
|
||||
module Cgi {
|
||||
module cgi {
|
||||
/**
|
||||
* Provides models for the `cgi.FieldStorage` class
|
||||
*
|
||||
@@ -1862,7 +1862,7 @@ private module StdlibPrivate {
|
||||
API::Node http() { result = API::moduleImport("http") }
|
||||
|
||||
/** Provides models for the `http` module. */
|
||||
module Http {
|
||||
module http {
|
||||
// -------------------------------------------------------------------------
|
||||
// http.server
|
||||
// -------------------------------------------------------------------------
|
||||
@@ -1870,7 +1870,7 @@ private module StdlibPrivate {
|
||||
API::Node server() { result = http().getMember("server") }
|
||||
|
||||
/** Provides models for the `http.server` module */
|
||||
module Server {
|
||||
module server {
|
||||
/**
|
||||
* Provides models for the `http.server.BaseHTTPRequestHandler` class (Python 3 only).
|
||||
*
|
||||
@@ -1926,9 +1926,9 @@ private module StdlibPrivate {
|
||||
SimpleHttpServer::SimpleHttpRequestHandler::classRef(),
|
||||
CGIHTTPServer::CGIHTTPRequestHandler::classRef(),
|
||||
// Python 3
|
||||
Http::Server::BaseHttpRequestHandler::classRef(),
|
||||
Http::Server::SimpleHttpRequestHandler::classRef(),
|
||||
Http::Server::CGIHTTPRequestHandler::classRef()
|
||||
http::server::BaseHttpRequestHandler::classRef(),
|
||||
http::server::SimpleHttpRequestHandler::classRef(),
|
||||
http::server::CGIHTTPRequestHandler::classRef()
|
||||
].getASubclass*()
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ private module Tornado {
|
||||
API::Node tornado() { result = API::moduleImport("tornado") }
|
||||
|
||||
/** Provides models for the `tornado` module. */
|
||||
module TornadoModule {
|
||||
module tornado {
|
||||
// -------------------------------------------------------------------------
|
||||
// tornado.web
|
||||
// -------------------------------------------------------------------------
|
||||
@@ -80,7 +80,7 @@ private module Tornado {
|
||||
API::Node web() { result = tornado().getMember("web") }
|
||||
|
||||
/** Provides models for the `tornado.web` module */
|
||||
module Web {
|
||||
module web {
|
||||
/**
|
||||
* Provides models for the `tornado.web.RequestHandler` class and subclasses.
|
||||
*
|
||||
@@ -199,7 +199,7 @@ private module Tornado {
|
||||
override string getAsyncMethodName() { none() }
|
||||
}
|
||||
|
||||
private class RequestAttrAccess extends TornadoModule::HttpUtil::HttpServerRequest::InstanceSource {
|
||||
private class RequestAttrAccess extends tornado::httputil::HttpServerRequest::InstanceSource {
|
||||
RequestAttrAccess() {
|
||||
this.(DataFlow::AttrRead).getObject() = instance() and
|
||||
this.(DataFlow::AttrRead).getAttributeName() = "request"
|
||||
@@ -263,7 +263,7 @@ private module Tornado {
|
||||
API::Node httputil() { result = tornado().getMember("httputil") }
|
||||
|
||||
/** Provides models for the `tornado.httputil` module */
|
||||
module HttpUtil {
|
||||
module httputil {
|
||||
/**
|
||||
* Provides models for the `tornado.httputil.HttpServerRequest` class
|
||||
*
|
||||
@@ -359,14 +359,12 @@ private module Tornado {
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Gets a sequence that defines a number of route rules */
|
||||
SequenceNode routeSetupRuleList() {
|
||||
exists(CallNode call |
|
||||
call = any(TornadoModule::Web::Application::ClassInstantiation c).asCfgNode()
|
||||
|
|
||||
exists(CallNode call | call = any(tornado::web::Application::ClassInstantiation c).asCfgNode() |
|
||||
result in [call.getArg(0), call.getArgByName("handlers")]
|
||||
)
|
||||
or
|
||||
exists(CallNode call |
|
||||
call.getFunction() = TornadoModule::Web::Application::add_handlers().asCfgNode()
|
||||
call.getFunction() = tornado::web::Application::add_handlers().asCfgNode()
|
||||
|
|
||||
result in [call.getArg(1), call.getArgByName("host_handlers")]
|
||||
)
|
||||
@@ -408,7 +406,7 @@ private module Tornado {
|
||||
override DataFlow::Node getUrlPatternArg() { result.asCfgNode() = node.getElement(0) }
|
||||
|
||||
override Function getARequestHandler() {
|
||||
exists(TornadoModule::Web::RequestHandler::RequestHandlerClass cls |
|
||||
exists(tornado::web::RequestHandler::RequestHandlerClass cls |
|
||||
cls.getARef().asCfgNode() = node.getElement(1) and
|
||||
result = cls.getARequestHandler()
|
||||
)
|
||||
@@ -439,7 +437,7 @@ private module Tornado {
|
||||
/** A request handler defined in a tornado RequestHandler class, that has no known route. */
|
||||
private class TornadoRequestHandlerWithoutKnownRoute extends HTTP::Server::RequestHandler::Range {
|
||||
TornadoRequestHandlerWithoutKnownRoute() {
|
||||
exists(TornadoModule::Web::RequestHandler::RequestHandlerClass cls |
|
||||
exists(tornado::web::RequestHandler::RequestHandlerClass cls |
|
||||
cls.getARequestHandler() = this
|
||||
) and
|
||||
not exists(TornadoRouteSetup setup | setup.getARequestHandler() = this)
|
||||
@@ -467,7 +465,7 @@ private module Tornado {
|
||||
private class TornadoRequestHandlerRedirectCall extends HTTP::Server::HttpRedirectResponse::Range,
|
||||
DataFlow::CallCfgNode {
|
||||
TornadoRequestHandlerRedirectCall() {
|
||||
this.getFunction() = TornadoModule::Web::RequestHandler::redirectMethod()
|
||||
this.getFunction() = tornado::web::RequestHandler::redirectMethod()
|
||||
}
|
||||
|
||||
override DataFlow::Node getRedirectLocation() {
|
||||
@@ -489,7 +487,7 @@ private module Tornado {
|
||||
private class TornadoRequestHandlerWriteCall extends HTTP::Server::HttpResponse::Range,
|
||||
DataFlow::CallCfgNode {
|
||||
TornadoRequestHandlerWriteCall() {
|
||||
this.getFunction() = TornadoModule::Web::RequestHandler::writeMethod()
|
||||
this.getFunction() = tornado::web::RequestHandler::writeMethod()
|
||||
}
|
||||
|
||||
override DataFlow::Node getBody() { result in [this.getArg(0), this.getArgByName("chunk")] }
|
||||
@@ -507,7 +505,7 @@ private module Tornado {
|
||||
class TornadoRequestHandlerSetCookieCall extends HTTP::Server::CookieWrite::Range,
|
||||
DataFlow::MethodCallNode {
|
||||
TornadoRequestHandlerSetCookieCall() {
|
||||
this.calls(TornadoModule::Web::RequestHandler::instance(), "set_cookie")
|
||||
this.calls(tornado::web::RequestHandler::instance(), "set_cookie")
|
||||
}
|
||||
|
||||
override DataFlow::Node getHeaderArg() { none() }
|
||||
|
||||
@@ -185,6 +185,11 @@ predicate function_can_never_return(FunctionObject func) {
|
||||
func = ModuleObject::named("sys").attr("exit")
|
||||
}
|
||||
|
||||
private newtype TIterationDefinition =
|
||||
TIterationDefinition_(SsaSourceVariable var, ControlFlowNode def, ControlFlowNode sequence) {
|
||||
SsaSource::iteration_defined_variable(var, def, sequence)
|
||||
}
|
||||
|
||||
/** Hold if outer contains inner, both are contained within a test and inner is a use is a plain use or an attribute lookup */
|
||||
pragma[noinline]
|
||||
predicate contains_interesting_expression_within_test(ControlFlowNode outer, ControlFlowNode inner) {
|
||||
|
||||
@@ -18,9 +18,9 @@ predicate mapping_format(StrConst e) {
|
||||
*/
|
||||
|
||||
private string conversion_specifier_string(StrConst e, int number, int position) {
|
||||
exists(string s, string regex | s = e.getText() |
|
||||
regex = "%(\\([^)]*\\))?[#0\\- +]*(\\*|[0-9]*)(\\.(\\*|[0-9]*))?(h|H|l|L)?[badiouxXeEfFgGcrs%]" and
|
||||
result = s.regexpFind(regex, number, position)
|
||||
exists(string s, string REGEX | s = e.getText() |
|
||||
REGEX = "%(\\([^)]*\\))?[#0\\- +]*(\\*|[0-9]*)(\\.(\\*|[0-9]*))?(h|H|l|L)?[badiouxXeEfFgGcrs%]" and
|
||||
result = s.regexpFind(REGEX, number, position)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,16 @@ private predicate class_statement(Comment c) {
|
||||
|
||||
private predicate triple_quote(Comment c) { c.getText().regexpMatch("#.*(\"\"\"|''').*") }
|
||||
|
||||
private predicate triple_quoted_string_part(Comment start, Comment end) {
|
||||
triple_quote(start) and end = start
|
||||
or
|
||||
exists(Comment mid |
|
||||
triple_quoted_string_part(start, mid) and
|
||||
end = non_empty_following(mid) and
|
||||
not triple_quote(end)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate maybe_code(Comment c) {
|
||||
not non_code(c) and not filler(c) and not endline_comment(c) and not file_or_url(c)
|
||||
or
|
||||
|
||||
@@ -11,15 +11,15 @@ private import semmle.python.ApiGraphs
|
||||
import semmle.python.dataflow.new.RemoteFlowSources
|
||||
|
||||
private module ExperimentalPrivateDjango {
|
||||
private module DjangoMod {
|
||||
private module django {
|
||||
API::Node http() { result = API::moduleImport("django").getMember("http") }
|
||||
|
||||
module Http {
|
||||
module http {
|
||||
API::Node response() { result = http().getMember("response") }
|
||||
|
||||
API::Node request() { result = http().getMember("request") }
|
||||
|
||||
module Request {
|
||||
module request {
|
||||
module HttpRequest {
|
||||
class DjangoGETParameter extends DataFlow::Node, RemoteFlowSource::Range {
|
||||
DjangoGETParameter() { this = request().getMember("GET").getMember("get").getACall() }
|
||||
@@ -29,7 +29,7 @@ private module ExperimentalPrivateDjango {
|
||||
}
|
||||
}
|
||||
|
||||
module Response {
|
||||
module response {
|
||||
module HttpResponse {
|
||||
API::Node baseClassRef() {
|
||||
result = response().getMember("HttpResponse").getReturn()
|
||||
|
||||
@@ -12,7 +12,7 @@ private import experimental.semmle.python.Concepts
|
||||
private import semmle.python.ApiGraphs
|
||||
|
||||
private module Werkzeug {
|
||||
module Datastructures {
|
||||
module datastructures {
|
||||
module Headers {
|
||||
class WerkzeugHeaderAddCall extends DataFlow::CallCfgNode, HeaderDeclaration::Range {
|
||||
WerkzeugHeaderAddCall() {
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import python
|
||||
|
||||
class ImplicitConcat extends StrConst {
|
||||
ImplicitConcat() { exists(this.getAnImplicitlyConcatenatedPart()) }
|
||||
}
|
||||
|
||||
from StringPart s
|
||||
select s.getLocation().getStartLine(), s.getText(), s.getLocation().getStartColumn(),
|
||||
s.getLocation().getEndColumn()
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import python
|
||||
|
||||
class ImplicitConcat extends StrConst {
|
||||
ImplicitConcat() { exists(this.getAnImplicitlyConcatenatedPart()) }
|
||||
}
|
||||
|
||||
from StrConst s, StringPart part, int n
|
||||
where part = s.getImplicitlyConcatenatedPart(n)
|
||||
select s.getLocation().getStartLine(), s.getText(), n, part.getText()
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
import ql
|
||||
private import codeql_ql.ast.internal.Module
|
||||
|
||||
FileOrModule hasQueryRelation(ClasslessPredicate pred) {
|
||||
pred.hasAnnotation("query") and
|
||||
(
|
||||
result.asModule().getAMember() = pred
|
||||
or
|
||||
any(TopLevel top | top.getLocation().getFile() = result.asFile()).getAMember() = pred
|
||||
)
|
||||
}
|
||||
|
||||
FileOrModule importsQueryRelation(ClasslessPredicate pred) {
|
||||
result = hasQueryRelation(pred)
|
||||
or
|
||||
exists(Import i |
|
||||
not (i.hasAnnotation("private") and i.getLocation().getFile().getExtension() = "qll") and
|
||||
importsQueryRelation(pred) = i.getResolvedModule()
|
||||
|
|
||||
i = result.asModule().getAMember()
|
||||
or
|
||||
i = any(TopLevel top | top.getLocation().getFile() = result.asFile()).getAMember()
|
||||
)
|
||||
}
|
||||
|
||||
class Query extends File {
|
||||
Query() { this.getExtension() = "ql" }
|
||||
|
||||
predicate isPathProblem() {
|
||||
exists(QLDoc doc | doc.getLocation().getFile() = this |
|
||||
doc.getContents().matches("%@kind path-problem%")
|
||||
)
|
||||
}
|
||||
|
||||
predicate isProblem() {
|
||||
exists(QLDoc doc | doc.getLocation().getFile() = this |
|
||||
doc.getContents().matches("%@kind problem%")
|
||||
)
|
||||
}
|
||||
|
||||
predicate hasEdgesRelation(ClasslessPredicate pred) {
|
||||
importsQueryRelation(pred).asFile() = this and pred.getName() = "edges"
|
||||
}
|
||||
}
|
||||
@@ -29,24 +29,6 @@ string getName(AstNode node, string kind) {
|
||||
result = node.(Module).getName() and kind = "module"
|
||||
}
|
||||
|
||||
string prettyPluralKind(string kind) {
|
||||
kind = "class" and result = "classes"
|
||||
or
|
||||
kind = "classlessPredicate" and result = "predicates"
|
||||
or
|
||||
kind = "classPredicate" and result = "class predicates"
|
||||
or
|
||||
kind = "newtypeBranch" and result = "newtype branches"
|
||||
or
|
||||
kind = "newtype" and result = "newtypes"
|
||||
or
|
||||
kind = "variable" and result = "variables"
|
||||
or
|
||||
kind = "field" and result = "fields"
|
||||
or
|
||||
kind = "module" and result = "modules"
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `name` seems to contain an upper-cased acronym that could be pascal-cased.
|
||||
* `name` is the name of `node`, and `kind` describes what kind of definition `node` is.
|
||||
|
||||
@@ -1,254 +0,0 @@
|
||||
import ql
|
||||
import codeql_ql.bugs.PathProblemQueryQuery as PathProblemQuery
|
||||
import codeql_ql.ast.internal.Module
|
||||
|
||||
/** Gets something that can be imported by a ".qll" file. */
|
||||
private AstNode publicApi() {
|
||||
// base case - the toplevel is always "exported".
|
||||
result instanceof TopLevel
|
||||
or
|
||||
// recursive case. A public class/module/predicate/import that is a child of a public API.
|
||||
not result.hasAnnotation("private") and
|
||||
not result.getLocation().getFile().getExtension() = "ql" and // everything in ".ql" files is kinda private, as you can't import it. Query predicates/from-where-select is handled in `queryable`.
|
||||
result.getParent() = publicApi() and
|
||||
(
|
||||
result instanceof Class
|
||||
or
|
||||
result instanceof ClasslessPredicate
|
||||
or
|
||||
result instanceof Module
|
||||
or
|
||||
result instanceof Import
|
||||
)
|
||||
or
|
||||
result = publicApi().(Import).getResolvedModule().asModule()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets any AstNode that directly computes a result of a query.
|
||||
* I.e. a query predicate or the from-where-select.
|
||||
*/
|
||||
private AstNode queryPredicate() {
|
||||
// result = query relation that is "transitively" imported by a .ql file.
|
||||
PathProblemQuery::importsQueryRelation(result).asFile().getExtension() = "ql"
|
||||
or
|
||||
// the from-where-select
|
||||
result instanceof Select
|
||||
or
|
||||
// child of the above.
|
||||
result = queryPredicate().getAChild()
|
||||
}
|
||||
|
||||
AstNode hackyShouldBeTreatedAsAlive() {
|
||||
// Stages from the shared DataFlow impl are copy-pasted, so predicates that are dead in one stage are not dead in another.
|
||||
result = any(Module mod | mod.getName().matches("Stage%")).getAMember().(ClasslessPredicate) and
|
||||
result.getLocation().getFile().getBaseName().matches("DataFlowImpl%")
|
||||
or
|
||||
// Python stuff
|
||||
result.(Predicate).getName() = "quickEvalMe" // private predicate used for quick-eval
|
||||
or
|
||||
result.(Module).getName() = "FutureWork" // holder for later.
|
||||
or
|
||||
result = hackyShouldBeTreatedAsAlive().getAChild()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an AST node that is alive.
|
||||
* That is, an API node that may in some way be part of or affect a query result or a publicly available API.
|
||||
*/
|
||||
private AstNode alive() {
|
||||
//
|
||||
// The 4 base cases.
|
||||
//
|
||||
// 1) everything that can be imported.
|
||||
result = publicApi()
|
||||
or
|
||||
// 2) everything that can be an output when running a query
|
||||
result = queryPredicate()
|
||||
or
|
||||
// 3) A module with an import that imports another file, the import can activate a file.
|
||||
result.(Module).getAMember().(Import).getResolvedModule().getFile() !=
|
||||
result.getLocation().getFile()
|
||||
or
|
||||
// 4) Things that aren't really alive, but that this query treats as live.
|
||||
result = hackyShouldBeTreatedAsAlive()
|
||||
or
|
||||
result instanceof TopLevel // toplevel is always alive.
|
||||
or
|
||||
// recurisve cases
|
||||
result = aliveStep(alive())
|
||||
}
|
||||
|
||||
private AstNode aliveStep(AstNode prev) {
|
||||
//
|
||||
// The recursive cases.
|
||||
//
|
||||
result.getEnclosingPredicate() = prev
|
||||
or
|
||||
result = prev.(Call).getTarget()
|
||||
or
|
||||
prev.(ClassPredicate).overrides(result)
|
||||
or
|
||||
result.(ClassPredicate).overrides(prev)
|
||||
or
|
||||
result = prev.(PredicateExpr).getResolvedPredicate()
|
||||
or
|
||||
// if a sub-class is alive, then the super-class is alive.
|
||||
result = prev.(Class).getASuperType().getResolvedType().(ClassType).getDeclaration()
|
||||
or
|
||||
// if the super class is alive and abstract, then any sub-class is alive.
|
||||
exists(Class sup | sup = prev and sup.isAbstract() |
|
||||
sup = result.(Class).getASuperType().getResolvedType().(ClassType).getDeclaration()
|
||||
)
|
||||
or
|
||||
result = prev.(Class).getAChild() and
|
||||
not result.hasAnnotation("private")
|
||||
or
|
||||
result = prev.getAnAnnotation()
|
||||
or
|
||||
result = prev.getQLDoc()
|
||||
or
|
||||
// any imported module is alive. We don't have to handle the "import a file"-case, those are treated as public APIs.
|
||||
result = prev.(Import).getResolvedModule().asModule()
|
||||
or
|
||||
result = prev.(VarDecl).getType().getDeclaration()
|
||||
or
|
||||
result = prev.(FieldDecl).getVarDecl()
|
||||
or
|
||||
result = prev.(InlineCast).getType().getDeclaration()
|
||||
or
|
||||
// a class overrides some predicate, is the super-predicate is alive.
|
||||
exists(ClassPredicate pred, ClassPredicate sup |
|
||||
pred.hasAnnotation("override") and
|
||||
pred.overrides(sup) and
|
||||
result = pred.getParent() and
|
||||
sup.getParent() = prev
|
||||
)
|
||||
or
|
||||
// if a class is alive, so is it's super-class
|
||||
result =
|
||||
[prev.(Class).getASuperType(), prev.(Class).getAnInstanceofType()]
|
||||
.getResolvedType()
|
||||
.getDeclaration()
|
||||
or
|
||||
// if a class is alive and abstract, then any sub-class is alive.
|
||||
exists(Class clz, Class sup | result = clz |
|
||||
clz.getASuperType().getResolvedType().getDeclaration() = sup and
|
||||
sup.isAbstract() and
|
||||
sup = prev
|
||||
)
|
||||
or
|
||||
// a module containing something live, is also alive.
|
||||
result.(Module).getAMember() = prev
|
||||
or
|
||||
result = prev.(Module).getAlias()
|
||||
or
|
||||
result.(NewType).getABranch() = prev
|
||||
or
|
||||
result = prev.(TypeExpr).getAChild()
|
||||
or
|
||||
result = prev.(FieldAccess).getDeclaration()
|
||||
or
|
||||
result = prev.(VarDecl).getTypeExpr()
|
||||
or
|
||||
result.(Import).getParent() = prev
|
||||
or
|
||||
result = prev.(NewType).getABranch()
|
||||
or
|
||||
result = prev.(ModuleExpr).getAChild()
|
||||
or
|
||||
result = prev.(ModuleExpr).getResolvedModule().asModule()
|
||||
or
|
||||
result = prev.(InstanceOf).getType().getResolvedType().getDeclaration()
|
||||
or
|
||||
result = prev.(Annotation).getAChild()
|
||||
or
|
||||
result = prev.(Predicate).getReturnType().getDeclaration()
|
||||
}
|
||||
|
||||
private AstNode deprecated() {
|
||||
result.hasAnnotation("deprecated")
|
||||
or
|
||||
result = deprecated().getQLDoc()
|
||||
or
|
||||
result = deprecated().getAnAnnotation()
|
||||
or
|
||||
result = deprecated().getAChild()
|
||||
}
|
||||
|
||||
// our type-resolution skips these, so ignore.
|
||||
private AstNode classUnion() {
|
||||
exists(result.(Class).getUnionMember())
|
||||
or
|
||||
exists(result.(Class).getAliasType())
|
||||
or
|
||||
result = classUnion().(Class).getUnionMember()
|
||||
or
|
||||
result = classUnion().(Class).getAliasType()
|
||||
or
|
||||
result = classUnion().getAnAnnotation()
|
||||
or
|
||||
result = classUnion().getQLDoc()
|
||||
or
|
||||
result = classUnion().(TypeExpr).getAChild()
|
||||
or
|
||||
result = classUnion().(ModuleExpr).getAChild()
|
||||
}
|
||||
|
||||
private AstNode benign() {
|
||||
not result.getLocation().getFile().getExtension() = ["ql", "qll"] or // ignore dbscheme files
|
||||
result instanceof BlockComment or
|
||||
not exists(result.toString()) or // <- invalid code
|
||||
// cached-stages pattern
|
||||
result.(Module).getAMember().(ClasslessPredicate).getName() = "forceStage" or
|
||||
result.(ClasslessPredicate).getName() = "forceStage" or
|
||||
result.getLocation().getFile().getBaseName() = "Caching.qll" or
|
||||
// sometimes contains dead code - ignore
|
||||
result.getLocation().getFile().getRelativePath().matches("%/tutorials/%") or
|
||||
result = classUnion()
|
||||
}
|
||||
|
||||
private predicate isDeadInternal(AstNode node) {
|
||||
not node = alive() and
|
||||
not node = deprecated()
|
||||
}
|
||||
|
||||
predicate isDead(AstNode node) {
|
||||
isDeadInternal(node) and
|
||||
not isDeadInternal(node.getParent()) and
|
||||
not node = benign()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an AST node that affects a query.
|
||||
*/
|
||||
private AstNode queryable() {
|
||||
//
|
||||
// The base cases.
|
||||
//
|
||||
// everything that can be an output when running a query
|
||||
result = queryPredicate()
|
||||
or
|
||||
// A module with an import that imports another file, the import can activate a file.
|
||||
result.(Module).getAMember().(Import).getResolvedModule().getFile() !=
|
||||
result.getLocation().getFile()
|
||||
or
|
||||
result instanceof TopLevel // toplevel is always alive.
|
||||
or
|
||||
// recurisve cases
|
||||
result = aliveStep(queryable())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an AstNode that does not affect any query result.
|
||||
* Is interresting as an quick-eval target to investigate dead code.
|
||||
* (It is intentional that this predicate is a result of this predicate).
|
||||
*/
|
||||
AstNode unQueryable(string msg) {
|
||||
not result = queryable() and
|
||||
not result = deprecated() and
|
||||
not result = benign() and
|
||||
not result.getParent() = any(AstNode node | not node = queryable()) and
|
||||
msg = result.getLocation().getFile().getBaseName() and
|
||||
result.getLocation().getFile().getAbsolutePath().matches("%/javascript/%")
|
||||
}
|
||||
@@ -10,7 +10,48 @@
|
||||
*/
|
||||
|
||||
import ql
|
||||
import codeql_ql.bugs.PathProblemQueryQuery
|
||||
import codeql_ql.ast.internal.Module
|
||||
|
||||
FileOrModule hasEdgesRelation(ClasslessPredicate pred) {
|
||||
pred.getName() = "edges" and
|
||||
pred.hasAnnotation("query") and
|
||||
(
|
||||
result.asModule().getAMember() = pred
|
||||
or
|
||||
any(TopLevel top | top.getLocation().getFile() = result.asFile()).getAMember() = pred
|
||||
)
|
||||
}
|
||||
|
||||
FileOrModule importsEdges(ClasslessPredicate pred) {
|
||||
result = hasEdgesRelation(pred)
|
||||
or
|
||||
exists(Import i |
|
||||
not (i.hasAnnotation("private") and i.getLocation().getFile().getExtension() = "qll") and
|
||||
importsEdges(pred) = i.getResolvedModule()
|
||||
|
|
||||
i = result.asModule().getAMember()
|
||||
or
|
||||
i = any(TopLevel top | top.getLocation().getFile() = result.asFile()).getAMember()
|
||||
)
|
||||
}
|
||||
|
||||
class Query extends File {
|
||||
Query() { this.getExtension() = "ql" }
|
||||
|
||||
predicate isPathProblem() {
|
||||
exists(QLDoc doc | doc.getLocation().getFile() = this |
|
||||
doc.getContents().matches("%@kind path-problem%")
|
||||
)
|
||||
}
|
||||
|
||||
predicate isProblem() {
|
||||
exists(QLDoc doc | doc.getLocation().getFile() = this |
|
||||
doc.getContents().matches("%@kind problem%")
|
||||
)
|
||||
}
|
||||
|
||||
predicate hasEdgesRelation(ClasslessPredicate pred) { importsEdges(pred).asFile() = this }
|
||||
}
|
||||
|
||||
from Query query, string msg, AstNode pred
|
||||
where
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
/**
|
||||
* @name Dead code
|
||||
* @description Code that cannot be reached should be deleted.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @id ql/dead-code
|
||||
* @precision very-high
|
||||
*/
|
||||
|
||||
import ql
|
||||
import codeql_ql.style.DeadCodeQuery
|
||||
|
||||
from AstNode node
|
||||
where isDead(node)
|
||||
select node, "Code is dead"
|
||||
@@ -1,51 +0,0 @@
|
||||
/**
|
||||
* @name Missing security metadata
|
||||
* @description Security queries should have both a `@tag security` and a `@security-severity` tag.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @precision very-high
|
||||
* @id ql/missing-security-metadata
|
||||
* @tags correctness
|
||||
*/
|
||||
|
||||
import ql
|
||||
|
||||
predicate missingSecuritySeverity(QLDoc doc) {
|
||||
exists(string s | s = doc.getContents() |
|
||||
exists(string securityTag | securityTag = s.splitAt("@") |
|
||||
securityTag.matches("tags%security%")
|
||||
) and
|
||||
exists(string precisionTag | precisionTag = s.splitAt("@") |
|
||||
precisionTag.matches("precision %")
|
||||
) and
|
||||
not exists(string securitySeverity | securitySeverity = s.splitAt("@") |
|
||||
securitySeverity.matches("security-severity %")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
predicate missingSecurityTag(QLDoc doc) {
|
||||
exists(string s | s = doc.getContents() |
|
||||
exists(string securitySeverity | securitySeverity = s.splitAt("@") |
|
||||
securitySeverity.matches("security-severity %")
|
||||
) and
|
||||
exists(string precisionTag | precisionTag = s.splitAt("@") |
|
||||
precisionTag.matches("precision %")
|
||||
) and
|
||||
not exists(string securityTag | securityTag = s.splitAt("@") |
|
||||
securityTag.matches("tags%security%")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
from TopLevel t, string msg
|
||||
where
|
||||
t.getLocation().getFile().getBaseName().matches("%.ql") and
|
||||
not t.getLocation().getFile().getRelativePath().matches(["%/experimental/%", "%/examples/%"]) and
|
||||
(
|
||||
missingSecuritySeverity(t.getQLDoc()) and
|
||||
msg = "This query file is missing a `@security-severity` tag."
|
||||
or
|
||||
missingSecurityTag(t.getQLDoc()) and msg = "This query file is missing a `@tag security`."
|
||||
)
|
||||
select t, msg
|
||||
@@ -1,42 +0,0 @@
|
||||
/**
|
||||
* @name Correct casing on name declaraions
|
||||
* @description Variables/fields/predicates should be lower-case, classes/modules should be upper-case
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @id ql/name-casing
|
||||
* @tags correctness
|
||||
* @precision very-high
|
||||
*/
|
||||
|
||||
import ql
|
||||
import codeql_ql.style.AcronymsShouldBeCamelCaseQuery as AcronymsQuery
|
||||
|
||||
predicate shouldBeUpperCase(AstNode node, string name, string kind) {
|
||||
name = AcronymsQuery::getName(node, kind) and
|
||||
kind = ["class", "newtypeBranch", "newtype", "module"]
|
||||
}
|
||||
|
||||
predicate shouldBeLowerCase(AstNode node, string name, string kind) {
|
||||
name = AcronymsQuery::getName(node, kind) and
|
||||
not shouldBeUpperCase(node, name, kind)
|
||||
}
|
||||
|
||||
string prettyKind(string kind) {
|
||||
exists(string prettyLower | prettyLower = AcronymsQuery::prettyPluralKind(kind) |
|
||||
result = prettyLower.prefix(1).toUpperCase() + prettyLower.suffix(1)
|
||||
)
|
||||
}
|
||||
|
||||
from string name, AstNode node, string message, string kind
|
||||
where
|
||||
(
|
||||
shouldBeLowerCase(node, name, kind) and
|
||||
name.regexpMatch("[^a-z].*") and
|
||||
message = "a lowercase"
|
||||
or
|
||||
shouldBeUpperCase(node, name, kind) and
|
||||
name.regexpMatch("[^A-Z].*") and
|
||||
message = "an uppercase"
|
||||
) and
|
||||
not node.hasAnnotation("deprecated")
|
||||
select node, prettyKind(kind) + " should start with " + message + " letter."
|
||||
@@ -143,6 +143,10 @@ module DataFlow {
|
||||
override string toString() { result = p.toString() }
|
||||
}
|
||||
|
||||
newtype TReturnKind =
|
||||
TNormalReturnKind() or
|
||||
TParameterOutKind(int i) { any(Parameter p).getIndex() = i }
|
||||
|
||||
/** A data flow node that represents the output of a call at the call site. */
|
||||
abstract class OutNode extends Node {
|
||||
/** Gets the underlying call. */
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
| Foo.qll:2:11:2:38 | ClasslessPredicate dead1 | Code is dead |
|
||||
| Foo.qll:6:3:6:30 | ClasslessPredicate dead2 | Code is dead |
|
||||
@@ -1 +0,0 @@
|
||||
queries/style/DeadCode.ql
|
||||
@@ -1,9 +0,0 @@
|
||||
private module Mixed {
|
||||
private predicate dead1() { none() }
|
||||
|
||||
predicate alive1() { none() }
|
||||
|
||||
predicate dead2() { none() }
|
||||
}
|
||||
|
||||
predicate usesAlive() { Mixed::alive1() }
|
||||
@@ -1,2 +0,0 @@
|
||||
| testcases/BadNoSecurity.ql:1:1:15:9 | TopLevel | This query file is missing a `@tag security`. |
|
||||
| testcases/BadNoSeverity.ql:1:1:15:9 | TopLevel | This query file is missing a `@security-severity` tag. |
|
||||
@@ -1 +0,0 @@
|
||||
queries/style/MissingSecurityMetadata.ql
|
||||
@@ -1,15 +0,0 @@
|
||||
/**
|
||||
* @name Some query
|
||||
* @description Some description
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 10.0
|
||||
* @precision very-high
|
||||
* @id ql/some-query
|
||||
* @tags quality
|
||||
*/
|
||||
|
||||
import ql
|
||||
|
||||
from Class c
|
||||
select c
|
||||
@@ -1,15 +0,0 @@
|
||||
/**
|
||||
* @name Some query
|
||||
* @description Some description
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @precision very-high
|
||||
* @id ql/some-query
|
||||
* @tags quality
|
||||
* security
|
||||
*/
|
||||
|
||||
import ql
|
||||
|
||||
from Class c
|
||||
select c
|
||||
@@ -1,16 +0,0 @@
|
||||
/**
|
||||
* @name Some query
|
||||
* @description Some description
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 10.0
|
||||
* @precision very-high
|
||||
* @id ql/some-query
|
||||
* @tags quality
|
||||
* security
|
||||
*/
|
||||
|
||||
import ql
|
||||
|
||||
from Class c
|
||||
select c
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user