Merge branch 'main' into redsun82/swift-diagnostics-wording

This commit is contained in:
Alexandre Boulgakov
2023-05-19 14:43:01 +01:00
committed by GitHub
145 changed files with 4240 additions and 3623 deletions

View File

@@ -27,9 +27,9 @@ jobs:
run: |
gh api 'repos/${{github.repository}}/pulls/${{github.event.number}}/files' --paginate --jq 'any(.[].filename ; test("/change-notes/.*[.]md$"))' |
grep true -c
- name: Fail if the change note filename doesn't match the expected format. The file name must be of the form 'YYYY-MM-DD.md' or 'YYYY-MM-DD-{title}.md', where '{title}' is arbitrary text.
- name: Fail if the change note filename doesn't match the expected format. The file name must be of the form 'YYYY-MM-DD.md', 'YYYY-MM-DD-{title}.md', where '{title}' is arbitrary text, or released/x.y.z.md for released change-notes
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh api 'repos/${{github.repository}}/pulls/${{github.event.number}}/files' --paginate --jq '[.[].filename | select(test("/change-notes/.*[.]md$"))] | all(test("/change-notes/[0-9]{4}-[0-9]{2}-[0-9]{2}.*[.]md$"))' |
grep true -c
gh api 'repos/${{github.repository}}/pulls/${{github.event.number}}/files' --paginate --jq '[.[].filename | select(test("/change-notes/.*[.]md$"))] | all(test("/change-notes/[0-9]{4}-[0-9]{2}-[0-9]{2}.*[.]md$") or test("/change-notes/released/[0-9]*[.][0-9]*[.][0-9]*[.]md$"))' |
grep true -c

18
.vscode/tasks.json vendored
View File

@@ -22,6 +22,22 @@
"command": "${config:python.pythonPath}",
},
"problemMatcher": []
},
{
"label": "Accept .expected changes from CI",
"type": "process",
// Non-Windows OS will usually have Python 3 already installed at /usr/bin/python3.
"command": "python3",
"args": [
"misc/scripts/accept-expected-changes-from-ci.py"
],
"group": "build",
"windows": {
// On Windows, use whatever Python interpreter is configured for this workspace. The default is
// just `python`, so if Python is already on the path, this will find it.
"command": "${config:python.pythonPath}",
},
"problemMatcher": []
}
]
}
}

View File

@@ -40,3 +40,6 @@ WORKSPACE.bazel @github/codeql-ci-reviewers
/.github/workflows/ql-for-ql-* @github/codeql-ql-for-ql-reviewers
/.github/workflows/ruby-* @github/codeql-ruby
/.github/workflows/swift.yml @github/codeql-swift
# Misc
/misc/scripts/accept-expected-changes-from-ci.py @RasmusWL

View File

