Compare commits

..

1 Commits

Author SHA1 Message Date
Esben Sparre Andreasen
3e4abb0a1d exclude intermediary data flow nodes from sinks 2022-03-16 08:03:05 +01:00
106 changed files with 934 additions and 1341 deletions

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* `hasImplicitCopyConstructor` and `hasImplicitCopyAssignmentOperator` now correctly handle implicitly-deleted operators in templates.

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,7 @@
private import ReachableBlock as Reachability
private module ReachabilityGraph = Reachability::Graph;
module Graph {
import Reachability::Graph

View File

@@ -1,5 +1,7 @@
private import ReachableBlock as Reachability
private module ReachabilityGraph = Reachability::Graph;
module Graph {
import Reachability::Graph

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,4 +0,0 @@
edges
nodes
subpaths
#select

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,7 @@
private import ReachableBlock as Reachability
private module ReachabilityGraph = Reachability::Graph;
module Graph {
import Reachability::Graph

View File

@@ -1,5 +1,7 @@
private import ReachableBlock as Reachability
private module ReachabilityGraph = Reachability::Graph;
module Graph {
import Reachability::Graph

View File

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

View File

@@ -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
1 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
2 android.app 16 103 7 9 18 85
3 android.content 24 27 100 16 8 27 31 69
4 android.database 59 30 59 30
5 android.net 60 45 15
6 android.os 122 41 81
7 android.util 6 16 6 16
8 android.webkit 3 2 3 2
9 android.widget 1 1 1 1
10 androidx.slice 2 5 88 2 5 27 61
11 cn.hutool.core.codec 1 1
12 com.esotericsoftware.kryo.io 1 1
13 com.esotericsoftware.kryo5.io 1 1
14 com.fasterxml.jackson.core 1 1
15 com.fasterxml.jackson.databind 6 6
16 com.google.common.base 85 62 23
17 com.google.common.cache 17 17
18 com.google.common.collect 553 2 551
19 com.google.common.flogger 29 29
20 com.google.common.io 6 73 6 72 1
21 com.opensymphony.xwork2.ognl 3 3
22 com.unboundid.ldap.sdk 17 17
23 com.zaxxer.hikari flexjson 2 1 2 1
24 flexjson groovy.lang 26 1 26 1
25 groovy.lang groovy.util 26 5 26 5
26 groovy.util jakarta.faces.context 5 2 7 5 2 7
27 jakarta.faces.context jakarta.json 2 7 123 2 7 100 23
28 jakarta.json jakarta.ws.rs.client 1 123 1 100 23
29 jakarta.ws.rs.client jakarta.ws.rs.container 1 9 1 9
30 jakarta.ws.rs.container jakarta.ws.rs.core 2 9 149 2 9 94 55
31 jakarta.ws.rs.core java.beans 2 149 1 2 94 1 55
32 java.beans java.io 37 1 31 15 22 1 31
33 java.io java.lang 37 8 31 58 15 8 22 31 46 12
34 java.lang java.net 8 10 3 58 7 8 10 3 46 7 12
35 java.net java.nio 10 15 3 7 6 13 10 2 3 7 6
36 java.nio java.sql 15 7 6 13 7 2 6
37 java.sql java.util 11 34 438 4 34 7 24 414
38 java.util javax.faces.context 34 2 7 438 34 2 7 24 414
39 javax.faces.context javax.json 2 7 123 2 7 100 23
40 javax.json javax.management.remote 2 123 2 100 23
41 javax.management.remote javax.naming 2 7 2 6 1
42 javax.naming javax.net.ssl 7 2 6 1 2
43 javax.net.ssl javax.script 2 1 1 2
44 javax.script javax.servlet 1 4 21 2 3 1 1 21 2
45 javax.servlet javax.validation 4 1 21 1 2 1 3 1 21 1 2
46 javax.validation javax.ws.rs.client 1 1 1 1 1
47 javax.ws.rs.client javax.ws.rs.container 1 9 1 9
48 javax.ws.rs.container javax.ws.rs.core 3 9 149 1 2 9 94 55
49 javax.ws.rs.core javax.xml.transform 3 1 149 6 1 2 1 94 6 55
50 javax.xml.transform javax.xml.xpath 1 3 6 3 1 6
51 javax.xml.xpath jodd.json 3 10 3 10
52 jodd.json net.sf.saxon.s9api 5 10 5 10
53 net.sf.saxon.s9api ognl 5 6 6 5
54 ognl org.apache.commons.codec 6 6 6 6
55 org.apache.commons.codec org.apache.commons.collections 6 800 6 17 783
56 org.apache.commons.collections org.apache.commons.collections4 800 17 783
57 org.apache.commons.collections4 org.apache.commons.io 93 2 800 565 78 15 2 17 551 783 14
58 org.apache.commons.io org.apache.commons.jexl2 93 15 2 565 78 15 15 2 551 14
59 org.apache.commons.jexl2 org.apache.commons.jexl3 15 15
60 org.apache.commons.jexl3 org.apache.commons.lang3 15 424 15 293 131
61 org.apache.commons.lang3 org.apache.commons.logging 6 424 6 293 131
62 org.apache.commons.logging org.apache.commons.ognl 6 6 6
63 org.apache.commons.ognl org.apache.commons.text 6 272 6 220 52
64 org.apache.commons.text org.apache.directory.ldap.client.api 1 272 1 220 52
65 org.apache.directory.ldap.client.api org.apache.hc.core5.function 1 1 1 1
66 org.apache.hc.core5.function org.apache.hc.core5.http 1 2 1 39 1 2 1 39
67 org.apache.hc.core5.http org.apache.hc.core5.net 1 2 39 2 1 2 39 2
68 org.apache.hc.core5.net org.apache.hc.core5.util 2 24 2 18 6
69 org.apache.hc.core5.util org.apache.http 27 3 24 70 25 2 3 18 62 6 8
70 org.apache.http org.apache.ibatis.jdbc 27 6 3 70 25 6 2 3 62 8
71 org.apache.ibatis.jdbc org.apache.log4j 6 11 11 6
72 org.apache.log4j org.apache.logging.log4j 11 359 8 11 359 4 4
73 org.apache.logging.log4j org.apache.shiro.codec 359 8 1 359 4 1 4
74 org.apache.shiro.codec org.apache.shiro.jndi 1 1 1 1
75 org.apache.shiro.jndi org.codehaus.groovy.control 1 1 1
76 org.codehaus.groovy.control org.dom4j 1 20 1 20
77 org.dom4j org.hibernate 20 7 7 20
78 org.hibernate org.jboss.logging 7 324 324 7
79 org.jboss.logging org.jooq 324 1 324 1
80 org.jdbi.v3.core org.json 6 236 6 198 38
81 org.jooq org.mvel2 1 16 16 1
82 org.json org.scijava.log 13 236 13 198 38
83 org.mvel2 org.slf4j 16 55 6 55 16 2 4
84 org.scijava.log org.springframework.beans 13 26 13 26
85 org.slf4j org.springframework.cache 55 6 13 55 2 4 13
86 org.springframework.beans org.springframework.context 26 3 3 26
87 org.springframework.boot.jdbc org.springframework.http 1 14 70 1 14 60 10
88 org.springframework.cache org.springframework.jdbc.core 10 13 10 13
89 org.springframework.context org.springframework.jdbc.object 9 3 9 3
90 org.springframework.http org.springframework.jndi 14 1 70 1 14 60 10
91 org.springframework.jdbc.core org.springframework.ldap 10 47 33 14 10
92 org.springframework.jdbc.datasource org.springframework.security.web.savedrequest 4 6 4 6
93 org.springframework.jdbc.object org.springframework.ui 9 32 9 32
94 org.springframework.jndi org.springframework.util 1 139 1 87 52
95 org.springframework.ldap org.springframework.validation 47 13 33 14 13
96 org.springframework.security.web.savedrequest org.springframework.web.client 13 6 3 13 6 3
97 org.springframework.ui org.springframework.web.context.request 8 32 8 32
98 org.springframework.util org.springframework.web.multipart 12 139 13 12 87 13 52
99 org.springframework.validation org.springframework.web.reactive.function.client 2 13 2 13
100 org.springframework.web.client org.springframework.web.util 13 3 163 13 3 138 25
101 org.springframework.web.context.request org.xml.sax 8 1 8 1
102 org.springframework.web.multipart org.xmlpull.v1 12 3 13 12 3 13
103 org.springframework.web.reactive.function.client play.mvc 2 4 2 4
104 org.springframework.web.util ratpack.core.form 163 3 138 3 25
105 org.xml.sax ratpack.core.handling 6 1 4 6 1 4
106 org.xmlpull.v1 ratpack.core.http 3 10 10 3 10 10
107 play.mvc ratpack.exec 4 48 4 48
108 ratpack.core.form ratpack.form 3 3
109 ratpack.core.handling ratpack.func 6 4 35 6 4 35
110 ratpack.core.http ratpack.handling 10 6 10 4 10 6 10 4
111 ratpack.exec ratpack.http 10 48 10 10 10 48
112 ratpack.form ratpack.util 3 35 3 35
ratpack.func 35 35
ratpack.handling 6 4 6 4
ratpack.http 10 10 10 10
ratpack.util 35 35

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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()
)
}
}
/**

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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/%")
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1 +0,0 @@
queries/style/DeadCode.ql

View File

@@ -1,9 +0,0 @@
private module Mixed {
private predicate dead1() { none() }
predicate alive1() { none() }
predicate dead2() { none() }
}
predicate usesAlive() { Mixed::alive1() }

View File

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

View File

@@ -1 +0,0 @@
queries/style/MissingSecurityMetadata.ql

View File

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

View File

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

View File

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