mirror of
https://github.com/github/codeql.git
synced 2026-07-05 11:35:30 +02:00
Compare commits
106 Commits
codeql-cli
...
remove-jav
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee314a4dad | ||
|
|
8dcf7926de | ||
|
|
d09c3bf863 | ||
|
|
1a92fa5d92 | ||
|
|
8d2ad4ed17 | ||
|
|
5f659f6e48 | ||
|
|
ee46717c76 | ||
|
|
914e621d1b | ||
|
|
976190e84d | ||
|
|
06eb93da3f | ||
|
|
7197f41e75 | ||
|
|
5488872044 | ||
|
|
413ac4e8f4 | ||
|
|
cec6cd0830 | ||
|
|
39a12a8464 | ||
|
|
46eb27cd01 | ||
|
|
ba98c0c1cb | ||
|
|
fc8b439263 | ||
|
|
a358ea8667 | ||
|
|
c294b75f6c | ||
|
|
d5e17f9ebf | ||
|
|
c7ea7ca5cd | ||
|
|
49c656d904 | ||
|
|
79549c2285 | ||
|
|
787f36f056 | ||
|
|
b7b229d59b | ||
|
|
64fcbe05c3 | ||
|
|
31c34870ef | ||
|
|
3c17ac424d | ||
|
|
bb6c079e5a | ||
|
|
a3c1975a84 | ||
|
|
bdd78d2bc7 | ||
|
|
29db42c3cd | ||
|
|
e6df8164cf | ||
|
|
cf03bd8bd1 | ||
|
|
342c14887b | ||
|
|
e1101e582e | ||
|
|
768203bd36 | ||
|
|
c51fb00082 | ||
|
|
0a92b04c8b | ||
|
|
15161d8867 | ||
|
|
53ee465726 | ||
|
|
a20acfee25 | ||
|
|
f69787afd0 | ||
|
|
9b12980688 | ||
|
|
cb0f82c36e | ||
|
|
3b678bfbc5 | ||
|
|
e1750adc38 | ||
|
|
fd0fb9483e | ||
|
|
3d1d491e6b | ||
|
|
18020707b8 | ||
|
|
cfa0d46b73 | ||
|
|
e027d514f1 | ||
|
|
d5f675c2dc | ||
|
|
78c12dc505 | ||
|
|
ad08ccb50b | ||
|
|
95751fcc21 | ||
|
|
13417dbf14 | ||
|
|
ff21662b23 | ||
|
|
6967b06dee | ||
|
|
fc58ada92e | ||
|
|
108118afa3 | ||
|
|
d8bb5273e7 | ||
|
|
c792567904 | ||
|
|
6d9a88d1c8 | ||
|
|
3520fed752 | ||
|
|
d10dbbdd9d | ||
|
|
6bf1e87bbe | ||
|
|
91f46624b6 | ||
|
|
94f32d2985 | ||
|
|
569426b04e | ||
|
|
b0852f6c16 | ||
|
|
b985ddb868 | ||
|
|
079769ed2e | ||
|
|
fc6af0476f | ||
|
|
03bd7d7f96 | ||
|
|
92ffd8c465 | ||
|
|
b0836a620c | ||
|
|
c977cfe40a | ||
|
|
e0921ac983 | ||
|
|
7e7dfe2cc4 | ||
|
|
91a8b9fdd9 | ||
|
|
1adc5c2a5b | ||
|
|
e664711f47 | ||
|
|
23e4ad1abb | ||
|
|
854f2a046a | ||
|
|
70e1724463 | ||
|
|
cbdabe35de | ||
|
|
032ac50034 | ||
|
|
3e5f7d0db5 | ||
|
|
b08eabec68 | ||
|
|
a4a9e2aa96 | ||
|
|
4841c3037d | ||
|
|
99881db8bd | ||
|
|
0c1f3ed0b3 | ||
|
|
a811ab3aff | ||
|
|
7383988988 | ||
|
|
e906ded0d1 | ||
|
|
c36292bfd0 | ||
|
|
05d83e487d | ||
|
|
3f5ab60fb4 | ||
|
|
8e9ac18026 | ||
|
|
1d76578202 | ||
|
|
2c93bce9ad | ||
|
|
3b3350e648 | ||
|
|
32b3e416b3 |
@@ -4,8 +4,8 @@ This open source repository contains the standard CodeQL libraries and queries t
|
|||||||
|
|
||||||
## How do I learn CodeQL and run queries?
|
## How do I learn CodeQL and run queries?
|
||||||
|
|
||||||
There is [extensive documentation](https://help.semmle.com/QL/learn-ql/) on getting started with writing CodeQL.
|
There is [extensive documentation](https://codeql.github.com/docs/) on getting started with writing CodeQL.
|
||||||
You can use the [interactive query console](https://lgtm.com/help/lgtm/using-query-console) on LGTM.com or the [CodeQL for Visual Studio Code](https://help.semmle.com/codeql/codeql-for-vscode.html) extension to try out your queries on any open source project that's currently being analyzed.
|
You can use the [interactive query console](https://lgtm.com/help/lgtm/using-query-console) on LGTM.com or the [CodeQL for Visual Studio Code](https://codeql.github.com/docs/codeql-for-visual-studio-code/) extension to try out your queries on any open source project that's currently being analyzed.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
|||||||
3
cpp/change-notes/2021-09-27-overflow-static.md
Normal file
3
cpp/change-notes/2021-09-27-overflow-static.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
lgtm,codescanning
|
||||||
|
* Increase precision to high for the "Static buffer overflow" query
|
||||||
|
(`cpp/static-buffer-overflow`). This means the query is run and displayed by default on Code Scanning and LGTM.
|
||||||
@@ -10,44 +10,11 @@ import semmle.code.cpp.dataflow.DataFlow
|
|||||||
* char data[1]; // v
|
* char data[1]; // v
|
||||||
* };
|
* };
|
||||||
* ```
|
* ```
|
||||||
* This requires that `v` is an array of size 0 or 1, and `v` is the last member of `c`.
|
* This requires that `v` is an array of size 0 or 1.
|
||||||
* In addition, if the size of the structure is taken, there must be at least one instance
|
|
||||||
* where a `c` pointer is allocated with additional space.
|
|
||||||
* For example, holds for `c` if it occurs as
|
|
||||||
* ```
|
|
||||||
* malloc(sizeof(c) + 100 * sizeof(char))
|
|
||||||
* ```
|
|
||||||
* but not if it only ever occurs as
|
|
||||||
* ```
|
|
||||||
* malloc(sizeof(c))
|
|
||||||
* ```
|
|
||||||
*/
|
*/
|
||||||
predicate memberMayBeVarSize(Class c, MemberVariable v) {
|
predicate memberMayBeVarSize(Class c, MemberVariable v) {
|
||||||
exists(int i |
|
c = v.getDeclaringType() and
|
||||||
// `v` is the last field in `c`
|
v.getUnspecifiedType().(ArrayType).getArraySize() <= 1
|
||||||
i = max(int j | c.getCanonicalMember(j) instanceof Field | j) and
|
|
||||||
v = c.getCanonicalMember(i) and
|
|
||||||
// v is an array of size at most 1
|
|
||||||
v.getUnspecifiedType().(ArrayType).getArraySize() <= 1 and
|
|
||||||
not c instanceof Union
|
|
||||||
) and
|
|
||||||
// If the size is taken, then arithmetic is performed on the result at least once
|
|
||||||
(
|
|
||||||
// `sizeof(c)` is not taken
|
|
||||||
not exists(SizeofOperator so |
|
|
||||||
so.(SizeofTypeOperator).getTypeOperand().getUnspecifiedType() = c or
|
|
||||||
so.(SizeofExprOperator).getExprOperand().getUnspecifiedType() = c
|
|
||||||
)
|
|
||||||
or
|
|
||||||
// or `sizeof(c)` is taken
|
|
||||||
exists(SizeofOperator so |
|
|
||||||
so.(SizeofTypeOperator).getTypeOperand().getUnspecifiedType() = c or
|
|
||||||
so.(SizeofExprOperator).getExprOperand().getUnspecifiedType() = c
|
|
||||||
|
|
|
||||||
// and arithmetic is performed on the result
|
|
||||||
so.getParent*() instanceof AddExpr
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,10 +27,6 @@ int getBufferSize(Expr bufferExpr, Element why) {
|
|||||||
result = bufferVar.getUnspecifiedType().(ArrayType).getSize() and
|
result = bufferVar.getUnspecifiedType().(ArrayType).getSize() and
|
||||||
why = bufferVar and
|
why = bufferVar and
|
||||||
not memberMayBeVarSize(_, bufferVar) and
|
not memberMayBeVarSize(_, bufferVar) and
|
||||||
not exists(Union bufferType |
|
|
||||||
bufferType.getAMemberVariable() = why and
|
|
||||||
bufferVar.getUnspecifiedType().(ArrayType).getSize() <= 1
|
|
||||||
) and
|
|
||||||
not result = 0 // zero sized arrays are likely to have special usage, for example
|
not result = 0 // zero sized arrays are likely to have special usage, for example
|
||||||
or
|
or
|
||||||
// behaving a bit like a 'union' overlapping other fields.
|
// behaving a bit like a 'union' overlapping other fields.
|
||||||
@@ -85,13 +48,6 @@ int getBufferSize(Expr bufferExpr, Element why) {
|
|||||||
parentPtr.getTarget().getUnspecifiedType().(PointerType).getBaseType() = parentClass and
|
parentPtr.getTarget().getUnspecifiedType().(PointerType).getBaseType() = parentClass and
|
||||||
result = getBufferSize(parentPtr, _) + bufferVar.getType().getSize() - parentClass.getSize()
|
result = getBufferSize(parentPtr, _) + bufferVar.getType().getSize() - parentClass.getSize()
|
||||||
)
|
)
|
||||||
or
|
|
||||||
exists(Union bufferType |
|
|
||||||
bufferType.getAMemberVariable() = why and
|
|
||||||
why = bufferVar and
|
|
||||||
bufferVar.getUnspecifiedType().(ArrayType).getSize() <= 1 and
|
|
||||||
result = bufferType.getSize()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// buffer is a fixed size dynamic allocation
|
// buffer is a fixed size dynamic allocation
|
||||||
|
|||||||
@@ -93,6 +93,15 @@ predicate variableMustBeNullTerminated(VariableAccess va) {
|
|||||||
fc.getArgument(i) = va
|
fc.getArgument(i) = va
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
|
// String argument to a formatting function (such as `printf`)
|
||||||
|
exists(int n, FormatLiteral fl |
|
||||||
|
fc.(FormattingFunctionCall).getConversionArgument(n) = va and
|
||||||
|
fl = fc.(FormattingFunctionCall).getFormat() and
|
||||||
|
fl.getConversionType(n) instanceof PointerType and // `%s`, `%ws` etc
|
||||||
|
not fl.getConversionType(n) instanceof VoidPointerType and // exclude: `%p`
|
||||||
|
not fl.hasPrecision(n) // exclude: `%.*s`
|
||||||
|
)
|
||||||
|
or
|
||||||
// Call to a wrapper function that requires null termination
|
// Call to a wrapper function that requires null termination
|
||||||
// (not itself adding a null terminator)
|
// (not itself adding a null terminator)
|
||||||
exists(Function wrapper, int i, Parameter p, VariableAccess use |
|
exists(Function wrapper, int i, Parameter p, VariableAccess use |
|
||||||
|
|||||||
@@ -29,8 +29,7 @@ predicate nanExcludingComparison(ComparisonOperation guard, boolean polarity) {
|
|||||||
*/
|
*/
|
||||||
private predicate excludesNan(RangeSsaDefinition def, VariableAccess v) {
|
private predicate excludesNan(RangeSsaDefinition def, VariableAccess v) {
|
||||||
exists(VariableAccess inCond, ComparisonOperation guard, boolean branch, StackVariable lsv |
|
exists(VariableAccess inCond, ComparisonOperation guard, boolean branch, StackVariable lsv |
|
||||||
def.isGuardPhi(inCond, guard, branch) and
|
def.isGuardPhi(lsv, inCond, guard, branch) and
|
||||||
inCond.getTarget() = lsv and
|
|
||||||
v = def.getAUse(lsv) and
|
v = def.getAUse(lsv) and
|
||||||
guard.getAnOperand() = inCond and
|
guard.getAnOperand() = inCond and
|
||||||
nanExcludingComparison(guard, branch)
|
nanExcludingComparison(guard, branch)
|
||||||
|
|||||||
@@ -94,10 +94,11 @@ class RangeSsaDefinition extends ControlFlowNodeBase {
|
|||||||
predicate isPhiNode(StackVariable v) { exists(RangeSSA x | x.phi_node(v, this.(BasicBlock))) }
|
predicate isPhiNode(StackVariable v) { exists(RangeSSA x | x.phi_node(v, this.(BasicBlock))) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* DEPRECATED: Use isGuardPhi/4 instead
|
||||||
* If this definition is a phi node corresponding to a guard,
|
* If this definition is a phi node corresponding to a guard,
|
||||||
* then return the variable access and the guard.
|
* then return the variable access and the guard.
|
||||||
*/
|
*/
|
||||||
predicate isGuardPhi(VariableAccess va, Expr guard, boolean branch) {
|
deprecated predicate isGuardPhi(VariableAccess va, Expr guard, boolean branch) {
|
||||||
guard_defn(va, guard, this, branch)
|
guard_defn(va, guard, this, branch)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,9 +143,8 @@ class RangeSsaDefinition extends ControlFlowNodeBase {
|
|||||||
// below excludes definitions which can only reach guard phi
|
// below excludes definitions which can only reach guard phi
|
||||||
// nodes by going through the corresponding guard.
|
// nodes by going through the corresponding guard.
|
||||||
not exists(VariableAccess access |
|
not exists(VariableAccess access |
|
||||||
v = access.getTarget() and
|
|
||||||
pred.contains(access) and
|
pred.contains(access) and
|
||||||
this.isGuardPhi(access, _, _)
|
this.isGuardPhi(v, access, _, _)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -433,10 +433,7 @@ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVaria
|
|||||||
private predicate phiDependsOnDef(
|
private predicate phiDependsOnDef(
|
||||||
RangeSsaDefinition phi, StackVariable v, RangeSsaDefinition srcDef, StackVariable srcVar
|
RangeSsaDefinition phi, StackVariable v, RangeSsaDefinition srcDef, StackVariable srcVar
|
||||||
) {
|
) {
|
||||||
exists(VariableAccess access, Expr guard |
|
exists(VariableAccess access, Expr guard | phi.isGuardPhi(v, access, guard, _) |
|
||||||
access = v.getAnAccess() and
|
|
||||||
phi.isGuardPhi(access, guard, _)
|
|
||||||
|
|
|
||||||
exprDependsOnDef(guard.(ComparisonOperation).getAnOperand(), srcDef, srcVar) or
|
exprDependsOnDef(guard.(ComparisonOperation).getAnOperand(), srcDef, srcVar) or
|
||||||
exprDependsOnDef(access, srcDef, srcVar)
|
exprDependsOnDef(access, srcDef, srcVar)
|
||||||
)
|
)
|
||||||
@@ -1204,8 +1201,7 @@ private float boolConversionUpperBound(Expr expr) {
|
|||||||
*/
|
*/
|
||||||
private float getPhiLowerBounds(StackVariable v, RangeSsaDefinition phi) {
|
private float getPhiLowerBounds(StackVariable v, RangeSsaDefinition phi) {
|
||||||
exists(VariableAccess access, Expr guard, boolean branch, float defLB, float guardLB |
|
exists(VariableAccess access, Expr guard, boolean branch, float defLB, float guardLB |
|
||||||
access = v.getAnAccess() and
|
phi.isGuardPhi(v, access, guard, branch) and
|
||||||
phi.isGuardPhi(access, guard, branch) and
|
|
||||||
lowerBoundFromGuard(guard, access, guardLB, branch) and
|
lowerBoundFromGuard(guard, access, guardLB, branch) and
|
||||||
defLB = getFullyConvertedLowerBounds(access)
|
defLB = getFullyConvertedLowerBounds(access)
|
||||||
|
|
|
|
||||||
@@ -1230,8 +1226,7 @@ private float getPhiLowerBounds(StackVariable v, RangeSsaDefinition phi) {
|
|||||||
/** See comment for `getPhiLowerBounds`, above. */
|
/** See comment for `getPhiLowerBounds`, above. */
|
||||||
private float getPhiUpperBounds(StackVariable v, RangeSsaDefinition phi) {
|
private float getPhiUpperBounds(StackVariable v, RangeSsaDefinition phi) {
|
||||||
exists(VariableAccess access, Expr guard, boolean branch, float defUB, float guardUB |
|
exists(VariableAccess access, Expr guard, boolean branch, float defUB, float guardUB |
|
||||||
access = v.getAnAccess() and
|
phi.isGuardPhi(v, access, guard, branch) and
|
||||||
phi.isGuardPhi(access, guard, branch) and
|
|
||||||
upperBoundFromGuard(guard, access, guardUB, branch) and
|
upperBoundFromGuard(guard, access, guardUB, branch) and
|
||||||
defUB = getFullyConvertedUpperBounds(access)
|
defUB = getFullyConvertedUpperBounds(access)
|
||||||
|
|
|
|
||||||
@@ -1493,8 +1488,7 @@ private predicate isNEPhi(
|
|||||||
exists(
|
exists(
|
||||||
ComparisonOperation cmp, boolean branch, Expr linearExpr, Expr rExpr, float p, float q, float r
|
ComparisonOperation cmp, boolean branch, Expr linearExpr, Expr rExpr, float p, float q, float r
|
||||||
|
|
|
|
||||||
access.getTarget() = v and
|
phi.isGuardPhi(v, access, cmp, branch) and
|
||||||
phi.isGuardPhi(access, cmp, branch) and
|
|
||||||
eqOpWithSwapAndNegate(cmp, linearExpr, rExpr, false, branch) and
|
eqOpWithSwapAndNegate(cmp, linearExpr, rExpr, false, branch) and
|
||||||
v.getUnspecifiedType() instanceof IntegralOrEnumType and // Float `!=` is too imprecise
|
v.getUnspecifiedType() instanceof IntegralOrEnumType and // Float `!=` is too imprecise
|
||||||
r = getValue(rExpr).toFloat() and
|
r = getValue(rExpr).toFloat() and
|
||||||
@@ -1503,8 +1497,7 @@ private predicate isNEPhi(
|
|||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(Expr op, boolean branch, Expr linearExpr, float p, float q |
|
exists(Expr op, boolean branch, Expr linearExpr, float p, float q |
|
||||||
access.getTarget() = v and
|
phi.isGuardPhi(v, access, op, branch) and
|
||||||
phi.isGuardPhi(access, op, branch) and
|
|
||||||
eqZeroWithNegate(op, linearExpr, false, branch) and
|
eqZeroWithNegate(op, linearExpr, false, branch) and
|
||||||
v.getUnspecifiedType() instanceof IntegralOrEnumType and // Float `!` is too imprecise
|
v.getUnspecifiedType() instanceof IntegralOrEnumType and // Float `!` is too imprecise
|
||||||
linearAccess(linearExpr, access, p, q) and
|
linearAccess(linearExpr, access, p, q) and
|
||||||
@@ -1524,8 +1517,7 @@ private predicate isUnsupportedGuardPhi(Variable v, RangeSsaDefinition phi, Vari
|
|||||||
or
|
or
|
||||||
eqZeroWithNegate(cmp, _, false, branch)
|
eqZeroWithNegate(cmp, _, false, branch)
|
||||||
|
|
|
|
||||||
access.getTarget() = v and
|
phi.isGuardPhi(v, access, cmp, branch) and
|
||||||
phi.isGuardPhi(access, cmp, branch) and
|
|
||||||
not isNEPhi(v, phi, access, _)
|
not isNEPhi(v, phi, access, _)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1594,6 +1586,15 @@ private module SimpleRangeAnalysisCached {
|
|||||||
result = min([max(getTruncatedUpperBounds(expr)), getGuardedUpperBound(expr)])
|
result = min([max(getTruncatedUpperBounds(expr)), getGuardedUpperBound(expr)])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Holds if the upper bound of `expr` may have been widened. This means the the upper bound is in practice likely to be overly wide. */
|
||||||
|
cached
|
||||||
|
predicate upperBoundMayBeWidened(Expr e) {
|
||||||
|
isRecursiveExpr(e) and
|
||||||
|
// Widening is not a problem if the post-analysis in `getGuardedUpperBound` has overridden the widening.
|
||||||
|
// Note that the RHS of `<` may be multi-valued.
|
||||||
|
not getGuardedUpperBound(e) < getTruncatedUpperBounds(e)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if `expr` has a provably empty range. For example:
|
* Holds if `expr` has a provably empty range. For example:
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* @kind problem
|
* @kind problem
|
||||||
* @problem.severity warning
|
* @problem.severity warning
|
||||||
* @security-severity 9.3
|
* @security-severity 9.3
|
||||||
* @precision medium
|
* @precision high
|
||||||
* @id cpp/static-buffer-overflow
|
* @id cpp/static-buffer-overflow
|
||||||
* @tags reliability
|
* @tags reliability
|
||||||
* security
|
* security
|
||||||
@@ -55,6 +55,8 @@ predicate overflowOffsetInLoop(BufferAccess bufaccess, string msg) {
|
|||||||
loop.counter().getAnAccess() = bufaccess.getArrayOffset() and
|
loop.counter().getAnAccess() = bufaccess.getArrayOffset() and
|
||||||
// Ensure that we don't have an upper bound on the array index that's less than the buffer size.
|
// Ensure that we don't have an upper bound on the array index that's less than the buffer size.
|
||||||
not upperBound(bufaccess.getArrayOffset().getFullyConverted()) < bufaccess.bufferSize() and
|
not upperBound(bufaccess.getArrayOffset().getFullyConverted()) < bufaccess.bufferSize() and
|
||||||
|
// The upper bounds analysis must not have been widended
|
||||||
|
not upperBoundMayBeWidened(bufaccess.getArrayOffset().getFullyConverted()) and
|
||||||
msg =
|
msg =
|
||||||
"Potential buffer-overflow: counter '" + loop.counter().toString() + "' <= " +
|
"Potential buffer-overflow: counter '" + loop.counter().toString() + "' <= " +
|
||||||
loop.limit().toString() + " but '" + bufaccess.buffer().getName() + "' has " +
|
loop.limit().toString() + " but '" + bufaccess.buffer().getName() + "' has " +
|
||||||
@@ -130,11 +132,13 @@ predicate outOfBounds(BufferAccess bufaccess, string msg) {
|
|||||||
(
|
(
|
||||||
access > size
|
access > size
|
||||||
or
|
or
|
||||||
access = size and not exists(AddressOfExpr addof | bufaccess = addof.getOperand())
|
access = size and
|
||||||
|
not exists(AddressOfExpr addof | bufaccess = addof.getOperand()) and
|
||||||
|
not exists(BuiltInOperationBuiltInOffsetOf offsetof | offsetof.getAChild() = bufaccess)
|
||||||
) and
|
) and
|
||||||
msg =
|
msg =
|
||||||
"Potential buffer-overflow: '" + buf + "' has size " + size.toString() + " but '" + buf + "[" +
|
"Potential buffer-overflow: '" + buf + "' has size " + size.toString() + " but '" + buf + "[" +
|
||||||
access.toString() + "]' is accessed here."
|
access.toString() + "]' may be accessed here."
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,14 +5,10 @@
|
|||||||
| test2.c:33:26:33:27 | 46 | Potential buffer-overflow: 'buffer' has size 40 not 46. |
|
| test2.c:33:26:33:27 | 46 | Potential buffer-overflow: 'buffer' has size 40 not 46. |
|
||||||
| test2.c:34:22:34:23 | 47 | Potential buffer-overflow: 'buffer' has size 40 not 47. |
|
| test2.c:34:22:34:23 | 47 | Potential buffer-overflow: 'buffer' has size 40 not 47. |
|
||||||
| test2.c:35:23:35:24 | 48 | Potential buffer-overflow: 'buffer' has size 40 not 48. |
|
| test2.c:35:23:35:24 | 48 | Potential buffer-overflow: 'buffer' has size 40 not 48. |
|
||||||
| test.c:14:9:14:13 | access to array | Potential buffer-overflow: 'xs' has size 5 but 'xs[5]' is accessed here. |
|
| test.c:14:9:14:13 | access to array | Potential buffer-overflow: 'xs' has size 5 but 'xs[5]' may be accessed here. |
|
||||||
| test.c:15:9:15:13 | access to array | Potential buffer-overflow: 'xs' has size 5 but 'xs[6]' is accessed here. |
|
| test.c:15:9:15:13 | access to array | Potential buffer-overflow: 'xs' has size 5 but 'xs[6]' may be accessed here. |
|
||||||
| test.c:20:9:20:18 | access to array | Potential buffer-overflow: 'ys' has size 5 but 'ys[5]' is accessed here. |
|
| test.c:20:9:20:18 | access to array | Potential buffer-overflow: 'ys' has size 5 but 'ys[5]' may be accessed here. |
|
||||||
| test.c:21:9:21:18 | access to array | Potential buffer-overflow: 'ys' has size 5 but 'ys[6]' is accessed here. |
|
| test.c:21:9:21:18 | access to array | Potential buffer-overflow: 'ys' has size 5 but 'ys[6]' may be accessed here. |
|
||||||
| test.c:47:3:47:18 | access to array | Potential buffer-overflow: 'ptr' has size 8 but 'ptr[8]' is accessed here. |
|
|
||||||
| test.c:54:3:54:26 | access to array | Potential buffer-overflow: 'ptr' has size 8 but 'ptr[8]' is accessed here. |
|
|
||||||
| test.c:61:3:61:18 | access to array | Potential buffer-overflow: 'ptr' has size 8 but 'ptr[8]' is accessed here. |
|
|
||||||
| test.c:72:3:72:11 | access to array | Potential buffer-overflow: 'buf' has size 1 but 'buf[1]' is accessed here. |
|
|
||||||
| test.cpp:19:3:19:12 | access to array | Potential buffer-overflow: counter 'i' <= 3 but 'buffer1' has 3 elements. |
|
| test.cpp:19:3:19:12 | access to array | Potential buffer-overflow: counter 'i' <= 3 but 'buffer1' has 3 elements. |
|
||||||
| test.cpp:20:3:20:12 | access to array | Potential buffer-overflow: counter 'i' <= 3 but 'buffer2' has 3 elements. |
|
| test.cpp:20:3:20:12 | access to array | Potential buffer-overflow: counter 'i' <= 3 but 'buffer2' has 3 elements. |
|
||||||
| test.cpp:24:27:24:27 | 4 | Potential buffer-overflow: 'buffer1' has size 3 not 4. |
|
| test.cpp:24:27:24:27 | 4 | Potential buffer-overflow: 'buffer1' has size 3 not 4. |
|
||||||
|
|||||||
@@ -44,21 +44,21 @@ void union_test() {
|
|||||||
union u u;
|
union u u;
|
||||||
u.ptr[0] = 0; // GOOD
|
u.ptr[0] = 0; // GOOD
|
||||||
u.ptr[sizeof(u)-1] = 0; // GOOD
|
u.ptr[sizeof(u)-1] = 0; // GOOD
|
||||||
u.ptr[sizeof(u)] = 0; // BAD
|
u.ptr[sizeof(u)] = 0; // BAD [NOT DETECTED]
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_struct_union() {
|
void test_struct_union() {
|
||||||
struct { union u u; } v;
|
struct { union u u; } v;
|
||||||
v.u.ptr[0] = 0; // GOOD
|
v.u.ptr[0] = 0; // GOOD
|
||||||
v.u.ptr[sizeof(union u)-1] = 0; // GOOD
|
v.u.ptr[sizeof(union u)-1] = 0; // GOOD
|
||||||
v.u.ptr[sizeof(union u)] = 0; // BAD
|
v.u.ptr[sizeof(union u)] = 0; // BAD [NOT DETECTED]
|
||||||
}
|
}
|
||||||
|
|
||||||
void union_test2() {
|
void union_test2() {
|
||||||
union { char ptr[1]; unsigned long value; } u;
|
union { char ptr[1]; unsigned long value; } u;
|
||||||
u.ptr[0] = 0; // GOOD
|
u.ptr[0] = 0; // GOOD
|
||||||
u.ptr[sizeof(u)-1] = 0; // GOOD
|
u.ptr[sizeof(u)-1] = 0; // GOOD
|
||||||
u.ptr[sizeof(u)] = 0; // BAD
|
u.ptr[sizeof(u)] = 0; // BAD [NOT DETECTED]
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -69,5 +69,5 @@ typedef struct {
|
|||||||
void test_alloc() {
|
void test_alloc() {
|
||||||
// Special case of taking sizeof without any addition or multiplications
|
// Special case of taking sizeof without any addition or multiplications
|
||||||
var_buf *b = malloc(sizeof(var_buf));
|
var_buf *b = malloc(sizeof(var_buf));
|
||||||
b->buf[1] = 0; // BAD
|
b->buf[1] = 0; // BAD [NOT DETECTED]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,3 +23,5 @@
|
|||||||
| test.cpp:365:19:365:25 | buffer2 | Variable $@ may not be null terminated. | test.cpp:363:8:363:14 | buffer2 | buffer2 |
|
| test.cpp:365:19:365:25 | buffer2 | Variable $@ may not be null terminated. | test.cpp:363:8:363:14 | buffer2 | buffer2 |
|
||||||
| test.cpp:392:17:392:22 | buffer | Variable $@ may not be null terminated. | test.cpp:390:8:390:13 | buffer | buffer |
|
| test.cpp:392:17:392:22 | buffer | Variable $@ may not be null terminated. | test.cpp:390:8:390:13 | buffer | buffer |
|
||||||
| test.cpp:398:18:398:23 | buffer | Variable $@ may not be null terminated. | test.cpp:396:8:396:13 | buffer | buffer |
|
| test.cpp:398:18:398:23 | buffer | Variable $@ may not be null terminated. | test.cpp:396:8:396:13 | buffer | buffer |
|
||||||
|
| test.cpp:444:10:444:15 | buffer | Variable $@ may not be null terminated. | test.cpp:442:8:442:13 | buffer | buffer |
|
||||||
|
| test.cpp:450:16:450:21 | buffer | Variable $@ may not be null terminated. | test.cpp:448:8:448:13 | buffer | buffer |
|
||||||
|
|||||||
@@ -433,3 +433,36 @@ void test_read_fread(int read_src, FILE *s)
|
|||||||
strlen(buffer); // GOOD
|
strlen(buffer); // GOOD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int printf(const char *format, ...);
|
||||||
|
|
||||||
|
void test_printf(char *str)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
char buffer[1024];
|
||||||
|
|
||||||
|
printf(buffer, ""); // BAD
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char buffer[1024];
|
||||||
|
|
||||||
|
printf("%s", buffer); // BAD
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t len = strlen(str);
|
||||||
|
char *copied_str = (char *)malloc(len);
|
||||||
|
|
||||||
|
memcpy(copied_str, str, len);
|
||||||
|
printf("%s", copied_str); // BAD [NOT DETECTED]
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t len = strlen(str);
|
||||||
|
char *copied_str = (char *)malloc(len + 1);
|
||||||
|
|
||||||
|
memcpy(copied_str, str, len + 1);
|
||||||
|
printf("%s", copied_str); // GOOD
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -72,12 +72,9 @@
|
|||||||
| unions.cpp:30:2:30:7 | call to memset | This 'memset' operation accesses 200 bytes but the $@ is only 100 bytes. | unions.cpp:15:7:15:11 | small | destination buffer |
|
| unions.cpp:30:2:30:7 | call to memset | This 'memset' operation accesses 200 bytes but the $@ is only 100 bytes. | unions.cpp:15:7:15:11 | small | destination buffer |
|
||||||
| unions.cpp:34:2:34:7 | call to memset | This 'memset' operation accesses 200 bytes but the $@ is only 100 bytes. | unions.cpp:16:7:16:11 | large | destination buffer |
|
| unions.cpp:34:2:34:7 | call to memset | This 'memset' operation accesses 200 bytes but the $@ is only 100 bytes. | unions.cpp:16:7:16:11 | large | destination buffer |
|
||||||
| unions.cpp:34:2:34:7 | call to memset | This 'memset' operation accesses 200 bytes but the $@ is only 100 bytes. | unions.cpp:34:14:34:18 | large | destination buffer |
|
| unions.cpp:34:2:34:7 | call to memset | This 'memset' operation accesses 200 bytes but the $@ is only 100 bytes. | unions.cpp:34:14:34:18 | large | destination buffer |
|
||||||
| var_size_struct.cpp:54:5:54:14 | access to array | This array indexing operation accesses byte offset 1 but the $@ is only 1 byte. | var_size_struct.cpp:32:8:32:10 | str | array |
|
|
||||||
| var_size_struct.cpp:55:5:55:14 | access to array | This array indexing operation accesses byte offset 1 but the $@ is only 1 byte. | var_size_struct.cpp:38:8:38:10 | str | array |
|
|
||||||
| var_size_struct.cpp:71:3:71:8 | call to memset | This 'memset' operation accesses 1025 bytes but the $@ is only 1024 bytes. | var_size_struct.cpp:63:8:63:11 | data | destination buffer |
|
| var_size_struct.cpp:71:3:71:8 | call to memset | This 'memset' operation accesses 1025 bytes but the $@ is only 1024 bytes. | var_size_struct.cpp:63:8:63:11 | data | destination buffer |
|
||||||
| var_size_struct.cpp:73:3:73:9 | call to strncpy | This 'strncpy' operation may access 1025 bytes but the $@ is only 1024 bytes. | var_size_struct.cpp:63:8:63:11 | data | destination buffer |
|
| var_size_struct.cpp:73:3:73:9 | call to strncpy | This 'strncpy' operation may access 1025 bytes but the $@ is only 1024 bytes. | var_size_struct.cpp:63:8:63:11 | data | destination buffer |
|
||||||
| var_size_struct.cpp:87:3:87:19 | access to array | This array indexing operation accesses byte offset 67 but the $@ is only 64 bytes. | var_size_struct.cpp:78:7:78:14 | elements | array |
|
| var_size_struct.cpp:87:3:87:19 | access to array | This array indexing operation accesses byte offset 67 but the $@ is only 64 bytes. | var_size_struct.cpp:78:7:78:14 | elements | array |
|
||||||
| var_size_struct.cpp:99:3:99:8 | call to memset | This 'memset' operation accesses 129 bytes but the $@ is only 128 bytes. | var_size_struct.cpp:92:8:92:10 | str | destination buffer |
|
| var_size_struct.cpp:99:3:99:8 | call to memset | This 'memset' operation accesses 129 bytes but the $@ is only 128 bytes. | var_size_struct.cpp:92:8:92:10 | str | destination buffer |
|
||||||
| var_size_struct.cpp:101:3:101:8 | call to memset | This 'memset' operation accesses 129 bytes but the $@ is only 128 bytes. | var_size_struct.cpp:92:8:92:10 | str | destination buffer |
|
| var_size_struct.cpp:101:3:101:8 | call to memset | This 'memset' operation accesses 129 bytes but the $@ is only 128 bytes. | var_size_struct.cpp:92:8:92:10 | str | destination buffer |
|
||||||
| var_size_struct.cpp:103:3:103:9 | call to strncpy | This 'strncpy' operation may access 129 bytes but the $@ is only 128 bytes. | var_size_struct.cpp:92:8:92:10 | str | destination buffer |
|
| var_size_struct.cpp:103:3:103:9 | call to strncpy | This 'strncpy' operation may access 129 bytes but the $@ is only 128 bytes. | var_size_struct.cpp:92:8:92:10 | str | destination buffer |
|
||||||
| var_size_struct.cpp:169:3:169:8 | call to memset | This 'memset' operation accesses 100 bytes but the $@ is only 1 byte. | var_size_struct.cpp:125:17:125:19 | arr | destination buffer |
|
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
| tests.cpp:163:3:163:11 | access to array | Potential buffer-overflow: counter 'k' <= 100 but 'buffer' has 100 elements. |
|
| tests.cpp:163:3:163:11 | access to array | Potential buffer-overflow: counter 'k' <= 100 but 'buffer' has 100 elements. |
|
||||||
| tests.cpp:164:8:164:16 | access to array | Potential buffer-overflow: counter 'k' <= 100 but 'buffer' has 100 elements. |
|
| tests.cpp:164:8:164:16 | access to array | Potential buffer-overflow: counter 'k' <= 100 but 'buffer' has 100 elements. |
|
||||||
| tests.cpp:245:42:245:42 | 6 | Potential buffer-overflow: 'global_array_5' has size 5 not 6. |
|
| tests.cpp:245:42:245:42 | 6 | Potential buffer-overflow: 'global_array_5' has size 5 not 6. |
|
||||||
| tests.cpp:349:2:349:14 | access to array | Potential buffer-overflow: 'charArray' has size 10 but 'charArray[10]' is accessed here. |
|
| tests.cpp:349:2:349:14 | access to array | Potential buffer-overflow: 'charArray' has size 10 but 'charArray[10]' may be accessed here. |
|
||||||
| tests.cpp:350:17:350:29 | access to array | Potential buffer-overflow: 'charArray' has size 10 but 'charArray[10]' is accessed here. |
|
| tests.cpp:350:17:350:29 | access to array | Potential buffer-overflow: 'charArray' has size 10 but 'charArray[10]' may be accessed here. |
|
||||||
| var_size_struct.cpp:54:5:54:14 | access to array | Potential buffer-overflow: 'str' has size 1 but 'str[1]' is accessed here. |
|
|
||||||
| var_size_struct.cpp:55:5:55:14 | access to array | Potential buffer-overflow: 'str' has size 1 but 'str[1]' is accessed here. |
|
|
||||||
| var_size_struct.cpp:103:39:103:41 | 129 | Potential buffer-overflow: 'str' has size 128 not 129. |
|
| var_size_struct.cpp:103:39:103:41 | 129 | Potential buffer-overflow: 'str' has size 128 not 129. |
|
||||||
|
|||||||
@@ -51,8 +51,8 @@ void testVarString(int n) {
|
|||||||
s1->str[1] = '?'; // GOOD
|
s1->str[1] = '?'; // GOOD
|
||||||
s2->str[1] = '?'; // GOOD
|
s2->str[1] = '?'; // GOOD
|
||||||
s3->str[1] = '?'; // GOOD
|
s3->str[1] = '?'; // GOOD
|
||||||
s4->str[1] = '?'; // BAD
|
s4->str[1] = '?'; // BAD [NOT DETECTED]
|
||||||
s5->str[1] = '?'; // BAD
|
s5->str[1] = '?'; // BAD [NOT DETECTED]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +166,7 @@ void useVarStruct34(varStruct5 *vs5) {
|
|||||||
|
|
||||||
void testVarStruct34(varStruct3 *vs3, varStruct4 *vs4, varStruct5 *vs5, varStruct6 *vs6, varStruct7 *vs7, varStruct8 *vs8, varStruct9 *vs9) {
|
void testVarStruct34(varStruct3 *vs3, varStruct4 *vs4, varStruct5 *vs5, varStruct6 *vs6, varStruct7 *vs7, varStruct8 *vs8, varStruct9 *vs9) {
|
||||||
memset(vs3->arr, 'x', 100); // GOOD: it's variable size, we don't know how big so shouldn't flag
|
memset(vs3->arr, 'x', 100); // GOOD: it's variable size, we don't know how big so shouldn't flag
|
||||||
memset(vs4->arr, 'x', 100); // BAD: it's not variable size, so this is a buffer overflow
|
memset(vs4->arr, 'x', 100); // BAD: [NOT DETECTED] it's not variable size, so this is a buffer overflow
|
||||||
memset(vs5->arr, 'x', 100); // GOOD: it's variable size, we don't know how big so shouldn't flag
|
memset(vs5->arr, 'x', 100); // GOOD: it's variable size, we don't know how big so shouldn't flag
|
||||||
memset(vs6->arr, 'x', 100); // GOOD: it's variable size, we don't know how big so shouldn't flag
|
memset(vs6->arr, 'x', 100); // GOOD: it's variable size, we don't know how big so shouldn't flag
|
||||||
memset(vs7->arr, 'x', 100); // GOOD: it's variable size, we don't know how big so shouldn't flag
|
memset(vs7->arr, 'x', 100); // GOOD: it's variable size, we don't know how big so shouldn't flag
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
| var_size_struct.cpp:13:8:13:17 | VarString1 | var_size_struct.cpp:15:8:15:10 | str |
|
| var_size_struct.cpp:13:8:13:17 | VarString1 | var_size_struct.cpp:15:8:15:10 | str |
|
||||||
| var_size_struct.cpp:18:8:18:17 | VarString2 | var_size_struct.cpp:20:8:20:10 | str |
|
| var_size_struct.cpp:18:8:18:17 | VarString2 | var_size_struct.cpp:20:8:20:10 | str |
|
||||||
| var_size_struct.cpp:24:8:24:17 | VarString3 | var_size_struct.cpp:26:8:26:10 | str |
|
| var_size_struct.cpp:24:8:24:17 | VarString3 | var_size_struct.cpp:26:8:26:10 | str |
|
||||||
|
| var_size_struct.cpp:30:8:30:17 | VarString4 | var_size_struct.cpp:32:8:32:10 | str |
|
||||||
|
| var_size_struct.cpp:36:8:36:17 | VarString5 | var_size_struct.cpp:38:8:38:10 | str |
|
||||||
| var_size_struct.cpp:36:8:36:17 | VarString5 | var_size_struct.cpp:39:8:39:11 | str2 |
|
| var_size_struct.cpp:36:8:36:17 | VarString5 | var_size_struct.cpp:39:8:39:11 | str2 |
|
||||||
| var_size_struct.cpp:61:8:61:17 | varStruct1 | var_size_struct.cpp:63:8:63:11 | data |
|
| var_size_struct.cpp:61:8:61:17 | varStruct1 | var_size_struct.cpp:63:8:63:11 | data |
|
||||||
| var_size_struct.cpp:76:8:76:17 | varStruct2 | var_size_struct.cpp:78:7:78:14 | elements |
|
| var_size_struct.cpp:76:8:76:17 | varStruct2 | var_size_struct.cpp:78:7:78:14 | elements |
|
||||||
|
| var_size_struct.cpp:106:8:106:20 | notVarStruct2 | var_size_struct.cpp:107:8:107:10 | str |
|
||||||
| var_size_struct.cpp:119:8:119:17 | varStruct3 | var_size_struct.cpp:121:17:121:19 | arr |
|
| var_size_struct.cpp:119:8:119:17 | varStruct3 | var_size_struct.cpp:121:17:121:19 | arr |
|
||||||
|
| var_size_struct.cpp:123:8:123:17 | varStruct4 | var_size_struct.cpp:125:17:125:19 | arr |
|
||||||
| var_size_struct.cpp:127:8:127:17 | varStruct5 | var_size_struct.cpp:129:17:129:19 | arr |
|
| var_size_struct.cpp:127:8:127:17 | varStruct5 | var_size_struct.cpp:129:17:129:19 | arr |
|
||||||
| var_size_struct.cpp:131:8:131:17 | varStruct6 | var_size_struct.cpp:133:17:133:19 | arr |
|
| var_size_struct.cpp:131:8:131:17 | varStruct6 | var_size_struct.cpp:133:17:133:19 | arr |
|
||||||
| var_size_struct.cpp:135:8:135:17 | varStruct7 | var_size_struct.cpp:137:17:137:19 | arr |
|
| var_size_struct.cpp:135:8:135:17 | varStruct7 | var_size_struct.cpp:137:17:137:19 | arr |
|
||||||
| var_size_struct.cpp:139:8:139:17 | varStruct8 | var_size_struct.cpp:141:9:141:11 | arr |
|
| var_size_struct.cpp:139:8:139:17 | varStruct8 | var_size_struct.cpp:141:9:141:11 | arr |
|
||||||
| var_size_struct.cpp:143:8:143:17 | varStruct9 | var_size_struct.cpp:145:17:145:19 | arr |
|
| var_size_struct.cpp:143:8:143:17 | varStruct9 | var_size_struct.cpp:145:17:145:19 | arr |
|
||||||
|
| var_size_struct.cpp:181:8:181:18 | PseudoUnion | var_size_struct.cpp:183:7:183:10 | data |
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ The CodeQL documentation in this repository is written in reStructuredText and c
|
|||||||
HTML using Sphinx.
|
HTML using Sphinx.
|
||||||
|
|
||||||
For more information on writing in reStructuredText,
|
For more information on writing in reStructuredText,
|
||||||
see http://docutils.sourceforge.net/rst.html.
|
see https://docutils.sourceforge.io/rst.html.
|
||||||
|
|
||||||
For more information on Sphinx, see https://www.sphinx-doc.org.
|
For more information on Sphinx, see https://www.sphinx-doc.org.
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ generates html slide shows in the ``<slides-output>`` directory when run from
|
|||||||
the ``ql-training`` source directory.
|
the ``ql-training`` source directory.
|
||||||
|
|
||||||
For more information about creating slides for QL training and variant analysis
|
For more information about creating slides for QL training and variant analysis
|
||||||
examples, see the `template slide deck <https://github.com/github/codeql/blob/main/docs/language/ql-training/template.rst>`__.
|
examples, see the `template slide deck <https://github.com/github/codeql/blob/main/docs/codeql/ql-training/template.rst>`__.
|
||||||
|
|
||||||
Viewing the current version of the CodeQL documentation
|
Viewing the current version of the CodeQL documentation
|
||||||
*******************************************************
|
*******************************************************
|
||||||
|
|||||||
@@ -252,8 +252,6 @@ Miscellaneous
|
|||||||
+=====================================+====================+============================================================================+
|
+=====================================+====================+============================================================================+
|
||||||
| ``(int) f`` | CastExpr_ | |
|
| ``(int) f`` | CastExpr_ | |
|
||||||
+-------------------------------------+--------------------+----------------------------------------------------------------------------+
|
+-------------------------------------+--------------------+----------------------------------------------------------------------------+
|
||||||
| ``(23 + 42)`` | ParExpr_ | |
|
|
||||||
+-------------------------------------+--------------------+----------------------------------------------------------------------------+
|
|
||||||
| ``o instanceof String`` | InstanceOfExpr_ | |
|
| ``o instanceof String`` | InstanceOfExpr_ | |
|
||||||
+-------------------------------------+--------------------+----------------------------------------------------------------------------+
|
+-------------------------------------+--------------------+----------------------------------------------------------------------------+
|
||||||
| `Expr`_ ``?`` `Expr`_ ``:`` `Expr`_ | ConditionalExpr_ | |
|
| `Expr`_ ``?`` `Expr`_ ``:`` `Expr`_ | ConditionalExpr_ | |
|
||||||
@@ -378,7 +376,6 @@ Further reading
|
|||||||
.. _WildcardTypeAccess: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$WildcardTypeAccess.html
|
.. _WildcardTypeAccess: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$WildcardTypeAccess.html
|
||||||
.. _FieldAccess: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$FieldAccess.html
|
.. _FieldAccess: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$FieldAccess.html
|
||||||
.. _CastExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$CastExpr.html
|
.. _CastExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$CastExpr.html
|
||||||
.. _ParExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$ParExpr.html
|
|
||||||
.. _InstanceOfExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$InstanceOfExpr.html
|
.. _InstanceOfExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$InstanceOfExpr.html
|
||||||
.. _ConditionalExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$ConditionalExpr.html
|
.. _ConditionalExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$ConditionalExpr.html
|
||||||
.. _TypeLiteral: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$TypeLiteral.html
|
.. _TypeLiteral: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$TypeLiteral.html
|
||||||
|
|||||||
@@ -55,12 +55,12 @@ def setup(sphinx):
|
|||||||
sphinx.add_lexer("ql", QLLexer())
|
sphinx.add_lexer("ql", QLLexer())
|
||||||
|
|
||||||
# The version of CodeQL for the current release you're documenting, acts as replacement for
|
# The version of CodeQL for the current release you're documenting, acts as replacement for
|
||||||
# |version| and |release|
|
# |version| and |release|. Not currently used except in LGTM Enterprise support info.
|
||||||
|
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = u'3.0'
|
# version = u'3.0'
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = u'3.0'
|
# release = u'3.0'
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
|
|||||||
@@ -1325,7 +1325,7 @@ Set literals denote a choice from a collection of values.
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
setliteral ::= "[" expr ("," expr)* "]"
|
setliteral ::= "[" expr ("," expr)* ","? "]"
|
||||||
|
|
||||||
Set literals can be of any type, but the types within a set literal have to be consistent according to the following criterion: At least one of the set elements has to be of a type that is a supertype of all the set element types. This supertype is the type of the set literal. For example, ``float`` is a supertype of ``float`` and ``int``, therefore ``x = [4, 5.6]`` is valid. On the other hand, ``y = [5, "test"]`` does not adhere to the criterion.
|
Set literals can be of any type, but the types within a set literal have to be consistent according to the following criterion: At least one of the set elements has to be of a type that is a supertype of all the set element types. This supertype is the type of the set literal. For example, ``float`` is a supertype of ``float`` and ``int``, therefore ``x = [4, 5.6]`` is valid. On the other hand, ``y = [5, "test"]`` does not adhere to the criterion.
|
||||||
|
|
||||||
@@ -1333,6 +1333,8 @@ The values of a set literal expression are all the values of all the contained e
|
|||||||
|
|
||||||
Set literals are supported from release 2.1.0 of the CodeQL CLI, and release 1.24 of LGTM Enterprise.
|
Set literals are supported from release 2.1.0 of the CodeQL CLI, and release 1.24 of LGTM Enterprise.
|
||||||
|
|
||||||
|
Since release 2.6.3 of the CodeQL CLI, and release 1.28 of LGTM Enterprise, a trailing comma is allowed in a set literal.
|
||||||
|
|
||||||
Disambiguation of expressions
|
Disambiguation of expressions
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
@@ -2170,7 +2172,7 @@ The complete grammar for QL is as follows:
|
|||||||
|
|
||||||
range ::= "[" expr ".." expr "]"
|
range ::= "[" expr ".." expr "]"
|
||||||
|
|
||||||
setliteral ::= "[" expr ("," expr)* "]"
|
setliteral ::= "[" expr ("," expr)* ","? "]"
|
||||||
|
|
||||||
simpleId ::= lowerId | upperId
|
simpleId ::= lowerId | upperId
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ import sys
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
def setup(sphinx):
|
def setup(sphinx):
|
||||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), os.path.pardir, 'global-sphinx-files')))
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.path.pardir))
|
||||||
from qllexer import QLLexer
|
from qllexer import QLLexer
|
||||||
sphinx.add_lexer("ql", QLLexer())
|
sphinx.add_lexer("ql", QLLexer())
|
||||||
|
|
||||||
@@ -86,11 +86,11 @@ htmlhelp_basename = 'CodeQL training'
|
|||||||
# built documents.
|
# built documents.
|
||||||
#
|
#
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = u'1.24'
|
# version = u'1.24'
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = u'1.24'
|
# release = u'1.24'
|
||||||
copyright = u'2019 Semmle Ltd'
|
# copyright = u'2019 Semmle Ltd'
|
||||||
author = u'Semmle Ltd'
|
# author = u'Semmle Ltd'
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
|
|||||||
@@ -11,12 +11,12 @@ Setup
|
|||||||
|
|
||||||
For this example you should download:
|
For this example you should download:
|
||||||
|
|
||||||
- `CodeQL for Visual Studio Code <https://help.semmle.com/codeql/codeql-for-vscode/procedures/setting-up.html>`__
|
- `CodeQL for Visual Studio Code <https://codeql.github.com/docs/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code/>`__
|
||||||
- `ChakraCore database <https://downloads.lgtm.com/snapshots/cpp/microsoft/chakracore/ChakraCore-revision-2017-April-12--18-13-26.zip>`__
|
- `ChakraCore database <https://downloads.lgtm.com/snapshots/cpp/microsoft/chakracore/ChakraCore-revision-2017-April-12--18-13-26.zip>`__
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
For the examples in this presentation, we will be analyzing `ChakraCore <https://github.com/microsoft/ChakraCore>`__.
|
For the examples in this presentation, we will be analyzing `ChakraCore <https://github.com/Chakra-Core/ChakraCore/>`__.
|
||||||
|
|
||||||
You can query the project in `the query console <https://lgtm.com/query/project:2034240708/lang:cpp/>`__ on LGTM.com.
|
You can query the project in `the query console <https://lgtm.com/query/project:2034240708/lang:cpp/>`__ on LGTM.com.
|
||||||
|
|
||||||
@@ -149,7 +149,7 @@ Let’s look for overflow guards of the form ``v + b < v``, using the classes
|
|||||||
- a ``RelationalOperation``: the overflow comparison check.
|
- a ``RelationalOperation``: the overflow comparison check.
|
||||||
- a ``Variable``: used as an argument to both the addition and comparison.
|
- a ``Variable``: used as an argument to both the addition and comparison.
|
||||||
|
|
||||||
- The ``where`` part of the query ties these three variables together using `predicates <https://help.semmle.com/QL/ql-handbook/predicates.html>`__ defined in the `standard CodeQL for C/C++ library <https://codeql.github.com/codeql-standard-libraries/cpp/>`__.
|
- The ``where`` part of the query ties these three variables together using `predicates <https://codeql.github.com/docs/ql-language-reference/predicates/>`__ defined in the `standard CodeQL for C/C++ library <https://codeql.github.com/codeql-standard-libraries/cpp/>`__.
|
||||||
|
|
||||||
CodeQL query: bad overflow guards
|
CodeQL query: bad overflow guards
|
||||||
=================================
|
=================================
|
||||||
@@ -229,4 +229,4 @@ The final query
|
|||||||
.. literalinclude:: ../query-examples/cpp/bad-overflow-guard-3.ql
|
.. literalinclude:: ../query-examples/cpp/bad-overflow-guard-3.ql
|
||||||
:language: ql
|
:language: ql
|
||||||
|
|
||||||
This query finds a single result in our historic database, which was `a genuine bug in ChakraCore <https://github.com/Microsoft/ChakraCore/commit/2500e1cdc12cb35af73d5c8c9b85656aba6bab4d>`__.
|
This query finds a single result in our historic database, which was `a genuine bug in ChakraCore <https://github.com/Chakra-Core/ChakraCore//commit/2500e1cdc12cb35af73d5c8c9b85656aba6bab4d>`__.
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ Setup
|
|||||||
|
|
||||||
For this example you should download:
|
For this example you should download:
|
||||||
|
|
||||||
- `CodeQL for Visual Studio Code <https://help.semmle.com/codeql/codeql-for-vscode/procedures/setting-up.html>`__
|
- `CodeQL for Visual Studio Code <https://codeql.github.com/docs/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code/>`__
|
||||||
- `ChakraCore database <https://downloads.lgtm.com/snapshots/cpp/microsoft/chakracore/ChakraCore-revision-2017-April-12--18-13-26.zip>`__
|
- `ChakraCore database <https://downloads.lgtm.com/snapshots/cpp/microsoft/chakracore/ChakraCore-revision-2017-April-12--18-13-26.zip>`__
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
For the examples in this presentation, we will be analyzing `ChakraCore <https://github.com/microsoft/ChakraCore>`__.
|
For the examples in this presentation, we will be analyzing `ChakraCore <https://github.com/Chakra-Core/ChakraCore/>`__.
|
||||||
|
|
||||||
You can query the project in `the query console <https://lgtm.com/query/project:2034240708/lang:cpp/>`__ on LGTM.com.
|
You can query the project in `the query console <https://lgtm.com/query/project:2034240708/lang:cpp/>`__ on LGTM.com.
|
||||||
|
|
||||||
@@ -222,7 +222,7 @@ A ``GuardCondition`` is a ``Boolean`` condition that controls one or more basic
|
|||||||
Further materials
|
Further materials
|
||||||
=================
|
=================
|
||||||
|
|
||||||
- CodeQL for C/C++: https://help.semmle.com/QL/learn-ql/ql/cpp/ql-for-cpp.html
|
- CodeQL for C/C++: https://codeql.github.com/docs/codeql-language-guides/codeql-for-cpp/
|
||||||
- API reference: https://codeql.github.com/codeql-standard-libraries/cpp
|
- API reference: https://codeql.github.com/codeql-standard-libraries/cpp
|
||||||
|
|
||||||
.. rst-class:: end-slide
|
.. rst-class:: end-slide
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ Setup
|
|||||||
|
|
||||||
For this example you should download:
|
For this example you should download:
|
||||||
|
|
||||||
- `CodeQL for Visual Studio Code <https://help.semmle.com/codeql/codeql-for-vscode/procedures/setting-up.html>`__
|
- `CodeQL for Visual Studio Code <https://codeql.github.com/docs/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code/>`__
|
||||||
- `dotnet/coreclr database <http://downloads.lgtm.com/snapshots/cpp/dotnet/coreclr/dotnet_coreclr_fbe0c77.zip>`__
|
- `dotnet/coreclr database <http://downloads.lgtm.com/snapshots/cpp/dotnet/coreclr/dotnet_coreclr_fbe0c77.zip>`__
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
@@ -139,7 +139,7 @@ Define a subclass of ``DataFlow::Node`` representing “source” nodes, that is
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
Note the scoping of the `don’t-care variable <https://help.semmle.com/QL/ql-handbook/expressions.html#don-t-care-expressions>`__ “_” in this example: the body of the characteristic predicate is equivalent to:
|
Note the scoping of the `don’t-care variable <https://codeql.github.com/docs/ql-language-reference/expressions/#don-t-care-expressions>`__ “_” in this example: the body of the characteristic predicate is equivalent to:
|
||||||
|
|
||||||
.. code-block:: ql
|
.. code-block:: ql
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ Setup
|
|||||||
|
|
||||||
For this example you should download:
|
For this example you should download:
|
||||||
|
|
||||||
- `CodeQL for Visual Studio Code <https://help.semmle.com/codeql/codeql-for-vscode/procedures/setting-up.html>`__
|
- `CodeQL for Visual Studio Code <https://codeql.github.com/docs/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code/>`__
|
||||||
- `dotnet/coreclr database <http://downloads.lgtm.com/snapshots/cpp/dotnet/coreclr/dotnet_coreclr_fbe0c77.zip>`__
|
- `dotnet/coreclr database <http://downloads.lgtm.com/snapshots/cpp/dotnet/coreclr/dotnet_coreclr_fbe0c77.zip>`__
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ Setup
|
|||||||
|
|
||||||
For this example you should download:
|
For this example you should download:
|
||||||
|
|
||||||
- `CodeQL for Visual Studio Code <https://help.semmle.com/codeql/codeql-for-vscode/procedures/setting-up.html>`__
|
- `CodeQL for Visual Studio Code <https://codeql.github.com/docs/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code/>`__
|
||||||
- `exiv2 database <http://downloads.lgtm.com/snapshots/cpp/exiv2/Exiv2_exiv2_b090f4d.zip>`__
|
- `exiv2 database <http://downloads.lgtm.com/snapshots/cpp/exiv2/Exiv2_exiv2_b090f4d.zip>`__
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
@@ -68,7 +68,7 @@ A simple CodeQL query
|
|||||||
|
|
||||||
We are going to write a simple query which finds “if statements” with empty “then” blocks, so we can highlight the results like those on the previous slide. The query can be run in the `query console on LGTM <https://lgtm.com/query>`__, or in your `IDE <https://lgtm.com/help/lgtm/running-queries-ide>`__.
|
We are going to write a simple query which finds “if statements” with empty “then” blocks, so we can highlight the results like those on the previous slide. The query can be run in the `query console on LGTM <https://lgtm.com/query>`__, or in your `IDE <https://lgtm.com/help/lgtm/running-queries-ide>`__.
|
||||||
|
|
||||||
A `query <https://help.semmle.com/QL/ql-handbook/queries.html>`__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language reference <https://help.semmle.com/QL/ql-handbook/index.html>`__), see `About CodeQL queries <https://help.semmle.com/QL/learn-ql/ql/writing-queries/introduction-to-queries.html>`__.
|
A `query <https://codeql.github.com/docs/ql-language-reference/queries/>`__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language reference <https://codeql.github.com/docs/ql-language-reference/>`__), see `About CodeQL queries <https://codeql.github.com/docs/writing-codeql-queries/about-codeql-queries/>`__.
|
||||||
|
|
||||||
In our example here, the first line of the query imports the `CodeQL library for C/C++ <https://codeql.github.com/codeql-standard-libraries/cpp/>`__, which defines concepts like ``IfStmt`` and ``Block``.
|
In our example here, the first line of the query imports the `CodeQL library for C/C++ <https://codeql.github.com/codeql-standard-libraries/cpp/>`__, which defines concepts like ``IfStmt`` and ``Block``.
|
||||||
The query proper starts by declaring two variables–ifStmt and block. These variables represent sets of values in the database, according to the type of each of the variables. For example, ifStmt has the type IfStmt, which means it represents the set of all if statements in the program.
|
The query proper starts by declaring two variables–ifStmt and block. These variables represent sets of values in the database, according to the type of each of the variables. For example, ifStmt has the type IfStmt, which means it represents the set of all if statements in the program.
|
||||||
@@ -108,9 +108,9 @@ Each query library also implicitly defines a module.
|
|||||||
|
|
||||||
Queries are always contained in query files with the file extension ``.ql``.
|
Queries are always contained in query files with the file extension ``.ql``.
|
||||||
|
|
||||||
Parts of queries can be lifted into `library files <https://help.semmle.com/QL/ql-handbook/modules.html#library-modules>`__ with the extension ``.qll``. Definitions within such libraries can be brought into scope using ``import`` statements, and similarly QLL files can import each other’s definitions using “import” statements.
|
Parts of queries can be lifted into `library files <https://codeql.github.com/docs/ql-language-reference/modules/#library-modules>`__ with the extension ``.qll``. Definitions within such libraries can be brought into scope using ``import`` statements, and similarly QLL files can import each other’s definitions using “import” statements.
|
||||||
|
|
||||||
Logic can be encapsulated as user-defined `predicates <https://help.semmle.com/QL/ql-handbook/predicates.html>`__ and `classes <https://help.semmle.com/QL/ql-handbook/types.html#classes>`__, and organized into `modules <https://help.semmle.com/QL/ql-handbook/modules.html>`__. Each QLL file implicitly defines a module, but QL and QLL files can also contain explicit module definitions, as we will see later.
|
Logic can be encapsulated as user-defined `predicates <https://codeql.github.com/docs/ql-language-reference/predicates/>`__ and `classes <https://codeql.github.com/docs/ql-language-reference/types/#classes>`__, and organized into `modules <https://codeql.github.com/docs/ql-language-reference/modules/>`__. Each QLL file implicitly defines a module, but QL and QLL files can also contain explicit module definitions, as we will see later.
|
||||||
|
|
||||||
Predicates
|
Predicates
|
||||||
==========
|
==========
|
||||||
@@ -131,7 +131,7 @@ A predicate allows you to pull out and name parts of a query.
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
A `predicate <https://help.semmle.com/QL/ql-handbook/predicates.html>`__ takes zero or more parameters, and its body is a condition on those parameters. The predicate may (or may not) hold. Predicates may also be `recursive <https://help.semmle.com/QL/ql-handbook/predicates.html#recursive-predicates>`__, simply by referring to themselves (directly or indirectly).
|
A `predicate <https://codeql.github.com/docs/ql-language-reference/predicates/>`__ takes zero or more parameters, and its body is a condition on those parameters. The predicate may (or may not) hold. Predicates may also be `recursive <https://codeql.github.com/docs/ql-language-reference/predicates/#recursive-predicates>`__, simply by referring to themselves (directly or indirectly).
|
||||||
|
|
||||||
You can imagine a predicate to be a self-contained from-where-select statement, that produces an intermediate relation, or table. In this case, the ``isEmpty`` predicate will be the set of all blocks which are empty.
|
You can imagine a predicate to be a self-contained from-where-select statement, that produces an intermediate relation, or table. In this case, the ``isEmpty`` predicate will be the set of all blocks which are empty.
|
||||||
|
|
||||||
@@ -154,7 +154,7 @@ Member predicates are inherited and can be overridden.
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
`Classes <https://help.semmle.com/QL/ql-handbook/types.html#classes>`__ model sets of values from the database. A class has one or more supertypes, and inherits `member predicates <https://help.semmle.com/QL/ql-handbook/types.html#member-predicates>`__ (methods) from each of them. Each value in a class must be in every supertype, but additional conditions can be stated in a so-called **characteristic predicate**, which looks a bit like a zero-argument constructor.
|
`Classes <https://codeql.github.com/docs/ql-language-reference/types/#classes>`__ model sets of values from the database. A class has one or more supertypes, and inherits `member predicates <https://codeql.github.com/docs/ql-language-reference/types/#member-predicates>`__ (methods) from each of them. Each value in a class must be in every supertype, but additional conditions can be stated in a so-called **characteristic predicate**, which looks a bit like a zero-argument constructor.
|
||||||
|
|
||||||
In the example, declaring a variable “EmptyBlock e” will allow it to range over only those blocks that have zero statements.
|
In the example, declaring a variable “EmptyBlock e” will allow it to range over only those blocks that have zero statements.
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ Setup
|
|||||||
|
|
||||||
For this example you should download:
|
For this example you should download:
|
||||||
|
|
||||||
- `CodeQL for Visual Studio Code <https://help.semmle.com/codeql/codeql-for-vscode/procedures/setting-up.html>`__
|
- `CodeQL for Visual Studio Code <https://codeql.github.com/docs/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code/>`__
|
||||||
- `rsyslog database <https://downloads.lgtm.com/snapshots/cpp/rsyslog/rsyslog/rsyslog-all-revision-2018-April-27--14-12-31.zip>`__
|
- `rsyslog database <https://downloads.lgtm.com/snapshots/cpp/rsyslog/rsyslog/rsyslog-all-revision-2018-April-27--14-12-31.zip>`__
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ Setup
|
|||||||
|
|
||||||
For this example you should download:
|
For this example you should download:
|
||||||
|
|
||||||
- `CodeQL for Visual Studio Code <https://help.semmle.com/codeql/codeql-for-vscode/procedures/setting-up.html>`__
|
- `CodeQL for Visual Studio Code <https://codeql.github.com/docs/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code/>`__
|
||||||
- `Apache Struts database <https://downloads.lgtm.com/snapshots/java/apache/struts/apache-struts-7fd1622-CVE-2018-11776.zip>`__
|
- `Apache Struts database <https://downloads.lgtm.com/snapshots/java/apache/struts/apache-struts-7fd1622-CVE-2018-11776.zip>`__
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
@@ -134,4 +134,4 @@ Model answer, step 4
|
|||||||
and sink.getNode() instanceof UnsafeDeserializationSink
|
and sink.getNode() instanceof UnsafeDeserializationSink
|
||||||
select sink.getNode().(UnsafeDeserializationSink).getMethodAccess(), source, sink, "Unsafe deserialization of $@.", source, "user input"
|
select sink.getNode().(UnsafeDeserializationSink).getMethodAccess(), source, sink, "Unsafe deserialization of $@.", source, "user input"
|
||||||
|
|
||||||
More full-featured version: https://github.com/github/security-lab/tree/main/CodeQL_Queries/java/Apache_Struts_CVE-2017-9805
|
More full-featured version: https://github.com/github/securitylab/tree/main/CodeQL_Queries/java/Apache_Struts_CVE-2017-9805
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ Setup
|
|||||||
|
|
||||||
For this example you should download:
|
For this example you should download:
|
||||||
|
|
||||||
- `CodeQL for Visual Studio Code <https://help.semmle.com/codeql/codeql-for-vscode/procedures/setting-up.html>`__
|
- `CodeQL for Visual Studio Code <https://codeql.github.com/docs/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code/>`__
|
||||||
- `VIVO Vitro database <http://downloads.lgtm.com/snapshots/java/vivo-project/Vitro/vivo-project_Vitro_java-srcVersion_47ae42c01954432c3c3b92d5d163551ce367f510-dist_odasa-lgtm-2019-04-23-7ceff95-linux64.zip>`__
|
- `VIVO Vitro database <http://downloads.lgtm.com/snapshots/java/vivo-project/Vitro/vivo-project_Vitro_java-srcVersion_47ae42c01954432c3c3b92d5d163551ce367f510-dist_odasa-lgtm-2019-04-23-7ceff95-linux64.zip>`__
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ Setup
|
|||||||
|
|
||||||
For this example you should download:
|
For this example you should download:
|
||||||
|
|
||||||
- `CodeQL for Visual Studio Code <https://help.semmle.com/codeql/codeql-for-vscode/procedures/setting-up.html>`__
|
- `CodeQL for Visual Studio Code <https://codeql.github.com/docs/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code/>`__
|
||||||
- `Apache Struts database <https://downloads.lgtm.com/snapshots/java/apache/struts/apache-struts-7fd1622-CVE-2018-11776.zip>`__
|
- `Apache Struts database <https://downloads.lgtm.com/snapshots/java/apache/struts/apache-struts-7fd1622-CVE-2018-11776.zip>`__
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
@@ -54,7 +54,7 @@ Code injection in Apache struts
|
|||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
More details on the CVE can be found here: https://securitylab.github.com/research/apache-struts-CVE-2018-11776 and
|
More details on the CVE can be found here: https://securitylab.github.com/research/apache-struts-CVE-2018-11776 and
|
||||||
https://github.com/github/security-lab/tree/main/CodeQL_Queries/java/Apache_Struts_CVE-2018-11776
|
https://github.com/github/securitylab/tree/main/CodeQL_Queries/java/Apache_Struts_CVE-2018-11776
|
||||||
|
|
||||||
More details on OGNL can be found here: https://commons.apache.org/proper/commons-ognl/
|
More details on OGNL can be found here: https://commons.apache.org/proper/commons-ognl/
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ Setup
|
|||||||
|
|
||||||
For this example you should download:
|
For this example you should download:
|
||||||
|
|
||||||
- `CodeQL for Visual Studio Code <https://help.semmle.com/codeql/codeql-for-vscode/procedures/setting-up.html>`__
|
- `CodeQL for Visual Studio Code <https://codeql.github.com/docs/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code/>`__
|
||||||
- `Apache Struts database <https://downloads.lgtm.com/snapshots/java/apache/struts/apache-struts-7fd1622-CVE-2018-11776.zip>`__
|
- `Apache Struts database <https://downloads.lgtm.com/snapshots/java/apache/struts/apache-struts-7fd1622-CVE-2018-11776.zip>`__
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
@@ -68,7 +68,7 @@ A simple CodeQL query
|
|||||||
|
|
||||||
We are going to write a simple query which finds “if statements” with empty “then” blocks, so we can highlight the results like those on the previous slide. The query can be run in the `query console on LGTM <https://lgtm.com/query>`__, or in your `IDE <https://lgtm.com/help/lgtm/running-queries-ide>`__.
|
We are going to write a simple query which finds “if statements” with empty “then” blocks, so we can highlight the results like those on the previous slide. The query can be run in the `query console on LGTM <https://lgtm.com/query>`__, or in your `IDE <https://lgtm.com/help/lgtm/running-queries-ide>`__.
|
||||||
|
|
||||||
A `query <https://help.semmle.com/QL/ql-handbook/queries.html>`__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language reference <https://help.semmle.com/QL/ql-handbook/index.html>`__), see `About CodeQL queries <https://help.semmle.com/QL/learn-ql/ql/writing-queries/introduction-to-queries.html>`__.
|
A `query <https://codeql.github.com/docs/ql-language-reference/queries/>`__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language reference <https://codeql.github.com/docs/ql-language-reference/>`__), see `About CodeQL queries <https://codeql.github.com/docs/writing-codeql-queries/about-codeql-queries/>`__.
|
||||||
|
|
||||||
In our example here, the first line of the query imports the `CodeQL library for Java <https://codeql.github.com/codeql-standard-libraries/java/>`__, which defines concepts like ``IfStmt`` and ``Block``.
|
In our example here, the first line of the query imports the `CodeQL library for Java <https://codeql.github.com/codeql-standard-libraries/java/>`__, which defines concepts like ``IfStmt`` and ``Block``.
|
||||||
The query proper starts by declaring two variables–ifStmt and block. These variables represent sets of values in the database, according to the type of each of the variables. For example, ``ifStmt`` has the type ``IfStmt``, which means it represents the set of all if statements in the program.
|
The query proper starts by declaring two variables–ifStmt and block. These variables represent sets of values in the database, according to the type of each of the variables. For example, ``ifStmt`` has the type ``IfStmt``, which means it represents the set of all if statements in the program.
|
||||||
@@ -107,9 +107,9 @@ Each query library also implicitly defines a module.
|
|||||||
|
|
||||||
Queries are always contained in query files with the file extension ``.ql``.
|
Queries are always contained in query files with the file extension ``.ql``.
|
||||||
|
|
||||||
Parts of queries can be lifted into `library files <https://help.semmle.com/QL/ql-handbook/modules.html#library-modules>`__ with the extension ``.qll``. Definitions within such libraries can be brought into scope using “import” statements, and similarly QLL files can import each other’s definitions using “import” statements.
|
Parts of queries can be lifted into `library files <https://codeql.github.com/docs/ql-language-reference/modules/#library-modules>`__ with the extension ``.qll``. Definitions within such libraries can be brought into scope using “import” statements, and similarly QLL files can import each other’s definitions using “import” statements.
|
||||||
|
|
||||||
Logic can be encapsulated as user-defined `predicates <https://help.semmle.com/QL/ql-handbook/predicates.html>`__ and `classes <https://help.semmle.com/QL/ql-handbook/types.html#classes>`__, and organized into `modules <https://help.semmle.com/QL/ql-handbook/modules.html>`__. Each QLL file implicitly defines a module, but QL and QLL files can also contain explicit module definitions, as we will see later.
|
Logic can be encapsulated as user-defined `predicates <https://codeql.github.com/docs/ql-language-reference/predicates/>`__ and `classes <https://codeql.github.com/docs/ql-language-reference/types/#classes>`__, and organized into `modules <https://codeql.github.com/docs/ql-language-reference/modules/>`__. Each QLL file implicitly defines a module, but QL and QLL files can also contain explicit module definitions, as we will see later.
|
||||||
|
|
||||||
Predicates
|
Predicates
|
||||||
==========
|
==========
|
||||||
@@ -130,7 +130,7 @@ A predicate allows you to pull out and name parts of a query.
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
A `predicate <https://help.semmle.com/QL/ql-handbook/predicates.html>`__ takes zero or more parameters, and its body is a condition on those parameters. The predicate may (or may not) hold. Predicates may also be `recursive <https://help.semmle.com/QL/ql-handbook/predicates.html#recursive-predicates>`__, simply by referring to themselves (directly or indirectly).
|
A `predicate <https://codeql.github.com/docs/ql-language-reference/predicates/>`__ takes zero or more parameters, and its body is a condition on those parameters. The predicate may (or may not) hold. Predicates may also be `recursive <https://codeql.github.com/docs/ql-language-reference/predicates/#recursive-predicates>`__, simply by referring to themselves (directly or indirectly).
|
||||||
|
|
||||||
You can imagine a predicate to be a self-contained from-where-select statement, that produces an intermediate relation, or table. In this case, the ``isEmpty`` predicate will be the set of all blocks which are empty.
|
You can imagine a predicate to be a self-contained from-where-select statement, that produces an intermediate relation, or table. In this case, the ``isEmpty`` predicate will be the set of all blocks which are empty.
|
||||||
|
|
||||||
@@ -154,7 +154,7 @@ Member predicates are inherited and can be overridden.
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
`Classes <https://help.semmle.com/QL/ql-handbook/types.html#classes>`__ model sets of values from the database. A class has one or more supertypes, and inherits `member predicates <https://help.semmle.com/QL/ql-handbook/types.html#member-predicates>`__ (methods) from each of them. Each value in a class must be in every supertype, but additional conditions can be stated in a so-called **characteristic predicate**, which looks a bit like a zero-argument constructor.
|
`Classes <https://codeql.github.com/docs/ql-language-reference/types/#classes>`__ model sets of values from the database. A class has one or more supertypes, and inherits `member predicates <https://codeql.github.com/docs/ql-language-reference/types/#member-predicates>`__ (methods) from each of them. Each value in a class must be in every supertype, but additional conditions can be stated in a so-called **characteristic predicate**, which looks a bit like a zero-argument constructor.
|
||||||
|
|
||||||
In the example, declaring a variable “EmptyBlock e” will allow it to range over only those blocks that have zero statements.
|
In the example, declaring a variable “EmptyBlock e” will allow it to range over only those blocks that have zero statements.
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ Setup
|
|||||||
|
|
||||||
For this example you should download:
|
For this example you should download:
|
||||||
|
|
||||||
- `CodeQL for Visual Studio Code <https://help.semmle.com/codeql/codeql-for-vscode/procedures/setting-up.html>`__
|
- `CodeQL for Visual Studio Code <https://codeql.github.com/docs/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code/>`__
|
||||||
- `VIVO Vitro database <http://downloads.lgtm.com/snapshots/java/vivo-project/Vitro/vivo-project_Vitro_java-srcVersion_47ae42c01954432c3c3b92d5d163551ce367f510-dist_odasa-lgtm-2019-04-23-7ceff95-linux64.zip>`__
|
- `VIVO Vitro database <http://downloads.lgtm.com/snapshots/java/vivo-project/Vitro/vivo-project_Vitro_java-srcVersion_47ae42c01954432c3c3b92d5d163551ce367f510-dist_odasa-lgtm-2019-04-23-7ceff95-linux64.zip>`__
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
@@ -84,7 +84,7 @@ Let’s start by looking for calls to methods with names of the form ``sparql*Qu
|
|||||||
- a ``MethodAccess``: the call to a SPARQL query method
|
- a ``MethodAccess``: the call to a SPARQL query method
|
||||||
- a ``Method``: the SPARQL query method.
|
- a ``Method``: the SPARQL query method.
|
||||||
|
|
||||||
- The ``where`` part of the query ties these variables together using `predicates <https://help.semmle.com/QL/ql-handbook/predicates.html>`__ defined in the `standard CodeQL library for Java <https://codeql.github.com/codeql-standard-libraries/java/>`__.
|
- The ``where`` part of the query ties these variables together using `predicates <https://codeql.github.com/docs/ql-language-reference/predicates/>`__ defined in the `standard CodeQL library for Java <https://codeql.github.com/codeql-standard-libraries/java/>`__.
|
||||||
|
|
||||||
CodeQL query: find string concatenation
|
CodeQL query: find string concatenation
|
||||||
=======================================
|
=======================================
|
||||||
|
|||||||
@@ -39,9 +39,9 @@ The basic representation of an analyzed program is an *abstract syntax tree (AST
|
|||||||
|
|
||||||
The following topics contain overviews of the important AST classes and CodeQL libraries for C/C++, C#, and Java:
|
The following topics contain overviews of the important AST classes and CodeQL libraries for C/C++, C#, and Java:
|
||||||
|
|
||||||
- `CodeQL library for C/C++ <https://help.semmle.com/QL/learn-ql/cpp/introduce-libraries-cpp.html>`__
|
- `CodeQL library for C/C++ <https://codeql.github.com/docs/codeql-language-guides/codeql-library-for-cpp/>`__
|
||||||
- `CodeQL library for C# <https://help.semmle.com/QL/learn-ql/csharp/introduce-libraries-csharp.html>`__
|
- `CodeQL library for C# <https://codeql.github.com/docs/codeql-language-guides/codeql-library-for-csharp/>`__
|
||||||
- `CodeQL library for Java <https://help.semmle.com/QL/learn-ql/java/introduce-libraries-java.html>`__
|
- `CodeQL library for Java <https://codeql.github.com/docs/codeql-language-guides/codeql-library-for-java/>`__
|
||||||
|
|
||||||
|
|
||||||
Database representations of ASTs
|
Database representations of ASTs
|
||||||
@@ -65,6 +65,6 @@ Entity types are rarely used directly, the usual pattern is to define a class th
|
|||||||
|
|
||||||
For example, the database schemas for C/++, C#, and Java CodeQL databases are here:
|
For example, the database schemas for C/++, C#, and Java CodeQL databases are here:
|
||||||
|
|
||||||
- https://github.com/github/codeql/blob/main/cpp/ql/src/semmlecode.cpp.dbscheme
|
- https://github.com/github/codeql/blob/main/cpp/ql/lib/semmlecode.cpp.dbscheme
|
||||||
- https://github.com/github/codeql/blob/main/csharp/ql/src/semmlecode.csharp.dbscheme
|
- https://github.com/github/codeql/blob/main/csharp/ql/lib/semmlecode.csharp.dbscheme
|
||||||
- https://github.com/github/codeql/blob/main/java/ql/src/config/semmlecode.dbscheme
|
- https://github.com/github/codeql/blob/main/java/ql/lib/config/semmlecode.dbscheme
|
||||||
@@ -4,6 +4,6 @@ You can download the database as a zip file by clicking the link on the slide ab
|
|||||||
#. Add the unzipped database to Visual Studio Code
|
#. Add the unzipped database to Visual Studio Code
|
||||||
#. Upgrade the database if necessary
|
#. Upgrade the database if necessary
|
||||||
|
|
||||||
For further information, see `Analyzing your projects <https://help.semmle.com/codeql/codeql-for-vscode/procedures/using-extension.html>`__ in the CodeQL for Visual Studio Code help.
|
For further information, see `Analyzing your projects <https://codeql.github.com/docs/codeql-for-visual-studio-code/analyzing-your-projects/>`__ in the CodeQL for Visual Studio Code help.
|
||||||
|
|
||||||
Note that results generated in the query console are likely to differ to those generated in CodeQL for Visual Studio Code as LGTM.com analyzes the most recent revisions of each project that has been added–the CodeQL database available to download above is based on an historical version of the codebase.
|
Note that results generated in the query console are likely to differ to those generated in CodeQL for Visual Studio Code as LGTM.com analyzes the most recent revisions of each project that has been added–the CodeQL database available to download above is based on an historical version of the codebase.
|
||||||
@@ -103,7 +103,7 @@ Analysis overview
|
|||||||
|
|
||||||
CodeQL analysis works by extracting a queryable database from your project. For compiled languages, the tools observe an ordinary build of the source code. Each time a compiler is invoked to process a source file, a copy of that file is made, and all relevant information about the source code (syntactic data about the abstract syntax tree, semantic data like name binding and type information, data on the operation of the C preprocessor, etc.) is collected. For interpreted languages, the extractor gathers similar information by running directly on the source code. Multi-language code bases are analyzed one language at a time.
|
CodeQL analysis works by extracting a queryable database from your project. For compiled languages, the tools observe an ordinary build of the source code. Each time a compiler is invoked to process a source file, a copy of that file is made, and all relevant information about the source code (syntactic data about the abstract syntax tree, semantic data like name binding and type information, data on the operation of the C preprocessor, etc.) is collected. For interpreted languages, the extractor gathers similar information by running directly on the source code. Multi-language code bases are analyzed one language at a time.
|
||||||
|
|
||||||
Once the extraction finishes, all this information is collected into a single `CodeQL database <https://help.semmle.com/codeql/about-codeql.html#about-codeql-databases>`__, which is then ready to query, possibly on a different machine. A copy of the source files, made at the time the database was created, is also included in the CodeQL database so analysis results can be displayed at the correct location in the code. The database schema is (source) language specific.
|
Once the extraction finishes, all this information is collected into a single `CodeQL database <https://codeql.github.com/docs/codeql-overview/about-codeql/#about-codeql-databases>`__, which is then ready to query, possibly on a different machine. A copy of the source files, made at the time the database was created, is also included in the CodeQL database so analysis results can be displayed at the correct location in the code. The database schema is (source) language specific.
|
||||||
|
|
||||||
Queries are written in QL and usually depend on one or more of the `standard CodeQL libraries <https://github.com/github/codeql>`__ (and of course you can write your own custom libraries). They are compiled into an efficiently executable format by the QL compiler and then run on a CodeQL database by the QL evaluator, either on a remote worker machine or locally on a developer’s machine.
|
Queries are written in QL and usually depend on one or more of the `standard CodeQL libraries <https://github.com/github/codeql>`__ (and of course you can write your own custom libraries). They are compiled into an efficiently executable format by the QL compiler and then run on a CodeQL database by the QL evaluator, either on a remote worker machine or locally on a developer’s machine.
|
||||||
|
|
||||||
@@ -124,7 +124,7 @@ QL is:
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
QL is the high-level, object-oriented logic language that underpins all CodeQL libraries and analyses. You can learn lots more about QL by visiting the `QL language reference <https://help.semmle.com/QL/ql-handbook>`__.
|
QL is the high-level, object-oriented logic language that underpins all CodeQL libraries and analyses. You can learn lots more about QL by visiting the `QL language reference <https://codeql.github.com/docs/ql-language-reference/>`__.
|
||||||
The key features of QL are:
|
The key features of QL are:
|
||||||
|
|
||||||
- All common logic connectives are available, including quantifiers like ``exist``, which can also introduce new variables.
|
- All common logic connectives are available, including quantifiers like ``exist``, which can also introduce new variables.
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ Local vs global data flow
|
|||||||
|
|
||||||
For further information, see:
|
For further information, see:
|
||||||
|
|
||||||
- `About data flow analysis <https://help.semmle.com/QL/learn-ql/ql/intro-to-data-flow.html>`__
|
- `About data flow analysis <https://codeql.github.com/docs/writing-codeql-queries/about-data-flow-analysis/>`__
|
||||||
|
|
||||||
.. rst-class:: background2
|
.. rst-class:: background2
|
||||||
|
|
||||||
@@ -111,8 +111,8 @@ So all references will need to be qualified (that is, ``DataFlow::Node``)
|
|||||||
|
|
||||||
A **module** is a way of organizing QL code by grouping together related predicates, classes, and (sub-)modules. They can be either explicitly declared or implicit. A query library implicitly declares a module with the same name as the QLL file.
|
A **module** is a way of organizing QL code by grouping together related predicates, classes, and (sub-)modules. They can be either explicitly declared or implicit. A query library implicitly declares a module with the same name as the QLL file.
|
||||||
|
|
||||||
For further information on libraries and modules in QL, see the chapter on `Modules <https://help.semmle.com/QL/ql-handbook/modules.html>`__ in the QL language reference.
|
For further information on libraries and modules in QL, see the chapter on `Modules <https://codeql.github.com/docs/ql-language-reference/modules/>`__ in the QL language reference.
|
||||||
For further information on importing QL libraries and modules, see the chapter on `Name resolution <https://help.semmle.com/QL/ql-handbook/name-resolution.html>`__ in the QL language reference.
|
For further information on importing QL libraries and modules, see the chapter on `Name resolution <https://codeql.github.com/docs/ql-language-reference/name-resolution/>`__ in the QL language reference.
|
||||||
|
|
||||||
Data flow graph
|
Data flow graph
|
||||||
===============
|
===============
|
||||||
@@ -131,7 +131,7 @@ Data flow graph
|
|||||||
|
|
||||||
The ``DataFlow::Node`` class is shared between both the local and global data flow graphs–the primary difference is the edges, which in the “global” case can link different functions.
|
The ``DataFlow::Node`` class is shared between both the local and global data flow graphs–the primary difference is the edges, which in the “global” case can link different functions.
|
||||||
|
|
||||||
``localFlowStep`` is the “single step” flow relation–that is, it describes single edges in the local data flow graph. ``localFlow`` represents the `transitive <https://help.semmle.com/QL/ql-handbook/recursion.html#transitive-closures>`__ closure of this relation–in other words, it contains every pair of nodes where the second node is reachable from the first in the data flow graph.
|
``localFlowStep`` is the “single step” flow relation–that is, it describes single edges in the local data flow graph. ``localFlow`` represents the `transitive <https://codeql.github.com/docs/ql-language-reference/recursion/#transitive-closures>`__ closure of this relation–in other words, it contains every pair of nodes where the second node is reachable from the first in the data flow graph.
|
||||||
|
|
||||||
The data flow graph is separate from the `AST <https://en.wikipedia.org/wiki/Abstract_syntax_tree>`__, to allow for flexibility in how data flow is modeled. There are a small number of data flow node types–expression nodes, parameter nodes, uninitialized variable nodes, and definition by reference nodes. Each node provides mapping functions to and from the relevant AST (for example ``Expr``, ``Parameter`` etc.) or symbol table (for example ``Variable``) classes.
|
The data flow graph is separate from the `AST <https://en.wikipedia.org/wiki/Abstract_syntax_tree>`__, to allow for flexibility in how data flow is modeled. There are a small number of data flow node types–expression nodes, parameter nodes, uninitialized variable nodes, and definition by reference nodes. Each node provides mapping functions to and from the relevant AST (for example ``Expr``, ``Parameter`` etc.) or symbol table (for example ``Variable``) classes.
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ Setup
|
|||||||
|
|
||||||
For this example you should download:
|
For this example you should download:
|
||||||
|
|
||||||
- `CodeQL for Visual Studio Code <https://help.semmle.com/codeql/codeql-for-vscode/procedures/setting-up.html>`__
|
- `CodeQL for Visual Studio Code <https://codeql.github.com/docs/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code/>`__
|
||||||
- A CodeQL database
|
- A CodeQL database
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
@@ -159,7 +159,7 @@ Specify the language to apply syntax highlighting and the lines of the fragment
|
|||||||
Further details
|
Further details
|
||||||
===============
|
===============
|
||||||
|
|
||||||
- For more information on writing in reStructuredText, see http://docutils.sourceforge.net/rst.html.
|
- For more information on writing in reStructuredText, see https://docutils.sourceforge.io/rst.html.
|
||||||
|
|
||||||
- For more information on Sphinx, see https://www.sphinx-doc.org.
|
- For more information on Sphinx, see https://www.sphinx-doc.org.
|
||||||
|
|
||||||
|
|||||||
@@ -41,9 +41,12 @@ project = u'Supported languages and frameworks for LGTM Enterprise'
|
|||||||
|
|
||||||
# The version info for this project, if different from version and release in main conf.py file.
|
# The version info for this project, if different from version and release in main conf.py file.
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = u'1.27'
|
|
||||||
# The full version, including alpha/beta/rc tags.
|
# LGTM Enterprise release
|
||||||
release = u'1.27'
|
release = u'1.28'
|
||||||
|
|
||||||
|
# CodeQL CLI version used by LGTM Enterprise release
|
||||||
|
version = u'2.5.9'
|
||||||
|
|
||||||
# -- Project-specifc options for HTML output ----------------------------------------------
|
# -- Project-specifc options for HTML output ----------------------------------------------
|
||||||
|
|
||||||
@@ -66,9 +69,9 @@ html_theme_options = {'font_size': '16px',
|
|||||||
'body_text': '#333',
|
'body_text': '#333',
|
||||||
'link': '#2F1695',
|
'link': '#2F1695',
|
||||||
'link_hover': '#2F1695',
|
'link_hover': '#2F1695',
|
||||||
'font_family': 'Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Segoe UI Symbol;',
|
|
||||||
'show_powered_by': False,
|
'show_powered_by': False,
|
||||||
'nosidebar':True,
|
'nosidebar':True,
|
||||||
|
'head_font_family': '-apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"',
|
||||||
}
|
}
|
||||||
|
|
||||||
html_favicon = '../images/site/favicon.ico'
|
html_favicon = '../images/site/favicon.ico'
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
Frameworks and libraries
|
Frameworks and libraries
|
||||||
########################
|
########################
|
||||||
|
|
||||||
The libraries and queries in version |version| have been explicitly checked against the libraries and frameworks listed below.
|
LGTM Enterprise |release| includes CodeQL CLI |version|. The CodeQL libraries and queries used by this version of LGTM Enterprise have been explicitly checked against the libraries and frameworks listed below.
|
||||||
|
|
||||||
.. pull-quote::
|
.. pull-quote::
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
Languages and compilers
|
Languages and compilers
|
||||||
#######################
|
#######################
|
||||||
|
|
||||||
CodeQL and LGTM version |version| support analysis of the following languages compiled by the following compilers.
|
LGTM Enterprise |release| includes CodeQL CLI |version|. LGTM Enterprise supports analysis of the following languages compiled by the following compilers.
|
||||||
(CodeQL was previously known as QL.)
|
|
||||||
|
|
||||||
Note that where there are several versions or dialects of a language, the supported variants are listed.
|
Note that where there are several versions or dialects of a language, the supported variants are listed.
|
||||||
If your code requires a particular version of a compiler, check that this version is included below.
|
If your code requires a particular version of a compiler, check that this version is included below.
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ When you have selected a presentation, use |arrow-r| and |arrow-l| to navigate b
|
|||||||
Press **p** to view the additional notes on slides that have an information icon |info| in the top right corner, and press **f** to enter full-screen mode.
|
Press **p** to view the additional notes on slides that have an information icon |info| in the top right corner, and press **f** to enter full-screen mode.
|
||||||
|
|
||||||
The presentations contain a number of query examples.
|
The presentations contain a number of query examples.
|
||||||
We recommend that you download `CodeQL for Visual Studio Code <https://help.semmle.com/codeql/codeql-for-vscode/procedures/setting-up.html>`__ and add the example database for each presentation so that you can find the bugs mentioned in the slides.
|
We recommend that you download `CodeQL for Visual Studio Code <https://codeql.github.com/docs/codeql-for-visual-studio-code/>`__ and add the example database for each presentation so that you can find the bugs mentioned in the slides.
|
||||||
|
|
||||||
|
|
||||||
.. pull-quote::
|
.. pull-quote::
|
||||||
@@ -39,23 +39,23 @@ We recommend that you download `CodeQL for Visual Studio Code <https://help.semm
|
|||||||
CodeQL and variant analysis for C/C++
|
CodeQL and variant analysis for C/C++
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
- `Introduction to variant analysis: CodeQL for C/C++ <https://help.semmle.com/QL/ql-training/cpp/intro-ql-cpp.html>`__–an introduction to variant analysis and CodeQL for C/C++ programmers.
|
- `Introduction to variant analysis: CodeQL for C/C++ </QL/ql-training/cpp/intro-ql-cpp.html>`__–an introduction to variant analysis and CodeQL for C/C++ programmers.
|
||||||
- `Example: Bad overflow guard <https://help.semmle.com/QL/ql-training/cpp/bad-overflow-guard.html>`__–an example of iterative query development to find bad overflow guards in a C++ project.
|
- `Example: Bad overflow guard </QL/ql-training/cpp/bad-overflow-guard.html>`__–an example of iterative query development to find bad overflow guards in a C++ project.
|
||||||
- `Program representation: CodeQL for C/C++ <https://help.semmle.com/QL/ql-training/cpp/program-representation-cpp.html>`__–information on how CodeQL analysis represents C/C++ programs.
|
- `Program representation: CodeQL for C/C++ </QL/ql-training/cpp/program-representation-cpp.html>`__–information on how CodeQL analysis represents C/C++ programs.
|
||||||
- `Introduction to local data flow <https://help.semmle.com/QL/ql-training/cpp/data-flow-cpp.html>`__–an introduction to analyzing local data flow in C/C++ using CodeQL, including an example demonstrating how to develop a query to find a real CVE.
|
- `Introduction to local data flow </QL/ql-training/cpp/data-flow-cpp.html>`__–an introduction to analyzing local data flow in C/C++ using CodeQL, including an example demonstrating how to develop a query to find a real CVE.
|
||||||
- `Exercise: snprintf overflow <https://help.semmle.com/QL/ql-training/cpp/snprintf.html>`__–an example demonstrating how to develop a data flow query.
|
- `Exercise: snprintf overflow </QL/ql-training/cpp/snprintf.html>`__–an example demonstrating how to develop a data flow query.
|
||||||
- `Introduction to global data flow <https://help.semmle.com/QL/ql-training/cpp/global-data-flow-cpp.html>`__–an introduction to analyzing global data flow in C/C++ using CodeQL.
|
- `Introduction to global data flow </QL/ql-training/cpp/global-data-flow-cpp.html>`__–an introduction to analyzing global data flow in C/C++ using CodeQL.
|
||||||
- `Analyzing control flow: CodeQL for C/C++ <https://help.semmle.com/QL/ql-training/cpp/control-flow-cpp.html>`__–an introduction to analyzing control flow in C/C++ using CodeQL.
|
- `Analyzing control flow: CodeQL for C/C++ </QL/ql-training/cpp/control-flow-cpp.html>`__–an introduction to analyzing control flow in C/C++ using CodeQL.
|
||||||
|
|
||||||
CodeQL and variant analysis for Java
|
CodeQL and variant analysis for Java
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
- `Introduction to variant analysis: CodeQL for Java <https://help.semmle.com/QL/ql-training/java/intro-ql-java.html>`__–an introduction to variant analysis and CodeQL for Java programmers.
|
- `Introduction to variant analysis: CodeQL for Java </QL/ql-training/java/intro-ql-java.html>`__–an introduction to variant analysis and CodeQL for Java programmers.
|
||||||
- `Example: Query injection <https://help.semmle.com/QL/ql-training/java/query-injection-java.html>`__–an example of iterative query development to find unsanitized SPARQL injections in a Java project.
|
- `Example: Query injection </QL/ql-training/java/query-injection-java.html>`__–an example of iterative query development to find unsanitized SPARQL injections in a Java project.
|
||||||
- `Program representation: CodeQL for Java <https://help.semmle.com/QL/ql-training/java/program-representation-java.html>`__–information on how CodeQL analysis represents Java programs.
|
- `Program representation: CodeQL for Java </QL/ql-training/java/program-representation-java.html>`__–information on how CodeQL analysis represents Java programs.
|
||||||
- `Introduction to local data flow <https://help.semmle.com/QL/ql-training/java/data-flow-java.html>`__–an introduction to analyzing local data flow in Java using CodeQL, including an example demonstrating how to develop a query to find a real CVE.
|
- `Introduction to local data flow </QL/ql-training/java/data-flow-java.html>`__–an introduction to analyzing local data flow in Java using CodeQL, including an example demonstrating how to develop a query to find a real CVE.
|
||||||
- `Exercise: Apache Struts <https://help.semmle.com/QL/ql-training/java/apache-struts-java.html>`__–an example demonstrating how to develop a data flow query.
|
- `Exercise: Apache Struts </QL/ql-training/java/apache-struts-java.html>`__–an example demonstrating how to develop a data flow query.
|
||||||
- `Introduction to global data flow <https://help.semmle.com/QL/ql-training/java/global-data-flow-java.html>`__–an introduction to analyzing global data flow in Java using CodeQL.
|
- `Introduction to global data flow </QL/ql-training/java/global-data-flow-java.html>`__–an introduction to analyzing global data flow in Java using CodeQL.
|
||||||
|
|
||||||
Further reading
|
Further reading
|
||||||
~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~
|
||||||
|
|||||||
2
java/change-notes/2021-06-08-spel-injection-query.md
Normal file
2
java/change-notes/2021-06-08-spel-injection-query.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
lgtm,codescanning
|
||||||
|
* The query "Expression language injection (Spring)" (`java/spel-expression-injection`) has been promoted from experimental to the main query pack. Its results will now appear by default. This query was originally [submitted as an experimental query by @artem-smotrakov](https://github.com/github/codeql/pull/3291).
|
||||||
2
java/change-notes/2021-06-16-xslt-injection-query.md
Normal file
2
java/change-notes/2021-06-16-xslt-injection-query.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
lgtm,codescanning
|
||||||
|
* The query "XSLT transformation with user-controlled stylesheet" (`java/xslt-injection`) has been promoted from experimental to the main query pack. Its results will now appear by default. This query was originally [submitted as an experimental query by @ggolawski](https://github.com/github/codeql/pull/3363).
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
lgtm,codescanning
|
||||||
|
* Added models for the subpackages of Apache Commons Collections. This may lead to more results from any query using data-flow analysis where a relevant path uses one of these container types.
|
||||||
@@ -1,89 +1,89 @@
|
|||||||
package,sink,source,summary,sink:bean-validation,sink:create-file,sink:groovy,sink:header-splitting,sink:information-leak,sink:jexl,sink:jndi-injection,sink:ldap,sink:mvel,sink:ognl-injection,sink:open-url,sink:set-hostname-verifier,sink:sql,sink:url-open-stream,sink:url-redirect,sink:xpath,sink:xss,source:remote,summary:taint,summary:value
|
package,sink,source,summary,sink:bean-validation,sink:create-file,sink:groovy,sink:header-splitting,sink:information-leak,sink:jexl,sink:jndi-injection,sink:ldap,sink:mvel,sink:ognl-injection,sink:open-url,sink:set-hostname-verifier,sink:sql,sink:url-open-stream,sink:url-redirect,sink:xpath,sink:xslt,sink:xss,source:contentprovider,source:remote,summary:taint,summary:value
|
||||||
android.content,8,,4,,,,,,,,,,,,,8,,,,,,4,
|
android.content,8,27,4,,,,,,,,,,,,,8,,,,,,27,,4,
|
||||||
android.database,59,,30,,,,,,,,,,,,,59,,,,,,30,
|
android.database,59,,30,,,,,,,,,,,,,59,,,,,,,,30,
|
||||||
android.net,,,60,,,,,,,,,,,,,,,,,,,45,15
|
android.net,,,60,,,,,,,,,,,,,,,,,,,,,45,15
|
||||||
android.util,,16,,,,,,,,,,,,,,,,,,,16,,
|
android.util,,16,,,,,,,,,,,,,,,,,,,,,16,,
|
||||||
android.webkit,3,2,,,,,,,,,,,,,,,,,,3,2,,
|
android.webkit,3,2,,,,,,,,,,,,,,,,,,,3,,2,,
|
||||||
com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,,,,,,,,,1,
|
com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,,,,,,,,,,,1,
|
||||||
com.esotericsoftware.kryo5.io,,,1,,,,,,,,,,,,,,,,,,,1,
|
com.esotericsoftware.kryo5.io,,,1,,,,,,,,,,,,,,,,,,,,,1,
|
||||||
com.fasterxml.jackson.core,,,1,,,,,,,,,,,,,,,,,,,1,
|
com.fasterxml.jackson.core,,,1,,,,,,,,,,,,,,,,,,,,,1,
|
||||||
com.fasterxml.jackson.databind,,,5,,,,,,,,,,,,,,,,,,,5,
|
com.fasterxml.jackson.databind,,,5,,,,,,,,,,,,,,,,,,,,,5,
|
||||||
com.google.common.base,,,85,,,,,,,,,,,,,,,,,,,62,23
|
com.google.common.base,,,85,,,,,,,,,,,,,,,,,,,,,62,23
|
||||||
com.google.common.cache,,,17,,,,,,,,,,,,,,,,,,,,17
|
com.google.common.cache,,,17,,,,,,,,,,,,,,,,,,,,,,17
|
||||||
com.google.common.collect,,,553,,,,,,,,,,,,,,,,,,,2,551
|
com.google.common.collect,,,553,,,,,,,,,,,,,,,,,,,,,2,551
|
||||||
com.google.common.io,6,,73,,,,,,,,,,,,,,6,,,,,72,1
|
com.google.common.io,6,,73,,,,,,,,,,,,,,6,,,,,,,72,1
|
||||||
com.opensymphony.xwork2.ognl,3,,,,,,,,,,,,3,,,,,,,,,,
|
com.opensymphony.xwork2.ognl,3,,,,,,,,,,,,3,,,,,,,,,,,,
|
||||||
com.unboundid.ldap.sdk,17,,,,,,,,,,17,,,,,,,,,,,,
|
com.unboundid.ldap.sdk,17,,,,,,,,,,17,,,,,,,,,,,,,,
|
||||||
flexjson,,,1,,,,,,,,,,,,,,,,,,,,1
|
flexjson,,,1,,,,,,,,,,,,,,,,,,,,,,1
|
||||||
groovy.lang,26,,,,,26,,,,,,,,,,,,,,,,,
|
groovy.lang,26,,,,,26,,,,,,,,,,,,,,,,,,,
|
||||||
groovy.util,5,,,,,5,,,,,,,,,,,,,,,,,
|
groovy.util,5,,,,,5,,,,,,,,,,,,,,,,,,,
|
||||||
jakarta.faces.context,2,7,,,,,,,,,,,,,,,,,,2,7,,
|
jakarta.faces.context,2,7,,,,,,,,,,,,,,,,,,,2,,7,,
|
||||||
jakarta.json,,,123,,,,,,,,,,,,,,,,,,,100,23
|
jakarta.json,,,123,,,,,,,,,,,,,,,,,,,,,100,23
|
||||||
jakarta.ws.rs.client,1,,,,,,,,,,,,,1,,,,,,,,,
|
jakarta.ws.rs.client,1,,,,,,,,,,,,,1,,,,,,,,,,,
|
||||||
jakarta.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,9,,
|
jakarta.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,9,,
|
||||||
jakarta.ws.rs.core,2,,149,,,,,,,,,,,,,,,2,,,,94,55
|
jakarta.ws.rs.core,2,,149,,,,,,,,,,,,,,,2,,,,,,94,55
|
||||||
java.beans,,,1,,,,,,,,,,,,,,,,,,,1,
|
java.beans,,,1,,,,,,,,,,,,,,,,,,,,,1,
|
||||||
java.io,3,,27,,3,,,,,,,,,,,,,,,,,26,1
|
java.io,3,,27,,3,,,,,,,,,,,,,,,,,,,26,1
|
||||||
java.lang,,,47,,,,,,,,,,,,,,,,,,,41,6
|
java.lang,,,50,,,,,,,,,,,,,,,,,,,,,41,9
|
||||||
java.net,10,3,7,,,,,,,,,,,10,,,,,,,3,7,
|
java.net,10,3,7,,,,,,,,,,,10,,,,,,,,,3,7,
|
||||||
java.nio,10,,4,,10,,,,,,,,,,,,,,,,,4,
|
java.nio,10,,4,,10,,,,,,,,,,,,,,,,,,,4,
|
||||||
java.sql,7,,,,,,,,,,,,,,,7,,,,,,,
|
java.sql,7,,,,,,,,,,,,,,,7,,,,,,,,,
|
||||||
java.util,,,337,,,,,,,,,,,,,,,,,,,15,322
|
java.util,,,337,,,,,,,,,,,,,,,,,,,,,15,322
|
||||||
javax.faces.context,2,7,,,,,,,,,,,,,,,,,,2,7,,
|
javax.faces.context,2,7,,,,,,,,,,,,,,,,,,,2,,7,,
|
||||||
javax.json,,,123,,,,,,,,,,,,,,,,,,,100,23
|
javax.json,,,123,,,,,,,,,,,,,,,,,,,,,100,23
|
||||||
javax.management.remote,2,,,,,,,,,2,,,,,,,,,,,,,
|
javax.management.remote,2,,,,,,,,,2,,,,,,,,,,,,,,,
|
||||||
javax.naming,7,,,,,,,,,6,1,,,,,,,,,,,,
|
javax.naming,7,,,,,,,,,6,1,,,,,,,,,,,,,,
|
||||||
javax.net.ssl,2,,,,,,,,,,,,,,2,,,,,,,,
|
javax.net.ssl,2,,,,,,,,,,,,,,2,,,,,,,,,,
|
||||||
javax.script,1,,,,,,,,,,,1,,,,,,,,,,,
|
javax.script,1,,,,,,,,,,,1,,,,,,,,,,,,,
|
||||||
javax.servlet,4,21,2,,,,3,1,,,,,,,,,,,,,21,2,
|
javax.servlet,4,21,2,,,,3,1,,,,,,,,,,,,,,,21,2,
|
||||||
javax.validation,1,1,,1,,,,,,,,,,,,,,,,,1,,
|
javax.validation,1,1,,1,,,,,,,,,,,,,,,,,,,1,,
|
||||||
javax.ws.rs.client,1,,,,,,,,,,,,,1,,,,,,,,,
|
javax.ws.rs.client,1,,,,,,,,,,,,,1,,,,,,,,,,,
|
||||||
javax.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,9,,
|
javax.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,9,,
|
||||||
javax.ws.rs.core,3,,149,,,,1,,,,,,,,,,,2,,,,94,55
|
javax.ws.rs.core,3,,149,,,,1,,,,,,,,,,,2,,,,,,94,55
|
||||||
javax.xml.transform.sax,,,4,,,,,,,,,,,,,,,,,,,4,
|
javax.xml.transform,1,,6,,,,,,,,,,,,,,,,,1,,,,6,
|
||||||
javax.xml.transform.stream,,,2,,,,,,,,,,,,,,,,,,,2,
|
javax.xml.xpath,3,,,,,,,,,,,,,,,,,,3,,,,,,
|
||||||
javax.xml.xpath,3,,,,,,,,,,,,,,,,,,3,,,,
|
jodd.json,,,10,,,,,,,,,,,,,,,,,,,,,,10
|
||||||
jodd.json,,,10,,,,,,,,,,,,,,,,,,,,10
|
net.sf.saxon.s9api,5,,,,,,,,,,,,,,,,,,,5,,,,,
|
||||||
ognl,6,,,,,,,,,,,,6,,,,,,,,,,
|
ognl,6,,,,,,,,,,,,6,,,,,,,,,,,,
|
||||||
org.apache.commons.codec,,,6,,,,,,,,,,,,,,,,,,,6,
|
org.apache.commons.codec,,,6,,,,,,,,,,,,,,,,,,,,,6,
|
||||||
org.apache.commons.collections,,,394,,,,,,,,,,,,,,,,,,,9,385
|
org.apache.commons.collections,,,800,,,,,,,,,,,,,,,,,,,,,17,783
|
||||||
org.apache.commons.collections4,,,394,,,,,,,,,,,,,,,,,,,9,385
|
org.apache.commons.collections4,,,800,,,,,,,,,,,,,,,,,,,,,17,783
|
||||||
org.apache.commons.io,,,22,,,,,,,,,,,,,,,,,,,22,
|
org.apache.commons.io,,,22,,,,,,,,,,,,,,,,,,,,,22,
|
||||||
org.apache.commons.jexl2,15,,,,,,,,15,,,,,,,,,,,,,,
|
org.apache.commons.jexl2,15,,,,,,,,15,,,,,,,,,,,,,,,,
|
||||||
org.apache.commons.jexl3,15,,,,,,,,15,,,,,,,,,,,,,,
|
org.apache.commons.jexl3,15,,,,,,,,15,,,,,,,,,,,,,,,,
|
||||||
org.apache.commons.lang3,,,423,,,,,,,,,,,,,,,,,,,292,131
|
org.apache.commons.lang3,,,423,,,,,,,,,,,,,,,,,,,,,292,131
|
||||||
org.apache.commons.ognl,6,,,,,,,,,,,,6,,,,,,,,,,
|
org.apache.commons.ognl,6,,,,,,,,,,,,6,,,,,,,,,,,,
|
||||||
org.apache.commons.text,,,272,,,,,,,,,,,,,,,,,,,220,52
|
org.apache.commons.text,,,272,,,,,,,,,,,,,,,,,,,,,220,52
|
||||||
org.apache.directory.ldap.client.api,1,,,,,,,,,,1,,,,,,,,,,,,
|
org.apache.directory.ldap.client.api,1,,,,,,,,,,1,,,,,,,,,,,,,,
|
||||||
org.apache.hc.core5.function,,,1,,,,,,,,,,,,,,,,,,,1,
|
org.apache.hc.core5.function,,,1,,,,,,,,,,,,,,,,,,,,,1,
|
||||||
org.apache.hc.core5.http,1,2,39,,,,,,,,,,,,,,,,,1,2,39,
|
org.apache.hc.core5.http,1,2,39,,,,,,,,,,,,,,,,,,1,,2,39,
|
||||||
org.apache.hc.core5.net,,,2,,,,,,,,,,,,,,,,,,,2,
|
org.apache.hc.core5.net,,,2,,,,,,,,,,,,,,,,,,,,,2,
|
||||||
org.apache.hc.core5.util,,,24,,,,,,,,,,,,,,,,,,,18,6
|
org.apache.hc.core5.util,,,24,,,,,,,,,,,,,,,,,,,,,18,6
|
||||||
org.apache.http,27,3,70,,,,,,,,,,,25,,,,,,2,3,62,8
|
org.apache.http,27,3,70,,,,,,,,,,,25,,,,,,,2,,3,62,8
|
||||||
org.apache.ibatis.jdbc,6,,,,,,,,,,,,,,,6,,,,,,,
|
org.apache.ibatis.jdbc,6,,,,,,,,,,,,,,,6,,,,,,,,,
|
||||||
org.apache.shiro.jndi,1,,,,,,,,,1,,,,,,,,,,,,,
|
org.apache.shiro.jndi,1,,,,,,,,,1,,,,,,,,,,,,,,,
|
||||||
org.codehaus.groovy.control,1,,,,,1,,,,,,,,,,,,,,,,,
|
org.codehaus.groovy.control,1,,,,,1,,,,,,,,,,,,,,,,,,,
|
||||||
org.dom4j,20,,,,,,,,,,,,,,,,,,20,,,,
|
org.dom4j,20,,,,,,,,,,,,,,,,,,20,,,,,,
|
||||||
org.hibernate,7,,,,,,,,,,,,,,,7,,,,,,,
|
org.hibernate,7,,,,,,,,,,,,,,,7,,,,,,,,,
|
||||||
org.jooq,1,,,,,,,,,,,,,,,1,,,,,,,
|
org.jooq,1,,,,,,,,,,,,,,,1,,,,,,,,,
|
||||||
org.json,,,236,,,,,,,,,,,,,,,,,,,198,38
|
org.json,,,236,,,,,,,,,,,,,,,,,,,,,198,38
|
||||||
org.mvel2,16,,,,,,,,,,,16,,,,,,,,,,,
|
org.mvel2,16,,,,,,,,,,,16,,,,,,,,,,,,,
|
||||||
org.springframework.beans,,,26,,,,,,,,,,,,,,,,,,,,26
|
org.springframework.beans,,,26,,,,,,,,,,,,,,,,,,,,,,26
|
||||||
org.springframework.cache,,,13,,,,,,,,,,,,,,,,,,,,13
|
org.springframework.cache,,,13,,,,,,,,,,,,,,,,,,,,,,13
|
||||||
org.springframework.http,14,,70,,,,,,,,,,,14,,,,,,,,60,10
|
org.springframework.http,14,,70,,,,,,,,,,,14,,,,,,,,,,60,10
|
||||||
org.springframework.jdbc.core,10,,,,,,,,,,,,,,,10,,,,,,,
|
org.springframework.jdbc.core,10,,,,,,,,,,,,,,,10,,,,,,,,,
|
||||||
org.springframework.jdbc.object,9,,,,,,,,,,,,,,,9,,,,,,,
|
org.springframework.jdbc.object,9,,,,,,,,,,,,,,,9,,,,,,,,,
|
||||||
org.springframework.jndi,1,,,,,,,,,1,,,,,,,,,,,,,
|
org.springframework.jndi,1,,,,,,,,,1,,,,,,,,,,,,,,,
|
||||||
org.springframework.ldap,42,,,,,,,,,28,14,,,,,,,,,,,,
|
org.springframework.ldap,42,,,,,,,,,28,14,,,,,,,,,,,,,,
|
||||||
org.springframework.security.web.savedrequest,,6,,,,,,,,,,,,,,,,,,,6,,
|
org.springframework.security.web.savedrequest,,6,,,,,,,,,,,,,,,,,,,,,6,,
|
||||||
org.springframework.ui,,,32,,,,,,,,,,,,,,,,,,,,32
|
org.springframework.ui,,,32,,,,,,,,,,,,,,,,,,,,,,32
|
||||||
org.springframework.util,,,139,,,,,,,,,,,,,,,,,,,87,52
|
org.springframework.util,,,139,,,,,,,,,,,,,,,,,,,,,87,52
|
||||||
org.springframework.validation,,,13,,,,,,,,,,,,,,,,,,,13,
|
org.springframework.validation,,,13,,,,,,,,,,,,,,,,,,,,,13,
|
||||||
org.springframework.web.client,13,3,,,,,,,,,,,,13,,,,,,,3,,
|
org.springframework.web.client,13,3,,,,,,,,,,,,13,,,,,,,,,3,,
|
||||||
org.springframework.web.context.request,,8,,,,,,,,,,,,,,,,,,,8,,
|
org.springframework.web.context.request,,8,,,,,,,,,,,,,,,,,,,,,8,,
|
||||||
org.springframework.web.multipart,,12,13,,,,,,,,,,,,,,,,,,12,13,
|
org.springframework.web.multipart,,12,13,,,,,,,,,,,,,,,,,,,,12,13,
|
||||||
org.springframework.web.reactive.function.client,2,,,,,,,,,,,,,2,,,,,,,,,
|
org.springframework.web.reactive.function.client,2,,,,,,,,,,,,,2,,,,,,,,,,,
|
||||||
org.springframework.web.util,,,163,,,,,,,,,,,,,,,,,,,138,25
|
org.springframework.web.util,,,163,,,,,,,,,,,,,,,,,,,,,138,25
|
||||||
org.xml.sax,,,1,,,,,,,,,,,,,,,,,,,1,
|
org.xml.sax,,,1,,,,,,,,,,,,,,,,,,,,,1,
|
||||||
org.xmlpull.v1,,3,,,,,,,,,,,,,,,,,,,3,,
|
org.xmlpull.v1,,3,,,,,,,,,,,,,,,,,,,,,3,,
|
||||||
play.mvc,,4,,,,,,,,,,,,,,,,,,,4,,
|
play.mvc,,4,,,,,,,,,,,,,,,,,,,,,4,,
|
||||||
|
|||||||
|
@@ -7,17 +7,17 @@ Java framework & library support
|
|||||||
:widths: auto
|
:widths: auto
|
||||||
|
|
||||||
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE‑022` :sub:`Path injection`,`CWE‑036` :sub:`Path traversal`,`CWE‑079` :sub:`Cross-site scripting`,`CWE‑089` :sub:`SQL injection`,`CWE‑090` :sub:`LDAP injection`,`CWE‑094` :sub:`Code injection`,`CWE‑319` :sub:`Cleartext transmission`
|
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE‑022` :sub:`Path injection`,`CWE‑036` :sub:`Path traversal`,`CWE‑079` :sub:`Cross-site scripting`,`CWE‑089` :sub:`SQL injection`,`CWE‑090` :sub:`LDAP injection`,`CWE‑094` :sub:`Code injection`,`CWE‑319` :sub:`Cleartext transmission`
|
||||||
Android,``android.*``,18,94,70,,,3,67,,,
|
Android,``android.*``,45,94,70,,,3,67,,,
|
||||||
`Apache Commons Collections <https://commons.apache.org/proper/commons-collections/>`_,"``org.apache.commons.collections``, ``org.apache.commons.collections4``",,788,,,,,,,,
|
`Apache Commons Collections <https://commons.apache.org/proper/commons-collections/>`_,"``org.apache.commons.collections``, ``org.apache.commons.collections4``",,1600,,,,,,,,
|
||||||
`Apache Commons IO <https://commons.apache.org/proper/commons-io/>`_,``org.apache.commons.io``,,22,,,,,,,,
|
`Apache Commons IO <https://commons.apache.org/proper/commons-io/>`_,``org.apache.commons.io``,,22,,,,,,,,
|
||||||
`Apache Commons Lang <https://commons.apache.org/proper/commons-lang/>`_,``org.apache.commons.lang3``,,423,,,,,,,,
|
`Apache Commons Lang <https://commons.apache.org/proper/commons-lang/>`_,``org.apache.commons.lang3``,,423,,,,,,,,
|
||||||
`Apache Commons Text <https://commons.apache.org/proper/commons-text/>`_,``org.apache.commons.text``,,272,,,,,,,,
|
`Apache Commons Text <https://commons.apache.org/proper/commons-text/>`_,``org.apache.commons.text``,,272,,,,,,,,
|
||||||
`Apache HttpComponents <https://hc.apache.org/>`_,"``org.apache.hc.core5.*``, ``org.apache.http``",5,136,28,,,3,,,,25
|
`Apache HttpComponents <https://hc.apache.org/>`_,"``org.apache.hc.core5.*``, ``org.apache.http``",5,136,28,,,3,,,,25
|
||||||
`Google Guava <https://guava.dev/>`_,``com.google.common.*``,,728,6,,6,,,,,
|
`Google Guava <https://guava.dev/>`_,``com.google.common.*``,,728,6,,6,,,,,
|
||||||
`JSON-java <https://github.com/stleary/JSON-java>`_,``org.json``,,236,,,,,,,,
|
`JSON-java <https://github.com/stleary/JSON-java>`_,``org.json``,,236,,,,,,,,
|
||||||
Java Standard Library,``java.*``,3,423,30,13,,,7,,,10
|
Java Standard Library,``java.*``,3,426,30,13,,,7,,,10
|
||||||
Java extensions,"``javax.*``, ``jakarta.*``",54,552,31,,,4,,1,1,2
|
Java extensions,"``javax.*``, ``jakarta.*``",54,552,32,,,4,,1,1,2
|
||||||
`Spring <https://spring.io/>`_,``org.springframework.*``,29,469,91,,,,19,14,,29
|
`Spring <https://spring.io/>`_,``org.springframework.*``,29,469,91,,,,19,14,,29
|
||||||
Others,"``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.opensymphony.xwork2.ognl``, ``com.unboundid.ldap.sdk``, ``flexjson``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``ognl``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.shiro.jndi``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jooq``, ``org.mvel2``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``",7,26,146,,,,14,18,,
|
Others,"``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.opensymphony.xwork2.ognl``, ``com.unboundid.ldap.sdk``, ``flexjson``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``net.sf.saxon.s9api``, ``ognl``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.shiro.jndi``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jooq``, ``org.mvel2``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``",7,26,151,,,,14,18,,
|
||||||
Totals,,116,4169,402,13,6,10,107,33,1,66
|
Totals,,143,4984,408,13,6,10,107,33,1,66
|
||||||
|
|
||||||
|
|||||||
@@ -726,6 +726,9 @@ class StringLiteral extends Literal, @stringliteral {
|
|||||||
*/
|
*/
|
||||||
string getRepresentedString() { result = getValue() }
|
string getRepresentedString() { result = getValue() }
|
||||||
|
|
||||||
|
/** Holds if this string literal is a text block (`""" ... """`). */
|
||||||
|
predicate isTextBlock() { getLiteral().matches("\"\"\"%") }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "StringLiteral" }
|
override string getAPrimaryQlClass() { result = "StringLiteral" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ private module Frameworks {
|
|||||||
private import semmle.code.java.security.MvelInjection
|
private import semmle.code.java.security.MvelInjection
|
||||||
private import semmle.code.java.security.OgnlInjection
|
private import semmle.code.java.security.OgnlInjection
|
||||||
private import semmle.code.java.security.XPath
|
private import semmle.code.java.security.XPath
|
||||||
|
private import semmle.code.java.security.XsltInjection
|
||||||
private import semmle.code.java.frameworks.android.Android
|
private import semmle.code.java.frameworks.android.Android
|
||||||
private import semmle.code.java.frameworks.android.SQLite
|
private import semmle.code.java.frameworks.android.SQLite
|
||||||
private import semmle.code.java.frameworks.Jdbc
|
private import semmle.code.java.frameworks.Jdbc
|
||||||
|
|||||||
@@ -247,3 +247,20 @@ class ExportedAndroidIntentInput extends RemoteFlowSource, AndroidIntentInput {
|
|||||||
|
|
||||||
override string getSourceType() { result = "Exported Android intent source" }
|
override string getSourceType() { result = "Exported Android intent source" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** A parameter of an entry-point method declared in a `ContentProvider` class. */
|
||||||
|
class AndroidContentProviderInput extends DataFlow::Node {
|
||||||
|
AndroidContentProvider declaringType;
|
||||||
|
|
||||||
|
AndroidContentProviderInput() {
|
||||||
|
sourceNode(this, "contentprovider") and
|
||||||
|
this.getEnclosingCallable().getDeclaringType() = declaringType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A parameter of an entry-point method declared in an exported `ContentProvider` class. */
|
||||||
|
class ExportedAndroidContentProviderInput extends RemoteFlowSource, AndroidContentProviderInput {
|
||||||
|
ExportedAndroidContentProviderInput() { declaringType.isExported() }
|
||||||
|
|
||||||
|
override string getSourceType() { result = "Exported Android content provider source" }
|
||||||
|
}
|
||||||
|
|||||||
@@ -95,6 +95,9 @@ private class ContainerFlowSummaries extends SummaryModelCsv {
|
|||||||
override predicate row(string row) {
|
override predicate row(string row) {
|
||||||
row =
|
row =
|
||||||
[
|
[
|
||||||
|
"java.lang;Object;true;clone;;;MapKey of Argument[-1];MapKey of ReturnValue;value",
|
||||||
|
"java.lang;Object;true;clone;;;MapValue of Argument[-1];MapValue of ReturnValue;value",
|
||||||
|
"java.lang;Object;true;clone;;;Element of Argument[-1];Element of ReturnValue;value",
|
||||||
"java.util;Map$Entry;true;getKey;;;MapKey of Argument[-1];ReturnValue;value",
|
"java.util;Map$Entry;true;getKey;;;MapKey of Argument[-1];ReturnValue;value",
|
||||||
"java.util;Map$Entry;true;getValue;;;MapValue of Argument[-1];ReturnValue;value",
|
"java.util;Map$Entry;true;getValue;;;MapValue of Argument[-1];ReturnValue;value",
|
||||||
"java.util;Map$Entry;true;setValue;;;MapValue of Argument[-1];ReturnValue;value",
|
"java.util;Map$Entry;true;setValue;;;MapValue of Argument[-1];ReturnValue;value",
|
||||||
|
|||||||
@@ -326,18 +326,24 @@ class LambdaCallKind = Method; // the "apply" method in the functional interface
|
|||||||
|
|
||||||
/** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */
|
/** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */
|
||||||
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) {
|
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) {
|
||||||
exists(FunctionalExpr func, FunctionalInterface interface |
|
exists(ClassInstanceExpr func, Interface t, FunctionalInterface interface |
|
||||||
creation.asExpr() = func and
|
creation.asExpr() = func and
|
||||||
func.asMethod() = c and
|
func.getAnonymousClass().getAMethod() = c and
|
||||||
func.getType().(RefType).getSourceDeclaration() = interface and
|
func.getConstructedType().extendsOrImplements+(t) and
|
||||||
kind = interface.getRunMethod()
|
t.getSourceDeclaration() = interface and
|
||||||
|
c.(Method).overridesOrInstantiates+(pragma[only_bind_into](kind)) and
|
||||||
|
pragma[only_bind_into](kind) = interface.getRunMethod().getSourceDeclaration()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */
|
/** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */
|
||||||
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
|
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
|
||||||
receiver = call.(SummaryCall).getReceiver() and
|
receiver = call.(SummaryCall).getReceiver() and
|
||||||
getNodeDataFlowType(receiver).getSourceDeclaration().(FunctionalInterface).getRunMethod() = kind
|
getNodeDataFlowType(receiver)
|
||||||
|
.getSourceDeclaration()
|
||||||
|
.(FunctionalInterface)
|
||||||
|
.getRunMethod()
|
||||||
|
.getSourceDeclaration() = kind
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Extra data-flow steps needed for lambda flow analysis. */
|
/** Extra data-flow steps needed for lambda flow analysis. */
|
||||||
|
|||||||
@@ -72,6 +72,14 @@ class AndroidContentProvider extends ExportableAndroidComponent {
|
|||||||
AndroidContentProvider() {
|
AndroidContentProvider() {
|
||||||
this.getASupertype*().hasQualifiedName("android.content", "ContentProvider")
|
this.getASupertype*().hasQualifiedName("android.content", "ContentProvider")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if this content provider requires read and write permissions
|
||||||
|
* in an `AndroidManifest.xml` file.
|
||||||
|
*/
|
||||||
|
predicate requiresPermissions() {
|
||||||
|
getAndroidComponentXmlElement().(AndroidProviderXmlElement).requiresPermissions()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An Android content resolver. */
|
/** An Android content resolver. */
|
||||||
@@ -148,3 +156,39 @@ private class UriModel extends SummaryModelCsv {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class ContentProviderSourceModels extends SourceModelCsv {
|
||||||
|
override predicate row(string row) {
|
||||||
|
row =
|
||||||
|
[
|
||||||
|
// ContentInterface models are here for backwards compatibility (it was removed in API 28)
|
||||||
|
"android.content;ContentInterface;true;call;(String,String,String,Bundle);;Parameter[0..3];contentprovider",
|
||||||
|
"android.content;ContentProvider;true;call;(String,String,String,Bundle);;Parameter[0..3];contentprovider",
|
||||||
|
"android.content;ContentProvider;true;call;(String,String,Bundle);;Parameter[0..2];contentprovider",
|
||||||
|
"android.content;ContentProvider;true;delete;(Uri,String,String[]);;Parameter[0..2];contentprovider",
|
||||||
|
"android.content;ContentInterface;true;delete;(Uri,Bundle);;Parameter[0..1];contentprovider",
|
||||||
|
"android.content;ContentProvider;true;delete;(Uri,Bundle);;Parameter[0..1];contentprovider",
|
||||||
|
"android.content;ContentInterface;true;getType;(Uri);;Parameter[0];contentprovider",
|
||||||
|
"android.content;ContentProvider;true;getType;(Uri);;Parameter[0];contentprovider",
|
||||||
|
"android.content;ContentInterface;true;insert;(Uri,ContentValues,Bundle);;Parameter[0];contentprovider",
|
||||||
|
"android.content;ContentProvider;true;insert;(Uri,ContentValues,Bundle);;Parameter[0..2];contentprovider",
|
||||||
|
"android.content;ContentProvider;true;insert;(Uri,ContentValues);;Parameter[0..1];contentprovider",
|
||||||
|
"android.content;ContentInterface;true;openAssetFile;(Uri,String,CancellationSignal);;Parameter[0];contentprovider",
|
||||||
|
"android.content;ContentProvider;true;openAssetFile;(Uri,String,CancellationSignal);;Parameter[0];contentprovider",
|
||||||
|
"android.content;ContentProvider;true;openAssetFile;(Uri,String);;Parameter[0];contentprovider",
|
||||||
|
"android.content;ContentInterface;true;openTypedAssetFile;(Uri,String,Bundle,CancellationSignal);;Parameter[0..2];contentprovider",
|
||||||
|
"android.content;ContentProvider;true;openTypedAssetFile;(Uri,String,Bundle,CancellationSignal);;Parameter[0..2];contentprovider",
|
||||||
|
"android.content;ContentProvider;true;openTypedAssetFile;(Uri,String,Bundle);;Parameter[0..2];contentprovider",
|
||||||
|
"android.content;ContentInterface;true;openFile;(Uri,String,CancellationSignal);;Parameter[0];contentprovider",
|
||||||
|
"android.content;ContentProvider;true;openFile;(Uri,String,CancellationSignal);;Parameter[0];contentprovider",
|
||||||
|
"android.content;ContentProvider;true;openFile;(Uri,String);;Parameter[0];contentprovider",
|
||||||
|
"android.content;ContentInterface;true;query;(Uri,String[],Bundle,CancellationSignal);;Parameter[0..2];contentprovider",
|
||||||
|
"android.content;ContentProvider;true;query;(Uri,String[],Bundle,CancellationSignal);;Parameter[0..2];contentprovider",
|
||||||
|
"android.content;ContentProvider;true;query;(Uri,String[],String,String[],String);;Parameter[0..4];contentprovider",
|
||||||
|
"android.content;ContentProvider;true;query;(Uri,String[],String,String[],String,CancellationSignal);;Parameter[0..4];contentprovider",
|
||||||
|
"android.content;ContentInterface;true;update;(Uri,ContentValues,Bundle);;Parameter[0..2];contentprovider",
|
||||||
|
"android.content;ContentProvider;true;update;(Uri,ContentValues,Bundle);;Parameter[0..2];contentprovider",
|
||||||
|
"android.content;ContentProvider;true;update;(Uri,ContentValues,String,String[]);;Parameter[0..3];contentprovider"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -136,6 +136,9 @@ private class ApacheCollectionsModel extends SummaryModelCsv {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note that when lambdas are supported we should model the package `org.apache.commons.collections4.functors`,
|
||||||
|
// and when more general callable flow is supported we should model the package
|
||||||
|
// `org.apache.commons.collections4.sequence`.
|
||||||
/**
|
/**
|
||||||
* Value-propagating models for classes in the package `org.apache.commons.collections4.keyvalue`.
|
* Value-propagating models for classes in the package `org.apache.commons.collections4.keyvalue`.
|
||||||
*/
|
*/
|
||||||
@@ -170,6 +173,24 @@ private class ApacheKeyValueModel extends SummaryModelCsv {
|
|||||||
".keyvalue;DefaultMapEntry;true;DefaultMapEntry;(KeyValue);;MapValue of Argument[0];MapValue of Argument[-1];value",
|
".keyvalue;DefaultMapEntry;true;DefaultMapEntry;(KeyValue);;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
".keyvalue;DefaultMapEntry;true;DefaultMapEntry;(Entry);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
".keyvalue;DefaultMapEntry;true;DefaultMapEntry;(Entry);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
".keyvalue;DefaultMapEntry;true;DefaultMapEntry;(Entry);;MapValue of Argument[0];MapValue of Argument[-1];value",
|
".keyvalue;DefaultMapEntry;true;DefaultMapEntry;(Entry);;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".keyvalue;MultiKey;true;MultiKey;(Object[]);;ArrayElement of Argument[0];Element of Argument[-1];value",
|
||||||
|
".keyvalue;MultiKey;true;MultiKey;(Object[],boolean);;ArrayElement of Argument[0];Element of Argument[-1];value",
|
||||||
|
".keyvalue;MultiKey;true;MultiKey;(Object,Object);;Argument[0];Element of Argument[-1];value",
|
||||||
|
".keyvalue;MultiKey;true;MultiKey;(Object,Object);;Argument[1];Element of Argument[-1];value",
|
||||||
|
".keyvalue;MultiKey;true;MultiKey;(Object,Object,Object);;Argument[0];Element of Argument[-1];value",
|
||||||
|
".keyvalue;MultiKey;true;MultiKey;(Object,Object,Object);;Argument[1];Element of Argument[-1];value",
|
||||||
|
".keyvalue;MultiKey;true;MultiKey;(Object,Object,Object);;Argument[2];Element of Argument[-1];value",
|
||||||
|
".keyvalue;MultiKey;true;MultiKey;(Object,Object,Object,Object);;Argument[0];Element of Argument[-1];value",
|
||||||
|
".keyvalue;MultiKey;true;MultiKey;(Object,Object,Object,Object);;Argument[1];Element of Argument[-1];value",
|
||||||
|
".keyvalue;MultiKey;true;MultiKey;(Object,Object,Object,Object);;Argument[2];Element of Argument[-1];value",
|
||||||
|
".keyvalue;MultiKey;true;MultiKey;(Object,Object,Object,Object);;Argument[3];Element of Argument[-1];value",
|
||||||
|
".keyvalue;MultiKey;true;MultiKey;(Object,Object,Object,Object,Object);;Argument[0];Element of Argument[-1];value",
|
||||||
|
".keyvalue;MultiKey;true;MultiKey;(Object,Object,Object,Object,Object);;Argument[1];Element of Argument[-1];value",
|
||||||
|
".keyvalue;MultiKey;true;MultiKey;(Object,Object,Object,Object,Object);;Argument[2];Element of Argument[-1];value",
|
||||||
|
".keyvalue;MultiKey;true;MultiKey;(Object,Object,Object,Object,Object);;Argument[3];Element of Argument[-1];value",
|
||||||
|
".keyvalue;MultiKey;true;MultiKey;(Object,Object,Object,Object,Object);;Argument[4];Element of Argument[-1];value",
|
||||||
|
".keyvalue;MultiKey;true;getKeys;;;Element of Argument[-1];ArrayElement of ReturnValue;value",
|
||||||
|
".keyvalue;MultiKey;true;getKey;;;Element of Argument[-1];ReturnValue;value",
|
||||||
".keyvalue;TiedMapEntry;true;TiedMapEntry;;;MapValue of Argument[0];MapValue of Argument[-1];value",
|
".keyvalue;TiedMapEntry;true;TiedMapEntry;;;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
".keyvalue;TiedMapEntry;true;TiedMapEntry;;;Argument[1];MapKey of Argument[-1];value",
|
".keyvalue;TiedMapEntry;true;TiedMapEntry;;;Argument[1];MapKey of Argument[-1];value",
|
||||||
".keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(Object,Object);;Argument[0];MapKey of Argument[-1];value",
|
".keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(Object,Object);;Argument[0];MapKey of Argument[-1];value",
|
||||||
@@ -182,6 +203,560 @@ private class ApacheKeyValueModel extends SummaryModelCsv {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value-propagating models for classes in the package `org.apache.commons.collections4.bag`.
|
||||||
|
*/
|
||||||
|
private class ApacheBagModel extends SummaryModelCsv {
|
||||||
|
override predicate row(string row) {
|
||||||
|
row =
|
||||||
|
["org.apache.commons.collections4", "org.apache.commons.collections"] +
|
||||||
|
[
|
||||||
|
// Note that when lambdas are supported we should have more models for TransformedBag, TransformedSortedBag
|
||||||
|
".bag;AbstractBagDecorator;true;AbstractBagDecorator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".bag;AbstractMapBag;true;AbstractMapBag;;;MapKey of Argument[0];Element of Argument[-1];value",
|
||||||
|
".bag;AbstractMapBag;true;getMap;;;Element of Argument[-1];MapKey of ReturnValue;value",
|
||||||
|
".bag;AbstractSortedBagDecorator;true;AbstractSortedBagDecorator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".bag;CollectionBag;true;CollectionBag;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".bag;CollectionBag;true;collectionBag;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".bag;CollectionSortedBag;true;CollectionSortedBag;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".bag;CollectionSortedBag;true;collectionSortedBag;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".bag;HashBag;true;HashBag;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".bag;PredicatedBag;true;predicatedBag;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".bag;PredicatedSortedBag;true;predicatedSortedBag;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".bag;SynchronizedBag;true;synchronizedBag;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".bag;SynchronizedSortedBag;true;synchronizedSortedBag;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".bag;TransformedBag;true;transformedBag;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".bag;TransformedSortedBag;true;transformedSortedBag;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".bag;TreeBag;true;TreeBag;(Collection);;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".bag;UnmodifiableBag;true;unmodifiableBag;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".bag;UnmodifiableSortedBag;true;unmodifiableSortedBag;;;Element of Argument[0];Element of ReturnValue;value"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value-propagating models for classes in the package `org.apache.commons.collections4.bidimap`.
|
||||||
|
*/
|
||||||
|
private class ApacheBidiMapModel extends SummaryModelCsv {
|
||||||
|
override predicate row(string row) {
|
||||||
|
row =
|
||||||
|
["org.apache.commons.collections4", "org.apache.commons.collections"] +
|
||||||
|
[
|
||||||
|
".bidimap;AbstractBidiMapDecorator;true;AbstractBidiMapDecorator;;;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".bidimap;AbstractBidiMapDecorator;true;AbstractBidiMapDecorator;;;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".bidimap;AbstractDualBidiMap;true;AbstractDualBidiMap;;;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".bidimap;AbstractDualBidiMap;true;AbstractDualBidiMap;;;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".bidimap;AbstractDualBidiMap;true;AbstractDualBidiMap;;;MapKey of Argument[1];MapValue of Argument[-1];value",
|
||||||
|
".bidimap;AbstractDualBidiMap;true;AbstractDualBidiMap;;;MapValue of Argument[1];MapKey of Argument[-1];value",
|
||||||
|
".bidimap;AbstractDualBidiMap;true;AbstractDualBidiMap;;;MapKey of Argument[2];MapValue of Argument[-1];value",
|
||||||
|
".bidimap;AbstractDualBidiMap;true;AbstractDualBidiMap;;;MapValue of Argument[2];MapKey of Argument[-1];value",
|
||||||
|
".bidimap;AbstractOrderedBidiMapDecorator;true;AbstractOrderedBidiMapDecorator;;;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".bidimap;AbstractOrderedBidiMapDecorator;true;AbstractOrderedBidiMapDecorator;;;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".bidimap;AbstractSortedBidiMapDecorator;true;AbstractSortedBidiMapDecorator;;;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".bidimap;AbstractSortedBidiMapDecorator;true;AbstractSortedBidiMapDecorator;;;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".bidimap;DualHashBidiMap;true;DualHashBidiMap;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".bidimap;DualHashBidiMap;true;DualHashBidiMap;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".bidimap;DualLinkedHashBidiMap;true;DualLinkedHashBidiMap;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".bidimap;DualLinkedHashBidiMap;true;DualLinkedHashBidiMap;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".bidimap;DualTreeBidiMap;true;DualTreeBidiMap;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".bidimap;DualTreeBidiMap;true;DualTreeBidiMap;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".bidimap;DualTreeBidiMap;true;inverseOrderedBidiMap;;;MapKey of Argument[-1];MapValue of ReturnValue;value",
|
||||||
|
".bidimap;DualTreeBidiMap;true;inverseOrderedBidiMap;;;MapValue of Argument[-1];MapKey of ReturnValue;value",
|
||||||
|
".bidimap;DualTreeBidiMap;true;inverseSortedBidiMap;;;MapKey of Argument[-1];MapValue of ReturnValue;value",
|
||||||
|
".bidimap;DualTreeBidiMap;true;inverseSortedBidiMap;;;MapValue of Argument[-1];MapKey of ReturnValue;value",
|
||||||
|
".bidimap;TreeBidiMap;true;TreeBidiMap;;;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".bidimap;TreeBidiMap;true;TreeBidiMap;;;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".bidimap;UnmodifiableBidiMap;true;unmodifiableBidiMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
|
".bidimap;UnmodifiableBidiMap;true;unmodifiableBidiMap;;;MapValue of Argument[0];MapValue of ReturnValue;value",
|
||||||
|
".bidimap;UnmodifiableOrderedBidiMap;true;unmodifiableOrderedBidiMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
|
".bidimap;UnmodifiableOrderedBidiMap;true;unmodifiableOrderedBidiMap;;;MapValue of Argument[0];MapValue of ReturnValue;value",
|
||||||
|
".bidimap;UnmodifiableOrderedBidiMap;true;inverseOrderedBidiMap;;;MapKey of Argument[-1];MapValue of ReturnValue;value",
|
||||||
|
".bidimap;UnmodifiableOrderedBidiMap;true;inverseOrderedBidiMap;;;MapValue of Argument[-1];MapKey of ReturnValue;value",
|
||||||
|
".bidimap;UnmodifiableSortedBidiMap;true;unmodifiableSortedBidiMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
|
".bidimap;UnmodifiableSortedBidiMap;true;unmodifiableSortedBidiMap;;;MapValue of Argument[0];MapValue of ReturnValue;value"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value-propagating models for classes in the package `org.apache.commons.collections4.collection`.
|
||||||
|
*/
|
||||||
|
private class ApacheCollectionModel extends SummaryModelCsv {
|
||||||
|
override predicate row(string row) {
|
||||||
|
row =
|
||||||
|
["org.apache.commons.collections4", "org.apache.commons.collections"] +
|
||||||
|
[
|
||||||
|
// Note that when lambdas are supported we should have more models for TransformedCollection
|
||||||
|
".collection;AbstractCollectionDecorator;true;AbstractCollectionDecorator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".collection;AbstractCollectionDecorator;true;decorated;;;Element of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".collection;AbstractCollectionDecorator;true;setCollection;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".collection;CompositeCollection$CollectionMutator;true;add;;;Argument[2];Element of Argument[0];value",
|
||||||
|
".collection;CompositeCollection$CollectionMutator;true;add;;;Argument[2];Element of Element of Argument[1];value",
|
||||||
|
".collection;CompositeCollection$CollectionMutator;true;addAll;;;Element of Argument[2];Element of Argument[0];value",
|
||||||
|
".collection;CompositeCollection$CollectionMutator;true;addAll;;;Element of Argument[2];Element of Element of Argument[1];value",
|
||||||
|
".collection;CompositeCollection;true;CompositeCollection;(Collection);;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".collection;CompositeCollection;true;CompositeCollection;(Collection,Collection);;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".collection;CompositeCollection;true;CompositeCollection;(Collection,Collection);;Element of Argument[1];Element of Argument[-1];value",
|
||||||
|
".collection;CompositeCollection;true;CompositeCollection;(Collection[]);;Element of ArrayElement of Argument[0];Element of Argument[-1];value",
|
||||||
|
".collection;CompositeCollection;true;addComposited;(Collection);;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".collection;CompositeCollection;true;addComposited;(Collection,Collection);;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".collection;CompositeCollection;true;addComposited;(Collection,Collection);;Element of Argument[1];Element of Argument[-1];value",
|
||||||
|
".collection;CompositeCollection;true;addComposited;(Collection[]);;Element of ArrayElement of Argument[0];Element of Argument[-1];value",
|
||||||
|
".collection;CompositeCollection;true;toCollection;;;Element of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".collection;CompositeCollection;true;getCollections;;;Element of Argument[-1];Element of Element of ReturnValue;value",
|
||||||
|
".collection;IndexedCollection;true;IndexedCollection;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".collection;IndexedCollection;true;uniqueIndexedCollection;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".collection;IndexedCollection;true;nonUniqueIndexedCollection;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".collection;IndexedCollection;true;get;;;Element of Argument[-1];ReturnValue;value",
|
||||||
|
".collection;IndexedCollection;true;values;;;Element of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".collection;PredicatedCollection$Builder;true;add;;;Argument[0];Element of Argument[-1];value",
|
||||||
|
".collection;PredicatedCollection$Builder;true;addAll;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".collection;PredicatedCollection$Builder;true;createPredicatedList;;;Element of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".collection;PredicatedCollection$Builder;true;createPredicatedList;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".collection;PredicatedCollection$Builder;true;createPredicatedSet;;;Element of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".collection;PredicatedCollection$Builder;true;createPredicatedSet;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".collection;PredicatedCollection$Builder;true;createPredicatedMultiSet;;;Element of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".collection;PredicatedCollection$Builder;true;createPredicatedMultiSet;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".collection;PredicatedCollection$Builder;true;createPredicatedBag;;;Element of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".collection;PredicatedCollection$Builder;true;createPredicatedBag;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".collection;PredicatedCollection$Builder;true;createPredicatedQueue;;;Element of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".collection;PredicatedCollection$Builder;true;createPredicatedQueue;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".collection;PredicatedCollection$Builder;true;rejectedElements;;;Element of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".collection;PredicatedCollection;true;predicatedCollection;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".collection;SynchronizedCollection;true;synchronizedCollection;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".collection;TransformedCollection;true;transformingCollection;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".collection;UnmodifiableBoundedCollection;true;unmodifiableBoundedCollection;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".collection;UnmodifiableCollection;true;unmodifiableCollection;;;Element of Argument[0];Element of ReturnValue;value"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value-propagating models for the package `org.apache.commons.collections4.iterators`.
|
||||||
|
*/
|
||||||
|
private class ApacheIteratorsModel extends SummaryModelCsv {
|
||||||
|
override predicate row(string row) {
|
||||||
|
row =
|
||||||
|
["org.apache.commons.collections4", "org.apache.commons.collections"] +
|
||||||
|
[
|
||||||
|
// Note that when lambdas are supported we should have more models for TransformIterator
|
||||||
|
".iterators;AbstractIteratorDecorator;true;AbstractIteratorDecorator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;AbstractListIteratorDecorator;true;AbstractListIteratorDecorator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;AbstractListIteratorDecorator;true;getListIterator;;;Element of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".iterators;AbstractMapIteratorDecorator;true;AbstractMapIteratorDecorator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;AbstractMapIteratorDecorator;true;AbstractMapIteratorDecorator;;;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".iterators;AbstractMapIteratorDecorator;true;getMapIterator;;;Element of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".iterators;AbstractMapIteratorDecorator;true;getMapIterator;;;MapValue of Argument[-1];MapValue of ReturnValue;value",
|
||||||
|
".iterators;AbstractOrderedMapIteratorDecorator;true;AbstractOrderedMapIteratorDecorator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;AbstractOrderedMapIteratorDecorator;true;AbstractOrderedMapIteratorDecorator;;;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".iterators;AbstractOrderedMapIteratorDecorator;true;getOrderedMapIterator;;;Element of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".iterators;AbstractOrderedMapIteratorDecorator;true;getOrderedMapIterator;;;MapValue of Argument[-1];MapValue of ReturnValue;value",
|
||||||
|
".iterators;AbstractUntypedIteratorDecorator;true;AbstractUntypedIteratorDecorator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;AbstractUntypedIteratorDecorator;true;getIterator;;;Element of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".iterators;ArrayIterator;true;ArrayIterator;;;ArrayElement of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;ArrayIterator;true;getArray;;;Element of Argument[-1];ArrayElement of ReturnValue;value",
|
||||||
|
".iterators;ArrayListIterator;true;ArrayListIterator;;;ArrayElement of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;BoundedIterator;true;BoundedIterator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;CollatingIterator;true;CollatingIterator;(Comparator,Iterator,Iterator);;Element of Argument[1];Element of Argument[-1];value",
|
||||||
|
".iterators;CollatingIterator;true;CollatingIterator;(Comparator,Iterator,Iterator);;Element of Argument[2];Element of Argument[-1];value",
|
||||||
|
".iterators;CollatingIterator;true;CollatingIterator;(Comparator,Iterator[]);;Element of ArrayElement of Argument[1];Element of Argument[-1];value",
|
||||||
|
".iterators;CollatingIterator;true;CollatingIterator;(Comparator,Collection);;Element of Element of Argument[1];Element of Argument[-1];value",
|
||||||
|
".iterators;CollatingIterator;true;addIterator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;CollatingIterator;true;setIterator;;;Element of Argument[1];Element of Argument[-1];value",
|
||||||
|
".iterators;CollatingIterator;true;getIterators;;;Element of Argument[-1];Element of Element of ReturnValue;value",
|
||||||
|
".iterators;EnumerationIterator;true;EnumerationIterator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;EnumerationIterator;true;getEnumeration;;;Element of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".iterators;EnumerationIterator;true;setEnumeration;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;FilterIterator;true;FilterIterator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;FilterIterator;true;getIterator;;;Element of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".iterators;FilterIterator;true;setIterator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;FilterListIterator;true;FilterListIterator;(ListIterator);;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;FilterListIterator;true;FilterListIterator;(ListIterator,Predicate);;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;FilterListIterator;true;getListIterator;;;Element of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".iterators;FilterListIterator;true;setListIterator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;IteratorChain;true;IteratorChain;(Iterator);;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;IteratorChain;true;IteratorChain;(Iterator,Iterator);;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;IteratorChain;true;IteratorChain;(Iterator,Iterator);;Element of Argument[1];Element of Argument[-1];value",
|
||||||
|
".iterators;IteratorChain;true;IteratorChain;(Iterator[]);;Element of ArrayElement of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;IteratorChain;true;IteratorChain;(Collection);;Element of Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;IteratorChain;true;addIterator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;IteratorEnumeration;true;IteratorEnumeration;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;IteratorEnumeration;true;getIterator;;;Element of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".iterators;IteratorEnumeration;true;setIterator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;IteratorIterable;true;IteratorIterable;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;ListIteratorWrapper;true;ListIteratorWrapper;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;LoopingIterator;true;LoopingIterator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;LoopingListIterator;true;LoopingListIterator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;ObjectArrayIterator;true;ObjectArrayIterator;;;ArrayElement of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;ObjectArrayIterator;true;getArray;;;Element of Argument[-1];ArrayElement of ReturnValue;value",
|
||||||
|
".iterators;ObjectArrayListIterator;true;ObjectArrayListIterator;;;ArrayElement of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;PeekingIterator;true;PeekingIterator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;PeekingIterator;true;peekingIterator;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".iterators;PeekingIterator;true;peek;;;Element of Argument[-1];ReturnValue;value",
|
||||||
|
".iterators;PeekingIterator;true;element;;;Element of Argument[-1];ReturnValue;value",
|
||||||
|
".iterators;PermutationIterator;true;PermutationIterator;;;Element of Argument[0];Element of Element of Argument[-1];value",
|
||||||
|
".iterators;PushbackIterator;true;PushbackIterator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;PushbackIterator;true;pushbackIterator;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".iterators;PushbackIterator;true;pushback;;;Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;ReverseListIterator;true;ReverseListIterator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;SingletonIterator;true;SingletonIterator;;;Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;SingletonListIterator;true;SingletonListIterator;;;Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;SkippingIterator;true;SkippingIterator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;UniqueFilterIterator;true;UniqueFilterIterator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;UnmodifiableIterator;true;unmodifiableIterator;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".iterators;UnmodifiableListIterator;true;umodifiableListIterator;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".iterators;UnmodifiableMapIterator;true;unmodifiableMapIterator;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".iterators;UnmodifiableMapIterator;true;unmodifiableMapIterator;;;MapValue of Argument[0];MapValue of ReturnValue;value",
|
||||||
|
".iterators;UnmodifiableOrderedMapIterator;true;unmodifiableOrderedMapIterator;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".iterators;UnmodifiableOrderedMapIterator;true;unmodifiableOrderedMapIterator;;;MapValue of Argument[0];MapValue of ReturnValue;value",
|
||||||
|
".iterators;ZippingIterator;true;ZippingIterator;(Iterator[]);;Element of ArrayElement of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;ZippingIterator;true;ZippingIterator;(Iterator,Iterator);;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;ZippingIterator;true;ZippingIterator;(Iterator,Iterator);;Element of Argument[1];Element of Argument[-1];value",
|
||||||
|
".iterators;ZippingIterator;true;ZippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".iterators;ZippingIterator;true;ZippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[1];Element of Argument[-1];value",
|
||||||
|
".iterators;ZippingIterator;true;ZippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[2];Element of Argument[-1];value"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value-propagating models for the package `org.apache.commons.collections4.list`.
|
||||||
|
*/
|
||||||
|
private class ApacheListModel extends SummaryModelCsv {
|
||||||
|
override predicate row(string row) {
|
||||||
|
row =
|
||||||
|
["org.apache.commons.collections4", "org.apache.commons.collections"] +
|
||||||
|
[
|
||||||
|
// Note that when lambdas are supported we should have more models for TransformedList
|
||||||
|
".list;AbstractLinkedList;true;AbstractLinkedList;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".list;AbstractLinkedList;true;getFirst;;;Element of Argument[-1];ReturnValue;value",
|
||||||
|
".list;AbstractLinkedList;true;getLast;;;Element of Argument[-1];ReturnValue;value",
|
||||||
|
".list;AbstractLinkedList;true;addFirst;;;Argument[0];Element of Argument[-1];value",
|
||||||
|
".list;AbstractLinkedList;true;addLast;;;Argument[0];Element of Argument[-1];value",
|
||||||
|
".list;AbstractLinkedList;true;removeFirst;;;Element of Argument[-1];ReturnValue;value",
|
||||||
|
".list;AbstractLinkedList;true;removeLast;;;Element of Argument[-1];ReturnValue;value",
|
||||||
|
".list;AbstractListDecorator;true;AbstractListDecorator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".list;AbstractSerializableListDecorator;true;AbstractSerializableListDecorator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".list;CursorableLinkedList;true;CursorableLinkedList;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".list;CursorableLinkedList;true;cursor;;;Element of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".list;FixedSizeList;true;fixedSizeList;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".list;GrowthList;true;growthList;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".list;LazyList;true;lazyList;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".list;NodeCachingLinkedList;true;NodeCachingLinkedList;(Collection);;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".list;PredicatedList;true;predicatedList;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".list;SetUniqueList;true;setUniqueList;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".list;SetUniqueList;true;asSet;;;Element of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".list;TransformedList;true;transformingList;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".list;TreeList;true;TreeList;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".list;UnmodifiableList;true;UnmodifiableList;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".list;UnmodifiableList;true;unmodifiableList;;;Element of Argument[0];Element of ReturnValue;value"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value-propagating models for the package `org.apache.commons.collections4.map`.
|
||||||
|
*/
|
||||||
|
private class ApacheMapModel extends SummaryModelCsv {
|
||||||
|
override predicate row(string row) {
|
||||||
|
row =
|
||||||
|
["org.apache.commons.collections4", "org.apache.commons.collections"] +
|
||||||
|
[
|
||||||
|
// Note that when lambdas are supported we should have more models for DefaultedMap, LazyMap, TransformedMap, TransformedSortedMap
|
||||||
|
".map;AbstractHashedMap;true;AbstractHashedMap;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".map;AbstractHashedMap;true;AbstractHashedMap;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".map;AbstractLinkedMap;true;AbstractLinkedMap;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".map;AbstractLinkedMap;true;AbstractLinkedMap;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".map;AbstractMapDecorator;true;AbstractMapDecorator;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".map;AbstractMapDecorator;true;AbstractMapDecorator;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".map;AbstractMapDecorator;true;decorated;;;MapKey of Argument[-1];MapKey of ReturnValue;value",
|
||||||
|
".map;AbstractMapDecorator;true;decorated;;;MapValue of Argument[-1];MapValue of ReturnValue;value",
|
||||||
|
".map;AbstractOrderedMapDecorator;true;AbstractOrderedMapDecorator;(OrderedMap);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".map;AbstractOrderedMapDecorator;true;AbstractOrderedMapDecorator;(OrderedMap);;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".map;AbstractSortedMapDecorator;true;AbstractSortedMapDecorator;(SortedMap);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".map;AbstractSortedMapDecorator;true;AbstractSortedMapDecorator;(SortedMap);;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".map;CaseInsensitiveMap;true;CaseInsensitiveMap;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".map;CaseInsensitiveMap;true;CaseInsensitiveMap;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".map;CompositeMap;true;CompositeMap;(Map,Map);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".map;CompositeMap;true;CompositeMap;(Map,Map);;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".map;CompositeMap;true;CompositeMap;(Map,Map);;MapKey of Argument[1];MapKey of Argument[-1];value",
|
||||||
|
".map;CompositeMap;true;CompositeMap;(Map,Map);;MapValue of Argument[1];MapValue of Argument[-1];value",
|
||||||
|
".map;CompositeMap;true;CompositeMap;(Map,Map,MapMutator);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".map;CompositeMap;true;CompositeMap;(Map,Map,MapMutator);;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".map;CompositeMap;true;CompositeMap;(Map,Map,MapMutator);;MapKey of Argument[1];MapKey of Argument[-1];value",
|
||||||
|
".map;CompositeMap;true;CompositeMap;(Map,Map,MapMutator);;MapValue of Argument[1];MapValue of Argument[-1];value",
|
||||||
|
".map;CompositeMap;true;CompositeMap;(Map[]);;MapKey of ArrayElement of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".map;CompositeMap;true;CompositeMap;(Map[]);;MapValue of ArrayElement of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".map;CompositeMap;true;CompositeMap;(Map[],MapMutator);;MapKey of ArrayElement of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".map;CompositeMap;true;CompositeMap;(Map[],MapMutator);;MapValue of ArrayElement of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".map;CompositeMap;true;addComposited;;;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".map;CompositeMap;true;addComposited;;;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".map;CompositeMap;true;removeComposited;;;MapKey of Argument[-1];MapKey of ReturnValue;value",
|
||||||
|
".map;CompositeMap;true;removeComposited;;;MapValue of Argument[-1];MapValue of ReturnValue;value",
|
||||||
|
".map;CompositeMap;true;removeComposited;;;Argument[0];ReturnValue;value",
|
||||||
|
".map;DefaultedMap;true;DefaultedMap;(Object);;Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".map;DefaultedMap;true;defaultedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
|
".map;DefaultedMap;true;defaultedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value",
|
||||||
|
".map;DefaultedMap;true;defaultedMap;(Map,Object);;Argument[1];MapValue of ReturnValue;value",
|
||||||
|
".map;EntrySetToMapIteratorAdapter;true;EntrySetToMapIteratorAdapter;;;MapKey of Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".map;EntrySetToMapIteratorAdapter;true;EntrySetToMapIteratorAdapter;;;MapValue of Element of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".map;FixedSizeMap;true;fixedSizeMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
|
".map;FixedSizeMap;true;fixedSizeMap;;;MapValue of Argument[0];MapValue of ReturnValue;value",
|
||||||
|
".map;FixedSizeSortedMap;true;fixedSizeSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
|
".map;FixedSizeSortedMap;true;fixedSizeSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value",
|
||||||
|
".map;Flat3Map;true;Flat3Map;;;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".map;Flat3Map;true;Flat3Map;;;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".map;HashedMap;true;HashedMap;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".map;HashedMap;true;HashedMap;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".map;LazyMap;true;lazyMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
|
".map;LazyMap;true;lazyMap;;;MapValue of Argument[0];MapValue of ReturnValue;value",
|
||||||
|
".map;LazySortedMap;true;lazySortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
|
".map;LazySortedMap;true;lazySortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value",
|
||||||
|
".map;LinkedMap;true;LinkedMap;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".map;LinkedMap;true;LinkedMap;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".map;LinkedMap;true;get;(int);;MapKey of Argument[-1];ReturnValue;value",
|
||||||
|
".map;LinkedMap;true;getValue;(int);;MapValue of Argument[-1];ReturnValue;value",
|
||||||
|
".map;LinkedMap;true;remove;(int);;MapValue of Argument[-1];ReturnValue;value",
|
||||||
|
".map;LinkedMap;true;asList;;;MapKey of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".map;ListOrderedMap;true;listOrderedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
|
".map;ListOrderedMap;true;listOrderedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value",
|
||||||
|
".map;ListOrderedMap;true;putAll;;;MapKey of Argument[1];MapKey of Argument[-1];value",
|
||||||
|
".map;ListOrderedMap;true;putAll;;;MapValue of Argument[1];MapValue of Argument[-1];value",
|
||||||
|
".map;ListOrderedMap;true;keyList;;;MapKey of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".map;ListOrderedMap;true;valueList;;;MapValue of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".map;ListOrderedMap;true;get;(int);;MapKey of Argument[-1];ReturnValue;value",
|
||||||
|
".map;ListOrderedMap;true;getValue;(int);;MapValue of Argument[-1];ReturnValue;value",
|
||||||
|
".map;ListOrderedMap;true;setValue;;;Argument[1];MapValue of Argument[-1];value",
|
||||||
|
".map;ListOrderedMap;true;put;;;Argument[1];MapKey of Argument[-1];value",
|
||||||
|
".map;ListOrderedMap;true;put;;;Argument[2];MapValue of Argument[-1];value",
|
||||||
|
".map;ListOrderedMap;true;remove;(int);;MapValue of Argument[-1];ReturnValue;value",
|
||||||
|
".map;ListOrderedMap;true;asList;;;MapKey of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".map;LRUMap;true;LRUMap;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".map;LRUMap;true;LRUMap;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".map;LRUMap;true;LRUMap;(Map,boolean);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".map;LRUMap;true;LRUMap;(Map,boolean);;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".map;LRUMap;true;get;(Object,boolean);;MapValue of Argument[0];ReturnValue;value",
|
||||||
|
".map;MultiKeyMap;true;get;;;MapValue of Argument[-1];ReturnValue;value",
|
||||||
|
".map;MultiKeyMap;true;put;;;MapValue of Argument[-1];ReturnValue;value",
|
||||||
|
".map;MultiKeyMap;true;put;(Object,Object,Object);;Argument[0..1];Element of MapKey of Argument[-1];value",
|
||||||
|
".map;MultiKeyMap;true;put;(Object,Object,Object,Object);;Argument[0..2];Element of MapKey of Argument[-1];value",
|
||||||
|
".map;MultiKeyMap;true;put;(Object,Object,Object,Object,Object);;Argument[0..3];Element of MapKey of Argument[-1];value",
|
||||||
|
".map;MultiKeyMap;true;put;(Object,Object,Object,Object,Object,Object);;Argument[0..4];Element of MapKey of Argument[-1];value",
|
||||||
|
".map;MultiKeyMap;true;put;(Object,Object,Object);;Argument[2];MapValue of Argument[-1];value",
|
||||||
|
".map;MultiKeyMap;true;put;(Object,Object,Object,Object);;Argument[3];MapValue of Argument[-1];value",
|
||||||
|
".map;MultiKeyMap;true;put;(Object,Object,Object,Object,Object);;Argument[4];MapValue of Argument[-1];value",
|
||||||
|
".map;MultiKeyMap;true;put;(Object,Object,Object,Object,Object,Object);;Argument[5];MapValue of Argument[-1];value",
|
||||||
|
".map;MultiKeyMap;true;removeMultiKey;;;MapValue of Argument[-1];ReturnValue;value",
|
||||||
|
".map;MultiValueMap;true;multiValueMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
|
".map;MultiValueMap;true;multiValueMap;;;Element of MapValue of Argument[0];Element of MapValue of ReturnValue;value",
|
||||||
|
".map;MultiValueMap;true;getCollection;;;Element of MapValue of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".map;MultiValueMap;true;putAll;(Map);;MapValue of Argument[0];Element of MapValue of Argument[-1];value",
|
||||||
|
".map;MultiValueMap;true;putAll;(Map);;Element of MapValue of Argument[0];Element of MapValue of Argument[-1];value",
|
||||||
|
".map;MultiValueMap;true;values;;;Element of MapValue of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".map;MultiValueMap;true;putAll;(Object,Collection);;Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".map;MultiValueMap;true;putAll;(Object,Collection);;Element of Argument[1];Element of MapValue of Argument[-1];value",
|
||||||
|
".map;MultiValueMap;true;iterator;(Object);;Element of MapValue of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".map;MultiValueMap;true;iterator;();;MapKey of Argument[-1];MapKey of Element of ReturnValue;value",
|
||||||
|
".map;MultiValueMap;true;iterator;();;Element of MapValue of Argument[-1];MapValue of Element of ReturnValue;value",
|
||||||
|
".map;PassiveExpiringMap;true;PassiveExpiringMap;(ExpirationPolicy,Map);;MapKey of Argument[1];MapKey of Argument[-1];value",
|
||||||
|
".map;PassiveExpiringMap;true;PassiveExpiringMap;(ExpirationPolicy,Map);;MapValue of Argument[1];MapValue of Argument[-1];value",
|
||||||
|
".map;PassiveExpiringMap;true;PassiveExpiringMap;(long,Map);;MapKey of Argument[1];MapKey of Argument[-1];value",
|
||||||
|
".map;PassiveExpiringMap;true;PassiveExpiringMap;(long,Map);;MapValue of Argument[1];MapValue of Argument[-1];value",
|
||||||
|
".map;PassiveExpiringMap;true;PassiveExpiringMap;(long,TimeUnit,Map);;MapKey of Argument[2];MapKey of Argument[-1];value",
|
||||||
|
".map;PassiveExpiringMap;true;PassiveExpiringMap;(long,TimeUnit,Map);;MapValue of Argument[2];MapValue of Argument[-1];value",
|
||||||
|
".map;PassiveExpiringMap;true;PassiveExpiringMap;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".map;PassiveExpiringMap;true;PassiveExpiringMap;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".map;PredicatedMap;true;predicatedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
|
".map;PredicatedMap;true;predicatedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value",
|
||||||
|
".map;PredicatedSortedMap;true;predicatedSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
|
".map;PredicatedSortedMap;true;predicatedSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value",
|
||||||
|
".map;SingletonMap;true;SingletonMap;(Object,Object);;Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".map;SingletonMap;true;SingletonMap;(Object,Object);;Argument[1];MapValue of Argument[-1];value",
|
||||||
|
".map;SingletonMap;true;SingletonMap;(KeyValue);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".map;SingletonMap;true;SingletonMap;(KeyValue);;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".map;SingletonMap;true;SingletonMap;(Entry);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".map;SingletonMap;true;SingletonMap;(Entry);;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".map;SingletonMap;true;SingletonMap;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".map;SingletonMap;true;SingletonMap;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".map;SingletonMap;true;setValue;;;Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".map;TransformedMap;true;transformingMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
|
".map;TransformedMap;true;transformingMap;;;MapValue of Argument[0];MapValue of ReturnValue;value",
|
||||||
|
".map;TransformedSortedMap;true;transformingSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
|
".map;TransformedSortedMap;true;transformingSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value",
|
||||||
|
".map;UnmodifiableEntrySet;true;unmodifiableEntrySet;;;MapKey of Element of Argument[0];MapKey of Element of ReturnValue;value",
|
||||||
|
".map;UnmodifiableEntrySet;true;unmodifiableEntrySet;;;MapValue of Element of Argument[0];MapValue of Element of ReturnValue;value",
|
||||||
|
".map;UnmodifiableMap;true;unmodifiableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
|
".map;UnmodifiableMap;true;unmodifiableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value",
|
||||||
|
".map;UnmodifiableOrderedMap;true;unmodifiableOrderedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
|
".map;UnmodifiableOrderedMap;true;unmodifiableOrderedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value",
|
||||||
|
".map;UnmodifiableSortedMap;true;unmodifiableSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
|
".map;UnmodifiableSortedMap;true;unmodifiableSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value-propagating models for the package `org.apache.commons.collections4.multimap`.
|
||||||
|
*/
|
||||||
|
private class ApacheMultiMapModel extends SummaryModelCsv {
|
||||||
|
override predicate row(string row) {
|
||||||
|
row =
|
||||||
|
["org.apache.commons.collections4", "org.apache.commons.collections"] +
|
||||||
|
[
|
||||||
|
// Note that when lambdas are supported we should have more models for TransformedMultiValuedMap
|
||||||
|
".multimap;ArrayListValuedHashMap;true;ArrayListValuedHashMap;(MultiValuedMap);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".multimap;ArrayListValuedHashMap;true;ArrayListValuedHashMap;(MultiValuedMap);;Element of MapValue of Argument[0];Element of MapValue of Argument[-1];value",
|
||||||
|
".multimap;ArrayListValuedHashMap;true;ArrayListValuedHashMap;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".multimap;ArrayListValuedHashMap;true;ArrayListValuedHashMap;(Map);;MapValue of Argument[0];Element of MapValue of Argument[-1];value",
|
||||||
|
".multimap;HashSetValuedHashMap;true;HashSetValuedHashMap;(MultiValuedMap);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".multimap;HashSetValuedHashMap;true;HashSetValuedHashMap;(MultiValuedMap);;Element of MapValue of Argument[0];Element of MapValue of Argument[-1];value",
|
||||||
|
".multimap;HashSetValuedHashMap;true;HashSetValuedHashMap;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".multimap;HashSetValuedHashMap;true;HashSetValuedHashMap;(Map);;MapValue of Argument[0];Element of MapValue of Argument[-1];value",
|
||||||
|
".multimap;TransformedMultiValuedMap;true;transformingMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
|
".multimap;TransformedMultiValuedMap;true;transformingMap;;;Element of MapValue of Argument[0];Element of MapValue of ReturnValue;value",
|
||||||
|
".multimap;UnmodifiableMultiValuedMap;true;unmodifiableMultiValuedMap;(MultiValuedMap);;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
|
".multimap;UnmodifiableMultiValuedMap;true;unmodifiableMultiValuedMap;(MultiValuedMap);;Element of MapValue of Argument[0];Element of MapValue of ReturnValue;value"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value-propagating models for the package `org.apache.commons.collections4.multiset`.
|
||||||
|
*/
|
||||||
|
private class ApacheMultiSetModel extends SummaryModelCsv {
|
||||||
|
override predicate row(string row) {
|
||||||
|
row =
|
||||||
|
["org.apache.commons.collections4", "org.apache.commons.collections"] +
|
||||||
|
[
|
||||||
|
".multiset;HashMultiSet;true;HashMultiSet;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".multiset;PredicatedMultiSet;true;predicatedMultiSet;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".multiset;SynchronizedMultiSet;true;synchronizedMultiSet;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".multiset;UnmodifiableMultiSet;true;unmodifiableMultiSet;;;Element of Argument[0];Element of ReturnValue;value"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value-propagating models for the package `org.apache.commons.collections4.properties`.
|
||||||
|
*/
|
||||||
|
private class ApachePropertiesModel extends SummaryModelCsv {
|
||||||
|
override predicate row(string row) {
|
||||||
|
row =
|
||||||
|
["org.apache.commons.collections4", "org.apache.commons.collections"] +
|
||||||
|
[
|
||||||
|
".properties;AbstractPropertiesFactory;true;load;(ClassLoader,String);;Argument[1];ReturnValue;taint",
|
||||||
|
".properties;AbstractPropertiesFactory;true;load;(File);;Argument[0];ReturnValue;taint",
|
||||||
|
".properties;AbstractPropertiesFactory;true;load;(InputStream);;Argument[0];ReturnValue;taint",
|
||||||
|
".properties;AbstractPropertiesFactory;true;load;(Path);;Argument[0];ReturnValue;taint",
|
||||||
|
".properties;AbstractPropertiesFactory;true;load;(Reader);;Argument[0];ReturnValue;taint",
|
||||||
|
".properties;AbstractPropertiesFactory;true;load;(String);;Argument[0];ReturnValue;taint",
|
||||||
|
".properties;AbstractPropertiesFactory;true;load;(URI);;Argument[0];ReturnValue;taint",
|
||||||
|
".properties;AbstractPropertiesFactory;true;load;(URL);;Argument[0];ReturnValue;taint"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value-propagating models for the package `org.apache.commons.collections4.queue`.
|
||||||
|
*/
|
||||||
|
private class ApacheQueueModel extends SummaryModelCsv {
|
||||||
|
override predicate row(string row) {
|
||||||
|
row =
|
||||||
|
["org.apache.commons.collections4", "org.apache.commons.collections"] +
|
||||||
|
[
|
||||||
|
// Note that when lambdas are supported we should have more models for TransformedQueue
|
||||||
|
".queue;CircularFifoQueue;true;CircularFifoQueue;(Collection);;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".queue;CircularFifoQueue;true;get;;;Element of Argument[-1];ReturnValue;value",
|
||||||
|
".queue;PredicatedQueue;true;predicatedQueue;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".queue;SynchronizedQueue;true;synchronizedQueue;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".queue;TransformedQueue;true;transformingQueue;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".queue;UnmodifiableQueue;true;unmodifiableQueue;;;Element of Argument[0];Element of ReturnValue;value"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value-propagating models for the package `org.apache.commons.collections4.set`.
|
||||||
|
*/
|
||||||
|
private class ApacheSetModel extends SummaryModelCsv {
|
||||||
|
override predicate row(string row) {
|
||||||
|
row =
|
||||||
|
["org.apache.commons.collections4", "org.apache.commons.collections"] +
|
||||||
|
[
|
||||||
|
// Note that when lambdas are supported we should have more models for TransformedNavigableSet
|
||||||
|
".set;AbstractNavigableSetDecorator;true;AbstractNavigableSetDecorator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".set;AbstractSetDecorator;true;AbstractSetDecorator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".set;AbstractSortedSetDecorator;true;AbstractSortedSetDecorator;;;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".set;CompositeSet$SetMutator;true;add;;;Argument[2];Element of Argument[0];value",
|
||||||
|
".set;CompositeSet$SetMutator;true;add;;;Argument[2];Element of Element of Argument[1];value",
|
||||||
|
".set;CompositeSet$SetMutator;true;addAll;;;Element of Argument[2];Element of Argument[0];value",
|
||||||
|
".set;CompositeSet$SetMutator;true;addAll;;;Element of Argument[2];Element of Element of Argument[1];value",
|
||||||
|
".set;CompositeSet;true;CompositeSet;(Set);;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".set;CompositeSet;true;CompositeSet;(Set[]);;Element of ArrayElement of Argument[0];Element of Argument[-1];value",
|
||||||
|
".set;CompositeSet;true;addComposited;(Set);;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".set;CompositeSet;true;addComposited;(Set,Set);;Element of Argument[0];Element of Argument[-1];value",
|
||||||
|
".set;CompositeSet;true;addComposited;(Set,Set);;Element of Argument[1];Element of Argument[-1];value",
|
||||||
|
".set;CompositeSet;true;addComposited;(Set[]);;Element of ArrayElement of Argument[0];Element of Argument[-1];value",
|
||||||
|
".set;CompositeSet;true;toSet;;;Element of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".set;CompositeSet;true;getSets;;;Element of Argument[-1];Element of Element of ReturnValue;value",
|
||||||
|
".set;ListOrderedSet;true;listOrderedSet;(Set);;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".set;ListOrderedSet;true;listOrderedSet;(List);;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".set;ListOrderedSet;true;asList;;;Element of Argument[-1];Element of ReturnValue;value",
|
||||||
|
".set;ListOrderedSet;true;get;;;Element of Argument[-1];ReturnValue;value",
|
||||||
|
".set;ListOrderedSet;true;add;;;Argument[1];Element of Argument[-1];value",
|
||||||
|
".set;ListOrderedSet;true;addAll;;;Element of Argument[1];Element of Argument[-1];value",
|
||||||
|
".set;MapBackedSet;true;mapBackedSet;;;MapKey of Argument[0];Element of ReturnValue;value",
|
||||||
|
".set;PredicatedNavigableSet;true;predicatedNavigableSet;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".set;PredicatedSet;true;predicatedSet;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".set;PredicatedSortedSet;true;predicatedSortedSet;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".set;TransformedNavigableSet;true;transformingNavigableSet;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".set;TransformedSet;true;transformingSet;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".set;TransformedSortedSet;true;transformingSortedSet;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".set;UnmodifiableNavigableSet;true;unmodifiableNavigableSet;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".set;UnmodifiableSet;true;unmodifiableSet;;;Element of Argument[0];Element of ReturnValue;value",
|
||||||
|
".set;UnmodifiableSortedSet;true;unmodifiableSortedSet;;;Element of Argument[0];Element of ReturnValue;value"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value-propagating models for the package `org.apache.commons.collections4.splitmap`.
|
||||||
|
*/
|
||||||
|
private class ApacheSplitMapModel extends SummaryModelCsv {
|
||||||
|
override predicate row(string row) {
|
||||||
|
row =
|
||||||
|
["org.apache.commons.collections4", "org.apache.commons.collections"] +
|
||||||
|
[
|
||||||
|
// Note that when lambdas are supported we should have more models for TransformedSplitMap
|
||||||
|
".splitmap;AbstractIterableGetMapDecorator;true;AbstractIterableGetMapDecorator;;;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".splitmap;AbstractIterableGetMapDecorator;true;AbstractIterableGetMapDecorator;;;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".splitmap;TransformedSplitMap;true;transformingMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
|
".splitmap;TransformedSplitMap;true;transformingMap;;;MapValue of Argument[0];MapValue of ReturnValue;value"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value-propagating models for the package `org.apache.commons.collections4.trie`.
|
||||||
|
*/
|
||||||
|
private class ApacheTrieModel extends SummaryModelCsv {
|
||||||
|
override predicate row(string row) {
|
||||||
|
row =
|
||||||
|
["org.apache.commons.collections4", "org.apache.commons.collections"] +
|
||||||
|
[
|
||||||
|
// Note that when lambdas are supported we should have more models for TransformedSplitMap
|
||||||
|
".trie;PatriciaTrie;true;PatriciaTrie;;;MapKey of Argument[0];MapKey of Argument[-1];value",
|
||||||
|
".trie;PatriciaTrie;true;PatriciaTrie;;;MapValue of Argument[0];MapValue of Argument[-1];value",
|
||||||
|
".trie;AbstractPatriciaTrie;true;select;;;MapKey of Argument[-1];MapKey of ReturnValue;value",
|
||||||
|
".trie;AbstractPatriciaTrie;true;select;;;MapValue of Argument[-1];MapValue of ReturnValue;value",
|
||||||
|
".trie;AbstractPatriciaTrie;true;selectKey;;;MapKey of Argument[-1];ReturnValue;value",
|
||||||
|
".trie;AbstractPatriciaTrie;true;selectValue;;;MapValue of Argument[-1];ReturnValue;value",
|
||||||
|
".trie;UnmodifiableTrie;true;unmodifiableTrie;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
|
".trie;UnmodifiableTrie;true;unmodifiableTrie;;;MapValue of Argument[0];MapValue of ReturnValue;value"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Value-propagating models for the class `org.apache.commons.collections4.MapUtils`.
|
* Value-propagating models for the class `org.apache.commons.collections4.MapUtils`.
|
||||||
*/
|
*/
|
||||||
@@ -217,7 +792,7 @@ private class ApacheMapUtilsModel extends SummaryModelCsv {
|
|||||||
";MapUtils;true;orderedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
";MapUtils;true;orderedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
";MapUtils;true;orderedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value",
|
";MapUtils;true;orderedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value",
|
||||||
";MapUtils;true;populateMap;(Map,Iterable,Transformer);;Element of Argument[1];MapValue of Argument[0];value",
|
";MapUtils;true;populateMap;(Map,Iterable,Transformer);;Element of Argument[1];MapValue of Argument[0];value",
|
||||||
";MapUtils;true;populateMap;(MultiMap,Iterable,Transformer);;Element of Argument[1];MapValue of Argument[0];value",
|
";MapUtils;true;populateMap;(MultiMap,Iterable,Transformer);;Element of Argument[1];Element of MapValue of Argument[0];value",
|
||||||
";MapUtils;true;predicatedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
";MapUtils;true;predicatedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
";MapUtils;true;predicatedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value",
|
";MapUtils;true;predicatedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value",
|
||||||
";MapUtils;true;predicatedSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
";MapUtils;true;predicatedSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
@@ -488,9 +1063,9 @@ private class ApacheMultiMapUtilsModel extends SummaryModelCsv {
|
|||||||
";MultiMapUtils;true;getValuesAsList;;;Element of MapValue of Argument[0];Element of ReturnValue;value",
|
";MultiMapUtils;true;getValuesAsList;;;Element of MapValue of Argument[0];Element of ReturnValue;value",
|
||||||
";MultiMapUtils;true;getValuesAsSet;;;Element of MapValue of Argument[0];Element of ReturnValue;value",
|
";MultiMapUtils;true;getValuesAsSet;;;Element of MapValue of Argument[0];Element of ReturnValue;value",
|
||||||
";MultiMapUtils;true;transformedMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
";MultiMapUtils;true;transformedMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
";MultiMapUtils;true;transformedMultiValuedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value",
|
";MultiMapUtils;true;transformedMultiValuedMap;;;Element of MapValue of Argument[0];Element of MapValue of ReturnValue;value",
|
||||||
";MultiMapUtils;true;unmodifiableMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
";MultiMapUtils;true;unmodifiableMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value",
|
||||||
";MultiMapUtils;true;unmodifiableMultiValuedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value"
|
";MultiMapUtils;true;unmodifiableMultiValuedMap;;;Element of MapValue of Argument[0];Element of MapValue of ReturnValue;value"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* Provides classes for working with the Spring Expression Language (SpEL).
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Methods that trigger the evaluation of a SpEL expression.
|
||||||
|
*/
|
||||||
|
class ExpressionEvaluationMethod extends Method {
|
||||||
|
ExpressionEvaluationMethod() {
|
||||||
|
this.getDeclaringType().getASupertype*() instanceof Expression and
|
||||||
|
this.hasName(["getValue", "getValueTypeDescriptor", "getValueType", "setValue"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class `org.springframework.expression.ExpressionParser`.
|
||||||
|
*/
|
||||||
|
class ExpressionParser extends RefType {
|
||||||
|
ExpressionParser() { hasQualifiedName("org.springframework.expression", "ExpressionParser") }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class `org.springframework.expression.spel.support.SimpleEvaluationContext$Builder`.
|
||||||
|
*/
|
||||||
|
class SimpleEvaluationContextBuilder extends RefType {
|
||||||
|
SimpleEvaluationContextBuilder() {
|
||||||
|
hasQualifiedName("org.springframework.expression.spel.support",
|
||||||
|
"SimpleEvaluationContext$Builder")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class `org.springframework.expression.Expression`.
|
||||||
|
*/
|
||||||
|
class Expression extends RefType {
|
||||||
|
Expression() { hasQualifiedName("org.springframework.expression", "Expression") }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class `org.springframework.expression.spel.support.SimpleEvaluationContext`.
|
||||||
|
*/
|
||||||
|
class SimpleEvaluationContext extends RefType {
|
||||||
|
SimpleEvaluationContext() {
|
||||||
|
hasQualifiedName("org.springframework.expression.spel.support", "SimpleEvaluationContext")
|
||||||
|
}
|
||||||
|
}
|
||||||
42
java/ql/lib/semmle/code/java/security/SpelInjection.qll
Normal file
42
java/ql/lib/semmle/code/java/security/SpelInjection.qll
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/** Provides classes to reason about SpEL injection attacks. */
|
||||||
|
|
||||||
|
import java
|
||||||
|
private import semmle.code.java.dataflow.DataFlow
|
||||||
|
private import semmle.code.java.dataflow.ExternalFlow
|
||||||
|
private import semmle.code.java.frameworks.spring.SpringExpression
|
||||||
|
|
||||||
|
/** A data flow sink for unvalidated user input that is used to construct SpEL expressions. */
|
||||||
|
abstract class SpelExpressionEvaluationSink extends DataFlow::ExprNode { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A unit class for adding additional taint steps.
|
||||||
|
*
|
||||||
|
* Extend this class to add additional taint steps that should apply to the `SpELInjectionConfig`.
|
||||||
|
*/
|
||||||
|
class SpelExpressionInjectionAdditionalTaintStep extends Unit {
|
||||||
|
/**
|
||||||
|
* Holds if the step from `node1` to `node2` should be considered a taint
|
||||||
|
* step for the `SpELInjectionConfig` configuration.
|
||||||
|
*/
|
||||||
|
abstract predicate step(DataFlow::Node node1, DataFlow::Node node2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A set of additional taint steps to consider when taint tracking SpEL related data flows. */
|
||||||
|
private class DefaultSpelExpressionInjectionAdditionalTaintStep extends SpelExpressionInjectionAdditionalTaintStep {
|
||||||
|
override predicate step(DataFlow::Node node1, DataFlow::Node node2) {
|
||||||
|
expressionParsingStep(node1, node2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `node1` to `node2` is a dataflow step that parses a SpEL expression,
|
||||||
|
* by calling `parser.parseExpression(tainted)`.
|
||||||
|
*/
|
||||||
|
private predicate expressionParsingStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||||
|
exists(MethodAccess ma, Method m | ma.getMethod() = m |
|
||||||
|
m.getDeclaringType().getASupertype*() instanceof ExpressionParser and
|
||||||
|
m.hasName(["parseExpression", "parseRaw"]) and
|
||||||
|
ma.getAnArgument() = node1.asExpr() and
|
||||||
|
node2.asExpr() = ma
|
||||||
|
)
|
||||||
|
}
|
||||||
86
java/ql/lib/semmle/code/java/security/SpelInjectionQuery.qll
Normal file
86
java/ql/lib/semmle/code/java/security/SpelInjectionQuery.qll
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
/** Provides taint tracking and dataflow configurations to be used in SpEL injection queries. */
|
||||||
|
|
||||||
|
import java
|
||||||
|
private import semmle.code.java.dataflow.FlowSources
|
||||||
|
private import semmle.code.java.dataflow.TaintTracking
|
||||||
|
private import semmle.code.java.frameworks.spring.SpringExpression
|
||||||
|
private import semmle.code.java.security.SpelInjection
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A taint-tracking configuration for unsafe user input
|
||||||
|
* that is used to construct and evaluate a SpEL expression.
|
||||||
|
*/
|
||||||
|
class SpelInjectionConfig extends TaintTracking::Configuration {
|
||||||
|
SpelInjectionConfig() { this = "SpelInjectionConfig" }
|
||||||
|
|
||||||
|
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
||||||
|
|
||||||
|
override predicate isSink(DataFlow::Node sink) { sink instanceof SpelExpressionEvaluationSink }
|
||||||
|
|
||||||
|
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||||
|
any(SpelExpressionInjectionAdditionalTaintStep c).step(node1, node2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Default sink for SpEL injection vulnerabilities. */
|
||||||
|
private class DefaultSpelExpressionEvaluationSink extends SpelExpressionEvaluationSink {
|
||||||
|
DefaultSpelExpressionEvaluationSink() {
|
||||||
|
exists(MethodAccess ma |
|
||||||
|
ma.getMethod() instanceof ExpressionEvaluationMethod and
|
||||||
|
ma.getQualifier() = this.asExpr() and
|
||||||
|
not exists(SafeEvaluationContextFlowConfig config |
|
||||||
|
config.hasFlowTo(DataFlow::exprNode(ma.getArgument(0)))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A configuration for safe evaluation context that may be used in expression evaluation.
|
||||||
|
*/
|
||||||
|
private class SafeEvaluationContextFlowConfig extends DataFlow2::Configuration {
|
||||||
|
SafeEvaluationContextFlowConfig() { this = "SpelInjection::SafeEvaluationContextFlowConfig" }
|
||||||
|
|
||||||
|
override predicate isSource(DataFlow::Node source) { source instanceof SafeContextSource }
|
||||||
|
|
||||||
|
override predicate isSink(DataFlow::Node sink) {
|
||||||
|
exists(MethodAccess ma |
|
||||||
|
ma.getMethod() instanceof ExpressionEvaluationMethod and
|
||||||
|
ma.getArgument(0) = sink.asExpr()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override int fieldFlowBranchLimit() { result = 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A `ContextSource` that is safe from SpEL injection.
|
||||||
|
*/
|
||||||
|
private class SafeContextSource extends DataFlow::ExprNode {
|
||||||
|
SafeContextSource() {
|
||||||
|
isSimpleEvaluationContextConstructorCall(getExpr()) or
|
||||||
|
isSimpleEvaluationContextBuilderCall(getExpr())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `expr` constructs `SimpleEvaluationContext`.
|
||||||
|
*/
|
||||||
|
private predicate isSimpleEvaluationContextConstructorCall(Expr expr) {
|
||||||
|
exists(ConstructorCall cc |
|
||||||
|
cc.getConstructedType() instanceof SimpleEvaluationContext and
|
||||||
|
cc = expr
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `expr` builds `SimpleEvaluationContext` via `SimpleEvaluationContext.Builder`,
|
||||||
|
* for instance, `SimpleEvaluationContext.forReadWriteDataBinding().build()`.
|
||||||
|
*/
|
||||||
|
private predicate isSimpleEvaluationContextBuilderCall(Expr expr) {
|
||||||
|
exists(MethodAccess ma, Method m | ma.getMethod() = m |
|
||||||
|
m.getDeclaringType() instanceof SimpleEvaluationContextBuilder and
|
||||||
|
m.hasName("build") and
|
||||||
|
ma = expr
|
||||||
|
)
|
||||||
|
}
|
||||||
248
java/ql/lib/semmle/code/java/security/XsltInjection.qll
Normal file
248
java/ql/lib/semmle/code/java/security/XsltInjection.qll
Normal file
@@ -0,0 +1,248 @@
|
|||||||
|
/** Provides classes to reason about XSLT injection vulnerabilities. */
|
||||||
|
|
||||||
|
import java
|
||||||
|
import semmle.code.java.dataflow.DataFlow
|
||||||
|
import semmle.code.java.dataflow.ExternalFlow
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A data flow sink for unvalidated user input that is used in XSLT transformation.
|
||||||
|
* Extend this class to add your own XSLT Injection sinks.
|
||||||
|
*/
|
||||||
|
abstract class XsltInjectionSink extends DataFlow::Node { }
|
||||||
|
|
||||||
|
/** A default sink representing methods susceptible to XSLT Injection attacks. */
|
||||||
|
private class DefaultXsltInjectionSink extends XsltInjectionSink {
|
||||||
|
DefaultXsltInjectionSink() { sinkNode(this, "xslt") }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DefaultXsltInjectionSinkModel extends SinkModelCsv {
|
||||||
|
override predicate row(string row) {
|
||||||
|
row =
|
||||||
|
[
|
||||||
|
"javax.xml.transform;Transformer;false;transform;;;Argument[-1];xslt",
|
||||||
|
"net.sf.saxon.s9api;XsltTransformer;false;transform;;;Argument[-1];xslt",
|
||||||
|
"net.sf.saxon.s9api;Xslt30Transformer;false;transform;;;Argument[-1];xslt",
|
||||||
|
"net.sf.saxon.s9api;Xslt30Transformer;false;applyTemplates;;;Argument[-1];xslt",
|
||||||
|
"net.sf.saxon.s9api;Xslt30Transformer;false;callFunction;;;Argument[-1];xslt",
|
||||||
|
"net.sf.saxon.s9api;Xslt30Transformer;false;callTemplate;;;Argument[-1];xslt"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A unit class for adding additional taint steps.
|
||||||
|
*
|
||||||
|
* Extend this class to add additional taint steps that should apply to the `XsltInjectionFlowConfig`.
|
||||||
|
*/
|
||||||
|
class XsltInjectionAdditionalTaintStep extends Unit {
|
||||||
|
/**
|
||||||
|
* Holds if the step from `node1` to `node2` should be considered a taint
|
||||||
|
* step for the `XsltInjectionFlowConfig` configuration.
|
||||||
|
*/
|
||||||
|
abstract predicate step(DataFlow::Node node1, DataFlow::Node node2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A set of additional taint steps to consider when taint tracking XSLT related data flows. */
|
||||||
|
private class DefaultXsltInjectionAdditionalTaintStep extends XsltInjectionAdditionalTaintStep {
|
||||||
|
override predicate step(DataFlow::Node node1, DataFlow::Node node2) {
|
||||||
|
xmlStreamReaderStep(node1, node2) or
|
||||||
|
xmlEventReaderStep(node1, node2) or
|
||||||
|
staxSourceStep(node1, node2) or
|
||||||
|
documentBuilderStep(node1, node2) or
|
||||||
|
domSourceStep(node1, node2) or
|
||||||
|
newTransformerFromTemplatesStep(node1, node2) or
|
||||||
|
xsltCompilerStep(node1, node2) or
|
||||||
|
xsltExecutableStep(node1, node2) or
|
||||||
|
xsltPackageStep(node1, node2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `n1` to `n2` is a dataflow step that converts between `InputStream` or `Reader` and
|
||||||
|
* `XMLStreamReader`, i.e. `XMLInputFactory.createXMLStreamReader(tainted)`.
|
||||||
|
*/
|
||||||
|
private predicate xmlStreamReaderStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||||
|
exists(XmlInputFactoryStreamReader xmlStreamReader |
|
||||||
|
if xmlStreamReader.getMethod().getParameterType(0) instanceof TypeString
|
||||||
|
then n1.asExpr() = xmlStreamReader.getArgument(1)
|
||||||
|
else n1.asExpr() = xmlStreamReader.getArgument(0)
|
||||||
|
|
|
||||||
|
n2.asExpr() = xmlStreamReader
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `n1` to `n2` is a dataflow step that converts between `InputStream` or `Reader` and
|
||||||
|
* `XMLEventReader`, i.e. `XMLInputFactory.createXMLEventReader(tainted)`.
|
||||||
|
*/
|
||||||
|
private predicate xmlEventReaderStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||||
|
exists(XmlInputFactoryEventReader xmlEventReader |
|
||||||
|
if xmlEventReader.getMethod().getParameterType(0) instanceof TypeString
|
||||||
|
then n1.asExpr() = xmlEventReader.getArgument(1)
|
||||||
|
else n1.asExpr() = xmlEventReader.getArgument(0)
|
||||||
|
|
|
||||||
|
n2.asExpr() = xmlEventReader
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `n1` to `n2` is a dataflow step that converts between `XMLStreamReader` or
|
||||||
|
* `XMLEventReader` and `StAXSource`, i.e. `new StAXSource(tainted)`.
|
||||||
|
*/
|
||||||
|
private predicate staxSourceStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||||
|
exists(ConstructorCall cc | cc.getConstructedType() instanceof TypeStAXSource |
|
||||||
|
n1.asExpr() = cc.getAnArgument() and
|
||||||
|
n2.asExpr() = cc
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `n1` to `n2` is a dataflow step that converts between `InputStream` and `Document`,
|
||||||
|
* i.e. `DocumentBuilder.parse(tainted)`.
|
||||||
|
*/
|
||||||
|
private predicate documentBuilderStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||||
|
exists(DocumentBuilderParse documentBuilder |
|
||||||
|
n1.asExpr() = documentBuilder.getArgument(0) and
|
||||||
|
n2.asExpr() = documentBuilder
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `n1` to `n2` is a dataflow step that converts between `Document` and `DOMSource`, i.e.
|
||||||
|
* `new DOMSource(tainted)`.
|
||||||
|
*/
|
||||||
|
private predicate domSourceStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||||
|
exists(ConstructorCall cc | cc.getConstructedType() instanceof TypeDOMSource |
|
||||||
|
n1.asExpr() = cc.getAnArgument() and
|
||||||
|
n2.asExpr() = cc
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `n1` to `n2` is a dataflow step that converts between `Templates` and `Transformer`,
|
||||||
|
* i.e. `tainted.newTransformer()`.
|
||||||
|
*/
|
||||||
|
private predicate newTransformerFromTemplatesStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||||
|
exists(MethodAccess ma, Method m | ma.getMethod() = m |
|
||||||
|
n1.asExpr() = ma.getQualifier() and
|
||||||
|
n2.asExpr() = ma and
|
||||||
|
m.getDeclaringType() instanceof TypeTemplates and
|
||||||
|
m.hasName("newTransformer")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `n1` to `n2` is a dataflow step that converts between `Source` or `URI` and
|
||||||
|
* `XsltExecutable` or `XsltPackage`, i.e. `XsltCompiler.compile(tainted)` or
|
||||||
|
* `XsltCompiler.loadExecutablePackage(tainted)` or `XsltCompiler.compilePackage(tainted)` or
|
||||||
|
* `XsltCompiler.loadLibraryPackage(tainted)`.
|
||||||
|
*/
|
||||||
|
private predicate xsltCompilerStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||||
|
exists(MethodAccess ma, Method m | ma.getMethod() = m |
|
||||||
|
n1.asExpr() = ma.getArgument(0) and
|
||||||
|
n2.asExpr() = ma and
|
||||||
|
m.getDeclaringType() instanceof TypeXsltCompiler and
|
||||||
|
m.hasName(["compile", "loadExecutablePackage", "compilePackage", "loadLibraryPackage"])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `n1` to `n2` is a dataflow step that converts between `XsltExecutable` and
|
||||||
|
* `XsltTransformer` or `Xslt30Transformer`, i.e. `XsltExecutable.load()` or
|
||||||
|
* `XsltExecutable.load30()`.
|
||||||
|
*/
|
||||||
|
private predicate xsltExecutableStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||||
|
exists(MethodAccess ma, Method m | ma.getMethod() = m |
|
||||||
|
n1.asExpr() = ma.getQualifier() and
|
||||||
|
n2.asExpr() = ma and
|
||||||
|
m.getDeclaringType() instanceof TypeXsltExecutable and
|
||||||
|
m.hasName(["load", "load30"])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `n1` to `n2` is a dataflow step that converts between `XsltPackage` and
|
||||||
|
* `XsltExecutable`, i.e. `XsltPackage.link()`.
|
||||||
|
*/
|
||||||
|
private predicate xsltPackageStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||||
|
exists(MethodAccess ma, Method m | ma.getMethod() = m |
|
||||||
|
n1.asExpr() = ma.getQualifier() and
|
||||||
|
n2.asExpr() = ma and
|
||||||
|
m.getDeclaringType() instanceof TypeXsltPackage and
|
||||||
|
m.hasName("link")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The class `javax.xml.transform.stax.StAXSource`. */
|
||||||
|
private class TypeStAXSource extends Class {
|
||||||
|
TypeStAXSource() { this.hasQualifiedName("javax.xml.transform.stax", "StAXSource") }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The class `javax.xml.transform.dom.DOMSource`. */
|
||||||
|
private class TypeDOMSource extends Class {
|
||||||
|
TypeDOMSource() { this.hasQualifiedName("javax.xml.transform.dom", "DOMSource") }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The interface `javax.xml.transform.Templates`. */
|
||||||
|
private class TypeTemplates extends Interface {
|
||||||
|
TypeTemplates() { this.hasQualifiedName("javax.xml.transform", "Templates") }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The class `net.sf.saxon.s9api.XsltCompiler`. */
|
||||||
|
private class TypeXsltCompiler extends Class {
|
||||||
|
TypeXsltCompiler() { this.hasQualifiedName("net.sf.saxon.s9api", "XsltCompiler") }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The class `net.sf.saxon.s9api.XsltExecutable`. */
|
||||||
|
private class TypeXsltExecutable extends Class {
|
||||||
|
TypeXsltExecutable() { this.hasQualifiedName("net.sf.saxon.s9api", "XsltExecutable") }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The class `net.sf.saxon.s9api.XsltPackage`. */
|
||||||
|
private class TypeXsltPackage extends Class {
|
||||||
|
TypeXsltPackage() { this.hasQualifiedName("net.sf.saxon.s9api", "XsltPackage") }
|
||||||
|
}
|
||||||
|
|
||||||
|
// XmlParsers classes
|
||||||
|
/** A call to `DocumentBuilder.parse`. */
|
||||||
|
private class DocumentBuilderParse extends MethodAccess {
|
||||||
|
DocumentBuilderParse() {
|
||||||
|
exists(Method m |
|
||||||
|
this.getMethod() = m and
|
||||||
|
m.getDeclaringType() instanceof DocumentBuilder and
|
||||||
|
m.hasName("parse")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The class `javax.xml.parsers.DocumentBuilder`. */
|
||||||
|
private class DocumentBuilder extends RefType {
|
||||||
|
DocumentBuilder() { this.hasQualifiedName("javax.xml.parsers", "DocumentBuilder") }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A call to `XMLInputFactory.createXMLStreamReader`. */
|
||||||
|
private class XmlInputFactoryStreamReader extends MethodAccess {
|
||||||
|
XmlInputFactoryStreamReader() {
|
||||||
|
exists(Method m |
|
||||||
|
this.getMethod() = m and
|
||||||
|
m.getDeclaringType() instanceof XmlInputFactory and
|
||||||
|
m.hasName("createXMLStreamReader")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A call to `XMLInputFactory.createEventReader`. */
|
||||||
|
private class XmlInputFactoryEventReader extends MethodAccess {
|
||||||
|
XmlInputFactoryEventReader() {
|
||||||
|
exists(Method m |
|
||||||
|
this.getMethod() = m and
|
||||||
|
m.getDeclaringType() instanceof XmlInputFactory and
|
||||||
|
m.hasName("createXMLEventReader")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The class `javax.xml.stream.XMLInputFactory`. */
|
||||||
|
private class XmlInputFactory extends RefType {
|
||||||
|
XmlInputFactory() { this.hasQualifiedName("javax.xml.stream", "XMLInputFactory") }
|
||||||
|
}
|
||||||
90
java/ql/lib/semmle/code/java/security/XsltInjectionQuery.qll
Normal file
90
java/ql/lib/semmle/code/java/security/XsltInjectionQuery.qll
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
/** Provides taint tracking configurations to be used in XSLT injection queries. */
|
||||||
|
|
||||||
|
import java
|
||||||
|
import semmle.code.java.dataflow.FlowSources
|
||||||
|
import semmle.code.java.dataflow.TaintTracking
|
||||||
|
import semmle.code.java.security.XmlParsers
|
||||||
|
import semmle.code.java.security.XsltInjection
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A taint-tracking configuration for unvalidated user input that is used in XSLT transformation.
|
||||||
|
*/
|
||||||
|
class XsltInjectionFlowConfig extends TaintTracking::Configuration {
|
||||||
|
XsltInjectionFlowConfig() { this = "XsltInjectionFlowConfig" }
|
||||||
|
|
||||||
|
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
||||||
|
|
||||||
|
override predicate isSink(DataFlow::Node sink) { sink instanceof XsltInjectionSink }
|
||||||
|
|
||||||
|
override predicate isSanitizer(DataFlow::Node node) {
|
||||||
|
node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||||
|
any(XsltInjectionAdditionalTaintStep c).step(node1, node2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A set of additional taint steps to consider when taint tracking XSLT related data flows.
|
||||||
|
* These steps use data flow logic themselves.
|
||||||
|
*/
|
||||||
|
private class DataFlowXsltInjectionAdditionalTaintStep extends XsltInjectionAdditionalTaintStep {
|
||||||
|
override predicate step(DataFlow::Node node1, DataFlow::Node node2) {
|
||||||
|
newTransformerOrTemplatesStep(node1, node2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `n1` to `n2` is a dataflow step that converts between `Source` and `Transformer` or
|
||||||
|
* `Templates`, i.e. `TransformerFactory.newTransformer(tainted)` or
|
||||||
|
* `TransformerFactory.newTemplates(tainted)`.
|
||||||
|
*/
|
||||||
|
private predicate newTransformerOrTemplatesStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||||
|
exists(MethodAccess ma, Method m | ma.getMethod() = m |
|
||||||
|
n1.asExpr() = ma.getAnArgument() and
|
||||||
|
n2.asExpr() = ma and
|
||||||
|
m.getDeclaringType() instanceof TransformerFactory and
|
||||||
|
m.hasName(["newTransformer", "newTemplates"]) and
|
||||||
|
not exists(TransformerFactoryWithSecureProcessingFeatureFlowConfig conf |
|
||||||
|
conf.hasFlowToExpr(ma.getQualifier())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A data flow configuration for secure processing feature that is enabled on `TransformerFactory`.
|
||||||
|
*/
|
||||||
|
private class TransformerFactoryWithSecureProcessingFeatureFlowConfig extends DataFlow2::Configuration {
|
||||||
|
TransformerFactoryWithSecureProcessingFeatureFlowConfig() {
|
||||||
|
this = "TransformerFactoryWithSecureProcessingFeatureFlowConfig"
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate isSource(DataFlow::Node src) {
|
||||||
|
exists(Variable v | v = src.asExpr().(VarAccess).getVariable() |
|
||||||
|
exists(TransformerFactoryFeatureConfig config | config.getQualifier() = v.getAnAccess() |
|
||||||
|
config.enables(configSecureProcessing())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate isSink(DataFlow::Node sink) {
|
||||||
|
exists(MethodAccess ma |
|
||||||
|
sink.asExpr() = ma.getQualifier() and
|
||||||
|
ma.getMethod().getDeclaringType() instanceof TransformerFactory
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override int fieldFlowBranchLimit() { result = 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A `ParserConfig` specific to `TransformerFactory`. */
|
||||||
|
private class TransformerFactoryFeatureConfig extends ParserConfig {
|
||||||
|
TransformerFactoryFeatureConfig() {
|
||||||
|
exists(Method m |
|
||||||
|
m = this.getMethod() and
|
||||||
|
m.getDeclaringType() instanceof TransformerFactory and
|
||||||
|
m.hasName("setFeature")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -79,6 +79,47 @@ class AndroidReceiverXmlElement extends AndroidComponentXmlElement {
|
|||||||
*/
|
*/
|
||||||
class AndroidProviderXmlElement extends AndroidComponentXmlElement {
|
class AndroidProviderXmlElement extends AndroidComponentXmlElement {
|
||||||
AndroidProviderXmlElement() { this.getName() = "provider" }
|
AndroidProviderXmlElement() { this.getName() = "provider" }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if this provider element has explicitly set a value for either its
|
||||||
|
* `android:permission` attribute or its `android:readPermission` and `android:writePermission`
|
||||||
|
* attributes.
|
||||||
|
*/
|
||||||
|
predicate requiresPermissions() {
|
||||||
|
this.getAnAttribute().(AndroidPermissionXmlAttribute).isFull()
|
||||||
|
or
|
||||||
|
this.getAnAttribute().(AndroidPermissionXmlAttribute).isWrite() and
|
||||||
|
this.getAnAttribute().(AndroidPermissionXmlAttribute).isRead()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attribute `android:perrmission`, `android:readPermission`, or `android:writePermission`.
|
||||||
|
*/
|
||||||
|
class AndroidPermissionXmlAttribute extends XMLAttribute {
|
||||||
|
AndroidPermissionXmlAttribute() {
|
||||||
|
this.getNamespace().getPrefix() = "android" and
|
||||||
|
this.getName() = ["permission", "readPermission", "writePermission"]
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Holds if this is an `android:permission` attribute. */
|
||||||
|
predicate isFull() { this.getName() = "permission" }
|
||||||
|
|
||||||
|
/** Holds if this is an `android:readPermission` attribute. */
|
||||||
|
predicate isRead() { this.getName() = "readPermission" }
|
||||||
|
|
||||||
|
/** Holds if this is an `android:writePermission` attribute. */
|
||||||
|
predicate isWrite() { this.getName() = "writePermission" }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `<path-permission`> element of a `<provider>` in an Android manifest file.
|
||||||
|
*/
|
||||||
|
class AndroidPathPermissionXmlElement extends XMLElement {
|
||||||
|
AndroidPathPermissionXmlElement() {
|
||||||
|
this.getParent() instanceof AndroidProviderXmlElement and
|
||||||
|
this.hasName("path-permission")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
<qhelp>
|
<qhelp>
|
||||||
<overview>
|
<overview>
|
||||||
<p>XSLT (Extensible Stylesheet Language Transformations) is a language for transforming XML
|
<p>XSLT (Extensible Stylesheet Language Transformations) is a language for transforming XML
|
||||||
documents into other XML documents or other formats. Processing of unvalidated XSLT stylesheet can
|
documents into other XML documents or other formats. Processing unvalidated XSLT stylesheets can
|
||||||
let attacker to read arbitrary files from the filesystem or to execute arbitrary code.</p>
|
allow attackers to read arbitrary files from the filesystem or to execute arbitrary code.</p>
|
||||||
</overview>
|
</overview>
|
||||||
|
|
||||||
<recommendation>
|
<recommendation>
|
||||||
<p>The general recommendation is to not process untrusted XSLT stylesheets. If user provided
|
<p>The general recommendation is to not process untrusted XSLT stylesheets. If user-provided
|
||||||
stylesheets must be processed, enable the secure processing mode.</p>
|
stylesheets must be processed, enable the secure processing mode.</p>
|
||||||
</recommendation>
|
</recommendation>
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ stylesheets must be processed, enable the secure processing mode.</p>
|
|||||||
<p>In the following examples, the code accepts an XSLT stylesheet from the user and processes it.
|
<p>In the following examples, the code accepts an XSLT stylesheet from the user and processes it.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>In the first example, the user provided XSLT stylesheet is parsed and processed.</p>
|
<p>In the first example, the user-provided XSLT stylesheet is parsed and processed.</p>
|
||||||
|
|
||||||
<p>In the second example, secure processing mode is enabled.</p>
|
<p>In the second example, secure processing mode is enabled.</p>
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @name XSLT transformation with user-controlled stylesheet
|
* @name XSLT transformation with user-controlled stylesheet
|
||||||
* @description Doing an XSLT transformation with user-controlled stylesheet can lead to
|
* @description Performing an XSLT transformation with user-controlled stylesheets can lead to
|
||||||
* information disclosure or execution of arbitrary code.
|
* information disclosure or execution of arbitrary code.
|
||||||
* @kind path-problem
|
* @kind path-problem
|
||||||
* @problem.severity error
|
* @problem.severity error
|
||||||
@@ -11,8 +11,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java
|
import java
|
||||||
import semmle.code.java.dataflow.FlowSources
|
import semmle.code.java.security.XsltInjectionQuery
|
||||||
import XsltInjectionLib
|
|
||||||
import DataFlow::PathGraph
|
import DataFlow::PathGraph
|
||||||
|
|
||||||
from DataFlow::PathNode source, DataFlow::PathNode sink, XsltInjectionFlowConfig conf
|
from DataFlow::PathNode source, DataFlow::PathNode sink, XsltInjectionFlowConfig conf
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<overview>
|
<overview>
|
||||||
<p>
|
<p>
|
||||||
The Spring Expression Language (SpEL) is a powerful expression language
|
The Spring Expression Language (SpEL) is a powerful expression language
|
||||||
provided by Spring Framework. The language offers many features
|
provided by the Spring Framework. The language offers many features
|
||||||
including invocation of methods available in the JVM.
|
including invocation of methods available in the JVM.
|
||||||
If a SpEL expression is built using attacker-controlled data,
|
If a SpEL expression is built using attacker-controlled data,
|
||||||
and then evaluated in a powerful context,
|
and then evaluated in a powerful context,
|
||||||
@@ -31,7 +31,7 @@ that doesn't allow arbitrary method invocation.
|
|||||||
<example>
|
<example>
|
||||||
<p>
|
<p>
|
||||||
The following example uses untrusted data to build a SpEL expression
|
The following example uses untrusted data to build a SpEL expression
|
||||||
and then runs it in the default powerfull context.
|
and then runs it in the default powerful context.
|
||||||
</p>
|
</p>
|
||||||
<sample src="UnsafeSpelExpressionEvaluation.java" />
|
<sample src="UnsafeSpelExpressionEvaluation.java" />
|
||||||
|
|
||||||
@@ -11,9 +11,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java
|
import java
|
||||||
import SpelInjectionLib
|
import semmle.code.java.security.SpelInjectionQuery
|
||||||
|
import semmle.code.java.dataflow.DataFlow
|
||||||
import DataFlow::PathGraph
|
import DataFlow::PathGraph
|
||||||
|
|
||||||
from DataFlow::PathNode source, DataFlow::PathNode sink, ExpressionInjectionConfig conf
|
from DataFlow::PathNode source, DataFlow::PathNode sink, SpelInjectionConfig conf
|
||||||
where conf.hasFlowPath(source, sink)
|
where conf.hasFlowPath(source, sink)
|
||||||
select sink.getNode(), source, sink, "SpEL injection from $@.", source.getNode(), "this user input"
|
select sink.getNode(), source, sink, "SpEL injection from $@.", source.getNode(), "this user input"
|
||||||
@@ -1,288 +0,0 @@
|
|||||||
import java
|
|
||||||
import semmle.code.java.dataflow.FlowSources
|
|
||||||
import semmle.code.java.security.XmlParsers
|
|
||||||
import DataFlow
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A taint-tracking configuration for unvalidated user input that is used in XSLT transformation.
|
|
||||||
*/
|
|
||||||
class XsltInjectionFlowConfig extends TaintTracking::Configuration {
|
|
||||||
XsltInjectionFlowConfig() { this = "XsltInjectionFlowConfig" }
|
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) { sink instanceof XsltInjectionSink }
|
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) {
|
|
||||||
node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
|
||||||
xmlStreamReaderStep(node1, node2) or
|
|
||||||
xmlEventReaderStep(node1, node2) or
|
|
||||||
staxSourceStep(node1, node2) or
|
|
||||||
documentBuilderStep(node1, node2) or
|
|
||||||
domSourceStep(node1, node2) or
|
|
||||||
newTransformerOrTemplatesStep(node1, node2) or
|
|
||||||
newTransformerFromTemplatesStep(node1, node2) or
|
|
||||||
xsltCompilerStep(node1, node2) or
|
|
||||||
xsltExecutableStep(node1, node2) or
|
|
||||||
xsltPackageStep(node1, node2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The class `javax.xml.transform.stax.StAXSource`. */
|
|
||||||
class TypeStAXSource extends Class {
|
|
||||||
TypeStAXSource() { this.hasQualifiedName("javax.xml.transform.stax", "StAXSource") }
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The class `javax.xml.transform.dom.DOMSource`. */
|
|
||||||
class TypeDOMSource extends Class {
|
|
||||||
TypeDOMSource() { this.hasQualifiedName("javax.xml.transform.dom", "DOMSource") }
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The interface `javax.xml.transform.Templates`. */
|
|
||||||
class TypeTemplates extends Interface {
|
|
||||||
TypeTemplates() { this.hasQualifiedName("javax.xml.transform", "Templates") }
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The method `net.sf.saxon.s9api.XsltTransformer.transform`. */
|
|
||||||
class XsltTransformerTransformMethod extends Method {
|
|
||||||
XsltTransformerTransformMethod() {
|
|
||||||
this.getDeclaringType().hasQualifiedName("net.sf.saxon.s9api", "XsltTransformer") and
|
|
||||||
this.hasName("transform")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The method `net.sf.saxon.s9api.Xslt30Transformer.transform`. */
|
|
||||||
class Xslt30TransformerTransformMethod extends Method {
|
|
||||||
Xslt30TransformerTransformMethod() {
|
|
||||||
this.getDeclaringType().hasQualifiedName("net.sf.saxon.s9api", "Xslt30Transformer") and
|
|
||||||
this.hasName("transform")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The method `net.sf.saxon.s9api.Xslt30Transformer.applyTemplates`. */
|
|
||||||
class Xslt30TransformerApplyTemplatesMethod extends Method {
|
|
||||||
Xslt30TransformerApplyTemplatesMethod() {
|
|
||||||
this.getDeclaringType().hasQualifiedName("net.sf.saxon.s9api", "Xslt30Transformer") and
|
|
||||||
this.hasName("applyTemplates")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The method `net.sf.saxon.s9api.Xslt30Transformer.callFunction`. */
|
|
||||||
class Xslt30TransformerCallFunctionMethod extends Method {
|
|
||||||
Xslt30TransformerCallFunctionMethod() {
|
|
||||||
this.getDeclaringType().hasQualifiedName("net.sf.saxon.s9api", "Xslt30Transformer") and
|
|
||||||
this.hasName("callFunction")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The method `net.sf.saxon.s9api.Xslt30Transformer.callTemplate`. */
|
|
||||||
class Xslt30TransformerCallTemplateMethod extends Method {
|
|
||||||
Xslt30TransformerCallTemplateMethod() {
|
|
||||||
this.getDeclaringType().hasQualifiedName("net.sf.saxon.s9api", "Xslt30Transformer") and
|
|
||||||
this.hasName("callTemplate")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The class `net.sf.saxon.s9api.XsltCompiler`. */
|
|
||||||
class TypeXsltCompiler extends Class {
|
|
||||||
TypeXsltCompiler() { this.hasQualifiedName("net.sf.saxon.s9api", "XsltCompiler") }
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The class `net.sf.saxon.s9api.XsltExecutable`. */
|
|
||||||
class TypeXsltExecutable extends Class {
|
|
||||||
TypeXsltExecutable() { this.hasQualifiedName("net.sf.saxon.s9api", "XsltExecutable") }
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The class `net.sf.saxon.s9api.XsltPackage`. */
|
|
||||||
class TypeXsltPackage extends Class {
|
|
||||||
TypeXsltPackage() { this.hasQualifiedName("net.sf.saxon.s9api", "XsltPackage") }
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A data flow sink for unvalidated user input that is used in XSLT transformation. */
|
|
||||||
class XsltInjectionSink extends DataFlow::ExprNode {
|
|
||||||
XsltInjectionSink() {
|
|
||||||
exists(MethodAccess ma, Method m | m = ma.getMethod() and ma.getQualifier() = this.getExpr() |
|
|
||||||
ma instanceof TransformerTransform or
|
|
||||||
m instanceof XsltTransformerTransformMethod or
|
|
||||||
m instanceof Xslt30TransformerTransformMethod or
|
|
||||||
m instanceof Xslt30TransformerApplyTemplatesMethod or
|
|
||||||
m instanceof Xslt30TransformerCallFunctionMethod or
|
|
||||||
m instanceof Xslt30TransformerCallTemplateMethod
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `n1` to `n2` is a dataflow step that converts between `InputStream` or `Reader` and
|
|
||||||
* `XMLStreamReader`, i.e. `XMLInputFactory.createXMLStreamReader(tainted)`.
|
|
||||||
*/
|
|
||||||
predicate xmlStreamReaderStep(ExprNode n1, ExprNode n2) {
|
|
||||||
exists(XmlInputFactoryStreamReader xmlStreamReader |
|
|
||||||
n1.asExpr() = xmlStreamReader.getSink() and
|
|
||||||
n2.asExpr() = xmlStreamReader
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `n1` to `n2` is a dataflow step that converts between `InputStream` or `Reader` and
|
|
||||||
* `XMLEventReader`, i.e. `XMLInputFactory.createXMLEventReader(tainted)`.
|
|
||||||
*/
|
|
||||||
predicate xmlEventReaderStep(ExprNode n1, ExprNode n2) {
|
|
||||||
exists(XmlInputFactoryEventReader xmlEventReader |
|
|
||||||
n1.asExpr() = xmlEventReader.getSink() and
|
|
||||||
n2.asExpr() = xmlEventReader
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `n1` to `n2` is a dataflow step that converts between `XMLStreamReader` or
|
|
||||||
* `XMLEventReader` and `StAXSource`, i.e. `new StAXSource(tainted)`.
|
|
||||||
*/
|
|
||||||
predicate staxSourceStep(ExprNode n1, ExprNode n2) {
|
|
||||||
exists(ConstructorCall cc | cc.getConstructedType() instanceof TypeStAXSource |
|
|
||||||
n1.asExpr() = cc.getAnArgument() and
|
|
||||||
n2.asExpr() = cc
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `n1` to `n2` is a dataflow step that converts between `InputStream` and `Document`,
|
|
||||||
* i.e. `DocumentBuilder.parse(tainted)`.
|
|
||||||
*/
|
|
||||||
predicate documentBuilderStep(ExprNode n1, ExprNode n2) {
|
|
||||||
exists(DocumentBuilderParse documentBuilder |
|
|
||||||
n1.asExpr() = documentBuilder.getSink() and
|
|
||||||
n2.asExpr() = documentBuilder
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `n1` to `n2` is a dataflow step that converts between `Document` and `DOMSource`, i.e.
|
|
||||||
* `new DOMSource(tainted)`.
|
|
||||||
*/
|
|
||||||
predicate domSourceStep(ExprNode n1, ExprNode n2) {
|
|
||||||
exists(ConstructorCall cc | cc.getConstructedType() instanceof TypeDOMSource |
|
|
||||||
n1.asExpr() = cc.getAnArgument() and
|
|
||||||
n2.asExpr() = cc
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A data flow configuration for secure processing feature that is enabled on `TransformerFactory`.
|
|
||||||
*/
|
|
||||||
private class TransformerFactoryWithSecureProcessingFeatureFlowConfig extends DataFlow2::Configuration {
|
|
||||||
TransformerFactoryWithSecureProcessingFeatureFlowConfig() {
|
|
||||||
this = "TransformerFactoryWithSecureProcessingFeatureFlowConfig"
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node src) {
|
|
||||||
exists(Variable v | v = src.asExpr().(VarAccess).getVariable() |
|
|
||||||
exists(TransformerFactoryFeatureConfig config | config.getQualifier() = v.getAnAccess() |
|
|
||||||
config.enables(configSecureProcessing())
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
|
||||||
exists(MethodAccess ma |
|
|
||||||
sink.asExpr() = ma.getQualifier() and
|
|
||||||
ma.getMethod().getDeclaringType() instanceof TransformerFactory
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override int fieldFlowBranchLimit() { result = 0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A `ParserConfig` specific to `TransformerFactory`. */
|
|
||||||
private class TransformerFactoryFeatureConfig extends ParserConfig {
|
|
||||||
TransformerFactoryFeatureConfig() {
|
|
||||||
exists(Method m |
|
|
||||||
m = this.getMethod() and
|
|
||||||
m.getDeclaringType() instanceof TransformerFactory and
|
|
||||||
m.hasName("setFeature")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `n1` to `n2` is a dataflow step that converts between `Source` and `Transformer` or
|
|
||||||
* `Templates`, i.e. `TransformerFactory.newTransformer(tainted)` or
|
|
||||||
* `TransformerFactory.newTemplates(tainted)`.
|
|
||||||
*/
|
|
||||||
predicate newTransformerOrTemplatesStep(ExprNode n1, ExprNode n2) {
|
|
||||||
exists(MethodAccess ma, Method m | ma.getMethod() = m |
|
|
||||||
n1.asExpr() = ma.getAnArgument() and
|
|
||||||
n2.asExpr() = ma and
|
|
||||||
(
|
|
||||||
m.getDeclaringType() instanceof TransformerFactory and m.hasName("newTransformer")
|
|
||||||
or
|
|
||||||
m.getDeclaringType() instanceof TransformerFactory and m.hasName("newTemplates")
|
|
||||||
) and
|
|
||||||
not exists(TransformerFactoryWithSecureProcessingFeatureFlowConfig conf |
|
|
||||||
conf.hasFlowToExpr(ma.getQualifier())
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `n1` to `n2` is a dataflow step that converts between `Templates` and `Transformer`,
|
|
||||||
* i.e. `tainted.newTransformer()`.
|
|
||||||
*/
|
|
||||||
predicate newTransformerFromTemplatesStep(ExprNode n1, ExprNode n2) {
|
|
||||||
exists(MethodAccess ma, Method m | ma.getMethod() = m |
|
|
||||||
n1.asExpr() = ma.getQualifier() and
|
|
||||||
n2.asExpr() = ma and
|
|
||||||
m.getDeclaringType() instanceof TypeTemplates and
|
|
||||||
m.hasName("newTransformer")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `n1` to `n2` is a dataflow step that converts between `Source` or `URI` and
|
|
||||||
* `XsltExecutable` or `XsltPackage`, i.e. `XsltCompiler.compile(tainted)` or
|
|
||||||
* `XsltCompiler.loadExecutablePackage(tainted)` or `XsltCompiler.compilePackage(tainted)` or
|
|
||||||
* `XsltCompiler.loadLibraryPackage(tainted)`.
|
|
||||||
*/
|
|
||||||
predicate xsltCompilerStep(ExprNode n1, ExprNode n2) {
|
|
||||||
exists(MethodAccess ma, Method m | ma.getMethod() = m |
|
|
||||||
n1.asExpr() = ma.getArgument(0) and
|
|
||||||
n2.asExpr() = ma and
|
|
||||||
m.getDeclaringType() instanceof TypeXsltCompiler and
|
|
||||||
(
|
|
||||||
m.hasName("compile") or
|
|
||||||
m.hasName("loadExecutablePackage") or
|
|
||||||
m.hasName("compilePackage") or
|
|
||||||
m.hasName("loadLibraryPackage")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `n1` to `n2` is a dataflow step that converts between `XsltExecutable` and
|
|
||||||
* `XsltTransformer` or `Xslt30Transformer`, i.e. `XsltExecutable.load()` or
|
|
||||||
* `XsltExecutable.load30()`.
|
|
||||||
*/
|
|
||||||
predicate xsltExecutableStep(ExprNode n1, ExprNode n2) {
|
|
||||||
exists(MethodAccess ma, Method m | ma.getMethod() = m |
|
|
||||||
n1.asExpr() = ma.getQualifier() and
|
|
||||||
n2.asExpr() = ma and
|
|
||||||
m.getDeclaringType() instanceof TypeXsltExecutable and
|
|
||||||
(m.hasName("load") or m.hasName("load30"))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `n1` to `n2` is a dataflow step that converts between `XsltPackage` and
|
|
||||||
* `XsltExecutable`, i.e. `XsltPackage.link()`.
|
|
||||||
*/
|
|
||||||
predicate xsltPackageStep(ExprNode n1, ExprNode n2) {
|
|
||||||
exists(MethodAccess ma, Method m | ma.getMethod() = m |
|
|
||||||
n1.asExpr() = ma.getQualifier() and
|
|
||||||
n2.asExpr() = ma and
|
|
||||||
m.getDeclaringType() instanceof TypeXsltPackage and
|
|
||||||
m.hasName("link")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
import java
|
|
||||||
import semmle.code.java.dataflow.FlowSources
|
|
||||||
import semmle.code.java.dataflow.TaintTracking2
|
|
||||||
import SpringFrameworkLib
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A taint-tracking configuration for unsafe user input
|
|
||||||
* that is used to construct and evaluate a SpEL expression.
|
|
||||||
*/
|
|
||||||
class ExpressionInjectionConfig extends TaintTracking::Configuration {
|
|
||||||
ExpressionInjectionConfig() { this = "ExpressionInjectionConfig" }
|
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) {
|
|
||||||
source instanceof RemoteFlowSource or
|
|
||||||
source instanceof WebRequestSource
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) { sink instanceof ExpressionEvaluationSink }
|
|
||||||
|
|
||||||
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
|
||||||
expressionParsingStep(node1, node2) or
|
|
||||||
springPropertiesStep(node1, node2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A sink for SpEL injection vulnerabilities,
|
|
||||||
* i.e. methods that run evaluation of a SpEL expression in a powerfull context.
|
|
||||||
*/
|
|
||||||
class ExpressionEvaluationSink extends DataFlow::ExprNode {
|
|
||||||
ExpressionEvaluationSink() {
|
|
||||||
exists(MethodAccess ma, Method m | m = ma.getMethod() |
|
|
||||||
m instanceof ExpressionEvaluationMethod and
|
|
||||||
getExpr() = ma.getQualifier() and
|
|
||||||
not exists(SafeEvaluationContextFlowConfig config |
|
|
||||||
config.hasFlowTo(DataFlow::exprNode(ma.getArgument(0)))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `node1` to `node2` is a dataflow step that parses a SpEL expression,
|
|
||||||
* i.e. `parser.parseExpression(tainted)`.
|
|
||||||
*/
|
|
||||||
predicate expressionParsingStep(DataFlow::Node node1, DataFlow::Node node2) {
|
|
||||||
exists(MethodAccess ma, Method m | ma.getMethod() = m |
|
|
||||||
m.getDeclaringType().getAnAncestor*() instanceof ExpressionParser and
|
|
||||||
m.hasName("parseExpression") and
|
|
||||||
ma.getAnArgument() = node1.asExpr() and
|
|
||||||
node2.asExpr() = ma
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A configuration for safe evaluation context that may be used in expression evaluation.
|
|
||||||
*/
|
|
||||||
class SafeEvaluationContextFlowConfig extends DataFlow2::Configuration {
|
|
||||||
SafeEvaluationContextFlowConfig() { this = "SpelInjection::SafeEvaluationContextFlowConfig" }
|
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { source instanceof SafeContextSource }
|
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
|
||||||
exists(MethodAccess ma, Method m | m = ma.getMethod() |
|
|
||||||
m instanceof ExpressionEvaluationMethod and
|
|
||||||
ma.getArgument(0) = sink.asExpr()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override int fieldFlowBranchLimit() { result = 0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
class SafeContextSource extends DataFlow::ExprNode {
|
|
||||||
SafeContextSource() {
|
|
||||||
isSimpleEvaluationContextConstructorCall(getExpr()) or
|
|
||||||
isSimpleEvaluationContextBuilderCall(getExpr())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `expr` constructs `SimpleEvaluationContext`.
|
|
||||||
*/
|
|
||||||
predicate isSimpleEvaluationContextConstructorCall(Expr expr) {
|
|
||||||
exists(ConstructorCall cc |
|
|
||||||
cc.getConstructedType() instanceof SimpleEvaluationContext and
|
|
||||||
cc = expr
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `expr` builds `SimpleEvaluationContext` via `SimpleEvaluationContext.Builder`,
|
|
||||||
* e.g. `SimpleEvaluationContext.forReadWriteDataBinding().build()`.
|
|
||||||
*/
|
|
||||||
predicate isSimpleEvaluationContextBuilderCall(Expr expr) {
|
|
||||||
exists(MethodAccess ma, Method m | ma.getMethod() = m |
|
|
||||||
m.getDeclaringType() instanceof SimpleEvaluationContextBuilder and
|
|
||||||
m.hasName("build") and
|
|
||||||
ma = expr
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,21 +1,6 @@
|
|||||||
import java
|
import java
|
||||||
import semmle.code.java.dataflow.DataFlow
|
import semmle.code.java.dataflow.DataFlow
|
||||||
|
|
||||||
/**
|
|
||||||
* Methods that trigger evaluation of an expression.
|
|
||||||
*/
|
|
||||||
class ExpressionEvaluationMethod extends Method {
|
|
||||||
ExpressionEvaluationMethod() {
|
|
||||||
getDeclaringType() instanceof Expression and
|
|
||||||
(
|
|
||||||
hasName("getValue") or
|
|
||||||
hasName("getValueTypeDescriptor") or
|
|
||||||
hasName("getValueType") or
|
|
||||||
hasName("setValue")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `WebRequest` interface is a source of tainted data.
|
* `WebRequest` interface is a source of tainted data.
|
||||||
*/
|
*/
|
||||||
@@ -37,100 +22,6 @@ class WebRequestSource extends DataFlow::Node {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `node1` to `node2` is a dataflow step that converts `PropertyValues`
|
|
||||||
* to an array of `PropertyValue`, i.e. `tainted.getPropertyValues()`.
|
|
||||||
*/
|
|
||||||
predicate getPropertyValuesStep(DataFlow::Node node1, DataFlow::Node node2) {
|
|
||||||
exists(MethodAccess ma, Method m | m = ma.getMethod() |
|
|
||||||
node1.asExpr() = ma.getQualifier() and
|
|
||||||
node2.asExpr() = ma and
|
|
||||||
m.getDeclaringType() instanceof PropertyValues and
|
|
||||||
m.hasName("getPropertyValues")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `node1` to `node2` is a dataflow step that constructs `MutablePropertyValues`,
|
|
||||||
* i.e. `new MutablePropertyValues(tainted)`.
|
|
||||||
*/
|
|
||||||
predicate createMutablePropertyValuesStep(DataFlow::Node node1, DataFlow::Node node2) {
|
|
||||||
exists(ConstructorCall cc | cc.getConstructedType() instanceof MutablePropertyValues |
|
|
||||||
node1.asExpr() = cc.getAnArgument() and
|
|
||||||
node2.asExpr() = cc
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `node1` to `node2` is a dataflow step that returns a name of `PropertyValue`,
|
|
||||||
* i.e. `tainted.getName()`.
|
|
||||||
*/
|
|
||||||
predicate getPropertyNameStep(DataFlow::Node node1, DataFlow::Node node2) {
|
|
||||||
exists(MethodAccess ma, Method m | m = ma.getMethod() |
|
|
||||||
node1.asExpr() = ma.getQualifier() and
|
|
||||||
node2.asExpr() = ma and
|
|
||||||
m.getDeclaringType() instanceof PropertyValue and
|
|
||||||
m.hasName("getName")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `node1` to `node2` is a dataflow step that converts `MutablePropertyValues`
|
|
||||||
* to a list of `PropertyValue`, i.e. `tainted.getPropertyValueList()`.
|
|
||||||
*/
|
|
||||||
predicate getPropertyValueListStep(DataFlow::Node node1, DataFlow::Node node2) {
|
|
||||||
exists(MethodAccess ma, Method m | m = ma.getMethod() |
|
|
||||||
node1.asExpr() = ma.getQualifier() and
|
|
||||||
node2.asExpr() = ma and
|
|
||||||
m.getDeclaringType() instanceof MutablePropertyValues and
|
|
||||||
m.hasName("getPropertyValueList")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `node1` to `node2` is one of the dataflow steps that propagate
|
|
||||||
* tainted data via Spring properties.
|
|
||||||
*/
|
|
||||||
predicate springPropertiesStep(DataFlow::Node node1, DataFlow::Node node2) {
|
|
||||||
createMutablePropertyValuesStep(node1, node2) or
|
|
||||||
getPropertyNameStep(node1, node2) or
|
|
||||||
getPropertyValuesStep(node1, node2) or
|
|
||||||
getPropertyValueListStep(node1, node2)
|
|
||||||
}
|
|
||||||
|
|
||||||
class PropertyValue extends RefType {
|
|
||||||
PropertyValue() { hasQualifiedName("org.springframework.beans", "PropertyValue") }
|
|
||||||
}
|
|
||||||
|
|
||||||
class PropertyValues extends RefType {
|
|
||||||
PropertyValues() { hasQualifiedName("org.springframework.beans", "PropertyValues") }
|
|
||||||
}
|
|
||||||
|
|
||||||
class MutablePropertyValues extends RefType {
|
|
||||||
MutablePropertyValues() { hasQualifiedName("org.springframework.beans", "MutablePropertyValues") }
|
|
||||||
}
|
|
||||||
|
|
||||||
class SimpleEvaluationContext extends RefType {
|
|
||||||
SimpleEvaluationContext() {
|
|
||||||
hasQualifiedName("org.springframework.expression.spel.support", "SimpleEvaluationContext")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SimpleEvaluationContextBuilder extends RefType {
|
|
||||||
SimpleEvaluationContextBuilder() {
|
|
||||||
hasQualifiedName("org.springframework.expression.spel.support",
|
|
||||||
"SimpleEvaluationContext$Builder")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class WebRequest extends RefType {
|
class WebRequest extends RefType {
|
||||||
WebRequest() { hasQualifiedName("org.springframework.web.context.request", "WebRequest") }
|
WebRequest() { hasQualifiedName("org.springframework.web.context.request", "WebRequest") }
|
||||||
}
|
}
|
||||||
|
|
||||||
class Expression extends RefType {
|
|
||||||
Expression() { hasQualifiedName("org.springframework.expression", "Expression") }
|
|
||||||
}
|
|
||||||
|
|
||||||
class ExpressionParser extends RefType {
|
|
||||||
ExpressionParser() { hasQualifiedName("org.springframework.expression", "ExpressionParser") }
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -361,6 +361,12 @@ private predicate excludedMember(Member m) {
|
|||||||
m.(Method).getDeclaringType() instanceof EnumType and
|
m.(Method).getDeclaringType() instanceof EnumType and
|
||||||
m.hasName(["values", "valueOf"]) and
|
m.hasName(["values", "valueOf"]) and
|
||||||
m.isStatic()
|
m.isStatic()
|
||||||
|
or
|
||||||
|
exists(Parameter p |
|
||||||
|
p = m.(Method).getAParameter() and
|
||||||
|
p.getType().fromSource() and
|
||||||
|
not p.getType().(RefType).isPublic()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private string stubMember(Member m) {
|
private string stubMember(Member m) {
|
||||||
|
|||||||
@@ -1,122 +0,0 @@
|
|||||||
edges
|
|
||||||
| XsltInjection.java:30:27:30:67 | new StreamSource(...) : StreamSource | XsltInjection.java:31:5:31:59 | newTransformer(...) |
|
|
||||||
| XsltInjection.java:30:44:30:66 | getInputStream(...) : InputStream | XsltInjection.java:30:27:30:67 | new StreamSource(...) : StreamSource |
|
|
||||||
| XsltInjection.java:35:27:35:90 | new StreamSource(...) : StreamSource | XsltInjection.java:36:5:36:74 | newTransformer(...) |
|
|
||||||
| XsltInjection.java:35:44:35:89 | new InputStreamReader(...) : InputStreamReader | XsltInjection.java:35:27:35:90 | new StreamSource(...) : StreamSource |
|
|
||||||
| XsltInjection.java:35:66:35:88 | getInputStream(...) : InputStream | XsltInjection.java:35:44:35:89 | new InputStreamReader(...) : InputStreamReader |
|
|
||||||
| XsltInjection.java:40:45:40:70 | param : String | XsltInjection.java:42:61:42:64 | xslt : String |
|
|
||||||
| XsltInjection.java:42:27:42:66 | new StreamSource(...) : StreamSource | XsltInjection.java:43:5:43:59 | newTransformer(...) |
|
|
||||||
| XsltInjection.java:42:44:42:65 | new StringReader(...) : StringReader | XsltInjection.java:42:27:42:66 | new StreamSource(...) : StreamSource |
|
|
||||||
| XsltInjection.java:42:61:42:64 | xslt : String | XsltInjection.java:42:44:42:65 | new StringReader(...) : StringReader |
|
|
||||||
| XsltInjection.java:47:24:47:78 | new SAXSource(...) : SAXSource | XsltInjection.java:48:5:48:74 | newTransformer(...) |
|
|
||||||
| XsltInjection.java:47:38:47:77 | new InputSource(...) : InputSource | XsltInjection.java:47:24:47:78 | new SAXSource(...) : SAXSource |
|
|
||||||
| XsltInjection.java:47:54:47:76 | getInputStream(...) : InputStream | XsltInjection.java:47:38:47:77 | new InputSource(...) : InputSource |
|
|
||||||
| XsltInjection.java:52:24:52:107 | new SAXSource(...) : SAXSource | XsltInjection.java:53:5:53:59 | newTransformer(...) |
|
|
||||||
| XsltInjection.java:52:44:52:106 | new InputSource(...) : InputSource | XsltInjection.java:52:24:52:107 | new SAXSource(...) : SAXSource |
|
|
||||||
| XsltInjection.java:52:60:52:105 | new InputStreamReader(...) : InputStreamReader | XsltInjection.java:52:44:52:106 | new InputSource(...) : InputSource |
|
|
||||||
| XsltInjection.java:52:82:52:104 | getInputStream(...) : InputStream | XsltInjection.java:52:60:52:105 | new InputStreamReader(...) : InputStreamReader |
|
|
||||||
| XsltInjection.java:57:91:57:113 | getInputStream(...) : InputStream | XsltInjection.java:58:5:58:59 | newTransformer(...) |
|
|
||||||
| XsltInjection.java:62:98:62:143 | new InputStreamReader(...) : InputStreamReader | XsltInjection.java:63:5:63:74 | newTransformer(...) |
|
|
||||||
| XsltInjection.java:62:120:62:142 | getInputStream(...) : InputStream | XsltInjection.java:62:98:62:143 | new InputStreamReader(...) : InputStreamReader |
|
|
||||||
| XsltInjection.java:67:102:67:124 | getInputStream(...) : InputStream | XsltInjection.java:68:5:68:59 | newTransformer(...) |
|
|
||||||
| XsltInjection.java:72:27:72:67 | new StreamSource(...) : StreamSource | XsltInjection.java:76:5:76:34 | newTransformer(...) |
|
|
||||||
| XsltInjection.java:72:44:72:66 | getInputStream(...) : InputStream | XsltInjection.java:72:27:72:67 | new StreamSource(...) : StreamSource |
|
|
||||||
| XsltInjection.java:80:27:80:67 | new StreamSource(...) : StreamSource | XsltInjection.java:83:5:83:34 | newTransformer(...) |
|
|
||||||
| XsltInjection.java:80:44:80:66 | getInputStream(...) : InputStream | XsltInjection.java:80:27:80:67 | new StreamSource(...) : StreamSource |
|
|
||||||
| XsltInjection.java:87:27:87:67 | new StreamSource(...) : StreamSource | XsltInjection.java:90:5:90:35 | load(...) |
|
|
||||||
| XsltInjection.java:87:27:87:67 | new StreamSource(...) : StreamSource | XsltInjection.java:91:5:91:37 | load30(...) |
|
|
||||||
| XsltInjection.java:87:27:87:67 | new StreamSource(...) : StreamSource | XsltInjection.java:92:5:92:37 | load30(...) |
|
|
||||||
| XsltInjection.java:87:27:87:67 | new StreamSource(...) : StreamSource | XsltInjection.java:93:5:93:37 | load30(...) |
|
|
||||||
| XsltInjection.java:87:27:87:67 | new StreamSource(...) : StreamSource | XsltInjection.java:94:5:94:37 | load30(...) |
|
|
||||||
| XsltInjection.java:87:27:87:67 | new StreamSource(...) : StreamSource | XsltInjection.java:95:5:95:37 | load30(...) |
|
|
||||||
| XsltInjection.java:87:27:87:67 | new StreamSource(...) : StreamSource | XsltInjection.java:96:5:96:37 | load30(...) |
|
|
||||||
| XsltInjection.java:87:27:87:67 | new StreamSource(...) : StreamSource | XsltInjection.java:97:5:97:37 | load30(...) |
|
|
||||||
| XsltInjection.java:87:27:87:67 | new StreamSource(...) : StreamSource | XsltInjection.java:98:5:98:37 | load30(...) |
|
|
||||||
| XsltInjection.java:87:27:87:67 | new StreamSource(...) : StreamSource | XsltInjection.java:99:5:99:37 | load30(...) |
|
|
||||||
| XsltInjection.java:87:44:87:66 | getInputStream(...) : InputStream | XsltInjection.java:87:27:87:67 | new StreamSource(...) : StreamSource |
|
|
||||||
| XsltInjection.java:103:36:103:61 | param : String | XsltInjection.java:104:23:104:27 | param : String |
|
|
||||||
| XsltInjection.java:104:15:104:28 | new URI(...) : URI | XsltInjection.java:108:5:108:46 | load(...) |
|
|
||||||
| XsltInjection.java:104:15:104:28 | new URI(...) : URI | XsltInjection.java:110:5:110:50 | load(...) |
|
|
||||||
| XsltInjection.java:104:23:104:27 | param : String | XsltInjection.java:104:15:104:28 | new URI(...) : URI |
|
|
||||||
| XsltInjection.java:105:27:105:67 | new StreamSource(...) : StreamSource | XsltInjection.java:109:5:109:49 | load(...) |
|
|
||||||
| XsltInjection.java:105:44:105:66 | getInputStream(...) : InputStream | XsltInjection.java:105:27:105:67 | new StreamSource(...) : StreamSource |
|
|
||||||
nodes
|
|
||||||
| XsltInjection.java:30:27:30:67 | new StreamSource(...) : StreamSource | semmle.label | new StreamSource(...) : StreamSource |
|
|
||||||
| XsltInjection.java:30:44:30:66 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
|
|
||||||
| XsltInjection.java:31:5:31:59 | newTransformer(...) | semmle.label | newTransformer(...) |
|
|
||||||
| XsltInjection.java:35:27:35:90 | new StreamSource(...) : StreamSource | semmle.label | new StreamSource(...) : StreamSource |
|
|
||||||
| XsltInjection.java:35:44:35:89 | new InputStreamReader(...) : InputStreamReader | semmle.label | new InputStreamReader(...) : InputStreamReader |
|
|
||||||
| XsltInjection.java:35:66:35:88 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
|
|
||||||
| XsltInjection.java:36:5:36:74 | newTransformer(...) | semmle.label | newTransformer(...) |
|
|
||||||
| XsltInjection.java:40:45:40:70 | param : String | semmle.label | param : String |
|
|
||||||
| XsltInjection.java:42:27:42:66 | new StreamSource(...) : StreamSource | semmle.label | new StreamSource(...) : StreamSource |
|
|
||||||
| XsltInjection.java:42:44:42:65 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader |
|
|
||||||
| XsltInjection.java:42:61:42:64 | xslt : String | semmle.label | xslt : String |
|
|
||||||
| XsltInjection.java:43:5:43:59 | newTransformer(...) | semmle.label | newTransformer(...) |
|
|
||||||
| XsltInjection.java:47:24:47:78 | new SAXSource(...) : SAXSource | semmle.label | new SAXSource(...) : SAXSource |
|
|
||||||
| XsltInjection.java:47:38:47:77 | new InputSource(...) : InputSource | semmle.label | new InputSource(...) : InputSource |
|
|
||||||
| XsltInjection.java:47:54:47:76 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
|
|
||||||
| XsltInjection.java:48:5:48:74 | newTransformer(...) | semmle.label | newTransformer(...) |
|
|
||||||
| XsltInjection.java:52:24:52:107 | new SAXSource(...) : SAXSource | semmle.label | new SAXSource(...) : SAXSource |
|
|
||||||
| XsltInjection.java:52:44:52:106 | new InputSource(...) : InputSource | semmle.label | new InputSource(...) : InputSource |
|
|
||||||
| XsltInjection.java:52:60:52:105 | new InputStreamReader(...) : InputStreamReader | semmle.label | new InputStreamReader(...) : InputStreamReader |
|
|
||||||
| XsltInjection.java:52:82:52:104 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
|
|
||||||
| XsltInjection.java:53:5:53:59 | newTransformer(...) | semmle.label | newTransformer(...) |
|
|
||||||
| XsltInjection.java:57:91:57:113 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
|
|
||||||
| XsltInjection.java:58:5:58:59 | newTransformer(...) | semmle.label | newTransformer(...) |
|
|
||||||
| XsltInjection.java:62:98:62:143 | new InputStreamReader(...) : InputStreamReader | semmle.label | new InputStreamReader(...) : InputStreamReader |
|
|
||||||
| XsltInjection.java:62:120:62:142 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
|
|
||||||
| XsltInjection.java:63:5:63:74 | newTransformer(...) | semmle.label | newTransformer(...) |
|
|
||||||
| XsltInjection.java:67:102:67:124 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
|
|
||||||
| XsltInjection.java:68:5:68:59 | newTransformer(...) | semmle.label | newTransformer(...) |
|
|
||||||
| XsltInjection.java:72:27:72:67 | new StreamSource(...) : StreamSource | semmle.label | new StreamSource(...) : StreamSource |
|
|
||||||
| XsltInjection.java:72:44:72:66 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
|
|
||||||
| XsltInjection.java:76:5:76:34 | newTransformer(...) | semmle.label | newTransformer(...) |
|
|
||||||
| XsltInjection.java:80:27:80:67 | new StreamSource(...) : StreamSource | semmle.label | new StreamSource(...) : StreamSource |
|
|
||||||
| XsltInjection.java:80:44:80:66 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
|
|
||||||
| XsltInjection.java:83:5:83:34 | newTransformer(...) | semmle.label | newTransformer(...) |
|
|
||||||
| XsltInjection.java:87:27:87:67 | new StreamSource(...) : StreamSource | semmle.label | new StreamSource(...) : StreamSource |
|
|
||||||
| XsltInjection.java:87:44:87:66 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
|
|
||||||
| XsltInjection.java:90:5:90:35 | load(...) | semmle.label | load(...) |
|
|
||||||
| XsltInjection.java:91:5:91:37 | load30(...) | semmle.label | load30(...) |
|
|
||||||
| XsltInjection.java:92:5:92:37 | load30(...) | semmle.label | load30(...) |
|
|
||||||
| XsltInjection.java:93:5:93:37 | load30(...) | semmle.label | load30(...) |
|
|
||||||
| XsltInjection.java:94:5:94:37 | load30(...) | semmle.label | load30(...) |
|
|
||||||
| XsltInjection.java:95:5:95:37 | load30(...) | semmle.label | load30(...) |
|
|
||||||
| XsltInjection.java:96:5:96:37 | load30(...) | semmle.label | load30(...) |
|
|
||||||
| XsltInjection.java:97:5:97:37 | load30(...) | semmle.label | load30(...) |
|
|
||||||
| XsltInjection.java:98:5:98:37 | load30(...) | semmle.label | load30(...) |
|
|
||||||
| XsltInjection.java:99:5:99:37 | load30(...) | semmle.label | load30(...) |
|
|
||||||
| XsltInjection.java:103:36:103:61 | param : String | semmle.label | param : String |
|
|
||||||
| XsltInjection.java:104:15:104:28 | new URI(...) : URI | semmle.label | new URI(...) : URI |
|
|
||||||
| XsltInjection.java:104:23:104:27 | param : String | semmle.label | param : String |
|
|
||||||
| XsltInjection.java:105:27:105:67 | new StreamSource(...) : StreamSource | semmle.label | new StreamSource(...) : StreamSource |
|
|
||||||
| XsltInjection.java:105:44:105:66 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
|
|
||||||
| XsltInjection.java:108:5:108:46 | load(...) | semmle.label | load(...) |
|
|
||||||
| XsltInjection.java:109:5:109:49 | load(...) | semmle.label | load(...) |
|
|
||||||
| XsltInjection.java:110:5:110:50 | load(...) | semmle.label | load(...) |
|
|
||||||
subpaths
|
|
||||||
#select
|
|
||||||
| XsltInjection.java:31:5:31:59 | newTransformer(...) | XsltInjection.java:30:44:30:66 | getInputStream(...) : InputStream | XsltInjection.java:31:5:31:59 | newTransformer(...) | XSLT transformation might include stylesheet from $@. | XsltInjection.java:30:44:30:66 | getInputStream(...) | this user input |
|
|
||||||
| XsltInjection.java:36:5:36:74 | newTransformer(...) | XsltInjection.java:35:66:35:88 | getInputStream(...) : InputStream | XsltInjection.java:36:5:36:74 | newTransformer(...) | XSLT transformation might include stylesheet from $@. | XsltInjection.java:35:66:35:88 | getInputStream(...) | this user input |
|
|
||||||
| XsltInjection.java:43:5:43:59 | newTransformer(...) | XsltInjection.java:40:45:40:70 | param : String | XsltInjection.java:43:5:43:59 | newTransformer(...) | XSLT transformation might include stylesheet from $@. | XsltInjection.java:40:45:40:70 | param | this user input |
|
|
||||||
| XsltInjection.java:48:5:48:74 | newTransformer(...) | XsltInjection.java:47:54:47:76 | getInputStream(...) : InputStream | XsltInjection.java:48:5:48:74 | newTransformer(...) | XSLT transformation might include stylesheet from $@. | XsltInjection.java:47:54:47:76 | getInputStream(...) | this user input |
|
|
||||||
| XsltInjection.java:53:5:53:59 | newTransformer(...) | XsltInjection.java:52:82:52:104 | getInputStream(...) : InputStream | XsltInjection.java:53:5:53:59 | newTransformer(...) | XSLT transformation might include stylesheet from $@. | XsltInjection.java:52:82:52:104 | getInputStream(...) | this user input |
|
|
||||||
| XsltInjection.java:58:5:58:59 | newTransformer(...) | XsltInjection.java:57:91:57:113 | getInputStream(...) : InputStream | XsltInjection.java:58:5:58:59 | newTransformer(...) | XSLT transformation might include stylesheet from $@. | XsltInjection.java:57:91:57:113 | getInputStream(...) | this user input |
|
|
||||||
| XsltInjection.java:63:5:63:74 | newTransformer(...) | XsltInjection.java:62:120:62:142 | getInputStream(...) : InputStream | XsltInjection.java:63:5:63:74 | newTransformer(...) | XSLT transformation might include stylesheet from $@. | XsltInjection.java:62:120:62:142 | getInputStream(...) | this user input |
|
|
||||||
| XsltInjection.java:68:5:68:59 | newTransformer(...) | XsltInjection.java:67:102:67:124 | getInputStream(...) : InputStream | XsltInjection.java:68:5:68:59 | newTransformer(...) | XSLT transformation might include stylesheet from $@. | XsltInjection.java:67:102:67:124 | getInputStream(...) | this user input |
|
|
||||||
| XsltInjection.java:76:5:76:34 | newTransformer(...) | XsltInjection.java:72:44:72:66 | getInputStream(...) : InputStream | XsltInjection.java:76:5:76:34 | newTransformer(...) | XSLT transformation might include stylesheet from $@. | XsltInjection.java:72:44:72:66 | getInputStream(...) | this user input |
|
|
||||||
| XsltInjection.java:83:5:83:34 | newTransformer(...) | XsltInjection.java:80:44:80:66 | getInputStream(...) : InputStream | XsltInjection.java:83:5:83:34 | newTransformer(...) | XSLT transformation might include stylesheet from $@. | XsltInjection.java:80:44:80:66 | getInputStream(...) | this user input |
|
|
||||||
| XsltInjection.java:90:5:90:35 | load(...) | XsltInjection.java:87:44:87:66 | getInputStream(...) : InputStream | XsltInjection.java:90:5:90:35 | load(...) | XSLT transformation might include stylesheet from $@. | XsltInjection.java:87:44:87:66 | getInputStream(...) | this user input |
|
|
||||||
| XsltInjection.java:91:5:91:37 | load30(...) | XsltInjection.java:87:44:87:66 | getInputStream(...) : InputStream | XsltInjection.java:91:5:91:37 | load30(...) | XSLT transformation might include stylesheet from $@. | XsltInjection.java:87:44:87:66 | getInputStream(...) | this user input |
|
|
||||||
| XsltInjection.java:92:5:92:37 | load30(...) | XsltInjection.java:87:44:87:66 | getInputStream(...) : InputStream | XsltInjection.java:92:5:92:37 | load30(...) | XSLT transformation might include stylesheet from $@. | XsltInjection.java:87:44:87:66 | getInputStream(...) | this user input |
|
|
||||||
| XsltInjection.java:93:5:93:37 | load30(...) | XsltInjection.java:87:44:87:66 | getInputStream(...) : InputStream | XsltInjection.java:93:5:93:37 | load30(...) | XSLT transformation might include stylesheet from $@. | XsltInjection.java:87:44:87:66 | getInputStream(...) | this user input |
|
|
||||||
| XsltInjection.java:94:5:94:37 | load30(...) | XsltInjection.java:87:44:87:66 | getInputStream(...) : InputStream | XsltInjection.java:94:5:94:37 | load30(...) | XSLT transformation might include stylesheet from $@. | XsltInjection.java:87:44:87:66 | getInputStream(...) | this user input |
|
|
||||||
| XsltInjection.java:95:5:95:37 | load30(...) | XsltInjection.java:87:44:87:66 | getInputStream(...) : InputStream | XsltInjection.java:95:5:95:37 | load30(...) | XSLT transformation might include stylesheet from $@. | XsltInjection.java:87:44:87:66 | getInputStream(...) | this user input |
|
|
||||||
| XsltInjection.java:96:5:96:37 | load30(...) | XsltInjection.java:87:44:87:66 | getInputStream(...) : InputStream | XsltInjection.java:96:5:96:37 | load30(...) | XSLT transformation might include stylesheet from $@. | XsltInjection.java:87:44:87:66 | getInputStream(...) | this user input |
|
|
||||||
| XsltInjection.java:97:5:97:37 | load30(...) | XsltInjection.java:87:44:87:66 | getInputStream(...) : InputStream | XsltInjection.java:97:5:97:37 | load30(...) | XSLT transformation might include stylesheet from $@. | XsltInjection.java:87:44:87:66 | getInputStream(...) | this user input |
|
|
||||||
| XsltInjection.java:98:5:98:37 | load30(...) | XsltInjection.java:87:44:87:66 | getInputStream(...) : InputStream | XsltInjection.java:98:5:98:37 | load30(...) | XSLT transformation might include stylesheet from $@. | XsltInjection.java:87:44:87:66 | getInputStream(...) | this user input |
|
|
||||||
| XsltInjection.java:99:5:99:37 | load30(...) | XsltInjection.java:87:44:87:66 | getInputStream(...) : InputStream | XsltInjection.java:99:5:99:37 | load30(...) | XSLT transformation might include stylesheet from $@. | XsltInjection.java:87:44:87:66 | getInputStream(...) | this user input |
|
|
||||||
| XsltInjection.java:108:5:108:46 | load(...) | XsltInjection.java:103:36:103:61 | param : String | XsltInjection.java:108:5:108:46 | load(...) | XSLT transformation might include stylesheet from $@. | XsltInjection.java:103:36:103:61 | param | this user input |
|
|
||||||
| XsltInjection.java:109:5:109:49 | load(...) | XsltInjection.java:105:44:105:66 | getInputStream(...) : InputStream | XsltInjection.java:109:5:109:49 | load(...) | XSLT transformation might include stylesheet from $@. | XsltInjection.java:105:44:105:66 | getInputStream(...) | this user input |
|
|
||||||
| XsltInjection.java:110:5:110:50 | load(...) | XsltInjection.java:103:36:103:61 | param : String | XsltInjection.java:110:5:110:50 | load(...) | XSLT transformation might include stylesheet from $@. | XsltInjection.java:103:36:103:61 | param | this user input |
|
|
||||||
@@ -1,127 +0,0 @@
|
|||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.StringReader;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.net.Socket;
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
import javax.xml.XMLConstants;
|
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
|
||||||
import javax.xml.stream.XMLInputFactory;
|
|
||||||
import javax.xml.transform.Source;
|
|
||||||
import javax.xml.transform.TransformerFactory;
|
|
||||||
import javax.xml.transform.dom.DOMSource;
|
|
||||||
import javax.xml.transform.sax.SAXSource;
|
|
||||||
import javax.xml.transform.stax.StAXSource;
|
|
||||||
import javax.xml.transform.stream.StreamResult;
|
|
||||||
import javax.xml.transform.stream.StreamSource;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.xml.sax.InputSource;
|
|
||||||
|
|
||||||
import net.sf.saxon.s9api.Processor;
|
|
||||||
import net.sf.saxon.s9api.XdmValue;
|
|
||||||
import net.sf.saxon.s9api.XsltCompiler;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
public class XsltInjection {
|
|
||||||
public void testStreamSourceInputStream(Socket socket) throws Exception {
|
|
||||||
StreamSource source = new StreamSource(socket.getInputStream());
|
|
||||||
TransformerFactory.newInstance().newTransformer(source).transform(null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testStreamSourceReader(Socket socket) throws Exception {
|
|
||||||
StreamSource source = new StreamSource(new InputStreamReader(socket.getInputStream()));
|
|
||||||
TransformerFactory.newInstance().newTemplates(source).newTransformer().transform(null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping
|
|
||||||
public void testStreamSourceInjectedParam(@RequestParam String param) throws Exception {
|
|
||||||
String xslt = "<xsl:stylesheet [...]" + param + "</xsl:stylesheet>";
|
|
||||||
StreamSource source = new StreamSource(new StringReader(xslt));
|
|
||||||
TransformerFactory.newInstance().newTransformer(source).transform(null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testSAXSourceInputStream(Socket socket) throws Exception {
|
|
||||||
SAXSource source = new SAXSource(new InputSource(socket.getInputStream()));
|
|
||||||
TransformerFactory.newInstance().newTemplates(source).newTransformer().transform(null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testSAXSourceReader(Socket socket) throws Exception {
|
|
||||||
SAXSource source = new SAXSource(null, new InputSource(new InputStreamReader(socket.getInputStream())));
|
|
||||||
TransformerFactory.newInstance().newTransformer(source).transform(null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testStAXSourceEventReader(Socket socket) throws Exception {
|
|
||||||
StAXSource source = new StAXSource(XMLInputFactory.newInstance().createXMLEventReader(socket.getInputStream()));
|
|
||||||
TransformerFactory.newInstance().newTransformer(source).transform(null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testStAXSourceEventStream(Socket socket) throws Exception {
|
|
||||||
StAXSource source = new StAXSource(XMLInputFactory.newInstance().createXMLStreamReader(null, new InputStreamReader(socket.getInputStream())));
|
|
||||||
TransformerFactory.newInstance().newTemplates(source).newTransformer().transform(null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testDOMSource(Socket socket) throws Exception {
|
|
||||||
DOMSource source = new DOMSource(DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(socket.getInputStream()));
|
|
||||||
TransformerFactory.newInstance().newTransformer(source).transform(null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testDisabledXXE(Socket socket) throws Exception {
|
|
||||||
StreamSource source = new StreamSource(socket.getInputStream());
|
|
||||||
TransformerFactory factory = TransformerFactory.newInstance();
|
|
||||||
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
|
|
||||||
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
|
|
||||||
factory.newTransformer(source).transform(null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testFeatureSecureProcessingDisabled(Socket socket) throws Exception {
|
|
||||||
StreamSource source = new StreamSource(socket.getInputStream());
|
|
||||||
TransformerFactory factory = TransformerFactory.newInstance();
|
|
||||||
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false);
|
|
||||||
factory.newTransformer(source).transform(null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testSaxon(Socket socket) throws Exception {
|
|
||||||
StreamSource source = new StreamSource(socket.getInputStream());
|
|
||||||
XsltCompiler compiler = new Processor(true).newXsltCompiler();
|
|
||||||
|
|
||||||
compiler.compile(source).load().transform();
|
|
||||||
compiler.compile(source).load30().transform(null, null);
|
|
||||||
compiler.compile(source).load30().applyTemplates((Source) null);
|
|
||||||
compiler.compile(source).load30().applyTemplates((Source) null, null);
|
|
||||||
compiler.compile(source).load30().applyTemplates((XdmValue) null);
|
|
||||||
compiler.compile(source).load30().applyTemplates((XdmValue) null, null);
|
|
||||||
compiler.compile(source).load30().callFunction(null, null);
|
|
||||||
compiler.compile(source).load30().callFunction(null, null, null);
|
|
||||||
compiler.compile(source).load30().callTemplate(null);
|
|
||||||
compiler.compile(source).load30().callTemplate(null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping
|
|
||||||
public void testSaxonXsltPackage(@RequestParam String param, Socket socket) throws Exception {
|
|
||||||
URI uri = new URI(param);
|
|
||||||
StreamSource source = new StreamSource(socket.getInputStream());
|
|
||||||
XsltCompiler compiler = new Processor(true).newXsltCompiler();
|
|
||||||
|
|
||||||
compiler.loadExecutablePackage(uri).load().transform();
|
|
||||||
compiler.compilePackage(source).link().load().transform();
|
|
||||||
compiler.loadLibraryPackage(uri).link().load().transform();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testOkFeatureSecureProcessing(Socket socket) throws Exception {
|
|
||||||
StreamSource source = new StreamSource(socket.getInputStream());
|
|
||||||
TransformerFactory factory = TransformerFactory.newInstance();
|
|
||||||
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
|
|
||||||
factory.newTransformer(source).transform(null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testOkSaxon(Socket socket) throws Exception {
|
|
||||||
StreamSource source = new StreamSource(socket.getInputStream());
|
|
||||||
XsltCompiler compiler = new Processor(true).newXsltCompiler();
|
|
||||||
|
|
||||||
compiler.compile(source).load().close();
|
|
||||||
compiler.compile((Source) new Object()).load().transform();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
experimental/Security/CWE/CWE-074/XsltInjection.ql
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/Saxon-HE-9.9.1-7
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
edges
|
|
||||||
| SpelInjection.java:15:22:15:44 | getInputStream(...) : InputStream | SpelInjection.java:18:13:18:14 | in : InputStream |
|
|
||||||
| SpelInjection.java:18:13:18:14 | in : InputStream | SpelInjection.java:18:21:18:25 | bytes [post update] : byte[] |
|
|
||||||
| SpelInjection.java:18:21:18:25 | bytes [post update] : byte[] | SpelInjection.java:19:31:19:35 | bytes : byte[] |
|
|
||||||
| SpelInjection.java:19:20:19:42 | new String(...) : String | SpelInjection.java:23:5:23:14 | expression |
|
|
||||||
| SpelInjection.java:19:31:19:35 | bytes : byte[] | SpelInjection.java:19:20:19:42 | new String(...) : String |
|
|
||||||
| SpelInjection.java:27:22:27:44 | getInputStream(...) : InputStream | SpelInjection.java:30:13:30:14 | in : InputStream |
|
|
||||||
| SpelInjection.java:30:13:30:14 | in : InputStream | SpelInjection.java:30:21:30:25 | bytes [post update] : byte[] |
|
|
||||||
| SpelInjection.java:30:21:30:25 | bytes [post update] : byte[] | SpelInjection.java:31:31:31:35 | bytes : byte[] |
|
|
||||||
| SpelInjection.java:31:20:31:42 | new String(...) : String | SpelInjection.java:34:5:34:14 | expression |
|
|
||||||
| SpelInjection.java:31:31:31:35 | bytes : byte[] | SpelInjection.java:31:20:31:42 | new String(...) : String |
|
|
||||||
| SpelInjection.java:38:22:38:44 | getInputStream(...) : InputStream | SpelInjection.java:41:13:41:14 | in : InputStream |
|
|
||||||
| SpelInjection.java:41:13:41:14 | in : InputStream | SpelInjection.java:41:21:41:25 | bytes [post update] : byte[] |
|
|
||||||
| SpelInjection.java:41:21:41:25 | bytes [post update] : byte[] | SpelInjection.java:42:31:42:35 | bytes : byte[] |
|
|
||||||
| SpelInjection.java:42:20:42:42 | new String(...) : String | SpelInjection.java:48:5:48:14 | expression |
|
|
||||||
| SpelInjection.java:42:31:42:35 | bytes : byte[] | SpelInjection.java:42:20:42:42 | new String(...) : String |
|
|
||||||
| SpelInjection.java:52:22:52:44 | getInputStream(...) : InputStream | SpelInjection.java:55:13:55:14 | in : InputStream |
|
|
||||||
| SpelInjection.java:55:13:55:14 | in : InputStream | SpelInjection.java:55:21:55:25 | bytes [post update] : byte[] |
|
|
||||||
| SpelInjection.java:55:21:55:25 | bytes [post update] : byte[] | SpelInjection.java:56:31:56:35 | bytes : byte[] |
|
|
||||||
| SpelInjection.java:56:20:56:42 | new String(...) : String | SpelInjection.java:59:5:59:14 | expression |
|
|
||||||
| SpelInjection.java:56:31:56:35 | bytes : byte[] | SpelInjection.java:56:20:56:42 | new String(...) : String |
|
|
||||||
| SpelInjection.java:63:22:63:44 | getInputStream(...) : InputStream | SpelInjection.java:66:13:66:14 | in : InputStream |
|
|
||||||
| SpelInjection.java:66:13:66:14 | in : InputStream | SpelInjection.java:66:21:66:25 | bytes [post update] : byte[] |
|
|
||||||
| SpelInjection.java:66:21:66:25 | bytes [post update] : byte[] | SpelInjection.java:67:31:67:35 | bytes : byte[] |
|
|
||||||
| SpelInjection.java:67:20:67:42 | new String(...) : String | SpelInjection.java:70:5:70:14 | expression |
|
|
||||||
| SpelInjection.java:67:31:67:35 | bytes : byte[] | SpelInjection.java:67:20:67:42 | new String(...) : String |
|
|
||||||
| SpelInjection.java:74:22:74:44 | getInputStream(...) : InputStream | SpelInjection.java:77:13:77:14 | in : InputStream |
|
|
||||||
| SpelInjection.java:77:13:77:14 | in : InputStream | SpelInjection.java:77:21:77:25 | bytes [post update] : byte[] |
|
|
||||||
| SpelInjection.java:77:21:77:25 | bytes [post update] : byte[] | SpelInjection.java:78:31:78:35 | bytes : byte[] |
|
|
||||||
| SpelInjection.java:78:20:78:42 | new String(...) : String | SpelInjection.java:83:5:83:14 | expression |
|
|
||||||
| SpelInjection.java:78:31:78:35 | bytes : byte[] | SpelInjection.java:78:20:78:42 | new String(...) : String |
|
|
||||||
nodes
|
|
||||||
| SpelInjection.java:15:22:15:44 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
|
|
||||||
| SpelInjection.java:18:13:18:14 | in : InputStream | semmle.label | in : InputStream |
|
|
||||||
| SpelInjection.java:18:21:18:25 | bytes [post update] : byte[] | semmle.label | bytes [post update] : byte[] |
|
|
||||||
| SpelInjection.java:19:20:19:42 | new String(...) : String | semmle.label | new String(...) : String |
|
|
||||||
| SpelInjection.java:19:31:19:35 | bytes : byte[] | semmle.label | bytes : byte[] |
|
|
||||||
| SpelInjection.java:23:5:23:14 | expression | semmle.label | expression |
|
|
||||||
| SpelInjection.java:27:22:27:44 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
|
|
||||||
| SpelInjection.java:30:13:30:14 | in : InputStream | semmle.label | in : InputStream |
|
|
||||||
| SpelInjection.java:30:21:30:25 | bytes [post update] : byte[] | semmle.label | bytes [post update] : byte[] |
|
|
||||||
| SpelInjection.java:31:20:31:42 | new String(...) : String | semmle.label | new String(...) : String |
|
|
||||||
| SpelInjection.java:31:31:31:35 | bytes : byte[] | semmle.label | bytes : byte[] |
|
|
||||||
| SpelInjection.java:34:5:34:14 | expression | semmle.label | expression |
|
|
||||||
| SpelInjection.java:38:22:38:44 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
|
|
||||||
| SpelInjection.java:41:13:41:14 | in : InputStream | semmle.label | in : InputStream |
|
|
||||||
| SpelInjection.java:41:21:41:25 | bytes [post update] : byte[] | semmle.label | bytes [post update] : byte[] |
|
|
||||||
| SpelInjection.java:42:20:42:42 | new String(...) : String | semmle.label | new String(...) : String |
|
|
||||||
| SpelInjection.java:42:31:42:35 | bytes : byte[] | semmle.label | bytes : byte[] |
|
|
||||||
| SpelInjection.java:48:5:48:14 | expression | semmle.label | expression |
|
|
||||||
| SpelInjection.java:52:22:52:44 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
|
|
||||||
| SpelInjection.java:55:13:55:14 | in : InputStream | semmle.label | in : InputStream |
|
|
||||||
| SpelInjection.java:55:21:55:25 | bytes [post update] : byte[] | semmle.label | bytes [post update] : byte[] |
|
|
||||||
| SpelInjection.java:56:20:56:42 | new String(...) : String | semmle.label | new String(...) : String |
|
|
||||||
| SpelInjection.java:56:31:56:35 | bytes : byte[] | semmle.label | bytes : byte[] |
|
|
||||||
| SpelInjection.java:59:5:59:14 | expression | semmle.label | expression |
|
|
||||||
| SpelInjection.java:63:22:63:44 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
|
|
||||||
| SpelInjection.java:66:13:66:14 | in : InputStream | semmle.label | in : InputStream |
|
|
||||||
| SpelInjection.java:66:21:66:25 | bytes [post update] : byte[] | semmle.label | bytes [post update] : byte[] |
|
|
||||||
| SpelInjection.java:67:20:67:42 | new String(...) : String | semmle.label | new String(...) : String |
|
|
||||||
| SpelInjection.java:67:31:67:35 | bytes : byte[] | semmle.label | bytes : byte[] |
|
|
||||||
| SpelInjection.java:70:5:70:14 | expression | semmle.label | expression |
|
|
||||||
| SpelInjection.java:74:22:74:44 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
|
|
||||||
| SpelInjection.java:77:13:77:14 | in : InputStream | semmle.label | in : InputStream |
|
|
||||||
| SpelInjection.java:77:21:77:25 | bytes [post update] : byte[] | semmle.label | bytes [post update] : byte[] |
|
|
||||||
| SpelInjection.java:78:20:78:42 | new String(...) : String | semmle.label | new String(...) : String |
|
|
||||||
| SpelInjection.java:78:31:78:35 | bytes : byte[] | semmle.label | bytes : byte[] |
|
|
||||||
| SpelInjection.java:83:5:83:14 | expression | semmle.label | expression |
|
|
||||||
subpaths
|
|
||||||
#select
|
|
||||||
| SpelInjection.java:23:5:23:14 | expression | SpelInjection.java:15:22:15:44 | getInputStream(...) : InputStream | SpelInjection.java:23:5:23:14 | expression | SpEL injection from $@. | SpelInjection.java:15:22:15:44 | getInputStream(...) | this user input |
|
|
||||||
| SpelInjection.java:34:5:34:14 | expression | SpelInjection.java:27:22:27:44 | getInputStream(...) : InputStream | SpelInjection.java:34:5:34:14 | expression | SpEL injection from $@. | SpelInjection.java:27:22:27:44 | getInputStream(...) | this user input |
|
|
||||||
| SpelInjection.java:48:5:48:14 | expression | SpelInjection.java:38:22:38:44 | getInputStream(...) : InputStream | SpelInjection.java:48:5:48:14 | expression | SpEL injection from $@. | SpelInjection.java:38:22:38:44 | getInputStream(...) | this user input |
|
|
||||||
| SpelInjection.java:59:5:59:14 | expression | SpelInjection.java:52:22:52:44 | getInputStream(...) : InputStream | SpelInjection.java:59:5:59:14 | expression | SpEL injection from $@. | SpelInjection.java:52:22:52:44 | getInputStream(...) | this user input |
|
|
||||||
| SpelInjection.java:70:5:70:14 | expression | SpelInjection.java:63:22:63:44 | getInputStream(...) : InputStream | SpelInjection.java:70:5:70:14 | expression | SpEL injection from $@. | SpelInjection.java:63:22:63:44 | getInputStream(...) | this user input |
|
|
||||||
| SpelInjection.java:83:5:83:14 | expression | SpelInjection.java:74:22:74:44 | getInputStream(...) : InputStream | SpelInjection.java:83:5:83:14 | expression | SpEL injection from $@. | SpelInjection.java:74:22:74:44 | getInputStream(...) | this user input |
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.Socket;
|
|
||||||
import org.springframework.expression.Expression;
|
|
||||||
import org.springframework.expression.ExpressionParser;
|
|
||||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
|
||||||
import org.springframework.expression.spel.support.SimpleEvaluationContext;
|
|
||||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
|
||||||
|
|
||||||
public class SpelInjection {
|
|
||||||
|
|
||||||
private static final ExpressionParser PARSER = new SpelExpressionParser();
|
|
||||||
|
|
||||||
public void testGetValue(Socket socket) throws IOException {
|
|
||||||
InputStream in = socket.getInputStream();
|
|
||||||
|
|
||||||
byte[] bytes = new byte[1024];
|
|
||||||
int n = in.read(bytes);
|
|
||||||
String input = new String(bytes, 0, n);
|
|
||||||
|
|
||||||
ExpressionParser parser = new SpelExpressionParser();
|
|
||||||
Expression expression = parser.parseExpression(input);
|
|
||||||
expression.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testGetValueWithChainedCalls(Socket socket) throws IOException {
|
|
||||||
InputStream in = socket.getInputStream();
|
|
||||||
|
|
||||||
byte[] bytes = new byte[1024];
|
|
||||||
int n = in.read(bytes);
|
|
||||||
String input = new String(bytes, 0, n);
|
|
||||||
|
|
||||||
Expression expression = new SpelExpressionParser().parseExpression(input);
|
|
||||||
expression.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testSetValueWithRootObject(Socket socket) throws IOException {
|
|
||||||
InputStream in = socket.getInputStream();
|
|
||||||
|
|
||||||
byte[] bytes = new byte[1024];
|
|
||||||
int n = in.read(bytes);
|
|
||||||
String input = new String(bytes, 0, n);
|
|
||||||
|
|
||||||
Expression expression = new SpelExpressionParser().parseExpression(input);
|
|
||||||
|
|
||||||
Object root = new Object();
|
|
||||||
Object value = new Object();
|
|
||||||
expression.setValue(root, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testGetValueWithStaticParser(Socket socket) throws IOException {
|
|
||||||
InputStream in = socket.getInputStream();
|
|
||||||
|
|
||||||
byte[] bytes = new byte[1024];
|
|
||||||
int n = in.read(bytes);
|
|
||||||
String input = new String(bytes, 0, n);
|
|
||||||
|
|
||||||
Expression expression = PARSER.parseExpression(input);
|
|
||||||
expression.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testGetValueType(Socket socket) throws IOException {
|
|
||||||
InputStream in = socket.getInputStream();
|
|
||||||
|
|
||||||
byte[] bytes = new byte[1024];
|
|
||||||
int n = in.read(bytes);
|
|
||||||
String input = new String(bytes, 0, n);
|
|
||||||
|
|
||||||
Expression expression = PARSER.parseExpression(input);
|
|
||||||
expression.getValueType();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testWithStandardEvaluationContext(Socket socket) throws IOException {
|
|
||||||
InputStream in = socket.getInputStream();
|
|
||||||
|
|
||||||
byte[] bytes = new byte[1024];
|
|
||||||
int n = in.read(bytes);
|
|
||||||
String input = new String(bytes, 0, n);
|
|
||||||
|
|
||||||
Expression expression = PARSER.parseExpression(input);
|
|
||||||
|
|
||||||
StandardEvaluationContext context = new StandardEvaluationContext();
|
|
||||||
expression.getValue(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testWithSimpleEvaluationContext(Socket socket) throws IOException {
|
|
||||||
InputStream in = socket.getInputStream();
|
|
||||||
|
|
||||||
byte[] bytes = new byte[1024];
|
|
||||||
int n = in.read(bytes);
|
|
||||||
String input = new String(bytes, 0, n);
|
|
||||||
|
|
||||||
Expression expression = PARSER.parseExpression(input);
|
|
||||||
SimpleEvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
|
|
||||||
|
|
||||||
// the expression is evaluated in a limited context
|
|
||||||
expression.getValue(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
experimental/Security/CWE/CWE-094/SpelInjection.ql
|
|
||||||
@@ -48,6 +48,8 @@ public class A {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface Producer1Consumer3<E> extends Producer1<E[]>, Consumer3<E[]> { }
|
||||||
|
|
||||||
static Object source(int i) { return null; }
|
static Object source(int i) { return null; }
|
||||||
|
|
||||||
static void sink(Object o) { }
|
static void sink(Object o) { }
|
||||||
@@ -71,7 +73,7 @@ public class A {
|
|||||||
|
|
||||||
applyConsumer1(source(4), new Consumer1() {
|
applyConsumer1(source(4), new Consumer1() {
|
||||||
@Override public void eat(Object o) {
|
@Override public void eat(Object o) {
|
||||||
sink(o); // $ MISSING: flow=4
|
sink(o); // $ flow=4
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -96,5 +98,16 @@ public class A {
|
|||||||
sink(applyConverter1((Integer)source(9), i -> i)); // $ flow=9
|
sink(applyConverter1((Integer)source(9), i -> i)); // $ flow=9
|
||||||
|
|
||||||
sink(applyConverter1((Integer)source(10), i -> new int[]{i})[0]); // $ flow=10
|
sink(applyConverter1((Integer)source(10), i -> new int[]{i})[0]); // $ flow=10
|
||||||
|
|
||||||
|
Producer1Consumer3<Integer> pc = new Producer1Consumer3<Integer>() {
|
||||||
|
@Override public Integer[] make() {
|
||||||
|
return new Integer[] { (Integer)source(11) };
|
||||||
|
}
|
||||||
|
@Override public void eat(Integer[] xs) {
|
||||||
|
sink(xs[0]); // $ flow=12
|
||||||
|
}
|
||||||
|
};
|
||||||
|
applyConsumer3(new Integer[] { (Integer)source(12) }, pc);
|
||||||
|
sink(applyProducer1(pc)[0]); // $ flow=11
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:versionCode="1"
|
||||||
|
android:versionName="1.0"
|
||||||
|
package="com.example.app">
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:supportsRtl="true"
|
||||||
|
android:theme="@style/AppTheme">
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".MainActivity"
|
||||||
|
android:icon="@drawable/ic_launcher"
|
||||||
|
android:label="@string/app_name">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<provider
|
||||||
|
android:name=".Test"
|
||||||
|
android:authority="com.example.myapp.Test"
|
||||||
|
android:exported="true" />
|
||||||
|
|
||||||
|
<provider
|
||||||
|
android:name=".Safe"
|
||||||
|
android:authority="com.example.myapp.Safe"
|
||||||
|
android:exported="false" />
|
||||||
|
</application>
|
||||||
|
</manifest>
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
package com.example.app;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import android.content.ContentProvider;
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.content.res.AssetFileDescriptor;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.CancellationSignal;
|
||||||
|
import android.os.ParcelFileDescriptor;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
|
||||||
|
// This Content Provider isn't exported, so there shouldn't be any flow
|
||||||
|
public class Safe extends ContentProvider {
|
||||||
|
|
||||||
|
void sink(Object o) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Bundle call(String authority, String method, String arg, Bundle extras) {
|
||||||
|
sink(authority);
|
||||||
|
sink(method);
|
||||||
|
sink(arg);
|
||||||
|
sink(extras.get("some_key"));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bundle call(String method, String arg, Bundle extras) {
|
||||||
|
sink(method);
|
||||||
|
sink(arg);
|
||||||
|
sink(extras.get("some_key"));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int delete(Uri uri, String selection, String[] selectionArgs) {
|
||||||
|
sink(uri);
|
||||||
|
sink(selection);
|
||||||
|
sink(selectionArgs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int delete(Uri uri, Bundle extras) {
|
||||||
|
sink(uri);
|
||||||
|
sink(extras.get("some_key"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType(Uri uri) {
|
||||||
|
sink(uri);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Uri insert(Uri uri, ContentValues values, Bundle extras) {
|
||||||
|
sink(uri);
|
||||||
|
sink(values);
|
||||||
|
sink(extras.get("some_key"));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Uri insert(Uri uri, ContentValues values) {
|
||||||
|
sink(uri);
|
||||||
|
sink(values);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AssetFileDescriptor openAssetFile(Uri uri, String mode, CancellationSignal signal) {
|
||||||
|
sink(uri);
|
||||||
|
sink(mode);
|
||||||
|
sink(signal);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AssetFileDescriptor openAssetFile(Uri uri, String mode) {
|
||||||
|
sink(uri);
|
||||||
|
sink(mode);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts,
|
||||||
|
CancellationSignal signal) throws RemoteException, FileNotFoundException {
|
||||||
|
sink(uri);
|
||||||
|
sink(mimeTypeFilter);
|
||||||
|
sink(opts.get("some_key"));
|
||||||
|
sink(signal);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts)
|
||||||
|
throws FileNotFoundException {
|
||||||
|
sink(uri);
|
||||||
|
sink(mimeTypeFilter);
|
||||||
|
sink(opts.get("some_key"));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParcelFileDescriptor openFile(Uri uri, String mode, CancellationSignal signal) {
|
||||||
|
sink(uri);
|
||||||
|
sink(mode);
|
||||||
|
sink(signal);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParcelFileDescriptor openFile(Uri uri, String mode) {
|
||||||
|
sink(uri);
|
||||||
|
sink(mode);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Cursor query(Uri uri, String[] projection, Bundle queryArgs,
|
||||||
|
CancellationSignal cancellationSignal) {
|
||||||
|
sink(uri);
|
||||||
|
sink(projection);
|
||||||
|
sink(queryArgs.get("some_key"));
|
||||||
|
sink(cancellationSignal);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
|
||||||
|
String sortOrder) {
|
||||||
|
sink(uri);
|
||||||
|
sink(projection);
|
||||||
|
sink(selection);
|
||||||
|
sink(selectionArgs);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
|
||||||
|
String sortOrder, CancellationSignal cancellationSignal) {
|
||||||
|
sink(uri);
|
||||||
|
sink(projection);
|
||||||
|
sink(selection);
|
||||||
|
sink(selectionArgs);
|
||||||
|
sink(sortOrder);
|
||||||
|
sink(cancellationSignal);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int update(Uri uri, ContentValues values, Bundle extras) {
|
||||||
|
sink(uri);
|
||||||
|
sink(values);
|
||||||
|
sink(extras.get("some_key"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||||
|
sink(uri);
|
||||||
|
sink(values);
|
||||||
|
sink(selection);
|
||||||
|
sink(selectionArgs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreate() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,190 @@
|
|||||||
|
package com.example.app;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import android.content.ContentProvider;
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.content.res.AssetFileDescriptor;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.CancellationSignal;
|
||||||
|
import android.os.ParcelFileDescriptor;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
|
||||||
|
public class Test extends ContentProvider {
|
||||||
|
|
||||||
|
void sink(Object o) {}
|
||||||
|
|
||||||
|
// "android.content;ContentProvider;true;call;(String,String,String,Bundle);;Parameter[0..3];contentprovider",
|
||||||
|
@Override
|
||||||
|
public Bundle call(String authority, String method, String arg, Bundle extras) {
|
||||||
|
sink(authority); // $ hasTaintFlow
|
||||||
|
sink(method); // $ hasTaintFlow
|
||||||
|
sink(arg); // $ hasTaintFlow
|
||||||
|
sink(extras.get("some_key")); // $ hasTaintFlow
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "android.content;ContentProvider;true;call;(String,String,Bundle);;Parameter[0..2];contentprovider",
|
||||||
|
public Bundle call(String method, String arg, Bundle extras) {
|
||||||
|
sink(method); // $ hasTaintFlow
|
||||||
|
sink(arg); // $ hasTaintFlow
|
||||||
|
sink(extras.get("some_key")); // $ hasTaintFlow
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "android.content;ContentProvider;true;delete;(Uri,String,String[]);;Parameter[0..2];contentprovider",
|
||||||
|
@Override
|
||||||
|
public int delete(Uri uri, String selection, String[] selectionArgs) {
|
||||||
|
sink(uri); // $ hasTaintFlow
|
||||||
|
sink(selection); // $ hasTaintFlow
|
||||||
|
sink(selectionArgs); // $ hasTaintFlow
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "android.content;ContentProvider;true;delete;(Uri,Bundle);;Parameter[0..1];contentprovider",
|
||||||
|
@Override
|
||||||
|
public int delete(Uri uri, Bundle extras) {
|
||||||
|
sink(uri); // $ hasTaintFlow
|
||||||
|
sink(extras.get("some_key")); // $ hasTaintFlow
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "android.content;ContentProvider;true;getType;(Uri);;Parameter[0];contentprovider",
|
||||||
|
@Override
|
||||||
|
public String getType(Uri uri) {
|
||||||
|
sink(uri); // $ hasTaintFlow
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "android.content;ContentProvider;true;insert;(Uri,ContentValues,Bundle);;Parameter[0..2];contentprovider",
|
||||||
|
@Override
|
||||||
|
public Uri insert(Uri uri, ContentValues values, Bundle extras) {
|
||||||
|
sink(uri); // $ hasTaintFlow
|
||||||
|
sink(values); // $ hasTaintFlow
|
||||||
|
sink(extras.get("some_key")); // $ hasTaintFlow
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "android.content;ContentProvider;true;insert;(Uri,ContentValues);;Parameter[0..1];contentprovider",
|
||||||
|
@Override
|
||||||
|
public Uri insert(Uri uri, ContentValues values) {
|
||||||
|
sink(uri); // $ hasTaintFlow
|
||||||
|
sink(values); // $ hasTaintFlow
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "android.content;ContentProvider;true;openAssetFile;(Uri,String,CancellationSignal);;Parameter[0];contentprovider",
|
||||||
|
@Override
|
||||||
|
public AssetFileDescriptor openAssetFile(Uri uri, String mode, CancellationSignal signal) {
|
||||||
|
sink(uri); // $ hasTaintFlow
|
||||||
|
sink(mode); // Safe
|
||||||
|
sink(signal); // Safe
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "android.content;ContentProvider;true;openAssetFile;(Uri,String);;Parameter[0];contentprovider",
|
||||||
|
@Override
|
||||||
|
public AssetFileDescriptor openAssetFile(Uri uri, String mode) {
|
||||||
|
sink(uri); // $ hasTaintFlow
|
||||||
|
sink(mode); // Safe
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "android.content;ContentProvider;true;openTypedAssetFile;(Uri,String,Bundle,CancellationSignal);;Parameter[0..2];contentprovider",
|
||||||
|
@Override
|
||||||
|
public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts,
|
||||||
|
CancellationSignal signal) throws RemoteException, FileNotFoundException {
|
||||||
|
sink(uri); // $ hasTaintFlow
|
||||||
|
sink(mimeTypeFilter); // $ hasTaintFlow
|
||||||
|
sink(opts.get("some_key")); // $ hasTaintFlow
|
||||||
|
sink(signal); // Safe
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "android.content;ContentProvider;true;openTypedAssetFile;(Uri,String,Bundle);;Parameter[0..2];contentprovider",
|
||||||
|
@Override
|
||||||
|
public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts)
|
||||||
|
throws FileNotFoundException {
|
||||||
|
sink(uri); // $ hasTaintFlow
|
||||||
|
sink(mimeTypeFilter); // $ hasTaintFlow
|
||||||
|
sink(opts.get("some_key")); // $ hasTaintFlow
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "android.content;ContentProvider;true;openFile;(Uri,String,CancellationSignal);;Parameter[0];contentprovider",
|
||||||
|
@Override
|
||||||
|
public ParcelFileDescriptor openFile(Uri uri, String mode, CancellationSignal signal) {
|
||||||
|
sink(uri); // $ hasTaintFlow
|
||||||
|
sink(mode); // Safe
|
||||||
|
sink(signal); // Safe
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "android.content;ContentProvider;true;openFile;(Uri,String);;Parameter[0..1];contentprovider",
|
||||||
|
@Override
|
||||||
|
public ParcelFileDescriptor openFile(Uri uri, String mode) {
|
||||||
|
sink(uri); // $ hasTaintFlow
|
||||||
|
sink(mode); // Safe
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "android.content;ContentProvider;true;query;(Uri,String[],Bundle,CancellationSignal);;Parameter[0..2];contentprovider",
|
||||||
|
@Override
|
||||||
|
public Cursor query(Uri uri, String[] projection, Bundle queryArgs,
|
||||||
|
CancellationSignal cancellationSignal) {
|
||||||
|
sink(uri); // $ hasTaintFlow
|
||||||
|
sink(projection); // $ hasTaintFlow
|
||||||
|
sink(queryArgs.get("some_key")); // $ hasTaintFlow
|
||||||
|
sink(cancellationSignal); // Safe
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "android.content;ContentProvider;true;query;(Uri,String[],String,String[],String);;Parameter[0..4];contentprovider",
|
||||||
|
@Override
|
||||||
|
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
|
||||||
|
String sortOrder) {
|
||||||
|
sink(uri); // $ hasTaintFlow
|
||||||
|
sink(projection); // $ hasTaintFlow
|
||||||
|
sink(selection); // $ hasTaintFlow
|
||||||
|
sink(selectionArgs); // $ hasTaintFlow
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "android.content;ContentProvider;true;query;(Uri,String[],String,String[],String,CancellationSignal);;Parameter[0..4];contentprovider",
|
||||||
|
@Override
|
||||||
|
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
|
||||||
|
String sortOrder, CancellationSignal cancellationSignal) {
|
||||||
|
sink(uri); // $ hasTaintFlow
|
||||||
|
sink(projection); // $ hasTaintFlow
|
||||||
|
sink(selection); // $ hasTaintFlow
|
||||||
|
sink(selectionArgs); // $ hasTaintFlow
|
||||||
|
sink(sortOrder); // $ hasTaintFlow
|
||||||
|
sink(cancellationSignal); // Safe
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "android.content;ContentProvider;true;update;(Uri,ContentValues,Bundle);;Parameter[0..2];contentprovider",
|
||||||
|
@Override
|
||||||
|
public int update(Uri uri, ContentValues values, Bundle extras) {
|
||||||
|
sink(uri); // $ hasTaintFlow
|
||||||
|
sink(values); // $ hasTaintFlow
|
||||||
|
sink(extras.get("some_key")); // $ hasTaintFlow
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "android.content;ContentProvider;true;update;(Uri,ContentValues,String,String[]);;Parameter[0..3];contentprovider"
|
||||||
|
@Override
|
||||||
|
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||||
|
sink(uri); // $ hasTaintFlow
|
||||||
|
sink(values); // $ hasTaintFlow
|
||||||
|
sink(selection); // $ hasTaintFlow
|
||||||
|
sink(selectionArgs); // $ hasTaintFlow
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreate() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/google-android-9.0.0
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import java
|
||||||
|
import semmle.code.java.dataflow.FlowSources
|
||||||
|
import TestUtilities.InlineFlowTest
|
||||||
|
|
||||||
|
class ProviderTaintFlowConf extends DefaultTaintFlowConf {
|
||||||
|
override predicate isSource(DataFlow::Node n) { n instanceof RemoteFlowSource }
|
||||||
|
}
|
||||||
|
|
||||||
|
class ProviderInlineFlowTest extends InlineFlowTest {
|
||||||
|
override DataFlow::Configuration getValueFlowConfig() { none() }
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,4 @@
|
|||||||
import java
|
import java
|
||||||
import semmle.code.java.dataflow.DataFlow
|
|
||||||
import semmle.code.java.dataflow.ExternalFlow
|
|
||||||
import semmle.code.java.dataflow.TaintTracking
|
|
||||||
import TestUtilities.InlineFlowTest
|
import TestUtilities.InlineFlowTest
|
||||||
|
|
||||||
class SummaryModelTest extends SummaryModelCsv {
|
class SummaryModelTest extends SummaryModelCsv {
|
||||||
@@ -9,8 +6,6 @@ class SummaryModelTest extends SummaryModelCsv {
|
|||||||
row =
|
row =
|
||||||
[
|
[
|
||||||
//"package;type;overrides;name;signature;ext;inputspec;outputspec;kind",
|
//"package;type;overrides;name;signature;ext;inputspec;outputspec;kind",
|
||||||
// This is temporarily modelled for the helper function newEnumerationWithElement, until the relevant package is modelled
|
|
||||||
"org.apache.commons.collections4.iterators;IteratorEnumeration;true;IteratorEnumeration;;;Element of Argument[0];Element of Argument[-1];value",
|
|
||||||
"generatedtest;Test;false;newRBWithMapValue;;;Argument[0];MapValue of ReturnValue;value",
|
"generatedtest;Test;false;newRBWithMapValue;;;Argument[0];MapValue of ReturnValue;value",
|
||||||
"generatedtest;Test;false;newRBWithMapKey;;;Argument[0];MapKey of ReturnValue;value"
|
"generatedtest;Test;false;newRBWithMapKey;;;Argument[0];MapKey of ReturnValue;value"
|
||||||
]
|
]
|
||||||
|
|||||||
131
java/ql/test/query-tests/security/CWE-074/XsltInjectionTest.java
Normal file
131
java/ql/test/query-tests/security/CWE-074/XsltInjectionTest.java
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import javax.xml.XMLConstants;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.stream.XMLInputFactory;
|
||||||
|
import javax.xml.transform.Source;
|
||||||
|
import javax.xml.transform.TransformerFactory;
|
||||||
|
import javax.xml.transform.dom.DOMSource;
|
||||||
|
import javax.xml.transform.sax.SAXSource;
|
||||||
|
import javax.xml.transform.stax.StAXSource;
|
||||||
|
import javax.xml.transform.stream.StreamResult;
|
||||||
|
import javax.xml.transform.stream.StreamSource;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.xml.sax.InputSource;
|
||||||
|
|
||||||
|
import net.sf.saxon.s9api.Processor;
|
||||||
|
import net.sf.saxon.s9api.XdmValue;
|
||||||
|
import net.sf.saxon.s9api.XsltCompiler;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class XsltInjectionTest {
|
||||||
|
public void testStreamSourceInputStream(Socket socket) throws Exception {
|
||||||
|
StreamSource source = new StreamSource(socket.getInputStream());
|
||||||
|
TransformerFactory.newInstance().newTransformer(source).transform(null, null); // $hasXsltInjection
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testStreamSourceReader(Socket socket) throws Exception {
|
||||||
|
StreamSource source = new StreamSource(new InputStreamReader(socket.getInputStream()));
|
||||||
|
TransformerFactory.newInstance().newTemplates(source).newTransformer().transform(null, null); // $hasXsltInjection
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping
|
||||||
|
public void testStreamSourceInjectedParam(@RequestParam String param) throws Exception {
|
||||||
|
String xslt = "<xsl:stylesheet [...]" + param + "</xsl:stylesheet>";
|
||||||
|
StreamSource source = new StreamSource(new StringReader(xslt));
|
||||||
|
TransformerFactory.newInstance().newTransformer(source).transform(null, null); // $hasXsltInjection
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSAXSourceInputStream(Socket socket) throws Exception {
|
||||||
|
SAXSource source = new SAXSource(new InputSource(socket.getInputStream()));
|
||||||
|
TransformerFactory.newInstance().newTemplates(source).newTransformer().transform(null, null); // $hasXsltInjection
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSAXSourceReader(Socket socket) throws Exception {
|
||||||
|
SAXSource source =
|
||||||
|
new SAXSource(null, new InputSource(new InputStreamReader(socket.getInputStream())));
|
||||||
|
TransformerFactory.newInstance().newTransformer(source).transform(null, null); // $hasXsltInjection
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testStAXSourceEventReader(Socket socket) throws Exception {
|
||||||
|
StAXSource source =
|
||||||
|
new StAXSource(XMLInputFactory.newInstance().createXMLEventReader(socket.getInputStream()));
|
||||||
|
TransformerFactory.newInstance().newTransformer(source).transform(null, null); // $hasXsltInjection
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testStAXSourceEventStream(Socket socket) throws Exception {
|
||||||
|
StAXSource source = new StAXSource(XMLInputFactory.newInstance().createXMLStreamReader(null,
|
||||||
|
new InputStreamReader(socket.getInputStream())));
|
||||||
|
TransformerFactory.newInstance().newTemplates(source).newTransformer().transform(null, null); // $hasXsltInjection
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDOMSource(Socket socket) throws Exception {
|
||||||
|
DOMSource source = new DOMSource(
|
||||||
|
DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(socket.getInputStream()));
|
||||||
|
TransformerFactory.newInstance().newTransformer(source).transform(null, null); // $hasXsltInjection
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDisabledXXE(Socket socket) throws Exception {
|
||||||
|
StreamSource source = new StreamSource(socket.getInputStream());
|
||||||
|
TransformerFactory factory = TransformerFactory.newInstance();
|
||||||
|
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
|
||||||
|
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
|
||||||
|
factory.newTransformer(source).transform(null, null); // $hasXsltInjection
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFeatureSecureProcessingDisabled(Socket socket) throws Exception {
|
||||||
|
StreamSource source = new StreamSource(socket.getInputStream());
|
||||||
|
TransformerFactory factory = TransformerFactory.newInstance();
|
||||||
|
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false);
|
||||||
|
factory.newTransformer(source).transform(null, null); // $hasXsltInjection
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSaxon(Socket socket) throws Exception {
|
||||||
|
StreamSource source = new StreamSource(socket.getInputStream());
|
||||||
|
XsltCompiler compiler = new Processor(true).newXsltCompiler();
|
||||||
|
|
||||||
|
compiler.compile(source).load().transform(); // $hasXsltInjection
|
||||||
|
compiler.compile(source).load30().transform(null, null); // $hasXsltInjection
|
||||||
|
compiler.compile(source).load30().applyTemplates((Source) null); // $hasXsltInjection
|
||||||
|
compiler.compile(source).load30().applyTemplates((Source) null, null); // $hasXsltInjection
|
||||||
|
compiler.compile(source).load30().applyTemplates((XdmValue) null); // $hasXsltInjection
|
||||||
|
compiler.compile(source).load30().applyTemplates((XdmValue) null, null); // $hasXsltInjection
|
||||||
|
compiler.compile(source).load30().callFunction(null, null); // $hasXsltInjection
|
||||||
|
compiler.compile(source).load30().callFunction(null, null, null); // $hasXsltInjection
|
||||||
|
compiler.compile(source).load30().callTemplate(null); // $hasXsltInjection
|
||||||
|
compiler.compile(source).load30().callTemplate(null, null); // $hasXsltInjection
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping
|
||||||
|
public void testSaxonXsltPackage(@RequestParam String param, Socket socket) throws Exception {
|
||||||
|
URI uri = new URI(param);
|
||||||
|
StreamSource source = new StreamSource(socket.getInputStream());
|
||||||
|
XsltCompiler compiler = new Processor(true).newXsltCompiler();
|
||||||
|
|
||||||
|
compiler.loadExecutablePackage(uri).load().transform(); // $hasXsltInjection
|
||||||
|
compiler.compilePackage(source).link().load().transform(); // $hasXsltInjection
|
||||||
|
compiler.loadLibraryPackage(uri).link().load().transform(); // $hasXsltInjection
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testOkFeatureSecureProcessing(Socket socket) throws Exception {
|
||||||
|
StreamSource source = new StreamSource(socket.getInputStream());
|
||||||
|
TransformerFactory factory = TransformerFactory.newInstance();
|
||||||
|
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
|
||||||
|
factory.newTransformer(source).transform(null, null); // Safe
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testOkSaxon(Socket socket) throws Exception {
|
||||||
|
StreamSource source = new StreamSource(socket.getInputStream());
|
||||||
|
XsltCompiler compiler = new Processor(true).newXsltCompiler();
|
||||||
|
|
||||||
|
compiler.compile(source).load().close(); // Safe
|
||||||
|
compiler.compile((Source) new Object()).load().transform(); // Safe
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import java
|
||||||
|
import semmle.code.java.dataflow.TaintTracking
|
||||||
|
import semmle.code.java.dataflow.FlowSources
|
||||||
|
import semmle.code.java.security.XsltInjectionQuery
|
||||||
|
import TestUtilities.InlineExpectationsTest
|
||||||
|
|
||||||
|
class HasXsltInjectionTest extends InlineExpectationsTest {
|
||||||
|
HasXsltInjectionTest() { this = "HasXsltInjectionTest" }
|
||||||
|
|
||||||
|
override string getARelevantTag() { result = "hasXsltInjection" }
|
||||||
|
|
||||||
|
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||||
|
tag = "hasXsltInjection" and
|
||||||
|
exists(DataFlow::Node src, DataFlow::Node sink, XsltInjectionFlowConfig conf |
|
||||||
|
conf.hasFlow(src, sink)
|
||||||
|
|
|
||||||
|
sink.getLocation() = location and
|
||||||
|
element = sink.toString() and
|
||||||
|
value = ""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1 +1 @@
|
|||||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/shiro-core-1.5.2:${testdir}/../../../stubs/spring-ldap-2.3.2
|
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/shiro-core-1.5.2:${testdir}/../../../stubs/spring-ldap-2.3.2:${testdir}/../../../stubs/Saxon-HE-9.9.1-7
|
||||||
|
|||||||
111
java/ql/test/query-tests/security/CWE-094/SpelInjectionTest.java
Normal file
111
java/ql/test/query-tests/security/CWE-094/SpelInjectionTest.java
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.Socket;
|
||||||
|
import org.springframework.expression.Expression;
|
||||||
|
import org.springframework.expression.ExpressionParser;
|
||||||
|
import org.springframework.expression.spel.standard.SpelExpression;
|
||||||
|
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||||
|
import org.springframework.expression.spel.support.SimpleEvaluationContext;
|
||||||
|
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||||
|
|
||||||
|
public class SpelInjectionTest {
|
||||||
|
|
||||||
|
private static final ExpressionParser PARSER = new SpelExpressionParser();
|
||||||
|
|
||||||
|
public void testGetValue(Socket socket) throws IOException {
|
||||||
|
InputStream in = socket.getInputStream();
|
||||||
|
|
||||||
|
byte[] bytes = new byte[1024];
|
||||||
|
int n = in.read(bytes);
|
||||||
|
String input = new String(bytes, 0, n);
|
||||||
|
|
||||||
|
ExpressionParser parser = new SpelExpressionParser();
|
||||||
|
Expression expression = parser.parseExpression(input);
|
||||||
|
expression.getValue(); // $hasSpelInjection
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetValueWithParseRaw(Socket socket) throws IOException {
|
||||||
|
InputStream in = socket.getInputStream();
|
||||||
|
|
||||||
|
byte[] bytes = new byte[1024];
|
||||||
|
int n = in.read(bytes);
|
||||||
|
String input = new String(bytes, 0, n);
|
||||||
|
SpelExpressionParser parser = new SpelExpressionParser();
|
||||||
|
SpelExpression expression = parser.parseRaw(input);
|
||||||
|
expression.getValue(); // $hasSpelInjection
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetValueWithChainedCalls(Socket socket) throws IOException {
|
||||||
|
InputStream in = socket.getInputStream();
|
||||||
|
|
||||||
|
byte[] bytes = new byte[1024];
|
||||||
|
int n = in.read(bytes);
|
||||||
|
String input = new String(bytes, 0, n);
|
||||||
|
|
||||||
|
Expression expression = new SpelExpressionParser().parseExpression(input);
|
||||||
|
expression.getValue(); // $hasSpelInjection
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSetValueWithRootObject(Socket socket) throws IOException {
|
||||||
|
InputStream in = socket.getInputStream();
|
||||||
|
|
||||||
|
byte[] bytes = new byte[1024];
|
||||||
|
int n = in.read(bytes);
|
||||||
|
String input = new String(bytes, 0, n);
|
||||||
|
|
||||||
|
Expression expression = new SpelExpressionParser().parseExpression(input);
|
||||||
|
|
||||||
|
Object root = new Object();
|
||||||
|
Object value = new Object();
|
||||||
|
expression.setValue(root, value); // $hasSpelInjection
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetValueWithStaticParser(Socket socket) throws IOException {
|
||||||
|
InputStream in = socket.getInputStream();
|
||||||
|
|
||||||
|
byte[] bytes = new byte[1024];
|
||||||
|
int n = in.read(bytes);
|
||||||
|
String input = new String(bytes, 0, n);
|
||||||
|
|
||||||
|
Expression expression = PARSER.parseExpression(input);
|
||||||
|
expression.getValue(); // $hasSpelInjection
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetValueType(Socket socket) throws IOException {
|
||||||
|
InputStream in = socket.getInputStream();
|
||||||
|
|
||||||
|
byte[] bytes = new byte[1024];
|
||||||
|
int n = in.read(bytes);
|
||||||
|
String input = new String(bytes, 0, n);
|
||||||
|
|
||||||
|
Expression expression = PARSER.parseExpression(input);
|
||||||
|
expression.getValueType(); // $hasSpelInjection
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWithStandardEvaluationContext(Socket socket) throws IOException {
|
||||||
|
InputStream in = socket.getInputStream();
|
||||||
|
|
||||||
|
byte[] bytes = new byte[1024];
|
||||||
|
int n = in.read(bytes);
|
||||||
|
String input = new String(bytes, 0, n);
|
||||||
|
|
||||||
|
Expression expression = PARSER.parseExpression(input);
|
||||||
|
|
||||||
|
StandardEvaluationContext context = new StandardEvaluationContext();
|
||||||
|
expression.getValue(context); // $hasSpelInjection
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWithSimpleEvaluationContext(Socket socket) throws IOException {
|
||||||
|
InputStream in = socket.getInputStream();
|
||||||
|
|
||||||
|
byte[] bytes = new byte[1024];
|
||||||
|
int n = in.read(bytes);
|
||||||
|
String input = new String(bytes, 0, n);
|
||||||
|
|
||||||
|
Expression expression = PARSER.parseExpression(input);
|
||||||
|
SimpleEvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
|
||||||
|
|
||||||
|
expression.getValue(context); // Safe - the expression is evaluated in a limited context
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import java
|
||||||
|
import semmle.code.java.dataflow.TaintTracking
|
||||||
|
import semmle.code.java.dataflow.FlowSources
|
||||||
|
import semmle.code.java.security.SpelInjectionQuery
|
||||||
|
import TestUtilities.InlineExpectationsTest
|
||||||
|
|
||||||
|
class HasSpelInjectionTest extends InlineExpectationsTest {
|
||||||
|
HasSpelInjectionTest() { this = "HasSpelInjectionTest" }
|
||||||
|
|
||||||
|
override string getARelevantTag() { result = "hasSpelInjection" }
|
||||||
|
|
||||||
|
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||||
|
tag = "hasSpelInjection" and
|
||||||
|
exists(DataFlow::Node src, DataFlow::Node sink, SpelInjectionConfig conf |
|
||||||
|
conf.hasFlow(src, sink)
|
||||||
|
|
|
||||||
|
sink.getLocation() = location and
|
||||||
|
element = sink.toString() and
|
||||||
|
value = ""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user