@@ -290,9 +290,9 @@ module ProductFlow {
predicate isBarrierIn(DataFlow::Node node) { Config::isBarrierIn1(node) }
}
module Flow1 = DataFlow::GlobalWithState<Config1>;
private module Flow1 = DataFlow::GlobalWithState<Config1>;
module Config2 implements DataFlow::StateConfigSig {
private module Config2 implements DataFlow::StateConfigSig {
class FlowState = FlowState2;
predicate isSource(DataFlow::Node source, FlowState state) {
@@ -322,27 +322,90 @@ module ProductFlow {
predicate isBarrierIn(DataFlow::Node node) { Config::isBarrierIn2(node) }
}
module Flow2 = DataFlow::GlobalWithState<Config2>;
private module Flow2 = DataFlow::GlobalWithState<Config2>;
private predicate isSourcePair(Flow1::PathNode node1, Flow2::PathNode node2) {
Config::isSourcePair(node1.getNode(), node1.getState(), node2.getNode(), node2.getState())
}
private predicate isSinkPair(Flow1::PathNode node1, Flow2::PathNode node2) {
Config::isSinkPair(node1.getNode(), node1.getState(), node2.getNode(), node2.getState())
}
pragma[assume_small_delta]
pragma[nomagic]
private predicate fwdReachableInterprocEntry(Flow1::PathNode node1, Flow2::PathNode node2) {
isSourcePair(node1, node2)
or
fwdIsSuccessor(_, _, node1, node2)
}
pragma[nomagic]
private predicate reachableInterprocEntry(
Flow1::PathNode source1, Flow2::PathNode source2, Flow1::PathNode node1, Flow2::PathNode node2
private predicate fwdIsSuccessorExit(
Flow1::PathNode mid1, Flow2::PathNode mid2, Flow1::PathNode succ1, Flow2::PathNode succ2
) {
Config::isSourcePair(node1.getNode(), node1.getState(), node2.getNode(), node2.getState()) and
node1 = source1 and
node2 = source2
isSinkPair(mid1, mid2) and
succ1 = mid1 and
succ2 = mid2
or
exists(
Flow1::PathNode midEntry1, Flow2::PathNode midEntry2, Flow1::PathNode midExit1,
Flow2::PathNode midExit2
|
reachableInterprocEntry(source1, source2, midEntry1, midEntry2) and
interprocEdgePair(midExit1, midExit2, node1, node2) and
localPathStep1*(midEntry1, midExit1) and
localPathStep2*(midEntry2, midExit2)
interprocEdgePair(mid1, mid2, succ1, succ2)
}
private predicate fwdIsSuccessor1(
Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode mid1, Flow2::PathNode mid2,
Flow1::PathNode succ1, Flow2::PathNode succ2
) {
fwdReachableInterprocEntry(pred1, pred2) and
localPathStep1*(pred1, mid1) and
fwdIsSuccessorExit(pragma[only_bind_into](mid1), pragma[only_bind_into](mid2), succ1, succ2)
}
private predicate fwdIsSuccessor2(
Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode mid1, Flow2::PathNode mid2,
Flow1::PathNode succ1, Flow2::PathNode succ2
) {
fwdReachableInterprocEntry(pred1, pred2) and
localPathStep2*(pred2, mid2) and
fwdIsSuccessorExit(pragma[only_bind_into](mid1), pragma[only_bind_into](mid2), succ1, succ2)
}
pragma[assume_small_delta]
private predicate fwdIsSuccessor(
Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode succ1, Flow2::PathNode succ2
) {
exists(Flow1::PathNode mid1, Flow2::PathNode mid2 |
fwdIsSuccessor1(pred1, pred2, mid1, mid2, succ1, succ2) and
fwdIsSuccessor2(pred1, pred2, mid1, mid2, succ1, succ2)
)
}
pragma[assume_small_delta]
pragma[nomagic]
private predicate revReachableInterprocEntry(Flow1::PathNode node1, Flow2::PathNode node2) {
fwdReachableInterprocEntry(node1, node2) and
isSinkPair(node1, node2)
or
exists(Flow1::PathNode succ1, Flow2::PathNode succ2 |
revReachableInterprocEntry(succ1, succ2) and
fwdIsSuccessor(node1, node2, succ1, succ2)
)
}
private newtype TNodePair =
TMkNodePair(Flow1::PathNode node1, Flow2::PathNode node2) {
revReachableInterprocEntry(node1, node2)
}
private predicate pathSucc(TNodePair n1, TNodePair n2) {
exists(Flow1::PathNode n11, Flow2::PathNode n12, Flow1::PathNode n21, Flow2::PathNode n22 |
n1 = TMkNodePair(n11, n12) and
n2 = TMkNodePair(n21, n22) and
fwdIsSuccessor(n11, n12, n21, n22)
)
}
private predicate pathSuccPlus(TNodePair n1, TNodePair n2) = fastTC(pathSucc/2)(n1, n2)
private predicate localPathStep1(Flow1::PathNode pred, Flow1::PathNode succ) {
Flow1::PathGraph::edges(pred, succ) and
pragma[only_bind_out](pred.getNode().getEnclosingCallable()) =
@@ -474,11 +537,14 @@ module ProductFlow {
private predicate reachable(
Flow1::PathNode source1, Flow2::PathNode source2, Flow1::PathNode sink1, Flow2::PathNode sink2
) {
exists(Flow1::PathNode mid1, Flow2::PathNode mid2 |
reachableInterprocEntry(source1, source2, mid1, mid2) and
Config::isSinkPair(sink1.getNode(), sink1.getState(), sink2.getNode(), sink2.getState()) and
localPathStep1*(mid1, sink1) and
localPathStep2*(mid2, sink2)
isSourcePair(source1, source2) and
isSinkPair(sink1, sink2) and
exists(TNodePair n1, TNodePair n2 |
n1 = TMkNodePair(source1, source2) and
n2 = TMkNodePair(sink1, sink2)
|
pathSuccPlus(n1, n2) or
n1 = n2
)
}
}

View File

@@ -1699,7 +1699,28 @@ class AutoType extends TemplateParameter {
private predicate suppressUnusedThis(Type t) { any() }
/** A source code location referring to a type */
/**
* A source code location referring to a user-defined type.
*
* Note that only _user-defined_ types have `TypeMention`s. In particular,
* built-in types, and derived types with built-in types as their base don't
* have any `TypeMention`s. For example, given
* ```cpp
* struct S { ... };
* void f(S s1, int i1) {
* S s2;
* S* s3;
* S& s4 = s2;
* decltype(s2) s5;
*
* int i2;
* int* i3;
* int i4[10];
* }
* ```
* there will be a `TypeMention` for the mention of `S` at `S s1`, `S s2`, and `S& s4 = s2`,
* but not at `decltype(s2) s5`. Additionally, there will be no `TypeMention`s for `int`.
*/
class TypeMention extends Locatable, @type_mention {
override string toString() { result = "type mention" }

View File

@@ -657,24 +657,16 @@ private predicate indirectConversionFlowStep(Node nFrom, Node nTo) {
* So this predicate recurses back along conversions and `PointerArithmeticInstruction`s to find the
* first use that has provides use-use flow, and uses that target as the target of the `nodeFrom`.
*/
private predicate adjustForPointerArith(
DefOrUse defOrUse, Node nodeFrom, UseOrPhi use, boolean uncertain
) {
nodeFrom = any(PostUpdateNode pun).getPreUpdateNode() and
exists(Node adjusted |
indirectConversionFlowStep*(adjusted, nodeFrom) and
nodeToDefOrUse(adjusted, defOrUse, uncertain) and
private predicate adjustForPointerArith(PostUpdateNode pun, UseOrPhi use) {
exists(DefOrUse defOrUse, Node adjusted |
indirectConversionFlowStep*(adjusted, pun.getPreUpdateNode()) and
nodeToDefOrUse(adjusted, defOrUse, _) and
adjacentDefRead(defOrUse, use)
)
}
private predicate ssaFlowImpl(SsaDefOrUse defOrUse, Node nodeFrom, Node nodeTo, boolean uncertain) {
// `nodeFrom = any(PostUpdateNode pun).getPreUpdateNode()` is implied by adjustedForPointerArith.
exists(UseOrPhi use |
adjustForPointerArith(defOrUse, nodeFrom, use, uncertain) and
useToNode(use, nodeTo)
or
not nodeFrom = any(PostUpdateNode pun).getPreUpdateNode() and
nodeToDefOrUse(nodeFrom, defOrUse, uncertain) and
adjacentDefRead(defOrUse, use) and
useToNode(use, nodeTo) and
@@ -719,14 +711,19 @@ predicate ssaFlow(Node nodeFrom, Node nodeTo) {
)
}
private predicate isArgumentOfCallable(DataFlowCall call, ArgumentNode arg) {
arg.argumentOf(call, _)
}
/** Holds if there is def-use or use-use flow from `pun` to `nodeTo`. */
predicate postUpdateFlow(PostUpdateNode pun, Node nodeTo) {
exists(Node preUpdate, Node nFrom, boolean uncertain, SsaDefOrUse defOrUse |
exists(UseOrPhi use, Node preUpdate |
adjustForPointerArith(pun, use) and
useToNode(use, nodeTo) and
preUpdate = pun.getPreUpdateNode() and
ssaFlowImpl(defOrUse, nFrom, nodeTo, uncertain)
|
if uncertain = true
then preUpdate = [nFrom, getAPriorDefinition(defOrUse)]
else preUpdate = nFrom
not exists(DataFlowCall call |
isArgumentOfCallable(call, preUpdate) and isArgumentOfCallable(call, nodeTo)
)
)
}

View File

@@ -78,6 +78,145 @@ predicate isSinkPairImpl(
)
}
module ValidState {
/**
* In the `StringSizeConfig` configuration we use an integer as the flow state for the second
* projection of the dataflow graph. The integer represents an offset that is added to the
* size of the allocation. For example, given:
* ```cpp
* char* p = new char[size + 1];
* size += 1;
* memset(p, 0, size);
* ```
* the initial flow state is `1`. This represents the fact that `size + 1` is a valid bound
* for the size of the allocation pointed to by `p`. After updating the size using `+=`, the
* flow state changes to `0`, which represents the fact that `size + 0` is a valid bound for
* the allocation.
*
* So we need to compute a set of valid integers that represent the offset applied to the
* size. We do this in two steps:
* 1. We first perform the dataflow traversal that the second projection of the product-flow
* library will perform, and visit all the places where the size argument is modified.
* 2. Once that dataflow traversal is done, we accumulate the offsets added at each places
* where the offset is modified (see `validStateImpl`).
*
* Because we want to guarantee that each place where we modify the offset has a `PathNode`
* we "flip" a boolean flow state in each `isAdditionalFlowStep`. This ensures that the node
* has a corresponding `PathNode`.
*/
private module ValidStateConfig implements DataFlow::StateConfigSig {
class FlowState = boolean;
predicate isSource(DataFlow::Node source, FlowState state) {
hasSize(_, source, _) and
state = false
}
predicate isSink(DataFlow::Node sink, FlowState state) {
isSinkPairImpl(_, _, sink, _, _) and
state = [false, true]
}
predicate isBarrier(DataFlow::Node node, FlowState state) { none() }
predicate isAdditionalFlowStep(
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
) {
isAdditionalFlowStep2(node1, node2, _) and
state1 = [false, true] and
state2 = state1.booleanNot()
}
predicate includeHiddenNodes() { any() }
}
private import DataFlow::GlobalWithState<ValidStateConfig>
private predicate inLoop(PathNode n) { n.getASuccessor+() = n }
/**
* Holds if `value` is a possible offset for `n`.
*
* To ensure termination, we limit `value` to be in the
* range `[-2, 2]` if the node is part of a loop. Without
* this restriction we wouldn't terminate on an example like:
* ```cpp
* while(unknown()) { size++; }
* ```
*/
private predicate validStateImpl(PathNode n, int value) {
// If the dataflow node depends recursively on itself we restrict the range.
(inLoop(n) implies value = [-2 .. 2]) and
(
// For the dataflow source we have an allocation such as `malloc(size + k)`,
// and the value of the flow-state is then `k`.
hasSize(_, n.getNode(), value)
or
// For a dataflow sink any `value` that is strictly smaller than the delta
// needs to be a valid flow-state. That is, for a snippet like:
// ```
// p = b ? new char[size] : new char[size + 1];
// memset(p, 0, size + 2);
// ```
// the valid flow-states at the `memset` must include the set `{0, 1}` since the
// flow-state at `new char[size]` is `0`, and the flow-state at `new char[size + 1]`
// is `1`.
//
// So we find a valid flow-state at the sink's predecessor, and use the definition
// of our sink predicate to compute the valid flow-states at the sink.
exists(int delta, PathNode n0 |
n0.getASuccessor() = n and
validStateImpl(n0, value) and
isSinkPairImpl(_, _, n.getNode(), delta, _) and
delta > value
)
or
// For a non-source and non-sink node there is two cases to consider.
// 1. A node where we have to update the flow-state, or
// 2. A node that doesn't update the flow-state.
//
// For case 1, we compute the new flow-state by adding the constant operand of the
// `AddInstruction` to the flow-state of any predecessor node.
// For case 2 we simply propagate the valid flow-states from the predecessor node to
// the next one.
exists(PathNode n0, DataFlow::Node node0, DataFlow::Node node, int value0 |
n0.getASuccessor() = n and
validStateImpl(n0, value0) and
node = n.getNode() and
node0 = n0.getNode()
|
exists(int delta |
isAdditionalFlowStep2(node0, node, delta) and
value0 = value + delta
)
or
not isAdditionalFlowStep2(node0, node, _) and
value = value0
)
)
}
predicate validState(DataFlow::Node n, int value) {
validStateImpl(any(PathNode pn | pn.getNode() = n), value)
}
}
import ValidState
/**
* Holds if `node2` is a dataflow node that represents an addition of two operands `op1`
* and `op2` such that:
* 1. `node1` is the dataflow node that represents `op1`, and
* 2. the value of `op2` can be upper bounded by `delta.`
*/
predicate isAdditionalFlowStep2(DataFlow::Node node1, DataFlow::Node node2, int delta) {
exists(AddInstruction add, Operand op |
add.hasOperands(node1.asOperand(), op) and
semBounded(getSemanticExpr(op.getDef()), any(SemZeroBound zero), delta, true, _) and
node2.asInstruction() = add
)
}
module StringSizeConfig implements ProductFlow::StateConfigSig {
class FlowState1 = Unit;
@@ -100,7 +239,7 @@ module StringSizeConfig implements ProductFlow::StateConfigSig {
DataFlow::Node bufSink, FlowState1 state1, DataFlow::Node sizeSink, FlowState2 state2
) {
exists(state1) and
state2 = [-32 .. 32] and // An arbitrary bound because we need to bound `state2`
validState(sizeSink, state2) and
exists(int delta |
isSinkPairImpl(_, bufSink, sizeSink, delta, _) and
delta > state2
@@ -124,14 +263,10 @@ module StringSizeConfig implements ProductFlow::StateConfigSig {
predicate isAdditionalFlowStep2(
DataFlow::Node node1, FlowState2 state1, DataFlow::Node node2, FlowState2 state2
) {
exists(AddInstruction add, Operand op, int delta, int s1, int s2 |
s1 = [-32 .. 32] and // An arbitrary bound because we need to bound `state`
state1 = s1 and
state2 = s2 and
add.hasOperands(node1.asOperand(), op) and
semBounded(getSemanticExpr(op.getDef()), any(SemZeroBound zero), delta, true, _) and
node2.asInstruction() = add and
s1 = s2 + delta
validState(node2, state2) and
exists(int delta |
isAdditionalFlowStep2(node1, node2, delta) and
state1 = state2 + delta
)
}
}

View File

@@ -48,44 +48,23 @@ bindingset[b]
pragma[inline_late]
predicate bounded2(Instruction i, Instruction b, int delta) { boundedImpl(i, b, delta) }
/**
* Holds if the combination of `n` and `state` represents an appropriate
* source for the expression `e` suitable for use-use flow.
*/
private predicate hasSizeImpl(Expr e, DataFlow::Node n, int state) {
// The simple case: If the size is a variable access with no qualifier we can just use the
// dataflow node for that expression and no state.
exists(VariableAccess va |
va = e and
not va instanceof FieldAccess and
n.asConvertedExpr() = va.getFullyConverted() and
state = 0
)
or
// If the size is a choice between two expressions we allow both to be nodes representing the size.
exists(ConditionalExpr cond | cond = e | hasSizeImpl([cond.getThen(), cond.getElse()], n, state))
or
// If the size is an expression plus a constant, we pick the dataflow node of the expression and
// remember the constant in the state.
exists(Expr const, Expr nonconst |
e.(AddExpr).hasOperands(const, nonconst) and
state = const.getValue().toInt() and
hasSizeImpl(nonconst, n, _)
)
or
exists(Expr const, Expr nonconst |
e.(SubExpr).hasOperands(const, nonconst) and
state = -const.getValue().toInt() and
hasSizeImpl(nonconst, n, _)
)
}
VariableAccess getAVariableAccess(Expr e) { e.getAChild*() = result }
/**
* Holds if `(n, state)` pair represents the source of flow for the size
* expression associated with `alloc`.
*/
predicate hasSize(HeuristicAllocationExpr alloc, DataFlow::Node n, int state) {
hasSizeImpl(alloc.getSizeExpr(), n, state)
exists(VariableAccess va, Expr size, int delta |
size = alloc.getSizeExpr() and
// Get the unique variable in a size expression like `x` in `malloc(x + 1)`.
va = unique( | | getAVariableAccess(size)) and
// Compute `delta` as the constant difference between `x` and `x + 1`.
bounded1(any(Instruction instr | instr.getUnconvertedResultExpression() = size),
any(LoadInstruction load | load.getUnconvertedResultExpression() = va), delta) and
n.asConvertedExpr() = va.getFullyConverted() and
state = delta
)
}
/**
@@ -345,6 +324,16 @@ query predicate edges(MergedPathNode node1, MergedPathNode node2) {
joinOn2(node1.asPathNode3(), node2.asSinkNode(), _)
}
query predicate subpaths(
MergedPathNode arg, MergedPathNode par, MergedPathNode ret, MergedPathNode out
) {
AllocToInvalidPointerFlow::PathGraph1::subpaths(arg.asPathNode1(), par.asPathNode1(),
ret.asPathNode1(), out.asPathNode1())
or
InvalidPointerToDerefFlow::PathGraph::subpaths(arg.asPathNode3(), par.asPathNode3(),
ret.asPathNode3(), out.asPathNode3())
}
/**
* Holds if `p1` is a sink of `AllocToInvalidPointerConf` and `p2` is a source
* of `InvalidPointerToDerefConf`, and they are connected through `pai`.

View File

@@ -1,202 +1,62 @@
edges
| test.cpp:16:11:16:21 | mk_string_t indirection [string] | test.cpp:24:21:24:31 | call to mk_string_t indirection [string] |
| test.cpp:16:11:16:21 | mk_string_t indirection [string] | test.cpp:34:21:34:31 | call to mk_string_t indirection [string] |
| test.cpp:16:11:16:21 | mk_string_t indirection [string] | test.cpp:39:21:39:31 | call to mk_string_t indirection [string] |
| test.cpp:18:5:18:30 | ... = ... | test.cpp:18:10:18:15 | str indirection [post update] [string] |
| test.cpp:18:10:18:15 | str indirection [post update] [string] | test.cpp:16:11:16:21 | mk_string_t indirection [string] |
| test.cpp:18:19:18:24 | call to malloc | test.cpp:18:5:18:30 | ... = ... |
| test.cpp:24:21:24:31 | call to mk_string_t indirection [string] | test.cpp:26:13:26:15 | str indirection [string] |
| test.cpp:26:13:26:15 | str indirection [string] | test.cpp:26:18:26:23 | string |
| test.cpp:26:13:26:15 | str indirection [string] | test.cpp:26:18:26:23 | string indirection |
| test.cpp:26:18:26:23 | string indirection | test.cpp:26:18:26:23 | string |
| test.cpp:29:32:29:34 | str indirection [string] | test.cpp:30:13:30:15 | str indirection [string] |
| test.cpp:30:13:30:15 | str indirection [string] | test.cpp:30:18:30:23 | string |
| test.cpp:30:13:30:15 | str indirection [string] | test.cpp:30:18:30:23 | string indirection |
| test.cpp:30:18:30:23 | string indirection | test.cpp:30:18:30:23 | string |
| test.cpp:34:21:34:31 | call to mk_string_t indirection [string] | test.cpp:35:21:35:23 | str indirection [string] |
| test.cpp:35:21:35:23 | str indirection [string] | test.cpp:29:32:29:34 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:41:13:41:15 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:42:13:42:15 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:44:13:44:15 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:45:13:45:15 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:48:17:48:19 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:52:17:52:19 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:56:17:56:19 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:60:17:60:19 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:64:17:64:19 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:68:17:68:19 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:72:17:72:19 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:76:17:76:19 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:80:17:80:19 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:84:17:84:19 | str indirection [string] |
| test.cpp:41:13:41:15 | str indirection [string] | test.cpp:41:18:41:23 | string |
| test.cpp:41:13:41:15 | str indirection [string] | test.cpp:41:18:41:23 | string indirection |
| test.cpp:41:18:41:23 | string indirection | test.cpp:41:18:41:23 | string |
| test.cpp:42:13:42:15 | str indirection [string] | test.cpp:42:18:42:23 | string |
| test.cpp:42:13:42:15 | str indirection [string] | test.cpp:42:18:42:23 | string indirection |
| test.cpp:42:18:42:23 | string indirection | test.cpp:42:18:42:23 | string |
| test.cpp:44:13:44:15 | str indirection [string] | test.cpp:44:18:44:23 | string |
| test.cpp:44:13:44:15 | str indirection [string] | test.cpp:44:18:44:23 | string indirection |
| test.cpp:44:18:44:23 | string indirection | test.cpp:44:18:44:23 | string |
| test.cpp:45:13:45:15 | str indirection [string] | test.cpp:45:18:45:23 | string |
| test.cpp:45:13:45:15 | str indirection [string] | test.cpp:45:18:45:23 | string indirection |
| test.cpp:45:18:45:23 | string indirection | test.cpp:45:18:45:23 | string |
| test.cpp:48:17:48:19 | str indirection [string] | test.cpp:48:22:48:27 | string |
| test.cpp:48:17:48:19 | str indirection [string] | test.cpp:48:22:48:27 | string indirection |
| test.cpp:48:22:48:27 | string indirection | test.cpp:48:22:48:27 | string |
| test.cpp:52:17:52:19 | str indirection [string] | test.cpp:52:22:52:27 | string |
| test.cpp:52:17:52:19 | str indirection [string] | test.cpp:52:22:52:27 | string indirection |
| test.cpp:52:22:52:27 | string indirection | test.cpp:52:22:52:27 | string |
| test.cpp:56:17:56:19 | str indirection [string] | test.cpp:56:22:56:27 | string |
| test.cpp:56:17:56:19 | str indirection [string] | test.cpp:56:22:56:27 | string indirection |
| test.cpp:56:22:56:27 | string indirection | test.cpp:56:22:56:27 | string |
| test.cpp:60:17:60:19 | str indirection [string] | test.cpp:60:22:60:27 | string |
| test.cpp:60:17:60:19 | str indirection [string] | test.cpp:60:22:60:27 | string indirection |
| test.cpp:60:22:60:27 | string indirection | test.cpp:60:22:60:27 | string |
| test.cpp:64:17:64:19 | str indirection [string] | test.cpp:64:22:64:27 | string |
| test.cpp:64:17:64:19 | str indirection [string] | test.cpp:64:22:64:27 | string indirection |
| test.cpp:64:22:64:27 | string indirection | test.cpp:64:22:64:27 | string |
| test.cpp:68:17:68:19 | str indirection [string] | test.cpp:68:22:68:27 | string |
| test.cpp:68:17:68:19 | str indirection [string] | test.cpp:68:22:68:27 | string indirection |
| test.cpp:68:22:68:27 | string indirection | test.cpp:68:22:68:27 | string |
| test.cpp:72:17:72:19 | str indirection [string] | test.cpp:72:22:72:27 | string |
| test.cpp:72:17:72:19 | str indirection [string] | test.cpp:72:22:72:27 | string indirection |
| test.cpp:72:22:72:27 | string indirection | test.cpp:72:22:72:27 | string |
| test.cpp:76:17:76:19 | str indirection [string] | test.cpp:76:22:76:27 | string |
| test.cpp:76:17:76:19 | str indirection [string] | test.cpp:76:22:76:27 | string indirection |
| test.cpp:76:22:76:27 | string indirection | test.cpp:76:22:76:27 | string |
| test.cpp:80:17:80:19 | str indirection [string] | test.cpp:80:22:80:27 | string |
| test.cpp:80:17:80:19 | str indirection [string] | test.cpp:80:22:80:27 | string indirection |
| test.cpp:80:22:80:27 | string indirection | test.cpp:80:22:80:27 | string |
| test.cpp:84:17:84:19 | str indirection [string] | test.cpp:84:22:84:27 | string |
| test.cpp:84:17:84:19 | str indirection [string] | test.cpp:84:22:84:27 | string indirection |
| test.cpp:84:22:84:27 | string indirection | test.cpp:84:22:84:27 | string |
| test.cpp:88:11:88:30 | mk_string_t_plus_one indirection [string] | test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] |
| test.cpp:90:5:90:34 | ... = ... | test.cpp:90:10:90:15 | str indirection [post update] [string] |
| test.cpp:90:10:90:15 | str indirection [post update] [string] | test.cpp:88:11:88:30 | mk_string_t_plus_one indirection [string] |
| test.cpp:90:19:90:24 | call to malloc | test.cpp:90:5:90:34 | ... = ... |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:98:13:98:15 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:99:13:99:15 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:101:13:101:15 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:102:13:102:15 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:105:17:105:19 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:109:17:109:19 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:113:17:113:19 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:117:17:117:19 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:121:17:121:19 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:125:17:125:19 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:129:17:129:19 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:133:17:133:19 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:137:17:137:19 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:141:17:141:19 | str indirection [string] |
| test.cpp:98:13:98:15 | str indirection [string] | test.cpp:98:18:98:23 | string |
| test.cpp:98:13:98:15 | str indirection [string] | test.cpp:98:18:98:23 | string indirection |
| test.cpp:98:18:98:23 | string indirection | test.cpp:98:18:98:23 | string |
| test.cpp:99:13:99:15 | str indirection [string] | test.cpp:99:18:99:23 | string |
| test.cpp:99:13:99:15 | str indirection [string] | test.cpp:99:18:99:23 | string indirection |
| test.cpp:99:18:99:23 | string indirection | test.cpp:99:18:99:23 | string |
| test.cpp:101:13:101:15 | str indirection [string] | test.cpp:101:18:101:23 | string |
| test.cpp:101:13:101:15 | str indirection [string] | test.cpp:101:18:101:23 | string indirection |
| test.cpp:101:18:101:23 | string indirection | test.cpp:101:18:101:23 | string |
| test.cpp:102:13:102:15 | str indirection [string] | test.cpp:102:18:102:23 | string |
| test.cpp:102:13:102:15 | str indirection [string] | test.cpp:102:18:102:23 | string indirection |
| test.cpp:102:18:102:23 | string indirection | test.cpp:102:18:102:23 | string |
| test.cpp:105:17:105:19 | str indirection [string] | test.cpp:105:22:105:27 | string |
| test.cpp:105:17:105:19 | str indirection [string] | test.cpp:105:22:105:27 | string indirection |
| test.cpp:105:22:105:27 | string indirection | test.cpp:105:22:105:27 | string |
| test.cpp:109:17:109:19 | str indirection [string] | test.cpp:109:22:109:27 | string |
| test.cpp:109:17:109:19 | str indirection [string] | test.cpp:109:22:109:27 | string indirection |
| test.cpp:109:22:109:27 | string indirection | test.cpp:109:22:109:27 | string |
| test.cpp:113:17:113:19 | str indirection [string] | test.cpp:113:22:113:27 | string |
| test.cpp:113:17:113:19 | str indirection [string] | test.cpp:113:22:113:27 | string indirection |
| test.cpp:113:22:113:27 | string indirection | test.cpp:113:22:113:27 | string |
| test.cpp:117:17:117:19 | str indirection [string] | test.cpp:117:22:117:27 | string |
| test.cpp:117:17:117:19 | str indirection [string] | test.cpp:117:22:117:27 | string indirection |
| test.cpp:117:22:117:27 | string indirection | test.cpp:117:22:117:27 | string |
| test.cpp:121:17:121:19 | str indirection [string] | test.cpp:121:22:121:27 | string |
| test.cpp:121:17:121:19 | str indirection [string] | test.cpp:121:22:121:27 | string indirection |
| test.cpp:121:22:121:27 | string indirection | test.cpp:121:22:121:27 | string |
| test.cpp:125:17:125:19 | str indirection [string] | test.cpp:125:22:125:27 | string |
| test.cpp:125:17:125:19 | str indirection [string] | test.cpp:125:22:125:27 | string indirection |
| test.cpp:125:22:125:27 | string indirection | test.cpp:125:22:125:27 | string |
| test.cpp:129:17:129:19 | str indirection [string] | test.cpp:129:22:129:27 | string |
| test.cpp:129:17:129:19 | str indirection [string] | test.cpp:129:22:129:27 | string indirection |
| test.cpp:129:22:129:27 | string indirection | test.cpp:129:22:129:27 | string |
| test.cpp:133:17:133:19 | str indirection [string] | test.cpp:133:22:133:27 | string |
| test.cpp:133:17:133:19 | str indirection [string] | test.cpp:133:22:133:27 | string indirection |
| test.cpp:133:22:133:27 | string indirection | test.cpp:133:22:133:27 | string |
| test.cpp:137:17:137:19 | str indirection [string] | test.cpp:137:22:137:27 | string |
| test.cpp:137:17:137:19 | str indirection [string] | test.cpp:137:22:137:27 | string indirection |
| test.cpp:137:22:137:27 | string indirection | test.cpp:137:22:137:27 | string |
| test.cpp:141:17:141:19 | str indirection [string] | test.cpp:141:22:141:27 | string |
| test.cpp:141:17:141:19 | str indirection [string] | test.cpp:141:22:141:27 | string indirection |
| test.cpp:141:22:141:27 | string indirection | test.cpp:141:22:141:27 | string |
| test.cpp:147:5:147:34 | ... = ... | test.cpp:147:10:147:15 | str indirection [post update] [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:150:13:150:15 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:151:13:151:15 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:152:13:152:15 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:154:13:154:15 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:155:13:155:15 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:156:13:156:15 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:159:17:159:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:163:17:163:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:167:17:167:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:171:17:171:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:175:17:175:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:179:17:179:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:183:17:183:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:187:17:187:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:191:17:191:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:195:17:195:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:199:17:199:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:203:17:203:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:207:17:207:19 | str indirection [string] |
| test.cpp:147:19:147:24 | call to malloc | test.cpp:147:5:147:34 | ... = ... |
| test.cpp:150:13:150:15 | str indirection [string] | test.cpp:150:18:150:23 | string |
| test.cpp:150:13:150:15 | str indirection [string] | test.cpp:150:18:150:23 | string indirection |
| test.cpp:150:18:150:23 | string indirection | test.cpp:150:18:150:23 | string |
| test.cpp:151:13:151:15 | str indirection [string] | test.cpp:151:18:151:23 | string |
| test.cpp:151:13:151:15 | str indirection [string] | test.cpp:151:18:151:23 | string indirection |
| test.cpp:151:18:151:23 | string indirection | test.cpp:151:18:151:23 | string |
| test.cpp:152:13:152:15 | str indirection [string] | test.cpp:152:18:152:23 | string |
| test.cpp:152:13:152:15 | str indirection [string] | test.cpp:152:18:152:23 | string indirection |
| test.cpp:152:18:152:23 | string indirection | test.cpp:152:18:152:23 | string |
| test.cpp:154:13:154:15 | str indirection [string] | test.cpp:154:18:154:23 | string |
| test.cpp:154:13:154:15 | str indirection [string] | test.cpp:154:18:154:23 | string indirection |
| test.cpp:154:18:154:23 | string indirection | test.cpp:154:18:154:23 | string |
| test.cpp:155:13:155:15 | str indirection [string] | test.cpp:155:18:155:23 | string |
| test.cpp:155:13:155:15 | str indirection [string] | test.cpp:155:18:155:23 | string indirection |
| test.cpp:155:18:155:23 | string indirection | test.cpp:155:18:155:23 | string |
| test.cpp:156:13:156:15 | str indirection [string] | test.cpp:156:18:156:23 | string |
| test.cpp:156:13:156:15 | str indirection [string] | test.cpp:156:18:156:23 | string indirection |
| test.cpp:156:18:156:23 | string indirection | test.cpp:156:18:156:23 | string |
| test.cpp:159:17:159:19 | str indirection [string] | test.cpp:159:22:159:27 | string |
| test.cpp:159:17:159:19 | str indirection [string] | test.cpp:159:22:159:27 | string indirection |
| test.cpp:159:22:159:27 | string indirection | test.cpp:159:22:159:27 | string |
| test.cpp:163:17:163:19 | str indirection [string] | test.cpp:163:22:163:27 | string |
| test.cpp:163:17:163:19 | str indirection [string] | test.cpp:163:22:163:27 | string indirection |
| test.cpp:163:22:163:27 | string indirection | test.cpp:163:22:163:27 | string |
| test.cpp:167:17:167:19 | str indirection [string] | test.cpp:167:22:167:27 | string |
| test.cpp:167:17:167:19 | str indirection [string] | test.cpp:167:22:167:27 | string indirection |
| test.cpp:167:22:167:27 | string indirection | test.cpp:167:22:167:27 | string |
| test.cpp:171:17:171:19 | str indirection [string] | test.cpp:171:22:171:27 | string |
| test.cpp:171:17:171:19 | str indirection [string] | test.cpp:171:22:171:27 | string indirection |
| test.cpp:171:22:171:27 | string indirection | test.cpp:171:22:171:27 | string |
| test.cpp:175:17:175:19 | str indirection [string] | test.cpp:175:22:175:27 | string |
| test.cpp:175:17:175:19 | str indirection [string] | test.cpp:175:22:175:27 | string indirection |
| test.cpp:175:22:175:27 | string indirection | test.cpp:175:22:175:27 | string |
| test.cpp:179:17:179:19 | str indirection [string] | test.cpp:179:22:179:27 | string |
| test.cpp:179:17:179:19 | str indirection [string] | test.cpp:179:22:179:27 | string indirection |
| test.cpp:179:22:179:27 | string indirection | test.cpp:179:22:179:27 | string |
| test.cpp:183:17:183:19 | str indirection [string] | test.cpp:183:22:183:27 | string |
| test.cpp:183:17:183:19 | str indirection [string] | test.cpp:183:22:183:27 | string indirection |
| test.cpp:183:22:183:27 | string indirection | test.cpp:183:22:183:27 | string |
| test.cpp:187:17:187:19 | str indirection [string] | test.cpp:187:22:187:27 | string |
| test.cpp:187:17:187:19 | str indirection [string] | test.cpp:187:22:187:27 | string indirection |
| test.cpp:187:22:187:27 | string indirection | test.cpp:187:22:187:27 | string |
| test.cpp:191:17:191:19 | str indirection [string] | test.cpp:191:22:191:27 | string |
| test.cpp:191:17:191:19 | str indirection [string] | test.cpp:191:22:191:27 | string indirection |
| test.cpp:191:22:191:27 | string indirection | test.cpp:191:22:191:27 | string |
| test.cpp:195:17:195:19 | str indirection [string] | test.cpp:195:22:195:27 | string |
| test.cpp:195:17:195:19 | str indirection [string] | test.cpp:195:22:195:27 | string indirection |
| test.cpp:195:22:195:27 | string indirection | test.cpp:195:22:195:27 | string |
@@ -229,154 +89,48 @@ nodes
| test.cpp:18:5:18:30 | ... = ... | semmle.label | ... = ... |
| test.cpp:18:10:18:15 | str indirection [post update] [string] | semmle.label | str indirection [post update] [string] |
| test.cpp:18:19:18:24 | call to malloc | semmle.label | call to malloc |
| test.cpp:24:21:24:31 | call to mk_string_t indirection [string] | semmle.label | call to mk_string_t indirection [string] |
| test.cpp:26:13:26:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:26:18:26:23 | string | semmle.label | string |
| test.cpp:26:18:26:23 | string indirection | semmle.label | string indirection |
| test.cpp:29:32:29:34 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:30:13:30:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:30:18:30:23 | string | semmle.label | string |
| test.cpp:30:18:30:23 | string indirection | semmle.label | string indirection |
| test.cpp:34:21:34:31 | call to mk_string_t indirection [string] | semmle.label | call to mk_string_t indirection [string] |
| test.cpp:35:21:35:23 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | semmle.label | call to mk_string_t indirection [string] |
| test.cpp:41:13:41:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:41:18:41:23 | string | semmle.label | string |
| test.cpp:41:18:41:23 | string indirection | semmle.label | string indirection |
| test.cpp:42:13:42:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:42:18:42:23 | string | semmle.label | string |
| test.cpp:42:18:42:23 | string indirection | semmle.label | string indirection |
| test.cpp:44:13:44:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:44:18:44:23 | string | semmle.label | string |
| test.cpp:44:18:44:23 | string indirection | semmle.label | string indirection |
| test.cpp:45:13:45:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:45:18:45:23 | string | semmle.label | string |
| test.cpp:45:18:45:23 | string indirection | semmle.label | string indirection |
| test.cpp:48:17:48:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:48:22:48:27 | string | semmle.label | string |
| test.cpp:48:22:48:27 | string indirection | semmle.label | string indirection |
| test.cpp:52:17:52:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:52:22:52:27 | string | semmle.label | string |
| test.cpp:52:22:52:27 | string indirection | semmle.label | string indirection |
| test.cpp:56:17:56:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:56:22:56:27 | string | semmle.label | string |
| test.cpp:56:22:56:27 | string indirection | semmle.label | string indirection |
| test.cpp:60:17:60:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:60:22:60:27 | string | semmle.label | string |
| test.cpp:60:22:60:27 | string indirection | semmle.label | string indirection |
| test.cpp:64:17:64:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:64:22:64:27 | string | semmle.label | string |
| test.cpp:64:22:64:27 | string indirection | semmle.label | string indirection |
| test.cpp:68:17:68:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:68:22:68:27 | string | semmle.label | string |
| test.cpp:68:22:68:27 | string indirection | semmle.label | string indirection |
| test.cpp:72:17:72:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:72:22:72:27 | string | semmle.label | string |
| test.cpp:72:22:72:27 | string indirection | semmle.label | string indirection |
| test.cpp:76:17:76:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:76:22:76:27 | string | semmle.label | string |
| test.cpp:76:22:76:27 | string indirection | semmle.label | string indirection |
| test.cpp:80:17:80:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:80:22:80:27 | string | semmle.label | string |
| test.cpp:80:22:80:27 | string indirection | semmle.label | string indirection |
| test.cpp:84:17:84:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:84:22:84:27 | string | semmle.label | string |
| test.cpp:84:22:84:27 | string indirection | semmle.label | string indirection |
| test.cpp:88:11:88:30 | mk_string_t_plus_one indirection [string] | semmle.label | mk_string_t_plus_one indirection [string] |
| test.cpp:90:5:90:34 | ... = ... | semmle.label | ... = ... |
| test.cpp:90:10:90:15 | str indirection [post update] [string] | semmle.label | str indirection [post update] [string] |
| test.cpp:90:19:90:24 | call to malloc | semmle.label | call to malloc |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | semmle.label | call to mk_string_t_plus_one indirection [string] |
| test.cpp:98:13:98:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:98:18:98:23 | string | semmle.label | string |
| test.cpp:98:18:98:23 | string indirection | semmle.label | string indirection |
| test.cpp:99:13:99:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:99:18:99:23 | string | semmle.label | string |
| test.cpp:99:18:99:23 | string indirection | semmle.label | string indirection |
| test.cpp:101:13:101:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:101:18:101:23 | string | semmle.label | string |
| test.cpp:101:18:101:23 | string indirection | semmle.label | string indirection |
| test.cpp:102:13:102:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:102:18:102:23 | string | semmle.label | string |
| test.cpp:102:18:102:23 | string indirection | semmle.label | string indirection |
| test.cpp:105:17:105:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:105:22:105:27 | string | semmle.label | string |
| test.cpp:105:22:105:27 | string indirection | semmle.label | string indirection |
| test.cpp:109:17:109:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:109:22:109:27 | string | semmle.label | string |
| test.cpp:109:22:109:27 | string indirection | semmle.label | string indirection |
| test.cpp:113:17:113:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:113:22:113:27 | string | semmle.label | string |
| test.cpp:113:22:113:27 | string indirection | semmle.label | string indirection |
| test.cpp:117:17:117:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:117:22:117:27 | string | semmle.label | string |
| test.cpp:117:22:117:27 | string indirection | semmle.label | string indirection |
| test.cpp:121:17:121:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:121:22:121:27 | string | semmle.label | string |
| test.cpp:121:22:121:27 | string indirection | semmle.label | string indirection |
| test.cpp:125:17:125:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:125:22:125:27 | string | semmle.label | string |
| test.cpp:125:22:125:27 | string indirection | semmle.label | string indirection |
| test.cpp:129:17:129:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:129:22:129:27 | string | semmle.label | string |
| test.cpp:129:22:129:27 | string indirection | semmle.label | string indirection |
| test.cpp:133:17:133:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:133:22:133:27 | string | semmle.label | string |
| test.cpp:133:22:133:27 | string indirection | semmle.label | string indirection |
| test.cpp:137:17:137:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:137:22:137:27 | string | semmle.label | string |
| test.cpp:137:22:137:27 | string indirection | semmle.label | string indirection |
| test.cpp:141:17:141:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:141:22:141:27 | string | semmle.label | string |
| test.cpp:141:22:141:27 | string indirection | semmle.label | string indirection |
| test.cpp:147:5:147:34 | ... = ... | semmle.label | ... = ... |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | semmle.label | str indirection [post update] [string] |
| test.cpp:147:19:147:24 | call to malloc | semmle.label | call to malloc |
| test.cpp:150:13:150:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:150:18:150:23 | string | semmle.label | string |
| test.cpp:150:18:150:23 | string indirection | semmle.label | string indirection |
| test.cpp:151:13:151:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:151:18:151:23 | string | semmle.label | string |
| test.cpp:151:18:151:23 | string indirection | semmle.label | string indirection |
| test.cpp:152:13:152:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:152:18:152:23 | string | semmle.label | string |
| test.cpp:152:18:152:23 | string indirection | semmle.label | string indirection |
| test.cpp:154:13:154:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:154:18:154:23 | string | semmle.label | string |
| test.cpp:154:18:154:23 | string indirection | semmle.label | string indirection |
| test.cpp:155:13:155:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:155:18:155:23 | string | semmle.label | string |
| test.cpp:155:18:155:23 | string indirection | semmle.label | string indirection |
| test.cpp:156:13:156:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:156:18:156:23 | string | semmle.label | string |
| test.cpp:156:18:156:23 | string indirection | semmle.label | string indirection |
| test.cpp:159:17:159:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:159:22:159:27 | string | semmle.label | string |
| test.cpp:159:22:159:27 | string indirection | semmle.label | string indirection |
| test.cpp:163:17:163:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:163:22:163:27 | string | semmle.label | string |
| test.cpp:163:22:163:27 | string indirection | semmle.label | string indirection |
| test.cpp:167:17:167:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:167:22:167:27 | string | semmle.label | string |
| test.cpp:167:22:167:27 | string indirection | semmle.label | string indirection |
| test.cpp:171:17:171:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:171:22:171:27 | string | semmle.label | string |
| test.cpp:171:22:171:27 | string indirection | semmle.label | string indirection |
| test.cpp:175:17:175:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:175:22:175:27 | string | semmle.label | string |
| test.cpp:175:22:175:27 | string indirection | semmle.label | string indirection |
| test.cpp:179:17:179:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:179:22:179:27 | string | semmle.label | string |
| test.cpp:179:22:179:27 | string indirection | semmle.label | string indirection |
| test.cpp:183:17:183:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:183:22:183:27 | string | semmle.label | string |
| test.cpp:183:22:183:27 | string indirection | semmle.label | string indirection |
| test.cpp:187:17:187:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:187:22:187:27 | string | semmle.label | string |
| test.cpp:187:22:187:27 | string indirection | semmle.label | string indirection |
| test.cpp:191:17:191:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:191:22:191:27 | string | semmle.label | string |
| test.cpp:191:22:191:27 | string indirection | semmle.label | string indirection |
| test.cpp:195:17:195:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:195:22:195:27 | string | semmle.label | string |
| test.cpp:195:22:195:27 | string indirection | semmle.label | string indirection |

View File

@@ -653,6 +653,7 @@ edges
| test.cpp:304:15:304:26 | new[] | test.cpp:308:5:308:6 | xs |
| test.cpp:308:5:308:6 | xs | test.cpp:308:5:308:11 | access to array |
| test.cpp:308:5:308:11 | access to array | test.cpp:308:5:308:29 | Store: ... = ... |
subpaths
#select
| test.cpp:6:14:6:15 | Load: * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:6:14:6:15 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size |
| test.cpp:8:14:8:21 | Load: * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:8:14:8:21 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size |

View File

@@ -304,7 +304,7 @@ void test21() {
void** xs = new void*[n];
for (int i = 0; i < n; i += 2) {
xs[i] = test21_get(i);
xs[i+1] = test21_get(i+1);
xs[i] = test21_get(i); // GOOD
xs[i+1] = test21_get(i+1); // GOOD [FALSE POSITIVE]
}
}

View File

@@ -1,7 +1,7 @@
// semmle-extractor-options: --edg --clang
int source();
void sink(int); void sink(const int *); void sink(int **);
void sink(int); void sink(const int *); void sink(int **); void indirect_sink(...);
struct twoIntFields {
int m1, m2;
@@ -19,7 +19,8 @@ void following_pointers( // $ ast-def=sourceStruct1_ptr
sink(sourceArray1[0]); // no flow
sink(*sourceArray1); // no flow
sink(&sourceArray1); // $ ast,ir // [should probably be taint only]
sink(&sourceArray1); // $ ast // [should probably be taint only]
indirect_sink(&sourceArray1); // $ ast,ir
sink(sourceStruct1.m1); // no flow
sink(sourceStruct1_ptr->m1); // no flow
@@ -48,5 +49,6 @@ void following_pointers( // $ ast-def=sourceStruct1_ptr
int stackArray[2] = { source(), source() };
stackArray[0] = source();
sink(stackArray); // $ ast ir ir=49:25 ir=49:35 ir=50:19
sink(stackArray); // $ ast,ir
indirect_sink(stackArray); // $ ast ir=50:25 ir=50:35 ir=51:19
}

View File

@@ -28,9 +28,10 @@ postWithInFlow
| BarrierGuard.cpp:49:6:49:6 | x [post update] | PostUpdateNode should not be the target of local flow. |
| BarrierGuard.cpp:60:7:60:7 | x [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:22:9:22:20 | sourceArray1 [inner post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:28:22:28:23 | m1 [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:50:3:50:12 | stackArray [inner post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:50:3:50:15 | access to array [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:23:18:23:29 | sourceArray1 [inner post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:29:22:29:23 | m1 [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:51:3:51:12 | stackArray [inner post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:51:3:51:15 | access to array [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:60:3:60:14 | globalBottom [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:61:3:61:14 | globalMiddle [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:78:24:78:37 | call to allocateBottom [inner post update] | PostUpdateNode should not be the target of local flow. |
@@ -125,6 +126,8 @@ postWithInFlow
| test.cpp:681:3:681:3 | s [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:689:3:689:3 | s [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:690:3:690:3 | s [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:694:4:694:6 | buf [inner post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:704:23:704:25 | buf [inner post update] | PostUpdateNode should not be the target of local flow. |
viableImplInCallContextTooLarge
uniqueParameterNodeAtPosition
uniqueParameterNodePosition

View File

@@ -1,5 +1,5 @@
int source();
void sink(int); void sink(const int *); void sink(int **);
void sink(int); void sink(const int *); void sink(int **); void indirect_sink(...);
void intraprocedural_with_local_flow() {
int t2;
@@ -626,7 +626,7 @@ void test_def_via_phi_read(bool b)
use(buffer);
}
intPointerSource(buffer);
sink(buffer); // $ ast,ir
indirect_sink(buffer); // $ ast,ir
}
void test_static_local_1() {
@@ -690,3 +690,16 @@ void test_static_local_9() {
s = 0;
}
void increment_buf(int** buf) { // $ ast-def=buf ir-def=*buf ir-def=**buf
*buf += 10;
sink(buf); // $ SPURIOUS: ast
}
void call_increment_buf(int** buf) { // $ ast-def=buf
increment_buf(buf);
}
void test_conflation_regression(int* source) { // $ ast-def=source
int* buf = source;
call_increment_buf(&buf);
}

View File

@@ -34,7 +34,7 @@ module AstTest {
override predicate isSink(DataFlow::Node sink) {
exists(FunctionCall call |
call.getTarget().getName() = "sink" and
call.getTarget().getName() = ["sink", "indirect_sink"] and
sink.asExpr() = call.getAnArgument()
)
}
@@ -83,9 +83,12 @@ module IRTest {
}
override predicate isSink(DataFlow::Node sink) {
exists(FunctionCall call |
exists(FunctionCall call, Expr e | e = call.getAnArgument() |
call.getTarget().getName() = "sink" and
call.getAnArgument() in [sink.asExpr(), sink.asIndirectExpr()]
sink.asExpr() = e
or
call.getTarget().getName() = "indirect_sink" and
sink.asIndirectExpr() = e
)
}

View File

@@ -1,29 +1,16 @@
edges
| tests.cpp:26:15:26:23 | badSource indirection | tests.cpp:51:12:51:20 | call to badSource indirection |
| tests.cpp:26:32:26:35 | data indirection | tests.cpp:26:15:26:23 | badSource indirection |
| tests.cpp:26:32:26:35 | data indirection | tests.cpp:38:25:38:36 | strncat output argument |
| tests.cpp:33:34:33:39 | call to getenv indirection | tests.cpp:38:39:38:49 | environment indirection |
| tests.cpp:38:25:38:36 | strncat output argument | tests.cpp:26:15:26:23 | badSource indirection |
| tests.cpp:38:25:38:36 | strncat output argument | tests.cpp:26:15:26:23 | badSource indirection |
| tests.cpp:38:25:38:36 | strncat output argument | tests.cpp:51:22:51:25 | badSource output argument |
| tests.cpp:38:39:38:49 | environment indirection | tests.cpp:38:25:38:36 | strncat output argument |
| tests.cpp:51:12:51:20 | call to badSource indirection | tests.cpp:53:16:53:19 | data indirection |
| tests.cpp:51:22:51:25 | badSource output argument | tests.cpp:51:22:51:25 | data indirection |
| tests.cpp:51:22:51:25 | data indirection | tests.cpp:26:32:26:35 | data indirection |
| tests.cpp:51:22:51:25 | data indirection | tests.cpp:51:12:51:20 | call to badSource indirection |
nodes
| tests.cpp:26:15:26:23 | badSource indirection | semmle.label | badSource indirection |
| tests.cpp:26:15:26:23 | badSource indirection | semmle.label | badSource indirection |
| tests.cpp:26:32:26:35 | data indirection | semmle.label | data indirection |
| tests.cpp:33:34:33:39 | call to getenv indirection | semmle.label | call to getenv indirection |
| tests.cpp:38:25:38:36 | strncat output argument | semmle.label | strncat output argument |
| tests.cpp:38:25:38:36 | strncat output argument | semmle.label | strncat output argument |
| tests.cpp:38:39:38:49 | environment indirection | semmle.label | environment indirection |
| tests.cpp:51:12:51:20 | call to badSource indirection | semmle.label | call to badSource indirection |
| tests.cpp:51:22:51:25 | badSource output argument | semmle.label | badSource output argument |
| tests.cpp:51:22:51:25 | data indirection | semmle.label | data indirection |
| tests.cpp:53:16:53:19 | data indirection | semmle.label | data indirection |
subpaths
| tests.cpp:51:22:51:25 | data indirection | tests.cpp:26:32:26:35 | data indirection | tests.cpp:26:15:26:23 | badSource indirection | tests.cpp:51:12:51:20 | call to badSource indirection |
#select
| tests.cpp:53:16:53:19 | data | tests.cpp:33:34:33:39 | call to getenv indirection | tests.cpp:53:16:53:19 | data indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | tests.cpp:33:34:33:39 | call to getenv indirection | user input (an environment variable) | tests.cpp:38:25:38:36 | strncat output argument | strncat output argument |

View File

@@ -45,8 +45,6 @@ edges
| test.cpp:186:47:186:54 | filename indirection | test.cpp:188:20:188:24 | flags indirection |
| test.cpp:187:11:187:15 | strncat output argument | test.cpp:188:11:188:17 | strncat output argument |
| test.cpp:187:18:187:25 | filename indirection | test.cpp:187:11:187:15 | strncat output argument |
| test.cpp:188:11:188:17 | strncat output argument | test.cpp:188:11:188:17 | strncat output argument |
| test.cpp:188:11:188:17 | strncat output argument | test.cpp:188:11:188:17 | strncat output argument |
| test.cpp:188:20:188:24 | flags indirection | test.cpp:188:11:188:17 | strncat output argument |
| test.cpp:194:9:194:16 | fread output argument | test.cpp:196:26:196:33 | filename indirection |
| test.cpp:196:10:196:16 | concat output argument | test.cpp:198:32:198:38 | command indirection |

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The `cs/log-forging`, `cs/cleartext-storage`, and `cs/exposure-of-sensitive-information` queries now correctly handle unsanitized arguments to `ILogger` extension methods.

View File

@@ -26,7 +26,14 @@ private class ExternalModelSink extends ExternalLocationSink {
* An argument to a call to a method on a logger class.
*/
class LogMessageSink extends ExternalLocationSink {
LogMessageSink() { this.getExpr() = any(LoggerType i).getAMethod().getACall().getAnArgument() }
LogMessageSink() {
this.getExpr() = any(LoggerType i).getAMethod().getACall().getAnArgument()
or
this.getExpr() =
any(ExtensionMethodCall call |
call.getTarget().(ExtensionMethod).getExtendedType() instanceof LoggerType
).getArgument(any(int i | i > 0))
}
}
/**

View File

@@ -214,4 +214,25 @@ namespace My.Qltest
static void Sink(object o) { }
}
public interface HI { }
public class HC : HI { }
public static class HE
{
public static object ExtensionMethod(this HI h) => throw null;
}
public class H
{
void M1()
{
var h = new HC();
var o = h.ExtensionMethod();
Sink(o);
}
static void Sink(object o) { }
}
}

View File

@@ -70,6 +70,9 @@ edges
| ExternalFlow.cs:197:42:197:43 | access to local variable o2 : Object | ExternalFlow.cs:197:18:197:44 | call to method GeneratedFlowArgs |
| ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | ExternalFlow.cs:206:38:206:39 | access to local variable o2 : Object |
| ExternalFlow.cs:206:38:206:39 | access to local variable o2 : Object | ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs |
| ExternalFlow.cs:231:21:231:28 | object creation of type HC : HC | ExternalFlow.cs:232:21:232:21 | access to local variable h : HC |
| ExternalFlow.cs:232:21:232:21 | access to local variable h : HC | ExternalFlow.cs:232:21:232:39 | call to method ExtensionMethod : HC |
| ExternalFlow.cs:232:21:232:39 | call to method ExtensionMethod : HC | ExternalFlow.cs:233:18:233:18 | access to local variable o |
nodes
| ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
| ExternalFlow.cs:10:18:10:33 | call to method StepArgRes | semmle.label | call to method StepArgRes |
@@ -162,6 +165,10 @@ nodes
| ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
| ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs | semmle.label | call to method MixedFlowArgs |
| ExternalFlow.cs:206:38:206:39 | access to local variable o2 : Object | semmle.label | access to local variable o2 : Object |
| ExternalFlow.cs:231:21:231:28 | object creation of type HC : HC | semmle.label | object creation of type HC : HC |
| ExternalFlow.cs:232:21:232:21 | access to local variable h : HC | semmle.label | access to local variable h : HC |
| ExternalFlow.cs:232:21:232:39 | call to method ExtensionMethod : HC | semmle.label | call to method ExtensionMethod : HC |
| ExternalFlow.cs:233:18:233:18 | access to local variable o | semmle.label | access to local variable o |
subpaths
#select
| ExternalFlow.cs:10:18:10:33 | call to method StepArgRes | ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | ExternalFlow.cs:10:18:10:33 | call to method StepArgRes | $@ | ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | object creation of type Object : Object |
@@ -188,3 +195,4 @@ subpaths
| ExternalFlow.cs:194:18:194:44 | call to method GeneratedFlowArgs | ExternalFlow.cs:193:22:193:33 | object creation of type Object : Object | ExternalFlow.cs:194:18:194:44 | call to method GeneratedFlowArgs | $@ | ExternalFlow.cs:193:22:193:33 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:197:18:197:44 | call to method GeneratedFlowArgs | ExternalFlow.cs:196:22:196:33 | object creation of type Object : Object | ExternalFlow.cs:197:18:197:44 | call to method GeneratedFlowArgs | $@ | ExternalFlow.cs:196:22:196:33 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs | ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs | $@ | ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:233:18:233:18 | access to local variable o | ExternalFlow.cs:231:21:231:28 | object creation of type HC : HC | ExternalFlow.cs:233:18:233:18 | access to local variable o | $@ | ExternalFlow.cs:231:21:231:28 | object creation of type HC : HC | object creation of type HC : HC |

View File

@@ -29,3 +29,4 @@ extensions:
- ["My.Qltest", "G", false, "GeneratedFlowArgs", "(System.Object,System.Object)", "", "Argument[1]", "ReturnValue", "value", "df-generated"]
- ["My.Qltest", "G", false, "MixedFlowArgs", "(System.Object,System.Object)", "", "Argument[0]", "ReturnValue", "value", "df-generated"]
- ["My.Qltest", "G", false, "MixedFlowArgs", "(System.Object,System.Object)", "", "Argument[1]", "ReturnValue", "value", "manual"]
- ["My.Qltest", "HE", false, "ExtensionMethod", "(My.Qltest.HI)", "", "Argument[0]", "ReturnValue", "value", "manual"]

View File

@@ -3,6 +3,7 @@ using System.Diagnostics;
using System.IO;
using System.Net;
using System.Web;
using Microsoft.Extensions.Logging;
class ILogger
{
@@ -24,6 +25,10 @@ public class LogForgingHandler : IHttpHandler
logger.Warn(WebUtility.HtmlEncode(username) + " logged in");
// BAD: Logged as-is to TraceSource
new TraceSource("Test").TraceInformation(username + " logged in");
Microsoft.Extensions.Logging.ILogger logger2 = null;
// BAD: Logged as-is
logger2.LogError(username);
}
public bool IsReusable

View File

@@ -1,19 +1,23 @@
edges
| LogForging.cs:17:27:17:49 | access to property QueryString : NameValueCollection | LogForging.cs:17:27:17:61 | access to indexer : String |
| LogForging.cs:17:27:17:49 | access to property QueryString : NameValueCollection | LogForging.cs:20:21:20:43 | ... + ... |
| LogForging.cs:17:27:17:49 | access to property QueryString : NameValueCollection | LogForging.cs:26:50:26:72 | ... + ... |
| LogForging.cs:17:27:17:61 | access to indexer : String | LogForging.cs:20:21:20:43 | ... + ... |
| LogForging.cs:17:27:17:61 | access to indexer : String | LogForging.cs:26:50:26:72 | ... + ... |
| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:18:27:18:61 | access to indexer : String |
| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:21:21:21:43 | ... + ... |
| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:27:50:27:72 | ... + ... |
| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:31:26:31:33 | access to local variable username |
| LogForging.cs:18:27:18:61 | access to indexer : String | LogForging.cs:21:21:21:43 | ... + ... |
| LogForging.cs:18:27:18:61 | access to indexer : String | LogForging.cs:27:50:27:72 | ... + ... |
| LogForging.cs:18:27:18:61 | access to indexer : String | LogForging.cs:31:26:31:33 | access to local variable username |
| LogForgingAsp.cs:8:32:8:39 | username : String | LogForgingAsp.cs:12:21:12:43 | ... + ... |
nodes
| LogForging.cs:17:27:17:49 | access to property QueryString : NameValueCollection | semmle.label | access to property QueryString : NameValueCollection |
| LogForging.cs:17:27:17:61 | access to indexer : String | semmle.label | access to indexer : String |
| LogForging.cs:20:21:20:43 | ... + ... | semmle.label | ... + ... |
| LogForging.cs:26:50:26:72 | ... + ... | semmle.label | ... + ... |
| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | semmle.label | access to property QueryString : NameValueCollection |
| LogForging.cs:18:27:18:61 | access to indexer : String | semmle.label | access to indexer : String |
| LogForging.cs:21:21:21:43 | ... + ... | semmle.label | ... + ... |
| LogForging.cs:27:50:27:72 | ... + ... | semmle.label | ... + ... |
| LogForging.cs:31:26:31:33 | access to local variable username | semmle.label | access to local variable username |
| LogForgingAsp.cs:8:32:8:39 | username : String | semmle.label | username : String |
| LogForgingAsp.cs:12:21:12:43 | ... + ... | semmle.label | ... + ... |
subpaths
#select
| LogForging.cs:20:21:20:43 | ... + ... | LogForging.cs:17:27:17:49 | access to property QueryString : NameValueCollection | LogForging.cs:20:21:20:43 | ... + ... | This log entry depends on a $@. | LogForging.cs:17:27:17:49 | access to property QueryString | user-provided value |
| LogForging.cs:26:50:26:72 | ... + ... | LogForging.cs:17:27:17:49 | access to property QueryString : NameValueCollection | LogForging.cs:26:50:26:72 | ... + ... | This log entry depends on a $@. | LogForging.cs:17:27:17:49 | access to property QueryString | user-provided value |
| LogForging.cs:21:21:21:43 | ... + ... | LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:21:21:21:43 | ... + ... | This log entry depends on a $@. | LogForging.cs:18:27:18:49 | access to property QueryString | user-provided value |
| LogForging.cs:27:50:27:72 | ... + ... | LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:27:50:27:72 | ... + ... | This log entry depends on a $@. | LogForging.cs:18:27:18:49 | access to property QueryString | user-provided value |
| LogForging.cs:31:26:31:33 | access to local variable username | LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:31:26:31:33 | access to local variable username | This log entry depends on a $@. | LogForging.cs:18:27:18:49 | access to property QueryString | user-provided value |
| LogForgingAsp.cs:12:21:12:43 | ... + ... | LogForgingAsp.cs:8:32:8:39 | username : String | LogForgingAsp.cs:12:21:12:43 | ... + ... | This log entry depends on a $@. | LogForgingAsp.cs:8:32:8:39 | username | user-provided value |

View File

@@ -193,7 +193,7 @@ The class `ASTNode <https://codeql.github.com/codeql-standard-libraries/javascri
.. pull-quote::
Note
These predicates should only be used to perform generic AST traversal. To access children of specific AST node types, the specialized predicates introduced below should be used instead. In particular, queries should not rely on the numeric indices of child nodes relative to their parent nodes: these are considered an implementation detail that may change between versions of the library.
Top-levels
@@ -700,28 +700,7 @@ The data flow graph-based analyses described so far are all intraprocedural: the
We distinguish here between data flow proper, and *taint tracking*: the latter not only considers value-preserving flow (such as from variable definitions to uses), but also cases where one value influences ("taints") another without determining it entirely. For example, in the assignment ``s2 = s1.substring(i)``, the value of ``s1`` influences the value of ``s2``, because ``s2`` is assigned a substring of ``s1``. In general, ``s2`` will not be assigned ``s1`` itself, so there is no data flow from ``s1`` to ``s2``, but ``s1`` still taints ``s2``.
The simplest way of implementing an interprocedural data flow analysis is to extend either class ``DataFlow::TrackedNode`` or ``DataFlow::TrackedExpr``. The former is a subclass of ``DataFlow::Node``, the latter of ``Expr``, and extending them ensures that the newly added values are tracked interprocedurally. You can use the predicate ``flowsTo`` to find out which nodes/expressions the tracked value flows to.
For example, suppose that we are developing an analysis to find hard-coded passwords. We might start by writing a simple query that looks for string constants flowing into variables named ``"password"``. To do this, we can extend ``TrackedExpr`` to track all constant strings, ``flowsTo`` to find cases where such a string flows into a (SSA) definition of a password variable:
.. code-block:: ql
import javascript
class TrackedStringLiteral extends DataFlow::TrackedNode {
TrackedStringLiteral() {
this.asExpr() instanceof ConstantString
}
}
from TrackedStringLiteral source, DataFlow::Node sink, SsaExplicitDefinition def
where source.flowsTo(sink) and sink = DataFlow::ssaDefinitionNode(def) and
def.getSourceVariable().getName().toLowerCase() = "password"
select sink
Note that ``TrackedNode`` and ``TrackedExpr`` do not restrict the set of "sinks" for the inter-procedural flow analysis, tracking flow into any expression that they might flow to. This can be expensive for large code bases, and is often unnecessary, since usually you are only interested in flow to a particular set of sinks. For example, the above query only looks for flow into assignments to password variables.
This is a particular instance of a general pattern, whereby we want to specify a data flow or taint analysis in terms of its *sources* (where flow starts), *sinks* (where it should be tracked), and *barriers* or *sanitizers* (where flow is interrupted). The example does not include any sanitizers, but they are very common in security analyses: for example, an analysis that tracks the flow of untrusted user input into, say, a SQL query has to keep track of code that validates the input, thereby making it safe to use. Such a validation step is an example of a sanitizer.
It is a common pattern that we wish to specify data flow or taint analysis in terms of its *sources* (where flow starts), *sinks* (where it should be tracked), and *barriers* or *sanitizers* (where flow is interrupted). Sanitizers they are very common in security analyses: for example, an analysis that tracks the flow of untrusted user input into, say, a SQL query has to keep track of code that validates the input, thereby making it safe to use. Such a validation step is an example of a sanitizer.
The classes ``DataFlow::Configuration`` and ``TaintTracking::Configuration`` allow specifying a data flow or taint analysis, respectively, by overriding the following predicates:
@@ -735,10 +714,12 @@ Since for technical reasons both ``Configuration`` classes are subtypes of ``str
The predicate ``Configuration.hasFlow`` performs the actual flow tracking, starting at a source and looking for flow to a sink that does not pass through a barrier node or edge.
To continue with our above example, we can phrase it as a data flow configuration as follows:
For example, suppose that we are developing an analysis to find hard-coded passwords. We might write a simple query that looks for string constants flowing into variables named ``"password"``.
.. code-block:: ql
import javascript
class PasswordTracker extends DataFlow::Configuration {
PasswordTracker() {
// unique identifier for this configuration
@@ -754,11 +735,8 @@ To continue with our above example, we can phrase it as a data flow configuratio
}
predicate passwordVarAssign(Variable v, DataFlow::Node nd) {
exists (SsaExplicitDefinition def |
nd = DataFlow::ssaDefinitionNode(def) and
def.getSourceVariable() = v and
v.getName().toLowerCase() = "password"
)
v.getAnAssignedExpr() = nd.asExpr() and
v.getName().toLowerCase() = "password"
}
}
@@ -770,7 +748,6 @@ Now we can rephrase our query to use ``Configuration.hasFlow``:
where pt.hasFlow(source, sink) and pt.passwordVarAssign(v, sink)
select sink, "Password variable " + v + " is assigned a constant string."
Note that while analyses implemented in this way are inter-procedural in that they track flow and taint across function calls and returns, flow through global variables is not tracked. Flow through object properties is only tracked in limited cases, for example through properties of object literals or CommonJS ``module`` and ``exports`` objects.
Syntax errors
~~~~~~~~~~~~~
@@ -794,7 +771,7 @@ The ``semmle.javascript.frameworks.AngularJS`` library provides support for work
HTTP framework libraries
^^^^^^^^^^^^^^^^^^^^^^^^
The library ``semmle.javacript.frameworks.HTTP`` provides classes modeling common concepts from various HTTP frameworks.
The library ``semmle.javacript.frameworks.HTTP`` provides classes modeling common concepts from various HTTP frameworks.
Currently supported frameworks are `Express <https://expressjs.com/>`__, the standard Node.js ``http`` and ``https`` modules, `Connect <https://github.com/senchalabs/connect>`__, `Koa <https://koajs.com>`__, `Hapi <https://hapi.dev/>`__ and `Restify <http://restify.com/>`__.

View File

@@ -4,7 +4,7 @@
:stub-columns: 1
Language,Variants,Compilers,Extensions
C/C++,"C89, C99, C11, C18, C++98, C++03, C++11, C++14, C++17, C++20 [1]_","Clang (and clang-cl [2]_) extensions (up to Clang 12.0),
C/C++,"C89, C99, C11, C17, C++98, C++03, C++11, C++14, C++17, C++20 [1]_","Clang (and clang-cl [2]_) extensions (up to Clang 12.0),
GNU extensions (up to GCC 11.1),

View File

@@ -134,7 +134,7 @@ org.springframework.cache,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,13
org.springframework.context,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,
org.springframework.data.repository,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1
org.springframework.http,14,,71,,,,,,,,,,,,,,,14,,,,,,,,,,,,,,,,,,,,,,61,10
org.springframework.jdbc.core,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,10,,,,,,,,,,,,
org.springframework.jdbc.core,19,,,,,,,,,,,,,,,,,,,,,,,,,,,,19,,,,,,,,,,,,
org.springframework.jdbc.datasource,4,,,,,,,,,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
org.springframework.jdbc.object,9,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,,,,,,,,,,,,
org.springframework.jndi,1,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1 package sink source summary sink:bean-validation sink:create-file sink:fragment-injection sink:groovy sink:header-splitting sink:information-leak sink:intent-start sink:jdbc-url sink:jexl sink:jndi-injection sink:ldap sink:logging sink:mvel sink:ognl-injection sink:open-url sink:pending-intent-sent sink:read-file sink:regex-use sink:regex-use[-1] sink:regex-use[0] sink:regex-use[] sink:regex-use[f-1] sink:regex-use[f1] sink:regex-use[f] sink:set-hostname-verifier sink:sql sink:ssti sink:url-redirect sink:write-file sink:xpath sink:xslt sink:xss source:android-external-storage-dir source:android-widget source:contentprovider source:remote summary:taint summary:value
134 org.springframework.context 3 3
135 org.springframework.data.repository 1 1
136 org.springframework.http 14 71 14 61 10
137 org.springframework.jdbc.core 10 19 10 19
138 org.springframework.jdbc.datasource 4 4
139 org.springframework.jdbc.object 9 9
140 org.springframework.jndi 1 1

View File

@@ -21,7 +21,7 @@ Java framework & library support
Java Standard Library,``java.*``,3,679,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,483,104,2,,19,14,,29
`Spring <https://spring.io/>`_,``org.springframework.*``,29,483,113,2,,28,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.jsonwebtoken``, ``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.net``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.hadoop.fs``, ``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``",89,827,515,26,,18,18,,181
Totals,,246,9119,1957,174,10,113,33,1,361
Totals,,246,9119,1966,174,10,122,33,1,361

View File

@@ -13,6 +13,12 @@ for k in ["JAVA_HOME_11_X64", "JAVA_HOME_17_X64"]:
if k in os.environ:
del os.environ[k]
run_codeql_database_create([], lang="java", runFunction = runUnsuccessfully, db = None)
# Use a custom, empty toolchains.xml file so the autobuilder doesn't see any Java versions that may be
# in a system-level toolchains file
toolchains_path = os.path.join(os.getcwd(), 'toolchains.xml')
run_codeql_database_create([], lang="java", runFunction = runUnsuccessfully, db = None, extra_env={
'LGTM_INDEX_MAVEN_TOOLCHAINS_FILE': toolchains_path
})
check_diagnostics()

View File

@@ -0,0 +1,5 @@
<?xml version="1.0"?>
<toolchains xmlns="https://maven.apache.org/TOOLCHAINS/1.1.0"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/TOOLCHAINS/1.1.0 https://maven.apache.org/xsd/toolchains-1.1.0.xsd">
</toolchains>

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added SQL injection sinks for Spring JDBC's `NamedParameterJdbcOperations`.

View File

@@ -0,0 +1,14 @@
extensions:
- addsTo:
pack: codeql/java-all
extensible: sinkModel
data:
- ["org.springframework.jdbc.core.namedparam", "NamedParameterJdbcOperations", True, "batchUpdate", "", "", "Argument[0]", "sql", "manual"]
- ["org.springframework.jdbc.core.namedparam", "NamedParameterJdbcOperations", True, "execute", "", "", "Argument[0]", "sql", "manual"]
- ["org.springframework.jdbc.core.namedparam", "NamedParameterJdbcOperations", True, "query", "", "", "Argument[0]", "sql", "manual"]
- ["org.springframework.jdbc.core.namedparam", "NamedParameterJdbcOperations", True, "queryForList", "", "", "Argument[0]", "sql", "manual"]
- ["org.springframework.jdbc.core.namedparam", "NamedParameterJdbcOperations", True, "queryForMap", "", "", "Argument[0]", "sql", "manual"]
- ["org.springframework.jdbc.core.namedparam", "NamedParameterJdbcOperations", True, "queryForObject", "", "", "Argument[0]", "sql", "manual"]
- ["org.springframework.jdbc.core.namedparam", "NamedParameterJdbcOperations", True, "queryForRowSet", "", "", "Argument[0]", "sql", "manual"]
- ["org.springframework.jdbc.core.namedparam", "NamedParameterJdbcOperations", True, "queryForStream", "", "", "Argument[0]", "sql", "manual"]
- ["org.springframework.jdbc.core.namedparam", "NamedParameterJdbcOperations", True, "update", "", "", "Argument[0]", "sql", "manual"]

View File

@@ -104,6 +104,17 @@ private predicate constantBooleanExpr(Expr e, boolean val) {
CalcConstants::calculateBooleanValue(e) = val
}
pragma[nomagic]
private predicate constantStringExpr(Expr e, string val) {
e.(CompileTimeConstantExpr).getStringValue() = val
or
exists(SsaExplicitUpdate v, Expr src |
e = v.getAUse() and
src = v.getDefiningExpr().(VariableAssign).getSource() and
constantStringExpr(src, val)
)
}
private boolean getBoolValue(Expr e) { constantBooleanExpr(e, result) }
private int getIntValue(Expr e) { constantIntegerExpr(e, result) }
@@ -126,6 +137,14 @@ class ConstantBooleanExpr extends Expr {
boolean getBooleanValue() { constantBooleanExpr(this, result) }
}
/** An expression that always has the same string value. */
class ConstantStringExpr extends Expr {
ConstantStringExpr() { constantStringExpr(this, _) }
/** Get the string value of this expression. */
string getStringValue() { constantStringExpr(this, result) }
}
/**
* Gets an expression that equals `v - d`.
*/

View File

@@ -0,0 +1,90 @@
/** Provides XML definitions related to the `org.apache.commons` package. */
import java
private import semmle.code.java.dataflow.RangeUtils
private import semmle.code.java.security.XmlParsers
/**
* The classes `org.apache.commons.digester3.Digester`, `org.apache.commons.digester.Digester` or `org.apache.tomcat.util.digester.Digester`.
*/
private class Digester extends RefType {
Digester() {
this.hasQualifiedName([
"org.apache.commons.digester3", "org.apache.commons.digester",
"org.apache.tomcat.util.digester"
], "Digester")
}
}
/** A call to `Digester.parse`. */
private class DigesterParse extends XmlParserCall {
DigesterParse() {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType() instanceof Digester and
m.hasName("parse")
)
}
override Expr getSink() { result = this.getArgument(0) }
override predicate isSafe() { SafeDigesterFlow::flowToExpr(this.getQualifier()) }
}
/** A `ParserConfig` that is specific to `Digester`. */
private class DigesterConfig extends ParserConfig {
DigesterConfig() {
exists(Method m |
m = this.getMethod() and
m.getDeclaringType() instanceof Digester and
m.hasName("setFeature")
)
}
}
/**
* A safely configured `Digester`.
*/
private class SafeDigester extends VarAccess {
SafeDigester() {
exists(Variable v | v = this.getVariable() |
exists(DigesterConfig config | config.getQualifier() = v.getAnAccess() |
config.enables(singleSafeConfig())
)
or
exists(DigesterConfig config | config.getQualifier() = v.getAnAccess() |
config
.disables(any(ConstantStringExpr s |
s.getStringValue() = "http://xml.org/sax/features/external-general-entities"
))
) and
exists(DigesterConfig config | config.getQualifier() = v.getAnAccess() |
config
.disables(any(ConstantStringExpr s |
s.getStringValue() = "http://xml.org/sax/features/external-parameter-entities"
))
) and
exists(DigesterConfig config | config.getQualifier() = v.getAnAccess() |
config
.disables(any(ConstantStringExpr s |
s.getStringValue() =
"http://apache.org/xml/features/nonvalidating/load-external-dtd"
))
)
)
}
}
private module SafeDigesterFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeDigester }
predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
sink.asExpr() = ma.getQualifier() and ma.getMethod().getDeclaringType() instanceof Digester
)
}
int fieldFlowBranchLimit() { result = 0 }
}
private module SafeDigesterFlow = DataFlow::Global<SafeDigesterFlowConfig>;

View File

@@ -0,0 +1,64 @@
/** Provides definitions related to the `javax.xml` package. */
import java
private import semmle.code.java.security.XmlParsers
/** A call to `Validator.validate`. */
private class ValidatorValidate extends XmlParserCall {
ValidatorValidate() {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType() instanceof Validator and
m.hasName("validate")
)
}
override Expr getSink() { result = this.getArgument(0) }
override predicate isSafe() { SafeValidatorFlow::flowToExpr(this.getQualifier()) }
}
/** A `TransformerConfig` specific to `Validator`. */
private class ValidatorConfig extends TransformerConfig {
ValidatorConfig() {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType() instanceof Validator and
m.hasName("setProperty")
)
}
}
/** The class `javax.xml.validation.Validator`. */
private class Validator extends RefType {
Validator() { this.hasQualifiedName("javax.xml.validation", "Validator") }
}
/** A safely configured `Validator`. */
private class SafeValidator extends VarAccess {
SafeValidator() {
exists(Variable v | v = this.getVariable() |
exists(ValidatorConfig config | config.getQualifier() = v.getAnAccess() |
config.disables(configAccessExternalDtd())
) and
exists(ValidatorConfig config | config.getQualifier() = v.getAnAccess() |
config.disables(configAccessExternalSchema())
)
)
}
}
private module SafeValidatorFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeValidator }
predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
sink.asExpr() = ma.getQualifier() and
ma.getMethod().getDeclaringType() instanceof Validator
)
}
int fieldFlowBranchLimit() { result = 0 }
}
private module SafeValidatorFlow = DataFlow::Global<SafeValidatorFlowConfig>;

View File

@@ -0,0 +1,24 @@
/** Provides definitions related to the `java.beans` package. */
import java
private import semmle.code.java.security.XmlParsers
/** The class `java.beans.XMLDecoder`. */
private class XmlDecoder extends RefType {
XmlDecoder() { this.hasQualifiedName("java.beans", "XMLDecoder") }
}
/** A call to `XMLDecoder.readObject`. */
private class XmlDecoderReadObject extends XmlParserCall {
XmlDecoderReadObject() {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType() instanceof XmlDecoder and
m.hasName("readObject")
)
}
override Expr getSink() { result = this.getQualifier() }
override predicate isSafe() { none() }
}

View File

@@ -0,0 +1,19 @@
/** Provides definitions related to XML parsing in Rundeck. */
import java
private import semmle.code.java.security.XmlParsers
/** A call to `ParserHelper.loadDocument`. */
private class ParserHelperLoadDocument extends XmlParserCall {
ParserHelperLoadDocument() {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType().hasQualifiedName("org.rundeck.api.parser", "ParserHelper") and
m.hasName("loadDocument")
)
}
override Expr getSink() { result = this.getArgument(0) }
override predicate isSafe() { none() }
}

View File

@@ -2,15 +2,15 @@
import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.DataFlow2
import semmle.code.java.dataflow.DataFlow3
import semmle.code.java.dataflow.DataFlow4
import semmle.code.java.dataflow.DataFlow5
private import semmle.code.java.dataflow.SSA
private import semmle.code.java.dataflow.RangeUtils
/*
* Various XML parsers in Java.
*/
private module Frameworks {
private import semmle.code.java.frameworks.apache.CommonsXml
private import semmle.code.java.frameworks.javaee.Xml
private import semmle.code.java.frameworks.javase.Beans
private import semmle.code.java.frameworks.rundeck.RundeckXml
}
/**
* An abstract type representing a call to parse XML files.
@@ -130,26 +130,6 @@ class DocumentBuilderFactoryConfig extends ParserConfig {
}
}
private predicate constantStringExpr(Expr e, string val) {
e.(CompileTimeConstantExpr).getStringValue() = val
or
exists(SsaExplicitUpdate v, Expr src |
e = v.getAUse() and
src = v.getDefiningExpr().(VariableAssign).getSource() and
constantStringExpr(src, val)
)
}
/** An expression that always has the same string value. */
private class ConstantStringExpr extends Expr {
string value;
ConstantStringExpr() { constantStringExpr(this, value) }
/** Get the string value of this expression. */
string getStringValue() { result = value }
}
/**
* A general configuration that is safe when enabled.
*/
@@ -973,7 +953,7 @@ class TransformerFactorySource extends XmlParserCall {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType() instanceof TransformerFactory and
m.hasName("newTransformer")
m.hasName(["newTransformer", "newTransformerHandler"])
)
}

View File

@@ -27,7 +27,7 @@ abstract class MetadataExtractor extends string {
abstract predicate hasMetadata(
DataFlow::ParameterNode e, string package, string type, boolean subtypes, string name,
string signature, int input
string signature, int input, string parameterName
);
}
@@ -167,14 +167,15 @@ class FrameworkModeMetadataExtractor extends MetadataExtractor {
override predicate hasMetadata(
Endpoint e, string package, string type, boolean subtypes, string name, string signature,
int input
int input, string parameterName
) {
exists(Callable callable |
e.asParameter() = callable.getParameter(input) and
package = callable.getDeclaringType().getPackage().getName() and
type = callable.getDeclaringType().getErasure().(RefType).nestedName() and
subtypes = this.considerSubtypes(callable) and
name = e.toString() and
name = callable.getName() and
parameterName = e.asParameter().getName() and
signature = ExternalFlow::paramsString(callable)
)
}

View File

@@ -17,7 +17,7 @@ private import AutomodelSharedUtil
from
Endpoint endpoint, string message, MetadataExtractor meta, string package, string type,
boolean subtypes, string name, string signature, int input
boolean subtypes, string name, string signature, int input, string parameterName
where
not exists(CharacteristicsImpl::UninterestingToModelCharacteristic u |
u.appliesToEndpoint(endpoint)
@@ -28,7 +28,7 @@ where
// overlap between our detected sinks and the pre-existing modeling. We assume that, if a sink has already been
// modeled in a MaD model, then it doesn't belong to any additional sink types, and we don't need to reexamine it.
not CharacteristicsImpl::isSink(endpoint, _) and
meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input) and
meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, parameterName) and
// The message is the concatenation of all sink types for which this endpoint is known neither to be a sink nor to be
// a non-sink, and we surface only endpoints that have at least one such sink type.
message =
@@ -39,7 +39,7 @@ where
sinkType, ", "
)
select endpoint,
message + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@.", //
message + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@.", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", //
package.(DollarAtString), "package", //
@@ -47,4 +47,5 @@ select endpoint,
subtypes.toString().(DollarAtString), "subtypes", //
name.(DollarAtString), "name", //
signature.(DollarAtString), "signature", //
input.toString().(DollarAtString), "input" //
input.toString().(DollarAtString), "input", //
parameterName.(DollarAtString), "parameterName" //

View File

@@ -15,7 +15,7 @@ private import AutomodelSharedUtil
from
Endpoint endpoint, EndpointCharacteristic characteristic, float confidence, string message,
MetadataExtractor meta, string package, string type, boolean subtypes, string name,
string signature, int input
string signature, int input, string parameterName
where
characteristic.appliesToEndpoint(endpoint) and
confidence >= SharedCharacteristics::highConfidence() and
@@ -23,7 +23,7 @@ where
// Exclude endpoints that have contradictory endpoint characteristics, because we only want examples we're highly
// certain about in the prompt.
not erroneousEndpoints(endpoint, _, _, _, _, false) and
meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input) and
meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, parameterName) and
// It's valid for a node to satisfy the logic for both `isSink` and `isSanitizer`, but in that case it will be
// treated by the actual query as a sanitizer, since the final logic is something like
// `isSink(n) and not isSanitizer(n)`. We don't want to include such nodes as negative examples in the prompt, because
@@ -36,7 +36,7 @@ where
) and
message = characteristic
select endpoint,
message + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@.", //
message + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@.", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", //
package.(DollarAtString), "package", //
@@ -44,4 +44,5 @@ select endpoint,
subtypes.toString().(DollarAtString), "subtypes", //
name.(DollarAtString), "name", //
signature.(DollarAtString), "signature", //
input.toString().(DollarAtString), "input" //
input.toString().(DollarAtString), "input", //
parameterName.(DollarAtString), "parameterName" //

