mirror of
https://github.com/github/codeql.git
synced 2026-05-30 19:11:23 +02:00
Compare commits
151 Commits
redsun82/u
...
rdmarsh2/i
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
06be3aec3e | ||
|
|
cb93684287 | ||
|
|
fd1ade8e50 | ||
|
|
536f9f9cca | ||
|
|
f4d3cdeca9 | ||
|
|
d0c603f2eb | ||
|
|
fc66aacf92 | ||
|
|
1ae116c4cc | ||
|
|
d7474f91dc | ||
|
|
128d102bbc | ||
|
|
20f555c715 | ||
|
|
35788162ec | ||
|
|
d114388470 | ||
|
|
12d181143f | ||
|
|
3c1456bd02 | ||
|
|
8fcfc6f4f1 | ||
|
|
5d80f0818c | ||
|
|
b696936d10 | ||
|
|
74242638e2 | ||
|
|
8ca5484dcf | ||
|
|
5b6d3afd89 | ||
|
|
9fe5462b1b | ||
|
|
09d4fe21e8 | ||
|
|
6b049cb37a | ||
|
|
3d01763092 | ||
|
|
90f84bb516 | ||
|
|
81ce6c7779 | ||
|
|
c9c281cb9a | ||
|
|
c1c2bcf419 | ||
|
|
0094c25791 | ||
|
|
a446c5452d | ||
|
|
799d92b218 | ||
|
|
f32b8ad5b1 | ||
|
|
96fba2dac3 | ||
|
|
4c102ab99c | ||
|
|
bc08d67f19 | ||
|
|
2c4246f29a | ||
|
|
389e8c4fe8 | ||
|
|
0650c016f6 | ||
|
|
d54c444606 | ||
|
|
311498841e | ||
|
|
9d80a43d6a | ||
|
|
6110b7aca5 | ||
|
|
738e3857e7 | ||
|
|
cb82bd62e7 | ||
|
|
e50f56cc56 | ||
|
|
e5f2b90aec | ||
|
|
95b8a22529 | ||
|
|
a95fc79874 | ||
|
|
d98723c35a | ||
|
|
cff7f63193 | ||
|
|
909f40b6ea | ||
|
|
84ddfe9c3f | ||
|
|
b1712d33fe | ||
|
|
b35637e1c5 | ||
|
|
89ee2b9ace | ||
|
|
c3c3faa4b5 | ||
|
|
3694ed5ed6 | ||
|
|
cab76507e7 | ||
|
|
ff67118097 | ||
|
|
125aab8107 | ||
|
|
a9d34458de | ||
|
|
0ebb06e185 | ||
|
|
2c28fae7e3 | ||
|
|
b0b2d6e05f | ||
|
|
fcbd211783 | ||
|
|
934a455908 | ||
|
|
65835cdb92 | ||
|
|
c88f9bf818 | ||
|
|
621761b289 | ||
|
|
3af72fa28e | ||
|
|
59e59125d6 | ||
|
|
36d34f199b | ||
|
|
3d1da8a45d | ||
|
|
927522c563 | ||
|
|
b47c8e8c4c | ||
|
|
0a7e525c16 | ||
|
|
14706b42fa | ||
|
|
0ebf529dc4 | ||
|
|
8756c031e0 | ||
|
|
1afe845ed3 | ||
|
|
e3d93c3581 | ||
|
|
e84bdf5bed | ||
|
|
feb31612f5 | ||
|
|
95ef7fb3f1 | ||
|
|
71cd973b42 | ||
|
|
361b15b2c7 | ||
|
|
bfe5db20a3 | ||
|
|
ba4d326768 | ||
|
|
8ade7247a1 | ||
|
|
bfbbb5277d | ||
|
|
b0efff0110 | ||
|
|
b16444dd22 | ||
|
|
5e274c9664 | ||
|
|
a5e919b6cb | ||
|
|
19e6a9a1d3 | ||
|
|
40aed29858 | ||
|
|
b919547e31 | ||
|
|
bc44b9e4fb | ||
|
|
c4a7353583 | ||
|
|
f61565cab1 | ||
|
|
9c25c150a3 | ||
|
|
a4d7570788 | ||
|
|
9881fdfe27 | ||
|
|
4bf03e7962 | ||
|
|
f3b14e13b2 | ||
|
|
239a763ef9 | ||
|
|
149753c052 | ||
|
|
85542638d7 | ||
|
|
94f11029ee | ||
|
|
2ae4b646a0 | ||
|
|
2ca8103a7e | ||
|
|
5dbd11a584 | ||
|
|
fa1a6da60d | ||
|
|
7c72ece4a0 | ||
|
|
9828ad0fc3 | ||
|
|
2e76e12316 | ||
|
|
1f861fda25 | ||
|
|
0fdeeba46f | ||
|
|
76f8d460e7 | ||
|
|
00436828a9 | ||
|
|
b707c8162e | ||
|
|
c7378a1e5b | ||
|
|
603a97faf9 | ||
|
|
9dc1ea1216 | ||
|
|
a47778c22e | ||
|
|
656d8d2451 | ||
|
|
c71278ceb7 | ||
|
|
60c723e7cc | ||
|
|
fc3c776bdc | ||
|
|
7f675d8c3b | ||
|
|
96f06f8eca | ||
|
|
83d5cde01d | ||
|
|
a168af349e | ||
|
|
a5a0861be0 | ||
|
|
d1de453c7a | ||
|
|
027f08a0df | ||
|
|
e180b7e2ba | ||
|
|
8c0c335daf | ||
|
|
8363171f1f | ||
|
|
7332cec9a5 | ||
|
|
29a20550f6 | ||
|
|
706fdce527 | ||
|
|
2adc4c0feb | ||
|
|
7b8606d411 | ||
|
|
17cfd489ea | ||
|
|
8b08e6042c | ||
|
|
37f1770623 | ||
|
|
941df4f274 | ||
|
|
cb2b2bc334 | ||
|
|
92198e1af0 |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -11,12 +11,6 @@
|
||||
*/ql/test/**/*.actual
|
||||
*/ql/test/**/go.sum
|
||||
|
||||
# upgrade/downgrade script tests projects and artifacts
|
||||
**/upgrades/**/test/*.testproj
|
||||
**/upgrades/**/test/*.actual
|
||||
**/downgrades/**/test/*.testproj
|
||||
**/downgrades/**/test/*.actual
|
||||
|
||||
# Visual studio temporaries, except a file used by QL4VS
|
||||
.vs/*
|
||||
!.vs/VSWorkspaceSettings.json
|
||||
|
||||
@@ -361,3 +361,52 @@ module MergePathGraph<
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a `PathGraph` from three `PathGraph`s by disjoint union.
|
||||
*/
|
||||
module MergePathGraph3<
|
||||
PathNodeSig PathNode1, PathNodeSig PathNode2, PathNodeSig PathNode3,
|
||||
PathGraphSig<PathNode1> Graph1, PathGraphSig<PathNode2> Graph2, PathGraphSig<PathNode3> Graph3>
|
||||
{
|
||||
private module MergedInner = MergePathGraph<PathNode1, PathNode2, Graph1, Graph2>;
|
||||
|
||||
private module Merged =
|
||||
MergePathGraph<MergedInner::PathNode, PathNode3, MergedInner::PathGraph, Graph3>;
|
||||
|
||||
/** A node in a graph of path explanations that is formed by disjoint union of the three given graphs. */
|
||||
class PathNode instanceof Merged::PathNode {
|
||||
/** Gets this as a projection on the first given `PathGraph`. */
|
||||
PathNode1 asPathNode1() { result = super.asPathNode1().asPathNode1() }
|
||||
|
||||
/** Gets this as a projection on the second given `PathGraph`. */
|
||||
PathNode2 asPathNode2() { result = super.asPathNode1().asPathNode2() }
|
||||
|
||||
/** Gets this as a projection on the third given `PathGraph`. */
|
||||
PathNode3 asPathNode3() { result = super.asPathNode2() }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets the underlying `Node`. */
|
||||
Node getNode() { result = super.getNode() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the query predicates needed to include a graph in a path-problem query.
|
||||
*/
|
||||
module PathGraph = Merged::PathGraph;
|
||||
}
|
||||
|
||||
@@ -361,3 +361,52 @@ module MergePathGraph<
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a `PathGraph` from three `PathGraph`s by disjoint union.
|
||||
*/
|
||||
module MergePathGraph3<
|
||||
PathNodeSig PathNode1, PathNodeSig PathNode2, PathNodeSig PathNode3,
|
||||
PathGraphSig<PathNode1> Graph1, PathGraphSig<PathNode2> Graph2, PathGraphSig<PathNode3> Graph3>
|
||||
{
|
||||
private module MergedInner = MergePathGraph<PathNode1, PathNode2, Graph1, Graph2>;
|
||||
|
||||
private module Merged =
|
||||
MergePathGraph<MergedInner::PathNode, PathNode3, MergedInner::PathGraph, Graph3>;
|
||||
|
||||
/** A node in a graph of path explanations that is formed by disjoint union of the three given graphs. */
|
||||
class PathNode instanceof Merged::PathNode {
|
||||
/** Gets this as a projection on the first given `PathGraph`. */
|
||||
PathNode1 asPathNode1() { result = super.asPathNode1().asPathNode1() }
|
||||
|
||||
/** Gets this as a projection on the second given `PathGraph`. */
|
||||
PathNode2 asPathNode2() { result = super.asPathNode1().asPathNode2() }
|
||||
|
||||
/** Gets this as a projection on the third given `PathGraph`. */
|
||||
PathNode3 asPathNode3() { result = super.asPathNode2() }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets the underlying `Node`. */
|
||||
Node getNode() { result = super.getNode() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the query predicates needed to include a graph in a path-problem query.
|
||||
*/
|
||||
module PathGraph = Merged::PathGraph;
|
||||
}
|
||||
|
||||
@@ -34,9 +34,13 @@ private module Cached {
|
||||
|
||||
cached
|
||||
predicate hasUnreachedInstructionCached(IRFunction irFunc) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
exists(OldIR::Instruction oldInstruction |
|
||||
irFunc = oldInstruction.getEnclosingIRFunction() and
|
||||
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _)
|
||||
(
|
||||
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _)
|
||||
or
|
||||
oldInstruction.getOpcode() instanceof Opcode::Unreached
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -366,21 +370,19 @@ private module Cached {
|
||||
then
|
||||
result = getChi(getOldInstruction(instruction)) and
|
||||
kind instanceof GotoEdge
|
||||
else (
|
||||
else
|
||||
exists(OldInstruction oldInstruction |
|
||||
oldInstruction = getOldInstruction(instruction) and
|
||||
(
|
||||
oldInstruction = getOldInstruction(instruction)
|
||||
or
|
||||
instruction = getChi(oldInstruction)
|
||||
) and
|
||||
(
|
||||
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind)
|
||||
then result = unreachedInstruction(instruction.getEnclosingIRFunction())
|
||||
else result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(OldInstruction oldInstruction |
|
||||
instruction = getChi(oldInstruction) and
|
||||
result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
|
||||
@@ -19,6 +19,9 @@ newtype TInstruction =
|
||||
) {
|
||||
IRConstruction::Raw::hasInstruction(tag1, tag2)
|
||||
} or
|
||||
TRawUnreachedInstruction(IRFunctionBase irFunc) {
|
||||
IRConstruction::hasUnreachedInstruction(irFunc)
|
||||
} or
|
||||
TUnaliasedSsaPhiInstruction(
|
||||
TRawInstruction blockStartInstr, UnaliasedSsa::Ssa::MemoryLocation memoryLocation
|
||||
) {
|
||||
|
||||
@@ -171,9 +171,9 @@ module Raw {
|
||||
}
|
||||
}
|
||||
|
||||
class TStageInstruction = TRawInstruction;
|
||||
class TStageInstruction = TRawInstruction or TRawUnreachedInstruction;
|
||||
|
||||
predicate hasInstruction(TRawInstruction instr) { any() }
|
||||
predicate hasInstruction(TStageInstruction instr) { any() }
|
||||
|
||||
predicate hasModeledMemoryResult(Instruction instruction) { none() }
|
||||
|
||||
@@ -361,6 +361,11 @@ private predicate isStrictlyForwardGoto(GotoStmt goto) {
|
||||
|
||||
Locatable getInstructionAst(TStageInstruction instr) {
|
||||
result = getInstructionTranslatedElement(instr).getAst()
|
||||
or
|
||||
exists(IRFunction irFunc |
|
||||
instr = TRawUnreachedInstruction(irFunc) and
|
||||
result = irFunc.getFunction()
|
||||
)
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for getInstructionAst */
|
||||
@@ -370,14 +375,22 @@ deprecated Locatable getInstructionAST(TStageInstruction instr) {
|
||||
|
||||
CppType getInstructionResultType(TStageInstruction instr) {
|
||||
getInstructionTranslatedElement(instr).hasInstruction(_, getInstructionTag(instr), result)
|
||||
or
|
||||
instr instanceof TRawUnreachedInstruction and
|
||||
result = getVoidType()
|
||||
}
|
||||
|
||||
predicate getInstructionOpcode(Opcode opcode, TStageInstruction instr) {
|
||||
getInstructionTranslatedElement(instr).hasInstruction(opcode, getInstructionTag(instr), _)
|
||||
or
|
||||
instr instanceof TRawUnreachedInstruction and
|
||||
opcode instanceof Opcode::Unreached
|
||||
}
|
||||
|
||||
IRFunctionBase getInstructionEnclosingIRFunction(TStageInstruction instr) {
|
||||
result.getFunction() = getInstructionTranslatedElement(instr).getFunction()
|
||||
or
|
||||
instr = TRawUnreachedInstruction(result)
|
||||
}
|
||||
|
||||
Instruction getPrimaryInstructionForSideEffect(SideEffectInstruction instruction) {
|
||||
@@ -386,6 +399,16 @@ Instruction getPrimaryInstructionForSideEffect(SideEffectInstruction instruction
|
||||
.getPrimaryInstructionForSideEffect(getInstructionTag(instruction))
|
||||
}
|
||||
|
||||
predicate hasUnreachedInstruction(IRFunction func) {
|
||||
exists(Call c |
|
||||
c.getEnclosingFunction() = func.getFunction() and
|
||||
any(Options opt).exits(c.getTarget())
|
||||
) and
|
||||
not exists(TranslatedUnreachableReturnStmt return |
|
||||
return.getEnclosingFunction().getFunction() = func.getFunction()
|
||||
)
|
||||
}
|
||||
|
||||
import CachedForDebugging
|
||||
|
||||
cached
|
||||
|
||||
@@ -34,6 +34,7 @@ newtype TInstructionTag =
|
||||
CallTargetTag() or
|
||||
CallTag() or
|
||||
CallSideEffectTag() or
|
||||
CallNoReturnTag() or
|
||||
AllocationSizeTag() or
|
||||
AllocationElementSizeTag() or
|
||||
AllocationExtentConvertTag() or
|
||||
|
||||
@@ -8,6 +8,7 @@ private import SideEffects
|
||||
private import TranslatedElement
|
||||
private import TranslatedExpr
|
||||
private import TranslatedFunction
|
||||
private import DefaultOptions as DefaultOptions
|
||||
|
||||
/**
|
||||
* Gets the `CallInstruction` from the `TranslatedCallExpr` for the specified expression.
|
||||
@@ -66,7 +67,13 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
)
|
||||
or
|
||||
child = getSideEffects() and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
if this.isNoReturn()
|
||||
then
|
||||
result =
|
||||
any(UnreachedInstruction instr |
|
||||
this.getEnclosingFunction().getFunction() = instr.getEnclosingFunction()
|
||||
)
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -161,6 +168,8 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
*/
|
||||
abstract predicate hasArguments();
|
||||
|
||||
predicate isNoReturn() { none() }
|
||||
|
||||
final TranslatedSideEffects getSideEffects() { result.getExpr() = expr }
|
||||
}
|
||||
|
||||
@@ -266,6 +275,8 @@ abstract class TranslatedCallExpr extends TranslatedNonConstantExpr, TranslatedC
|
||||
}
|
||||
|
||||
final override int getNumberOfArguments() { result = expr.getNumberOfArguments() }
|
||||
|
||||
final override predicate isNoReturn() { any(Options opt).exits(expr.getTarget()) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,6 +7,9 @@ predicate isInfeasibleInstructionSuccessor(Instruction instr, EdgeKind kind) {
|
||||
conditionValue = getConstantValue(instr.(ConditionalBranchInstruction).getCondition()) and
|
||||
if conditionValue = 0 then kind instanceof TrueEdge else kind instanceof FalseEdge
|
||||
)
|
||||
or
|
||||
instr.getSuccessor(kind) instanceof UnreachedInstruction and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
@@ -41,7 +44,9 @@ class ReachableBlock extends IRBlockBase {
|
||||
* An instruction that is contained in a reachable block.
|
||||
*/
|
||||
class ReachableInstruction extends Instruction {
|
||||
ReachableInstruction() { this.getBlock() instanceof ReachableBlock }
|
||||
ReachableInstruction() {
|
||||
this.getBlock() instanceof ReachableBlock and not this instanceof UnreachedInstruction
|
||||
}
|
||||
}
|
||||
|
||||
module Graph {
|
||||
|
||||
@@ -34,9 +34,13 @@ private module Cached {
|
||||
|
||||
cached
|
||||
predicate hasUnreachedInstructionCached(IRFunction irFunc) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
exists(OldIR::Instruction oldInstruction |
|
||||
irFunc = oldInstruction.getEnclosingIRFunction() and
|
||||
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _)
|
||||
(
|
||||
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _)
|
||||
or
|
||||
oldInstruction.getOpcode() instanceof Opcode::Unreached
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -366,21 +370,19 @@ private module Cached {
|
||||
then
|
||||
result = getChi(getOldInstruction(instruction)) and
|
||||
kind instanceof GotoEdge
|
||||
else (
|
||||
else
|
||||
exists(OldInstruction oldInstruction |
|
||||
oldInstruction = getOldInstruction(instruction) and
|
||||
(
|
||||
oldInstruction = getOldInstruction(instruction)
|
||||
or
|
||||
instruction = getChi(oldInstruction)
|
||||
) and
|
||||
(
|
||||
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind)
|
||||
then result = unreachedInstruction(instruction.getEnclosingIRFunction())
|
||||
else result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(OldInstruction oldInstruction |
|
||||
instruction = getChi(oldInstruction) and
|
||||
result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
|
||||
@@ -7,6 +7,9 @@ predicate isInfeasibleInstructionSuccessor(Instruction instr, EdgeKind kind) {
|
||||
conditionValue = getConstantValue(instr.(ConditionalBranchInstruction).getCondition()) and
|
||||
if conditionValue = 0 then kind instanceof TrueEdge else kind instanceof FalseEdge
|
||||
)
|
||||
or
|
||||
instr.getSuccessor(kind) instanceof UnreachedInstruction and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
@@ -41,7 +44,9 @@ class ReachableBlock extends IRBlockBase {
|
||||
* An instruction that is contained in a reachable block.
|
||||
*/
|
||||
class ReachableInstruction extends Instruction {
|
||||
ReachableInstruction() { this.getBlock() instanceof ReachableBlock }
|
||||
ReachableInstruction() {
|
||||
this.getBlock() instanceof ReachableBlock and not this instanceof UnreachedInstruction
|
||||
}
|
||||
}
|
||||
|
||||
module Graph {
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
--- old/aggregate_array_init
|
||||
+++ new/aggregate_array_init
|
||||
-| 0 | 3 | 42 |
|
||||
+| 0 | 3 | 42 | 17 |
|
||||
|
||||
--- old/aggregate_field_init
|
||||
+++ new/aggregate_field_init
|
||||
-| 0 | 1 | 2 |
|
||||
+| 0 | 1 | 2 | 3 |
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
aggregate_field_init(@"an_aggregate_literal", @"init1", @"a_field")
|
||||
aggregate_array_init(@"an_aggregate_literal", @"init2", 42)
|
||||
|
||||
files(@"file", "dummy file")
|
||||
locations_expr(@"loc", @"file", 0, 0, 0, 0)
|
||||
|
||||
exprs(@"an_aggregate_literal", 127, @"loc")
|
||||
exprs(@"init1", 1, @"loc")
|
||||
exprs(@"init2", 1, @"loc")
|
||||
|
||||
membervariables(@"a_field", @"a_type", "my_field")
|
||||
usertypes(@"a_type", "MyType", 1)
|
||||
|
||||
exprparents(@"init1", 3, @"an_aggregate_literal")
|
||||
exprparents(@"init2", 17, @"an_aggregate_literal")
|
||||
@@ -14377,6 +14377,60 @@ ir.cpp:
|
||||
# 1885| Type = [ClassTemplateInstantiation,Struct] Bar2<int>
|
||||
# 1885| ValueCategory = lvalue
|
||||
# 1886| getStmt(2): [ReturnStmt] return ...
|
||||
# 1889| [TopLevelFunction] void noreturnFunc()
|
||||
# 1889| <params>:
|
||||
# 1891| [TopLevelFunction] int noreturnTest(int)
|
||||
# 1891| <params>:
|
||||
# 1891| getParameter(0): [Parameter] x
|
||||
# 1891| Type = [IntType] int
|
||||
# 1891| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 1892| getStmt(0): [IfStmt] if (...) ...
|
||||
# 1892| getCondition(): [LTExpr] ... < ...
|
||||
# 1892| Type = [BoolType] bool
|
||||
# 1892| ValueCategory = prvalue
|
||||
# 1892| getLesserOperand(): [VariableAccess] x
|
||||
# 1892| Type = [IntType] int
|
||||
# 1892| ValueCategory = prvalue(load)
|
||||
# 1892| getGreaterOperand(): [Literal] 10
|
||||
# 1892| Type = [IntType] int
|
||||
# 1892| Value = [Literal] 10
|
||||
# 1892| ValueCategory = prvalue
|
||||
# 1892| getThen(): [BlockStmt] { ... }
|
||||
# 1893| getStmt(0): [ReturnStmt] return ...
|
||||
# 1893| getExpr(): [VariableAccess] x
|
||||
# 1893| Type = [IntType] int
|
||||
# 1893| ValueCategory = prvalue(load)
|
||||
# 1894| getElse(): [BlockStmt] { ... }
|
||||
# 1895| getStmt(0): [ExprStmt] ExprStmt
|
||||
# 1895| getExpr(): [FunctionCall] call to noreturnFunc
|
||||
# 1895| Type = [VoidType] void
|
||||
# 1895| ValueCategory = prvalue
|
||||
# 1897| getStmt(1): [ReturnStmt] return ...
|
||||
# 1899| [TopLevelFunction] int noreturnTest2(int)
|
||||
# 1899| <params>:
|
||||
# 1899| getParameter(0): [Parameter] x
|
||||
# 1899| Type = [IntType] int
|
||||
# 1899| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 1900| getStmt(0): [IfStmt] if (...) ...
|
||||
# 1900| getCondition(): [LTExpr] ... < ...
|
||||
# 1900| Type = [BoolType] bool
|
||||
# 1900| ValueCategory = prvalue
|
||||
# 1900| getLesserOperand(): [VariableAccess] x
|
||||
# 1900| Type = [IntType] int
|
||||
# 1900| ValueCategory = prvalue(load)
|
||||
# 1900| getGreaterOperand(): [Literal] 10
|
||||
# 1900| Type = [IntType] int
|
||||
# 1900| Value = [Literal] 10
|
||||
# 1900| ValueCategory = prvalue
|
||||
# 1900| getThen(): [BlockStmt] { ... }
|
||||
# 1901| getStmt(0): [ExprStmt] ExprStmt
|
||||
# 1901| getExpr(): [FunctionCall] call to noreturnFunc
|
||||
# 1901| Type = [VoidType] void
|
||||
# 1901| ValueCategory = prvalue
|
||||
# 1903| getStmt(1): [ReturnStmt] return ...
|
||||
# 1903| getExpr(): [VariableAccess] x
|
||||
# 1903| Type = [IntType] int
|
||||
# 1903| ValueCategory = prvalue(load)
|
||||
perf-regression.cpp:
|
||||
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
|
||||
# 4| <params>:
|
||||
|
||||
@@ -1886,4 +1886,21 @@ namespace missing_declaration_entries {
|
||||
}
|
||||
}
|
||||
|
||||
[[noreturn]] void noreturnFunc();
|
||||
|
||||
int noreturnTest(int x) {
|
||||
if (x < 10) {
|
||||
return x;
|
||||
} else {
|
||||
noreturnFunc();
|
||||
}
|
||||
}
|
||||
|
||||
int noreturnTest2(int x) {
|
||||
if (x < 10) {
|
||||
noreturnFunc();
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
// semmle-extractor-options: -std=c++17 --clang
|
||||
|
||||
@@ -8741,6 +8741,44 @@
|
||||
| ir.cpp:1885:11:1885:50 | ChiPartial | partial:m1885_4 |
|
||||
| ir.cpp:1885:11:1885:50 | ChiTotal | total:m1883_4 |
|
||||
| ir.cpp:1885:11:1885:50 | SideEffect | ~m1883_4 |
|
||||
| ir.cpp:1891:5:1891:16 | Address | &:r1891_7 |
|
||||
| ir.cpp:1891:5:1891:16 | ChiPartial | partial:m1891_3 |
|
||||
| ir.cpp:1891:5:1891:16 | ChiTotal | total:m1891_2 |
|
||||
| ir.cpp:1891:5:1891:16 | Load | m1893_4 |
|
||||
| ir.cpp:1891:5:1891:16 | SideEffect | m1891_3 |
|
||||
| ir.cpp:1891:22:1891:22 | Address | &:r1891_5 |
|
||||
| ir.cpp:1892:9:1892:9 | Address | &:r1892_1 |
|
||||
| ir.cpp:1892:9:1892:9 | Left | r1892_2 |
|
||||
| ir.cpp:1892:9:1892:9 | Load | m1891_6 |
|
||||
| ir.cpp:1892:9:1892:14 | Condition | r1892_4 |
|
||||
| ir.cpp:1892:13:1892:14 | Right | r1892_3 |
|
||||
| ir.cpp:1893:9:1893:17 | Address | &:r1893_1 |
|
||||
| ir.cpp:1893:16:1893:16 | Address | &:r1893_2 |
|
||||
| ir.cpp:1893:16:1893:16 | Load | m1891_6 |
|
||||
| ir.cpp:1893:16:1893:16 | StoreValue | r1893_3 |
|
||||
| ir.cpp:1895:9:1895:20 | CallTarget | func:r1895_1 |
|
||||
| ir.cpp:1895:9:1895:20 | ChiPartial | partial:m1895_3 |
|
||||
| ir.cpp:1895:9:1895:20 | ChiTotal | total:m1891_4 |
|
||||
| ir.cpp:1895:9:1895:20 | SideEffect | ~m1891_4 |
|
||||
| ir.cpp:1899:5:1899:17 | Address | &:r1899_8 |
|
||||
| ir.cpp:1899:5:1899:17 | ChiPartial | partial:m1899_3 |
|
||||
| ir.cpp:1899:5:1899:17 | ChiTotal | total:m1899_2 |
|
||||
| ir.cpp:1899:5:1899:17 | Load | m1903_4 |
|
||||
| ir.cpp:1899:5:1899:17 | SideEffect | m1899_3 |
|
||||
| ir.cpp:1899:23:1899:23 | Address | &:r1899_5 |
|
||||
| ir.cpp:1900:9:1900:9 | Address | &:r1900_1 |
|
||||
| ir.cpp:1900:9:1900:9 | Left | r1900_2 |
|
||||
| ir.cpp:1900:9:1900:9 | Load | m1899_6 |
|
||||
| ir.cpp:1900:9:1900:14 | Condition | r1900_4 |
|
||||
| ir.cpp:1900:13:1900:14 | Right | r1900_3 |
|
||||
| ir.cpp:1901:9:1901:20 | CallTarget | func:r1901_1 |
|
||||
| ir.cpp:1901:9:1901:20 | ChiPartial | partial:m1901_3 |
|
||||
| ir.cpp:1901:9:1901:20 | ChiTotal | total:m1899_4 |
|
||||
| ir.cpp:1901:9:1901:20 | SideEffect | ~m1899_4 |
|
||||
| ir.cpp:1903:5:1903:13 | Address | &:r1903_1 |
|
||||
| ir.cpp:1903:12:1903:12 | Address | &:r1903_2 |
|
||||
| ir.cpp:1903:12:1903:12 | Load | m1899_6 |
|
||||
| ir.cpp:1903:12:1903:12 | StoreValue | r1903_3 |
|
||||
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
|
||||
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
|
||||
| perf-regression.cpp:6:3:6:5 | Address | &:r6_7 |
|
||||
|
||||
@@ -10035,6 +10035,68 @@ ir.cpp:
|
||||
# 1883| v1883_5(void) = AliasedUse : ~m?
|
||||
# 1883| v1883_6(void) = ExitFunction :
|
||||
|
||||
# 1891| int noreturnTest(int)
|
||||
# 1891| Block 0
|
||||
# 1891| v1891_1(void) = EnterFunction :
|
||||
# 1891| mu1891_2(unknown) = AliasedDefinition :
|
||||
# 1891| mu1891_3(unknown) = InitializeNonLocal :
|
||||
# 1891| r1891_4(glval<int>) = VariableAddress[x] :
|
||||
# 1891| mu1891_5(int) = InitializeParameter[x] : &:r1891_4
|
||||
# 1892| r1892_1(glval<int>) = VariableAddress[x] :
|
||||
# 1892| r1892_2(int) = Load[x] : &:r1892_1, ~m?
|
||||
# 1892| r1892_3(int) = Constant[10] :
|
||||
# 1892| r1892_4(bool) = CompareLT : r1892_2, r1892_3
|
||||
# 1892| v1892_5(void) = ConditionalBranch : r1892_4
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 1
|
||||
|
||||
# 1893| Block 1
|
||||
# 1893| r1893_1(glval<int>) = VariableAddress[#return] :
|
||||
# 1893| r1893_2(glval<int>) = VariableAddress[x] :
|
||||
# 1893| r1893_3(int) = Load[x] : &:r1893_2, ~m?
|
||||
# 1893| mu1893_4(int) = Store[#return] : &:r1893_1, r1893_3
|
||||
# 1891| r1891_6(glval<int>) = VariableAddress[#return] :
|
||||
# 1891| v1891_7(void) = ReturnValue : &:r1891_6, ~m?
|
||||
# 1891| v1891_8(void) = AliasedUse : ~m?
|
||||
# 1891| v1891_9(void) = ExitFunction :
|
||||
|
||||
# 1895| Block 2
|
||||
# 1895| r1895_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
|
||||
# 1895| v1895_2(void) = Call[noreturnFunc] : func:r1895_1
|
||||
# 1895| mu1895_3(unknown) = ^CallSideEffect : ~m?
|
||||
# 1897| v1897_1(void) = Unreached :
|
||||
|
||||
# 1899| int noreturnTest2(int)
|
||||
# 1899| Block 0
|
||||
# 1899| v1899_1(void) = EnterFunction :
|
||||
# 1899| mu1899_2(unknown) = AliasedDefinition :
|
||||
# 1899| mu1899_3(unknown) = InitializeNonLocal :
|
||||
# 1899| r1899_4(glval<int>) = VariableAddress[x] :
|
||||
# 1899| mu1899_5(int) = InitializeParameter[x] : &:r1899_4
|
||||
# 1900| r1900_1(glval<int>) = VariableAddress[x] :
|
||||
# 1900| r1900_2(int) = Load[x] : &:r1900_1, ~m?
|
||||
# 1900| r1900_3(int) = Constant[10] :
|
||||
# 1900| r1900_4(bool) = CompareLT : r1900_2, r1900_3
|
||||
# 1900| v1900_5(void) = ConditionalBranch : r1900_4
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 1
|
||||
|
||||
# 1901| Block 1
|
||||
# 1901| r1901_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
|
||||
# 1901| v1901_2(void) = Call[noreturnFunc] : func:r1901_1
|
||||
# 1901| mu1901_3(unknown) = ^CallSideEffect : ~m?
|
||||
# 1899| v1899_6(void) = Unreached :
|
||||
|
||||
# 1903| Block 2
|
||||
# 1903| r1903_1(glval<int>) = VariableAddress[#return] :
|
||||
# 1903| r1903_2(glval<int>) = VariableAddress[x] :
|
||||
# 1903| r1903_3(int) = Load[x] : &:r1903_2, ~m?
|
||||
# 1903| mu1903_4(int) = Store[#return] : &:r1903_1, r1903_3
|
||||
# 1899| r1899_7(glval<int>) = VariableAddress[#return] :
|
||||
# 1899| v1899_8(void) = ReturnValue : &:r1899_7, ~m?
|
||||
# 1899| v1899_9(void) = AliasedUse : ~m?
|
||||
# 1899| v1899_10(void) = ExitFunction :
|
||||
|
||||
perf-regression.cpp:
|
||||
# 6| void Big::Big()
|
||||
# 6| Block 0
|
||||
|
||||
@@ -2091,3 +2091,69 @@ ssa.cpp:
|
||||
# 417| v417_5(void) = ReturnVoid :
|
||||
# 417| v417_6(void) = AliasedUse : m417_3
|
||||
# 417| v417_7(void) = ExitFunction :
|
||||
|
||||
# 423| int noreturnTest(int)
|
||||
# 423| Block 0
|
||||
# 423| v423_1(void) = EnterFunction :
|
||||
# 423| m423_2(unknown) = AliasedDefinition :
|
||||
# 423| m423_3(unknown) = InitializeNonLocal :
|
||||
# 423| m423_4(unknown) = Chi : total:m423_2, partial:m423_3
|
||||
# 423| r423_5(glval<int>) = VariableAddress[x] :
|
||||
# 423| m423_6(int) = InitializeParameter[x] : &:r423_5
|
||||
# 424| r424_1(glval<int>) = VariableAddress[x] :
|
||||
# 424| r424_2(int) = Load[x] : &:r424_1, m423_6
|
||||
# 424| r424_3(int) = Constant[10] :
|
||||
# 424| r424_4(bool) = CompareLT : r424_2, r424_3
|
||||
# 424| v424_5(void) = ConditionalBranch : r424_4
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 1
|
||||
|
||||
# 425| Block 1
|
||||
# 425| r425_1(glval<int>) = VariableAddress[#return] :
|
||||
# 425| r425_2(glval<int>) = VariableAddress[x] :
|
||||
# 425| r425_3(int) = Load[x] : &:r425_2, m423_6
|
||||
# 425| m425_4(int) = Store[#return] : &:r425_1, r425_3
|
||||
# 423| r423_7(glval<int>) = VariableAddress[#return] :
|
||||
# 423| v423_8(void) = ReturnValue : &:r423_7, m425_4
|
||||
# 423| v423_9(void) = AliasedUse : m423_3
|
||||
# 423| v423_10(void) = ExitFunction :
|
||||
|
||||
# 427| Block 2
|
||||
# 427| r427_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
|
||||
# 427| v427_2(void) = Call[noreturnFunc] : func:r427_1
|
||||
# 427| m427_3(unknown) = ^CallSideEffect : ~m423_4
|
||||
# 427| m427_4(unknown) = Chi : total:m423_4, partial:m427_3
|
||||
# 423| v423_11(void) = Unreached :
|
||||
|
||||
# 431| int noreturnTest2(int)
|
||||
# 431| Block 0
|
||||
# 431| v431_1(void) = EnterFunction :
|
||||
# 431| m431_2(unknown) = AliasedDefinition :
|
||||
# 431| m431_3(unknown) = InitializeNonLocal :
|
||||
# 431| m431_4(unknown) = Chi : total:m431_2, partial:m431_3
|
||||
# 431| r431_5(glval<int>) = VariableAddress[x] :
|
||||
# 431| m431_6(int) = InitializeParameter[x] : &:r431_5
|
||||
# 432| r432_1(glval<int>) = VariableAddress[x] :
|
||||
# 432| r432_2(int) = Load[x] : &:r432_1, m431_6
|
||||
# 432| r432_3(int) = Constant[10] :
|
||||
# 432| r432_4(bool) = CompareLT : r432_2, r432_3
|
||||
# 432| v432_5(void) = ConditionalBranch : r432_4
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 1
|
||||
|
||||
# 433| Block 1
|
||||
# 433| r433_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
|
||||
# 433| v433_2(void) = Call[noreturnFunc] : func:r433_1
|
||||
# 433| m433_3(unknown) = ^CallSideEffect : ~m431_4
|
||||
# 433| m433_4(unknown) = Chi : total:m431_4, partial:m433_3
|
||||
# 431| v431_7(void) = Unreached :
|
||||
|
||||
# 435| Block 2
|
||||
# 435| r435_1(glval<int>) = VariableAddress[#return] :
|
||||
# 435| r435_2(glval<int>) = VariableAddress[x] :
|
||||
# 435| r435_3(int) = Load[x] : &:r435_2, m431_6
|
||||
# 435| m435_4(int) = Store[#return] : &:r435_1, r435_3
|
||||
# 431| r431_8(glval<int>) = VariableAddress[#return] :
|
||||
# 431| v431_9(void) = ReturnValue : &:r431_8, m435_4
|
||||
# 431| v431_10(void) = AliasedUse : m431_3
|
||||
# 431| v431_11(void) = ExitFunction :
|
||||
|
||||
@@ -2080,3 +2080,69 @@ ssa.cpp:
|
||||
# 417| v417_5(void) = ReturnVoid :
|
||||
# 417| v417_6(void) = AliasedUse : m417_3
|
||||
# 417| v417_7(void) = ExitFunction :
|
||||
|
||||
# 423| int noreturnTest(int)
|
||||
# 423| Block 0
|
||||
# 423| v423_1(void) = EnterFunction :
|
||||
# 423| m423_2(unknown) = AliasedDefinition :
|
||||
# 423| m423_3(unknown) = InitializeNonLocal :
|
||||
# 423| m423_4(unknown) = Chi : total:m423_2, partial:m423_3
|
||||
# 423| r423_5(glval<int>) = VariableAddress[x] :
|
||||
# 423| m423_6(int) = InitializeParameter[x] : &:r423_5
|
||||
# 424| r424_1(glval<int>) = VariableAddress[x] :
|
||||
# 424| r424_2(int) = Load[x] : &:r424_1, m423_6
|
||||
# 424| r424_3(int) = Constant[10] :
|
||||
# 424| r424_4(bool) = CompareLT : r424_2, r424_3
|
||||
# 424| v424_5(void) = ConditionalBranch : r424_4
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 1
|
||||
|
||||
# 425| Block 1
|
||||
# 425| r425_1(glval<int>) = VariableAddress[#return] :
|
||||
# 425| r425_2(glval<int>) = VariableAddress[x] :
|
||||
# 425| r425_3(int) = Load[x] : &:r425_2, m423_6
|
||||
# 425| m425_4(int) = Store[#return] : &:r425_1, r425_3
|
||||
# 423| r423_7(glval<int>) = VariableAddress[#return] :
|
||||
# 423| v423_8(void) = ReturnValue : &:r423_7, m425_4
|
||||
# 423| v423_9(void) = AliasedUse : m423_3
|
||||
# 423| v423_10(void) = ExitFunction :
|
||||
|
||||
# 427| Block 2
|
||||
# 427| r427_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
|
||||
# 427| v427_2(void) = Call[noreturnFunc] : func:r427_1
|
||||
# 427| m427_3(unknown) = ^CallSideEffect : ~m423_4
|
||||
# 427| m427_4(unknown) = Chi : total:m423_4, partial:m427_3
|
||||
# 423| v423_11(void) = Unreached :
|
||||
|
||||
# 431| int noreturnTest2(int)
|
||||
# 431| Block 0
|
||||
# 431| v431_1(void) = EnterFunction :
|
||||
# 431| m431_2(unknown) = AliasedDefinition :
|
||||
# 431| m431_3(unknown) = InitializeNonLocal :
|
||||
# 431| m431_4(unknown) = Chi : total:m431_2, partial:m431_3
|
||||
# 431| r431_5(glval<int>) = VariableAddress[x] :
|
||||
# 431| m431_6(int) = InitializeParameter[x] : &:r431_5
|
||||
# 432| r432_1(glval<int>) = VariableAddress[x] :
|
||||
# 432| r432_2(int) = Load[x] : &:r432_1, m431_6
|
||||
# 432| r432_3(int) = Constant[10] :
|
||||
# 432| r432_4(bool) = CompareLT : r432_2, r432_3
|
||||
# 432| v432_5(void) = ConditionalBranch : r432_4
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 1
|
||||
|
||||
# 433| Block 1
|
||||
# 433| r433_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
|
||||
# 433| v433_2(void) = Call[noreturnFunc] : func:r433_1
|
||||
# 433| m433_3(unknown) = ^CallSideEffect : ~m431_4
|
||||
# 433| m433_4(unknown) = Chi : total:m431_4, partial:m433_3
|
||||
# 431| v431_7(void) = Unreached :
|
||||
|
||||
# 435| Block 2
|
||||
# 435| r435_1(glval<int>) = VariableAddress[#return] :
|
||||
# 435| r435_2(glval<int>) = VariableAddress[x] :
|
||||
# 435| r435_3(int) = Load[x] : &:r435_2, m431_6
|
||||
# 435| m435_4(int) = Store[#return] : &:r435_1, r435_3
|
||||
# 431| r431_8(glval<int>) = VariableAddress[#return] :
|
||||
# 431| v431_9(void) = ReturnValue : &:r431_8, m435_4
|
||||
# 431| v431_10(void) = AliasedUse : m431_3
|
||||
# 431| v431_11(void) = ExitFunction :
|
||||
|
||||
@@ -417,3 +417,20 @@ void vla(int n1, int n2, int n3, bool b1) {
|
||||
void nested_array_designators() {
|
||||
int x[1][2] = {[0][0] = 1234, [0][1] = 5678};
|
||||
}
|
||||
|
||||
[[noreturn]] void noreturnFunc();
|
||||
|
||||
int noreturnTest(int x) {
|
||||
if (x < 10) {
|
||||
return x;
|
||||
} else {
|
||||
noreturnFunc();
|
||||
}
|
||||
}
|
||||
|
||||
int noreturnTest2(int x) {
|
||||
if (x < 10) {
|
||||
noreturnFunc();
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
@@ -1940,3 +1940,65 @@ ssa.cpp:
|
||||
# 417| v417_4(void) = ReturnVoid :
|
||||
# 417| v417_5(void) = AliasedUse : ~m?
|
||||
# 417| v417_6(void) = ExitFunction :
|
||||
|
||||
# 423| int noreturnTest(int)
|
||||
# 423| Block 0
|
||||
# 423| v423_1(void) = EnterFunction :
|
||||
# 423| mu423_2(unknown) = AliasedDefinition :
|
||||
# 423| mu423_3(unknown) = InitializeNonLocal :
|
||||
# 423| r423_4(glval<int>) = VariableAddress[x] :
|
||||
# 423| m423_5(int) = InitializeParameter[x] : &:r423_4
|
||||
# 424| r424_1(glval<int>) = VariableAddress[x] :
|
||||
# 424| r424_2(int) = Load[x] : &:r424_1, m423_5
|
||||
# 424| r424_3(int) = Constant[10] :
|
||||
# 424| r424_4(bool) = CompareLT : r424_2, r424_3
|
||||
# 424| v424_5(void) = ConditionalBranch : r424_4
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 1
|
||||
|
||||
# 425| Block 1
|
||||
# 425| r425_1(glval<int>) = VariableAddress[#return] :
|
||||
# 425| r425_2(glval<int>) = VariableAddress[x] :
|
||||
# 425| r425_3(int) = Load[x] : &:r425_2, m423_5
|
||||
# 425| m425_4(int) = Store[#return] : &:r425_1, r425_3
|
||||
# 423| r423_6(glval<int>) = VariableAddress[#return] :
|
||||
# 423| v423_7(void) = ReturnValue : &:r423_6, m425_4
|
||||
# 423| v423_8(void) = AliasedUse : ~m?
|
||||
# 423| v423_9(void) = ExitFunction :
|
||||
|
||||
# 427| Block 2
|
||||
# 427| r427_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
|
||||
# 427| v427_2(void) = Call[noreturnFunc] : func:r427_1
|
||||
# 427| mu427_3(unknown) = ^CallSideEffect : ~m?
|
||||
# 423| v423_10(void) = Unreached :
|
||||
|
||||
# 431| int noreturnTest2(int)
|
||||
# 431| Block 0
|
||||
# 431| v431_1(void) = EnterFunction :
|
||||
# 431| mu431_2(unknown) = AliasedDefinition :
|
||||
# 431| mu431_3(unknown) = InitializeNonLocal :
|
||||
# 431| r431_4(glval<int>) = VariableAddress[x] :
|
||||
# 431| m431_5(int) = InitializeParameter[x] : &:r431_4
|
||||
# 432| r432_1(glval<int>) = VariableAddress[x] :
|
||||
# 432| r432_2(int) = Load[x] : &:r432_1, m431_5
|
||||
# 432| r432_3(int) = Constant[10] :
|
||||
# 432| r432_4(bool) = CompareLT : r432_2, r432_3
|
||||
# 432| v432_5(void) = ConditionalBranch : r432_4
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 1
|
||||
|
||||
# 433| Block 1
|
||||
# 433| r433_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
|
||||
# 433| v433_2(void) = Call[noreturnFunc] : func:r433_1
|
||||
# 433| mu433_3(unknown) = ^CallSideEffect : ~m?
|
||||
# 431| v431_6(void) = Unreached :
|
||||
|
||||
# 435| Block 2
|
||||
# 435| r435_1(glval<int>) = VariableAddress[#return] :
|
||||
# 435| r435_2(glval<int>) = VariableAddress[x] :
|
||||
# 435| r435_3(int) = Load[x] : &:r435_2, m431_5
|
||||
# 435| m435_4(int) = Store[#return] : &:r435_1, r435_3
|
||||
# 431| r431_7(glval<int>) = VariableAddress[#return] :
|
||||
# 431| v431_8(void) = ReturnValue : &:r431_7, m435_4
|
||||
# 431| v431_9(void) = AliasedUse : ~m?
|
||||
# 431| v431_10(void) = ExitFunction :
|
||||
|
||||
@@ -1940,3 +1940,65 @@ ssa.cpp:
|
||||
# 417| v417_4(void) = ReturnVoid :
|
||||
# 417| v417_5(void) = AliasedUse : ~m?
|
||||
# 417| v417_6(void) = ExitFunction :
|
||||
|
||||
# 423| int noreturnTest(int)
|
||||
# 423| Block 0
|
||||
# 423| v423_1(void) = EnterFunction :
|
||||
# 423| mu423_2(unknown) = AliasedDefinition :
|
||||
# 423| mu423_3(unknown) = InitializeNonLocal :
|
||||
# 423| r423_4(glval<int>) = VariableAddress[x] :
|
||||
# 423| m423_5(int) = InitializeParameter[x] : &:r423_4
|
||||
# 424| r424_1(glval<int>) = VariableAddress[x] :
|
||||
# 424| r424_2(int) = Load[x] : &:r424_1, m423_5
|
||||
# 424| r424_3(int) = Constant[10] :
|
||||
# 424| r424_4(bool) = CompareLT : r424_2, r424_3
|
||||
# 424| v424_5(void) = ConditionalBranch : r424_4
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 1
|
||||
|
||||
# 425| Block 1
|
||||
# 425| r425_1(glval<int>) = VariableAddress[#return] :
|
||||
# 425| r425_2(glval<int>) = VariableAddress[x] :
|
||||
# 425| r425_3(int) = Load[x] : &:r425_2, m423_5
|
||||
# 425| m425_4(int) = Store[#return] : &:r425_1, r425_3
|
||||
# 423| r423_6(glval<int>) = VariableAddress[#return] :
|
||||
# 423| v423_7(void) = ReturnValue : &:r423_6, m425_4
|
||||
# 423| v423_8(void) = AliasedUse : ~m?
|
||||
# 423| v423_9(void) = ExitFunction :
|
||||
|
||||
# 427| Block 2
|
||||
# 427| r427_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
|
||||
# 427| v427_2(void) = Call[noreturnFunc] : func:r427_1
|
||||
# 427| mu427_3(unknown) = ^CallSideEffect : ~m?
|
||||
# 423| v423_10(void) = Unreached :
|
||||
|
||||
# 431| int noreturnTest2(int)
|
||||
# 431| Block 0
|
||||
# 431| v431_1(void) = EnterFunction :
|
||||
# 431| mu431_2(unknown) = AliasedDefinition :
|
||||
# 431| mu431_3(unknown) = InitializeNonLocal :
|
||||
# 431| r431_4(glval<int>) = VariableAddress[x] :
|
||||
# 431| m431_5(int) = InitializeParameter[x] : &:r431_4
|
||||
# 432| r432_1(glval<int>) = VariableAddress[x] :
|
||||
# 432| r432_2(int) = Load[x] : &:r432_1, m431_5
|
||||
# 432| r432_3(int) = Constant[10] :
|
||||
# 432| r432_4(bool) = CompareLT : r432_2, r432_3
|
||||
# 432| v432_5(void) = ConditionalBranch : r432_4
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 1
|
||||
|
||||
# 433| Block 1
|
||||
# 433| r433_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
|
||||
# 433| v433_2(void) = Call[noreturnFunc] : func:r433_1
|
||||
# 433| mu433_3(unknown) = ^CallSideEffect : ~m?
|
||||
# 431| v431_6(void) = Unreached :
|
||||
|
||||
# 435| Block 2
|
||||
# 435| r435_1(glval<int>) = VariableAddress[#return] :
|
||||
# 435| r435_2(glval<int>) = VariableAddress[x] :
|
||||
# 435| r435_3(int) = Load[x] : &:r435_2, m431_5
|
||||
# 435| m435_4(int) = Store[#return] : &:r435_1, r435_3
|
||||
# 431| r431_7(glval<int>) = VariableAddress[#return] :
|
||||
# 431| v431_8(void) = ReturnValue : &:r431_7, m435_4
|
||||
# 431| v431_9(void) = AliasedUse : ~m?
|
||||
# 431| v431_10(void) = ExitFunction :
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
package,sink,source,summary,sink:code,sink:encryption-decryptor,sink:encryption-encryptor,sink:encryption-keyprop,sink:encryption-symmetrickey,sink:html,sink:remote,sink:sql,sink:xss,source:file,source:local,source:remote,summary:taint,summary:value
|
||||
Dapper,55,,,,,,,,,,55,,,,,,
|
||||
JsonToItemsTaskFactory,,,7,,,,,,,,,,,,,7,
|
||||
Microsoft.ApplicationBlocks.Data,28,,,,,,,,,,28,,,,,,
|
||||
Microsoft.CSharp,,,24,,,,,,,,,,,,,24,
|
||||
Microsoft.EntityFrameworkCore,6,,,,,,,,,,6,,,,,,
|
||||
Microsoft.Extensions.Caching.Distributed,,,15,,,,,,,,,,,,,15,
|
||||
Microsoft.Extensions.Caching.Memory,,,46,,,,,,,,,,,,,45,1
|
||||
Microsoft.Extensions.Configuration,,,83,,,,,,,,,,,,,80,3
|
||||
Microsoft.Extensions.DependencyInjection,,,62,,,,,,,,,,,,,62,
|
||||
Microsoft.Extensions.DependencyModel,,,12,,,,,,,,,,,,,12,
|
||||
Microsoft.Extensions.FileProviders,,,16,,,,,,,,,,,,,16,
|
||||
Microsoft.Extensions.FileSystemGlobbing,,,15,,,,,,,,,,,,,13,2
|
||||
Microsoft.Extensions.Hosting,,,17,,,,,,,,,,,,,16,1
|
||||
Microsoft.Extensions.Http,,,10,,,,,,,,,,,,,10,
|
||||
Microsoft.Extensions.Logging,,,37,,,,,,,,,,,,,37,
|
||||
Microsoft.Extensions.Options,,,8,,,,,,,,,,,,,8,
|
||||
Microsoft.Extensions.Primitives,,,63,,,,,,,,,,,,,63,
|
||||
Microsoft.Interop,,,27,,,,,,,,,,,,,27,
|
||||
Microsoft.NET.Build.Tasks,,,1,,,,,,,,,,,,,1,
|
||||
Microsoft.NETCore.Platforms.BuildTasks,,,4,,,,,,,,,,,,,4,
|
||||
Microsoft.VisualBasic,,,10,,,,,,,,,,,,,5,5
|
||||
Microsoft.Win32,,,8,,,,,,,,,,,,,8,
|
||||
MySql.Data.MySqlClient,48,,,,,,,,,,48,,,,,,
|
||||
Newtonsoft.Json,,,91,,,,,,,,,,,,,73,18
|
||||
ServiceStack,194,,7,27,,,,,,75,92,,,,,7,
|
||||
System,65,8,12154,,8,8,9,,4,,33,3,1,3,4,10163,1991
|
||||
Windows.Security.Cryptography.Core,1,,,,,,,1,,,,,,,,,
|
||||
package,sink,source,summary,sink:code,sink:encryption-decryptor,sink:encryption-encryptor,sink:encryption-keyprop,sink:encryption-symmetrickey,sink:html,sink:remote,sink:sql,sink:xss,source:file,source:file-write,source:local,source:remote,summary:taint,summary:value
|
||||
Dapper,55,,,,,,,,,,55,,,,,,,
|
||||
JsonToItemsTaskFactory,,,7,,,,,,,,,,,,,,7,
|
||||
Microsoft.ApplicationBlocks.Data,28,,,,,,,,,,28,,,,,,,
|
||||
Microsoft.CSharp,,,24,,,,,,,,,,,,,,24,
|
||||
Microsoft.EntityFrameworkCore,6,,,,,,,,,,6,,,,,,,
|
||||
Microsoft.Extensions.Caching.Distributed,,,15,,,,,,,,,,,,,,15,
|
||||
Microsoft.Extensions.Caching.Memory,,,46,,,,,,,,,,,,,,45,1
|
||||
Microsoft.Extensions.Configuration,,,83,,,,,,,,,,,,,,80,3
|
||||
Microsoft.Extensions.DependencyInjection,,,62,,,,,,,,,,,,,,62,
|
||||
Microsoft.Extensions.DependencyModel,,,12,,,,,,,,,,,,,,12,
|
||||
Microsoft.Extensions.FileProviders,,,16,,,,,,,,,,,,,,16,
|
||||
Microsoft.Extensions.FileSystemGlobbing,,,15,,,,,,,,,,,,,,13,2
|
||||
Microsoft.Extensions.Hosting,,,17,,,,,,,,,,,,,,16,1
|
||||
Microsoft.Extensions.Http,,,10,,,,,,,,,,,,,,10,
|
||||
Microsoft.Extensions.Logging,,,37,,,,,,,,,,,,,,37,
|
||||
Microsoft.Extensions.Options,,,8,,,,,,,,,,,,,,8,
|
||||
Microsoft.Extensions.Primitives,,,63,,,,,,,,,,,,,,63,
|
||||
Microsoft.Interop,,,27,,,,,,,,,,,,,,27,
|
||||
Microsoft.NET.Build.Tasks,,,1,,,,,,,,,,,,,,1,
|
||||
Microsoft.NETCore.Platforms.BuildTasks,,,4,,,,,,,,,,,,,,4,
|
||||
Microsoft.VisualBasic,,,10,,,,,,,,,,,,,,5,5
|
||||
Microsoft.Win32,,,8,,,,,,,,,,,,,,8,
|
||||
MySql.Data.MySqlClient,48,,,,,,,,,,48,,,,,,,
|
||||
Newtonsoft.Json,,,91,,,,,,,,,,,,,,73,18
|
||||
ServiceStack,194,,7,27,,,,,,75,92,,,,,,7,
|
||||
System,65,25,12154,,8,8,9,,4,,33,3,1,17,3,4,10163,1991
|
||||
Windows.Security.Cryptography.Core,1,,,,,,,1,,,,,,,,,,
|
||||
|
||||
|
@@ -8,7 +8,7 @@ C# framework & library support
|
||||
|
||||
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE-079` :sub:`Cross-site scripting`
|
||||
`ServiceStack <https://servicestack.net/>`_,"``ServiceStack.*``, ``ServiceStack``",,7,194,
|
||||
System,"``System.*``, ``System``",8,12154,65,7
|
||||
System,"``System.*``, ``System``",25,12154,65,7
|
||||
Others,"``Dapper``, ``JsonToItemsTaskFactory``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.CSharp``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Caching.Distributed``, ``Microsoft.Extensions.Caching.Memory``, ``Microsoft.Extensions.Configuration``, ``Microsoft.Extensions.DependencyInjection``, ``Microsoft.Extensions.DependencyModel``, ``Microsoft.Extensions.FileProviders``, ``Microsoft.Extensions.FileSystemGlobbing``, ``Microsoft.Extensions.Hosting``, ``Microsoft.Extensions.Http``, ``Microsoft.Extensions.Logging``, ``Microsoft.Extensions.Options``, ``Microsoft.Extensions.Primitives``, ``Microsoft.Interop``, ``Microsoft.NET.Build.Tasks``, ``Microsoft.NETCore.Platforms.BuildTasks``, ``Microsoft.VisualBasic``, ``Microsoft.Win32``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``, ``Windows.Security.Cryptography.Core``",,556,138,
|
||||
Totals,,8,12717,397,7
|
||||
Totals,,25,12717,397,7
|
||||
|
||||
|
||||
@@ -4,6 +4,23 @@ extensions:
|
||||
extensible: sourceModel
|
||||
data:
|
||||
- ["System.IO", "FileStream", False, "FileStream", "", "", "Argument[this]", "file", "manual"]
|
||||
- ["System.IO", "FileStream", False, "FileStream", "", "", "Argument[this]", "file-write", "manual"]
|
||||
- ["System.IO", "StreamWriter", False, "StreamWriter", "(System.String)", "", "Argument[this]", "file-write", "manual"]
|
||||
- ["System.IO", "StreamWriter", False, "StreamWriter", "(System.String,System.Boolean)", "", "Argument[this]", "file-write", "manual"]
|
||||
- ["System.IO", "StreamWriter", False, "StreamWriter", "(System.String,System.Boolean,System.Text.Encoding)", "", "Argument[this]", "file-write", "manual"]
|
||||
- ["System.IO", "StreamWriter", False, "StreamWriter", "(System.String,System.Boolean,System.Text.Encoding,System.Int32)", "", "Argument[this]", "file-write", "manual"]
|
||||
- ["System.IO", "StreamWriter", False, "StreamWriter", "(System.String,System.Text.Encoding,System.IO.FileStreamOptions)", "", "Argument[this]", "file-write", "manual"]
|
||||
- ["System.IO", "StreamWriter", False, "StreamWriter", "(System.String,System.IO.FileStreamOptions)", "", "Argument[this]", "file-write", "manual"]
|
||||
- ["System.IO", "File", False, "Open", "", "", "ReturnValue", "file-write", "manual"]
|
||||
- ["System.IO", "File", False, "OpenWrite", "", "", "ReturnValue", "file-write", "manual"]
|
||||
- ["System.IO", "File", False, "Create", "", "", "ReturnValue", "file-write", "manual"]
|
||||
- ["System.IO", "File", False, "CreateText", "", "", "ReturnValue", "file-write", "manual"]
|
||||
- ["System.IO", "File", False, "AppendText", "", "", "ReturnValue", "file-write", "manual"]
|
||||
- ["System.IO", "FileInfo", False, "Open", "", "", "ReturnValue", "file-write", "manual"]
|
||||
- ["System.IO", "FileInfo", False, "OpenWrite", "", "", "ReturnValue", "file-write", "manual"]
|
||||
- ["System.IO", "FileInfo", False, "Create", "", "", "ReturnValue", "file-write", "manual"]
|
||||
- ["System.IO", "FileInfo", False, "CreateText", "", "", "ReturnValue", "file-write", "manual"]
|
||||
- ["System.IO", "FileInfo", False, "AppendText", "", "", "ReturnValue", "file-write", "manual"]
|
||||
- addsTo:
|
||||
pack: codeql/csharp-all
|
||||
extensible: summaryModel
|
||||
|
||||
@@ -215,7 +215,7 @@ module ModelValidation {
|
||||
)
|
||||
or
|
||||
exists(string kind | sourceModel(_, _, _, _, _, _, _, kind, _) |
|
||||
not kind = ["local", "remote", "file"] and
|
||||
not kind = ["local", "remote", "file", "file-write"] and
|
||||
result = "Invalid kind \"" + kind + "\" in source model."
|
||||
)
|
||||
}
|
||||
|
||||
@@ -361,3 +361,52 @@ module MergePathGraph<
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a `PathGraph` from three `PathGraph`s by disjoint union.
|
||||
*/
|
||||
module MergePathGraph3<
|
||||
PathNodeSig PathNode1, PathNodeSig PathNode2, PathNodeSig PathNode3,
|
||||
PathGraphSig<PathNode1> Graph1, PathGraphSig<PathNode2> Graph2, PathGraphSig<PathNode3> Graph3>
|
||||
{
|
||||
private module MergedInner = MergePathGraph<PathNode1, PathNode2, Graph1, Graph2>;
|
||||
|
||||
private module Merged =
|
||||
MergePathGraph<MergedInner::PathNode, PathNode3, MergedInner::PathGraph, Graph3>;
|
||||
|
||||
/** A node in a graph of path explanations that is formed by disjoint union of the three given graphs. */
|
||||
class PathNode instanceof Merged::PathNode {
|
||||
/** Gets this as a projection on the first given `PathGraph`. */
|
||||
PathNode1 asPathNode1() { result = super.asPathNode1().asPathNode1() }
|
||||
|
||||
/** Gets this as a projection on the second given `PathGraph`. */
|
||||
PathNode2 asPathNode2() { result = super.asPathNode1().asPathNode2() }
|
||||
|
||||
/** Gets this as a projection on the third given `PathGraph`. */
|
||||
PathNode3 asPathNode3() { result = super.asPathNode2() }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets the underlying `Node`. */
|
||||
Node getNode() { result = super.getNode() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the query predicates needed to include a graph in a path-problem query.
|
||||
*/
|
||||
module PathGraph = Merged::PathGraph;
|
||||
}
|
||||
|
||||
@@ -18,12 +18,10 @@ private import semmle.code.csharp.dataflow.TaintTracking2
|
||||
*/
|
||||
predicate xssFlow(XssNode source, XssNode sink, string message) {
|
||||
// standard taint-tracking
|
||||
exists(
|
||||
TaintTrackingConfiguration c, DataFlow2::PathNode sourceNode, DataFlow2::PathNode sinkNode
|
||||
|
|
||||
exists(XssTracking::PathNode sourceNode, XssTracking::PathNode sinkNode |
|
||||
sourceNode = source.asDataFlowNode() and
|
||||
sinkNode = sink.asDataFlowNode() and
|
||||
c.hasFlowPath(sourceNode, sinkNode) and
|
||||
XssTracking::flowPath(sourceNode, sinkNode) and
|
||||
message =
|
||||
"is written to HTML or JavaScript" +
|
||||
any(string explanation |
|
||||
@@ -45,7 +43,7 @@ predicate xssFlow(XssNode source, XssNode sink, string message) {
|
||||
module PathGraph {
|
||||
/** Holds if `(pred,succ)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(XssNode pred, XssNode succ) {
|
||||
exists(DataFlow2::PathNode a, DataFlow2::PathNode b | DataFlow2::PathGraph::edges(a, b) |
|
||||
exists(XssTracking::PathNode a, XssTracking::PathNode b | XssTracking::PathGraph::edges(a, b) |
|
||||
pred.asDataFlowNode() = a and
|
||||
succ.asDataFlowNode() = b
|
||||
)
|
||||
@@ -56,7 +54,7 @@ module PathGraph {
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(XssNode n, string key, string val) {
|
||||
DataFlow2::PathGraph::nodes(n.asDataFlowNode(), key, val)
|
||||
XssTracking::PathGraph::nodes(n.asDataFlowNode(), key, val)
|
||||
or
|
||||
xssFlow(n, n, _) and
|
||||
key = "semmle.label" and
|
||||
@@ -69,13 +67,13 @@ module PathGraph {
|
||||
* `ret -> out` is summarized as the edge `arg -> out`.
|
||||
*/
|
||||
query predicate subpaths(XssNode arg, XssNode par, XssNode ret, XssNode out) {
|
||||
DataFlow2::PathGraph::subpaths(arg.asDataFlowNode(), par.asDataFlowNode(), ret.asDataFlowNode(),
|
||||
out.asDataFlowNode())
|
||||
XssTracking::PathGraph::subpaths(arg.asDataFlowNode(), par.asDataFlowNode(),
|
||||
ret.asDataFlowNode(), out.asDataFlowNode())
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TXssNode =
|
||||
TXssDataFlowNode(DataFlow2::PathNode node) or
|
||||
TXssDataFlowNode(XssTracking::PathNode node) or
|
||||
TXssAspNode(AspInlineMember m)
|
||||
|
||||
/**
|
||||
@@ -90,21 +88,25 @@ class XssNode extends TXssNode {
|
||||
/** Gets the location of this node. */
|
||||
Location getLocation() { none() }
|
||||
|
||||
/** Gets the data flow node corresponding to this node, if any. */
|
||||
DataFlow2::PathNode asDataFlowNode() { result = this.(XssDataFlowNode).getDataFlowNode() }
|
||||
/**
|
||||
* Gets the data flow node corresponding to this node, if any.
|
||||
*/
|
||||
XssTracking::PathNode asDataFlowNode() { result = this.(XssDataFlowNode).getDataFlowNode() }
|
||||
|
||||
/** Gets the ASP inline code element corresponding to this node, if any. */
|
||||
AspInlineMember asAspInlineMember() { result = this.(XssAspNode).getAspInlineMember() }
|
||||
}
|
||||
|
||||
/** A data flow node, viewed as an XSS flow node. */
|
||||
/**
|
||||
* A data flow node, viewed as an XSS flow node.
|
||||
*/
|
||||
class XssDataFlowNode extends TXssDataFlowNode, XssNode {
|
||||
DataFlow2::PathNode node;
|
||||
XssTracking::PathNode node;
|
||||
|
||||
XssDataFlowNode() { this = TXssDataFlowNode(node) }
|
||||
|
||||
/** Gets the data flow node corresponding to this node. */
|
||||
DataFlow2::PathNode getDataFlowNode() { result = node }
|
||||
XssTracking::PathNode getDataFlowNode() { result = node }
|
||||
|
||||
override string toString() { result = node.toString() }
|
||||
|
||||
@@ -136,9 +138,11 @@ abstract class Source extends DataFlow::Node { }
|
||||
abstract class Sanitizer extends DataFlow::ExprNode { }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `XssTracking` instead.
|
||||
*
|
||||
* A taint-tracking configuration for cross-site scripting (XSS) vulnerabilities.
|
||||
*/
|
||||
class TaintTrackingConfiguration extends TaintTracking2::Configuration {
|
||||
deprecated class TaintTrackingConfiguration extends TaintTracking2::Configuration {
|
||||
TaintTrackingConfiguration() { this = "XSSDataFlowConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
@@ -148,6 +152,29 @@ class TaintTrackingConfiguration extends TaintTracking2::Configuration {
|
||||
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for cross-site scripting (XSS) vulnerabilities.
|
||||
*/
|
||||
module XssTrackingConfig implements DataFlow::ConfigSig {
|
||||
/**
|
||||
* Holds if `source` is a relevant data flow source.
|
||||
*/
|
||||
predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant data flow sink.
|
||||
*/
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
/**
|
||||
* Holds if data flow through `node` is prohibited. This completely removes
|
||||
* `node` from the data flow graph.
|
||||
*/
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
}
|
||||
|
||||
module XssTracking = TaintTracking::Global<XssTrackingConfig>;
|
||||
|
||||
/** A source of remote user input. */
|
||||
private class RemoteSource extends Source instanceof RemoteFlowSource { }
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import csharp
|
||||
private import Remote
|
||||
private import semmle.code.csharp.commons.Loggers
|
||||
private import semmle.code.csharp.frameworks.system.Web
|
||||
private import semmle.code.csharp.frameworks.system.IO
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/**
|
||||
@@ -63,3 +64,56 @@ class CookieStorageSink extends ExternalLocationSink, RemoteFlowSink {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate isFileWriteCall(Expr stream, Expr data) {
|
||||
exists(MethodCall mc, Method m | mc.getTarget() = m.getAnOverrider*() |
|
||||
m.hasQualifiedName("System.IO", "Stream", ["Write", "WriteAsync"]) and
|
||||
stream = mc.getQualifier() and
|
||||
data = mc.getArgument(0)
|
||||
or
|
||||
m.hasQualifiedName("System.IO", "TextWriter",
|
||||
["Write", "WriteAsync", "WriteLine", "WriteLineAsync"]) and
|
||||
stream = mc.getQualifier() and
|
||||
data = mc.getArgument(0)
|
||||
or
|
||||
m.hasQualifiedName("System.Xml.Linq", "XDocument", ["Save", "SaveAsync"]) and
|
||||
data = mc.getQualifier() and
|
||||
stream = mc.getArgument(0)
|
||||
)
|
||||
}
|
||||
|
||||
/** A configuration for tracking flow from calls that open a file in write mode to methods that write to that file, excluding encrypted streams. */
|
||||
private module LocalFileOutputStreamConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node src) { sourceNode(src, "file-write") }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { isFileWriteCall(sink.asExpr(), _) }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
node.asExpr()
|
||||
.(ObjectCreation)
|
||||
.getObjectType()
|
||||
.hasQualifiedName("System.Security.Cryptography", "CryptoStream")
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(ObjectCreation oc |
|
||||
node2.asExpr() = oc and
|
||||
node1.asExpr() = oc.getArgument(0) and
|
||||
oc.getObjectType() instanceof SystemIOStreamWriterClass
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private module LocalFileOutputStreamFlow = DataFlow::Global<LocalFileOutputStreamConfig>;
|
||||
|
||||
/**
|
||||
* A write to the local filesystem.
|
||||
*/
|
||||
class LocalFileOutputSink extends ExternalLocationSink {
|
||||
LocalFileOutputSink() {
|
||||
exists(DataFlow::Node streamSink |
|
||||
LocalFileOutputStreamFlow::flowTo(streamSink) and
|
||||
isFileWriteCall(streamSink.asExpr(), this.asExpr())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,18 +16,21 @@ import csharp
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Stored
|
||||
import semmle.code.csharp.security.dataflow.XSSQuery
|
||||
import semmle.code.csharp.security.dataflow.XSSSinks
|
||||
import semmle.code.csharp.dataflow.DataFlow2
|
||||
import DataFlow2::PathGraph
|
||||
import StoredXss::PathGraph
|
||||
|
||||
class StoredTaintTrackingConfiguration extends TaintTrackingConfiguration {
|
||||
override predicate isSource(DataFlow2::Node source) { source instanceof StoredFlowSource }
|
||||
module StoredXssTrackingConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof StoredFlowSource }
|
||||
|
||||
predicate isSink = XssTrackingConfig::isSink/1;
|
||||
|
||||
predicate isBarrier = XssTrackingConfig::isBarrier/1;
|
||||
}
|
||||
|
||||
from
|
||||
StoredTaintTrackingConfiguration c, DataFlow2::PathNode source, DataFlow2::PathNode sink,
|
||||
string explanation
|
||||
module StoredXss = TaintTracking::Global<StoredXssTrackingConfig>;
|
||||
|
||||
from StoredXss::PathNode source, StoredXss::PathNode sink, string explanation
|
||||
where
|
||||
c.hasFlowPath(source, sink) and
|
||||
StoredXss::flowPath(source, sink) and
|
||||
if exists(sink.getNode().(Sink).explanation())
|
||||
then explanation = " (" + sink.getNode().(Sink).explanation() + ")"
|
||||
else explanation = ""
|
||||
|
||||
@@ -20,57 +20,46 @@ import semmle.code.csharp.security.dataflow.SqlInjectionQuery as SqlInjection
|
||||
import semmle.code.csharp.security.dataflow.flowsinks.Html
|
||||
import semmle.code.csharp.security.dataflow.UrlRedirectQuery as UrlRedirect
|
||||
import semmle.code.csharp.security.Sanitizers
|
||||
import semmle.code.csharp.dataflow.DataFlow2::DataFlow2
|
||||
import semmle.code.csharp.dataflow.DataFlow2::DataFlow2::PathGraph
|
||||
import semmle.code.csharp.dataflow.TaintTracking2
|
||||
import EncodingConfigurations::Flow::PathGraph
|
||||
|
||||
/**
|
||||
* A configuration for specifying expressions that must be
|
||||
* encoded, along with a set of potential valid encoded values.
|
||||
*/
|
||||
abstract class RequiresEncodingConfiguration extends TaintTracking2::Configuration {
|
||||
bindingset[this]
|
||||
RequiresEncodingConfiguration() { any() }
|
||||
|
||||
/** Gets a textual representation of this kind of encoding requirement. */
|
||||
abstract string getKind();
|
||||
|
||||
/** Holds if `e` is an expression whose value must be encoded. */
|
||||
abstract predicate requiresEncoding(Node n);
|
||||
signature module EncodingConfigSig {
|
||||
/** Holds if `n` is a node whose value must be encoded. */
|
||||
predicate requiresEncoding(DataFlow::Node n);
|
||||
|
||||
/** Holds if `e` is a possible valid encoded value. */
|
||||
predicate isPossibleEncodedValue(Expr e) { none() }
|
||||
predicate isPossibleEncodedValue(Expr e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `encodedValue` is a possibly ill-encoded value that reaches
|
||||
* `sink`, where `sink` is an expression of kind `kind` that is required
|
||||
* to be encoded.
|
||||
*/
|
||||
predicate hasWrongEncoding(PathNode encodedValue, PathNode sink, string kind) {
|
||||
this.hasFlowPath(encodedValue, sink) and
|
||||
kind = this.getKind()
|
||||
}
|
||||
|
||||
override predicate isSource(Node source) {
|
||||
/**
|
||||
* A configuration for specifying expressions that must be encoded.
|
||||
*/
|
||||
module RequiresEncodingConfig<EncodingConfigSig EncodingConfig> implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
// all encoded values that do not match this configuration are
|
||||
// considered sources
|
||||
exists(Expr e | e = source.asExpr() |
|
||||
e instanceof EncodedValue and
|
||||
not this.isPossibleEncodedValue(e)
|
||||
not EncodingConfig::isPossibleEncodedValue(e)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSink(Node sink) { this.requiresEncoding(sink) }
|
||||
predicate isSink(DataFlow::Node sink) { EncodingConfig::requiresEncoding(sink) }
|
||||
|
||||
override predicate isSanitizer(Node sanitizer) { this.isPossibleEncodedValue(sanitizer.asExpr()) }
|
||||
predicate isBarrier(DataFlow::Node sanitizer) {
|
||||
EncodingConfig::isPossibleEncodedValue(sanitizer.asExpr())
|
||||
}
|
||||
|
||||
override int fieldFlowBranchLimit() { result = 0 }
|
||||
int fieldFlowBranchLimit() { result = 0 }
|
||||
}
|
||||
|
||||
/** An encoded value, for example a call to `HttpServerUtility.HtmlEncode`. */
|
||||
/** An encoded value, for example through a call to `HttpServerUtility.HtmlEncode`. */
|
||||
class EncodedValue extends Expr {
|
||||
EncodedValue() {
|
||||
any(RequiresEncodingConfiguration c).isPossibleEncodedValue(this)
|
||||
EncodingConfigurations::SqlExprEncodingConfig::isPossibleEncodedValue(this)
|
||||
or
|
||||
EncodingConfigurations::HtmlExprEncodingConfig::isPossibleEncodedValue(this)
|
||||
or
|
||||
EncodingConfigurations::UrlExprEncodingConfig::isPossibleEncodedValue(this)
|
||||
or
|
||||
this = any(SystemWebHttpUtility c).getAJavaScriptStringEncodeMethod().getACall()
|
||||
or
|
||||
@@ -86,18 +75,20 @@ class EncodedValue extends Expr {
|
||||
}
|
||||
|
||||
module EncodingConfigurations {
|
||||
module SqlExprEncodingConfig implements EncodingConfigSig {
|
||||
predicate requiresEncoding(DataFlow::Node n) { n instanceof SqlInjection::Sink }
|
||||
|
||||
predicate isPossibleEncodedValue(Expr e) { none() }
|
||||
}
|
||||
|
||||
/** An encoding configuration for SQL expressions. */
|
||||
class SqlExpr extends RequiresEncodingConfiguration {
|
||||
SqlExpr() { this = "SqlExpr" }
|
||||
|
||||
override string getKind() { result = "SQL expression" }
|
||||
|
||||
override predicate requiresEncoding(Node n) { n instanceof SqlInjection::Sink }
|
||||
module SqlExprConfig implements DataFlow::ConfigSig {
|
||||
import RequiresEncodingConfig<SqlExprEncodingConfig> as Super
|
||||
|
||||
// no override for `isPossibleEncodedValue` as SQL parameters should
|
||||
// be used instead of explicit encoding
|
||||
override predicate isSource(Node source) {
|
||||
super.isSource(source)
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
Super::isSource(source)
|
||||
or
|
||||
// consider quote-replacing calls as additional sources for
|
||||
// SQL expressions (e.g., `s.Replace("\"", "\"\"")`)
|
||||
@@ -107,32 +98,62 @@ module EncodingConfigurations {
|
||||
mc.getArgument(0).getValue().regexpMatch("\"|'|`")
|
||||
)
|
||||
}
|
||||
|
||||
predicate isSink = Super::isSink/1;
|
||||
|
||||
predicate isBarrier = Super::isBarrier/1;
|
||||
|
||||
int fieldFlowBranchLimit() { result = Super::fieldFlowBranchLimit() }
|
||||
}
|
||||
|
||||
module SqlExpr = TaintTracking::Global<SqlExprConfig>;
|
||||
|
||||
module HtmlExprEncodingConfig implements EncodingConfigSig {
|
||||
predicate requiresEncoding(DataFlow::Node n) { n instanceof HtmlSink }
|
||||
|
||||
predicate isPossibleEncodedValue(Expr e) { e instanceof HtmlSanitizedExpr }
|
||||
}
|
||||
|
||||
/** An encoding configuration for HTML expressions. */
|
||||
class HtmlExpr extends RequiresEncodingConfiguration {
|
||||
HtmlExpr() { this = "HtmlExpr" }
|
||||
module HtmlExprConfig = RequiresEncodingConfig<HtmlExprEncodingConfig>;
|
||||
|
||||
override string getKind() { result = "HTML expression" }
|
||||
module HtmlExpr = TaintTracking::Global<HtmlExprConfig>;
|
||||
|
||||
override predicate requiresEncoding(Node n) { n instanceof HtmlSink }
|
||||
module UrlExprEncodingConfig implements EncodingConfigSig {
|
||||
predicate requiresEncoding(DataFlow::Node n) { n instanceof UrlRedirect::Sink }
|
||||
|
||||
override predicate isPossibleEncodedValue(Expr e) { e instanceof HtmlSanitizedExpr }
|
||||
predicate isPossibleEncodedValue(Expr e) { e instanceof UrlSanitizedExpr }
|
||||
}
|
||||
|
||||
/** An encoding configuration for URL expressions. */
|
||||
class UrlExpr extends RequiresEncodingConfiguration {
|
||||
UrlExpr() { this = "UrlExpr" }
|
||||
module UrlExprConfig = RequiresEncodingConfig<UrlExprEncodingConfig>;
|
||||
|
||||
override string getKind() { result = "URL expression" }
|
||||
module UrlExpr = TaintTracking::Global<UrlExprConfig>;
|
||||
|
||||
override predicate requiresEncoding(Node n) { n instanceof UrlRedirect::Sink }
|
||||
module Flow =
|
||||
DataFlow::MergePathGraph3<SqlExpr::PathNode, HtmlExpr::PathNode, UrlExpr::PathNode,
|
||||
SqlExpr::PathGraph, HtmlExpr::PathGraph, UrlExpr::PathGraph>;
|
||||
|
||||
override predicate isPossibleEncodedValue(Expr e) { e instanceof UrlSanitizedExpr }
|
||||
/**
|
||||
* Holds if `encodedValue` is a possibly ill-encoded value that reaches
|
||||
* `sink`, where `sink` is an expression of kind `kind` that is required
|
||||
* to be encoded.
|
||||
*/
|
||||
predicate hasWrongEncoding(Flow::PathNode encodedValue, Flow::PathNode sink, string kind) {
|
||||
SqlExpr::flowPath(encodedValue.asPathNode1(), sink.asPathNode1()) and
|
||||
kind = "SQL expression"
|
||||
or
|
||||
HtmlExpr::flowPath(encodedValue.asPathNode2(), sink.asPathNode2()) and
|
||||
kind = "HTML expression"
|
||||
or
|
||||
UrlExpr::flowPath(encodedValue.asPathNode3(), sink.asPathNode3()) and
|
||||
kind = "URL expression"
|
||||
}
|
||||
}
|
||||
|
||||
from RequiresEncodingConfiguration c, PathNode encodedValue, PathNode sink, string kind
|
||||
where c.hasWrongEncoding(encodedValue, sink, kind)
|
||||
from
|
||||
EncodingConfigurations::Flow::PathNode encodedValue, EncodingConfigurations::Flow::PathNode sink,
|
||||
string kind
|
||||
where EncodingConfigurations::hasWrongEncoding(encodedValue, sink, kind)
|
||||
select sink.getNode(), encodedValue, sink, "This " + kind + " may include data from a $@.",
|
||||
encodedValue.getNode(), "possibly inappropriately encoded value"
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Additional sinks modelling writes to unencrypted local files have been added to `ExternalLocationSink`, used by the `cs/cleartext-storage` and `cs/exposure-of-sensitive-information` queries.
|
||||
@@ -19,6 +19,9 @@ newtype TInstruction =
|
||||
) {
|
||||
IRConstruction::Raw::hasInstruction(tag1, tag2)
|
||||
} or
|
||||
TRawUnreachedInstruction(IRFunctionBase irFunc) {
|
||||
IRConstruction::hasUnreachedInstruction(irFunc)
|
||||
} or
|
||||
TUnaliasedSsaPhiInstruction(
|
||||
TRawInstruction blockStartInstr, UnaliasedSsa::Ssa::MemoryLocation memoryLocation
|
||||
) {
|
||||
|
||||
@@ -414,6 +414,8 @@ private module Cached {
|
||||
}
|
||||
}
|
||||
|
||||
predicate hasUnreachedInstruction(IRFunction func) { none() }
|
||||
|
||||
import CachedForDebugging
|
||||
|
||||
cached
|
||||
|
||||
@@ -34,9 +34,13 @@ private module Cached {
|
||||
|
||||
cached
|
||||
predicate hasUnreachedInstructionCached(IRFunction irFunc) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
exists(OldIR::Instruction oldInstruction |
|
||||
irFunc = oldInstruction.getEnclosingIRFunction() and
|
||||
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _)
|
||||
(
|
||||
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _)
|
||||
or
|
||||
oldInstruction.getOpcode() instanceof Opcode::Unreached
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -366,21 +370,19 @@ private module Cached {
|
||||
then
|
||||
result = getChi(getOldInstruction(instruction)) and
|
||||
kind instanceof GotoEdge
|
||||
else (
|
||||
else
|
||||
exists(OldInstruction oldInstruction |
|
||||
oldInstruction = getOldInstruction(instruction) and
|
||||
(
|
||||
oldInstruction = getOldInstruction(instruction)
|
||||
or
|
||||
instruction = getChi(oldInstruction)
|
||||
) and
|
||||
(
|
||||
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind)
|
||||
then result = unreachedInstruction(instruction.getEnclosingIRFunction())
|
||||
else result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(OldInstruction oldInstruction |
|
||||
instruction = getChi(oldInstruction) and
|
||||
result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
|
||||
@@ -2,6 +2,8 @@ using System.Text;
|
||||
using System.Web;
|
||||
using System.Web.Security;
|
||||
using System.Windows.Forms;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
public class ClearTextStorageHandler : IHttpHandler
|
||||
{
|
||||
@@ -24,6 +26,22 @@ public class ClearTextStorageHandler : IHttpHandler
|
||||
logger.Warn(GetPassword());
|
||||
// GOOD: Logging encrypted sensitive data
|
||||
logger.Warn(Encode(GetPassword(), "Password"));
|
||||
|
||||
// BAD: Storing sensitive data in local file
|
||||
using (var writeStream = File.Open("passwords.txt", FileMode.Create))
|
||||
{
|
||||
var writer = new StreamWriter(writeStream);
|
||||
writer.Write(GetPassword());
|
||||
writer.Close();
|
||||
}
|
||||
|
||||
// GOOD: Storing encrypted sensitive data
|
||||
using (var writeStream = File.Open("passwords.txt", FileMode.Create))
|
||||
{
|
||||
var writer = new StreamWriter(new CryptoStream(writeStream, GetEncryptor(), CryptoStreamMode.Write));
|
||||
writer.Write(GetPassword());
|
||||
writer.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public string Encode(string value, string type)
|
||||
@@ -31,6 +49,10 @@ public class ClearTextStorageHandler : IHttpHandler
|
||||
return Encoding.UTF8.GetString(MachineKey.Protect(Encoding.UTF8.GetBytes(value), type));
|
||||
}
|
||||
|
||||
public ICryptoTransform GetEncryptor(){
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetPassword()
|
||||
{
|
||||
return "password";
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
edges
|
||||
nodes
|
||||
| CleartextStorage.cs:13:50:13:59 | access to field accountKey | semmle.label | access to field accountKey |
|
||||
| CleartextStorage.cs:14:62:14:74 | call to method GetPassword | semmle.label | call to method GetPassword |
|
||||
| CleartextStorage.cs:15:69:15:81 | call to method GetPassword | semmle.label | call to method GetPassword |
|
||||
| CleartextStorage.cs:16:50:16:63 | call to method GetAccountID | semmle.label | call to method GetAccountID |
|
||||
| CleartextStorage.cs:24:21:24:33 | call to method GetPassword | semmle.label | call to method GetPassword |
|
||||
| CleartextStorage.cs:72:21:72:33 | access to property Text | semmle.label | access to property Text |
|
||||
| CleartextStorage.cs:73:21:73:29 | access to property Text | semmle.label | access to property Text |
|
||||
| CleartextStorage.cs:74:21:74:29 | access to property Text | semmle.label | access to property Text |
|
||||
| CleartextStorage.cs:15:50:15:59 | access to field accountKey | semmle.label | access to field accountKey |
|
||||
| CleartextStorage.cs:16:62:16:74 | call to method GetPassword | semmle.label | call to method GetPassword |
|
||||
| CleartextStorage.cs:17:69:17:81 | call to method GetPassword | semmle.label | call to method GetPassword |
|
||||
| CleartextStorage.cs:18:50:18:63 | call to method GetAccountID | semmle.label | call to method GetAccountID |
|
||||
| CleartextStorage.cs:26:21:26:33 | call to method GetPassword | semmle.label | call to method GetPassword |
|
||||
| CleartextStorage.cs:34:26:34:38 | call to method GetPassword | semmle.label | call to method GetPassword |
|
||||
| CleartextStorage.cs:94:21:94:33 | access to property Text | semmle.label | access to property Text |
|
||||
| CleartextStorage.cs:95:21:95:29 | access to property Text | semmle.label | access to property Text |
|
||||
| CleartextStorage.cs:96:21:96:29 | access to property Text | semmle.label | access to property Text |
|
||||
subpaths
|
||||
#select
|
||||
| CleartextStorage.cs:13:50:13:59 | access to field accountKey | CleartextStorage.cs:13:50:13:59 | access to field accountKey | CleartextStorage.cs:13:50:13:59 | access to field accountKey | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:13:50:13:59 | access to field accountKey | access to field accountKey |
|
||||
| CleartextStorage.cs:14:62:14:74 | call to method GetPassword | CleartextStorage.cs:14:62:14:74 | call to method GetPassword | CleartextStorage.cs:14:62:14:74 | call to method GetPassword | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:14:62:14:74 | call to method GetPassword | call to method GetPassword |
|
||||
| CleartextStorage.cs:15:69:15:81 | call to method GetPassword | CleartextStorage.cs:15:69:15:81 | call to method GetPassword | CleartextStorage.cs:15:69:15:81 | call to method GetPassword | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:15:69:15:81 | call to method GetPassword | call to method GetPassword |
|
||||
| CleartextStorage.cs:16:50:16:63 | call to method GetAccountID | CleartextStorage.cs:16:50:16:63 | call to method GetAccountID | CleartextStorage.cs:16:50:16:63 | call to method GetAccountID | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:16:50:16:63 | call to method GetAccountID | call to method GetAccountID |
|
||||
| CleartextStorage.cs:24:21:24:33 | call to method GetPassword | CleartextStorage.cs:24:21:24:33 | call to method GetPassword | CleartextStorage.cs:24:21:24:33 | call to method GetPassword | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:24:21:24:33 | call to method GetPassword | call to method GetPassword |
|
||||
| CleartextStorage.cs:72:21:72:33 | access to property Text | CleartextStorage.cs:72:21:72:33 | access to property Text | CleartextStorage.cs:72:21:72:33 | access to property Text | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:72:21:72:33 | access to property Text | access to property Text |
|
||||
| CleartextStorage.cs:73:21:73:29 | access to property Text | CleartextStorage.cs:73:21:73:29 | access to property Text | CleartextStorage.cs:73:21:73:29 | access to property Text | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:73:21:73:29 | access to property Text | access to property Text |
|
||||
| CleartextStorage.cs:74:21:74:29 | access to property Text | CleartextStorage.cs:74:21:74:29 | access to property Text | CleartextStorage.cs:74:21:74:29 | access to property Text | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:74:21:74:29 | access to property Text | access to property Text |
|
||||
| CleartextStorage.cs:15:50:15:59 | access to field accountKey | CleartextStorage.cs:15:50:15:59 | access to field accountKey | CleartextStorage.cs:15:50:15:59 | access to field accountKey | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:15:50:15:59 | access to field accountKey | access to field accountKey |
|
||||
| CleartextStorage.cs:16:62:16:74 | call to method GetPassword | CleartextStorage.cs:16:62:16:74 | call to method GetPassword | CleartextStorage.cs:16:62:16:74 | call to method GetPassword | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:16:62:16:74 | call to method GetPassword | call to method GetPassword |
|
||||
| CleartextStorage.cs:17:69:17:81 | call to method GetPassword | CleartextStorage.cs:17:69:17:81 | call to method GetPassword | CleartextStorage.cs:17:69:17:81 | call to method GetPassword | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:17:69:17:81 | call to method GetPassword | call to method GetPassword |
|
||||
| CleartextStorage.cs:18:50:18:63 | call to method GetAccountID | CleartextStorage.cs:18:50:18:63 | call to method GetAccountID | CleartextStorage.cs:18:50:18:63 | call to method GetAccountID | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:18:50:18:63 | call to method GetAccountID | call to method GetAccountID |
|
||||
| CleartextStorage.cs:26:21:26:33 | call to method GetPassword | CleartextStorage.cs:26:21:26:33 | call to method GetPassword | CleartextStorage.cs:26:21:26:33 | call to method GetPassword | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:26:21:26:33 | call to method GetPassword | call to method GetPassword |
|
||||
| CleartextStorage.cs:34:26:34:38 | call to method GetPassword | CleartextStorage.cs:34:26:34:38 | call to method GetPassword | CleartextStorage.cs:34:26:34:38 | call to method GetPassword | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:34:26:34:38 | call to method GetPassword | call to method GetPassword |
|
||||
| CleartextStorage.cs:94:21:94:33 | access to property Text | CleartextStorage.cs:94:21:94:33 | access to property Text | CleartextStorage.cs:94:21:94:33 | access to property Text | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:94:21:94:33 | access to property Text | access to property Text |
|
||||
| CleartextStorage.cs:95:21:95:29 | access to property Text | CleartextStorage.cs:95:21:95:29 | access to property Text | CleartextStorage.cs:95:21:95:29 | access to property Text | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:95:21:95:29 | access to property Text | access to property Text |
|
||||
| CleartextStorage.cs:96:21:96:29 | access to property Text | CleartextStorage.cs:96:21:96:29 | access to property Text | CleartextStorage.cs:96:21:96:29 | access to property Text | This stores sensitive data returned by $@ as clear text. | CleartextStorage.cs:96:21:96:29 | access to property Text | access to property Text |
|
||||
|
||||
@@ -1 +1 @@
|
||||
semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs /r:System.Collections.Specialized.dll {testdir}/../../../../resources/stubs/System.Windows.cs
|
||||
semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs /r:System.Collections.Specialized.dll /r:System.Security.Cryptography.dll {testdir}/../../../../resources/stubs/System.Windows.cs
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System.Web;
|
||||
using System.Security.Cryptography;
|
||||
using System.IO;
|
||||
|
||||
public class Person
|
||||
{
|
||||
@@ -21,9 +23,29 @@ public class ExposureOfPrivateInformationHandler : IHttpHandler
|
||||
ILogger logger = new ILogger();
|
||||
logger.Warn(p.getTelephone());
|
||||
|
||||
// BAD: Storing sensitive data in unencrypted local file
|
||||
using (var writeStream = File.Open("telephones.txt", FileMode.Create))
|
||||
{
|
||||
var writer = new StreamWriter(writeStream);
|
||||
writer.Write(p.getTelephone());
|
||||
writer.Close();
|
||||
}
|
||||
|
||||
// GOOD: Storing encrypted sensitive data
|
||||
using (var writeStream = File.Open("telephones.txt", FileMode.Create))
|
||||
{
|
||||
var writer = new StreamWriter(new CryptoStream(writeStream, GetEncryptor(), CryptoStreamMode.Write));
|
||||
writer.Write(p.getTelephone());
|
||||
writer.Close();
|
||||
}
|
||||
|
||||
// GOOD: Don't write these values to sensitive locations in the first place
|
||||
}
|
||||
|
||||
public ICryptoTransform GetEncryptor(){
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool IsReusable
|
||||
{
|
||||
get
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
edges
|
||||
nodes
|
||||
| ExposureOfPrivateInformation.cs:16:50:16:84 | access to indexer | semmle.label | access to indexer |
|
||||
| ExposureOfPrivateInformation.cs:18:50:18:65 | call to method getTelephone | semmle.label | call to method getTelephone |
|
||||
| ExposureOfPrivateInformation.cs:22:21:22:36 | call to method getTelephone | semmle.label | call to method getTelephone |
|
||||
| ExposureOfPrivateInformation.cs:40:21:40:33 | access to property Text | semmle.label | access to property Text |
|
||||
| ExposureOfPrivateInformation.cs:18:50:18:84 | access to indexer | semmle.label | access to indexer |
|
||||
| ExposureOfPrivateInformation.cs:20:50:20:65 | call to method getTelephone | semmle.label | call to method getTelephone |
|
||||
| ExposureOfPrivateInformation.cs:24:21:24:36 | call to method getTelephone | semmle.label | call to method getTelephone |
|
||||
| ExposureOfPrivateInformation.cs:30:26:30:41 | call to method getTelephone | semmle.label | call to method getTelephone |
|
||||
| ExposureOfPrivateInformation.cs:62:21:62:33 | access to property Text | semmle.label | access to property Text |
|
||||
subpaths
|
||||
#select
|
||||
| ExposureOfPrivateInformation.cs:16:50:16:84 | access to indexer | ExposureOfPrivateInformation.cs:16:50:16:84 | access to indexer | ExposureOfPrivateInformation.cs:16:50:16:84 | access to indexer | Private data returned by $@ is written to an external location. | ExposureOfPrivateInformation.cs:16:50:16:84 | access to indexer | access to indexer |
|
||||
| ExposureOfPrivateInformation.cs:18:50:18:65 | call to method getTelephone | ExposureOfPrivateInformation.cs:18:50:18:65 | call to method getTelephone | ExposureOfPrivateInformation.cs:18:50:18:65 | call to method getTelephone | Private data returned by $@ is written to an external location. | ExposureOfPrivateInformation.cs:18:50:18:65 | call to method getTelephone | call to method getTelephone |
|
||||
| ExposureOfPrivateInformation.cs:22:21:22:36 | call to method getTelephone | ExposureOfPrivateInformation.cs:22:21:22:36 | call to method getTelephone | ExposureOfPrivateInformation.cs:22:21:22:36 | call to method getTelephone | Private data returned by $@ is written to an external location. | ExposureOfPrivateInformation.cs:22:21:22:36 | call to method getTelephone | call to method getTelephone |
|
||||
| ExposureOfPrivateInformation.cs:40:21:40:33 | access to property Text | ExposureOfPrivateInformation.cs:40:21:40:33 | access to property Text | ExposureOfPrivateInformation.cs:40:21:40:33 | access to property Text | Private data returned by $@ is written to an external location. | ExposureOfPrivateInformation.cs:40:21:40:33 | access to property Text | access to property Text |
|
||||
| ExposureOfPrivateInformation.cs:18:50:18:84 | access to indexer | ExposureOfPrivateInformation.cs:18:50:18:84 | access to indexer | ExposureOfPrivateInformation.cs:18:50:18:84 | access to indexer | Private data returned by $@ is written to an external location. | ExposureOfPrivateInformation.cs:18:50:18:84 | access to indexer | access to indexer |
|
||||
| ExposureOfPrivateInformation.cs:20:50:20:65 | call to method getTelephone | ExposureOfPrivateInformation.cs:20:50:20:65 | call to method getTelephone | ExposureOfPrivateInformation.cs:20:50:20:65 | call to method getTelephone | Private data returned by $@ is written to an external location. | ExposureOfPrivateInformation.cs:20:50:20:65 | call to method getTelephone | call to method getTelephone |
|
||||
| ExposureOfPrivateInformation.cs:24:21:24:36 | call to method getTelephone | ExposureOfPrivateInformation.cs:24:21:24:36 | call to method getTelephone | ExposureOfPrivateInformation.cs:24:21:24:36 | call to method getTelephone | Private data returned by $@ is written to an external location. | ExposureOfPrivateInformation.cs:24:21:24:36 | call to method getTelephone | call to method getTelephone |
|
||||
| ExposureOfPrivateInformation.cs:30:26:30:41 | call to method getTelephone | ExposureOfPrivateInformation.cs:30:26:30:41 | call to method getTelephone | ExposureOfPrivateInformation.cs:30:26:30:41 | call to method getTelephone | Private data returned by $@ is written to an external location. | ExposureOfPrivateInformation.cs:30:26:30:41 | call to method getTelephone | call to method getTelephone |
|
||||
| ExposureOfPrivateInformation.cs:62:21:62:33 | access to property Text | ExposureOfPrivateInformation.cs:62:21:62:33 | access to property Text | ExposureOfPrivateInformation.cs:62:21:62:33 | access to property Text | Private data returned by $@ is written to an external location. | ExposureOfPrivateInformation.cs:62:21:62:33 | access to property Text | access to property Text |
|
||||
|
||||
@@ -1 +1 @@
|
||||
semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs /r:System.Collections.Specialized.dll ${testdir}/../../../resources/stubs/System.Windows.cs
|
||||
semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs /r:System.Collections.Specialized.dll /r:System.Security.Cryptography.dll ${testdir}/../../../resources/stubs/System.Windows.cs
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
CodeQL query help
|
||||
-----------------
|
||||
|
||||
View the query help for the queries included in the ``code-scanning``, ``security-extended``, and ``security-and-quality`` query suites for the languages supported by CodeQL.
|
||||
View the query help for the queries included in the ``default``, ``security-extended``, and ``security-and-quality`` query suites for the languages supported by CodeQL.
|
||||
|
||||
- :doc:`CodeQL query help for C and C++ <cpp>`
|
||||
- :doc:`CodeQL query help for C# <csharp>`
|
||||
@@ -15,20 +15,20 @@ View the query help for the queries included in the ``code-scanning``, ``securit
|
||||
|
||||
.. pull-quote:: Information
|
||||
|
||||
Each query help article includes:
|
||||
|
||||
Each query help article includes:
|
||||
|
||||
- A summary of key metadata for the query.
|
||||
- Information about which query suites the query is included in.
|
||||
- A link to the query in the `CodeQL repository <https://github.com/github/codeql>`__.
|
||||
- A description of the potential vulnerability that the query identifies and a recommendation for how to avoid introducing the problem to your code.
|
||||
|
||||
|
||||
For a full list of the CWEs covered by these queries, see ":doc:`CodeQL CWE coverage <codeql-cwe-coverage>`."
|
||||
For a full list of the CWEs covered by these queries, see ":doc:`CodeQL CWE coverage <codeql-cwe-coverage>`."
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
:titlesonly:
|
||||
|
||||
|
||||
cpp
|
||||
csharp
|
||||
go
|
||||
@@ -37,4 +37,3 @@ For a full list of the CWEs covered by these queries, see ":doc:`CodeQL CWE cove
|
||||
python
|
||||
ruby
|
||||
codeql-cwe-coverage
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Visit the articles below to see the documentation for the queries included in the following query suites:
|
||||
|
||||
- ``code-scanning``: queries run by default in CodeQL code scanning on GitHub.
|
||||
- ``security-extended``: queries from ``code-scanning``, plus extra security queries with slightly lower precision and severity.
|
||||
- ``security-and-quality``: queries from ``code-scanning``, ``security-extended``, plus extra maintainability and reliability queries.
|
||||
- ``default``: queries run by default in CodeQL code scanning on GitHub.
|
||||
- ``security-extended``: queries from ``default``, plus extra security queries with slightly lower precision and severity.
|
||||
- ``security-and-quality``: queries from ``default``, ``security-extended``, plus extra maintainability and reliability queries.
|
||||
|
||||
@@ -318,7 +318,7 @@ func getNeedGopath(depMode DependencyInstallerMode, importpath string) bool {
|
||||
|
||||
func tryUpdateGoModAndGoSum(modMode ModMode, depMode DependencyInstallerMode) {
|
||||
// Go 1.16 and later won't automatically attempt to update go.mod / go.sum during package loading, so try to update them here:
|
||||
if modMode != ModVendor && depMode == GoGetWithModules && semver.Compare(getEnvGoSemVer(), "1.16") >= 0 {
|
||||
if modMode != ModVendor && depMode == GoGetWithModules && semver.Compare(getEnvGoSemVer(), "v1.16") >= 0 {
|
||||
// stat go.mod and go.sum
|
||||
beforeGoModFileInfo, beforeGoModErr := os.Stat("go.mod")
|
||||
if beforeGoModErr != nil {
|
||||
|
||||
@@ -361,3 +361,52 @@ module MergePathGraph<
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a `PathGraph` from three `PathGraph`s by disjoint union.
|
||||
*/
|
||||
module MergePathGraph3<
|
||||
PathNodeSig PathNode1, PathNodeSig PathNode2, PathNodeSig PathNode3,
|
||||
PathGraphSig<PathNode1> Graph1, PathGraphSig<PathNode2> Graph2, PathGraphSig<PathNode3> Graph3>
|
||||
{
|
||||
private module MergedInner = MergePathGraph<PathNode1, PathNode2, Graph1, Graph2>;
|
||||
|
||||
private module Merged =
|
||||
MergePathGraph<MergedInner::PathNode, PathNode3, MergedInner::PathGraph, Graph3>;
|
||||
|
||||
/** A node in a graph of path explanations that is formed by disjoint union of the three given graphs. */
|
||||
class PathNode instanceof Merged::PathNode {
|
||||
/** Gets this as a projection on the first given `PathGraph`. */
|
||||
PathNode1 asPathNode1() { result = super.asPathNode1().asPathNode1() }
|
||||
|
||||
/** Gets this as a projection on the second given `PathGraph`. */
|
||||
PathNode2 asPathNode2() { result = super.asPathNode1().asPathNode2() }
|
||||
|
||||
/** Gets this as a projection on the third given `PathGraph`. */
|
||||
PathNode3 asPathNode3() { result = super.asPathNode2() }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets the underlying `Node`. */
|
||||
Node getNode() { result = super.getNode() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the query predicates needed to include a graph in a path-problem query.
|
||||
*/
|
||||
module PathGraph = Merged::PathGraph;
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ 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.util,3,,142,,2,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,90,52
|
||||
org.springframework.validation,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,13,
|
||||
org.springframework.web.client,13,3,,,,,,,,,,,,,,,,13,,,,,,,,,,,,,,,,,,,,,,3,,
|
||||
org.springframework.web.context.request,,8,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,8,,
|
||||
|
||||
|
@@ -21,7 +21,7 @@ Java framework & library support
|
||||
Java Standard Library,``java.*``,3,673,168,39,,,9,,,13
|
||||
Java extensions,"``javax.*``, ``jakarta.*``",63,611,34,1,,4,,1,1,2
|
||||
Kotlin Standard Library,``kotlin*``,,1843,16,11,,,,,,2
|
||||
`Spring <https://spring.io/>`_,``org.springframework.*``,29,480,101,,,,19,14,,29
|
||||
`Spring <https://spring.io/>`_,``org.springframework.*``,29,483,104,2,,,19,14,,29
|
||||
Others,"``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.hubspot.jinjava``, ``com.mitchellbosecke.pebble``, ``com.opensymphony.xwork2.ognl``, ``com.rabbitmq.client``, ``com.thoughtworks.xstream``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``freemarker.cache``, ``freemarker.template``, ``groovy.lang``, ``groovy.util``, ``hudson``, ``io.netty.bootstrap``, ``io.netty.buffer``, ``io.netty.channel``, ``io.netty.handler.codec``, ``io.netty.handler.ssl``, ``io.netty.handler.stream``, ``io.netty.resolver``, ``io.netty.util``, ``javafx.scene.web``, ``jodd.json``, ``net.sf.saxon.s9api``, ``ognl``, ``okhttp3``, ``org.apache.commons.codec``, ``org.apache.commons.compress.archivers.tar``, ``org.apache.commons.httpclient.util``, ``org.apache.commons.jelly``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.logging``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.hadoop.hive.metastore``, ``org.apache.hc.client5.http.async.methods``, ``org.apache.hc.client5.http.classic.methods``, ``org.apache.hc.client5.http.fluent``, ``org.apache.hive.hcatalog.templeton``, ``org.apache.ibatis.jdbc``, ``org.apache.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.apache.tools.ant``, ``org.apache.tools.zip``, ``org.apache.velocity.app``, ``org.apache.velocity.runtime``, ``org.codehaus.cargo.container.installer``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.eclipse.jetty.client``, ``org.geogebra.web.full.main``, ``org.hibernate``, ``org.jdbi.v3.core``, ``org.jooq``, ``org.kohsuke.stapler``, ``org.mvel2``, ``org.openjdk.jmh.runner.options``, ``org.scijava.log``, ``org.slf4j``, ``org.thymeleaf``, ``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``, ``retrofit2``",75,813,506,26,,,18,18,,175
|
||||
Totals,,232,9096,1951,172,6,10,113,33,1,355
|
||||
Totals,,232,9099,1954,174,6,10,113,33,1,355
|
||||
|
||||
|
||||
@@ -3,22 +3,22 @@ import semmle.code.java.dataflow.TaintTracking
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
class Config extends TaintTracking::Configuration {
|
||||
Config() { this = "Config" }
|
||||
|
||||
override predicate isSource(DataFlow::Node n) {
|
||||
module Config implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node n) {
|
||||
n.asExpr().(MethodAccess).getCallee().getName() = "source"
|
||||
or
|
||||
sourceNode(n, "kotlinMadFlowTest")
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node n) {
|
||||
predicate isSink(DataFlow::Node n) {
|
||||
n.asExpr().(Argument).getCall().getCallee().getName() = "sink"
|
||||
or
|
||||
sinkNode(n, "kotlinMadFlowTest")
|
||||
}
|
||||
}
|
||||
|
||||
module Flow = TaintTracking::Global<Config>;
|
||||
|
||||
class InlineFlowTest extends InlineExpectationsTest {
|
||||
InlineFlowTest() { this = "HasFlowTest" }
|
||||
|
||||
@@ -26,7 +26,7 @@ class InlineFlowTest extends InlineExpectationsTest {
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
tag = "flow" and
|
||||
exists(DataFlow::Node sink, Config c | c.hasFlowTo(sink) |
|
||||
exists(DataFlow::Node sink | Flow::flowTo(sink) |
|
||||
sink.getLocation() = location and
|
||||
element = sink.toString() and
|
||||
value = ""
|
||||
|
||||
@@ -19,18 +19,18 @@ query predicate superAccesses(
|
||||
enclosingType = enclosingCallable.getDeclaringType()
|
||||
}
|
||||
|
||||
class Config extends DataFlow::Configuration {
|
||||
Config() { this = "testconfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node x) {
|
||||
module Config implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node x) {
|
||||
x.asExpr() instanceof IntegerLiteral and x.getEnclosingCallable().fromSource()
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node x) {
|
||||
predicate isSink(DataFlow::Node x) {
|
||||
x.asExpr().(Argument).getCall().getCallee().getName() = "sink"
|
||||
}
|
||||
}
|
||||
|
||||
from Config c, DataFlow::Node source, DataFlow::Node sink
|
||||
where c.hasFlow(source, sink)
|
||||
module Flow = DataFlow::Global<Config>;
|
||||
|
||||
from DataFlow::Node source, DataFlow::Node sink
|
||||
where Flow::flow(source, sink)
|
||||
select source, sink
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import java
|
||||
import semmle.code.java.dataflow.DataFlow
|
||||
import DataFlow::PathGraph
|
||||
import Flow::PathGraph
|
||||
|
||||
class Config extends DataFlow::Configuration {
|
||||
Config() { this = "Config" }
|
||||
module Config implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node n) { n.asExpr().(StringLiteral).getValue() = "taint" }
|
||||
|
||||
override predicate isSource(DataFlow::Node n) { n.asExpr().(StringLiteral).getValue() = "taint" }
|
||||
|
||||
override predicate isSink(DataFlow::Node n) {
|
||||
predicate isSink(DataFlow::Node n) {
|
||||
n.asExpr().(Argument).getCall().getCallee().getName() = "sink"
|
||||
}
|
||||
}
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, Config c
|
||||
where c.hasFlowPath(source, sink)
|
||||
module Flow = DataFlow::Global<Config>;
|
||||
|
||||
from Flow::PathNode source, Flow::PathNode sink
|
||||
where Flow::flowPath(source, sink)
|
||||
select source, source, sink, "flow path"
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added new flow steps for `java.util.StringJoiner`.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Changed some models of Spring's `FileCopyUtils.copy` to be path injection sinks instead of summaries.
|
||||
@@ -338,8 +338,14 @@ extensions:
|
||||
- ["java.util", "Stack", True, "peek", "()", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
|
||||
- ["java.util", "Stack", True, "pop", "()", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
|
||||
- ["java.util", "Stack", True, "push", "(Object)", "", "Argument[0]", "Argument[this].Element", "value", "manual"]
|
||||
- ["java.util", "StringJoiner", False, "add", "(CharSequence)", "", "Argument[this]", "ReturnValue", "taint", "manual"]
|
||||
- ["java.util", "StringJoiner", False, "add", "(CharSequence)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["java.util", "StringJoiner", False, "StringJoiner", "", "", "Argument[0..2]", "Argument[this]", "taint", "manual"]
|
||||
- ["java.util", "StringJoiner", False, "add", "(CharSequence)", "", "Argument[this]", "ReturnValue", "value", "manual"]
|
||||
- ["java.util", "StringJoiner", False, "add", "(CharSequence)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
|
||||
- ["java.util", "StringJoiner", False, "merge", "", "", "Argument[0]", "Argument[this]", "taint", "manual"]
|
||||
- ["java.util", "StringJoiner", False, "merge", "", "", "Argument[this]", "ReturnValue", "value", "manual"]
|
||||
- ["java.util", "StringJoiner", False, "setEmptyValue", "", "", "Argument[0]", "Argument[this]", "taint", "manual"]
|
||||
- ["java.util", "StringJoiner", False, "setEmptyValue", "", "", "Argument[this]", "ReturnValue", "value", "manual"]
|
||||
- ["java.util", "StringJoiner", False, "toString", "", "", "Argument[this]", "ReturnValue", "taint", "manual"]
|
||||
- ["java.util", "StringTokenizer", False, "StringTokenizer", "", "", "Argument[0]", "Argument[this]", "taint", "manual"]
|
||||
- ["java.util", "StringTokenizer", False, "nextElement", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
|
||||
- ["java.util", "StringTokenizer", False, "nextToken", "", "", "Argument[this]", "ReturnValue", "taint", "manual"]
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/java-all
|
||||
extensible: sinkModel
|
||||
data:
|
||||
- ["org.springframework.util", "FileCopyUtils", False, "copy", "(byte[],File)", "", "Argument[1]", "create-file", "manual"]
|
||||
- ["org.springframework.util", "FileCopyUtils", False, "copy", "(File,File)", "", "Argument[0]", "read-file", "manual"]
|
||||
- ["org.springframework.util", "FileCopyUtils", False, "copy", "(File,File)", "", "Argument[1]", "create-file", "manual"]
|
||||
|
||||
- addsTo:
|
||||
pack: codeql/java-all
|
||||
extensible: summaryModel
|
||||
@@ -42,7 +50,10 @@ extensions:
|
||||
- ["org.springframework.util", "FastByteArrayOutputStream", False, "toByteArray", "", "", "Argument[this]", "ReturnValue", "taint", "manual"]
|
||||
- ["org.springframework.util", "FastByteArrayOutputStream", False, "write", "", "", "Argument[0]", "Argument[this]", "taint", "manual"]
|
||||
- ["org.springframework.util", "FastByteArrayOutputStream", False, "writeTo", "", "", "Argument[this]", "Argument[0]", "taint", "manual"]
|
||||
- ["org.springframework.util", "FileCopyUtils", False, "copy", "", "", "Argument[0]", "Argument[1]", "taint", "manual"]
|
||||
- ["org.springframework.util", "FileCopyUtils", False, "copy", "(byte[],OutputStream)", "", "Argument[0]", "Argument[1]", "taint", "manual"]
|
||||
- ["org.springframework.util", "FileCopyUtils", False, "copy", "(InputStream,OutputStream)", "", "Argument[0]", "Argument[1]", "taint", "manual"]
|
||||
- ["org.springframework.util", "FileCopyUtils", False, "copy", "(Reader,Writer)", "", "Argument[0]", "Argument[1]", "taint", "manual"]
|
||||
- ["org.springframework.util", "FileCopyUtils", False, "copy", "(String,Writer)", "", "Argument[0]", "Argument[1]", "taint", "manual"]
|
||||
- ["org.springframework.util", "FileCopyUtils", False, "copyToByteArray", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["org.springframework.util", "FileCopyUtils", False, "copyToString", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["org.springframework.util", "FileSystemUtils", False, "copyRecursively", "(java.io.File,java.io.File)", "", "Argument[0]", "Argument[1]", "taint", "manual"]
|
||||
|
||||
@@ -340,6 +340,47 @@ class Callable extends StmtParent, Member, @callable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the given type is public and, if it is a nested type, that all of
|
||||
* its enclosing types are public as well.
|
||||
*/
|
||||
private predicate veryPublic(RefType t) {
|
||||
t.isPublic() and
|
||||
(
|
||||
not t instanceof NestedType or
|
||||
veryPublic(t.(NestedType).getEnclosingType())
|
||||
)
|
||||
}
|
||||
|
||||
/** A callable that is the same as its source declaration. */
|
||||
class SrcCallable extends Callable {
|
||||
SrcCallable() { this.isSourceDeclaration() }
|
||||
|
||||
/**
|
||||
* Holds if this callable is effectively public in the sense that it can be
|
||||
* called from outside the codebase. This means either a `public` callable on
|
||||
* a sufficiently public type or a `protected` callable on a sufficiently
|
||||
* public non-`final` type.
|
||||
*/
|
||||
predicate isEffectivelyPublic() {
|
||||
exists(RefType t | t = this.getDeclaringType() |
|
||||
this.isPublic() and veryPublic(t)
|
||||
or
|
||||
this.isProtected() and not t.isFinal() and veryPublic(t)
|
||||
)
|
||||
or
|
||||
exists(SrcRefType tsub, Method m |
|
||||
veryPublic(tsub) and
|
||||
tsub.hasMethod(m, _) and
|
||||
m.getSourceDeclaration() = this
|
||||
|
|
||||
this.isPublic()
|
||||
or
|
||||
this.isProtected() and not tsub.isFinal()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Gets the erasure of `t1` if it is a raw type, or `t1` itself otherwise. */
|
||||
private Type eraseRaw(Type t1) {
|
||||
if t1 instanceof RawType then result = t1.getErasure() else result = t1
|
||||
|
||||
@@ -361,3 +361,52 @@ module MergePathGraph<
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a `PathGraph` from three `PathGraph`s by disjoint union.
|
||||
*/
|
||||
module MergePathGraph3<
|
||||
PathNodeSig PathNode1, PathNodeSig PathNode2, PathNodeSig PathNode3,
|
||||
PathGraphSig<PathNode1> Graph1, PathGraphSig<PathNode2> Graph2, PathGraphSig<PathNode3> Graph3>
|
||||
{
|
||||
private module MergedInner = MergePathGraph<PathNode1, PathNode2, Graph1, Graph2>;
|
||||
|
||||
private module Merged =
|
||||
MergePathGraph<MergedInner::PathNode, PathNode3, MergedInner::PathGraph, Graph3>;
|
||||
|
||||
/** A node in a graph of path explanations that is formed by disjoint union of the three given graphs. */
|
||||
class PathNode instanceof Merged::PathNode {
|
||||
/** Gets this as a projection on the first given `PathGraph`. */
|
||||
PathNode1 asPathNode1() { result = super.asPathNode1().asPathNode1() }
|
||||
|
||||
/** Gets this as a projection on the second given `PathGraph`. */
|
||||
PathNode2 asPathNode2() { result = super.asPathNode1().asPathNode2() }
|
||||
|
||||
/** Gets this as a projection on the third given `PathGraph`. */
|
||||
PathNode3 asPathNode3() { result = super.asPathNode2() }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets the underlying `Node`. */
|
||||
Node getNode() { result = super.getNode() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the query predicates needed to include a graph in a path-problem query.
|
||||
*/
|
||||
module PathGraph = Merged::PathGraph;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/** Provides classes and predicates for exclusions related to MaD models. */
|
||||
|
||||
import java
|
||||
|
||||
/** Holds if the given package `p` is a test package. */
|
||||
pragma[nomagic]
|
||||
private predicate isTestPackage(Package p) {
|
||||
p.getName()
|
||||
.matches([
|
||||
"org.junit%", "junit.%", "org.mockito%", "org.assertj%",
|
||||
"com.github.tomakehurst.wiremock%", "org.hamcrest%", "org.springframework.test.%",
|
||||
"org.springframework.mock.%", "org.springframework.boot.test.%", "reactor.test%",
|
||||
"org.xmlunit%", "org.testcontainers.%", "org.opentest4j%", "org.mockserver%",
|
||||
"org.powermock%", "org.skyscreamer.jsonassert%", "org.rnorth.visibleassertions",
|
||||
"org.openqa.selenium%", "com.gargoylesoftware.htmlunit%", "org.jboss.arquillian.testng%",
|
||||
"org.testng%"
|
||||
])
|
||||
}
|
||||
|
||||
/**
|
||||
* A test library.
|
||||
*/
|
||||
class TestLibrary extends RefType {
|
||||
TestLibrary() { isTestPackage(this.getPackage()) }
|
||||
}
|
||||
|
||||
/** Holds if the given file is a test file. */
|
||||
private predicate isInTestFile(File file) {
|
||||
file.getAbsolutePath().matches(["%/test/%", "%/guava-tests/%", "%/guava-testlib/%"]) and
|
||||
not file.getAbsolutePath().matches("%/ql/test/%") // allows our test cases to work
|
||||
}
|
||||
|
||||
/** Holds if the given compilation unit's package is a JDK internal. */
|
||||
private predicate isJdkInternal(CompilationUnit cu) {
|
||||
cu.getPackage().getName().matches("org.graalvm%") or
|
||||
cu.getPackage().getName().matches("com.sun%") or
|
||||
cu.getPackage().getName().matches("sun%") or
|
||||
cu.getPackage().getName().matches("jdk%") or
|
||||
cu.getPackage().getName().matches("java2d%") or
|
||||
cu.getPackage().getName().matches("build.tools%") or
|
||||
cu.getPackage().getName().matches("propertiesparser%") or
|
||||
cu.getPackage().getName().matches("org.jcp%") or
|
||||
cu.getPackage().getName().matches("org.w3c%") or
|
||||
cu.getPackage().getName().matches("org.ietf.jgss%") or
|
||||
cu.getPackage().getName().matches("org.xml.sax%") or
|
||||
cu.getPackage().getName().matches("com.oracle%") or
|
||||
cu.getPackage().getName().matches("org.omg%") or
|
||||
cu.getPackage().getName().matches("org.relaxng%") or
|
||||
cu.getPackage().getName() = "compileproperties" or
|
||||
cu.getPackage().getName() = "transparentruler" or
|
||||
cu.getPackage().getName() = "genstubs" or
|
||||
cu.getPackage().getName() = "netscape.javascript" or
|
||||
cu.getPackage().getName() = ""
|
||||
}
|
||||
|
||||
/** Holds if the given callable is not worth modeling. */
|
||||
predicate isUninterestingForModels(Callable c) {
|
||||
isInTestFile(c.getCompilationUnit().getFile()) or
|
||||
isJdkInternal(c.getCompilationUnit()) or
|
||||
c instanceof MainMethod or
|
||||
c instanceof StaticInitializer or
|
||||
exists(FunctionalExpr funcExpr | c = funcExpr.asMethod()) or
|
||||
c.getDeclaringType() instanceof TestLibrary or
|
||||
c.(Constructor).isParameterless()
|
||||
}
|
||||
|
||||
/**
|
||||
* A class that represents all callables for which we might be
|
||||
* interested in having a MaD model.
|
||||
*/
|
||||
class ModelApi extends SrcCallable {
|
||||
ModelApi() {
|
||||
this.fromSource() and
|
||||
this.isEffectivelyPublic() and
|
||||
not isUninterestingForModels(this)
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
private import semmle.code.java.dataflow.FlowSummary
|
||||
private import utils.modelgenerator.internal.CaptureModels
|
||||
private import semmle.code.java.dataflow.internal.ModelExclusions
|
||||
private import TopJdkApis
|
||||
|
||||
/**
|
||||
* Returns the number of `DataFlowTargetApi`s with Summary MaD models
|
||||
* Returns the number of `ModelApi`s with Summary MaD models
|
||||
* for a given package and provenance.
|
||||
*/
|
||||
bindingset[package, apiSubset]
|
||||
@@ -13,7 +13,7 @@ private int getNumMadModeledApis(string package, string provenance, string apiSu
|
||||
count(SummarizedCallable sc |
|
||||
callableSubset(sc.asCallable(), apiSubset) and
|
||||
package = sc.asCallable().getCompilationUnit().getPackage().getName() and
|
||||
sc.asCallable() instanceof DataFlowTargetApi and
|
||||
sc.asCallable() instanceof ModelApi and
|
||||
(
|
||||
// "auto-only"
|
||||
not sc.hasManualModel() and
|
||||
@@ -34,12 +34,12 @@ private int getNumMadModeledApis(string package, string provenance, string apiSu
|
||||
)
|
||||
}
|
||||
|
||||
/** Returns the total number of `DataFlowTargetApi`s for a given package. */
|
||||
/** Returns the total number of `ModelApi`s for a given package. */
|
||||
private int getNumApis(string package, string apiSubset) {
|
||||
result =
|
||||
strictcount(DataFlowTargetApi dataFlowTargApi |
|
||||
callableSubset(dataFlowTargApi, apiSubset) and
|
||||
package = dataFlowTargApi.getCompilationUnit().getPackage().getName()
|
||||
strictcount(ModelApi api |
|
||||
callableSubset(api, apiSubset) and
|
||||
package = api.getCompilationUnit().getPackage().getName()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ predicate modelCoverageGenVsMan(
|
||||
// calculate the total generated and total manual numbers
|
||||
generated = generatedOnly + both and
|
||||
manual = manualOnly + both and
|
||||
// count the total number of `DataFlowTargetApi`s for each package
|
||||
// count the total number of `ModelApi`s for each package
|
||||
all = getNumApis(package, apiSubset) and
|
||||
non = all - (generatedOnly + both + manualOnly) and
|
||||
// Proportion of coverage
|
||||
|
||||
@@ -8,27 +8,7 @@ private import semmle.code.java.dataflow.FlowSummary
|
||||
private import semmle.code.java.dataflow.internal.DataFlowPrivate
|
||||
private import semmle.code.java.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
|
||||
private import semmle.code.java.dataflow.TaintTracking
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate isTestPackage(Package p) {
|
||||
p.getName()
|
||||
.matches([
|
||||
"org.junit%", "junit.%", "org.mockito%", "org.assertj%",
|
||||
"com.github.tomakehurst.wiremock%", "org.hamcrest%", "org.springframework.test.%",
|
||||
"org.springframework.mock.%", "org.springframework.boot.test.%", "reactor.test%",
|
||||
"org.xmlunit%", "org.testcontainers.%", "org.opentest4j%", "org.mockserver%",
|
||||
"org.powermock%", "org.skyscreamer.jsonassert%", "org.rnorth.visibleassertions",
|
||||
"org.openqa.selenium%", "com.gargoylesoftware.htmlunit%", "org.jboss.arquillian.testng%",
|
||||
"org.testng%"
|
||||
])
|
||||
}
|
||||
|
||||
/**
|
||||
* A test library.
|
||||
*/
|
||||
private class TestLibrary extends RefType {
|
||||
TestLibrary() { isTestPackage(this.getPackage()) }
|
||||
}
|
||||
private import semmle.code.java.dataflow.internal.ModelExclusions
|
||||
|
||||
private string containerAsJar(Container container) {
|
||||
if container instanceof JarFile then result = container.getBaseName() else result = "rt.jar"
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
private import java as J
|
||||
private import semmle.code.java.dataflow.internal.DataFlowPrivate
|
||||
private import semmle.code.java.dataflow.internal.ContainerFlow as ContainerFlow
|
||||
private import semmle.code.java.dataflow.internal.ModelExclusions
|
||||
private import semmle.code.java.dataflow.DataFlow as Df
|
||||
private import semmle.code.java.dataflow.SSA as Ssa
|
||||
private import semmle.code.java.dataflow.TaintTracking as Tt
|
||||
@@ -26,34 +27,6 @@ private J::Method superImpl(J::Method m) {
|
||||
not m instanceof J::ToStringMethod
|
||||
}
|
||||
|
||||
private predicate isInTestFile(J::File file) {
|
||||
file.getAbsolutePath().matches("%src/test/%") or
|
||||
file.getAbsolutePath().matches("%/guava-tests/%") or
|
||||
file.getAbsolutePath().matches("%/guava-testlib/%")
|
||||
}
|
||||
|
||||
private predicate isJdkInternal(J::CompilationUnit cu) {
|
||||
cu.getPackage().getName().matches("org.graalvm%") or
|
||||
cu.getPackage().getName().matches("com.sun%") or
|
||||
cu.getPackage().getName().matches("sun%") or
|
||||
cu.getPackage().getName().matches("jdk%") or
|
||||
cu.getPackage().getName().matches("java2d%") or
|
||||
cu.getPackage().getName().matches("build.tools%") or
|
||||
cu.getPackage().getName().matches("propertiesparser%") or
|
||||
cu.getPackage().getName().matches("org.jcp%") or
|
||||
cu.getPackage().getName().matches("org.w3c%") or
|
||||
cu.getPackage().getName().matches("org.ietf.jgss%") or
|
||||
cu.getPackage().getName().matches("org.xml.sax%") or
|
||||
cu.getPackage().getName().matches("com.oracle%") or
|
||||
cu.getPackage().getName().matches("org.omg%") or
|
||||
cu.getPackage().getName().matches("org.relaxng%") or
|
||||
cu.getPackage().getName() = "compileproperties" or
|
||||
cu.getPackage().getName() = "transparentruler" or
|
||||
cu.getPackage().getName() = "genstubs" or
|
||||
cu.getPackage().getName() = "netscape.javascript" or
|
||||
cu.getPackage().getName() = ""
|
||||
}
|
||||
|
||||
private predicate isInfrequentlyUsed(J::CompilationUnit cu) {
|
||||
cu.getPackage().getName().matches("javax.swing%") or
|
||||
cu.getPackage().getName().matches("java.awt%")
|
||||
@@ -63,13 +36,8 @@ private predicate isInfrequentlyUsed(J::CompilationUnit cu) {
|
||||
* Holds if it is relevant to generate models for `api`.
|
||||
*/
|
||||
private predicate isRelevantForModels(J::Callable api) {
|
||||
not isInTestFile(api.getCompilationUnit().getFile()) and
|
||||
not isJdkInternal(api.getCompilationUnit()) and
|
||||
not isInfrequentlyUsed(api.getCompilationUnit()) and
|
||||
not api instanceof J::MainMethod and
|
||||
not api instanceof J::StaticInitializer and
|
||||
not exists(J::FunctionalExpr funcExpr | api = funcExpr.asMethod()) and
|
||||
not api.(J::Constructor).isParameterless()
|
||||
not isUninterestingForModels(api) and
|
||||
not isInfrequentlyUsed(api.getCompilationUnit())
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -61,37 +61,11 @@ private module DefaultValueFlow = DataFlow::Global<DefaultFlowConfig>;
|
||||
|
||||
private module DefaultTaintFlow = TaintTracking::Global<DefaultFlowConfig>;
|
||||
|
||||
class DefaultValueFlowConf extends DataFlow::Configuration {
|
||||
DefaultValueFlowConf() { this = "qltest:defaultValueFlowConf" }
|
||||
|
||||
override predicate isSource(DataFlow::Node n) { defaultSource(n) }
|
||||
|
||||
override predicate isSink(DataFlow::Node n) {
|
||||
exists(MethodAccess ma | ma.getMethod().hasName("sink") | n.asExpr() = ma.getAnArgument())
|
||||
}
|
||||
|
||||
override int fieldFlowBranchLimit() { result = 1000 }
|
||||
}
|
||||
|
||||
class DefaultTaintFlowConf extends TaintTracking::Configuration {
|
||||
DefaultTaintFlowConf() { this = "qltest:defaultTaintFlowConf" }
|
||||
|
||||
override predicate isSource(DataFlow::Node n) { defaultSource(n) }
|
||||
|
||||
override predicate isSink(DataFlow::Node n) {
|
||||
exists(MethodAccess ma | ma.getMethod().hasName("sink") | n.asExpr() = ma.getAnArgument())
|
||||
}
|
||||
|
||||
override int fieldFlowBranchLimit() { result = 1000 }
|
||||
}
|
||||
|
||||
private string getSourceArgString(DataFlow::Node src) {
|
||||
defaultSource(src) and
|
||||
src.asExpr().(MethodAccess).getAnArgument().(StringLiteral).getValue() = result
|
||||
}
|
||||
|
||||
abstract class EnableLegacyConfiguration extends Unit { }
|
||||
|
||||
class InlineFlowTest extends InlineExpectationsTest {
|
||||
InlineFlowTest() { this = "HasFlowTest" }
|
||||
|
||||
@@ -116,18 +90,10 @@ class InlineFlowTest extends InlineExpectationsTest {
|
||||
}
|
||||
|
||||
predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) {
|
||||
if exists(EnableLegacyConfiguration e)
|
||||
then getValueFlowConfig().hasFlow(src, sink)
|
||||
else DefaultValueFlow::flow(src, sink)
|
||||
DefaultValueFlow::flow(src, sink)
|
||||
}
|
||||
|
||||
predicate hasTaintFlow(DataFlow::Node src, DataFlow::Node sink) {
|
||||
if exists(EnableLegacyConfiguration e)
|
||||
then getTaintFlowConfig().hasFlow(src, sink)
|
||||
else DefaultTaintFlow::flow(src, sink)
|
||||
DefaultTaintFlow::flow(src, sink)
|
||||
}
|
||||
|
||||
DataFlow::Configuration getValueFlowConfig() { result = any(DefaultValueFlowConf config) }
|
||||
|
||||
DataFlow::Configuration getTaintFlowConfig() { result = any(DefaultTaintFlowConf config) }
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ public class Test {
|
||||
sink(sj1.add((CharSequence)source())); // $hasTaintFlow
|
||||
|
||||
StringJoiner sj2 = (StringJoiner)source();
|
||||
sink(sj2.add("test")); // $hasTaintFlow
|
||||
sink(sj2.add("test")); // $hasValueFlow
|
||||
}
|
||||
|
||||
// top 300-500 JDK APIs tests
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
import java.util.StringJoiner;
|
||||
|
||||
public class StringJoinerTests {
|
||||
|
||||
Object taint() {
|
||||
return null;
|
||||
}
|
||||
|
||||
void sink(Object o) {}
|
||||
|
||||
public void test() throws Exception {
|
||||
{
|
||||
// "java.util;StringJoiner;false;StringJoiner;(CharSequence);;Argument[0];Argument[-1];taint;manual"
|
||||
StringJoiner out = null;
|
||||
CharSequence in = (CharSequence) taint();
|
||||
out = new StringJoiner(in);
|
||||
sink(out);
|
||||
}
|
||||
{
|
||||
// "java.util;StringJoiner;false;StringJoiner;(CharSequence,CharSequence,CharSequence);;Argument[0];Argument[-1];taint;manual"
|
||||
StringJoiner out = null;
|
||||
CharSequence in = (CharSequence) taint();
|
||||
out = new StringJoiner(in, null, null);
|
||||
sink(out);
|
||||
}
|
||||
{
|
||||
// "java.util;StringJoiner;false;StringJoiner;(CharSequence,CharSequence,CharSequence);;Argument[1];Argument[-1];taint;manual"
|
||||
StringJoiner out = null;
|
||||
CharSequence in = (CharSequence) taint();
|
||||
out = new StringJoiner(null, in, null);
|
||||
sink(out);
|
||||
}
|
||||
{
|
||||
// "java.util;StringJoiner;false;StringJoiner;(CharSequence,CharSequence,CharSequence);;Argument[2];Argument[-1];taint;manual"
|
||||
StringJoiner out = null;
|
||||
CharSequence in = (CharSequence) taint();
|
||||
out = new StringJoiner(null, null, in);
|
||||
sink(out);
|
||||
}
|
||||
{
|
||||
// "java.util;StringJoiner;false;add;;;Argument[-1];ReturnValue;value;manual"
|
||||
StringJoiner out = null;
|
||||
StringJoiner in = (StringJoiner) taint();
|
||||
out = in.add(null);
|
||||
sink(out);
|
||||
}
|
||||
{
|
||||
// "java.util;StringJoiner;false;add;;;Argument[0];Argument[-1];taint;manual"
|
||||
StringJoiner out = null;
|
||||
CharSequence in = (CharSequence) taint();
|
||||
out.add(in);
|
||||
sink(out);
|
||||
}
|
||||
{
|
||||
// "java.util;StringJoiner;false;merge;;;Argument[-1];ReturnValue;value;manual"
|
||||
StringJoiner out = null;
|
||||
StringJoiner in = (StringJoiner) taint();
|
||||
out = in.merge(null);
|
||||
sink(out);
|
||||
}
|
||||
{
|
||||
// "java.util;StringJoiner;false;merge;;;Argument[0];Argument[-1];taint;manual"
|
||||
StringJoiner out = null;
|
||||
StringJoiner in = (StringJoiner) taint();
|
||||
out.merge(in);
|
||||
sink(out);
|
||||
}
|
||||
{
|
||||
// "java.util;StringJoiner;false;setEmptyValue;;;Argument[-1];ReturnValue;taint;manual"
|
||||
StringJoiner out = null;
|
||||
StringJoiner in = (StringJoiner) taint();
|
||||
out = in.setEmptyValue(null);
|
||||
sink(out);
|
||||
}
|
||||
{
|
||||
// "java.util;StringJoiner;false;setEmptyValue;;;Argument[0];Argument[-1];taint;manual"
|
||||
StringJoiner out = null;
|
||||
CharSequence in = (CharSequence) taint();
|
||||
out.setEmptyValue(in);
|
||||
sink(out);
|
||||
}
|
||||
{
|
||||
// "java.util;StringJoiner;false;toString;;;Argument[-1];ReturnValue;taint;manual"
|
||||
String out = null;
|
||||
StringJoiner in = (StringJoiner) taint();
|
||||
out = in.toString();
|
||||
sink(out);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -71,6 +71,17 @@
|
||||
| StringBuilderTests.java:70:15:70:21 | taint(...) | StringBuilderTests.java:73:10:73:26 | new String(...) |
|
||||
| StringBuilderTests.java:79:15:79:21 | taint(...) | StringBuilderTests.java:80:10:80:40 | toString(...) |
|
||||
| StringBuilderTests.java:86:15:86:21 | taint(...) | StringBuilderTests.java:87:10:87:27 | substring(...) |
|
||||
| StringJoinerTests.java:15:37:15:43 | taint(...) | StringJoinerTests.java:17:9:17:11 | out |
|
||||
| StringJoinerTests.java:22:37:22:43 | taint(...) | StringJoinerTests.java:24:9:24:11 | out |
|
||||
| StringJoinerTests.java:29:37:29:43 | taint(...) | StringJoinerTests.java:31:9:31:11 | out |
|
||||
| StringJoinerTests.java:36:37:36:43 | taint(...) | StringJoinerTests.java:38:9:38:11 | out |
|
||||
| StringJoinerTests.java:43:37:43:43 | taint(...) | StringJoinerTests.java:45:9:45:11 | out |
|
||||
| StringJoinerTests.java:50:37:50:43 | taint(...) | StringJoinerTests.java:52:9:52:11 | out |
|
||||
| StringJoinerTests.java:57:37:57:43 | taint(...) | StringJoinerTests.java:59:9:59:11 | out |
|
||||
| StringJoinerTests.java:64:37:64:43 | taint(...) | StringJoinerTests.java:66:9:66:11 | out |
|
||||
| StringJoinerTests.java:71:37:71:43 | taint(...) | StringJoinerTests.java:73:9:73:11 | out |
|
||||
| StringJoinerTests.java:78:37:78:43 | taint(...) | StringJoinerTests.java:80:9:80:11 | out |
|
||||
| StringJoinerTests.java:85:37:85:43 | taint(...) | StringJoinerTests.java:87:9:87:11 | out |
|
||||
| Varargs.java:7:8:7:14 | taint(...) | Varargs.java:14:10:14:10 | s |
|
||||
| Varargs.java:8:8:8:14 | taint(...) | Varargs.java:19:10:19:10 | s |
|
||||
| Varargs.java:8:17:8:23 | taint(...) | Varargs.java:19:10:19:10 | s |
|
||||
|
||||
@@ -3,22 +3,26 @@ import semmle.code.java.dataflow.TaintTracking
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import TestUtilities.InlineFlowTest
|
||||
|
||||
class EnableLegacy extends EnableLegacyConfiguration {
|
||||
EnableLegacy() { exists(this) }
|
||||
module Config implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) {
|
||||
DefaultFlowConfig::isSource(node)
|
||||
or
|
||||
node instanceof RemoteFlowSource
|
||||
}
|
||||
|
||||
predicate isSink = DefaultFlowConfig::isSink/1;
|
||||
}
|
||||
|
||||
class TaintFlowConf extends DefaultTaintFlowConf {
|
||||
override predicate isSource(DataFlow::Node n) {
|
||||
super.isSource(n)
|
||||
or
|
||||
n instanceof RemoteFlowSource
|
||||
}
|
||||
}
|
||||
module TaintFlow = TaintTracking::Global<Config>;
|
||||
|
||||
class ValueFlowConf extends DefaultValueFlowConf {
|
||||
override predicate isSource(DataFlow::Node n) {
|
||||
super.isSource(n)
|
||||
or
|
||||
n instanceof RemoteFlowSource
|
||||
module ValueFlow = DataFlow::Global<Config>;
|
||||
|
||||
class Test extends InlineFlowTest {
|
||||
override predicate hasTaintFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||
TaintFlow::flow(source, sink)
|
||||
}
|
||||
|
||||
override predicate hasValueFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||
ValueFlow::flow(source, sink)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,37 @@
|
||||
import java
|
||||
import semmle.code.java.dataflow.TaintTracking
|
||||
import TestUtilities.InlineFlowTest
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
|
||||
class EnableLegacy extends EnableLegacyConfiguration {
|
||||
EnableLegacy() { exists(this) }
|
||||
}
|
||||
|
||||
class SliceValueFlowConf extends DefaultValueFlowConf {
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
super.isSource(source) or source instanceof RemoteFlowSource
|
||||
module SliceValueFlowConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
DefaultFlowConfig::isSource(source) or source instanceof RemoteFlowSource
|
||||
}
|
||||
|
||||
predicate isSink = DefaultFlowConfig::isSink/1;
|
||||
}
|
||||
|
||||
class SliceTaintFlowConf extends DefaultTaintFlowConf {
|
||||
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
|
||||
super.allowImplicitRead(node, c)
|
||||
or
|
||||
isSink(node) and
|
||||
module SliceValueFlow = DataFlow::Global<SliceValueFlowConfig>;
|
||||
|
||||
module SliceTaintFlowConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource = DefaultFlowConfig::isSource/1;
|
||||
|
||||
predicate isSink = DefaultFlowConfig::isSink/1;
|
||||
|
||||
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
|
||||
DefaultFlowConfig::isSink(node) and
|
||||
c.(DataFlow::SyntheticFieldContent).getField() = "androidx.slice.Slice.action"
|
||||
}
|
||||
}
|
||||
|
||||
module SliceTaintFlow = TaintTracking::Global<SliceTaintFlowConfig>;
|
||||
|
||||
class SliceFlowTest extends InlineFlowTest {
|
||||
override predicate hasValueFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||
SliceValueFlow::flow(source, sink)
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||
SliceTaintFlow::flow(source, sink)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
import java
|
||||
import semmle.code.java.dataflow.DataFlow
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import TestUtilities.InlineFlowTest
|
||||
|
||||
class Conf extends DefaultTaintFlowConf {
|
||||
override predicate isSource(DataFlow::Node node) {
|
||||
super.isSource(node)
|
||||
module Config implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) {
|
||||
DefaultFlowConfig::isSource(node)
|
||||
or
|
||||
node instanceof RemoteFlowSource
|
||||
}
|
||||
|
||||
predicate isSink = DefaultFlowConfig::isSink/1;
|
||||
}
|
||||
|
||||
class LegacyConfig extends EnableLegacyConfiguration {
|
||||
LegacyConfig() { this instanceof Unit }
|
||||
module Flow = TaintTracking::Global<Config>;
|
||||
|
||||
class Test extends InlineFlowTest {
|
||||
override predicate hasTaintFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||
Flow::flow(source, sink)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
import java
|
||||
import semmle.code.java.dataflow.DataFlow
|
||||
import TestUtilities.InlineFlowTest
|
||||
|
||||
class EnableLegacy extends EnableLegacyConfiguration {
|
||||
EnableLegacy() { exists(this) }
|
||||
module OkHttpFlowConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource = DefaultFlowConfig::isSource/1;
|
||||
|
||||
predicate isSink(DataFlow::Node n) { DefaultFlowConfig::isSink(n) or sinkNode(n, "open-url") }
|
||||
}
|
||||
|
||||
class FlowConf extends DefaultValueFlowConf {
|
||||
override predicate isSink(DataFlow::Node n) { super.isSink(n) or sinkNode(n, "open-url") }
|
||||
module OkHttpFlow = DataFlow::Global<OkHttpFlowConfig>;
|
||||
|
||||
class OkHttpTest extends InlineFlowTest {
|
||||
override predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) {
|
||||
OkHttpFlow::flow(src, sink)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import java
|
||||
import semmle.code.java.dataflow.DataFlow
|
||||
import TestUtilities.InlineFlowTest
|
||||
|
||||
class EnableLegacy extends EnableLegacyConfiguration {
|
||||
EnableLegacy() { exists(this) }
|
||||
module FlowConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource = DefaultFlowConfig::isSource/1;
|
||||
|
||||
predicate isSink(DataFlow::Node n) { DefaultFlowConfig::isSink(n) or sinkNode(n, "open-url") }
|
||||
}
|
||||
|
||||
class FlowConf extends DefaultValueFlowConf {
|
||||
override predicate isSink(DataFlow::Node n) { super.isSink(n) or sinkNode(n, "open-url") }
|
||||
module Flow = DataFlow::Global<FlowConfig>;
|
||||
|
||||
class RetrofitFlowTest extends InlineFlowTest {
|
||||
override predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) { Flow::flow(src, sink) }
|
||||
}
|
||||
|
||||
@@ -380,20 +380,6 @@ public class Test {
|
||||
FileCopyUtils.copy(in, out);
|
||||
sink(out); // $hasTaintFlow
|
||||
}
|
||||
{
|
||||
// "org.springframework.util;FileCopyUtils;false;copy;;;Argument[0];Argument[1];taint;manual"
|
||||
File out = null;
|
||||
byte[] in = (byte[])source();
|
||||
FileCopyUtils.copy(in, out);
|
||||
sink(out); // $hasTaintFlow
|
||||
}
|
||||
{
|
||||
// "org.springframework.util;FileCopyUtils;false;copy;;;Argument[0];Argument[1];taint;manual"
|
||||
File out = null;
|
||||
File in = (File)source();
|
||||
FileCopyUtils.copy(in, out);
|
||||
sink(out); // $hasTaintFlow
|
||||
}
|
||||
{
|
||||
// "org.springframework.util;FileCopyUtils;false;copyToByteArray;;;Argument[0];ReturnValue;taint;manual"
|
||||
byte[] out = null;
|
||||
|
||||
@@ -7,8 +7,8 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence
|
||||
{
|
||||
public char charAt(int p0){ return '0'; } // manual summary
|
||||
public int length(){ return 0; } // manual neutral
|
||||
public void setCharAt(int p0, char p1){} // manual neutral, Note: not currently counted by query due to exclusions in `TargetApiSpecific`
|
||||
public void setLength(int p0){} // manual neutral, Note: not currently counted by query due to exclusions in `TargetApiSpecific`
|
||||
public void setCharAt(int p0, char p1){} // manual neutral
|
||||
public void setLength(int p0){} // manual neutral
|
||||
|
||||
|
||||
public AbstractStringBuilder append(CharSequence p0){ return null; }
|
||||
|
||||
@@ -7,7 +7,7 @@ import java.io.Serializable;
|
||||
abstract public class Enum<E extends Enum<E>> implements Comparable<E>, Serializable
|
||||
{
|
||||
protected Enum() {}
|
||||
protected Enum(String p0, int p1){} // manual neutral, Note: this will not be counted in query results since `protected` not `public`
|
||||
protected Enum(String p0, int p1){} // manual neutral
|
||||
public String toString(){ return null; } // manual neutral
|
||||
public final String name(){ return null; } // manual neutral
|
||||
public final boolean equals(Object p0){ return false; } // manual neutral
|
||||
|
||||
@@ -12,7 +12,4 @@ public class StringBuffer extends AbstractStringBuilder implements Serializable
|
||||
public StringBuffer append(char p0){ return null; } // manual summary
|
||||
|
||||
public StringBuffer append(CharSequence s, int start, int end) { return null; }
|
||||
|
||||
public void setCharAt(int p0, char p1){}
|
||||
public void setLength(int p0){}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,4 @@ public class StringBuilder extends AbstractStringBuilder implements Serializable
|
||||
public StringBuilder(int p0){} // manual summary
|
||||
|
||||
public StringBuilder append(CharSequence s, int start, int end) { return null; }
|
||||
|
||||
public void setCharAt(int p0, char p1){}
|
||||
public void setLength(int p0){}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
| java.io | 0 | 0 | 22 | 9 | 31 | 0.7096774193548387 | 0.0 | 0.7096774193548387 | 0.0 | NaN | 0.2903225806451613 |
|
||||
| java.lang | 0 | 0 | 60 | 89 | 149 | 0.40268456375838924 | 0.0 | 0.40268456375838924 | 0.0 | NaN | 0.5973154362416108 |
|
||||
| java.awt | 0 | 0 | 2 | 1 | 3 | 0.6666666666666666 | 0.0 | 0.6666666666666666 | 0.0 | NaN | 0.3333333333333333 |
|
||||
| java.io | 0 | 0 | 22 | 15 | 37 | 0.5945945945945946 | 0.0 | 0.5945945945945946 | 0.0 | NaN | 0.40540540540540543 |
|
||||
| java.lang | 0 | 0 | 62 | 94 | 156 | 0.3974358974358974 | 0.0 | 0.3974358974358974 | 0.0 | NaN | 0.6025641025641025 |
|
||||
| java.lang.invoke | 0 | 0 | 0 | 1 | 1 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 |
|
||||
| java.lang.reflect | 0 | 0 | 0 | 4 | 4 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 |
|
||||
| java.math | 0 | 0 | 0 | 16 | 16 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 |
|
||||
| java.net | 0 | 0 | 5 | 0 | 5 | 1.0 | 0.0 | 1.0 | 0.0 | NaN | 0.0 |
|
||||
| java.nio | 0 | 0 | 2 | 3 | 5 | 0.4 | 0.0 | 0.4 | 0.0 | NaN | 0.6 |
|
||||
| java.nio.charset | 0 | 0 | 0 | 1 | 1 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 |
|
||||
| java.nio.file | 0 | 0 | 1 | 1 | 2 | 0.5 | 0.0 | 0.5 | 0.0 | NaN | 0.5 |
|
||||
| java.sql | 0 | 0 | 0 | 2 | 2 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 |
|
||||
| java.nio.file | 0 | 0 | 7 | 1 | 8 | 0.875 | 0.0 | 0.875 | 0.0 | NaN | 0.125 |
|
||||
| java.sql | 0 | 0 | 2 | 14 | 16 | 0.125 | 0.0 | 0.125 | 0.0 | NaN | 0.875 |
|
||||
| java.text | 0 | 0 | 0 | 5 | 5 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 |
|
||||
| java.time | 0 | 0 | 0 | 17 | 17 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 |
|
||||
| java.time.chrono | 0 | 0 | 0 | 1 | 1 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 |
|
||||
| java.time.format | 0 | 0 | 0 | 2 | 2 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 |
|
||||
| java.util | 0 | 0 | 56 | 45 | 101 | 0.5544554455445545 | 0.0 | 0.5544554455445545 | 0.0 | NaN | 0.44554455445544555 |
|
||||
| java.util.concurrent | 0 | 0 | 6 | 7 | 13 | 0.46153846153846156 | 0.0 | 0.46153846153846156 | 0.0 | NaN | 0.5384615384615384 |
|
||||
| java.util | 0 | 0 | 84 | 68 | 152 | 0.5526315789473685 | 0.0 | 0.5526315789473685 | 0.0 | NaN | 0.4473684210526316 |
|
||||
| java.util.concurrent | 0 | 0 | 9 | 9 | 18 | 0.5 | 0.0 | 0.5 | 0.0 | NaN | 0.5 |
|
||||
| java.util.concurrent.atomic | 0 | 0 | 2 | 11 | 13 | 0.15384615384615385 | 0.0 | 0.15384615384615385 | 0.0 | NaN | 0.8461538461538461 |
|
||||
| java.util.function | 0 | 0 | 0 | 1 | 1 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 |
|
||||
| java.util.concurrent.locks | 0 | 0 | 0 | 2 | 2 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 |
|
||||
| java.util.function | 0 | 0 | 0 | 6 | 6 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 |
|
||||
| java.util.logging | 0 | 0 | 1 | 1 | 2 | 0.5 | 0.0 | 0.5 | 0.0 | NaN | 0.5 |
|
||||
| java.util.regex | 0 | 0 | 3 | 1 | 4 | 0.75 | 0.0 | 0.75 | 0.0 | NaN | 0.25 |
|
||||
| java.util.stream | 0 | 0 | 4 | 5 | 9 | 0.4444444444444444 | 0.0 | 0.4444444444444444 | 0.0 | NaN | 0.5555555555555556 |
|
||||
| java.util.stream | 0 | 0 | 18 | 8 | 26 | 0.6923076923076923 | 0.0 | 0.6923076923076923 | 0.0 | NaN | 0.3076923076923077 |
|
||||
|
||||
@@ -14,108 +14,114 @@ edges
|
||||
| Test.java:95:14:95:34 | getHostName(...) : String | Test.java:99:12:99:33 | new URI(...) |
|
||||
| Test.java:95:14:95:34 | getHostName(...) : String | Test.java:100:12:100:45 | new URI(...) |
|
||||
| Test.java:95:14:95:34 | getHostName(...) : String | Test.java:101:12:101:54 | new URI(...) |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:33:61:33:68 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:35:41:35:48 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:37:56:37:63 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:39:46:39:53 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:41:38:41:45 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:43:36:43:43 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:45:31:45:38 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:47:33:47:40 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:49:27:49:34 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:50:27:50:34 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:51:34:51:41 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:53:40:53:47 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:54:48:54:55 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:55:47:55:54 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:57:40:57:47 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:59:38:59:45 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:61:33:61:40 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:63:33:63:40 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:65:41:65:48 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:67:42:67:49 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:69:37:69:44 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:71:29:71:36 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:73:37:73:44 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:75:28:75:35 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:77:33:77:40 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:79:40:79:47 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:81:40:81:47 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:82:40:82:47 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:84:38:84:45 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:86:28:86:35 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:87:28:87:35 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:88:28:88:35 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:90:34:90:41 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:91:34:91:41 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:93:33:93:40 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:95:42:95:49 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:97:50:97:57 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:99:54:99:61 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:104:37:104:44 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:106:74:106:81 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:108:68:108:75 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:110:68:110:75 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:112:30:112:37 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:117:30:117:37 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:122:33:122:40 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:124:27:124:34 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:126:28:126:35 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:128:29:128:36 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:133:27:133:34 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:135:26:135:33 | source(...) : String |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:140:29:140:36 | source(...) : String |
|
||||
| mad/Test.java:33:61:33:68 | source(...) : String | mad/Test.java:33:52:33:68 | (...)... |
|
||||
| mad/Test.java:35:41:35:48 | source(...) : String | mad/Test.java:35:32:35:48 | (...)... |
|
||||
| mad/Test.java:37:56:37:63 | source(...) : String | mad/Test.java:37:47:37:63 | (...)... |
|
||||
| mad/Test.java:39:46:39:53 | source(...) : String | mad/Test.java:39:39:39:53 | (...)... |
|
||||
| mad/Test.java:41:38:41:45 | source(...) : String | mad/Test.java:41:31:41:45 | (...)... |
|
||||
| mad/Test.java:43:36:43:43 | source(...) : String | mad/Test.java:43:29:43:43 | (...)... |
|
||||
| mad/Test.java:45:31:45:38 | source(...) : String | mad/Test.java:45:24:45:38 | (...)... |
|
||||
| mad/Test.java:47:33:47:40 | source(...) : String | mad/Test.java:47:24:47:40 | (...)... |
|
||||
| mad/Test.java:49:27:49:34 | source(...) : String | mad/Test.java:49:20:49:34 | (...)... |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:34:61:34:68 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:36:41:36:48 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:38:56:38:63 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:40:46:40:53 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:42:38:42:45 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:44:36:44:43 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:46:31:46:38 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:48:33:48:40 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:50:27:50:34 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:51:27:51:34 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:52:34:52:41 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:54:40:54:47 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:55:48:55:55 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:56:47:56:54 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:58:40:58:47 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:60:38:60:45 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:62:33:62:40 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:64:33:64:40 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:66:41:66:48 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:68:42:68:49 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:70:37:70:44 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:72:29:72:36 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:74:37:74:44 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:76:28:76:35 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:78:33:78:40 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:80:40:80:47 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:82:40:82:47 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:83:40:83:47 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:85:38:85:45 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:87:28:87:35 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:88:28:88:35 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:89:28:89:35 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:91:34:91:41 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:92:34:92:41 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:94:33:94:40 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:96:42:96:49 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:98:50:98:57 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:100:54:100:61 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:102:50:102:57 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:104:35:104:42 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:106:48:106:55 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:111:37:111:44 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:113:74:113:81 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:115:68:115:75 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:117:68:117:75 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:119:30:119:37 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:124:30:124:37 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:129:33:129:40 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:131:27:131:34 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:133:28:133:35 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:135:29:135:36 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:140:27:140:34 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:142:26:142:33 | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:147:29:147:36 | source(...) : String |
|
||||
| mad/Test.java:34:61:34:68 | source(...) : String | mad/Test.java:34:52:34:68 | (...)... |
|
||||
| mad/Test.java:36:41:36:48 | source(...) : String | mad/Test.java:36:32:36:48 | (...)... |
|
||||
| mad/Test.java:38:56:38:63 | source(...) : String | mad/Test.java:38:47:38:63 | (...)... |
|
||||
| mad/Test.java:40:46:40:53 | source(...) : String | mad/Test.java:40:39:40:53 | (...)... |
|
||||
| mad/Test.java:42:38:42:45 | source(...) : String | mad/Test.java:42:31:42:45 | (...)... |
|
||||
| mad/Test.java:44:36:44:43 | source(...) : String | mad/Test.java:44:29:44:43 | (...)... |
|
||||
| mad/Test.java:46:31:46:38 | source(...) : String | mad/Test.java:46:24:46:38 | (...)... |
|
||||
| mad/Test.java:48:33:48:40 | source(...) : String | mad/Test.java:48:24:48:40 | (...)... |
|
||||
| mad/Test.java:50:27:50:34 | source(...) : String | mad/Test.java:50:20:50:34 | (...)... |
|
||||
| mad/Test.java:51:34:51:41 | source(...) : String | mad/Test.java:51:20:51:41 | (...)... |
|
||||
| mad/Test.java:53:40:53:47 | source(...) : String | mad/Test.java:53:33:53:47 | (...)... |
|
||||
| mad/Test.java:54:48:54:55 | source(...) : String | mad/Test.java:54:33:54:55 | (...)... |
|
||||
| mad/Test.java:55:47:55:54 | source(...) : String | mad/Test.java:55:40:55:54 | (...)... |
|
||||
| mad/Test.java:57:40:57:47 | source(...) : String | mad/Test.java:57:33:57:47 | (...)... |
|
||||
| mad/Test.java:59:38:59:45 | source(...) : String | mad/Test.java:59:31:59:45 | (...)... |
|
||||
| mad/Test.java:61:33:61:40 | source(...) : String | mad/Test.java:61:26:61:40 | (...)... |
|
||||
| mad/Test.java:63:33:63:40 | source(...) : String | mad/Test.java:63:26:63:40 | (...)... |
|
||||
| mad/Test.java:65:41:65:48 | source(...) : String | mad/Test.java:65:34:65:48 | (...)... |
|
||||
| mad/Test.java:67:42:67:49 | source(...) : String | mad/Test.java:67:35:67:49 | (...)... |
|
||||
| mad/Test.java:69:37:69:44 | source(...) : String | mad/Test.java:69:30:69:44 | (...)... |
|
||||
| mad/Test.java:71:29:71:36 | source(...) : String | mad/Test.java:71:22:71:36 | (...)... |
|
||||
| mad/Test.java:73:37:73:44 | source(...) : String | mad/Test.java:73:30:73:44 | (...)... |
|
||||
| mad/Test.java:75:28:75:35 | source(...) : String | mad/Test.java:75:21:75:35 | (...)... |
|
||||
| mad/Test.java:77:33:77:40 | source(...) : String | mad/Test.java:77:26:77:40 | (...)... |
|
||||
| mad/Test.java:79:40:79:47 | source(...) : String | mad/Test.java:79:33:79:47 | (...)... |
|
||||
| mad/Test.java:81:40:81:47 | source(...) : String | mad/Test.java:81:33:81:47 | (...)... |
|
||||
| mad/Test.java:51:27:51:34 | source(...) : String | mad/Test.java:51:20:51:34 | (...)... |
|
||||
| mad/Test.java:52:34:52:41 | source(...) : String | mad/Test.java:52:20:52:41 | (...)... |
|
||||
| mad/Test.java:54:40:54:47 | source(...) : String | mad/Test.java:54:33:54:47 | (...)... |
|
||||
| mad/Test.java:55:48:55:55 | source(...) : String | mad/Test.java:55:33:55:55 | (...)... |
|
||||
| mad/Test.java:56:47:56:54 | source(...) : String | mad/Test.java:56:40:56:54 | (...)... |
|
||||
| mad/Test.java:58:40:58:47 | source(...) : String | mad/Test.java:58:33:58:47 | (...)... |
|
||||
| mad/Test.java:60:38:60:45 | source(...) : String | mad/Test.java:60:31:60:45 | (...)... |
|
||||
| mad/Test.java:62:33:62:40 | source(...) : String | mad/Test.java:62:26:62:40 | (...)... |
|
||||
| mad/Test.java:64:33:64:40 | source(...) : String | mad/Test.java:64:26:64:40 | (...)... |
|
||||
| mad/Test.java:66:41:66:48 | source(...) : String | mad/Test.java:66:34:66:48 | (...)... |
|
||||
| mad/Test.java:68:42:68:49 | source(...) : String | mad/Test.java:68:35:68:49 | (...)... |
|
||||
| mad/Test.java:70:37:70:44 | source(...) : String | mad/Test.java:70:30:70:44 | (...)... |
|
||||
| mad/Test.java:72:29:72:36 | source(...) : String | mad/Test.java:72:22:72:36 | (...)... |
|
||||
| mad/Test.java:74:37:74:44 | source(...) : String | mad/Test.java:74:30:74:44 | (...)... |
|
||||
| mad/Test.java:76:28:76:35 | source(...) : String | mad/Test.java:76:21:76:35 | (...)... |
|
||||
| mad/Test.java:78:33:78:40 | source(...) : String | mad/Test.java:78:26:78:40 | (...)... |
|
||||
| mad/Test.java:80:40:80:47 | source(...) : String | mad/Test.java:80:33:80:47 | (...)... |
|
||||
| mad/Test.java:82:40:82:47 | source(...) : String | mad/Test.java:82:33:82:47 | (...)... |
|
||||
| mad/Test.java:84:38:84:45 | source(...) : String | mad/Test.java:84:31:84:45 | (...)... |
|
||||
| mad/Test.java:86:28:86:35 | source(...) : String | mad/Test.java:86:21:86:35 | (...)... |
|
||||
| mad/Test.java:83:40:83:47 | source(...) : String | mad/Test.java:83:33:83:47 | (...)... |
|
||||
| mad/Test.java:85:38:85:45 | source(...) : String | mad/Test.java:85:31:85:45 | (...)... |
|
||||
| mad/Test.java:87:28:87:35 | source(...) : String | mad/Test.java:87:21:87:35 | (...)... |
|
||||
| mad/Test.java:88:28:88:35 | source(...) : String | mad/Test.java:88:21:88:35 | (...)... |
|
||||
| mad/Test.java:90:34:90:41 | source(...) : String | mad/Test.java:90:27:90:41 | (...)... |
|
||||
| mad/Test.java:89:28:89:35 | source(...) : String | mad/Test.java:89:21:89:35 | (...)... |
|
||||
| mad/Test.java:91:34:91:41 | source(...) : String | mad/Test.java:91:27:91:41 | (...)... |
|
||||
| mad/Test.java:93:33:93:40 | source(...) : String | mad/Test.java:93:26:93:40 | (...)... |
|
||||
| mad/Test.java:95:42:95:49 | source(...) : String | mad/Test.java:95:35:95:49 | (...)... |
|
||||
| mad/Test.java:97:50:97:57 | source(...) : String | mad/Test.java:97:41:97:57 | (...)... |
|
||||
| mad/Test.java:99:54:99:61 | source(...) : String | mad/Test.java:99:45:99:61 | (...)... |
|
||||
| mad/Test.java:104:37:104:44 | source(...) : String | mad/Test.java:104:30:104:44 | (...)... |
|
||||
| mad/Test.java:106:74:106:81 | source(...) : String | mad/Test.java:106:40:106:81 | (...)... |
|
||||
| mad/Test.java:108:68:108:75 | source(...) : String | mad/Test.java:108:34:108:75 | (...)... |
|
||||
| mad/Test.java:110:68:110:75 | source(...) : String | mad/Test.java:110:34:110:75 | (...)... |
|
||||
| mad/Test.java:112:30:112:37 | source(...) : String | mad/Test.java:112:23:112:37 | (...)... |
|
||||
| mad/Test.java:117:30:117:37 | source(...) : String | mad/Test.java:117:23:117:37 | (...)... |
|
||||
| mad/Test.java:122:33:122:40 | source(...) : String | mad/Test.java:122:23:122:40 | (...)... |
|
||||
| mad/Test.java:124:27:124:34 | source(...) : String | mad/Test.java:124:20:124:34 | (...)... |
|
||||
| mad/Test.java:126:28:126:35 | source(...) : String | mad/Test.java:126:21:126:35 | (...)... |
|
||||
| mad/Test.java:128:29:128:36 | source(...) : String | mad/Test.java:128:22:128:36 | (...)... |
|
||||
| mad/Test.java:133:27:133:34 | source(...) : String | mad/Test.java:133:20:133:34 | (...)... |
|
||||
| mad/Test.java:135:26:135:33 | source(...) : String | mad/Test.java:135:19:135:33 | (...)... |
|
||||
| mad/Test.java:140:29:140:36 | source(...) : String | mad/Test.java:140:20:140:36 | (...)... |
|
||||
| mad/Test.java:92:34:92:41 | source(...) : String | mad/Test.java:92:27:92:41 | (...)... |
|
||||
| mad/Test.java:94:33:94:40 | source(...) : String | mad/Test.java:94:26:94:40 | (...)... |
|
||||
| mad/Test.java:96:42:96:49 | source(...) : String | mad/Test.java:96:35:96:49 | (...)... |
|
||||
| mad/Test.java:98:50:98:57 | source(...) : String | mad/Test.java:98:41:98:57 | (...)... |
|
||||
| mad/Test.java:100:54:100:61 | source(...) : String | mad/Test.java:100:45:100:61 | (...)... |
|
||||
| mad/Test.java:102:50:102:57 | source(...) : String | mad/Test.java:102:43:102:57 | (...)... |
|
||||
| mad/Test.java:104:35:104:42 | source(...) : String | mad/Test.java:104:28:104:42 | (...)... |
|
||||
| mad/Test.java:106:48:106:55 | source(...) : String | mad/Test.java:106:41:106:55 | (...)... |
|
||||
| mad/Test.java:111:37:111:44 | source(...) : String | mad/Test.java:111:30:111:44 | (...)... |
|
||||
| mad/Test.java:113:74:113:81 | source(...) : String | mad/Test.java:113:40:113:81 | (...)... |
|
||||
| mad/Test.java:115:68:115:75 | source(...) : String | mad/Test.java:115:34:115:75 | (...)... |
|
||||
| mad/Test.java:117:68:117:75 | source(...) : String | mad/Test.java:117:34:117:75 | (...)... |
|
||||
| mad/Test.java:119:30:119:37 | source(...) : String | mad/Test.java:119:23:119:37 | (...)... |
|
||||
| mad/Test.java:124:30:124:37 | source(...) : String | mad/Test.java:124:23:124:37 | (...)... |
|
||||
| mad/Test.java:129:33:129:40 | source(...) : String | mad/Test.java:129:23:129:40 | (...)... |
|
||||
| mad/Test.java:131:27:131:34 | source(...) : String | mad/Test.java:131:20:131:34 | (...)... |
|
||||
| mad/Test.java:133:28:133:35 | source(...) : String | mad/Test.java:133:21:133:35 | (...)... |
|
||||
| mad/Test.java:135:29:135:36 | source(...) : String | mad/Test.java:135:22:135:36 | (...)... |
|
||||
| mad/Test.java:140:27:140:34 | source(...) : String | mad/Test.java:140:20:140:34 | (...)... |
|
||||
| mad/Test.java:142:26:142:33 | source(...) : String | mad/Test.java:142:19:142:33 | (...)... |
|
||||
| mad/Test.java:147:29:147:36 | source(...) : String | mad/Test.java:147:20:147:36 | (...)... |
|
||||
nodes
|
||||
| Test.java:19:18:19:38 | getHostName(...) : String | semmle.label | getHostName(...) : String |
|
||||
| Test.java:24:20:24:23 | temp | semmle.label | temp |
|
||||
@@ -136,109 +142,115 @@ nodes
|
||||
| Test.java:99:12:99:33 | new URI(...) | semmle.label | new URI(...) |
|
||||
| Test.java:100:12:100:45 | new URI(...) | semmle.label | new URI(...) |
|
||||
| Test.java:101:12:101:54 | new URI(...) | semmle.label | new URI(...) |
|
||||
| mad/Test.java:28:16:28:36 | getHostName(...) : String | semmle.label | getHostName(...) : String |
|
||||
| mad/Test.java:33:52:33:68 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:33:61:33:68 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:35:32:35:48 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:35:41:35:48 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:37:47:37:63 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:37:56:37:63 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:39:39:39:53 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:39:46:39:53 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:41:31:41:45 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:41:38:41:45 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:43:29:43:43 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:43:36:43:43 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:45:24:45:38 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:45:31:45:38 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:47:24:47:40 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:47:33:47:40 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:49:20:49:34 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:49:27:49:34 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:29:16:29:36 | getHostName(...) : String | semmle.label | getHostName(...) : String |
|
||||
| mad/Test.java:34:52:34:68 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:34:61:34:68 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:36:32:36:48 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:36:41:36:48 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:38:47:38:63 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:38:56:38:63 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:40:39:40:53 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:40:46:40:53 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:42:31:42:45 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:42:38:42:45 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:44:29:44:43 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:44:36:44:43 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:46:24:46:38 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:46:31:46:38 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:48:24:48:40 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:48:33:48:40 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:50:20:50:34 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:50:27:50:34 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:51:20:51:41 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:51:34:51:41 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:53:33:53:47 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:53:40:53:47 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:54:33:54:55 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:54:48:54:55 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:55:40:55:54 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:55:47:55:54 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:57:33:57:47 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:57:40:57:47 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:59:31:59:45 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:59:38:59:45 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:61:26:61:40 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:61:33:61:40 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:63:26:63:40 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:63:33:63:40 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:65:34:65:48 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:65:41:65:48 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:67:35:67:49 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:67:42:67:49 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:69:30:69:44 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:69:37:69:44 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:71:22:71:36 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:71:29:71:36 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:73:30:73:44 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:73:37:73:44 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:75:21:75:35 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:75:28:75:35 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:77:26:77:40 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:77:33:77:40 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:79:33:79:47 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:79:40:79:47 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:81:33:81:47 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:81:40:81:47 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:51:20:51:34 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:51:27:51:34 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:52:20:52:41 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:52:34:52:41 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:54:33:54:47 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:54:40:54:47 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:55:33:55:55 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:55:48:55:55 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:56:40:56:54 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:56:47:56:54 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:58:33:58:47 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:58:40:58:47 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:60:31:60:45 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:60:38:60:45 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:62:26:62:40 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:62:33:62:40 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:64:26:64:40 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:64:33:64:40 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:66:34:66:48 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:66:41:66:48 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:68:35:68:49 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:68:42:68:49 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:70:30:70:44 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:70:37:70:44 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:72:22:72:36 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:72:29:72:36 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:74:30:74:44 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:74:37:74:44 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:76:21:76:35 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:76:28:76:35 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:78:26:78:40 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:78:33:78:40 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:80:33:80:47 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:80:40:80:47 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:82:33:82:47 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:82:40:82:47 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:84:31:84:45 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:84:38:84:45 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:86:21:86:35 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:86:28:86:35 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:83:33:83:47 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:83:40:83:47 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:85:31:85:45 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:85:38:85:45 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:87:21:87:35 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:87:28:87:35 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:88:21:88:35 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:88:28:88:35 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:90:27:90:41 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:90:34:90:41 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:89:21:89:35 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:89:28:89:35 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:91:27:91:41 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:91:34:91:41 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:93:26:93:40 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:93:33:93:40 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:95:35:95:49 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:95:42:95:49 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:97:41:97:57 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:97:50:97:57 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:99:45:99:61 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:99:54:99:61 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:104:30:104:44 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:104:37:104:44 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:106:40:106:81 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:106:74:106:81 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:108:34:108:75 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:108:68:108:75 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:110:34:110:75 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:110:68:110:75 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:112:23:112:37 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:112:30:112:37 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:117:23:117:37 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:117:30:117:37 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:122:23:122:40 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:122:33:122:40 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:124:20:124:34 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:124:27:124:34 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:126:21:126:35 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:126:28:126:35 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:128:22:128:36 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:128:29:128:36 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:133:20:133:34 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:133:27:133:34 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:135:19:135:33 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:135:26:135:33 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:140:20:140:36 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:140:29:140:36 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:92:27:92:41 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:92:34:92:41 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:94:26:94:40 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:94:33:94:40 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:96:35:96:49 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:96:42:96:49 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:98:41:98:57 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:98:50:98:57 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:100:45:100:61 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:100:54:100:61 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:102:43:102:57 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:102:50:102:57 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:104:28:104:42 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:104:35:104:42 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:106:41:106:55 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:106:48:106:55 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:111:30:111:44 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:111:37:111:44 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:113:40:113:81 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:113:74:113:81 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:115:34:115:75 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:115:68:115:75 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:117:34:117:75 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:117:68:117:75 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:119:23:119:37 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:119:30:119:37 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:124:23:124:37 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:124:30:124:37 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:129:23:129:40 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:129:33:129:40 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:131:20:131:34 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:131:27:131:34 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:133:21:133:35 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:133:28:133:35 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:135:22:135:36 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:135:29:135:36 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:140:20:140:34 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:140:27:140:34 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:142:19:142:33 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:142:26:142:33 | source(...) : String | semmle.label | source(...) : String |
|
||||
| mad/Test.java:147:20:147:36 | (...)... | semmle.label | (...)... |
|
||||
| mad/Test.java:147:29:147:36 | source(...) : String | semmle.label | source(...) : String |
|
||||
subpaths
|
||||
#select
|
||||
| Test.java:24:11:24:24 | new File(...) | Test.java:19:18:19:38 | getHostName(...) : String | Test.java:24:20:24:23 | temp | This path depends on a $@. | Test.java:19:18:19:38 | getHostName(...) | user-provided value |
|
||||
@@ -252,54 +264,57 @@ subpaths
|
||||
| Test.java:99:3:99:34 | new File(...) | Test.java:95:14:95:34 | getHostName(...) : String | Test.java:99:12:99:33 | new URI(...) | This path depends on a $@. | Test.java:95:14:95:34 | getHostName(...) | user-provided value |
|
||||
| Test.java:100:3:100:46 | new File(...) | Test.java:95:14:95:34 | getHostName(...) : String | Test.java:100:12:100:45 | new URI(...) | This path depends on a $@. | Test.java:95:14:95:34 | getHostName(...) | user-provided value |
|
||||
| Test.java:101:3:101:55 | new File(...) | Test.java:95:14:95:34 | getHostName(...) : String | Test.java:101:12:101:54 | new URI(...) | This path depends on a $@. | Test.java:95:14:95:34 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:33:52:33:68 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:33:52:33:68 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:35:32:35:48 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:35:32:35:48 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:37:47:37:63 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:37:47:37:63 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:39:39:39:53 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:39:39:39:53 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:41:31:41:45 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:41:31:41:45 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:43:29:43:43 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:43:29:43:43 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:45:24:45:38 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:45:24:45:38 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:47:9:47:41 | new FileReader(...) | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:47:24:47:40 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:49:20:49:34 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:49:20:49:34 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:50:20:50:34 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:50:20:50:34 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:51:20:51:41 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:51:20:51:41 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:53:33:53:47 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:53:33:53:47 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:54:33:54:55 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:54:33:54:55 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:55:40:55:54 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:55:40:55:54 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:57:33:57:47 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:57:33:57:47 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:59:31:59:45 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:59:31:59:45 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:61:26:61:40 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:61:26:61:40 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:63:26:63:40 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:63:26:63:40 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:65:34:65:48 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:65:34:65:48 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:67:35:67:49 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:67:35:67:49 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:69:30:69:44 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:69:30:69:44 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:71:22:71:36 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:71:22:71:36 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:73:30:73:44 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:73:30:73:44 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:75:21:75:35 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:75:21:75:35 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:77:26:77:40 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:77:26:77:40 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:79:33:79:47 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:79:33:79:47 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:81:33:81:47 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:81:33:81:47 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:82:33:82:47 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:82:33:82:47 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:84:31:84:45 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:84:31:84:45 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:86:21:86:35 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:86:21:86:35 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:87:21:87:35 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:87:21:87:35 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:88:21:88:35 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:88:21:88:35 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:90:27:90:41 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:90:27:90:41 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:91:27:91:41 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:91:27:91:41 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:93:26:93:40 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:93:26:93:40 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:95:35:95:49 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:95:35:95:49 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:97:41:97:57 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:97:41:97:57 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:99:45:99:61 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:99:45:99:61 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:104:30:104:44 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:104:30:104:44 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:106:40:106:81 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:106:40:106:81 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:108:34:108:75 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:108:34:108:75 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:110:34:110:75 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:110:34:110:75 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:112:23:112:37 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:112:23:112:37 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:117:23:117:37 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:117:23:117:37 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:122:23:122:40 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:122:23:122:40 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:124:20:124:34 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:124:20:124:34 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:126:21:126:35 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:126:21:126:35 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:128:22:128:36 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:128:22:128:36 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:133:20:133:34 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:133:20:133:34 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:135:19:135:33 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:135:19:135:33 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:140:20:140:36 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:140:20:140:36 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:34:52:34:68 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:34:52:34:68 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:36:32:36:48 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:36:32:36:48 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:38:47:38:63 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:38:47:38:63 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:40:39:40:53 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:40:39:40:53 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:42:31:42:45 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:42:31:42:45 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:44:29:44:43 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:44:29:44:43 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:46:24:46:38 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:46:24:46:38 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:48:9:48:41 | new FileReader(...) | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:48:24:48:40 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:50:20:50:34 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:50:20:50:34 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:51:20:51:34 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:51:20:51:34 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:52:20:52:41 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:52:20:52:41 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:54:33:54:47 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:54:33:54:47 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:55:33:55:55 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:55:33:55:55 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:56:40:56:54 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:56:40:56:54 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:58:33:58:47 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:58:33:58:47 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:60:31:60:45 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:60:31:60:45 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:62:26:62:40 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:62:26:62:40 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:64:26:64:40 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:64:26:64:40 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:66:34:66:48 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:66:34:66:48 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:68:35:68:49 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:68:35:68:49 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:70:30:70:44 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:70:30:70:44 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:72:22:72:36 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:72:22:72:36 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:74:30:74:44 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:74:30:74:44 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:76:21:76:35 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:76:21:76:35 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:78:26:78:40 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:78:26:78:40 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:80:33:80:47 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:80:33:80:47 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:82:33:82:47 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:82:33:82:47 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:83:33:83:47 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:83:33:83:47 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:85:31:85:45 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:85:31:85:45 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:87:21:87:35 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:87:21:87:35 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:88:21:88:35 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:88:21:88:35 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:89:21:89:35 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:89:21:89:35 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:91:27:91:41 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:91:27:91:41 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:92:27:92:41 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:92:27:92:41 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:94:26:94:40 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:94:26:94:40 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:96:35:96:49 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:96:35:96:49 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:98:41:98:57 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:98:41:98:57 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:100:45:100:61 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:100:45:100:61 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:102:43:102:57 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:102:43:102:57 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:104:28:104:42 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:104:28:104:42 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:106:41:106:55 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:106:41:106:55 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:111:30:111:44 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:111:30:111:44 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:113:40:113:81 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:113:40:113:81 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:115:34:115:75 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:115:34:115:75 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:117:34:117:75 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:117:34:117:75 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:119:23:119:37 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:119:23:119:37 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:124:23:124:37 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:124:23:124:37 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:129:23:129:40 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:129:23:129:40 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:131:20:131:34 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:131:20:131:34 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:133:21:133:35 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:133:21:133:35 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:135:22:135:36 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:135:22:135:36 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:140:20:140:34 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:140:20:140:34 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:142:19:142:33 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:142:19:142:33 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
| mad/Test.java:147:20:147:36 | (...)... | mad/Test.java:29:16:29:36 | getHostName(...) : String | mad/Test.java:147:20:147:36 | (...)... | This path depends on a $@. | mad/Test.java:29:16:29:36 | getHostName(...) | user-provided value |
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.apache.tools.ant.types.FileSet;
|
||||
import org.codehaus.cargo.container.installer.ZipURLInstaller;
|
||||
import org.kohsuke.stapler.framework.io.LargeText;
|
||||
import org.openjdk.jmh.runner.options.ChainedOptionsBuilder;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
public class Test {
|
||||
|
||||
@@ -97,6 +98,12 @@ public class Test {
|
||||
new ZipURLInstaller((URL) null, (String) source(), "");
|
||||
// "org.codehaus.cargo.container.installer;ZipURLInstaller;true;ZipURLInstaller;(URL,String,String);;Argument[2];create-file;ai-generated"
|
||||
new ZipURLInstaller((URL) null, "", (String) source());
|
||||
// "org.springframework.util;FileCopyUtils;false;copy;(byte[],File);;Argument[1];create-file;manual"
|
||||
FileCopyUtils.copy((byte[]) null, (File) source());
|
||||
// "org.springframework.util;FileCopyUtils;false;copy;(File,File);;Argument[0];create-file;manual"
|
||||
FileCopyUtils.copy((File) source(), null);
|
||||
// "org.springframework.util;FileCopyUtils;false;copy;(File,File);;Argument[1];create-file;manual"
|
||||
FileCopyUtils.copy((File) null, (File) source());
|
||||
}
|
||||
|
||||
void test(AntClassLoader acl) {
|
||||
|
||||
@@ -1 +1 @@
|
||||
// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/servlet-api-2.4:${testdir}/../../../../../stubs/apache-commons-io-2.6:${testdir}/../../../../../stubs/cargo:${testdir}/../../../../../stubs/apache-ant-1.10.13:${testdir}/../../../../../stubs/stapler-1.263:${testdir}/../../../../../stubs/javax-servlet-2.5:${testdir}/../../../../../stubs/apache-commons-jelly-1.0.1:${testdir}/../../../../../stubs/apache-commons-fileupload-1.4:${testdir}/../../../../../stubs/saxon-xqj-9.x:${testdir}/../../../../../stubs/apache-commons-beanutils:${testdir}/../../../../../stubs/dom4j-2.1.1:${testdir}/../../../../../stubs/apache-commons-lang:${testdir}/../../../../../stubs/jaxen-1.2.0:${testdir}/../../../../../stubs/jmh-1.3.6
|
||||
// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/servlet-api-2.4:${testdir}/../../../../../stubs/apache-commons-io-2.6:${testdir}/../../../../../stubs/cargo:${testdir}/../../../../../stubs/apache-ant-1.10.13:${testdir}/../../../../../stubs/stapler-1.263:${testdir}/../../../../../stubs/javax-servlet-2.5:${testdir}/../../../../../stubs/apache-commons-jelly-1.0.1:${testdir}/../../../../../stubs/apache-commons-fileupload-1.4:${testdir}/../../../../../stubs/saxon-xqj-9.x:${testdir}/../../../../../stubs/apache-commons-beanutils:${testdir}/../../../../../stubs/dom4j-2.1.1:${testdir}/../../../../../stubs/apache-commons-lang:${testdir}/../../../../../stubs/jaxen-1.2.0:${testdir}/../../../../../stubs/jmh-1.3.6:${testdir}/../../../../../stubs/springframework-5.3.8
|
||||
@@ -43,6 +43,9 @@ function isTypeAlwaysSafeToExpand(type: ts.Type): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (type.aliasSymbol != null) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -447,7 +450,7 @@ export class TypeTable {
|
||||
this.isInShallowTypeContext ? TypeExtractionState.PendingShallow : TypeExtractionState.PendingFull);
|
||||
// If the type is the self-type for a named type (not a generic instantiation of it),
|
||||
// emit the self-type binding for that type.
|
||||
if (content.startsWith("reference;") && !(isTypeReference(type) && type.target !== type)) {
|
||||
if (content.startsWith("reference;") && isTypeSelfReference(type)) {
|
||||
this.selfTypes.symbols.push(this.getSymbolId(type.aliasSymbol || type.symbol));
|
||||
this.selfTypes.selfTypes.push(id);
|
||||
}
|
||||
@@ -533,7 +536,7 @@ export class TypeTable {
|
||||
let enclosingType = getEnclosingTypeOfThisType(type);
|
||||
if (enclosingType != null) {
|
||||
return "this;" + this.getId(enclosingType, false);
|
||||
} else if (symbol.parent == null) {
|
||||
} else if (symbol.parent == null || isFunctionTypeOrTypeAlias(symbol.declarations?.[0])) {
|
||||
// The type variable is bound on a call signature. Only extract it by name.
|
||||
return "lextypevar;" + symbol.name;
|
||||
} else {
|
||||
@@ -614,14 +617,14 @@ export class TypeTable {
|
||||
// cannot be written using TypeScript syntax - so we ignore them entirely.
|
||||
return null;
|
||||
}
|
||||
return this.makeTypeStringVector("union", unionType.types);
|
||||
return this.makeDeduplicatedTypeStringVector("union", unionType.types);
|
||||
}
|
||||
if (flags & ts.TypeFlags.Intersection) {
|
||||
let intersectionType = type as ts.IntersectionType;
|
||||
if (intersectionType.types.length === 0) {
|
||||
return null; // Ignore malformed type.
|
||||
}
|
||||
return this.makeTypeStringVector("intersection", intersectionType.types);
|
||||
return this.makeDeduplicatedTypeStringVector("intersection", intersectionType.types);
|
||||
}
|
||||
if (isTypeReference(type) && (type.target.objectFlags & ts.ObjectFlags.Tuple)) {
|
||||
// Encode the minimum length and presence of rest element in the first two parts of the type string.
|
||||
@@ -784,6 +787,27 @@ export class TypeTable {
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the given string with the IDs of the given types appended,
|
||||
* ignoring duplicates, and each separated by `;`.
|
||||
*/
|
||||
private makeDeduplicatedTypeStringVector(tag: string, types: ReadonlyArray<ts.Type>, length = types.length): string | null {
|
||||
let seenIds = new Set<number>();
|
||||
let numberOfSeenIds = 0;
|
||||
let hash = tag;
|
||||
for (let i = 0; i < length; ++i) {
|
||||
let id = this.getId(types[i], false);
|
||||
if (id == null) return null;
|
||||
seenIds.add(id);
|
||||
if (seenIds.size > numberOfSeenIds) {
|
||||
// This ID was not seen before
|
||||
++numberOfSeenIds;
|
||||
hash += ";" + id;
|
||||
}
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/** Returns the type of `symbol` or `null` if it could not be computed. */
|
||||
private tryGetTypeOfSymbol(symbol: ts.Symbol) {
|
||||
try {
|
||||
@@ -1328,3 +1352,35 @@ export class TypeTable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isFunctionTypeOrTypeAlias(declaration: ts.Declaration | undefined) {
|
||||
if (declaration == null) return false;
|
||||
return declaration.kind === ts.SyntaxKind.FunctionType || declaration.kind === ts.SyntaxKind.TypeAliasDeclaration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a `type` whose type-string is known to be a `reference`, returns true if this is the self-type for the referenced type.
|
||||
*
|
||||
* For example, for `type Foo<R> = ...` this returns true if `type` is `Foo<R>`.
|
||||
*/
|
||||
function isTypeSelfReference(type: ts.Type) {
|
||||
if (type.aliasSymbol != null) {
|
||||
const { aliasTypeArguments } = type;
|
||||
if (aliasTypeArguments == null) return true;
|
||||
let declaration = type.aliasSymbol.declarations?.[0];
|
||||
if (declaration == null || declaration.kind !== ts.SyntaxKind.TypeAliasDeclaration) return false;
|
||||
let alias = declaration as ts.TypeAliasDeclaration;
|
||||
for (let i = 0; i < aliasTypeArguments.length; ++i) {
|
||||
if (aliasTypeArguments[i].symbol?.declarations?.[0] !== alias.typeParameters[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if (isTypeReference(type)) {
|
||||
return type.target === type;
|
||||
} else {
|
||||
// Return true because we know we have mapped this type to kind `reference`, and in the cases
|
||||
// not covered above (i.e. generic types) it is always a self-reference.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
@@ -1237,19 +1238,29 @@ protected DependencyInstallationResult preparePackagesAndDependencies(Set<Path>
|
||||
List<ParseError> errors = loc == null ? Collections.emptyList() : loc.getParseErrors();
|
||||
for (ParseError err : errors) {
|
||||
String msg = "A parse error occurred: " + StringUtil.quoteWithBackticks(err.getMessage().trim())
|
||||
+ ". Check the syntax of the file. If the file is invalid, correct the error or [exclude](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/customizing-code-scanning) the file from analysis.";
|
||||
// file, relative to the source root
|
||||
DiagnosticLocation.Builder builder = DiagnosticLocation.builder();
|
||||
+ ".";
|
||||
|
||||
Optional<DiagnosticLocation> diagLoc = Optional.empty();
|
||||
if (file.startsWith(LGTM_SRC)) {
|
||||
builder = builder.setFile(file.subpath(LGTM_SRC.getNameCount(), file.getNameCount()).toString());
|
||||
}
|
||||
DiagnosticLocation diagLoc = builder
|
||||
diagLoc = DiagnosticLocation.builder()
|
||||
.setFile(file.subpath(LGTM_SRC.getNameCount(), file.getNameCount()).toString()) // file, relative to the source root
|
||||
.setStartLine(err.getPosition().getLine())
|
||||
.setStartColumn(err.getPosition().getColumn() + 1) // convert from 0-based to 1-based
|
||||
.setEndLine(err.getPosition().getLine())
|
||||
.setEndColumn(err.getPosition().getColumn() + 1) // convert from 0-based to 1-based
|
||||
.build();
|
||||
writeDiagnostics(msg, JSDiagnosticKind.PARSE_ERROR, diagLoc);
|
||||
.build()
|
||||
.getOk();
|
||||
}
|
||||
if (diagLoc.isPresent()) {
|
||||
msg += " Check the syntax of the file. If the file is invalid, correct the error or "
|
||||
+ "[exclude](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-"
|
||||
+ "your-code-for-vulnerabilities-and-errors/customizing-code-scanning) the file from analysis.";
|
||||
writeDiagnostics(msg, JSDiagnosticKind.PARSE_ERROR, diagLoc.get());
|
||||
} else {
|
||||
msg += " The affected file is not located within the code being analyzed."
|
||||
+ (Env.systemEnv().isActions() ? " Please see the workflow run logs for more information." : "");
|
||||
writeDiagnostics(msg, JSDiagnosticKind.PARSE_ERROR);
|
||||
}
|
||||
}
|
||||
logEndProcess(start, "Done extracting " + file);
|
||||
} catch (OutOfMemoryError oom) {
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: fix
|
||||
---
|
||||
* Fixes an issue that would cause TypeScript extraction to hang in rare cases when extracting
|
||||
code containing recursive generic type aliases.
|
||||
@@ -0,0 +1,15 @@
|
||||
typeAliases
|
||||
| tst.ts:1:8:1:41 | type Fo ... R \| A>; |
|
||||
| tst.ts:3:8:3:42 | type Ba ... R, A]>; |
|
||||
| tst.ts:5:8:5:47 | type Ba ... => A>; |
|
||||
typeAliasType
|
||||
| tst.ts:1:8:1:41 | type Fo ... R \| A>; | Foo<R> |
|
||||
| tst.ts:3:8:3:42 | type Ba ... R, A]>; | Bar<R> |
|
||||
| tst.ts:5:8:5:47 | type Ba ... => A>; | Baz<R> |
|
||||
getAliasedType
|
||||
| Bar<R> | <A>() => Bar<[R, A]> |
|
||||
| Bar<[R, A]> | <A>() => Bar<[[R, A], A]> |
|
||||
| Baz<(x: R) => A> | <A>() => Baz<(x: (x: R) => A) => A> |
|
||||
| Baz<R> | <A>() => Baz<(x: R) => A> |
|
||||
| Foo<R \| A> | <A>() => Foo<R \| A> |
|
||||
| Foo<R> | <A>() => Foo<R \| A> |
|
||||
@@ -0,0 +1,8 @@
|
||||
import javascript
|
||||
|
||||
// The extractor would hang on this test case, it doesn't matter too much what the output of the test is.
|
||||
query TypeAliasDeclaration typeAliases() { any() }
|
||||
|
||||
query Type typeAliasType(TypeAliasDeclaration decl) { result = decl.getTypeName().getType() }
|
||||
|
||||
query Type getAliasedType(TypeAliasReference ref) { result = ref.getAliasedType() }
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"include": ["."]
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export type Foo<R> = <A>() => Foo<R | A>;
|
||||
|
||||
export type Bar<R> = <A>() => Bar<[R, A]>;
|
||||
|
||||
export type Baz<R> = <A>() => Baz<(x: R) => A>;
|
||||
@@ -43,3 +43,13 @@ def codeql_workspace(repository_name = "codeql"):
|
||||
"https://github.com/bazelbuild/bazel-skylib/releases/download/1.4.1/bazel-skylib-1.4.1.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
maybe(
|
||||
repo_rule = http_archive,
|
||||
name = "absl",
|
||||
sha256 = "cec2e5bf780532bd0ac672eb8d43c0f8bbe84ca5df8718320184034b7f59a398",
|
||||
urls = [
|
||||
"https://github.com/abseil/abseil-cpp/archive/d2c5297a3c3948de765100cb7e5cccca1210d23c.tar.gz",
|
||||
],
|
||||
strip_prefix = "abseil-cpp-d2c5297a3c3948de765100cb7e5cccca1210d23c",
|
||||
)
|
||||
|
||||
@@ -1,222 +0,0 @@
|
||||
#!/bin/env python3
|
||||
|
||||
"""
|
||||
usage: test_upgrade.py [-h] [--learn] [--accept] [--verbose] [DIR ...]
|
||||
|
||||
Run upgrade/downgrade scripts unit tests
|
||||
|
||||
positional arguments:
|
||||
DIR directories to look for upgrade/downgrade scripts in
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
--learn write down test results in expected files
|
||||
--accept accept actual results
|
||||
--verbose, -v print codeql output
|
||||
|
||||
Tests must be contained within a `test` directory directly within the upgrade/downgrade script directory, and
|
||||
take the form of a `<name>.trap` file containing the initial data of the DB and `<name>.expected` containing a
|
||||
form of difference between the database before and after the upgrade/downgrade is applied, similar to the format
|
||||
of `codeql database diff`. It is required and checked that the initial data is consistent with `old.dbscheme`, and
|
||||
it is then checked that final data is consistent with the new dbscheme.
|
||||
|
||||
Behavior is similar to `codeql test run`: if the test fails, a `<name>.actual` file is created, and `--accept`
|
||||
can be later used to accept the test result. `--learn` can be used to directly write the result in the
|
||||
`<name>.expected` file.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import pathlib
|
||||
import subprocess
|
||||
import sys
|
||||
import typing
|
||||
import shutil
|
||||
import difflib
|
||||
|
||||
class Error(Exception):
|
||||
def __str__(self):
|
||||
return f">>> {super().__str__()}"
|
||||
|
||||
verbose = False
|
||||
|
||||
def codeql(*args, quiet=False, **kwargs) -> str:
|
||||
cmd = ["codeql"]
|
||||
cmd.extend(args)
|
||||
for k, v in kwargs.items():
|
||||
k = k.replace('_', '-')
|
||||
cmd.append(f"--{k}" if v is True else f"--{k}={v}")
|
||||
result = subprocess.run(cmd, capture_output=True, text=True)
|
||||
if not quiet and verbose:
|
||||
sys.stderr.write(result.stderr)
|
||||
if result.returncode:
|
||||
cmd = " ".join(str(arg) for arg in cmd)
|
||||
out = (result.stderr + result.stdout).strip()
|
||||
raise Error(f"FAILURE running {cmd}:\n{out}")
|
||||
return result.stdout
|
||||
|
||||
|
||||
def options() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(description="Run upgrade/downgrade scripts unit tests")
|
||||
parser.add_argument("--learn", action="store_true", help="write down test results in expected files")
|
||||
parser.add_argument("--accept", action="store_true", help="accept actual results")
|
||||
parser.add_argument("--verbose", "-v", action="store_true", help="print codeql output")
|
||||
parser.add_argument("script_dirs", nargs="*", type=pathlib.Path, default=[pathlib.Path()],
|
||||
metavar="DIR", help="directories to look for upgrade/downgrade scripts in")
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def collect_tests(dirs: typing.Iterable[pathlib.Path]) -> typing.Iterable[typing.Tuple[pathlib.Path, str]]:
|
||||
for dir in dirs:
|
||||
for script in dir.rglob("upgrade.properties"):
|
||||
if not (script.parent / "test").is_dir():
|
||||
continue
|
||||
script_kind = script.parents[1].name
|
||||
if script_kind == "upgrades":
|
||||
pack = script.parents[4]
|
||||
elif script_kind == "downgrades":
|
||||
pack = script.parents[2]
|
||||
else:
|
||||
raise Error(f"{script} is not within a standard upgrades or downgrades directory")
|
||||
if pack.name == "extractor-pack":
|
||||
# do not run tests within extractor packs!
|
||||
continue
|
||||
for test in script.parent.glob("test/*.trap"):
|
||||
yield test, pack.name
|
||||
|
||||
|
||||
def extract_tuples(db: pathlib.Path, lang: str, dbschemename: str):
|
||||
"""
|
||||
Slightly hacky workaround to get all tuples of a DB in the format of `database diff --no-resolve-tuples`, by
|
||||
running the diff against an empty DB with the same dbscheme and parsing the result.
|
||||
"""
|
||||
empty = db.with_suffix(".empty")
|
||||
shutil.rmtree(empty, ignore_errors=True)
|
||||
codeql("database", "init", empty, source_root=".", language=lang)
|
||||
(empty / "src").mkdir()
|
||||
codeql("database", "finalize", empty, dbscheme=db / f"db-{lang}" / dbschemename)
|
||||
|
||||
diff_lines = codeql("database", "diff", empty, db, no_resolve_tuples=True, mode="tables", quiet=True).splitlines(keepends=True)
|
||||
shutil.rmtree(empty)
|
||||
|
||||
tables = {}
|
||||
for line in diff_lines:
|
||||
if line.startswith("+++"):
|
||||
table = pathlib.Path(line[4:].strip()).name
|
||||
elif line.startswith("+"):
|
||||
tables.setdefault(table, []).append(line[1:])
|
||||
return tables
|
||||
|
||||
def run_test(test: pathlib.Path, lang: str, learn: bool):
|
||||
print(">>>", test, end=" " if not verbose else "\n")
|
||||
sys.stdout.flush()
|
||||
|
||||
upgrade_scrip_dir = test.parents[1]
|
||||
dbschemename = next(f for f in upgrade_scrip_dir.glob("*.dbscheme") if f.stem != "old").name
|
||||
working_dir = test.with_suffix(".testproj")
|
||||
working_dir.mkdir(exist_ok=True)
|
||||
shutil.copy(upgrade_scrip_dir / "old.dbscheme", working_dir / dbschemename)
|
||||
|
||||
# create old version of database
|
||||
olddb = working_dir / "old-db"
|
||||
olddataset = olddb / f"db-{lang}"
|
||||
shutil.rmtree(olddb, ignore_errors=True)
|
||||
codeql("database", "init", olddb, source_root=".", language=lang)
|
||||
(olddb / "src").mkdir() # make sure codeql does not complain about non extracted sources
|
||||
(olddb / "trap" / lang).mkdir(parents=True)
|
||||
shutil.copy(test, olddb / "trap" / lang)
|
||||
codeql("database", "finalize", olddb, dbscheme=working_dir / dbschemename)
|
||||
with open(olddataset / f"{dbschemename}.stats", "w") as stats:
|
||||
print("<dbstats><typesizes /><stats /></dbstats>", file=stats)
|
||||
codeql("dataset", "check", olddataset)
|
||||
|
||||
# perform upgrade
|
||||
newdb = working_dir / "new-db"
|
||||
newdataset = newdb / f"db-{lang}"
|
||||
shutil.rmtree(newdb, ignore_errors=True)
|
||||
shutil.copytree(olddb, newdb)
|
||||
codeql("execute", "upgrades", newdataset, upgrade_scrip_dir)
|
||||
# sometimes the above generates a stats file in the script dir, let's clean it up
|
||||
for stat in upgrade_scrip_dir.glob("*.stats"):
|
||||
stat.unlink()
|
||||
codeql("dataset", "check", newdataset)
|
||||
|
||||
# compare tables
|
||||
# as `codeql database diff` does not allow comparing DBs with different dbschemes, we just
|
||||
# do the diff ourselves
|
||||
tuples = extract_tuples(olddb, lang, dbschemename)
|
||||
new_tuples = extract_tuples(newdb, lang, dbschemename)
|
||||
|
||||
for table in tuples:
|
||||
tuples[table] = (tuples[table], new_tuples.pop(table, None))
|
||||
|
||||
for table, value in new_tuples.items():
|
||||
tuples[table] = (None, value)
|
||||
|
||||
actual_lines = []
|
||||
for table, (old, new) in sorted(tuples.items()):
|
||||
size = len(actual_lines)
|
||||
actual_lines.extend(difflib.unified_diff(
|
||||
old or [],
|
||||
new or [],
|
||||
fromfile=f"old/{table}" if old is not None else "<created>",
|
||||
tofile=f"new/{table}" if new is not None else "<deleted>",
|
||||
n=0))
|
||||
if len(actual_lines) > size:
|
||||
actual_lines.append("\n")
|
||||
|
||||
# for this unified diff line numbers @@-lines are just noise
|
||||
actual_lines[:] = [l for l in actual_lines if not l.startswith("@@")]
|
||||
|
||||
# manage .actual/.expected interactions
|
||||
actual = test.with_suffix(".actual")
|
||||
actual.unlink(missing_ok=True)
|
||||
expected = test.with_suffix(".expected")
|
||||
if not learn:
|
||||
with open(expected) as expectedin:
|
||||
expected_lines = expectedin.readlines()
|
||||
|
||||
diff = list(difflib.unified_diff(expected_lines, actual_lines, fromfile=str(expected), tofile=str(actual)))
|
||||
if diff:
|
||||
with open(actual, "w") as actualout:
|
||||
actualout.writelines(actual_lines)
|
||||
print("FAILURE")
|
||||
raise Error(f"{test} FAILURE:\n{''.join(diff)}")
|
||||
else:
|
||||
print("SUCCESS")
|
||||
else:
|
||||
with open(expected, "w") as expectedout:
|
||||
expectedout.writelines(actual_lines)
|
||||
print("SUCCESS (results learned)")
|
||||
|
||||
|
||||
def accept_test_results(test: pathlib.Path):
|
||||
actual = test.with_suffix(".actual")
|
||||
if actual.is_file():
|
||||
actual.rename(test.with_suffix(".expected"))
|
||||
print(f"=== {test} results accepted ===")
|
||||
|
||||
def main(opts: argparse.Namespace):
|
||||
global verbose
|
||||
verbose = opts.verbose
|
||||
errors = []
|
||||
for dir in opts.script_dirs:
|
||||
if (dir / "upgrade.properties").is_file() and not (dir / "test").is_dir():
|
||||
errors.append(Error(
|
||||
f"testing of {dir.relative_to(dir.parents[1])} explicitly requested, but no test directory found"))
|
||||
tests = collect_tests(opts.script_dirs)
|
||||
if opts.accept:
|
||||
for test, _ in tests:
|
||||
accept_test_results(test)
|
||||
else:
|
||||
for test, lang in tests:
|
||||
try:
|
||||
run_test(test, lang, opts.learn)
|
||||
except Error as e:
|
||||
errors.append(e)
|
||||
if errors:
|
||||
for e in errors:
|
||||
print(e, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(options())
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
||||
description: Add YAML tables
|
||||
compatibility: backwards
|
||||
|
||||
yaml.rel: delete
|
||||
yaml_anchors.rel: delete
|
||||
yaml_aliases.rel: delete
|
||||
yaml_scalars.rel: delete
|
||||
yaml_errors.rel: delete
|
||||
yaml_locations.rel: delete
|
||||
|
||||
4
python/ql/lib/change-notes/2023-04-20-yaml.md
Normal file
4
python/ql/lib/change-notes/2023-04-20-yaml.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added support for querying the contents of YAML files.
|
||||
@@ -9,5 +9,6 @@ dependencies:
|
||||
codeql/regex: ${workspace}
|
||||
codeql/tutorial: ${workspace}
|
||||
codeql/util: ${workspace}
|
||||
codeql/yaml: ${workspace}
|
||||
dataExtensions:
|
||||
- semmle/python/frameworks/**/model.yml
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
import python
|
||||
import semmle.python.RegexTreeView
|
||||
import semmle.python.Yaml
|
||||
|
||||
private newtype TPrintAstConfiguration = MkPrintAstConfiguration()
|
||||
|
||||
@@ -53,7 +54,9 @@ private newtype TPrintAstNode =
|
||||
shouldPrint(list.getAnItem(), _) and
|
||||
not list = any(Module mod).getBody() and
|
||||
not forall(AstNode child | child = list.getAnItem() | isNotNeeded(child))
|
||||
}
|
||||
} or
|
||||
TYamlNode(YamlNode node) or
|
||||
TYamlMappingNode(YamlMapping mapping, int i) { exists(mapping.getKeyNode(i)) }
|
||||
|
||||
/**
|
||||
* A node in the output tree.
|
||||
@@ -633,6 +636,80 @@ private module PrettyPrinting {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Classes for printing YAML AST.
|
||||
*/
|
||||
module PrintYaml {
|
||||
/**
|
||||
* A print node representing a YAML value in a .yml file.
|
||||
*/
|
||||
class YamlNodeNode extends PrintAstNode, TYamlNode {
|
||||
YamlNode node;
|
||||
|
||||
YamlNodeNode() { this = TYamlNode(node) }
|
||||
|
||||
override string toString() {
|
||||
result = "[" + concat(node.getAPrimaryQlClass(), ",") + "] " + node.toString()
|
||||
}
|
||||
|
||||
override Location getLocation() { result = node.getLocation() }
|
||||
|
||||
/**
|
||||
* Gets the `YAMLNode` represented by this node.
|
||||
*/
|
||||
final YamlNode getValue() { result = node }
|
||||
|
||||
override PrintAstNode getChild(int childIndex) {
|
||||
exists(YamlNode child | result.(YamlNodeNode).getValue() = child |
|
||||
child = node.getChildNode(childIndex)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A print node representing a `YAMLMapping`.
|
||||
*
|
||||
* Each child of this node aggregates the key and value of a mapping.
|
||||
*/
|
||||
class YamlMappingNode extends YamlNodeNode {
|
||||
override YamlMapping node;
|
||||
|
||||
override PrintAstNode getChild(int childIndex) {
|
||||
exists(YamlMappingMapNode map | map = result | map.maps(node, childIndex))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A print node representing the `i`th mapping in `mapping`.
|
||||
*/
|
||||
class YamlMappingMapNode extends PrintAstNode, TYamlMappingNode {
|
||||
YamlMapping mapping;
|
||||
int i;
|
||||
|
||||
YamlMappingMapNode() { this = TYamlMappingNode(mapping, i) }
|
||||
|
||||
override string toString() {
|
||||
result = "(Mapping " + i + ")" and not exists(mapping.getKeyNode(i).(YamlScalar).getValue())
|
||||
or
|
||||
result = "(Mapping " + i + ") " + mapping.getKeyNode(i).(YamlScalar).getValue() + ":"
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this print node represents the `index`th mapping of `m`.
|
||||
*/
|
||||
predicate maps(YamlMapping m, int index) {
|
||||
m = mapping and
|
||||
index = i
|
||||
}
|
||||
|
||||
override PrintAstNode getChild(int childIndex) {
|
||||
childIndex = 0 and result.(YamlNodeNode).getValue() = mapping.getKeyNode(i)
|
||||
or
|
||||
childIndex = 1 and result.(YamlNodeNode).getValue() = mapping.getValueNode(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if `node` belongs to the output tree, and its property `key` has the given `value`. */
|
||||
query predicate nodes(PrintAstNode node, string key, string value) { value = node.getProperty(key) }
|
||||
|
||||
|
||||
50
python/ql/lib/semmle/python/Yaml.qll
Normal file
50
python/ql/lib/semmle/python/Yaml.qll
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Provides classes for working with YAML data.
|
||||
*
|
||||
* YAML documents are represented as abstract syntax trees whose nodes
|
||||
* are either YAML values or alias nodes referring to another YAML value.
|
||||
*/
|
||||
|
||||
private import codeql.yaml.Yaml as LibYaml
|
||||
|
||||
private module YamlSig implements LibYaml::InputSig {
|
||||
import semmle.python.Files
|
||||
|
||||
class LocatableBase extends @yaml_locatable {
|
||||
Location getLocation() { yaml_locations(this, result) }
|
||||
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class NodeBase extends LocatableBase, @yaml_node {
|
||||
NodeBase getChildNode(int i) { yaml(result, _, this, i, _, _) }
|
||||
|
||||
string getTag() { yaml(this, _, _, _, result, _) }
|
||||
|
||||
string getAnchor() { yaml_anchors(this, result) }
|
||||
|
||||
override string toString() { yaml(this, _, _, _, _, result) }
|
||||
}
|
||||
|
||||
class ScalarNodeBase extends NodeBase, @yaml_scalar_node {
|
||||
int getStyle() { yaml_scalars(this, result, _) }
|
||||
|
||||
string getValue() { yaml_scalars(this, _, result) }
|
||||
}
|
||||
|
||||
class CollectionNodeBase extends NodeBase, @yaml_collection_node { }
|
||||
|
||||
class MappingNodeBase extends CollectionNodeBase, @yaml_mapping_node { }
|
||||
|
||||
class SequenceNodeBase extends CollectionNodeBase, @yaml_sequence_node { }
|
||||
|
||||
class AliasNodeBase extends NodeBase, @yaml_alias_node {
|
||||
string getTarget() { yaml_aliases(this, result) }
|
||||
}
|
||||
|
||||
class ParseErrorBase extends LocatableBase, @yaml_error {
|
||||
string getMessage() { yaml_errors(this, result) }
|
||||
}
|
||||
}
|
||||
|
||||
import LibYaml::Make<YamlSig>
|
||||
@@ -361,3 +361,52 @@ module MergePathGraph<
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a `PathGraph` from three `PathGraph`s by disjoint union.
|
||||
*/
|
||||
module MergePathGraph3<
|
||||
PathNodeSig PathNode1, PathNodeSig PathNode2, PathNodeSig PathNode3,
|
||||
PathGraphSig<PathNode1> Graph1, PathGraphSig<PathNode2> Graph2, PathGraphSig<PathNode3> Graph3>
|
||||
{
|
||||
private module MergedInner = MergePathGraph<PathNode1, PathNode2, Graph1, Graph2>;
|
||||
|
||||
private module Merged =
|
||||
MergePathGraph<MergedInner::PathNode, PathNode3, MergedInner::PathGraph, Graph3>;
|
||||
|
||||
/** A node in a graph of path explanations that is formed by disjoint union of the three given graphs. */
|
||||
class PathNode instanceof Merged::PathNode {
|
||||
/** Gets this as a projection on the first given `PathGraph`. */
|
||||
PathNode1 asPathNode1() { result = super.asPathNode1().asPathNode1() }
|
||||
|
||||
/** Gets this as a projection on the second given `PathGraph`. */
|
||||
PathNode2 asPathNode2() { result = super.asPathNode1().asPathNode2() }
|
||||
|
||||
/** Gets this as a projection on the third given `PathGraph`. */
|
||||
PathNode3 asPathNode3() { result = super.asPathNode2() }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets the underlying `Node`. */
|
||||
Node getNode() { result = super.getNode() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the query predicates needed to include a graph in a path-problem query.
|
||||
*/
|
||||
module PathGraph = Merged::PathGraph;
|
||||
}
|
||||
|
||||
@@ -1200,6 +1200,7 @@ predicate normalCallArg(CallNode call, Node arg, ArgumentPosition apos) {
|
||||
* time the bound method is used, such that the `clear()` call would essentially be
|
||||
* translated into `l.clear()`, and we can still have use-use flow.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
cached
|
||||
predicate getCallArg(CallNode call, Function target, CallType type, Node arg, ArgumentPosition apos) {
|
||||
Stages::DataFlow::ref() and
|
||||
|
||||
@@ -1104,3 +1104,44 @@ xmllocations(int xmlElement: @xmllocatable ref,
|
||||
int location: @location_default ref);
|
||||
|
||||
@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
|
||||
|
||||
/**
|
||||
* YAML
|
||||
*/
|
||||
|
||||
#keyset[parent, idx]
|
||||
yaml (unique int id: @yaml_node,
|
||||
int kind: int ref,
|
||||
int parent: @yaml_node_parent ref,
|
||||
int idx: int ref,
|
||||
varchar(900) tag: string ref,
|
||||
varchar(900) tostring: string ref);
|
||||
|
||||
case @yaml_node.kind of
|
||||
0 = @yaml_scalar_node
|
||||
| 1 = @yaml_mapping_node
|
||||
| 2 = @yaml_sequence_node
|
||||
| 3 = @yaml_alias_node
|
||||
;
|
||||
|
||||
@yaml_collection_node = @yaml_mapping_node | @yaml_sequence_node;
|
||||
|
||||
@yaml_node_parent = @yaml_collection_node | @file;
|
||||
|
||||
yaml_anchors (unique int node: @yaml_node ref,
|
||||
varchar(900) anchor: string ref);
|
||||
|
||||
yaml_aliases (unique int alias: @yaml_alias_node ref,
|
||||
varchar(900) target: string ref);
|
||||
|
||||
yaml_scalars (unique int scalar: @yaml_scalar_node ref,
|
||||
int style: int ref,
|
||||
varchar(900) value: string ref);
|
||||
|
||||
yaml_errors (unique int id: @yaml_error,
|
||||
varchar(900) message: string ref);
|
||||
|
||||
yaml_locations(unique int locatable: @yaml_locatable ref,
|
||||
int location: @location_default ref);
|
||||
|
||||
@yaml_locatable = @yaml_node | @yaml_error;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user