View File

@@ -14,16 +14,16 @@ private import AutomodelSharedUtil
from
Endpoint endpoint, SinkType sinkType, MetadataExtractor meta, string package, string type,
boolean subtypes, string name, string signature, int input
boolean subtypes, string name, string signature, int input, string parameterName
where
// Exclude endpoints that have contradictory endpoint characteristics, because we only want examples we're highly
// certain about in the prompt.
not erroneousEndpoints(endpoint, _, _, _, _, false) and
meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input) and
meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, parameterName) and
// Extract positive examples of sinks belonging to the existing ATM query configurations.
CharacteristicsImpl::isKnownSink(endpoint, sinkType)
select endpoint,
sinkType + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@.", //
sinkType + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@.", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", //
package.(DollarAtString), "package", //
@@ -31,4 +31,5 @@ select endpoint,
subtypes.toString().(DollarAtString), "subtypes", //
name.(DollarAtString), "name", //
signature.(DollarAtString), "signature", //
input.toString().(DollarAtString), "input" //
input.toString().(DollarAtString), "input", //
parameterName.(DollarAtString), "parameterName" //

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Experimental sinks for the query "Resolving XML external entity in user-controlled data" (`java/xxe`) have been promoted to the main query pack. These sinks were originally [submitted as part of an experimental query by @haby0](https://github.com/github/codeql/pull/6564).

View File

@@ -1,85 +0,0 @@
import java.beans.XMLDecoder;
import java.io.BufferedReader;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.apache.commons.digester3.Digester;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class XxeController {
@PostMapping(value = "xxe1")
public void bad1(HttpServletRequest request, HttpServletResponse response) throws Exception {
ServletInputStream servletInputStream = request.getInputStream();
Digester digester = new Digester();
digester.parse(servletInputStream);
}
@PostMapping(value = "xxe2")
public void bad2(HttpServletRequest request) throws Exception {
BufferedReader br = request.getReader();
String str = "";
StringBuilder listString = new StringBuilder();
while ((str = br.readLine()) != null) {
listString.append(str).append("\n");
}
Document document = DocumentHelper.parseText(listString.toString());
}
@PostMapping(value = "xxe3")
public void bad3(HttpServletRequest request) throws Exception {
ServletInputStream servletInputStream = request.getInputStream();
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema schema = factory.newSchema();
Validator validator = schema.newValidator();
StreamSource source = new StreamSource(servletInputStream);
validator.validate(source);
}
@PostMapping(value = "xxe4")
public void bad4(HttpServletRequest request) throws Exception {
ServletInputStream servletInputStream = request.getInputStream();
XMLDecoder xmlDecoder = new XMLDecoder(servletInputStream);
xmlDecoder.readObject();
}
@PostMapping(value = "good1")
public void good1(HttpServletRequest request, HttpServletResponse response) throws Exception {
BufferedReader br = request.getReader();
String str = "";
StringBuilder listString = new StringBuilder();
while ((str = br.readLine()) != null) {
listString.append(str);
}
Digester digester = new Digester();
digester.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
digester.setFeature("http://xml.org/sax/features/external-general-entities", false);
digester.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
digester.parse(listString.toString());
}
@PostMapping(value = "good2")
public void good2(HttpServletRequest request, HttpServletResponse response) throws Exception {
BufferedReader br = request.getReader();
String str = "";
StringBuilder listString = new StringBuilder();
while ((str = br.readLine()) != null) {
listString.append(str).append("\n");
}
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema schema = factory.newSchema();
Validator validator = schema.newValidator();
validator.setProperty("http://javax.xml.XMLConstants/property/accessExternalDTD", "");
validator.setProperty("http://javax.xml.XMLConstants/property/accessExternalSchema", "");
StreamSource source = new StreamSource(listString.toString());
validator.validate(source);
}
}

View File

@@ -1,67 +0,0 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>
Parsing untrusted XML files with a weakly configured XML parser may lead to an XML External Entity (XXE) attack. This type of attack
uses external entity references to access arbitrary files on a system, carry out denial of service, or server side
request forgery. Even when the result of parsing is not returned to the user, out-of-band
data retrieval techniques may allow attackers to steal sensitive data. Denial of services can also be
carried out in this situation.
</p>
<p>
There are many XML parsers for Java, and most of them are vulnerable to XXE because their default settings enable parsing of
external entities. This query currently identifies vulnerable XML parsing from the following parsers: <code>javax.xml.validation.Validator</code>,
<code>org.dom4j.DocumentHelper</code>, <code>org.rundeck.api.parser.ParserHelper</code>, <code>org.apache.commons.digester3.Digester</code>,
<code>org.apache.commons.digester.Digester</code>, <code>org.apache.tomcat.util.digester.Digester</code>, <code>java.beans.XMLDecoder</code>.
</p>
</overview>
<recommendation>
<p>
The best way to prevent XXE attacks is to disable the parsing of any Document Type Declarations (DTDs) in untrusted data.
If this is not possible you should disable the parsing of external general entities and external parameter entities.
This improves security but the code will still be at risk of denial of service and server side request forgery attacks.
Protection against denial of service attacks may also be implemented by setting entity expansion limits, which is done
by default in recent JDK and JRE implementations.
</p>
</recommendation>
<example>
<p>
The following bad examples parses the xml data entered by the user under an unsafe configuration, which is inherently insecure and may cause xml entity injection.
In good examples, the security configuration is carried out, for example: Disable DTD to protect the program from XXE attacks.
</p>
<sample src="XXE.java" />
</example>
<references>
<li>
OWASP vulnerability description:
<a href="https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing">XML External Entity (XXE) Processing</a>.
</li>
<li>
OWASP guidance on parsing xml files:
<a href="https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#java">XXE Prevention Cheat Sheet</a>.
</li>
<li>
Paper by Timothy Morgen:
<a href="https://research.nccgroup.com/2014/05/19/xml-schema-dtd-and-entity-attacks-a-compendium-of-known-techniques/">XML Schema, DTD, and Entity Attacks</a>
</li>
<li>
Out-of-band data retrieval: Timur Yunusov &amp; Alexey Osipov, Black hat EU 2013:
<a href="https://www.slideshare.net/qqlan/bh-ready-v4">XML Out-Of-Band Data Retrieval</a>.
</li>
<li>
Denial of service attack (Billion laughs):
<a href="https://en.wikipedia.org/wiki/Billion_laughs">Billion Laughs.</a>
</li>
<li>
The Java Tutorials:
<a href="https://docs.oracle.com/javase/tutorial/jaxp/limits/limits.html">Processing Limit Definitions.</a>
</li>
</references>
</qhelp>

View File

@@ -1,32 +0,0 @@
/**
* @name Resolving XML external entity in user-controlled data (experimental sinks)
* @description Parsing user-controlled XML documents and allowing expansion of external entity
* references may lead to disclosure of confidential data or denial of service.
* (note this version differs from query `java/xxe` by including support for additional possibly-vulnerable XML parsers)
* @kind path-problem
* @problem.severity error
* @precision high
* @id java/xxe-with-experimental-sinks
* @tags security
* experimental
* external/cwe/cwe-611
*/
import java
import XXELib
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.FlowSources
import XxeFlow::PathGraph
module XxeConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeXxeSink }
}
module XxeFlow = TaintTracking::Global<XxeConfig>;
from XxeFlow::PathNode source, XxeFlow::PathNode sink
where XxeFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Unsafe parsing of XML file from $@.", source.getNode(),
"user input"

View File

@@ -1,246 +0,0 @@
import java
import semmle.code.java.dataflow.DataFlow3
import semmle.code.java.dataflow.DataFlow4
import semmle.code.java.dataflow.DataFlow5
import semmle.code.java.security.XmlParsers
private import semmle.code.java.dataflow.SSA
/** A data flow sink for untrusted user input used to insecure xml parse. */
class UnsafeXxeSink extends DataFlow::ExprNode {
UnsafeXxeSink() {
exists(XmlParserCall parse |
parse.getSink() = this.getExpr() and
not parse.isSafe()
)
}
}
/** The class `org.rundeck.api.parser.ParserHelper`. */
class ParserHelper extends RefType {
ParserHelper() { this.hasQualifiedName("org.rundeck.api.parser", "ParserHelper") }
}
/** A call to `ParserHelper.loadDocument`. */
class ParserHelperLoadDocument extends XmlParserCall {
ParserHelperLoadDocument() {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType() instanceof ParserHelper and
m.hasName("loadDocument")
)
}
override Expr getSink() { result = this.getArgument(0) }
override predicate isSafe() { none() }
}
/** The class `javax.xml.validation.Validator`. */
class Validator extends RefType {
Validator() { this.hasQualifiedName("javax.xml.validation", "Validator") }
}
/** A call to `Validator.validate`. */
class ValidatorValidate extends XmlParserCall {
ValidatorValidate() {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType() instanceof Validator and
m.hasName("validate")
)
}
override Expr getSink() { result = this.getArgument(0) }
override predicate isSafe() { SafeValidatorFlow::flowToExpr(this.getQualifier()) }
}
/** A `ParserConfig` specific to `Validator`. */
class ValidatorConfig extends TransformerConfig {
ValidatorConfig() {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType() instanceof Validator and
m.hasName("setProperty")
)
}
}
/** A safely configured `Validator`. */
class SafeValidator extends VarAccess {
SafeValidator() {
exists(Variable v | v = this.getVariable() |
exists(ValidatorConfig config | config.getQualifier() = v.getAnAccess() |
config.disables(configAccessExternalDtd())
) and
exists(ValidatorConfig config | config.getQualifier() = v.getAnAccess() |
config.disables(configAccessExternalSchema())
)
)
}
}
private module SafeValidatorFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeValidator }
predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
sink.asExpr() = ma.getQualifier() and
ma.getMethod().getDeclaringType() instanceof Validator
)
}
int fieldFlowBranchLimit() { result = 0 }
}
private module SafeValidatorFlow = DataFlow::Global<SafeValidatorFlowConfig>;
/**
* The classes `org.apache.commons.digester3.Digester`, `org.apache.commons.digester.Digester` or `org.apache.tomcat.util.digester.Digester`.
*/
class Digester extends RefType {
Digester() {
this.hasQualifiedName([
"org.apache.commons.digester3", "org.apache.commons.digester",
"org.apache.tomcat.util.digester"
], "Digester")
}
}
/** A call to `Digester.parse`. */
class DigesterParse extends XmlParserCall {
DigesterParse() {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType() instanceof Digester and
m.hasName("parse")
)
}
override Expr getSink() { result = this.getArgument(0) }
override predicate isSafe() { SafeDigesterFlow::flowToExpr(this.getQualifier()) }
}
/** A `ParserConfig` that is specific to `Digester`. */
class DigesterConfig extends ParserConfig {
DigesterConfig() {
exists(Method m |
m = this.getMethod() and
m.getDeclaringType() instanceof Digester and
m.hasName("setFeature")
)
}
}
/**
* A safely configured `Digester`.
*/
class SafeDigester extends VarAccess {
SafeDigester() {
exists(Variable v | v = this.getVariable() |
exists(DigesterConfig config | config.getQualifier() = v.getAnAccess() |
config.enables(singleSafeConfig())
)
or
exists(DigesterConfig config | config.getQualifier() = v.getAnAccess() |
config
.disables(any(ConstantStringExpr s |
s.getStringValue() = "http://xml.org/sax/features/external-general-entities"
))
) and
exists(DigesterConfig config | config.getQualifier() = v.getAnAccess() |
config
.disables(any(ConstantStringExpr s |
s.getStringValue() = "http://xml.org/sax/features/external-parameter-entities"
))
) and
exists(DigesterConfig config | config.getQualifier() = v.getAnAccess() |
config
.disables(any(ConstantStringExpr s |
s.getStringValue() =
"http://apache.org/xml/features/nonvalidating/load-external-dtd"
))
)
)
}
}
private module SafeDigesterFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeDigester }
predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
sink.asExpr() = ma.getQualifier() and ma.getMethod().getDeclaringType() instanceof Digester
)
}
int fieldFlowBranchLimit() { result = 0 }
}
private module SafeDigesterFlow = DataFlow::Global<SafeDigesterFlowConfig>;
/** The class `java.beans.XMLDecoder`. */
class XmlDecoder extends RefType {
XmlDecoder() { this.hasQualifiedName("java.beans", "XMLDecoder") }
}
/** DEPRECATED: Alias for XmlDecoder */
deprecated class XMLDecoder = XmlDecoder;
/** A call to `XMLDecoder.readObject`. */
class XmlDecoderReadObject extends XmlParserCall {
XmlDecoderReadObject() {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType() instanceof XmlDecoder and
m.hasName("readObject")
)
}
override Expr getSink() { result = this.getQualifier() }
override predicate isSafe() { none() }
}
/** DEPRECATED: Alias for XmlDecoderReadObject */
deprecated class XMLDecoderReadObject = XmlDecoderReadObject;
private predicate constantStringExpr(Expr e, string val) {
e.(CompileTimeConstantExpr).getStringValue() = val
or
exists(SsaExplicitUpdate v, Expr src |
e = v.getAUse() and
src = v.getDefiningExpr().(VariableAssign).getSource() and
constantStringExpr(src, val)
)
}
/** A call to `SAXTransformerFactory.newTransformerHandler`. */
class SaxTransformerFactoryNewTransformerHandler extends XmlParserCall {
SaxTransformerFactoryNewTransformerHandler() {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType().hasQualifiedName("javax.xml.transform.sax", "SAXTransformerFactory") and
m.hasName("newTransformerHandler")
)
}
override Expr getSink() { result = this.getArgument(0) }
override predicate isSafe() { SafeTransformerFactoryFlow::flowToExpr(this.getQualifier()) }
}
/** DEPRECATED: Alias for SaxTransformerFactoryNewTransformerHandler */
deprecated class SAXTransformerFactoryNewTransformerHandler =
SaxTransformerFactoryNewTransformerHandler;
/** An expression that always has the same string value. */
private class ConstantStringExpr extends Expr {
string value;
ConstantStringExpr() { constantStringExpr(this, value) }
/** Get the string value of this expression. */
string getStringValue() { result = value }
}

View File

@@ -1,5 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="XXE.qhelp" /></qhelp>

View File

@@ -1,34 +0,0 @@
/**
* @name Resolving XML external entity from a local source (experimental sinks)
* @description Parsing user-controlled XML documents and allowing expansion of external entity
* references may lead to disclosure of confidential data or denial of service.
* (note this version differs from query `java/xxe` by including support for additional possibly-vulnerable XML parsers,
* and by considering local information sources dangerous (e.g. environment variables) in addition to the remote sources
* considered by the normal `java/xxe` query)
* @kind path-problem
* @problem.severity recommendation
* @precision medium
* @id java/xxe-local-experimental-sinks
* @tags security
* experimental
* external/cwe/cwe-611
*/
import java
import XXELib
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.FlowSources
import XxeLocalFlow::PathGraph
module XxeLocalConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src instanceof LocalUserInput }
predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeXxeSink }
}
module XxeLocalFlow = TaintTracking::Global<XxeLocalConfig>;
from XxeLocalFlow::PathNode source, XxeLocalFlow::PathNode sink
where XxeLocalFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Unsafe parsing of XML file from $@.", source.getNode(),
"user input"

View File

@@ -1,26 +0,0 @@
edges
| XXE.java:22:43:22:66 | getInputStream(...) : ServletInputStream | XXE.java:24:18:24:35 | servletInputStream |
| XXE.java:29:43:29:66 | getInputStream(...) : ServletInputStream | XXE.java:33:42:33:59 | servletInputStream : ServletInputStream |
| XXE.java:33:25:33:60 | new StreamSource(...) : StreamSource | XXE.java:34:22:34:27 | source |
| XXE.java:33:42:33:59 | servletInputStream : ServletInputStream | XXE.java:33:25:33:60 | new StreamSource(...) : StreamSource |
| XXE.java:39:43:39:66 | getInputStream(...) : ServletInputStream | XXE.java:40:42:40:59 | servletInputStream : ServletInputStream |
| XXE.java:40:27:40:60 | new XMLDecoder(...) : XMLDecoder | XXE.java:41:3:41:12 | xmlDecoder |
| XXE.java:40:42:40:59 | servletInputStream : ServletInputStream | XXE.java:40:27:40:60 | new XMLDecoder(...) : XMLDecoder |
nodes
| XXE.java:22:43:22:66 | getInputStream(...) : ServletInputStream | semmle.label | getInputStream(...) : ServletInputStream |
| XXE.java:24:18:24:35 | servletInputStream | semmle.label | servletInputStream |
| XXE.java:29:43:29:66 | getInputStream(...) : ServletInputStream | semmle.label | getInputStream(...) : ServletInputStream |
| XXE.java:33:25:33:60 | new StreamSource(...) : StreamSource | semmle.label | new StreamSource(...) : StreamSource |
| XXE.java:33:42:33:59 | servletInputStream : ServletInputStream | semmle.label | servletInputStream : ServletInputStream |
| XXE.java:34:22:34:27 | source | semmle.label | source |
| XXE.java:39:43:39:66 | getInputStream(...) : ServletInputStream | semmle.label | getInputStream(...) : ServletInputStream |
| XXE.java:40:27:40:60 | new XMLDecoder(...) : XMLDecoder | semmle.label | new XMLDecoder(...) : XMLDecoder |
| XXE.java:40:42:40:59 | servletInputStream : ServletInputStream | semmle.label | servletInputStream : ServletInputStream |
| XXE.java:41:3:41:12 | xmlDecoder | semmle.label | xmlDecoder |
| XXE.java:46:49:46:72 | getInputStream(...) | semmle.label | getInputStream(...) |
subpaths
#select
| XXE.java:24:18:24:35 | servletInputStream | XXE.java:22:43:22:66 | getInputStream(...) : ServletInputStream | XXE.java:24:18:24:35 | servletInputStream | Unsafe parsing of XML file from $@. | XXE.java:22:43:22:66 | getInputStream(...) | user input |
| XXE.java:34:22:34:27 | source | XXE.java:29:43:29:66 | getInputStream(...) : ServletInputStream | XXE.java:34:22:34:27 | source | Unsafe parsing of XML file from $@. | XXE.java:29:43:29:66 | getInputStream(...) | user input |
| XXE.java:41:3:41:12 | xmlDecoder | XXE.java:39:43:39:66 | getInputStream(...) : ServletInputStream | XXE.java:41:3:41:12 | xmlDecoder | Unsafe parsing of XML file from $@. | XXE.java:39:43:39:66 | getInputStream(...) | user input |
| XXE.java:46:49:46:72 | getInputStream(...) | XXE.java:46:49:46:72 | getInputStream(...) | XXE.java:46:49:46:72 | getInputStream(...) | Unsafe parsing of XML file from $@. | XXE.java:46:49:46:72 | getInputStream(...) | user input |

View File

@@ -1,92 +0,0 @@
import java.beans.XMLDecoder;
import java.io.BufferedReader;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.rundeck.api.parser.ParserHelper;
import org.apache.commons.digester3.Digester;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class XXE {
@PostMapping(value = "bad1")
public void bad1(HttpServletRequest request, HttpServletResponse response) throws Exception {
ServletInputStream servletInputStream = request.getInputStream();
Digester digester = new Digester();
digester.parse(servletInputStream); // bad
}
@PostMapping(value = "bad2")
public void bad2(HttpServletRequest request) throws Exception {
ServletInputStream servletInputStream = request.getInputStream();
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema schema = factory.newSchema();
Validator validator = schema.newValidator();
StreamSource source = new StreamSource(servletInputStream);
validator.validate(source); // bad
}
@PostMapping(value = "bad3")
public void bad3(HttpServletRequest request) throws Exception {
ServletInputStream servletInputStream = request.getInputStream();
XMLDecoder xmlDecoder = new XMLDecoder(servletInputStream);
xmlDecoder.readObject(); // bad
}
@PostMapping(value = "bad4")
public void bad4(HttpServletRequest request) throws Exception {
Document document = ParserHelper.loadDocument(request.getInputStream()); // bad
}
@PostMapping(value = "good1")
public void good1(HttpServletRequest request, HttpServletResponse response) throws Exception {
BufferedReader br = request.getReader();
String str = "";
StringBuilder listString = new StringBuilder();
while ((str = br.readLine()) != null) {
listString.append(str);
}
Digester digester = new Digester();
digester.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
digester.setFeature("http://xml.org/sax/features/external-general-entities", false);
digester.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
digester.parse(listString.toString());
}
@PostMapping(value = "good2")
public void good2(HttpServletRequest request, HttpServletResponse response) throws Exception {
BufferedReader br = request.getReader();
String str = "";
StringBuilder listString = new StringBuilder();
while ((str = br.readLine()) != null) {
listString.append(str).append("\n");
}
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema schema = factory.newSchema();
Validator validator = schema.newValidator();
validator.setProperty("http://javax.xml.XMLConstants/property/accessExternalDTD", "");
validator.setProperty("http://javax.xml.XMLConstants/property/accessExternalSchema", "");
StreamSource source = new StreamSource(listString.toString());
validator.validate(source);
}
@PostMapping(value = "good3")
public void good3(HttpServletRequest request) throws Exception {
BufferedReader br = request.getReader();
String str = "";
StringBuilder listString = new StringBuilder();
while ((str = br.readLine()) != null) {
listString.append(str).append("\n");
}
// parseText falls back to a default SAXReader, which is safe
Document document = DocumentHelper.parseText(listString.toString()); // Safe
}
}

View File

@@ -1 +0,0 @@
experimental/Security/CWE/CWE-611/XXE.ql

View File

@@ -1 +0,0 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/servlet-api-2.4/:${testdir}/../../../../stubs/springframework-5.3.8/:${testdir}/../../../../stubs/dom4j-2.1.1:${testdir}/../../../../stubs/apache-commons-digester3-3.2:${testdir}/../../../../stubs/jaxen-1.2.0/:${testdir}/../../../../stubs/rundeck-api-java-client-13.2

View File

@@ -1,7 +1,13 @@
import java.sql.ResultSet;
import java.util.Map;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.PreparedStatementCallback;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.object.BatchSqlUpdate;
import org.springframework.jdbc.object.MappingSqlQueryWithParameters;
import org.springframework.jdbc.object.SqlFunction;
@@ -22,7 +28,7 @@ public class SpringJdbc {
}
}
public static void test(JdbcTemplate template) {
public static void test(JdbcTemplate template, NamedParameterJdbcOperations namedParamTemplate) {
new BatchSqlUpdate(null, source()); // $ sqlInjection
new SqlFunction(null, source()); // $ sqlInjection
new SqlUpdate(null, source()); // $ sqlInjection
@@ -39,6 +45,39 @@ public class SpringJdbc {
template.queryForObject(source(), (Class)null); // $ sqlInjection
template.queryForRowSet(source()); // $ sqlInjection
template.queryForStream(source(), (RowMapper)null); // $ sqlInjection
namedParamTemplate.batchUpdate(source(), (Map<String, ?>[]) null); // $ sqlInjection
namedParamTemplate.batchUpdate(source(), (SqlParameterSource[]) null); // $ sqlInjection
namedParamTemplate.execute(source(), (PreparedStatementCallback) null); // $ sqlInjection
namedParamTemplate.execute(source(), (Map<String, ?>) null, (PreparedStatementCallback) null); // $ sqlInjection
namedParamTemplate.execute(source(), (SqlParameterSource) null, (PreparedStatementCallback) null); // $ sqlInjection
namedParamTemplate.query(source(), (Map<String, ?>) null, (ResultSetExtractor) null); // $ sqlInjection
namedParamTemplate.query(source(), (Map<String, ?>) null, (RowMapper) null); // $ sqlInjection
namedParamTemplate.query(source(), (Map<String, ?>) null, (RowCallbackHandler) null); // $ sqlInjection
namedParamTemplate.query(source(), (SqlParameterSource) null, (ResultSetExtractor) null); // $ sqlInjection
namedParamTemplate.query(source(), (SqlParameterSource) null, (RowMapper) null); // $ sqlInjection
namedParamTemplate.query(source(), (SqlParameterSource) null, (RowCallbackHandler) null); // $ sqlInjection
namedParamTemplate.query(source(), (ResultSetExtractor) null); // $ sqlInjection
namedParamTemplate.query(source(), (RowMapper) null); // $ sqlInjection
namedParamTemplate.query(source(), (RowCallbackHandler) null); // $ sqlInjection
namedParamTemplate.queryForList(source(), (Map<String, ?>) null); // $ sqlInjection
namedParamTemplate.queryForList(source(), (Map<String, ?>) null, (Class) null); // $ sqlInjection
namedParamTemplate.queryForList(source(), (SqlParameterSource) null); // $ sqlInjection
namedParamTemplate.queryForList(source(), (SqlParameterSource) null, (Class) null); // $ sqlInjection
namedParamTemplate.queryForMap(source(), (Map<String, ?>) null); // $ sqlInjection
namedParamTemplate.queryForMap(source(), (SqlParameterSource) null); // $ sqlInjection
namedParamTemplate.queryForObject(source(), (Map<String, ?>) null, (Class) null); // $ sqlInjection
namedParamTemplate.queryForObject(source(), (Map<String, ?>) null, (RowMapper) null); // $ sqlInjection
namedParamTemplate.queryForObject(source(), (SqlParameterSource) null, (Class) null); // $ sqlInjection
namedParamTemplate.queryForObject(source(), (SqlParameterSource) null, (RowMapper) null); // $ sqlInjection
namedParamTemplate.queryForRowSet(source(), (Map<String, ?>) null); // $ sqlInjection
namedParamTemplate.queryForRowSet(source(), (SqlParameterSource) null); // $ sqlInjection
namedParamTemplate.queryForStream(source(), (Map<String, ?>) null, (RowMapper) null); // $ sqlInjection
namedParamTemplate.queryForStream(source(), (SqlParameterSource) null, (RowMapper) null); // $ sqlInjection
namedParamTemplate.update(source(), (Map<String, ?>) null); // $ sqlInjection
namedParamTemplate.update(source(), (SqlParameterSource) null); // $ sqlInjection
namedParamTemplate.update(source(), null, null); // $ sqlInjection
namedParamTemplate.update(source(), null, null, null); // $ sqlInjection
}
}

View File

@@ -0,0 +1,33 @@
import java.io.BufferedReader;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.digester3.Digester;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class DigesterTests {
@PostMapping(value = "bad")
public void bad1(HttpServletRequest request, HttpServletResponse response) throws Exception {
ServletInputStream servletInputStream = request.getInputStream();
Digester digester = new Digester();
digester.parse(servletInputStream); // $ hasTaintFlow
}
@PostMapping(value = "good")
public void good1(HttpServletRequest request, HttpServletResponse response) throws Exception {
BufferedReader br = request.getReader();
String str = "";
StringBuilder listString = new StringBuilder();
while ((str = br.readLine()) != null) {
listString.append(str);
}
Digester digester = new Digester();
digester.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
digester.setFeature("http://xml.org/sax/features/external-general-entities", false);
digester.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
digester.parse(listString.toString());
}
}

View File

@@ -11,42 +11,44 @@ class DocumentBuilderTests {
public void unconfiguredParse(Socket sock) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
builder.parse(sock.getInputStream()); //unsafe
builder.parse(sock.getInputStream()); // $ hasTaintFlow
}
public void disableDTD(Socket sock) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
DocumentBuilder builder = factory.newDocumentBuilder();
builder.parse(sock.getInputStream()); //safe
builder.parse(sock.getInputStream()); // safe
}
public void enableSecurityFeature(Socket sock) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
DocumentBuilder builder = factory.newDocumentBuilder();
builder.parse(sock.getInputStream()); //unsafe -- secure-processing by itself is insufficient
builder.parse(sock.getInputStream()); // $ hasTaintFlow -- secure-processing by itself is
// insufficient
}
public void enableSecurityFeature2(Socket sock) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature("http://javax.xml.XMLConstants/feature/secure-processing", true);
DocumentBuilder builder = factory.newDocumentBuilder();
builder.parse(sock.getInputStream()); //unsafe -- secure-processing by itself is insufficient
builder.parse(sock.getInputStream()); // $ hasTaintFlow -- secure-processing by itself is
// insufficient
}
public void enableDTD(Socket sock) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false);
DocumentBuilder builder = factory.newDocumentBuilder();
builder.parse(sock.getInputStream()); //unsafe
builder.parse(sock.getInputStream()); // $ hasTaintFlow
}
public void disableSecurityFeature(Socket sock) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature("http://javax.xml.XMLConstants/feature/secure-processing", false);
DocumentBuilder builder = factory.newDocumentBuilder();
builder.parse(sock.getInputStream()); //unsafe
builder.parse(sock.getInputStream()); // $ hasTaintFlow
}
public void disableExternalEntities(Socket sock) throws Exception {
@@ -54,21 +56,21 @@ class DocumentBuilderTests {
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
DocumentBuilder builder = factory.newDocumentBuilder();
builder.parse(sock.getInputStream()); //safe
builder.parse(sock.getInputStream()); // safe
}
public void partialDisableExternalEntities(Socket sock) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
DocumentBuilder builder = factory.newDocumentBuilder();
builder.parse(sock.getInputStream()); //unsafe
builder.parse(sock.getInputStream()); // $ hasTaintFlow
}
public void partialDisableExternalEntities2(Socket sock) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
DocumentBuilder builder = factory.newDocumentBuilder();
builder.parse(sock.getInputStream()); //unsafe
builder.parse(sock.getInputStream()); // $ hasTaintFlow
}
public void misConfigureExternalEntities1(Socket sock) throws Exception {
@@ -76,7 +78,7 @@ class DocumentBuilderTests {
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", true);
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
DocumentBuilder builder = factory.newDocumentBuilder();
builder.parse(sock.getInputStream()); //unsafe
builder.parse(sock.getInputStream()); // $ hasTaintFlow
}
public void misConfigureExternalEntities2(Socket sock) throws Exception {
@@ -84,22 +86,22 @@ class DocumentBuilderTests {
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
factory.setFeature("http://xml.org/sax/features/external-general-entities", true);
DocumentBuilder builder = factory.newDocumentBuilder();
builder.parse(sock.getInputStream()); //unsafe
builder.parse(sock.getInputStream()); // $ hasTaintFlow
}
public void taintedSAXInputSource1(Socket sock) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
SAXSource source = new SAXSource(new InputSource(sock.getInputStream()));
builder.parse(source.getInputSource()); //unsafe
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
SAXSource source = new SAXSource(new InputSource(sock.getInputStream()));
builder.parse(source.getInputSource()); // $ hasTaintFlow
}
public void taintedSAXInputSource2(Socket sock) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
StreamSource source = new StreamSource(sock.getInputStream());
builder.parse(SAXSource.sourceToInputSource(source)); //unsafe
builder.parse(source.getInputStream()); //unsafe
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
StreamSource source = new StreamSource(sock.getInputStream());
builder.parse(SAXSource.sourceToInputSource(source)); // $ hasTaintFlow
builder.parse(source.getInputStream()); // $ hasTaintFlow
}
private static DocumentBuilderFactory getDocumentBuilderFactory() throws Exception {
@@ -112,21 +114,22 @@ class DocumentBuilderTests {
return factory;
}
private static final ThreadLocal<DocumentBuilder> XML_DOCUMENT_BUILDER = new ThreadLocal<DocumentBuilder>() {
@Override
protected DocumentBuilder initialValue() {
try {
DocumentBuilderFactory factory = getDocumentBuilderFactory();
return factory.newDocumentBuilder();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
};
private static final ThreadLocal<DocumentBuilder> XML_DOCUMENT_BUILDER =
new ThreadLocal<DocumentBuilder>() {
@Override
protected DocumentBuilder initialValue() {
try {
DocumentBuilderFactory factory = getDocumentBuilderFactory();
return factory.newDocumentBuilder();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
};
public void disableExternalEntities2(Socket sock) throws Exception {
DocumentBuilder builder = XML_DOCUMENT_BUILDER.get();
builder.parse(sock.getInputStream()); //safe
builder.parse(sock.getInputStream()); // safe
}
}

View File

@@ -0,0 +1,14 @@
import javax.servlet.http.HttpServletRequest;
import org.dom4j.Document;
import org.rundeck.api.parser.ParserHelper;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class ParserHelperTests {
@PostMapping(value = "bad4")
public void bad4(HttpServletRequest request) throws Exception {
Document document = ParserHelper.loadDocument(request.getInputStream()); // $ hasTaintFlow
}
}

View File

@@ -5,18 +5,18 @@ public class SAXBuilderTests {
public void unconfiguredSAXBuilder(Socket sock) throws Exception {
SAXBuilder builder = new SAXBuilder();
builder.build(sock.getInputStream()); //unsafe
builder.build(sock.getInputStream()); // $ hasTaintFlow
}
public void safeBuilder(Socket sock) throws Exception {
SAXBuilder builder = new SAXBuilder();
builder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
builder.build(sock.getInputStream()); //safe
builder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
builder.build(sock.getInputStream()); // safe
}
public void misConfiguredBuilder(Socket sock) throws Exception {
SAXBuilder builder = new SAXBuilder();
builder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",false);
builder.build(sock.getInputStream()); //unsafe
builder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false);
builder.build(sock.getInputStream()); // $ hasTaintFlow
}
}

View File

@@ -6,78 +6,78 @@ import javax.xml.XMLConstants;
import org.xml.sax.helpers.DefaultHandler;
public class SAXParserTests {
public void unconfiguredParser(Socket sock) throws Exception {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
parser.parse(sock.getInputStream(), new DefaultHandler()); //unsafe
parser.parse(sock.getInputStream(), new DefaultHandler()); // $ hasTaintFlow
}
public void safeParser(Socket sock) throws Exception {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
SAXParser parser = factory.newSAXParser();
parser.parse(sock.getInputStream(), new DefaultHandler()); //safe
parser.parse(sock.getInputStream(), new DefaultHandler()); // safe
}
public void partialConfiguredParser1(Socket sock) throws Exception {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
SAXParser parser = factory.newSAXParser();
parser.parse(sock.getInputStream(), new DefaultHandler()); //unsafe
parser.parse(sock.getInputStream(), new DefaultHandler()); // $ hasTaintFlow
}
public void partialConfiguredParser2(Socket sock) throws Exception {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
SAXParser parser = factory.newSAXParser();
parser.parse(sock.getInputStream(), new DefaultHandler()); //unsafe
parser.parse(sock.getInputStream(), new DefaultHandler()); // $ hasTaintFlow
}
public void partialConfiguredParser3(Socket sock) throws Exception {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
SAXParser parser = factory.newSAXParser();
parser.parse(sock.getInputStream(), new DefaultHandler()); //unsafe
parser.parse(sock.getInputStream(), new DefaultHandler()); // $ hasTaintFlow
}
public void misConfiguredParser1(Socket sock) throws Exception {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setFeature("http://xml.org/sax/features/external-general-entities", true);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
SAXParser parser = factory.newSAXParser();
parser.parse(sock.getInputStream(), new DefaultHandler()); //unsafe
parser.parse(sock.getInputStream(), new DefaultHandler()); // $ hasTaintFlow
}
public void misConfiguredParser2(Socket sock) throws Exception {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", true);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
SAXParser parser = factory.newSAXParser();
parser.parse(sock.getInputStream(), new DefaultHandler()); //unsafe
parser.parse(sock.getInputStream(), new DefaultHandler()); // $ hasTaintFlow
}
public void misConfiguredParser3(Socket sock) throws Exception {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", true);
SAXParser parser = factory.newSAXParser();
parser.parse(sock.getInputStream(), new DefaultHandler()); //unsafe
parser.parse(sock.getInputStream(), new DefaultHandler()); // $ hasTaintFlow
}
public void safeParser2(Socket sock) throws Exception {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
SAXParser parser = factory.newSAXParser();
parser.parse(sock.getInputStream(), new DefaultHandler()); //safe
parser.parse(sock.getInputStream(), new DefaultHandler()); // safe
}
}

View File

@@ -5,59 +5,59 @@ public class SAXReaderTests {
public void unconfiguredReader(Socket sock) throws Exception {
SAXReader reader = new SAXReader();
reader.read(sock.getInputStream()); //unsafe
reader.read(sock.getInputStream()); // $ hasTaintFlow
}
public void safeReader(Socket sock) throws Exception {
SAXReader reader = new SAXReader();
reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
reader.read(sock.getInputStream()); //safe
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
reader.read(sock.getInputStream()); // safe
}
public void partialConfiguredReader1(Socket sock) throws Exception {
SAXReader reader = new SAXReader();
reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
reader.read(sock.getInputStream()); //unsafe
reader.read(sock.getInputStream()); // $ hasTaintFlow
}
public void partialConfiguredReader2(Socket sock) throws Exception {
SAXReader reader = new SAXReader();
reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
reader.read(sock.getInputStream()); //unsafe
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
reader.read(sock.getInputStream()); // $ hasTaintFlow
}
public void partialConfiguredReader3(Socket sock) throws Exception {
SAXReader reader = new SAXReader();
reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
reader.read(sock.getInputStream()); //unsafe
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
reader.read(sock.getInputStream()); // $ hasTaintFlow
}
public void misConfiguredReader1(Socket sock) throws Exception {
SAXReader reader = new SAXReader();
reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
reader.setFeature("http://xml.org/sax/features/external-general-entities", true);
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
reader.read(sock.getInputStream()); //unsafe
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
reader.read(sock.getInputStream()); // $ hasTaintFlow
}
public void misConfiguredReader2(Socket sock) throws Exception {
SAXReader reader = new SAXReader();
reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false);
reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
reader.read(sock.getInputStream()); //unsafe
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
reader.read(sock.getInputStream()); // $ hasTaintFlow
}
public void misConfiguredReader3(Socket sock) throws Exception {
SAXReader reader = new SAXReader();
reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", true);
reader.read(sock.getInputStream()); //unsafe
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", true);
reader.read(sock.getInputStream()); // $ hasTaintFlow
}
}

View File

@@ -17,14 +17,14 @@ public class SAXSourceTests {
SAXSource source = new SAXSource(reader, new InputSource(sock.getInputStream()));
JAXBContext jc = JAXBContext.newInstance(Object.class);
Unmarshaller um = jc.createUnmarshaller();
um.unmarshal(source); // BAD
um.unmarshal(source); // $ hasTaintFlow
}
public void explicitlySafeSource1(Socket sock) throws Exception {
XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd",false);
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
SAXSource source = new SAXSource(reader, new InputSource(sock.getInputStream())); // GOOD
}

View File

@@ -9,39 +9,39 @@ public class SchemaTests {
public void unconfiguredSchemaFactory(Socket sock) throws Exception {
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema schema = factory.newSchema(new StreamSource(sock.getInputStream())); //unsafe
Schema schema = factory.newSchema(new StreamSource(sock.getInputStream())); // $ hasTaintFlow
}
public void safeSchemaFactory(Socket sock) throws Exception {
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
Schema schema = factory.newSchema(new StreamSource(sock.getInputStream())); //safe
Schema schema = factory.newSchema(new StreamSource(sock.getInputStream())); // safe
}
public void partialConfiguredSchemaFactory1(Socket sock) throws Exception {
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
Schema schema = factory.newSchema(new StreamSource(sock.getInputStream())); //unsafe
Schema schema = factory.newSchema(new StreamSource(sock.getInputStream())); // $ hasTaintFlow
}
public void partialConfiguredSchemaFactory2(Socket sock) throws Exception {
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
Schema schema = factory.newSchema(new StreamSource(sock.getInputStream())); //unsafe
Schema schema = factory.newSchema(new StreamSource(sock.getInputStream())); // $ hasTaintFlow
}
public void misConfiguredSchemaFactory1(Socket sock) throws Exception {
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "ab");
Schema schema = factory.newSchema(new StreamSource(sock.getInputStream())); //unsafe
Schema schema = factory.newSchema(new StreamSource(sock.getInputStream())); // $ hasTaintFlow
}
public void misConfiguredSchemaFactory2(Socket sock) throws Exception {
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "cd");
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
Schema schema = factory.newSchema(new StreamSource(sock.getInputStream())); //unsafe
Schema schema = factory.newSchema(new StreamSource(sock.getInputStream())); // $ hasTaintFlow
}
}

View File

@@ -11,145 +11,145 @@ public class SimpleXMLTests {
public void persisterValidate1(Socket sock) throws Exception {
Persister persister = new Persister();
persister.validate(this.getClass(), sock.getInputStream());
persister.validate(this.getClass(), sock.getInputStream()); // $ hasTaintFlow
}
public void persisterValidate2(Socket sock) throws Exception {
Persister persister = new Persister();
persister.validate(this.getClass(), sock.getInputStream(), true);
persister.validate(this.getClass(), sock.getInputStream(), true); // $ hasTaintFlow
}
public void persisterValidate3(Socket sock) throws Exception {
Persister persister = new Persister();
persister.validate(this.getClass(), new InputStreamReader(sock.getInputStream()));
persister.validate(this.getClass(), new InputStreamReader(sock.getInputStream())); // $ hasTaintFlow
}
public void persisterValidate4(Socket sock) throws Exception {
Persister persister = new Persister();
byte[] b = new byte[]{};
byte[] b = new byte[] {};
sock.getInputStream().read(b);
persister.validate(this.getClass(), new String(b));
persister.validate(this.getClass(), new String(b)); // $ hasTaintFlow
}
public void persisterValidate5(Socket sock) throws Exception {
Persister persister = new Persister();
byte[] b = new byte[]{};
byte[] b = new byte[] {};
sock.getInputStream().read(b);
persister.validate(this.getClass(), new String(b), true);
persister.validate(this.getClass(), new String(b), true); // $ hasTaintFlow
}
public void persisterValidate6(Socket sock) throws Exception {
Persister persister = new Persister();
persister.validate(this.getClass(), new InputStreamReader(sock.getInputStream()), true);
persister.validate(this.getClass(), new InputStreamReader(sock.getInputStream()), true); // $ hasTaintFlow
}
public void persisterRead1(Socket sock) throws Exception {
Persister persister = new Persister();
persister.read(this.getClass(), sock.getInputStream());
persister.read(this.getClass(), sock.getInputStream()); // $ hasTaintFlow
}
public void persisterRead2(Socket sock) throws Exception {
Persister persister = new Persister();
persister.read(this.getClass(), sock.getInputStream(), true);
persister.read(this.getClass(), sock.getInputStream(), true); // $ hasTaintFlow
}
public void persisterRead3(Socket sock) throws Exception {
Persister persister = new Persister();
persister.read(this, sock.getInputStream());
persister.read(this, sock.getInputStream()); // $ hasTaintFlow
}
public void persisterRead4(Socket sock) throws Exception {
Persister persister = new Persister();
persister.read(this, sock.getInputStream(), true);
persister.read(this, sock.getInputStream(), true); // $ hasTaintFlow
}
public void persisterRead5(Socket sock) throws Exception {
Persister persister = new Persister();
persister.read(this.getClass(), new InputStreamReader(sock.getInputStream()));
persister.read(this.getClass(), new InputStreamReader(sock.getInputStream())); // $ hasTaintFlow
}
public void persisterRead6(Socket sock) throws Exception {
Persister persister = new Persister();
persister.read(this.getClass(), new InputStreamReader(sock.getInputStream()), true);
persister.read(this.getClass(), new InputStreamReader(sock.getInputStream()), true); // $ hasTaintFlow
}
public void persisterRead7(Socket sock) throws Exception {
Persister persister = new Persister();
persister.read(this, new InputStreamReader(sock.getInputStream()));
persister.read(this, new InputStreamReader(sock.getInputStream())); // $ hasTaintFlow
}
public void persisterRead8(Socket sock) throws Exception {
Persister persister = new Persister();
persister.read(this, new InputStreamReader(sock.getInputStream()), true);
persister.read(this, new InputStreamReader(sock.getInputStream()), true); // $ hasTaintFlow
}
public void persisterRead9(Socket sock) throws Exception {
Persister persister = new Persister();
byte[] b = new byte[]{};
byte[] b = new byte[] {};
sock.getInputStream().read(b);
persister.read(this.getClass(), new String(b));
persister.read(this.getClass(), new String(b)); // $ hasTaintFlow
}
public void persisterRead10(Socket sock) throws Exception {
Persister persister = new Persister();
byte[] b = new byte[]{};
byte[] b = new byte[] {};
sock.getInputStream().read(b);
persister.read(this.getClass(), new String(b), true);
persister.read(this.getClass(), new String(b), true); // $ hasTaintFlow
}
public void persisterRead11(Socket sock) throws Exception {
Persister persister = new Persister();
byte[] b = new byte[]{};
byte[] b = new byte[] {};
sock.getInputStream().read(b);
persister.read(this, new String(b));
persister.read(this, new String(b)); // $ hasTaintFlow
}
public void persisterRead12(Socket sock) throws Exception {
Persister persister = new Persister();
byte[] b = new byte[]{};
byte[] b = new byte[] {};
sock.getInputStream().read(b);
persister.read(this, new String(b), true);
persister.read(this, new String(b), true); // $ hasTaintFlow
}
public void nodeBuilderRead1(Socket sock) throws Exception {
NodeBuilder.read(sock.getInputStream());
NodeBuilder.read(sock.getInputStream()); // $ hasTaintFlow
}
public void nodeBuilderRead2(Socket sock) throws Exception {
NodeBuilder.read(new InputStreamReader(sock.getInputStream()));
NodeBuilder.read(new InputStreamReader(sock.getInputStream())); // $ hasTaintFlow
}
public void documentProviderProvide1(Socket sock) throws Exception {
DocumentProvider provider = new DocumentProvider();
provider.provide(sock.getInputStream());
provider.provide(sock.getInputStream()); // $ hasTaintFlow
}
public void documentProviderProvide2(Socket sock) throws Exception {
DocumentProvider provider = new DocumentProvider();
provider.provide(new InputStreamReader(sock.getInputStream()));
provider.provide(new InputStreamReader(sock.getInputStream())); // $ hasTaintFlow
}
public void streamProviderProvide1(Socket sock) throws Exception {
StreamProvider provider = new StreamProvider();
provider.provide(sock.getInputStream());
provider.provide(sock.getInputStream()); // $ hasTaintFlow
}
public void streamProviderProvide2(Socket sock) throws Exception {
StreamProvider provider = new StreamProvider();
provider.provide(new InputStreamReader(sock.getInputStream()));
provider.provide(new InputStreamReader(sock.getInputStream())); // $ hasTaintFlow
}
public void formatterFormat1(Socket sock) throws Exception {
Formatter formatter = new Formatter();
byte[] b = new byte[]{};
byte[] b = new byte[] {};
sock.getInputStream().read(b);
formatter.format(new String(b), null);
formatter.format(new String(b), null); // $ hasTaintFlow
}
public void formatterFormat2(Socket sock) throws Exception {
Formatter formatter = new Formatter();
byte[] b = new byte[]{};
byte[] b = new byte[] {};
sock.getInputStream().read(b);
formatter.format(new String(b));
formatter.format(new String(b)); // $ hasTaintFlow
}
}

View File

@@ -17,8 +17,8 @@ public class TransformerTests {
public void unconfiguredTransformerFactory(Socket sock) throws Exception {
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.transform(new StreamSource(sock.getInputStream()), null); //unsafe
tf.newTransformer(new StreamSource(sock.getInputStream())); //unsafe
transformer.transform(new StreamSource(sock.getInputStream()), null); // $ hasTaintFlow
tf.newTransformer(new StreamSource(sock.getInputStream())); // $ hasTaintFlow
}
public void safeTransformerFactory1(Socket sock) throws Exception {
@@ -26,8 +26,8 @@ public class TransformerTests {
tf.setAttribute("http://javax.xml.XMLConstants/property/accessExternalDTD", "");
tf.setAttribute("http://javax.xml.XMLConstants/property/accessExternalStylesheet", "");
Transformer transformer = tf.newTransformer();
transformer.transform(new StreamSource(sock.getInputStream()), null); //safe
tf.newTransformer(new StreamSource(sock.getInputStream())); //safe
transformer.transform(new StreamSource(sock.getInputStream()), null); // safe
tf.newTransformer(new StreamSource(sock.getInputStream())); // safe
}
public void safeTransformerFactory2(Socket sock) throws Exception {
@@ -35,49 +35,49 @@ public class TransformerTests {
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
Transformer transformer = tf.newTransformer();
transformer.transform(new StreamSource(sock.getInputStream()), null); //safe
tf.newTransformer(new StreamSource(sock.getInputStream())); //safe
transformer.transform(new StreamSource(sock.getInputStream()), null); // safe
tf.newTransformer(new StreamSource(sock.getInputStream())); // safe
}
public void safeTransformerFactory3(Socket sock) throws Exception {
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd",false);
SAXSource source = new SAXSource(reader, new InputSource(sock.getInputStream())); //safe
transformer.transform(source, null); //safe
tf.newTransformer(source); //safe
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
SAXSource source = new SAXSource(reader, new InputSource(sock.getInputStream())); // safe
transformer.transform(source, null); // safe
tf.newTransformer(source); // safe
}
public void safeTransformerFactory4(Socket sock) throws Exception {
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd",false);
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
SAXSource source = new SAXSource(new InputSource(sock.getInputStream()));
source.setXMLReader(reader);
transformer.transform(source, null); //safe
tf.newTransformer(source); //safe
transformer.transform(source, null); // safe
tf.newTransformer(source); // safe
}
public void partialConfiguredTransformerFactory1(Socket sock) throws Exception {
TransformerFactory tf = TransformerFactory.newInstance();
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
Transformer transformer = tf.newTransformer();
transformer.transform(new StreamSource(sock.getInputStream()), null); //unsafe
tf.newTransformer(new StreamSource(sock.getInputStream())); //unsafe
transformer.transform(new StreamSource(sock.getInputStream()), null); // $ hasTaintFlow
tf.newTransformer(new StreamSource(sock.getInputStream())); // $ hasTaintFlow
}
public void partialConfiguredTransformerFactory2(Socket sock) throws Exception {
TransformerFactory tf = TransformerFactory.newInstance();
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
Transformer transformer = tf.newTransformer();
transformer.transform(new StreamSource(sock.getInputStream()), null); //unsafe
tf.newTransformer(new StreamSource(sock.getInputStream())); //unsafe
transformer.transform(new StreamSource(sock.getInputStream()), null); // $ hasTaintFlow
tf.newTransformer(new StreamSource(sock.getInputStream())); // $ hasTaintFlow
}
public void misConfiguredTransformerFactory1(Socket sock) throws Exception {
@@ -85,8 +85,8 @@ public class TransformerTests {
Transformer transformer = tf.newTransformer();
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "ab");
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
transformer.transform(new StreamSource(sock.getInputStream()), null); //unsafe
tf.newTransformer(new StreamSource(sock.getInputStream())); //unsafe
transformer.transform(new StreamSource(sock.getInputStream()), null); // $ hasTaintFlow
tf.newTransformer(new StreamSource(sock.getInputStream())); // $ hasTaintFlow
}
public void misConfiguredTransformerFactory2(Socket sock) throws Exception {
@@ -94,50 +94,50 @@ public class TransformerTests {
Transformer transformer = tf.newTransformer();
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "cd");
transformer.transform(new StreamSource(sock.getInputStream()), null); //unsafe
tf.newTransformer(new StreamSource(sock.getInputStream())); //unsafe
transformer.transform(new StreamSource(sock.getInputStream()), null); // $ hasTaintFlow
tf.newTransformer(new StreamSource(sock.getInputStream())); // $ hasTaintFlow
}
public void unconfiguredSAXTransformerFactory(Socket sock) throws Exception {
SAXTransformerFactory sf = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
sf.newXMLFilter(new StreamSource(sock.getInputStream())); //unsafe
SAXTransformerFactory sf = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
sf.newXMLFilter(new StreamSource(sock.getInputStream())); // $ hasTaintFlow
}
public void safeSAXTransformerFactory(Socket sock) throws Exception {
SAXTransformerFactory sf = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
SAXTransformerFactory sf = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
sf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
sf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
sf.newXMLFilter(new StreamSource(sock.getInputStream())); //safe
sf.newXMLFilter(new StreamSource(sock.getInputStream())); // safe
}
public void partialConfiguredSAXTransformerFactory1(Socket sock) throws Exception {
SAXTransformerFactory sf = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
SAXTransformerFactory sf = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
sf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
sf.newXMLFilter(new StreamSource(sock.getInputStream())); //unsafe
sf.newXMLFilter(new StreamSource(sock.getInputStream())); // $ hasTaintFlow
}
public void partialConfiguredSAXTransformerFactory2(Socket sock) throws Exception {
SAXTransformerFactory sf = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
SAXTransformerFactory sf = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
sf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
sf.newXMLFilter(new StreamSource(sock.getInputStream())); //unsafe
sf.newXMLFilter(new StreamSource(sock.getInputStream())); // $ hasTaintFlow
}
public void misConfiguredSAXTransformerFactory1(Socket sock) throws Exception {
SAXTransformerFactory sf = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
SAXTransformerFactory sf = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
sf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "ab");
sf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
sf.newXMLFilter(new StreamSource(sock.getInputStream())); //unsafe
sf.newXMLFilter(new StreamSource(sock.getInputStream())); // $ hasTaintFlow
}
public void misConfiguredSAXTransformerFactory2(Socket sock) throws Exception {
SAXTransformerFactory sf = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
SAXTransformerFactory sf = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
sf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
sf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "cd");
sf.newXMLFilter(new StreamSource(sock.getInputStream())); //unsafe
sf.newXMLFilter(new StreamSource(sock.getInputStream())); // $ hasTaintFlow
}
public void taintedSAXSource(Socket sock) throws Exception {
SAXTransformerFactory sf = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
sf.newXMLFilter(new SAXSource(new InputSource(sock.getInputStream()))); //unsafe
SAXTransformerFactory sf = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
sf.newXMLFilter(new SAXSource(new InputSource(sock.getInputStream()))); // $ hasTaintFlow
}
}

View File

@@ -16,15 +16,16 @@ public class UnmarshallerTests {
spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
JAXBContext jc = JAXBContext.newInstance(Object.class);
Source xmlSource = new SAXSource(spf.newSAXParser().getXMLReader(), new InputSource(sock.getInputStream()));
Source xmlSource =
new SAXSource(spf.newSAXParser().getXMLReader(), new InputSource(sock.getInputStream()));
Unmarshaller um = jc.createUnmarshaller();
um.unmarshal(xmlSource); //safe
um.unmarshal(xmlSource); // safe
}
public void unsafeUnmarshal(Socket sock) throws Exception {
SAXParserFactory spf = SAXParserFactory.newInstance();
JAXBContext jc = JAXBContext.newInstance(Object.class);
Unmarshaller um = jc.createUnmarshaller();
um.unmarshal(sock.getInputStream()); //unsafe
um.unmarshal(sock.getInputStream()); // $ hasTaintFlow
}
}

View File

@@ -0,0 +1,41 @@
import java.io.BufferedReader;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class ValidatorTests {
@PostMapping(value = "bad")
public void bad2(HttpServletRequest request) throws Exception {
ServletInputStream servletInputStream = request.getInputStream();
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema schema = factory.newSchema();
Validator validator = schema.newValidator();
StreamSource source = new StreamSource(servletInputStream);
validator.validate(source); // $ hasTaintFlow
}
@PostMapping(value = "good")
public void good2(HttpServletRequest request, HttpServletResponse response) throws Exception {
BufferedReader br = request.getReader();
String str = "";
StringBuilder listString = new StringBuilder();
while ((str = br.readLine()) != null) {
listString.append(str).append("\n");
}
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema schema = factory.newSchema();
Validator validator = schema.newValidator();
validator.setProperty("http://javax.xml.XMLConstants/property/accessExternalDTD", "");
validator.setProperty("http://javax.xml.XMLConstants/property/accessExternalSchema", "");
StreamSource source = new StreamSource(listString.toString());
validator.validate(source);
}
}

View File

@@ -0,0 +1,32 @@
import java.beans.XMLDecoder;
import java.io.BufferedReader;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class XMLDecoderTests {
@PostMapping(value = "bad")
public void bad3(HttpServletRequest request) throws Exception {
ServletInputStream servletInputStream = request.getInputStream();
XMLDecoder xmlDecoder = new XMLDecoder(servletInputStream);
xmlDecoder.readObject(); // $ hasTaintFlow
}
@PostMapping(value = "good")
public void good3(HttpServletRequest request) throws Exception {
BufferedReader br = request.getReader();
String str = "";
StringBuilder listString = new StringBuilder();
while ((str = br.readLine()) != null) {
listString.append(str).append("\n");
}
// parseText falls back to a default SAXReader, which is safe
Document document = DocumentHelper.parseText(listString.toString()); // Safe
}
}

View File

@@ -13,23 +13,23 @@ public class XMLReaderTests {
public void unconfiguredReader(Socket sock) throws Exception {
XMLReader reader = XMLReaderFactory.createXMLReader();
reader.parse(new InputSource(sock.getInputStream())); //unsafe
reader.parse(new InputSource(sock.getInputStream())); // $ hasTaintFlow
}
public void safeReaderFromConfig1(Socket sock) throws Exception {
XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd",false);
reader.parse(new InputSource(sock.getInputStream())); //safe
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
reader.parse(new InputSource(sock.getInputStream())); // safe
}
public void safeReaderFromConfig2(Socket sock) throws Exception {
XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
reader.parse(new InputSource(sock.getInputStream())); //safe
reader.parse(new InputSource(sock.getInputStream())); // safe
}
public void safeReaderFromSAXParser(Socket sock) throws Exception {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
@@ -37,66 +37,66 @@ public class XMLReaderTests {
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
SAXParser parser = factory.newSAXParser();
XMLReader reader = parser.getXMLReader();
reader.parse(new InputSource(sock.getInputStream())); //safe
reader.parse(new InputSource(sock.getInputStream())); // safe
}
public void safeReaderFromSAXReader(Socket sock) throws Exception {
SAXReader reader = new SAXReader();
reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
XMLReader xmlReader = reader.getXMLReader();
xmlReader.parse(new InputSource(sock.getInputStream())); //safe
xmlReader.parse(new InputSource(sock.getInputStream())); // safe
}
public void partialConfiguredXMLReader1(Socket sock) throws Exception {
XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
reader.parse(new InputSource(sock.getInputStream())); //unsafe
reader.parse(new InputSource(sock.getInputStream())); // $ hasTaintFlow
}
public void partialConfiguredXMLReader2(Socket sock) throws Exception {
XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd",false);
reader.parse(new InputSource(sock.getInputStream())); //unsafe
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
reader.parse(new InputSource(sock.getInputStream())); // $ hasTaintFlow
}
public void partilaConfiguredXMLReader3(Socket sock) throws Exception {
XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd",false);
reader.parse(new InputSource(sock.getInputStream())); //unsafe
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
reader.parse(new InputSource(sock.getInputStream())); // $ hasTaintFlow
}
public void misConfiguredXMLReader1(Socket sock) throws Exception {
XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setFeature("http://xml.org/sax/features/external-general-entities", true);
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd",false);
reader.parse(new InputSource(sock.getInputStream())); //unsafe
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
reader.parse(new InputSource(sock.getInputStream())); // $ hasTaintFlow
}
public void misConfiguredXMLReader2(Socket sock) throws Exception {
XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", true);
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd",false);
reader.parse(new InputSource(sock.getInputStream())); //unsafe
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
reader.parse(new InputSource(sock.getInputStream())); // $ hasTaintFlow
}
public void misConfiguredXMLReader3(Socket sock) throws Exception {
XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", true);
reader.parse(new InputSource(sock.getInputStream())); //unsafe
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", true);
reader.parse(new InputSource(sock.getInputStream())); // $ hasTaintFlow
}
public void misConfiguredXMLReader4(Socket sock) throws Exception {
XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false);
reader.parse(new InputSource(sock.getInputStream())); //unsafe
reader.parse(new InputSource(sock.getInputStream())); // $ hasTaintFlow
}
}

View File

@@ -24,7 +24,7 @@ public class XPathExpressionTests {
XPathFactory xFactory = XPathFactory.newInstance();
XPath path = xFactory.newXPath();
XPathExpression expr = path.compile("");
expr.evaluate(new InputSource(sock.getInputStream())); // unsafe
expr.evaluate(new InputSource(sock.getInputStream())); // $ hasTaintFlow
}
public void safeXPathEvaluateTest(Socket sock) throws Exception {
@@ -33,12 +33,12 @@ public class XPathExpressionTests {
DocumentBuilder builder = factory.newDocumentBuilder();
XPathFactory xFactory = XPathFactory.newInstance();
XPath path = xFactory.newXPath();
path.evaluate("", builder.parse(sock.getInputStream()));
path.evaluate("", builder.parse(sock.getInputStream())); // safe
}
public void unsafeXPathEvaluateTest(Socket sock) throws Exception {
XPathFactory xFactory = XPathFactory.newInstance();
XPath path = xFactory.newXPath();
path.evaluate("", new InputSource(sock.getInputStream())); // unsafe
path.evaluate("", new InputSource(sock.getInputStream())); // $ hasTaintFlow
}
}

View File

@@ -1,355 +0,0 @@
edges
| DocumentBuilderTests.java:93:21:93:73 | new SAXSource(...) : SAXSource | DocumentBuilderTests.java:94:16:94:21 | source : SAXSource |
| DocumentBuilderTests.java:93:35:93:72 | new InputSource(...) : InputSource | DocumentBuilderTests.java:93:21:93:73 | new SAXSource(...) : SAXSource |
| DocumentBuilderTests.java:93:51:93:71 | getInputStream(...) : InputStream | DocumentBuilderTests.java:93:35:93:72 | new InputSource(...) : InputSource |
| DocumentBuilderTests.java:94:16:94:21 | source : SAXSource | DocumentBuilderTests.java:94:16:94:38 | getInputSource(...) |
| DocumentBuilderTests.java:100:24:100:62 | new StreamSource(...) : StreamSource | DocumentBuilderTests.java:101:46:101:51 | source : StreamSource |
| DocumentBuilderTests.java:100:24:100:62 | new StreamSource(...) : StreamSource | DocumentBuilderTests.java:102:16:102:21 | source : StreamSource |
| DocumentBuilderTests.java:100:41:100:61 | getInputStream(...) : InputStream | DocumentBuilderTests.java:100:24:100:62 | new StreamSource(...) : StreamSource |
| DocumentBuilderTests.java:101:46:101:51 | source : StreamSource | DocumentBuilderTests.java:101:16:101:52 | sourceToInputSource(...) |
| DocumentBuilderTests.java:102:16:102:21 | source : StreamSource | DocumentBuilderTests.java:102:16:102:38 | getInputStream(...) |
| SAXSourceTests.java:17:24:17:84 | new SAXSource(...) : SAXSource | SAXSourceTests.java:20:18:20:23 | source |
| SAXSourceTests.java:17:46:17:83 | new InputSource(...) : InputSource | SAXSourceTests.java:17:24:17:84 | new SAXSource(...) : SAXSource |
| SAXSourceTests.java:17:62:17:82 | getInputStream(...) : InputStream | SAXSourceTests.java:17:46:17:83 | new InputSource(...) : InputSource |
| SchemaTests.java:12:56:12:76 | getInputStream(...) : InputStream | SchemaTests.java:12:39:12:77 | new StreamSource(...) |
| SchemaTests.java:25:56:25:76 | getInputStream(...) : InputStream | SchemaTests.java:25:39:25:77 | new StreamSource(...) |
| SchemaTests.java:31:56:31:76 | getInputStream(...) : InputStream | SchemaTests.java:31:39:31:77 | new StreamSource(...) |
| SchemaTests.java:38:56:38:76 | getInputStream(...) : InputStream | SchemaTests.java:38:39:38:77 | new StreamSource(...) |
| SchemaTests.java:45:56:45:76 | getInputStream(...) : InputStream | SchemaTests.java:45:39:45:77 | new StreamSource(...) |
| SimpleXMLTests.java:24:63:24:83 | getInputStream(...) : InputStream | SimpleXMLTests.java:24:41:24:84 | new InputStreamReader(...) |
| SimpleXMLTests.java:30:5:30:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:30:32:30:32 | b [post update] : byte[] |
| SimpleXMLTests.java:30:32:30:32 | b [post update] : byte[] | SimpleXMLTests.java:31:52:31:52 | b : byte[] |
| SimpleXMLTests.java:31:52:31:52 | b : byte[] | SimpleXMLTests.java:31:41:31:53 | new String(...) |
| SimpleXMLTests.java:37:5:37:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:37:32:37:32 | b [post update] : byte[] |
| SimpleXMLTests.java:37:32:37:32 | b [post update] : byte[] | SimpleXMLTests.java:38:52:38:52 | b : byte[] |
| SimpleXMLTests.java:38:52:38:52 | b : byte[] | SimpleXMLTests.java:38:41:38:53 | new String(...) |
| SimpleXMLTests.java:43:63:43:83 | getInputStream(...) : InputStream | SimpleXMLTests.java:43:41:43:84 | new InputStreamReader(...) |
| SimpleXMLTests.java:68:59:68:79 | getInputStream(...) : InputStream | SimpleXMLTests.java:68:37:68:80 | new InputStreamReader(...) |
| SimpleXMLTests.java:73:59:73:79 | getInputStream(...) : InputStream | SimpleXMLTests.java:73:37:73:80 | new InputStreamReader(...) |
| SimpleXMLTests.java:78:48:78:68 | getInputStream(...) : InputStream | SimpleXMLTests.java:78:26:78:69 | new InputStreamReader(...) |
| SimpleXMLTests.java:83:48:83:68 | getInputStream(...) : InputStream | SimpleXMLTests.java:83:26:83:69 | new InputStreamReader(...) |
| SimpleXMLTests.java:89:5:89:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:89:32:89:32 | b [post update] : byte[] |
| SimpleXMLTests.java:89:32:89:32 | b [post update] : byte[] | SimpleXMLTests.java:90:48:90:48 | b : byte[] |
| SimpleXMLTests.java:90:48:90:48 | b : byte[] | SimpleXMLTests.java:90:37:90:49 | new String(...) |
| SimpleXMLTests.java:96:5:96:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:96:32:96:32 | b [post update] : byte[] |
| SimpleXMLTests.java:96:32:96:32 | b [post update] : byte[] | SimpleXMLTests.java:97:48:97:48 | b : byte[] |
| SimpleXMLTests.java:97:48:97:48 | b : byte[] | SimpleXMLTests.java:97:37:97:49 | new String(...) |
| SimpleXMLTests.java:103:5:103:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:103:32:103:32 | b [post update] : byte[] |
| SimpleXMLTests.java:103:32:103:32 | b [post update] : byte[] | SimpleXMLTests.java:104:37:104:37 | b : byte[] |
| SimpleXMLTests.java:104:37:104:37 | b : byte[] | SimpleXMLTests.java:104:26:104:38 | new String(...) |
| SimpleXMLTests.java:110:5:110:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:110:32:110:32 | b [post update] : byte[] |
| SimpleXMLTests.java:110:32:110:32 | b [post update] : byte[] | SimpleXMLTests.java:111:37:111:37 | b : byte[] |
| SimpleXMLTests.java:111:37:111:37 | b : byte[] | SimpleXMLTests.java:111:26:111:38 | new String(...) |
| SimpleXMLTests.java:119:44:119:64 | getInputStream(...) : InputStream | SimpleXMLTests.java:119:22:119:65 | new InputStreamReader(...) |
| SimpleXMLTests.java:129:44:129:64 | getInputStream(...) : InputStream | SimpleXMLTests.java:129:22:129:65 | new InputStreamReader(...) |
| SimpleXMLTests.java:139:44:139:64 | getInputStream(...) : InputStream | SimpleXMLTests.java:139:22:139:65 | new InputStreamReader(...) |
| SimpleXMLTests.java:145:5:145:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:145:32:145:32 | b [post update] : byte[] |
| SimpleXMLTests.java:145:32:145:32 | b [post update] : byte[] | SimpleXMLTests.java:146:33:146:33 | b : byte[] |
| SimpleXMLTests.java:146:33:146:33 | b : byte[] | SimpleXMLTests.java:146:22:146:34 | new String(...) |
| SimpleXMLTests.java:152:5:152:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:152:32:152:32 | b [post update] : byte[] |
| SimpleXMLTests.java:152:32:152:32 | b [post update] : byte[] | SimpleXMLTests.java:153:33:153:33 | b : byte[] |
| SimpleXMLTests.java:153:33:153:33 | b : byte[] | SimpleXMLTests.java:153:22:153:34 | new String(...) |
| TransformerTests.java:20:44:20:64 | getInputStream(...) : InputStream | TransformerTests.java:20:27:20:65 | new StreamSource(...) |
| TransformerTests.java:21:40:21:60 | getInputStream(...) : InputStream | TransformerTests.java:21:23:21:61 | new StreamSource(...) |
| TransformerTests.java:71:44:71:64 | getInputStream(...) : InputStream | TransformerTests.java:71:27:71:65 | new StreamSource(...) |
| TransformerTests.java:72:40:72:60 | getInputStream(...) : InputStream | TransformerTests.java:72:23:72:61 | new StreamSource(...) |
| TransformerTests.java:79:44:79:64 | getInputStream(...) : InputStream | TransformerTests.java:79:27:79:65 | new StreamSource(...) |
| TransformerTests.java:80:40:80:60 | getInputStream(...) : InputStream | TransformerTests.java:80:23:80:61 | new StreamSource(...) |
| TransformerTests.java:88:44:88:64 | getInputStream(...) : InputStream | TransformerTests.java:88:27:88:65 | new StreamSource(...) |
| TransformerTests.java:89:40:89:60 | getInputStream(...) : InputStream | TransformerTests.java:89:23:89:61 | new StreamSource(...) |
| TransformerTests.java:97:44:97:64 | getInputStream(...) : InputStream | TransformerTests.java:97:27:97:65 | new StreamSource(...) |
| TransformerTests.java:98:40:98:60 | getInputStream(...) : InputStream | TransformerTests.java:98:23:98:61 | new StreamSource(...) |
| TransformerTests.java:103:38:103:58 | getInputStream(...) : InputStream | TransformerTests.java:103:21:103:59 | new StreamSource(...) |
| TransformerTests.java:116:38:116:58 | getInputStream(...) : InputStream | TransformerTests.java:116:21:116:59 | new StreamSource(...) |
| TransformerTests.java:122:38:122:58 | getInputStream(...) : InputStream | TransformerTests.java:122:21:122:59 | new StreamSource(...) |
| TransformerTests.java:129:38:129:58 | getInputStream(...) : InputStream | TransformerTests.java:129:21:129:59 | new StreamSource(...) |
| TransformerTests.java:136:38:136:58 | getInputStream(...) : InputStream | TransformerTests.java:136:21:136:59 | new StreamSource(...) |
| TransformerTests.java:141:32:141:69 | new InputSource(...) : InputSource | TransformerTests.java:141:18:141:70 | new SAXSource(...) |
| TransformerTests.java:141:48:141:68 | getInputStream(...) : InputStream | TransformerTests.java:141:32:141:69 | new InputSource(...) : InputSource |
| XMLReaderTests.java:16:34:16:54 | getInputStream(...) : InputStream | XMLReaderTests.java:16:18:16:55 | new InputSource(...) |
| XMLReaderTests.java:56:34:56:54 | getInputStream(...) : InputStream | XMLReaderTests.java:56:18:56:55 | new InputSource(...) |
| XMLReaderTests.java:63:34:63:54 | getInputStream(...) : InputStream | XMLReaderTests.java:63:18:63:55 | new InputSource(...) |
| XMLReaderTests.java:70:34:70:54 | getInputStream(...) : InputStream | XMLReaderTests.java:70:18:70:55 | new InputSource(...) |
| XMLReaderTests.java:78:34:78:54 | getInputStream(...) : InputStream | XMLReaderTests.java:78:18:78:55 | new InputSource(...) |
| XMLReaderTests.java:86:34:86:54 | getInputStream(...) : InputStream | XMLReaderTests.java:86:18:86:55 | new InputSource(...) |
| XMLReaderTests.java:94:34:94:54 | getInputStream(...) : InputStream | XMLReaderTests.java:94:18:94:55 | new InputSource(...) |
| XMLReaderTests.java:100:34:100:54 | getInputStream(...) : InputStream | XMLReaderTests.java:100:18:100:55 | new InputSource(...) |
| XPathExpressionTests.java:27:35:27:55 | getInputStream(...) : InputStream | XPathExpressionTests.java:27:19:27:56 | new InputSource(...) |
| XPathExpressionTests.java:42:39:42:59 | getInputStream(...) : InputStream | XPathExpressionTests.java:42:23:42:60 | new InputSource(...) |
nodes
| DocumentBuilderTests.java:14:19:14:39 | getInputStream(...) | semmle.label | getInputStream(...) |
| DocumentBuilderTests.java:28:19:28:39 | getInputStream(...) | semmle.label | getInputStream(...) |
| DocumentBuilderTests.java:35:19:35:39 | getInputStream(...) | semmle.label | getInputStream(...) |
| DocumentBuilderTests.java:42:19:42:39 | getInputStream(...) | semmle.label | getInputStream(...) |
| DocumentBuilderTests.java:49:19:49:39 | getInputStream(...) | semmle.label | getInputStream(...) |
| DocumentBuilderTests.java:64:19:64:39 | getInputStream(...) | semmle.label | getInputStream(...) |
| DocumentBuilderTests.java:71:19:71:39 | getInputStream(...) | semmle.label | getInputStream(...) |
| DocumentBuilderTests.java:79:19:79:39 | getInputStream(...) | semmle.label | getInputStream(...) |
| DocumentBuilderTests.java:87:19:87:39 | getInputStream(...) | semmle.label | getInputStream(...) |
| DocumentBuilderTests.java:93:21:93:73 | new SAXSource(...) : SAXSource | semmle.label | new SAXSource(...) : SAXSource |
| DocumentBuilderTests.java:93:35:93:72 | new InputSource(...) : InputSource | semmle.label | new InputSource(...) : InputSource |
| DocumentBuilderTests.java:93:51:93:71 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| DocumentBuilderTests.java:94:16:94:21 | source : SAXSource | semmle.label | source : SAXSource |
| DocumentBuilderTests.java:94:16:94:38 | getInputSource(...) | semmle.label | getInputSource(...) |
| DocumentBuilderTests.java:100:24:100:62 | new StreamSource(...) : StreamSource | semmle.label | new StreamSource(...) : StreamSource |
| DocumentBuilderTests.java:100:41:100:61 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| DocumentBuilderTests.java:101:16:101:52 | sourceToInputSource(...) | semmle.label | sourceToInputSource(...) |
| DocumentBuilderTests.java:101:46:101:51 | source : StreamSource | semmle.label | source : StreamSource |
| DocumentBuilderTests.java:102:16:102:21 | source : StreamSource | semmle.label | source : StreamSource |
| DocumentBuilderTests.java:102:16:102:38 | getInputStream(...) | semmle.label | getInputStream(...) |
| SAXBuilderTests.java:8:19:8:39 | getInputStream(...) | semmle.label | getInputStream(...) |
| SAXBuilderTests.java:20:19:20:39 | getInputStream(...) | semmle.label | getInputStream(...) |
| SAXParserTests.java:13:18:13:38 | getInputStream(...) | semmle.label | getInputStream(...) |
| SAXParserTests.java:30:18:30:38 | getInputStream(...) | semmle.label | getInputStream(...) |
| SAXParserTests.java:38:18:38:38 | getInputStream(...) | semmle.label | getInputStream(...) |
| SAXParserTests.java:46:18:46:38 | getInputStream(...) | semmle.label | getInputStream(...) |
| SAXParserTests.java:55:18:55:38 | getInputStream(...) | semmle.label | getInputStream(...) |
| SAXParserTests.java:64:18:64:38 | getInputStream(...) | semmle.label | getInputStream(...) |
| SAXParserTests.java:73:18:73:38 | getInputStream(...) | semmle.label | getInputStream(...) |
| SAXReaderTests.java:8:17:8:37 | getInputStream(...) | semmle.label | getInputStream(...) |
| SAXReaderTests.java:23:17:23:37 | getInputStream(...) | semmle.label | getInputStream(...) |
| SAXReaderTests.java:30:17:30:37 | getInputStream(...) | semmle.label | getInputStream(...) |
| SAXReaderTests.java:37:17:37:37 | getInputStream(...) | semmle.label | getInputStream(...) |
| SAXReaderTests.java:45:17:45:37 | getInputStream(...) | semmle.label | getInputStream(...) |
| SAXReaderTests.java:53:17:53:37 | getInputStream(...) | semmle.label | getInputStream(...) |
| SAXReaderTests.java:61:17:61:37 | getInputStream(...) | semmle.label | getInputStream(...) |
| SAXSourceTests.java:17:24:17:84 | new SAXSource(...) : SAXSource | semmle.label | new SAXSource(...) : SAXSource |
| SAXSourceTests.java:17:46:17:83 | new InputSource(...) : InputSource | semmle.label | new InputSource(...) : InputSource |
| SAXSourceTests.java:17:62:17:82 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SAXSourceTests.java:20:18:20:23 | source | semmle.label | source |
| SchemaTests.java:12:39:12:77 | new StreamSource(...) | semmle.label | new StreamSource(...) |
| SchemaTests.java:12:56:12:76 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SchemaTests.java:25:39:25:77 | new StreamSource(...) | semmle.label | new StreamSource(...) |
| SchemaTests.java:25:56:25:76 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SchemaTests.java:31:39:31:77 | new StreamSource(...) | semmle.label | new StreamSource(...) |
| SchemaTests.java:31:56:31:76 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SchemaTests.java:38:39:38:77 | new StreamSource(...) | semmle.label | new StreamSource(...) |
| SchemaTests.java:38:56:38:76 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SchemaTests.java:45:39:45:77 | new StreamSource(...) | semmle.label | new StreamSource(...) |
| SchemaTests.java:45:56:45:76 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SimpleXMLTests.java:14:41:14:61 | getInputStream(...) | semmle.label | getInputStream(...) |
| SimpleXMLTests.java:19:41:19:61 | getInputStream(...) | semmle.label | getInputStream(...) |
| SimpleXMLTests.java:24:41:24:84 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) |
| SimpleXMLTests.java:24:63:24:83 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SimpleXMLTests.java:30:5:30:25 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SimpleXMLTests.java:30:32:30:32 | b [post update] : byte[] | semmle.label | b [post update] : byte[] |
| SimpleXMLTests.java:31:41:31:53 | new String(...) | semmle.label | new String(...) |
| SimpleXMLTests.java:31:52:31:52 | b : byte[] | semmle.label | b : byte[] |
| SimpleXMLTests.java:37:5:37:25 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SimpleXMLTests.java:37:32:37:32 | b [post update] : byte[] | semmle.label | b [post update] : byte[] |
| SimpleXMLTests.java:38:41:38:53 | new String(...) | semmle.label | new String(...) |
| SimpleXMLTests.java:38:52:38:52 | b : byte[] | semmle.label | b : byte[] |
| SimpleXMLTests.java:43:41:43:84 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) |
| SimpleXMLTests.java:43:63:43:83 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SimpleXMLTests.java:48:37:48:57 | getInputStream(...) | semmle.label | getInputStream(...) |
| SimpleXMLTests.java:53:37:53:57 | getInputStream(...) | semmle.label | getInputStream(...) |
| SimpleXMLTests.java:58:26:58:46 | getInputStream(...) | semmle.label | getInputStream(...) |
| SimpleXMLTests.java:63:26:63:46 | getInputStream(...) | semmle.label | getInputStream(...) |
| SimpleXMLTests.java:68:37:68:80 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) |
| SimpleXMLTests.java:68:59:68:79 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SimpleXMLTests.java:73:37:73:80 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) |
| SimpleXMLTests.java:73:59:73:79 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SimpleXMLTests.java:78:26:78:69 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) |
| SimpleXMLTests.java:78:48:78:68 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SimpleXMLTests.java:83:26:83:69 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) |
| SimpleXMLTests.java:83:48:83:68 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SimpleXMLTests.java:89:5:89:25 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SimpleXMLTests.java:89:32:89:32 | b [post update] : byte[] | semmle.label | b [post update] : byte[] |
| SimpleXMLTests.java:90:37:90:49 | new String(...) | semmle.label | new String(...) |
| SimpleXMLTests.java:90:48:90:48 | b : byte[] | semmle.label | b : byte[] |
| SimpleXMLTests.java:96:5:96:25 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SimpleXMLTests.java:96:32:96:32 | b [post update] : byte[] | semmle.label | b [post update] : byte[] |
| SimpleXMLTests.java:97:37:97:49 | new String(...) | semmle.label | new String(...) |
| SimpleXMLTests.java:97:48:97:48 | b : byte[] | semmle.label | b : byte[] |
| SimpleXMLTests.java:103:5:103:25 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SimpleXMLTests.java:103:32:103:32 | b [post update] : byte[] | semmle.label | b [post update] : byte[] |
| SimpleXMLTests.java:104:26:104:38 | new String(...) | semmle.label | new String(...) |
| SimpleXMLTests.java:104:37:104:37 | b : byte[] | semmle.label | b : byte[] |
| SimpleXMLTests.java:110:5:110:25 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SimpleXMLTests.java:110:32:110:32 | b [post update] : byte[] | semmle.label | b [post update] : byte[] |
| SimpleXMLTests.java:111:26:111:38 | new String(...) | semmle.label | new String(...) |
| SimpleXMLTests.java:111:37:111:37 | b : byte[] | semmle.label | b : byte[] |
| SimpleXMLTests.java:115:22:115:42 | getInputStream(...) | semmle.label | getInputStream(...) |
| SimpleXMLTests.java:119:22:119:65 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) |
| SimpleXMLTests.java:119:44:119:64 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SimpleXMLTests.java:124:22:124:42 | getInputStream(...) | semmle.label | getInputStream(...) |
| SimpleXMLTests.java:129:22:129:65 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) |
| SimpleXMLTests.java:129:44:129:64 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SimpleXMLTests.java:134:22:134:42 | getInputStream(...) | semmle.label | getInputStream(...) |
| SimpleXMLTests.java:139:22:139:65 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) |
| SimpleXMLTests.java:139:44:139:64 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SimpleXMLTests.java:145:5:145:25 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SimpleXMLTests.java:145:32:145:32 | b [post update] : byte[] | semmle.label | b [post update] : byte[] |
| SimpleXMLTests.java:146:22:146:34 | new String(...) | semmle.label | new String(...) |
| SimpleXMLTests.java:146:33:146:33 | b : byte[] | semmle.label | b : byte[] |
| SimpleXMLTests.java:152:5:152:25 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SimpleXMLTests.java:152:32:152:32 | b [post update] : byte[] | semmle.label | b [post update] : byte[] |
| SimpleXMLTests.java:153:22:153:34 | new String(...) | semmle.label | new String(...) |
| SimpleXMLTests.java:153:33:153:33 | b : byte[] | semmle.label | b : byte[] |
| TransformerTests.java:20:27:20:65 | new StreamSource(...) | semmle.label | new StreamSource(...) |
| TransformerTests.java:20:44:20:64 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| TransformerTests.java:21:23:21:61 | new StreamSource(...) | semmle.label | new StreamSource(...) |
| TransformerTests.java:21:40:21:60 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| TransformerTests.java:71:27:71:65 | new StreamSource(...) | semmle.label | new StreamSource(...) |
| TransformerTests.java:71:44:71:64 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| TransformerTests.java:72:23:72:61 | new StreamSource(...) | semmle.label | new StreamSource(...) |
| TransformerTests.java:72:40:72:60 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| TransformerTests.java:79:27:79:65 | new StreamSource(...) | semmle.label | new StreamSource(...) |
| TransformerTests.java:79:44:79:64 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| TransformerTests.java:80:23:80:61 | new StreamSource(...) | semmle.label | new StreamSource(...) |
| TransformerTests.java:80:40:80:60 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| TransformerTests.java:88:27:88:65 | new StreamSource(...) | semmle.label | new StreamSource(...) |
| TransformerTests.java:88:44:88:64 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| TransformerTests.java:89:23:89:61 | new StreamSource(...) | semmle.label | new StreamSource(...) |
| TransformerTests.java:89:40:89:60 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| TransformerTests.java:97:27:97:65 | new StreamSource(...) | semmle.label | new StreamSource(...) |
| TransformerTests.java:97:44:97:64 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| TransformerTests.java:98:23:98:61 | new StreamSource(...) | semmle.label | new StreamSource(...) |
| TransformerTests.java:98:40:98:60 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| TransformerTests.java:103:21:103:59 | new StreamSource(...) | semmle.label | new StreamSource(...) |
| TransformerTests.java:103:38:103:58 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| TransformerTests.java:116:21:116:59 | new StreamSource(...) | semmle.label | new StreamSource(...) |
| TransformerTests.java:116:38:116:58 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| TransformerTests.java:122:21:122:59 | new StreamSource(...) | semmle.label | new StreamSource(...) |
| TransformerTests.java:122:38:122:58 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| TransformerTests.java:129:21:129:59 | new StreamSource(...) | semmle.label | new StreamSource(...) |
| TransformerTests.java:129:38:129:58 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| TransformerTests.java:136:21:136:59 | new StreamSource(...) | semmle.label | new StreamSource(...) |
| TransformerTests.java:136:38:136:58 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| TransformerTests.java:141:18:141:70 | new SAXSource(...) | semmle.label | new SAXSource(...) |
| TransformerTests.java:141:32:141:69 | new InputSource(...) : InputSource | semmle.label | new InputSource(...) : InputSource |
| TransformerTests.java:141:48:141:68 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| UnmarshallerTests.java:28:18:28:38 | getInputStream(...) | semmle.label | getInputStream(...) |
| XMLReaderTests.java:16:18:16:55 | new InputSource(...) | semmle.label | new InputSource(...) |
| XMLReaderTests.java:16:34:16:54 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| XMLReaderTests.java:56:18:56:55 | new InputSource(...) | semmle.label | new InputSource(...) |
| XMLReaderTests.java:56:34:56:54 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| XMLReaderTests.java:63:18:63:55 | new InputSource(...) | semmle.label | new InputSource(...) |
| XMLReaderTests.java:63:34:63:54 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| XMLReaderTests.java:70:18:70:55 | new InputSource(...) | semmle.label | new InputSource(...) |
| XMLReaderTests.java:70:34:70:54 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| XMLReaderTests.java:78:18:78:55 | new InputSource(...) | semmle.label | new InputSource(...) |
| XMLReaderTests.java:78:34:78:54 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| XMLReaderTests.java:86:18:86:55 | new InputSource(...) | semmle.label | new InputSource(...) |
| XMLReaderTests.java:86:34:86:54 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| XMLReaderTests.java:94:18:94:55 | new InputSource(...) | semmle.label | new InputSource(...) |
| XMLReaderTests.java:94:34:94:54 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| XMLReaderTests.java:100:18:100:55 | new InputSource(...) | semmle.label | new InputSource(...) |
| XMLReaderTests.java:100:34:100:54 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| XPathExpressionTests.java:27:19:27:56 | new InputSource(...) | semmle.label | new InputSource(...) |
| XPathExpressionTests.java:27:35:27:55 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| XPathExpressionTests.java:42:23:42:60 | new InputSource(...) | semmle.label | new InputSource(...) |
| XPathExpressionTests.java:42:39:42:59 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | semmle.label | getInputStream(...) |
| XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | semmle.label | getInputStream(...) |
| XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | semmle.label | getInputStream(...) |
| XmlInputFactoryTests.java:25:34:25:54 | getInputStream(...) | semmle.label | getInputStream(...) |
| XmlInputFactoryTests.java:31:35:31:55 | getInputStream(...) | semmle.label | getInputStream(...) |
| XmlInputFactoryTests.java:32:34:32:54 | getInputStream(...) | semmle.label | getInputStream(...) |
| XmlInputFactoryTests.java:39:35:39:55 | getInputStream(...) | semmle.label | getInputStream(...) |
| XmlInputFactoryTests.java:40:34:40:54 | getInputStream(...) | semmle.label | getInputStream(...) |
| XmlInputFactoryTests.java:47:35:47:55 | getInputStream(...) | semmle.label | getInputStream(...) |
| XmlInputFactoryTests.java:48:34:48:54 | getInputStream(...) | semmle.label | getInputStream(...) |
| XmlInputFactoryTests.java:55:35:55:55 | getInputStream(...) | semmle.label | getInputStream(...) |
| XmlInputFactoryTests.java:56:34:56:54 | getInputStream(...) | semmle.label | getInputStream(...) |
subpaths
#select
| DocumentBuilderTests.java:14:19:14:39 | getInputStream(...) | DocumentBuilderTests.java:14:19:14:39 | getInputStream(...) | DocumentBuilderTests.java:14:19:14:39 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | DocumentBuilderTests.java:14:19:14:39 | getInputStream(...) | user-provided value |
| DocumentBuilderTests.java:28:19:28:39 | getInputStream(...) | DocumentBuilderTests.java:28:19:28:39 | getInputStream(...) | DocumentBuilderTests.java:28:19:28:39 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | DocumentBuilderTests.java:28:19:28:39 | getInputStream(...) | user-provided value |
| DocumentBuilderTests.java:35:19:35:39 | getInputStream(...) | DocumentBuilderTests.java:35:19:35:39 | getInputStream(...) | DocumentBuilderTests.java:35:19:35:39 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | DocumentBuilderTests.java:35:19:35:39 | getInputStream(...) | user-provided value |
| DocumentBuilderTests.java:42:19:42:39 | getInputStream(...) | DocumentBuilderTests.java:42:19:42:39 | getInputStream(...) | DocumentBuilderTests.java:42:19:42:39 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | DocumentBuilderTests.java:42:19:42:39 | getInputStream(...) | user-provided value |
| DocumentBuilderTests.java:49:19:49:39 | getInputStream(...) | DocumentBuilderTests.java:49:19:49:39 | getInputStream(...) | DocumentBuilderTests.java:49:19:49:39 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | DocumentBuilderTests.java:49:19:49:39 | getInputStream(...) | user-provided value |
| DocumentBuilderTests.java:64:19:64:39 | getInputStream(...) | DocumentBuilderTests.java:64:19:64:39 | getInputStream(...) | DocumentBuilderTests.java:64:19:64:39 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | DocumentBuilderTests.java:64:19:64:39 | getInputStream(...) | user-provided value |
| DocumentBuilderTests.java:71:19:71:39 | getInputStream(...) | DocumentBuilderTests.java:71:19:71:39 | getInputStream(...) | DocumentBuilderTests.java:71:19:71:39 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | DocumentBuilderTests.java:71:19:71:39 | getInputStream(...) | user-provided value |
| DocumentBuilderTests.java:79:19:79:39 | getInputStream(...) | DocumentBuilderTests.java:79:19:79:39 | getInputStream(...) | DocumentBuilderTests.java:79:19:79:39 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | DocumentBuilderTests.java:79:19:79:39 | getInputStream(...) | user-provided value |
| DocumentBuilderTests.java:87:19:87:39 | getInputStream(...) | DocumentBuilderTests.java:87:19:87:39 | getInputStream(...) | DocumentBuilderTests.java:87:19:87:39 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | DocumentBuilderTests.java:87:19:87:39 | getInputStream(...) | user-provided value |
| DocumentBuilderTests.java:94:16:94:38 | getInputSource(...) | DocumentBuilderTests.java:93:51:93:71 | getInputStream(...) : InputStream | DocumentBuilderTests.java:94:16:94:38 | getInputSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | DocumentBuilderTests.java:93:51:93:71 | getInputStream(...) | user-provided value |
| DocumentBuilderTests.java:101:16:101:52 | sourceToInputSource(...) | DocumentBuilderTests.java:100:41:100:61 | getInputStream(...) : InputStream | DocumentBuilderTests.java:101:16:101:52 | sourceToInputSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | DocumentBuilderTests.java:100:41:100:61 | getInputStream(...) | user-provided value |
| DocumentBuilderTests.java:102:16:102:38 | getInputStream(...) | DocumentBuilderTests.java:100:41:100:61 | getInputStream(...) : InputStream | DocumentBuilderTests.java:102:16:102:38 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | DocumentBuilderTests.java:100:41:100:61 | getInputStream(...) | user-provided value |
| SAXBuilderTests.java:8:19:8:39 | getInputStream(...) | SAXBuilderTests.java:8:19:8:39 | getInputStream(...) | SAXBuilderTests.java:8:19:8:39 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SAXBuilderTests.java:8:19:8:39 | getInputStream(...) | user-provided value |
| SAXBuilderTests.java:20:19:20:39 | getInputStream(...) | SAXBuilderTests.java:20:19:20:39 | getInputStream(...) | SAXBuilderTests.java:20:19:20:39 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SAXBuilderTests.java:20:19:20:39 | getInputStream(...) | user-provided value |
| SAXParserTests.java:13:18:13:38 | getInputStream(...) | SAXParserTests.java:13:18:13:38 | getInputStream(...) | SAXParserTests.java:13:18:13:38 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SAXParserTests.java:13:18:13:38 | getInputStream(...) | user-provided value |
| SAXParserTests.java:30:18:30:38 | getInputStream(...) | SAXParserTests.java:30:18:30:38 | getInputStream(...) | SAXParserTests.java:30:18:30:38 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SAXParserTests.java:30:18:30:38 | getInputStream(...) | user-provided value |
| SAXParserTests.java:38:18:38:38 | getInputStream(...) | SAXParserTests.java:38:18:38:38 | getInputStream(...) | SAXParserTests.java:38:18:38:38 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SAXParserTests.java:38:18:38:38 | getInputStream(...) | user-provided value |
| SAXParserTests.java:46:18:46:38 | getInputStream(...) | SAXParserTests.java:46:18:46:38 | getInputStream(...) | SAXParserTests.java:46:18:46:38 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SAXParserTests.java:46:18:46:38 | getInputStream(...) | user-provided value |
| SAXParserTests.java:55:18:55:38 | getInputStream(...) | SAXParserTests.java:55:18:55:38 | getInputStream(...) | SAXParserTests.java:55:18:55:38 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SAXParserTests.java:55:18:55:38 | getInputStream(...) | user-provided value |
| SAXParserTests.java:64:18:64:38 | getInputStream(...) | SAXParserTests.java:64:18:64:38 | getInputStream(...) | SAXParserTests.java:64:18:64:38 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SAXParserTests.java:64:18:64:38 | getInputStream(...) | user-provided value |
| SAXParserTests.java:73:18:73:38 | getInputStream(...) | SAXParserTests.java:73:18:73:38 | getInputStream(...) | SAXParserTests.java:73:18:73:38 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SAXParserTests.java:73:18:73:38 | getInputStream(...) | user-provided value |
| SAXReaderTests.java:8:17:8:37 | getInputStream(...) | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | user-provided value |
| SAXReaderTests.java:23:17:23:37 | getInputStream(...) | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | user-provided value |
| SAXReaderTests.java:30:17:30:37 | getInputStream(...) | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | user-provided value |
| SAXReaderTests.java:37:17:37:37 | getInputStream(...) | SAXReaderTests.java:37:17:37:37 | getInputStream(...) | SAXReaderTests.java:37:17:37:37 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SAXReaderTests.java:37:17:37:37 | getInputStream(...) | user-provided value |
| SAXReaderTests.java:45:17:45:37 | getInputStream(...) | SAXReaderTests.java:45:17:45:37 | getInputStream(...) | SAXReaderTests.java:45:17:45:37 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SAXReaderTests.java:45:17:45:37 | getInputStream(...) | user-provided value |
| SAXReaderTests.java:53:17:53:37 | getInputStream(...) | SAXReaderTests.java:53:17:53:37 | getInputStream(...) | SAXReaderTests.java:53:17:53:37 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SAXReaderTests.java:53:17:53:37 | getInputStream(...) | user-provided value |
| SAXReaderTests.java:61:17:61:37 | getInputStream(...) | SAXReaderTests.java:61:17:61:37 | getInputStream(...) | SAXReaderTests.java:61:17:61:37 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SAXReaderTests.java:61:17:61:37 | getInputStream(...) | user-provided value |
| SAXSourceTests.java:20:18:20:23 | source | SAXSourceTests.java:17:62:17:82 | getInputStream(...) : InputStream | SAXSourceTests.java:20:18:20:23 | source | XML parsing depends on a $@ without guarding against external entity expansion. | SAXSourceTests.java:17:62:17:82 | getInputStream(...) | user-provided value |
| SchemaTests.java:12:39:12:77 | new StreamSource(...) | SchemaTests.java:12:56:12:76 | getInputStream(...) : InputStream | SchemaTests.java:12:39:12:77 | new StreamSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SchemaTests.java:12:56:12:76 | getInputStream(...) | user-provided value |
| SchemaTests.java:25:39:25:77 | new StreamSource(...) | SchemaTests.java:25:56:25:76 | getInputStream(...) : InputStream | SchemaTests.java:25:39:25:77 | new StreamSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SchemaTests.java:25:56:25:76 | getInputStream(...) | user-provided value |
| SchemaTests.java:31:39:31:77 | new StreamSource(...) | SchemaTests.java:31:56:31:76 | getInputStream(...) : InputStream | SchemaTests.java:31:39:31:77 | new StreamSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SchemaTests.java:31:56:31:76 | getInputStream(...) | user-provided value |
| SchemaTests.java:38:39:38:77 | new StreamSource(...) | SchemaTests.java:38:56:38:76 | getInputStream(...) : InputStream | SchemaTests.java:38:39:38:77 | new StreamSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SchemaTests.java:38:56:38:76 | getInputStream(...) | user-provided value |
| SchemaTests.java:45:39:45:77 | new StreamSource(...) | SchemaTests.java:45:56:45:76 | getInputStream(...) : InputStream | SchemaTests.java:45:39:45:77 | new StreamSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SchemaTests.java:45:56:45:76 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:14:41:14:61 | getInputStream(...) | SimpleXMLTests.java:14:41:14:61 | getInputStream(...) | SimpleXMLTests.java:14:41:14:61 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:14:41:14:61 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:19:41:19:61 | getInputStream(...) | SimpleXMLTests.java:19:41:19:61 | getInputStream(...) | SimpleXMLTests.java:19:41:19:61 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:19:41:19:61 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:24:41:24:84 | new InputStreamReader(...) | SimpleXMLTests.java:24:63:24:83 | getInputStream(...) : InputStream | SimpleXMLTests.java:24:41:24:84 | new InputStreamReader(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:24:63:24:83 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:31:41:31:53 | new String(...) | SimpleXMLTests.java:30:5:30:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:31:41:31:53 | new String(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:30:5:30:25 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:38:41:38:53 | new String(...) | SimpleXMLTests.java:37:5:37:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:38:41:38:53 | new String(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:37:5:37:25 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:43:41:43:84 | new InputStreamReader(...) | SimpleXMLTests.java:43:63:43:83 | getInputStream(...) : InputStream | SimpleXMLTests.java:43:41:43:84 | new InputStreamReader(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:43:63:43:83 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:48:37:48:57 | getInputStream(...) | SimpleXMLTests.java:48:37:48:57 | getInputStream(...) | SimpleXMLTests.java:48:37:48:57 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:48:37:48:57 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:53:37:53:57 | getInputStream(...) | SimpleXMLTests.java:53:37:53:57 | getInputStream(...) | SimpleXMLTests.java:53:37:53:57 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:53:37:53:57 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:58:26:58:46 | getInputStream(...) | SimpleXMLTests.java:58:26:58:46 | getInputStream(...) | SimpleXMLTests.java:58:26:58:46 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:58:26:58:46 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:63:26:63:46 | getInputStream(...) | SimpleXMLTests.java:63:26:63:46 | getInputStream(...) | SimpleXMLTests.java:63:26:63:46 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:63:26:63:46 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:68:37:68:80 | new InputStreamReader(...) | SimpleXMLTests.java:68:59:68:79 | getInputStream(...) : InputStream | SimpleXMLTests.java:68:37:68:80 | new InputStreamReader(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:68:59:68:79 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:73:37:73:80 | new InputStreamReader(...) | SimpleXMLTests.java:73:59:73:79 | getInputStream(...) : InputStream | SimpleXMLTests.java:73:37:73:80 | new InputStreamReader(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:73:59:73:79 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:78:26:78:69 | new InputStreamReader(...) | SimpleXMLTests.java:78:48:78:68 | getInputStream(...) : InputStream | SimpleXMLTests.java:78:26:78:69 | new InputStreamReader(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:78:48:78:68 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:83:26:83:69 | new InputStreamReader(...) | SimpleXMLTests.java:83:48:83:68 | getInputStream(...) : InputStream | SimpleXMLTests.java:83:26:83:69 | new InputStreamReader(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:83:48:83:68 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:90:37:90:49 | new String(...) | SimpleXMLTests.java:89:5:89:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:90:37:90:49 | new String(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:89:5:89:25 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:97:37:97:49 | new String(...) | SimpleXMLTests.java:96:5:96:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:97:37:97:49 | new String(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:96:5:96:25 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:104:26:104:38 | new String(...) | SimpleXMLTests.java:103:5:103:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:104:26:104:38 | new String(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:103:5:103:25 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:111:26:111:38 | new String(...) | SimpleXMLTests.java:110:5:110:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:111:26:111:38 | new String(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:110:5:110:25 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:115:22:115:42 | getInputStream(...) | SimpleXMLTests.java:115:22:115:42 | getInputStream(...) | SimpleXMLTests.java:115:22:115:42 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:115:22:115:42 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:119:22:119:65 | new InputStreamReader(...) | SimpleXMLTests.java:119:44:119:64 | getInputStream(...) : InputStream | SimpleXMLTests.java:119:22:119:65 | new InputStreamReader(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:119:44:119:64 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:124:22:124:42 | getInputStream(...) | SimpleXMLTests.java:124:22:124:42 | getInputStream(...) | SimpleXMLTests.java:124:22:124:42 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:124:22:124:42 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:129:22:129:65 | new InputStreamReader(...) | SimpleXMLTests.java:129:44:129:64 | getInputStream(...) : InputStream | SimpleXMLTests.java:129:22:129:65 | new InputStreamReader(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:129:44:129:64 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:134:22:134:42 | getInputStream(...) | SimpleXMLTests.java:134:22:134:42 | getInputStream(...) | SimpleXMLTests.java:134:22:134:42 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:134:22:134:42 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:139:22:139:65 | new InputStreamReader(...) | SimpleXMLTests.java:139:44:139:64 | getInputStream(...) : InputStream | SimpleXMLTests.java:139:22:139:65 | new InputStreamReader(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:139:44:139:64 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:146:22:146:34 | new String(...) | SimpleXMLTests.java:145:5:145:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:146:22:146:34 | new String(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:145:5:145:25 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:153:22:153:34 | new String(...) | SimpleXMLTests.java:152:5:152:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:153:22:153:34 | new String(...) | XML parsing depends on a $@ without guarding against external entity expansion. | SimpleXMLTests.java:152:5:152:25 | getInputStream(...) | user-provided value |
| TransformerTests.java:20:27:20:65 | new StreamSource(...) | TransformerTests.java:20:44:20:64 | getInputStream(...) : InputStream | TransformerTests.java:20:27:20:65 | new StreamSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | TransformerTests.java:20:44:20:64 | getInputStream(...) | user-provided value |
| TransformerTests.java:21:23:21:61 | new StreamSource(...) | TransformerTests.java:21:40:21:60 | getInputStream(...) : InputStream | TransformerTests.java:21:23:21:61 | new StreamSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | TransformerTests.java:21:40:21:60 | getInputStream(...) | user-provided value |
| TransformerTests.java:71:27:71:65 | new StreamSource(...) | TransformerTests.java:71:44:71:64 | getInputStream(...) : InputStream | TransformerTests.java:71:27:71:65 | new StreamSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | TransformerTests.java:71:44:71:64 | getInputStream(...) | user-provided value |
| TransformerTests.java:72:23:72:61 | new StreamSource(...) | TransformerTests.java:72:40:72:60 | getInputStream(...) : InputStream | TransformerTests.java:72:23:72:61 | new StreamSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | TransformerTests.java:72:40:72:60 | getInputStream(...) | user-provided value |
| TransformerTests.java:79:27:79:65 | new StreamSource(...) | TransformerTests.java:79:44:79:64 | getInputStream(...) : InputStream | TransformerTests.java:79:27:79:65 | new StreamSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | TransformerTests.java:79:44:79:64 | getInputStream(...) | user-provided value |
| TransformerTests.java:80:23:80:61 | new StreamSource(...) | TransformerTests.java:80:40:80:60 | getInputStream(...) : InputStream | TransformerTests.java:80:23:80:61 | new StreamSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | TransformerTests.java:80:40:80:60 | getInputStream(...) | user-provided value |
| TransformerTests.java:88:27:88:65 | new StreamSource(...) | TransformerTests.java:88:44:88:64 | getInputStream(...) : InputStream | TransformerTests.java:88:27:88:65 | new StreamSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | TransformerTests.java:88:44:88:64 | getInputStream(...) | user-provided value |
| TransformerTests.java:89:23:89:61 | new StreamSource(...) | TransformerTests.java:89:40:89:60 | getInputStream(...) : InputStream | TransformerTests.java:89:23:89:61 | new StreamSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | TransformerTests.java:89:40:89:60 | getInputStream(...) | user-provided value |
| TransformerTests.java:97:27:97:65 | new StreamSource(...) | TransformerTests.java:97:44:97:64 | getInputStream(...) : InputStream | TransformerTests.java:97:27:97:65 | new StreamSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | TransformerTests.java:97:44:97:64 | getInputStream(...) | user-provided value |
| TransformerTests.java:98:23:98:61 | new StreamSource(...) | TransformerTests.java:98:40:98:60 | getInputStream(...) : InputStream | TransformerTests.java:98:23:98:61 | new StreamSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | TransformerTests.java:98:40:98:60 | getInputStream(...) | user-provided value |
| TransformerTests.java:103:21:103:59 | new StreamSource(...) | TransformerTests.java:103:38:103:58 | getInputStream(...) : InputStream | TransformerTests.java:103:21:103:59 | new StreamSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | TransformerTests.java:103:38:103:58 | getInputStream(...) | user-provided value |
| TransformerTests.java:116:21:116:59 | new StreamSource(...) | TransformerTests.java:116:38:116:58 | getInputStream(...) : InputStream | TransformerTests.java:116:21:116:59 | new StreamSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | TransformerTests.java:116:38:116:58 | getInputStream(...) | user-provided value |
| TransformerTests.java:122:21:122:59 | new StreamSource(...) | TransformerTests.java:122:38:122:58 | getInputStream(...) : InputStream | TransformerTests.java:122:21:122:59 | new StreamSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | TransformerTests.java:122:38:122:58 | getInputStream(...) | user-provided value |
| TransformerTests.java:129:21:129:59 | new StreamSource(...) | TransformerTests.java:129:38:129:58 | getInputStream(...) : InputStream | TransformerTests.java:129:21:129:59 | new StreamSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | TransformerTests.java:129:38:129:58 | getInputStream(...) | user-provided value |
| TransformerTests.java:136:21:136:59 | new StreamSource(...) | TransformerTests.java:136:38:136:58 | getInputStream(...) : InputStream | TransformerTests.java:136:21:136:59 | new StreamSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | TransformerTests.java:136:38:136:58 | getInputStream(...) | user-provided value |
| TransformerTests.java:141:18:141:70 | new SAXSource(...) | TransformerTests.java:141:48:141:68 | getInputStream(...) : InputStream | TransformerTests.java:141:18:141:70 | new SAXSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | TransformerTests.java:141:48:141:68 | getInputStream(...) | user-provided value |
| UnmarshallerTests.java:28:18:28:38 | getInputStream(...) | UnmarshallerTests.java:28:18:28:38 | getInputStream(...) | UnmarshallerTests.java:28:18:28:38 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | UnmarshallerTests.java:28:18:28:38 | getInputStream(...) | user-provided value |
| XMLReaderTests.java:16:18:16:55 | new InputSource(...) | XMLReaderTests.java:16:34:16:54 | getInputStream(...) : InputStream | XMLReaderTests.java:16:18:16:55 | new InputSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XMLReaderTests.java:16:34:16:54 | getInputStream(...) | user-provided value |
| XMLReaderTests.java:56:18:56:55 | new InputSource(...) | XMLReaderTests.java:56:34:56:54 | getInputStream(...) : InputStream | XMLReaderTests.java:56:18:56:55 | new InputSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XMLReaderTests.java:56:34:56:54 | getInputStream(...) | user-provided value |
| XMLReaderTests.java:63:18:63:55 | new InputSource(...) | XMLReaderTests.java:63:34:63:54 | getInputStream(...) : InputStream | XMLReaderTests.java:63:18:63:55 | new InputSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XMLReaderTests.java:63:34:63:54 | getInputStream(...) | user-provided value |
| XMLReaderTests.java:70:18:70:55 | new InputSource(...) | XMLReaderTests.java:70:34:70:54 | getInputStream(...) : InputStream | XMLReaderTests.java:70:18:70:55 | new InputSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XMLReaderTests.java:70:34:70:54 | getInputStream(...) | user-provided value |
| XMLReaderTests.java:78:18:78:55 | new InputSource(...) | XMLReaderTests.java:78:34:78:54 | getInputStream(...) : InputStream | XMLReaderTests.java:78:18:78:55 | new InputSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XMLReaderTests.java:78:34:78:54 | getInputStream(...) | user-provided value |
| XMLReaderTests.java:86:18:86:55 | new InputSource(...) | XMLReaderTests.java:86:34:86:54 | getInputStream(...) : InputStream | XMLReaderTests.java:86:18:86:55 | new InputSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XMLReaderTests.java:86:34:86:54 | getInputStream(...) | user-provided value |
| XMLReaderTests.java:94:18:94:55 | new InputSource(...) | XMLReaderTests.java:94:34:94:54 | getInputStream(...) : InputStream | XMLReaderTests.java:94:18:94:55 | new InputSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XMLReaderTests.java:94:34:94:54 | getInputStream(...) | user-provided value |
| XMLReaderTests.java:100:18:100:55 | new InputSource(...) | XMLReaderTests.java:100:34:100:54 | getInputStream(...) : InputStream | XMLReaderTests.java:100:18:100:55 | new InputSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XMLReaderTests.java:100:34:100:54 | getInputStream(...) | user-provided value |
| XPathExpressionTests.java:27:19:27:56 | new InputSource(...) | XPathExpressionTests.java:27:35:27:55 | getInputStream(...) : InputStream | XPathExpressionTests.java:27:19:27:56 | new InputSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XPathExpressionTests.java:27:35:27:55 | getInputStream(...) | user-provided value |
| XPathExpressionTests.java:42:23:42:60 | new InputSource(...) | XPathExpressionTests.java:42:39:42:59 | getInputStream(...) : InputStream | XPathExpressionTests.java:42:23:42:60 | new InputSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XPathExpressionTests.java:42:39:42:59 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:25:34:25:54 | getInputStream(...) | XmlInputFactoryTests.java:25:34:25:54 | getInputStream(...) | XmlInputFactoryTests.java:25:34:25:54 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XmlInputFactoryTests.java:25:34:25:54 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:31:35:31:55 | getInputStream(...) | XmlInputFactoryTests.java:31:35:31:55 | getInputStream(...) | XmlInputFactoryTests.java:31:35:31:55 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XmlInputFactoryTests.java:31:35:31:55 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:32:34:32:54 | getInputStream(...) | XmlInputFactoryTests.java:32:34:32:54 | getInputStream(...) | XmlInputFactoryTests.java:32:34:32:54 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XmlInputFactoryTests.java:32:34:32:54 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:39:35:39:55 | getInputStream(...) | XmlInputFactoryTests.java:39:35:39:55 | getInputStream(...) | XmlInputFactoryTests.java:39:35:39:55 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XmlInputFactoryTests.java:39:35:39:55 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:40:34:40:54 | getInputStream(...) | XmlInputFactoryTests.java:40:34:40:54 | getInputStream(...) | XmlInputFactoryTests.java:40:34:40:54 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XmlInputFactoryTests.java:40:34:40:54 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:47:35:47:55 | getInputStream(...) | XmlInputFactoryTests.java:47:35:47:55 | getInputStream(...) | XmlInputFactoryTests.java:47:35:47:55 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XmlInputFactoryTests.java:47:35:47:55 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:48:34:48:54 | getInputStream(...) | XmlInputFactoryTests.java:48:34:48:54 | getInputStream(...) | XmlInputFactoryTests.java:48:34:48:54 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XmlInputFactoryTests.java:48:34:48:54 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:55:35:55:55 | getInputStream(...) | XmlInputFactoryTests.java:55:35:55:55 | getInputStream(...) | XmlInputFactoryTests.java:55:35:55:55 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XmlInputFactoryTests.java:55:35:55:55 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:56:34:56:54 | getInputStream(...) | XmlInputFactoryTests.java:56:34:56:54 | getInputStream(...) | XmlInputFactoryTests.java:56:34:56:54 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XmlInputFactoryTests.java:56:34:56:54 | getInputStream(...) | user-provided value |

View File

@@ -0,0 +1,11 @@
import java
import TestUtilities.InlineFlowTest
import semmle.code.java.security.XxeRemoteQuery
class HasFlowTest extends InlineFlowTest {
override predicate hasTaintFlow(DataFlow::Node src, DataFlow::Node sink) {
XxeFlow::flow(src, sink)
}
override predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) { none() }
}

View File

@@ -1 +0,0 @@
Security/CWE/CWE-611/XXE.ql

View File

@@ -6,53 +6,53 @@ public class XmlInputFactoryTests {
public void unconfigureFactory(Socket sock) throws Exception {
XMLInputFactory factory = XMLInputFactory.newFactory();
factory.createXMLStreamReader(sock.getInputStream()); //unsafe
factory.createXMLEventReader(sock.getInputStream()); //unsafe
factory.createXMLStreamReader(sock.getInputStream()); // $ hasTaintFlow
factory.createXMLEventReader(sock.getInputStream()); // $ hasTaintFlow
}
public void safeFactory(Socket sock) throws Exception {
XMLInputFactory factory = XMLInputFactory.newFactory();
factory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
factory.setProperty("javax.xml.stream.isSupportingExternalEntities", false);
factory.createXMLStreamReader(sock.getInputStream()); //safe
factory.createXMLEventReader(sock.getInputStream()); //safe
factory.createXMLStreamReader(sock.getInputStream()); // safe
factory.createXMLEventReader(sock.getInputStream()); // safe
}
public void misConfiguredFactory(Socket sock) throws Exception {
XMLInputFactory factory = XMLInputFactory.newFactory();
factory.setProperty("javax.xml.stream.isSupportingExternalEntities", false);
factory.createXMLStreamReader(sock.getInputStream()); //unsafe
factory.createXMLEventReader(sock.getInputStream()); //unsafe
factory.createXMLStreamReader(sock.getInputStream()); // $ hasTaintFlow
factory.createXMLEventReader(sock.getInputStream()); // $ hasTaintFlow
}
public void misConfiguredFactory2(Socket sock) throws Exception {
XMLInputFactory factory = XMLInputFactory.newFactory();
factory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
factory.createXMLStreamReader(sock.getInputStream()); //unsafe
factory.createXMLEventReader(sock.getInputStream()); //unsafe
factory.createXMLStreamReader(sock.getInputStream()); // $ hasTaintFlow
factory.createXMLEventReader(sock.getInputStream()); // $ hasTaintFlow
}
public void misConfiguredFactory3(Socket sock) throws Exception {
XMLInputFactory factory = XMLInputFactory.newFactory();
factory.setProperty("javax.xml.stream.isSupportingExternalEntities", true);
factory.setProperty(XMLInputFactory.SUPPORT_DTD, true);
factory.createXMLStreamReader(sock.getInputStream()); //unsafe
factory.createXMLEventReader(sock.getInputStream()); //unsafe
factory.createXMLStreamReader(sock.getInputStream()); // $ hasTaintFlow
factory.createXMLEventReader(sock.getInputStream()); // $ hasTaintFlow
}
public void misConfiguredFactory4(Socket sock) throws Exception {
XMLInputFactory factory = XMLInputFactory.newFactory();
factory.setProperty("javax.xml.stream.isSupportingExternalEntities", false);
factory.setProperty(XMLInputFactory.SUPPORT_DTD, true);
factory.createXMLStreamReader(sock.getInputStream()); //unsafe
factory.createXMLEventReader(sock.getInputStream()); //unsafe
factory.createXMLStreamReader(sock.getInputStream()); // $ hasTaintFlow
factory.createXMLEventReader(sock.getInputStream()); // $ hasTaintFlow
}
public void misConfiguredFactory5(Socket sock) throws Exception {
XMLInputFactory factory = XMLInputFactory.newFactory();
factory.setProperty("javax.xml.stream.isSupportingExternalEntities", true);
factory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
factory.createXMLStreamReader(sock.getInputStream()); //unsafe
factory.createXMLEventReader(sock.getInputStream()); //unsafe
}
factory.createXMLStreamReader(sock.getInputStream()); // $ hasTaintFlow
factory.createXMLEventReader(sock.getInputStream()); // $ hasTaintFlow
}
}

View File

@@ -1 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/jdom-1.1.3:${testdir}/../../../stubs/dom4j-2.1.1:${testdir}/../../../stubs/simple-xml-2.7.1:${testdir}/../../../stubs/jaxb-api-2.3.1:${testdir}/../../../stubs/jaxen-1.2.0
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/jdom-1.1.3:${testdir}/../../../stubs/dom4j-2.1.1:${testdir}/../../../stubs/simple-xml-2.7.1:${testdir}/../../../stubs/jaxb-api-2.3.1:${testdir}/../../../stubs/jaxen-1.2.0:${testdir}/../../../stubs/apache-commons-digester3-3.2:${testdir}/../../../stubs/servlet-api-2.4/:${testdir}/../../../stubs/rundeck-api-java-client-13.2:${testdir}/../../../stubs/springframework-5.3.8/

View File

@@ -24,41 +24,41 @@ import org.springframework.jdbc.support.rowset.SqlRowSet;
public interface JdbcOperations
{
<T> List<T> query(PreparedStatementCreator p0, RowMapper<T> p1);
<T> List<T> query(String p0, Object[] p1, RowMapper<T> p2);
<T> List<T> query(String p0, Object[] p1, int[] p2, RowMapper<T> p3);
<T> List<T> query(String p0, PreparedStatementSetter p1, RowMapper<T> p2);
<T> List<T> query(String p0, RowMapper<T> p1);
<T> List<T> query(String p0, RowMapper<T> p1, Object... p2);
<T> List<T> queryForList(String p0, Class<T> p1);
<T> List<T> queryForList(String p0, Class<T> p1, Object... p2);
<T> List<T> queryForList(String p0, Object[] p1, Class<T> p2);
<T> List<T> queryForList(String p0, Object[] p1, int[] p2, Class<T> p3);
<T> Stream<T> queryForStream(PreparedStatementCreator p0, RowMapper<T> p1);
<T> Stream<T> queryForStream(String p0, PreparedStatementSetter p1, RowMapper<T> p2);
<T> Stream<T> queryForStream(String p0, RowMapper<T> p1);
<T> Stream<T> queryForStream(String p0, RowMapper<T> p1, Object... p2);
<T> T execute(CallableStatementCreator p0, CallableStatementCallback<T> p1);
<T> T execute(ConnectionCallback<T> p0);
<T> T execute(PreparedStatementCreator p0, PreparedStatementCallback<T> p1);
<T> T execute(StatementCallback<T> p0);
<T> T execute(String p0, CallableStatementCallback<T> p1);
<T> T execute(String p0, PreparedStatementCallback<T> p1);
<T> T query(PreparedStatementCreator p0, ResultSetExtractor<T> p1);
<T> T query(String p0, Object[] p1, ResultSetExtractor<T> p2);
<T> T query(String p0, Object[] p1, int[] p2, ResultSetExtractor<T> p3);
<T> T query(String p0, PreparedStatementSetter p1, ResultSetExtractor<T> p2);
<T> T query(String p0, ResultSetExtractor<T> p1);
<T> T query(String p0, ResultSetExtractor<T> p1, Object... p2);
<T> T queryForObject(String p0, Class<T> p1);
<T> T queryForObject(String p0, Class<T> p1, Object... p2);
<T> T queryForObject(String p0, Object[] p1, Class<T> p2);
<T> T queryForObject(String p0, Object[] p1, RowMapper<T> p2);
<T> T queryForObject(String p0, Object[] p1, int[] p2, Class<T> p3);
<T> T queryForObject(String p0, Object[] p1, int[] p2, RowMapper<T> p3);
<T> T queryForObject(String p0, RowMapper<T> p1);
<T> T queryForObject(String p0, RowMapper<T> p1, Object... p2);
<T> int[] batchUpdate(String p0, Collection<T> p1, int p2, ParameterizedPreparedStatementSetter<T> p3);
<T> T execute(CallableStatementCreator p0, org.springframework.jdbc.core.CallableStatementCallback<T> p1);
<T> T execute(PreparedStatementCreator p0, org.springframework.jdbc.core.PreparedStatementCallback<T> p1);
<T> T execute(String p0, org.springframework.jdbc.core.CallableStatementCallback<T> p1);
<T> T execute(String p0, org.springframework.jdbc.core.PreparedStatementCallback<T> p1);
<T> T execute(org.springframework.jdbc.core.ConnectionCallback<T> p0);
<T> T execute(org.springframework.jdbc.core.StatementCallback<T> p0);
<T> T query(PreparedStatementCreator p0, org.springframework.jdbc.core.ResultSetExtractor<T> p1);
<T> T query(String p0, Object[] p1, int[] p2, org.springframework.jdbc.core.ResultSetExtractor<T> p3);
<T> T query(String p0, Object[] p1, org.springframework.jdbc.core.ResultSetExtractor<T> p2);
<T> T query(String p0, PreparedStatementSetter p1, org.springframework.jdbc.core.ResultSetExtractor<T> p2);
<T> T query(String p0, org.springframework.jdbc.core.ResultSetExtractor<T> p1);
<T> T query(String p0, org.springframework.jdbc.core.ResultSetExtractor<T> p1, Object... p2);
<T> T queryForObject(String p0, Object[] p1, int[] p2, java.lang.Class<T> p3);
<T> T queryForObject(String p0, Object[] p1, int[] p2, org.springframework.jdbc.core.RowMapper<T> p3);
<T> T queryForObject(String p0, Object[] p1, java.lang.Class<T> p2);
<T> T queryForObject(String p0, Object[] p1, org.springframework.jdbc.core.RowMapper<T> p2);
<T> T queryForObject(String p0, java.lang.Class<T> p1);
<T> T queryForObject(String p0, java.lang.Class<T> p1, Object... p2);
<T> T queryForObject(String p0, org.springframework.jdbc.core.RowMapper<T> p1);
<T> T queryForObject(String p0, org.springframework.jdbc.core.RowMapper<T> p1, Object... p2);
<T> int[][] batchUpdate(String p0, java.util.Collection<T> p1, int p2, org.springframework.jdbc.core.ParameterizedPreparedStatementSetter<T> p3);
<T> java.util.List<T> query(PreparedStatementCreator p0, org.springframework.jdbc.core.RowMapper<T> p1);
<T> java.util.List<T> query(String p0, Object[] p1, int[] p2, org.springframework.jdbc.core.RowMapper<T> p3);
<T> java.util.List<T> query(String p0, Object[] p1, org.springframework.jdbc.core.RowMapper<T> p2);
<T> java.util.List<T> query(String p0, PreparedStatementSetter p1, org.springframework.jdbc.core.RowMapper<T> p2);
<T> java.util.List<T> query(String p0, org.springframework.jdbc.core.RowMapper<T> p1);
<T> java.util.List<T> query(String p0, org.springframework.jdbc.core.RowMapper<T> p1, Object... p2);
<T> java.util.List<T> queryForList(String p0, Object[] p1, int[] p2, java.lang.Class<T> p3);
<T> java.util.List<T> queryForList(String p0, Object[] p1, java.lang.Class<T> p2);
<T> java.util.List<T> queryForList(String p0, java.lang.Class<T> p1);
<T> java.util.List<T> queryForList(String p0, java.lang.Class<T> p1, Object... p2);
<T> java.util.stream.Stream<T> queryForStream(PreparedStatementCreator p0, org.springframework.jdbc.core.RowMapper<T> p1);
<T> java.util.stream.Stream<T> queryForStream(String p0, PreparedStatementSetter p1, org.springframework.jdbc.core.RowMapper<T> p2);
<T> java.util.stream.Stream<T> queryForStream(String p0, org.springframework.jdbc.core.RowMapper<T> p1);
<T> java.util.stream.Stream<T> queryForStream(String p0, org.springframework.jdbc.core.RowMapper<T> p1, Object... p2);
List<Map<String, Object>> queryForList(String p0);
List<Map<String, Object>> queryForList(String p0, Object... p1);
List<Map<String, Object>> queryForList(String p0, Object[] p1, int[] p2);

View File

@@ -35,7 +35,7 @@ import org.springframework.jdbc.support.rowset.SqlRowSet;
public class JdbcTemplate extends JdbcAccessor implements JdbcOperations
{
protected <T> RowMapper<T> getSingleColumnRowMapper(Class<T> p0){ return null; }
protected <T> org.springframework.jdbc.core.RowMapper<T> getSingleColumnRowMapper(java.lang.Class<T> p0){ return null; }
protected Connection createConnectionProxy(Connection p0){ return null; }
protected DataAccessException translateException(String p0, String p1, SQLException p2){ return null; }
protected Map<String, Object> createResultsMap(){ return null; }
@@ -49,43 +49,43 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations
protected void applyStatementSettings(Statement p0){}
protected void handleWarnings(SQLWarning p0){}
protected void handleWarnings(Statement p0){}
public <T> List<T> query(PreparedStatementCreator p0, RowMapper<T> p1){ return null; }
public <T> List<T> query(String p0, Object[] p1, RowMapper<T> p2){ return null; }
public <T> List<T> query(String p0, Object[] p1, int[] p2, RowMapper<T> p3){ return null; }
public <T> List<T> query(String p0, PreparedStatementSetter p1, RowMapper<T> p2){ return null; }
public <T> List<T> query(String p0, RowMapper<T> p1){ return null; }
public <T> List<T> query(String p0, RowMapper<T> p1, Object... p2){ return null; }
public <T> List<T> queryForList(String p0, Class<T> p1){ return null; }
public <T> List<T> queryForList(String p0, Class<T> p1, Object... p2){ return null; }
public <T> List<T> queryForList(String p0, Object[] p1, Class<T> p2){ return null; }
public <T> List<T> queryForList(String p0, Object[] p1, int[] p2, Class<T> p3){ return null; }
public <T> Stream<T> queryForStream(PreparedStatementCreator p0, PreparedStatementSetter p1, RowMapper<T> p2){ return null; }
public <T> Stream<T> queryForStream(PreparedStatementCreator p0, RowMapper<T> p1){ return null; }
public <T> Stream<T> queryForStream(String p0, PreparedStatementSetter p1, RowMapper<T> p2){ return null; }
public <T> Stream<T> queryForStream(String p0, RowMapper<T> p1){ return null; }
public <T> Stream<T> queryForStream(String p0, RowMapper<T> p1, Object... p2){ return null; }
public <T> T execute(CallableStatementCreator p0, CallableStatementCallback<T> p1){ return null; }
public <T> T execute(ConnectionCallback<T> p0){ return null; }
public <T> T execute(PreparedStatementCreator p0, PreparedStatementCallback<T> p1){ return null; }
public <T> T execute(StatementCallback<T> p0){ return null; }
public <T> T execute(String p0, CallableStatementCallback<T> p1){ return null; }
public <T> T execute(String p0, PreparedStatementCallback<T> p1){ return null; }
public <T> T query(PreparedStatementCreator p0, PreparedStatementSetter p1, ResultSetExtractor<T> p2){ return null; }
public <T> T query(PreparedStatementCreator p0, ResultSetExtractor<T> p1){ return null; }
public <T> T query(String p0, Object[] p1, ResultSetExtractor<T> p2){ return null; }
public <T> T query(String p0, Object[] p1, int[] p2, ResultSetExtractor<T> p3){ return null; }
public <T> T query(String p0, PreparedStatementSetter p1, ResultSetExtractor<T> p2){ return null; }
public <T> T query(String p0, ResultSetExtractor<T> p1){ return null; }
public <T> T query(String p0, ResultSetExtractor<T> p1, Object... p2){ return null; }
public <T> T queryForObject(String p0, Class<T> p1){ return null; }
public <T> T queryForObject(String p0, Class<T> p1, Object... p2){ return null; }
public <T> T queryForObject(String p0, Object[] p1, Class<T> p2){ return null; }
public <T> T queryForObject(String p0, Object[] p1, RowMapper<T> p2){ return null; }
public <T> T queryForObject(String p0, Object[] p1, int[] p2, Class<T> p3){ return null; }
public <T> T queryForObject(String p0, Object[] p1, int[] p2, RowMapper<T> p3){ return null; }
public <T> T queryForObject(String p0, RowMapper<T> p1){ return null; }
public <T> T queryForObject(String p0, RowMapper<T> p1, Object... p2){ return null; }
public <T> int[] batchUpdate(String p0, Collection<T> p1, int p2, ParameterizedPreparedStatementSetter<T> p3){ return null; }
public <T> T execute(CallableStatementCreator p0, org.springframework.jdbc.core.CallableStatementCallback<T> p1){ return null; }
public <T> T execute(PreparedStatementCreator p0, org.springframework.jdbc.core.PreparedStatementCallback<T> p1){ return null; }
public <T> T execute(String p0, org.springframework.jdbc.core.CallableStatementCallback<T> p1){ return null; }
public <T> T execute(String p0, org.springframework.jdbc.core.PreparedStatementCallback<T> p1){ return null; }
public <T> T execute(org.springframework.jdbc.core.ConnectionCallback<T> p0){ return null; }
public <T> T execute(org.springframework.jdbc.core.StatementCallback<T> p0){ return null; }
public <T> T query(PreparedStatementCreator p0, PreparedStatementSetter p1, org.springframework.jdbc.core.ResultSetExtractor<T> p2){ return null; }
public <T> T query(PreparedStatementCreator p0, org.springframework.jdbc.core.ResultSetExtractor<T> p1){ return null; }
public <T> T query(String p0, Object[] p1, int[] p2, org.springframework.jdbc.core.ResultSetExtractor<T> p3){ return null; }
public <T> T query(String p0, Object[] p1, org.springframework.jdbc.core.ResultSetExtractor<T> p2){ return null; }
public <T> T query(String p0, PreparedStatementSetter p1, org.springframework.jdbc.core.ResultSetExtractor<T> p2){ return null; }
public <T> T query(String p0, org.springframework.jdbc.core.ResultSetExtractor<T> p1){ return null; }
public <T> T query(String p0, org.springframework.jdbc.core.ResultSetExtractor<T> p1, Object... p2){ return null; }
public <T> T queryForObject(String p0, Object[] p1, int[] p2, java.lang.Class<T> p3){ return null; }
public <T> T queryForObject(String p0, Object[] p1, int[] p2, org.springframework.jdbc.core.RowMapper<T> p3){ return null; }
public <T> T queryForObject(String p0, Object[] p1, java.lang.Class<T> p2){ return null; }
public <T> T queryForObject(String p0, Object[] p1, org.springframework.jdbc.core.RowMapper<T> p2){ return null; }
public <T> T queryForObject(String p0, java.lang.Class<T> p1){ return null; }
public <T> T queryForObject(String p0, java.lang.Class<T> p1, Object... p2){ return null; }
public <T> T queryForObject(String p0, org.springframework.jdbc.core.RowMapper<T> p1){ return null; }
public <T> T queryForObject(String p0, org.springframework.jdbc.core.RowMapper<T> p1, Object... p2){ return null; }
public <T> int[][] batchUpdate(String p0, java.util.Collection<T> p1, int p2, org.springframework.jdbc.core.ParameterizedPreparedStatementSetter<T> p3){ return null; }
public <T> java.util.List<T> query(PreparedStatementCreator p0, org.springframework.jdbc.core.RowMapper<T> p1){ return null; }
public <T> java.util.List<T> query(String p0, Object[] p1, int[] p2, org.springframework.jdbc.core.RowMapper<T> p3){ return null; }
public <T> java.util.List<T> query(String p0, Object[] p1, org.springframework.jdbc.core.RowMapper<T> p2){ return null; }
public <T> java.util.List<T> query(String p0, PreparedStatementSetter p1, org.springframework.jdbc.core.RowMapper<T> p2){ return null; }
public <T> java.util.List<T> query(String p0, org.springframework.jdbc.core.RowMapper<T> p1){ return null; }
public <T> java.util.List<T> query(String p0, org.springframework.jdbc.core.RowMapper<T> p1, Object... p2){ return null; }
public <T> java.util.List<T> queryForList(String p0, Object[] p1, int[] p2, java.lang.Class<T> p3){ return null; }
public <T> java.util.List<T> queryForList(String p0, Object[] p1, java.lang.Class<T> p2){ return null; }
public <T> java.util.List<T> queryForList(String p0, java.lang.Class<T> p1){ return null; }
public <T> java.util.List<T> queryForList(String p0, java.lang.Class<T> p1, Object... p2){ return null; }
public <T> java.util.stream.Stream<T> queryForStream(PreparedStatementCreator p0, PreparedStatementSetter p1, org.springframework.jdbc.core.RowMapper<T> p2){ return null; }
public <T> java.util.stream.Stream<T> queryForStream(PreparedStatementCreator p0, org.springframework.jdbc.core.RowMapper<T> p1){ return null; }
public <T> java.util.stream.Stream<T> queryForStream(String p0, PreparedStatementSetter p1, org.springframework.jdbc.core.RowMapper<T> p2){ return null; }
public <T> java.util.stream.Stream<T> queryForStream(String p0, org.springframework.jdbc.core.RowMapper<T> p1){ return null; }
public <T> java.util.stream.Stream<T> queryForStream(String p0, org.springframework.jdbc.core.RowMapper<T> p1, Object... p2){ return null; }
public JdbcTemplate(){}
public JdbcTemplate(DataSource p0){}
public JdbcTemplate(DataSource p0, boolean p1){}

View File

@@ -0,0 +1,52 @@
// Generated automatically from org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations for testing purposes
package org.springframework.jdbc.core.namedparam;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.PreparedStatementCallback;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.jdbc.support.rowset.SqlRowSet;
public interface NamedParameterJdbcOperations
{
<T> T execute(String p0, Map<String, ? extends Object> p1, org.springframework.jdbc.core.PreparedStatementCallback<T> p2);
<T> T execute(String p0, SqlParameterSource p1, org.springframework.jdbc.core.PreparedStatementCallback<T> p2);
<T> T execute(String p0, org.springframework.jdbc.core.PreparedStatementCallback<T> p1);
<T> T query(String p0, Map<String, ? extends Object> p1, org.springframework.jdbc.core.ResultSetExtractor<T> p2);
<T> T query(String p0, SqlParameterSource p1, org.springframework.jdbc.core.ResultSetExtractor<T> p2);
<T> T query(String p0, org.springframework.jdbc.core.ResultSetExtractor<T> p1);
<T> T queryForObject(String p0, Map<String, ? extends Object> p1, java.lang.Class<T> p2);
<T> T queryForObject(String p0, Map<String, ? extends Object> p1, org.springframework.jdbc.core.RowMapper<T> p2);
<T> T queryForObject(String p0, SqlParameterSource p1, java.lang.Class<T> p2);
<T> T queryForObject(String p0, SqlParameterSource p1, org.springframework.jdbc.core.RowMapper<T> p2);
<T> java.util.List<T> query(String p0, Map<String, ? extends Object> p1, org.springframework.jdbc.core.RowMapper<T> p2);
<T> java.util.List<T> query(String p0, SqlParameterSource p1, org.springframework.jdbc.core.RowMapper<T> p2);
<T> java.util.List<T> query(String p0, org.springframework.jdbc.core.RowMapper<T> p1);
<T> java.util.List<T> queryForList(String p0, Map<String, ? extends Object> p1, java.lang.Class<T> p2);
<T> java.util.List<T> queryForList(String p0, SqlParameterSource p1, java.lang.Class<T> p2);
<T> java.util.stream.Stream<T> queryForStream(String p0, Map<String, ? extends Object> p1, org.springframework.jdbc.core.RowMapper<T> p2);
<T> java.util.stream.Stream<T> queryForStream(String p0, SqlParameterSource p1, org.springframework.jdbc.core.RowMapper<T> p2);
JdbcOperations getJdbcOperations();
List<Map<String, Object>> queryForList(String p0, Map<String, ? extends Object> p1);
List<Map<String, Object>> queryForList(String p0, SqlParameterSource p1);
Map<String, Object> queryForMap(String p0, Map<String, ? extends Object> p1);
Map<String, Object> queryForMap(String p0, SqlParameterSource p1);
SqlRowSet queryForRowSet(String p0, Map<String, ? extends Object> p1);
SqlRowSet queryForRowSet(String p0, SqlParameterSource p1);
int update(String p0, Map<String, ? extends Object> p1);
int update(String p0, SqlParameterSource p1);
int update(String p0, SqlParameterSource p1, KeyHolder p2);
int update(String p0, SqlParameterSource p1, KeyHolder p2, String[] p3);
int[] batchUpdate(String p0, Map<String, ? extends Object>[] p1);
int[] batchUpdate(String p0, SqlParameterSource[] p1);
void query(String p0, Map<String, ? extends Object> p1, RowCallbackHandler p2);
void query(String p0, RowCallbackHandler p1);
void query(String p0, SqlParameterSource p1, RowCallbackHandler p2);
}

View File

@@ -2,21 +2,9 @@
package org.springframework.jdbc.core.namedparam;
import java.util.List;
public class ParsedSql
{
protected ParsedSql() {}
List<String> getParameterNames(){ return null; }
ParsedSql(String p0){}
String getOriginalSql(){ return null; }
int getNamedParameterCount(){ return 0; }
int getTotalParameterCount(){ return 0; }
int getUnnamedParameterCount(){ return 0; }
int[] getParameterIndexes(int p0){ return null; }
public String toString(){ return null; }
void addNamedParameter(String p0, int p1, int p2){}
void setNamedParameterCount(int p0){}
void setTotalParameterCount(int p0){}
void setUnnamedParameterCount(int p0){}
}

View File

@@ -0,0 +1,14 @@
// Generated automatically from org.springframework.jdbc.core.namedparam.SqlParameterSource for testing purposes
package org.springframework.jdbc.core.namedparam;
public interface SqlParameterSource
{
Object getValue(String p0);
boolean hasValue(String p0);
default String getTypeName(String p0){ return null; }
default String[] getParameterNames(){ return null; }
default int getSqlType(String p0){ return 0; }
static int TYPE_UNKNOWN = 0;
}

View File

@@ -3,12 +3,14 @@
package org.springframework.jdbc.support;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jdbc.support.SQLExceptionTranslator;
abstract public class JdbcAccessor implements InitializingBean
{
protected DataSource obtainDataSource(){ return null; }
protected final Log logger = null;
public DataSource getDataSource(){ return null; }
public JdbcAccessor(){}
public SQLExceptionTranslator getExceptionTranslator(){ return null; }

View File

@@ -7,7 +7,7 @@ import java.util.Map;
public interface KeyHolder
{
<T> T getKeyAs(Class<T> p0);
<T> T getKeyAs(java.lang.Class<T> p0);
List<Map<String, Object>> getKeyList();
Map<String, Object> getKeys();
Number getKey();

View File

@@ -11,11 +11,8 @@ class PasswordTracker extends DataFlow::Configuration {
override predicate isSink(DataFlow::Node nd) { this.passwordVarAssign(_, nd) }
predicate passwordVarAssign(Variable v, DataFlow::Node nd) {
exists(SsaExplicitDefinition def |
nd = DataFlow::ssaDefinitionNode(def) and
def.getSourceVariable() = v and
v.getName().toLowerCase() = "password"
)
v.getAnAssignedExpr() = nd.asExpr() and
v.getName().toLowerCase() = "password"
}
}

View File

@@ -9,6 +9,7 @@ test_query4
| tst.js:29:1:29:5 | 1 + 2 | This expression should be bracketed to clarify precedence rules. |
test_query19
test_query17
| tst.js:38:18:38:23 | "blah" | Password variable password is assigned a constant string. |
test_query18
| m.js:1:1:3:0 | <toplevel> | 0 |
test_query8
@@ -18,6 +19,7 @@ test_query11
| tst.js:31:12:31:12 | x | Dead store of local variable. |
| tst.js:31:15:31:15 | y | Dead store of local variable. |
| tst.js:31:18:31:18 | x | Dead store of local variable. |
| tst.js:38:7:38:23 | password = "blah" | Dead store of local variable. |
test_query12
test_query20
test_query3

View File

@@ -32,4 +32,8 @@ function l(x, y, x) {
for (i=0;i<10;++i);
}
var j, j;
var j, j;
function foo() {
var password = "blah";
}

View File

@@ -0,0 +1,472 @@
#!/usr/bin/env python3
"""
This script can be used to go over `codeql test run` expected/actual log output from
github actions, and apply patches locally to make the tests pass.
It works by forming individual patches for each test-failure, and then applying them one
by one. Since Python runs some tests twice (for both Python2 and Python3), we try to do
some simple duplicate patch detection, to avoid failing to apply the same patch twice.
Use it by checking out an up to date version of your branch, and just run the script (it
will use `gh` cli to figure out what the PR number is). You must have the `gh` cli tool
installed.
The parsing of logs is somewhat tolerant of output being interleaved with other parallel
execution, but it might fail in some cases ¯\_(ツ)_/¯
Code written to hack things together until they work, so don't expect much :D
"""
import argparse
import sys
import re
import tempfile
from typing import List, Dict, Set, Optional, Any
from pathlib import Path
import subprocess
import logging
import json
from dataclasses import dataclass, field
from datetime import datetime
import os.path
import itertools
LOGGER = logging.getLogger(Path(__file__).name)
DEBUG_SAVE_PATCHES = False
DEBUG_LOG_FILE = None
def _get_codeql_repo_dir() -> Path:
return Path(__file__).parent.parent.parent
CODEQL_REPO_DIR = _get_codeql_repo_dir()
def _get_semmle_code_dir() -> Optional[Path]:
guess = CODEQL_REPO_DIR.parent
try:
out = subprocess.check_output(
["git", "remote", "-v"],
cwd=guess,
).decode("utf-8")
if "github/semmle-code" in out:
return guess
else:
return None
except subprocess.CalledProcessError:
return None
SEMMLE_CODE_DIR = _get_semmle_code_dir()
if SEMMLE_CODE_DIR is None:
LOGGER.warning("Could not find semmle-code repo, will not be able to apply patches for it")
@dataclass(frozen=True, eq=True, order=True)
class Patch:
filename: Path
dir: Optional[str]
patch_first_line: str
patch: List[str] = field(hash=False)
def format_as_patch(self) -> str:
return (f"--- a/{self.filename}\n" +
f"+++ b/{self.filename}\n" +
"\n".join(self.patch) +
"\n"
)
def parse_log_line(log_line: str) -> str:
if '\t' in log_line:
m = re.fullmatch(r"^(?:[^\t]+\t){2}\S+ ?(.*)$", log_line.strip())
else:
m = re.fullmatch(r"^(?:[^ ]+ )(.*)$", log_line.strip())
if not m:
return ""
return m.group(1)
def make_patches_from_log_file(log_file_lines) -> List[Patch]:
# TODO: If the expected output contains `Password=123` this will be masked as `***`
# in the actions logs. We _could_ try to detect this and replace the line with the
# actual content from file (but it would require parsing the @@ lines, to understand
# what the old linenumber to read is)
patches = []
lines = iter(log_file_lines)
for raw_line in lines:
line = parse_log_line(raw_line)
if line == "--- expected":
while True:
next_line = parse_log_line(next(lines))
if next_line == "+++ actual":
break
lines_changed = []
while True:
next_line = parse_log_line(next(lines))
# it can be the case that
if next_line[0] in (" ", "-", "+", "@"):
lines_changed.append(next_line)
if "FAILED" in next_line:
break
# error line _should_ be next, but sometimes the output gets interleaved...
# so we just skip until we find the error line
error_line = next_line
while True:
# internal
filename_match = re.fullmatch(r"^##\[error\].*FAILED\(RESULT\) (.*)$", error_line)
if not filename_match:
# codeql action
filename_match = re.fullmatch(r"^.*FAILED\(RESULT\) (.*)$", error_line)
if filename_match:
break
error_line = parse_log_line(next(lines))
full_path = filename_match.group(1)
known_start_paths = {
# internal CI runs
"/home/runner/work/semmle-code/semmle-code/ql/": CODEQL_REPO_DIR,
"/home/runner/work/semmle-code/semmle-code/target/codeql-java-integration-tests/ql/": CODEQL_REPO_DIR,
"/home/runner/work/semmle-code/semmle-code/" : SEMMLE_CODE_DIR,
# github actions on codeql repo
"/home/runner/work/codeql/codeql/": CODEQL_REPO_DIR,
"/Users/runner/work/codeql/codeql/" : CODEQL_REPO_DIR, # MacOS
}
for known_start_path, dir in known_start_paths.items():
if full_path.startswith(known_start_path):
filename = Path(full_path[len(known_start_path):])
break
else:
raise Exception(f"Unknown path {full_path}, skipping")
expected_filename = filename.with_suffix(".expected")
# if the .expected file used to be empty, `codeql test run` outputs a diff
# that uses `@@ -1,1 ` but git wants it to be `@@ -0,0 ` (and not include
# the removal of the empty line)
if lines_changed[0].startswith("@@ -1,1 ") and lines_changed[1] == "-":
lines_changed[0] = lines_changed[0].replace("@@ -1,1 ", "@@ -0,0 ")
del lines_changed[1]
patch = Patch(
filename=expected_filename,
dir=dir,
patch_first_line=lines_changed[0],
patch=lines_changed,
)
patches.append(patch)
return patches
def make_github_api_list_request(path: str) -> Any:
"""Handles the way paginate currently works, which is to return multiple lists of
results, instead of merging them :(
"""
s = subprocess.check_output(
["gh", "api", "--paginate", path],
).decode("utf-8")
try:
return json.loads(s)
except json.JSONDecodeError:
assert "][" in s
parts = s.split("][")
parts[0] = parts[0] + "]"
parts[-1] = "[" + parts[-1]
for i in range(1, len(parts) - 1):
parts[i] = "[" + parts[i] + "]"
return itertools.chain(*[json.loads(x) for x in parts])
@dataclass
class GithubStatus():
state: str
context: str
target_url: str
created_at: datetime
nwo: str
job_id: int = None
def get_log_content(status: GithubStatus) -> str:
LOGGER.debug(f"'{status.context}': Getting logs")
if status.job_id:
content = subprocess.check_output(
["gh", "api", f"/repos/{status.nwo}/actions/jobs/{status.job_id}/logs"],
).decode("utf-8")
else:
m = re.fullmatch(r"^https://github\.com/([^/]+/[^/]+)/actions/runs/(\d+)(?:/jobs/(\d+))?$", status.target_url)
nwo = m.group(1)
run_id = m.group(2)
content = subprocess.check_output(
["gh", "run", "view", "--repo", nwo, run_id, "--log-failed"],
).decode("utf-8")
if DEBUG_SAVE_PATCHES:
tmp = tempfile.NamedTemporaryFile(delete=False)
tmp.write(content.encode(encoding="utf-8"))
print(tmp.name)
return content
def main(pr_number: Optional[int], sha_override: Optional[str] = None, force=False):
if not pr_number and not sha_override:
raise Exception("Must specify either a PR number or a SHA")
if sha_override:
github_sha = sha_override
else:
LOGGER.info(f"Getting status URL for codeql PR #{pr_number}")
github_sha = subprocess.check_output(
["gh", "api", f"repos/github/codeql/pulls/{pr_number}", "--jq", ".head.sha"]
).decode("utf-8").strip()
local_sha = subprocess.check_output(
["git", "rev-parse", "HEAD"]
).decode("utf-8").strip()
if local_sha != github_sha and not force:
LOGGER.error(f"GitHub SHA ({github_sha}) different from your local SHA ({local_sha}), sync your changes first!")
sys.exit(1)
sha = github_sha
status_url = f"https://api.github.com/repos/github/codeql/commits/{sha}/statuses"
LOGGER.info(f"Getting status details ({status_url})")
statuses = make_github_api_list_request(status_url)
newest_status: Dict[str, GithubStatus] = dict()
for status in statuses:
created_at = datetime.fromisoformat(status["created_at"][:-1])
key = status["context"]
if key not in newest_status or created_at > newest_status[key].created_at:
m = re.fullmatch(r"^https://github\.com/([^/]+/[^/]+)/actions/runs/(\d+)(?:/jobs/(\d+))?$", status["target_url"])
newest_status[key] = GithubStatus(
state=status["state"],
context=status["context"],
target_url=status["target_url"],
created_at=created_at,
nwo=m.group(1),
)
supported_internal_status_language_test_names = [
"Java Integration Tests Linux",
# "codeql-coding-standards Unit Tests Linux",
# TODO: Currently disabled, would just require support for figuring out where
# https://github.com/github/codeql-coding-standards/ is checked out locally
]
lang_test_failures: List[GithubStatus] = list()
for status in newest_status.values():
if " Language Tests" in status.context or status.context in supported_internal_status_language_test_names:
if status.state == "failure":
lang_test_failures.append(status)
elif status.state == "pending":
LOGGER.error(f"Language tests ({status.context}) are still running, please wait for them to finish before running this script again")
sys.exit(1)
job_failure_urls = set()
for lang_test_failure in lang_test_failures:
job_failure_urls.add(lang_test_failure.target_url)
if job_failure_urls:
assert len(job_failure_urls) == 1, f"Multiple job failure URLs: {job_failure_urls}"
job_failure_url = job_failure_urls.pop()
# fixup URL. On the status, the target URL is the run, and it's really hard to
# change this to link to the full `/runs/<run_id>/jobs/<numeric_job_id>` URL, since
# the `<numeric_job_id>` is not available in a context: https://github.com/community/community/discussions/40291
m = re.fullmatch(r"^https://github\.com/([^/]+/[^/]+)/actions/runs/(\d+)$", job_failure_url)
nwo = m.group(1)
run_id = m.group(2)
jobs_url = f"https://api.github.com/repos/{nwo}/actions/runs/{run_id}/jobs"
LOGGER.info(f"Fixing up target url from looking at {jobs_url}")
jobs = json.loads(subprocess.check_output(["gh", "api", "--paginate", jobs_url]).decode("utf-8"))
for lang_test_failure in lang_test_failures:
workflow_translation = {
"codeql-coding-standards Unit Tests Linux": "Start codeql-coding-standards"
}
expected_workflow_name = workflow_translation.get(lang_test_failure.context, lang_test_failure.context)
for job in jobs["jobs"]:
api_name: str = job["name"]
if " / " not in api_name:
continue
workflow_name, job_name = api_name.split(" / ")
# The job names we're looking for looks like "Python2 Language Tests / Python2 Language Tests" or "Java Language Tests / Java Language Tests Linux"
# for "Java Integration Tests Linux / Java Integration tests Linux" we need to ignore case :|
if workflow_name == expected_workflow_name and job_name.lower().startswith(lang_test_failure.context.lower()):
lang_test_failure.job_id = job["id"]
break
else:
LOGGER.error(f"Could not find job for {lang_test_failure.context!r}")
sys.exit(1)
# Ruby/Swift/C#/Go use github actions, and not internal CI. These are not reported
# from the /statuses API, but from the /check-suites API
check_suites_url = f"https://api.github.com/repos/github/codeql/commits/{sha}/check-suites"
LOGGER.info(f"Getting check suites ({check_suites_url})")
check_suites = json.loads(subprocess.check_output(["gh", "api", "--paginate", check_suites_url]).decode("utf-8"))
check_failure_urls = []
for check in check_suites["check_suites"]:
if check["status"] != "completed":
print(check)
LOGGER.error("At least one check not completed yet!")
sys.exit(1)
if check["conclusion"] == "failure":
check_failure_urls.append(check["check_runs_url"])
for check_failure_url in check_failure_urls:
# run information: https://docs.github.com/en/rest/actions/workflow-jobs?apiVersion=2022-11-28#get-a-job-for-a-workflow-run
check_runs = json.loads(subprocess.check_output(["gh", "api", "--paginate", check_failure_url]).decode("utf-8"))
for check_run in check_runs["check_runs"]:
if check_run["conclusion"] == "failure":
m = re.fullmatch(r"^https://github\.com/([^/]+/[^/]+)/actions/runs/(\d+)(?:/jobs/(\d+))?$", check_run["details_url"])
nwo = m.group(1)
run_id = m.group(2)
jobs_url = f"https://api.github.com/repos/{nwo}/actions/runs/{run_id}/jobs"
LOGGER.debug(f"Looking into failure at {jobs_url}")
jobs = json.loads(subprocess.check_output(["gh", "api", "--paginate", jobs_url]).decode("utf-8"))
for job in jobs["jobs"]:
OK_WORKFLOW_NAMES = ["C#: Run QL Tests", "Go: Run Tests", "Ruby: Run QL Tests", "Swift"]
def ok_job_name(job_name: str) -> bool:
if job_name.startswith("qltest"):
return True
if job_name.startswith("Test Linux"):
return True
if job_name.startswith("integration-tests"):
return True
return False
if job["name"] == check_run['name'] and job["workflow_name"] in OK_WORKFLOW_NAMES and ok_job_name(job["name"]):
# print(check_run['name'], 'matched to', f"{job['workflow_name']} / {job['name']}")
lang_test_failures.append(GithubStatus(
state="failure",
context=f"{job['workflow_name']} / {job['name']}",
target_url=job["html_url"],
created_at=check_run["completed_at"],
nwo=nwo,
job_id=job["id"],
))
break
else:
LOGGER.debug(f"Ignoring actions failure for '{check_run['name']}' ({check_run['details_url']})")
if not lang_test_failures:
LOGGER.info("No language test failures found")
return
patches_to_apply: Set[Patch] = set()
for failure in lang_test_failures:
log_content = get_log_content(failure)
LOGGER.info(f"'{failure.context}': Making patches")
patches = make_patches_from_log_file(log_content.splitlines())
if not patches:
LOGGER.warning(f"No patches generated for job {failure}")
continue
for patch in patches:
if patch in patches_to_apply:
LOGGER.debug(f"Skipping duplicate patch for {patch.filename}")
continue
patches_to_apply.add(patch)
if DEBUG_SAVE_PATCHES:
sys.exit("debug save patches")
if not patches_to_apply:
print("No patches to apply")
return
semmle_code_changed = False
for patch in patches_to_apply:
with tempfile.NamedTemporaryFile(prefix=f"patches-", suffix=".patch") as temp:
temp.write(patch.format_as_patch().encode(encoding="utf-8"))
temp.flush()
LOGGER.info(f"Applying patch for '{patch.filename}'")
try:
if patch.dir is None:
LOGGER.warning(f"Did not find local semmle-code directory, so skipping patch for '{patch.filename}'")
continue
subprocess.check_call(["git", "apply", temp.name], cwd=patch.dir)
if "CONSISTENCY" in patch.filename.parts:
# delete if empty
if os.path.getsize(patch.filename) == 1 and patch.filename.read_text() == "\n":
os.remove(patch.filename)
LOGGER.info(f"Deleted empty CONSISTENCY file '{patch.filename}'")
if patch.dir == SEMMLE_CODE_DIR:
semmle_code_changed = True
except subprocess.CalledProcessError:
LOGGER.error(f"Could not apply patches for '{patch.filename}' '{patch.patch[0]}', skipping")
tmp_keep = tempfile.NamedTemporaryFile(delete=False)
tmp_keep.write(patch.format_as_patch().encode(encoding="utf-8"))
LOGGER.error(f"Patch saved to {tmp_keep.name}")
if semmle_code_changed:
print("Expected output in semmle-code changed!")
if __name__ == "__main__":
level = logging.INFO
try:
import coloredlogs
coloredlogs.install(level, fmt="%(levelname)s: %(message)s")
except ImportError:
logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
# parse command line arguments
parser = argparse.ArgumentParser()
parser.add_argument("--force", action="store_true", help="Apply patches even if the local SHA is different from the GitHub PR SHA")
parser.add_argument("posarg", nargs="?", default=None)
if DEBUG_LOG_FILE:
patches = make_patches_from_log_file(open(DEBUG_LOG_FILE, "r").readlines())
for patch in patches:
if True:
tmp_keep = tempfile.NamedTemporaryFile(delete=False)
tmp_keep.write(patch.format_as_patch().encode(encoding="utf-8"))
LOGGER.info(f"Patch for {patch.filename} saved to {tmp_keep.name}")
sys.exit(1)
os.chdir(CODEQL_REPO_DIR)
pr_number = None
override_sha = None
args = parser.parse_args()
if args.posarg is None:
pr_number_response = subprocess.check_output([
"gh", "pr", "view", "--json", "number"
]).decode("utf-8")
pr_number = json.loads(pr_number_response)["number"]
else:
if len(args.posarg) > 10:
override_sha = args.posarg
else:
pr_number = int(args.posarg)
main(pr_number, override_sha, force=args.force)

View File

@@ -1,6 +1,7 @@
private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate
private import FlowSummaryImpl as FlowSummaryImpl
private import semmle.python.dataflow.new.internal.TaintTrackingPublic
private import semmle.python.ApiGraphs
@@ -55,6 +56,8 @@ private module Cached {
awaitStep(nodeFrom, nodeTo)
or
asyncWithStep(nodeFrom, nodeTo)
or
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, false)
}
}
@@ -159,7 +162,7 @@ predicate stringManipulation(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeT
* is currently very imprecise, as an example, since we model `dict.get`, we treat any
* `<tainted object>.get(<arg>)` will be tainted, whether it's true or not.
*/
predicate containerStep(DataFlow::CfgNode nodeFrom, DataFlow::Node nodeTo) {
predicate containerStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
// construction by literal
//
// TODO: once we have proper flow-summary modeling, we might not need this step any
@@ -181,13 +184,6 @@ predicate containerStep(DataFlow::CfgNode nodeFrom, DataFlow::Node nodeTo) {
// don't provide that right now.
DataFlowPrivate::comprehensionStoreStep(nodeFrom, _, nodeTo)
or
// constructor call
exists(DataFlow::CallCfgNode call | call = nodeTo |
call = API::builtin(["list", "set", "frozenset", "dict", "tuple"]).getACall() and
call.getArg(0) = nodeFrom
// TODO: Properly handle defaultdict/namedtuple
)
or
// functions operating on collections
exists(DataFlow::CallCfgNode call | call = nodeTo |
call = API::builtin(["sorted", "reversed", "iter", "next"]).getACall() and

View File

@@ -3790,6 +3790,138 @@ private module StdlibPrivate {
override DataFlow::Node getAPathArgument() { result = this.getAnInput() }
}
// ---------------------------------------------------------------------------
// Flow summaries for functions contructing containers
// ---------------------------------------------------------------------------
/** A flow summary for `dict`. */
class DictSummary extends SummarizedCallable {
DictSummary() { this = "builtins.dict" }
override DataFlow::CallCfgNode getACall() { result = API::builtin("dict").getACall() }
override DataFlow::ArgumentNode getACallback() {
result = API::builtin("dict").getAValueReachableFromSource()
}
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
exists(DataFlow::DictionaryElementContent dc, string key | key = dc.getKey() |
input = "Argument[0].DictionaryElement[" + key + "]" and
output = "ReturnValue.DictionaryElement[" + key + "]" and
preservesValue = true
)
or
exists(DataFlow::DictionaryElementContent dc, string key | key = dc.getKey() |
input = "Argument[" + key + ":]" and
output = "ReturnValue.DictionaryElement[" + key + "]" and
preservesValue = true
)
or
input = "Argument[0]" and
output = "ReturnValue" and
preservesValue = false
}
}
/** A flow summary for `list`. */
class ListSummary extends SummarizedCallable {
ListSummary() { this = "builtins.list" }
override DataFlow::CallCfgNode getACall() { result = API::builtin("list").getACall() }
override DataFlow::ArgumentNode getACallback() {
result = API::builtin("list").getAValueReachableFromSource()
}
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
(
input = "Argument[0].ListElement"
or
input = "Argument[0].SetElement"
or
exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
input = "Argument[0].TupleElement[" + i.toString() + "]"
)
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
) and
output = "ReturnValue.ListElement" and
preservesValue = true
or
input = "Argument[0]" and
output = "ReturnValue" and
preservesValue = false
}
}
/** A flow summary for tuple */
class TupleSummary extends SummarizedCallable {
TupleSummary() { this = "builtins.tuple" }
override DataFlow::CallCfgNode getACall() { result = API::builtin("tuple").getACall() }
override DataFlow::ArgumentNode getACallback() {
result = API::builtin("tuple").getAValueReachableFromSource()
}
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
input = "Argument[0].TupleElement[" + i.toString() + "]" and
output = "ReturnValue.TupleElement[" + i.toString() + "]" and
preservesValue = true
)
or
// TODO: We need to also translate iterable content such as list element
// but we currently lack TupleElementAny
input = "Argument[0]" and
output = "ReturnValue" and
preservesValue = false
}
}
/** A flow summary for set */
class SetSummary extends SummarizedCallable {
SetSummary() { this = "builtins.set" }
override DataFlow::CallCfgNode getACall() { result = API::builtin("set").getACall() }
override DataFlow::ArgumentNode getACallback() {
result = API::builtin("set").getAValueReachableFromSource()
}
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
(
input = "Argument[0].ListElement"
or
input = "Argument[0].SetElement"
or
exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
input = "Argument[0].TupleElement[" + i.toString() + "]"
)
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
) and
output = "ReturnValue.SetElement" and
preservesValue = true
or
input = "Argument[0]" and
output = "ReturnValue" and
preservesValue = false
}
}
/** A flow summary for frozenset */
class FrozensetSummary extends SummarizedCallable {
FrozensetSummary() { this = "builtins.frozenset" }
override DataFlow::CallCfgNode getACall() { result = API::builtin("frozenset").getACall() }
override DataFlow::ArgumentNode getACallback() {
result = API::builtin("frozenset").getAValueReachableFromSource()
}
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
any(SetSummary s).propagatesFlowExt(input, output, preservesValue)
}
}
/** A flow summary for `reversed`. */
class ReversedSummary extends SummarizedCallable {
ReversedSummary() { this = "builtins.reversed" }

View File

@@ -1,5 +1,8 @@
import experimental.dataflow.callGraphConfig
from DataFlow::Node source, DataFlow::Node sink
where exists(CallGraphConfig cfg | cfg.hasFlow(source, sink))
where
exists(CallGraphConfig cfg | cfg.hasFlow(source, sink)) and
exists(source.getLocation().getFile().getRelativePath()) and
exists(sink.getLocation().getFile().getRelativePath())
select source, sink

View File

@@ -1,5 +1,3 @@
| file://:0:0:0:0 | parameter position 0 of builtins.reversed |
| file://:0:0:0:0 | parameter position 1 of dict.setdefault |
| test.py:1:1:1:21 | SynthDictSplatParameterNode |
| test.py:1:19:1:19 | ControlFlowNode for x |
| test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |

View File

@@ -1,5 +1,7 @@
import experimental.dataflow.callGraphConfig
from DataFlow::Node sink
where exists(CallGraphConfig cfg | cfg.isSink(sink))
where
exists(CallGraphConfig cfg | cfg.isSink(sink)) and
exists(sink.getLocation().getFile().getRelativePath())
select sink

View File

@@ -1,4 +1,2 @@
| file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed |
| file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
| test.py:4:10:4:10 | ControlFlowNode for z |
| test.py:7:19:7:19 | ControlFlowNode for a |

View File

@@ -1,5 +1,7 @@
import experimental.dataflow.callGraphConfig
from DataFlow::Node source
where exists(CallGraphConfig cfg | cfg.isSource(source))
where
exists(CallGraphConfig cfg | cfg.isSource(source)) and
exists(source.getLocation().getFile().getRelativePath())
select source

View File

@@ -1,5 +1,3 @@
| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed |
| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id |
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id |
| test.py:1:5:1:17 | GSSA Variable obfuscated_id | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id |

View File

@@ -3,5 +3,7 @@ import allFlowsConfig
from DataFlow::Node source, DataFlow::Node sink
where
source != sink and
exists(AllFlowsConfig cfg | cfg.hasFlow(source, sink))
exists(AllFlowsConfig cfg | cfg.hasFlow(source, sink)) and
exists(source.getLocation().getFile().getRelativePath()) and
exists(sink.getLocation().getFile().getRelativePath())
select source, sink

View File

@@ -1,5 +1,3 @@
| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed |
| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id |
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id |
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id |

View File

@@ -1,5 +1,8 @@
import allFlowsConfig
from DataFlow::PathNode fromNode, DataFlow::PathNode toNode
where toNode = fromNode.getASuccessor()
where
toNode = fromNode.getASuccessor() and
exists(fromNode.getNode().getLocation().getFile().getRelativePath()) and
exists(toNode.getNode().getLocation().getFile().getRelativePath())
select fromNode, toNode

View File

@@ -1,11 +1,3 @@
| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed |
| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed |
| file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed |
| file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
| file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed |
| file://:0:0:0:0 | parameter position 0 of builtins.reversed | file://:0:0:0:0 | parameter position 0 of builtins.reversed |
| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | parameter position 1 of dict.setdefault |
| test.py:0:0:0:0 | GSSA Variable __name__ | test.py:0:0:0:0 | GSSA Variable __name__ |
| test.py:0:0:0:0 | GSSA Variable __package__ | test.py:0:0:0:0 | GSSA Variable __package__ |
| test.py:0:0:0:0 | GSSA Variable b | test.py:0:0:0:0 | GSSA Variable b |

View File

@@ -1,5 +1,8 @@
import semmle.python.dataflow.new.DataFlow
from DataFlow::Node fromNode, DataFlow::Node toNode
where DataFlow::localFlow(fromNode, toNode)
where
DataFlow::localFlow(fromNode, toNode) and
exists(fromNode.getLocation().getFile().getRelativePath()) and
exists(toNode.getLocation().getFile().getRelativePath())
select fromNode, toNode

View File

@@ -1,5 +1,3 @@
| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed |
| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id |
| test.py:1:5:1:17 | GSSA Variable obfuscated_id | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id |
| test.py:1:19:1:19 | ControlFlowNode for x | test.py:1:19:1:19 | SSA variable x |

View File

@@ -1,5 +1,8 @@
import semmle.python.dataflow.new.DataFlow
from DataFlow::Node fromNode, DataFlow::Node toNode
where DataFlow::localFlowStep(fromNode, toNode)
where
DataFlow::localFlowStep(fromNode, toNode) and
exists(fromNode.getLocation().getFile().getRelativePath()) and
exists(toNode.getLocation().getFile().getRelativePath())
select fromNode, toNode

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