Compare commits

...

106 Commits

Author SHA1 Message Date
Esben Sparre Andreasen
ee314a4dad remove javascript 2021-09-29 11:19:08 +02:00
Mathias Vorreiter Pedersen
8dcf7926de Merge pull request #6760 from andersfugmann/relax_memberMayBeVarSize
Increase precision to high for cpp/static-buffer-overflow
2021-09-29 10:09:11 +02:00
Benjamin Muskalla
d09c3bf863 Merge pull request #6748 from bmuskalla/fixHiddenTypesTestGenerator
Java: Avoid stubbing methods with private parameter types
2021-09-29 09:27:13 +02:00
Anders Schack-Mulligen
1a92fa5d92 Merge pull request #6772 from github/workflow/coverage/update
Update CSV framework coverage reports
2021-09-29 09:25:19 +02:00
github-actions[bot]
8d2ad4ed17 Add changed framework coverage reports 2021-09-29 00:08:05 +00:00
Benjamin Muskalla
5f659f6e48 Merge branch 'main' into fixHiddenTypesTestGenerator 2021-09-28 17:42:39 +02:00
Shati Patel
ee46717c76 Merge pull request #6771 from shati-patel/mergeback-3.2-main
Merge 3.2 into main
2021-09-28 14:52:17 +01:00
Jonas Jensen
914e621d1b Merge pull request #6678 from andersfugmann/refactor_use_of_isGuardPhi
C++: Refactor code to use predicate isGuardPhi/4
2021-09-28 15:45:05 +02:00
Shati Patel
976190e84d Merge pull request #6764 from shati-patel/slides-links
Docs: Fix a few links in the training slides
2021-09-28 14:35:46 +01:00
Mathias Vorreiter Pedersen
06eb93da3f Merge pull request #6769 from github/docfix-dead-links-in-readme
Fix dead links in README.md
2021-09-28 15:21:19 +02:00
Mathias Vorreiter Pedersen
7197f41e75 Fix dead links in README.md 2021-09-28 15:12:36 +02:00
Edoardo Pirovano
5488872044 Merge pull request #6505 from edoardopirovano/trailing-comma
QL Language Spec: Trailing comma in set literal
2021-09-28 13:45:09 +01:00
Chris Smowton
413ac4e8f4 Merge pull request #6684 from owen-mc/java/model/apache-collections-subpackages
Java: model remaining subpackages of Apache Commons Collections
2021-09-28 12:28:48 +01:00
Tony Torralba
cec6cd0830 Merge pull request #6724 from atorralba/atorralba/android-contentprovider-sources
Java: Add sources for content providers in Android
2021-09-28 12:13:54 +02:00
Chris Smowton
39a12a8464 Remove models that are no longer required 2021-09-28 10:48:43 +01:00
Tony Torralba
46eb27cd01 Don't restrict inputs to be ParameterNodes
Co-authored-by: Anders Schack-Mulligen <aschackmull@users.noreply.github.com>
2021-09-28 11:21:56 +02:00
Anders Fugmann
ba98c0c1cb Merge remote-tracking branch 'upstream/main' into relax_memberMayBeVarSize 2021-09-28 11:15:11 +02:00
Anders Schack-Mulligen
fc8b439263 Merge pull request #6740 from aschackmull/java/callback-dispatch
Java: Add callback dispatch to more anonymous classes.
2021-09-28 10:49:27 +02:00
Anders Peter Fugmann
a358ea8667 C++: Apply documentation change suggestion
Co-authored-by: Jonas Jensen <jbj@github.com>
2021-09-28 10:38:02 +02:00
Anders Schack-Mulligen
c294b75f6c Merge pull request #6766 from github/workflow/coverage/update
Update CSV framework coverage reports
2021-09-28 10:35:43 +02:00
Shati Patel
d5e17f9ebf Merge pull request #6765 from shati-patel/docs-config-fixes
Docs: Fix inconsistencies in sphinx config files
2021-09-28 09:18:02 +01:00
Anders Peter Fugmann
c7ea7ca5cd C++: Apply documentation change suggestion
Co-authored-by: Jonas Jensen <jbj@github.com>
2021-09-28 09:40:25 +02:00
Anders Peter Fugmann
49c656d904 C++: Apply documentation change suggestion
Co-authored-by: Jonas Jensen <jbj@github.com>
2021-09-28 09:40:07 +02:00
Anders Fugmann
79549c2285 Merge remote-tracking branch 'upstream/main' into refactor_use_of_isGuardPhi 2021-09-28 09:38:16 +02:00
Owen Mansel-Chan
787f36f056 Add a change note 2021-09-28 07:32:28 +01:00
github-actions[bot]
b7b229d59b Add changed framework coverage reports 2021-09-28 00:08:59 +00:00
shati-patel
64fcbe05c3 Docs: Fix inconsistencies in sphinx config files 2021-09-27 18:54:23 +01:00
shati-patel
31c34870ef Fix warning about "Anonymous hyperlink mismatch" 2021-09-27 18:27:57 +01:00
shati-patel
3c17ac424d Docs: Fix some broken/redirected links 2021-09-27 18:27:30 +01:00
Felicity Chapman
bb6c079e5a Merge pull request #6762 from github/felicitymay-patch-1
Update links to match those on the staging site
2021-09-27 16:49:58 +01:00
Felicity Chapman
a3c1975a84 Update links to match those on the staging site 2021-09-27 16:35:22 +01:00
Owen Mansel-Chan
bdd78d2bc7 Fix stub 2021-09-27 16:24:41 +01:00
Owen Mansel-Chan
29db42c3cd Generate stubs 2021-09-27 16:24:40 +01:00
Owen Mansel-Chan
e6df8164cf Fix up old tests for new helper functions 2021-09-27 16:24:39 +01:00
Owen Mansel-Chan
cf03bd8bd1 Merge new and old tests
# Conflicts:
#	java/ql/test/library-tests/frameworks/apache-collections/TestNew.java
2021-09-27 16:24:38 +01:00
Owen Mansel-Chan
342c14887b Fix existing models for MapUtils 2021-09-27 16:24:37 +01:00
Owen Mansel-Chan
e1101e582e Minor improvement to existing tests 2021-09-27 16:24:37 +01:00
Owen Mansel-Chan
768203bd36 Remove redundant casts 2021-09-27 16:24:36 +01:00
Owen Mansel-Chan
c51fb00082 Add tests for non-public abstract classes 2021-09-27 16:24:35 +01:00
Owen Mansel-Chan
0a92b04c8b Fix up automatically generated tests 2021-09-27 16:24:34 +01:00
Owen Mansel-Chan
15161d8867 Make concrete subclasses of abstract classes 2021-09-27 16:24:33 +01:00
Owen Mansel-Chan
53ee465726 Fix errors in generated tests that stop compilation 2021-09-27 16:24:32 +01:00
Owen Mansel-Chan
a20acfee25 Add automatically generated tests
Also update test.ql to use the new InlineFlowTest.
2021-09-27 16:24:31 +01:00
Owen Mansel-Chan
f69787afd0 Miscellaneous model fixes 2021-09-27 16:24:30 +01:00
Owen Mansel-Chan
9b12980688 Do not model some protected methods 2021-09-27 16:24:29 +01:00
Owen Mansel-Chan
cb0f82c36e Do not modelled protected static inner classes 2021-09-27 16:24:29 +01:00
Owen Mansel-Chan
3b678bfbc5 Address review comments 2021-09-27 16:24:28 +01:00
Owen Mansel-Chan
e1750adc38 Address problems highlighted by generating tests 2021-09-27 16:24:27 +01:00
Owen Mansel-Chan
fd0fb9483e Model the remaining subpackages in Apache Commons Collections 2021-09-27 16:24:26 +01:00
Owen Mansel-Chan
3d1d491e6b Model java.lang.Object.clone() better for access paths.
Model value flow for Element, MapKey and MapValue. This assumes
that clone() is a shallow copy.
2021-09-27 16:24:25 +01:00
Edoardo Pirovano
18020707b8 QL Language Spec: Trailing comma in set literal 2021-09-27 15:57:39 +01:00
Anders Schack-Mulligen
cfa0d46b73 Merge pull request #6097 from atorralba/atorralba/promote-xslt-injection
Java: Promote XSLT Injection from experimental
2021-09-27 13:14:57 +02:00
Anders Schack-Mulligen
e027d514f1 Merge pull request #6037 from atorralba/atorralba/promote-spel-injection
Java: Promote SpEL Injection query from experimental
2021-09-27 13:13:35 +02:00
Tony Torralba
d5f675c2dc Fix unbound field
Add tests for non-exported providers
2021-09-27 12:58:28 +02:00
Tony Torralba
78c12dc505 Move to lib 2021-09-27 12:04:14 +02:00
Tony Torralba
ad08ccb50b Apply suggestion from code review 2021-09-27 12:00:21 +02:00
mc
95751fcc21 Update XsltInjection.qhelp
Made a few minor tweaks during editorial review
2021-09-27 12:00:21 +02:00
Tony Torralba
13417dbf14 Remove DataFlow references from XsltInjection.qll 2021-09-27 12:00:20 +02:00
Tony Torralba
ff21662b23 Refactor XsltInjection.qll 2021-09-27 12:00:18 +02:00
Tony Torralba
6967b06dee Decouple XsltInjection.qll to reuse the taint tracking configuration 2021-09-27 11:59:51 +02:00
Tony Torralba
fc58ada92e Add change note 2021-09-27 11:58:20 +02:00
Tony Torralba
108118afa3 Use InlineExpectationsTest 2021-09-27 11:58:18 +02:00
Tony Torralba
d8bb5273e7 Refactor to use CSV sink models 2021-09-27 11:57:58 +02:00
Tony Torralba
c792567904 Move from experimental 2021-09-27 11:57:53 +02:00
Tony Torralba
6d9a88d1c8 Move to lib 2021-09-27 11:43:46 +02:00
mc
3520fed752 Update SpelInjection.qhelp 2021-09-27 11:40:51 +02:00
Tony Torralba
d10dbbdd9d Apply suggestions from code review
Co-authored-by: Marcono1234 <Marcono1234@users.noreply.github.com>
2021-09-27 11:40:51 +02:00
Tony Torralba
6bf1e87bbe Remove CSV sinks; make imports private 2021-09-27 11:40:47 +02:00
Tony Torralba
91f46624b6 Refactor SpelInjection.qll 2021-09-27 11:40:26 +02:00
Tony Torralba
94f32d2985 Decouple SpelInjection.qll to reuse the taint tracking configuration 2021-09-27 11:39:30 +02:00
Tony Torralba
569426b04e Consider subtypes of Expression and ExpressionParser
Add parseRaw as additional taint step
2021-09-27 11:38:12 +02:00
Tony Torralba
b0852f6c16 Add change note 2021-09-27 11:37:46 +02:00
Tony Torralba
b985ddb868 Use InlineExpectationsTest 2021-09-27 11:37:41 +02:00
Tony Torralba
079769ed2e Refactored SpelInjection.qll to use CSV sink models 2021-09-27 11:36:56 +02:00
Tony Torralba
fc6af0476f Moved from experimental 2021-09-27 11:36:48 +02:00
Anders Fugmann
03bd7d7f96 C++: Update test results from OverflowStatic 2021-09-27 11:23:08 +02:00
Anders Schack-Mulligen
92ffd8c465 Merge pull request #6749 from aschackmull/java/istextblock
Java: Add StringLiteral.isTextBlock().
2021-09-27 10:54:31 +02:00
Jonas Jensen
b0836a620c Merge pull request #6757 from geoffw0/impropnulltest2
C++: Small improvement to cpp/improper-null-termination
2021-09-27 10:52:49 +02:00
James Fletcher
c977cfe40a Merge pull request #6754 from github/update-link
Update one more link in the QL training content
2021-09-27 08:33:42 +01:00
Anders Fugmann
e0921ac983 C++: Increase precision of cpp/static-buffer-overflow to high 2021-09-27 09:06:36 +02:00
Geoffrey White
7e7dfe2cc4 C++: Understand format arguments. 2021-09-24 19:25:43 +01:00
Geoffrey White
91a8b9fdd9 C++: Add suggested test (and a good variant). 2021-09-24 18:34:28 +01:00
james
1adc5c2a5b update links correctly 2021-09-24 17:00:59 +01:00
james
e664711f47 make links to slide decks relative 2021-09-24 14:56:48 +01:00
james
23e4ad1abb update one more link 2021-09-24 14:46:14 +01:00
Anders Schack-Mulligen
854f2a046a Java: Add StringLiteral.isTextBlock(). 2021-09-24 13:11:18 +02:00
Benjamin Muskalla
70e1724463 Exclude methods with non-public parameter types 2021-09-24 12:41:12 +02:00
Anders Fugmann
cbdabe35de C++: Update test results to reflect changes 2021-09-24 12:29:28 +02:00
Anders Fugmann
032ac50034 C++: Do not warn on static buffer overflow using loop counters, if the loop counter has been widened 2021-09-24 08:31:36 +02:00
Anders Fugmann
3e5f7d0db5 C++: using buildin offsetof for an array member indexed after end is legal 2021-09-24 08:31:35 +02:00
Anders Fugmann
b08eabec68 C++: Relax predicate memberMayBeVarSize to mark all members of size 0 or 1 as variable sized 2021-09-24 08:31:35 +02:00
Anders Fugmann
a4a9e2aa96 C++: Weaken wording on overflow static alert text 2021-09-24 08:31:35 +02:00
Anders Schack-Mulligen
4841c3037d Java: Add callback dispatch to more anonymous classes. 2021-09-23 14:34:56 +02:00
Tony Torralba
99881db8bd Add stubs 2021-09-21 12:10:05 +02:00
Tony Torralba
0c1f3ed0b3 Add tests for ContentProvider sources 2021-09-21 12:09:47 +02:00
Tony Torralba
a811ab3aff Add ContentProvider sources 2021-09-21 12:09:28 +02:00
Felicity Chapman
7383988988 Merge pull request #6701 from github/docs-4908-training-note-links
Update links in training notes to use CodeQL microsite
2021-09-17 09:00:36 +01:00
james
e906ded0d1 remove java class 2021-09-17 08:48:26 +01:00
james
c36292bfd0 a few more links 2021-09-16 17:03:29 +01:00
Felicity Chapman
05d83e487d Update all links to CodeQL microsite 2021-09-15 17:08:55 +01:00
Anders Fugmann
3f5ab60fb4 C++: Add DEPRECATED to documentation block 2021-09-14 09:55:19 +02:00
Anders Fugmann
8e9ac18026 C++: Deprecate RangeSSA::isGuardPhi/3 2021-09-13 15:35:05 +02:00
Felicity Chapman
1d76578202 Merge pull request #6659 from github/docs-311-update-version
Update version numbers for LGTM Enterprise 1.28
2021-09-13 10:26:52 +01:00
Anders Fugmann
2c93bce9ad C++: Refactor code to use predicate isGuardPhi/4 2021-09-10 10:53:48 +02:00
Felicity Chapman
3b3350e648 Correct the Qllexer path for slides 2021-09-10 08:04:07 +01:00
Felicity Chapman
32b3e416b3 Update version numbers for LGTM E 1.28 2021-09-10 06:54:36 +01:00
7284 changed files with 10822 additions and 590201 deletions

View File

@@ -4,8 +4,8 @@ This open source repository contains the standard CodeQL libraries and queries t
## 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.
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.
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://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

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

View File

@@ -10,44 +10,11 @@ import semmle.code.cpp.dataflow.DataFlow
* char data[1]; // v
* };
* ```
* This requires that `v` is an array of size 0 or 1, and `v` is the last member of `c`.
* 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))
* ```
* This requires that `v` is an array of size 0 or 1.
*/
predicate memberMayBeVarSize(Class c, MemberVariable v) {
exists(int i |
// `v` is the last field in `c`
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
)
)
c = v.getDeclaringType() and
v.getUnspecifiedType().(ArrayType).getArraySize() <= 1
}
/**
@@ -60,10 +27,6 @@ int getBufferSize(Expr bufferExpr, Element why) {
result = bufferVar.getUnspecifiedType().(ArrayType).getSize() and
why = 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
or
// 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
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
// buffer is a fixed size dynamic allocation

View File

@@ -93,6 +93,15 @@ predicate variableMustBeNullTerminated(VariableAccess va) {
fc.getArgument(i) = va
)
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
// (not itself adding a null terminator)
exists(Function wrapper, int i, Parameter p, VariableAccess use |

View File

@@ -29,8 +29,7 @@ predicate nanExcludingComparison(ComparisonOperation guard, boolean polarity) {
*/
private predicate excludesNan(RangeSsaDefinition def, VariableAccess v) {
exists(VariableAccess inCond, ComparisonOperation guard, boolean branch, StackVariable lsv |
def.isGuardPhi(inCond, guard, branch) and
inCond.getTarget() = lsv and
def.isGuardPhi(lsv, inCond, guard, branch) and
v = def.getAUse(lsv) and
guard.getAnOperand() = inCond and
nanExcludingComparison(guard, branch)

View File

@@ -94,10 +94,11 @@ class RangeSsaDefinition extends ControlFlowNodeBase {
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,
* 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)
}
@@ -142,9 +143,8 @@ class RangeSsaDefinition extends ControlFlowNodeBase {
// below excludes definitions which can only reach guard phi
// nodes by going through the corresponding guard.
not exists(VariableAccess access |
v = access.getTarget() and
pred.contains(access) and
this.isGuardPhi(access, _, _)
this.isGuardPhi(v, access, _, _)
)
)
}

View File

@@ -433,10 +433,7 @@ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVaria
private predicate phiDependsOnDef(
RangeSsaDefinition phi, StackVariable v, RangeSsaDefinition srcDef, StackVariable srcVar
) {
exists(VariableAccess access, Expr guard |
access = v.getAnAccess() and
phi.isGuardPhi(access, guard, _)
|
exists(VariableAccess access, Expr guard | phi.isGuardPhi(v, access, guard, _) |
exprDependsOnDef(guard.(ComparisonOperation).getAnOperand(), srcDef, srcVar) or
exprDependsOnDef(access, srcDef, srcVar)
)
@@ -1204,8 +1201,7 @@ private float boolConversionUpperBound(Expr expr) {
*/
private float getPhiLowerBounds(StackVariable v, RangeSsaDefinition phi) {
exists(VariableAccess access, Expr guard, boolean branch, float defLB, float guardLB |
access = v.getAnAccess() and
phi.isGuardPhi(access, guard, branch) and
phi.isGuardPhi(v, access, guard, branch) and
lowerBoundFromGuard(guard, access, guardLB, branch) and
defLB = getFullyConvertedLowerBounds(access)
|
@@ -1230,8 +1226,7 @@ private float getPhiLowerBounds(StackVariable v, RangeSsaDefinition phi) {
/** See comment for `getPhiLowerBounds`, above. */
private float getPhiUpperBounds(StackVariable v, RangeSsaDefinition phi) {
exists(VariableAccess access, Expr guard, boolean branch, float defUB, float guardUB |
access = v.getAnAccess() and
phi.isGuardPhi(access, guard, branch) and
phi.isGuardPhi(v, access, guard, branch) and
upperBoundFromGuard(guard, access, guardUB, branch) and
defUB = getFullyConvertedUpperBounds(access)
|
@@ -1493,8 +1488,7 @@ private predicate isNEPhi(
exists(
ComparisonOperation cmp, boolean branch, Expr linearExpr, Expr rExpr, float p, float q, float r
|
access.getTarget() = v and
phi.isGuardPhi(access, cmp, branch) and
phi.isGuardPhi(v, access, cmp, branch) and
eqOpWithSwapAndNegate(cmp, linearExpr, rExpr, false, branch) and
v.getUnspecifiedType() instanceof IntegralOrEnumType and // Float `!=` is too imprecise
r = getValue(rExpr).toFloat() and
@@ -1503,8 +1497,7 @@ private predicate isNEPhi(
)
or
exists(Expr op, boolean branch, Expr linearExpr, float p, float q |
access.getTarget() = v and
phi.isGuardPhi(access, op, branch) and
phi.isGuardPhi(v, access, op, branch) and
eqZeroWithNegate(op, linearExpr, false, branch) and
v.getUnspecifiedType() instanceof IntegralOrEnumType and // Float `!` is too imprecise
linearAccess(linearExpr, access, p, q) and
@@ -1524,8 +1517,7 @@ private predicate isUnsupportedGuardPhi(Variable v, RangeSsaDefinition phi, Vari
or
eqZeroWithNegate(cmp, _, false, branch)
|
access.getTarget() = v and
phi.isGuardPhi(access, cmp, branch) and
phi.isGuardPhi(v, access, cmp, branch) and
not isNEPhi(v, phi, access, _)
)
}
@@ -1594,6 +1586,15 @@ private module SimpleRangeAnalysisCached {
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:
*

View File

@@ -5,7 +5,7 @@
* @kind problem
* @problem.severity warning
* @security-severity 9.3
* @precision medium
* @precision high
* @id cpp/static-buffer-overflow
* @tags reliability
* security
@@ -55,6 +55,8 @@ predicate overflowOffsetInLoop(BufferAccess bufaccess, string msg) {
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.
not upperBound(bufaccess.getArrayOffset().getFullyConverted()) < bufaccess.bufferSize() and
// The upper bounds analysis must not have been widended
not upperBoundMayBeWidened(bufaccess.getArrayOffset().getFullyConverted()) and
msg =
"Potential buffer-overflow: counter '" + loop.counter().toString() + "' <= " +
loop.limit().toString() + " but '" + bufaccess.buffer().getName() + "' has " +
@@ -130,11 +132,13 @@ predicate outOfBounds(BufferAccess bufaccess, string msg) {
(
access > size
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
msg =
"Potential buffer-overflow: '" + buf + "' has size " + size.toString() + " but '" + buf + "[" +
access.toString() + "]' is accessed here."
access.toString() + "]' may be accessed here."
)
}

View File

@@ -5,14 +5,10 @@
| 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: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:15:9:15:13 | access to array | Potential buffer-overflow: 'xs' has size 5 but 'xs[6]' is 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:21:9:21:18 | access to array | Potential buffer-overflow: 'ys' has size 5 but 'ys[6]' is 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.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]' may be 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]' may be accessed here. |
| 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:24:27:24:27 | 4 | Potential buffer-overflow: 'buffer1' has size 3 not 4. |

View File

@@ -44,21 +44,21 @@ void union_test() {
union u u;
u.ptr[0] = 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() {
struct { union u u; } v;
v.u.ptr[0] = 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() {
union { char ptr[1]; unsigned long value; } u;
u.ptr[0] = 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 {
@@ -69,5 +69,5 @@ typedef struct {
void test_alloc() {
// Special case of taking sizeof without any addition or multiplications
var_buf *b = malloc(sizeof(var_buf));
b->buf[1] = 0; // BAD
b->buf[1] = 0; // BAD [NOT DETECTED]
}

View File

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

View File

@@ -433,3 +433,36 @@ void test_read_fread(int read_src, FILE *s)
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
}
}

View File

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

View File

@@ -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: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:349:2:349:14 | 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]' is 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. |
| 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]' may be accessed here. |
| var_size_struct.cpp:103:39:103:41 | 129 | Potential buffer-overflow: 'str' has size 128 not 129. |

View File

@@ -51,8 +51,8 @@ void testVarString(int n) {
s1->str[1] = '?'; // GOOD
s2->str[1] = '?'; // GOOD
s3->str[1] = '?'; // GOOD
s4->str[1] = '?'; // BAD
s5->str[1] = '?'; // BAD
s4->str[1] = '?'; // BAD [NOT DETECTED]
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) {
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(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

View File

@@ -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: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: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: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: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: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: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: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:181:8:181:18 | PseudoUnion | var_size_struct.cpp:183:7:183:10 | data |

View File

@@ -8,7 +8,7 @@ The CodeQL documentation in this repository is written in reStructuredText and c
HTML using Sphinx.
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.
@@ -99,7 +99,7 @@ generates html slide shows in the ``<slides-output>`` directory when run from
the ``ql-training`` source directory.
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
*******************************************************

View File

@@ -252,8 +252,6 @@ Miscellaneous
+=====================================+====================+============================================================================+
| ``(int) f`` | CastExpr_ | |
+-------------------------------------+--------------------+----------------------------------------------------------------------------+
| ``(23 + 42)`` | ParExpr_ | |
+-------------------------------------+--------------------+----------------------------------------------------------------------------+
| ``o instanceof String`` | InstanceOfExpr_ | |
+-------------------------------------+--------------------+----------------------------------------------------------------------------+
| `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
.. _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
.. _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
.. _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

View File

@@ -55,12 +55,12 @@ def setup(sphinx):
sphinx.add_lexer("ql", QLLexer())
# 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.
version = u'3.0'
# version = u'3.0'
# 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
# for a list of supported languages.

View File

@@ -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.
@@ -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.
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
-----------------------------
@@ -2170,7 +2172,7 @@ The complete grammar for QL is as follows:
range ::= "[" expr ".." expr "]"
setliteral ::= "[" expr ("," expr)* "]"
setliteral ::= "[" expr ("," expr)* ","? "]"
simpleId ::= lowerId | upperId

View File

@@ -47,7 +47,7 @@ import sys
import os
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
sphinx.add_lexer("ql", QLLexer())
@@ -86,11 +86,11 @@ htmlhelp_basename = 'CodeQL training'
# built documents.
#
# The short X.Y version.
version = u'1.24'
# version = u'1.24'
# The full version, including alpha/beta/rc tags.
release = u'1.24'
copyright = u'2019 Semmle Ltd'
author = u'Semmle Ltd'
# release = u'1.24'
# copyright = u'2019 Semmle Ltd'
# author = u'Semmle Ltd'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

View File

@@ -11,12 +11,12 @@ Setup
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>`__
.. 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.
@@ -149,7 +149,7 @@ Lets look for overflow guards of the form ``v + b < v``, using the classes
- a ``RelationalOperation``: the overflow comparison check.
- 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
=================================
@@ -229,4 +229,4 @@ The final query
.. literalinclude:: ../query-examples/cpp/bad-overflow-guard-3.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>`__.

View File

@@ -13,12 +13,12 @@ Setup
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>`__
.. 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.
@@ -222,7 +222,7 @@ A ``GuardCondition`` is a ``Boolean`` condition that controls one or more basic
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
.. rst-class:: end-slide

View File

@@ -11,7 +11,7 @@ Setup
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>`__
.. note::
@@ -139,7 +139,7 @@ Define a subclass of ``DataFlow::Node`` representing “source” nodes, that is
.. note::
Note the scoping of the `dont-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 `dont-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

View File

@@ -11,7 +11,7 @@ Setup
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>`__
.. note::

View File

@@ -11,7 +11,7 @@ Setup
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>`__
.. 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>`__.
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``.
The query proper starts by declaring two variablesifStmt 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``.
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 others 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 others 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
==========
@@ -131,7 +131,7 @@ A predicate allows you to pull out and name parts of a query.
.. 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.
@@ -154,7 +154,7 @@ Member predicates are inherited and can be overridden.
.. 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.

View File

@@ -11,7 +11,7 @@ Setup
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>`__
.. note::

View File

@@ -15,7 +15,7 @@ Setup
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>`__
.. note::
@@ -134,4 +134,4 @@ Model answer, step 4
and sink.getNode() instanceof UnsafeDeserializationSink
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

View File

@@ -11,7 +11,7 @@ Setup
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>`__
.. note::

View File

@@ -11,7 +11,7 @@ Setup
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>`__
.. note::
@@ -54,7 +54,7 @@ Code injection in Apache struts
.. note::
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/

View File

@@ -11,7 +11,7 @@ Setup
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>`__
.. 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>`__.
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``.
The query proper starts by declaring two variablesifStmt 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``.
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 others 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 others 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
==========
@@ -130,7 +130,7 @@ A predicate allows you to pull out and name parts of a query.
.. 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.
@@ -154,7 +154,7 @@ Member predicates are inherited and can be overridden.
.. 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.

View File

@@ -11,7 +11,7 @@ Setup
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>`__
.. note::
@@ -84,7 +84,7 @@ Lets start by looking for calls to methods with names of the form ``sparql*Qu
- a ``MethodAccess``: the call to a 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
=======================================

View File

@@ -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:
- `CodeQL library for C/C++ <https://help.semmle.com/QL/learn-ql/cpp/introduce-libraries-cpp.html>`__
- `CodeQL library for C# <https://help.semmle.com/QL/learn-ql/csharp/introduce-libraries-csharp.html>`__
- `CodeQL library for Java <https://help.semmle.com/QL/learn-ql/java/introduce-libraries-java.html>`__
- `CodeQL library for C/C++ <https://codeql.github.com/docs/codeql-language-guides/codeql-library-for-cpp/>`__
- `CodeQL library for C# <https://codeql.github.com/docs/codeql-language-guides/codeql-library-for-csharp/>`__
- `CodeQL library for Java <https://codeql.github.com/docs/codeql-language-guides/codeql-library-for-java/>`__
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:
- https://github.com/github/codeql/blob/main/cpp/ql/src/semmlecode.cpp.dbscheme
- https://github.com/github/codeql/blob/main/csharp/ql/src/semmlecode.csharp.dbscheme
- https://github.com/github/codeql/blob/main/java/ql/src/config/semmlecode.dbscheme
- https://github.com/github/codeql/blob/main/cpp/ql/lib/semmlecode.cpp.dbscheme
- https://github.com/github/codeql/blob/main/csharp/ql/lib/semmlecode.csharp.dbscheme
- https://github.com/github/codeql/blob/main/java/ql/lib/config/semmlecode.dbscheme

View File

@@ -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
#. 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 addedthe CodeQL database available to download above is based on an historical version of the codebase.

View File

@@ -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.
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 developers machine.
@@ -124,7 +124,7 @@ QL is:
.. 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:
- All common logic connectives are available, including quantifiers like ``exist``, which can also introduce new variables.

View File

@@ -70,7 +70,7 @@ Local vs global data flow
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
@@ -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.
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 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 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://codeql.github.com/docs/ql-language-reference/name-resolution/>`__ in the QL language reference.
Data flow graph
===============
@@ -131,7 +131,7 @@ Data flow graph
The ``DataFlow::Node`` class is shared between both the local and global data flow graphsthe primary difference is the edges, which in the “global” case can link different functions.
``localFlowStep`` is the “single step” flow relationthat 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 relationin 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 relationthat 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 relationin 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 typesexpression 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.

View File

@@ -36,7 +36,7 @@ Setup
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
.. note::
@@ -159,7 +159,7 @@ Specify the language to apply syntax highlighting and the lines of the fragment
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.

View File

@@ -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 short X.Y version.
version = u'1.27'
# The full version, including alpha/beta/rc tags.
release = u'1.27'
# LGTM Enterprise release
release = u'1.28'
# CodeQL CLI version used by LGTM Enterprise release
version = u'2.5.9'
# -- Project-specifc options for HTML output ----------------------------------------------
@@ -66,9 +69,9 @@ html_theme_options = {'font_size': '16px',
'body_text': '#333',
'link': '#2F1695',
'link_hover': '#2F1695',
'font_family': 'Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Segoe UI Symbol;',
'show_powered_by': False,
'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'

View File

@@ -1,7 +1,7 @@
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::

View File

@@ -1,8 +1,7 @@
Languages and compilers
#######################
CodeQL and LGTM version |version| support analysis of the following languages compiled by the following compilers.
(CodeQL was previously known as QL.)
LGTM Enterprise |release| includes CodeQL CLI |version|. LGTM Enterprise supports analysis of the following languages compiled by the following compilers.
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.

View File

@@ -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.
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::
@@ -39,25 +39,25 @@ We recommend that you download `CodeQL for Visual Studio Code <https://help.semm
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.
- `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.
- `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.
- `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.
- `Exercise: snprintf overflow <https://help.semmle.com/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.
- `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.
- `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 </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++ </QL/ql-training/cpp/program-representation-cpp.html>`__information on how CodeQL analysis represents C/C++ programs.
- `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 </QL/ql-training/cpp/snprintf.html>`__an example demonstrating how to develop a data flow query.
- `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++ </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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- `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.
- `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.
- `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.
- `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.
- `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.
- `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 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 </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 </QL/ql-training/java/program-representation-java.html>`__information on how CodeQL analysis represents Java programs.
- `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 </QL/ql-training/java/apache-struts-java.html>`__an example demonstrating how to develop a data flow query.
- `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
~~~~~~~~~~~~~~~
- `GitHub Security Lab <https://securitylab.github.com/research>`__
- `GitHub Security Lab <https://securitylab.github.com/research>`__

View 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).

View 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).

View File

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

View File

@@ -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
android.content,8,,4,,,,,,,,,,,,,8,,,,,,4,
android.database,59,,30,,,,,,,,,,,,,59,,,,,,30,
android.net,,,60,,,,,,,,,,,,,,,,,,,45,15
android.util,,16,,,,,,,,,,,,,,,,,,,16,,
android.webkit,3,2,,,,,,,,,,,,,,,,,,3,2,,
com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,,,,,,,,,1,
com.esotericsoftware.kryo5.io,,,1,,,,,,,,,,,,,,,,,,,1,
com.fasterxml.jackson.core,,,1,,,,,,,,,,,,,,,,,,,1,
com.fasterxml.jackson.databind,,,5,,,,,,,,,,,,,,,,,,,5,
com.google.common.base,,,85,,,,,,,,,,,,,,,,,,,62,23
com.google.common.cache,,,17,,,,,,,,,,,,,,,,,,,,17
com.google.common.collect,,,553,,,,,,,,,,,,,,,,,,,2,551
com.google.common.io,6,,73,,,,,,,,,,,,,,6,,,,,72,1
com.opensymphony.xwork2.ognl,3,,,,,,,,,,,,3,,,,,,,,,,
com.unboundid.ldap.sdk,17,,,,,,,,,,17,,,,,,,,,,,,
flexjson,,,1,,,,,,,,,,,,,,,,,,,,1
groovy.lang,26,,,,,26,,,,,,,,,,,,,,,,,
groovy.util,5,,,,,5,,,,,,,,,,,,,,,,,
jakarta.faces.context,2,7,,,,,,,,,,,,,,,,,,2,7,,
jakarta.json,,,123,,,,,,,,,,,,,,,,,,,100,23
jakarta.ws.rs.client,1,,,,,,,,,,,,,1,,,,,,,,,
jakarta.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,9,,
jakarta.ws.rs.core,2,,149,,,,,,,,,,,,,,,2,,,,94,55
java.beans,,,1,,,,,,,,,,,,,,,,,,,1,
java.io,3,,27,,3,,,,,,,,,,,,,,,,,26,1
java.lang,,,47,,,,,,,,,,,,,,,,,,,41,6
java.net,10,3,7,,,,,,,,,,,10,,,,,,,3,7,
java.nio,10,,4,,10,,,,,,,,,,,,,,,,,4,
java.sql,7,,,,,,,,,,,,,,,7,,,,,,,
java.util,,,337,,,,,,,,,,,,,,,,,,,15,322
javax.faces.context,2,7,,,,,,,,,,,,,,,,,,2,7,,
javax.json,,,123,,,,,,,,,,,,,,,,,,,100,23
javax.management.remote,2,,,,,,,,,2,,,,,,,,,,,,,
javax.naming,7,,,,,,,,,6,1,,,,,,,,,,,,
javax.net.ssl,2,,,,,,,,,,,,,,2,,,,,,,,
javax.script,1,,,,,,,,,,,1,,,,,,,,,,,
javax.servlet,4,21,2,,,,3,1,,,,,,,,,,,,,21,2,
javax.validation,1,1,,1,,,,,,,,,,,,,,,,,1,,
javax.ws.rs.client,1,,,,,,,,,,,,,1,,,,,,,,,
javax.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,9,,
javax.ws.rs.core,3,,149,,,,1,,,,,,,,,,,2,,,,94,55
javax.xml.transform.sax,,,4,,,,,,,,,,,,,,,,,,,4,
javax.xml.transform.stream,,,2,,,,,,,,,,,,,,,,,,,2,
javax.xml.xpath,3,,,,,,,,,,,,,,,,,,3,,,,
jodd.json,,,10,,,,,,,,,,,,,,,,,,,,10
ognl,6,,,,,,,,,,,,6,,,,,,,,,,
org.apache.commons.codec,,,6,,,,,,,,,,,,,,,,,,,6,
org.apache.commons.collections,,,394,,,,,,,,,,,,,,,,,,,9,385
org.apache.commons.collections4,,,394,,,,,,,,,,,,,,,,,,,9,385
org.apache.commons.io,,,22,,,,,,,,,,,,,,,,,,,22,
org.apache.commons.jexl2,15,,,,,,,,15,,,,,,,,,,,,,,
org.apache.commons.jexl3,15,,,,,,,,15,,,,,,,,,,,,,,
org.apache.commons.lang3,,,423,,,,,,,,,,,,,,,,,,,292,131
org.apache.commons.ognl,6,,,,,,,,,,,,6,,,,,,,,,,
org.apache.commons.text,,,272,,,,,,,,,,,,,,,,,,,220,52
org.apache.directory.ldap.client.api,1,,,,,,,,,,1,,,,,,,,,,,,
org.apache.hc.core5.function,,,1,,,,,,,,,,,,,,,,,,,1,
org.apache.hc.core5.http,1,2,39,,,,,,,,,,,,,,,,,1,2,39,
org.apache.hc.core5.net,,,2,,,,,,,,,,,,,,,,,,,2,
org.apache.hc.core5.util,,,24,,,,,,,,,,,,,,,,,,,18,6
org.apache.http,27,3,70,,,,,,,,,,,25,,,,,,2,3,62,8
org.apache.ibatis.jdbc,6,,,,,,,,,,,,,,,6,,,,,,,
org.apache.shiro.jndi,1,,,,,,,,,1,,,,,,,,,,,,,
org.codehaus.groovy.control,1,,,,,1,,,,,,,,,,,,,,,,,
org.dom4j,20,,,,,,,,,,,,,,,,,,20,,,,
org.hibernate,7,,,,,,,,,,,,,,,7,,,,,,,
org.jooq,1,,,,,,,,,,,,,,,1,,,,,,,
org.json,,,236,,,,,,,,,,,,,,,,,,,198,38
org.mvel2,16,,,,,,,,,,,16,,,,,,,,,,,
org.springframework.beans,,,26,,,,,,,,,,,,,,,,,,,,26
org.springframework.cache,,,13,,,,,,,,,,,,,,,,,,,,13
org.springframework.http,14,,70,,,,,,,,,,,14,,,,,,,,60,10
org.springframework.jdbc.core,10,,,,,,,,,,,,,,,10,,,,,,,
org.springframework.jdbc.object,9,,,,,,,,,,,,,,,9,,,,,,,
org.springframework.jndi,1,,,,,,,,,1,,,,,,,,,,,,,
org.springframework.ldap,42,,,,,,,,,28,14,,,,,,,,,,,,
org.springframework.security.web.savedrequest,,6,,,,,,,,,,,,,,,,,,,6,,
org.springframework.ui,,,32,,,,,,,,,,,,,,,,,,,,32
org.springframework.util,,,139,,,,,,,,,,,,,,,,,,,87,52
org.springframework.validation,,,13,,,,,,,,,,,,,,,,,,,13,
org.springframework.web.client,13,3,,,,,,,,,,,,13,,,,,,,3,,
org.springframework.web.context.request,,8,,,,,,,,,,,,,,,,,,,8,,
org.springframework.web.multipart,,12,13,,,,,,,,,,,,,,,,,,12,13,
org.springframework.web.reactive.function.client,2,,,,,,,,,,,,,2,,,,,,,,,
org.springframework.web.util,,,163,,,,,,,,,,,,,,,,,,,138,25
org.xml.sax,,,1,,,,,,,,,,,,,,,,,,,1,
org.xmlpull.v1,,3,,,,,,,,,,,,,,,,,,,3,,
play.mvc,,4,,,,,,,,,,,,,,,,,,,4,,
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,27,4,,,,,,,,,,,,,8,,,,,,27,,4,
android.database,59,,30,,,,,,,,,,,,,59,,,,,,,,30,
android.net,,,60,,,,,,,,,,,,,,,,,,,,,45,15
android.util,,16,,,,,,,,,,,,,,,,,,,,,16,,
android.webkit,3,2,,,,,,,,,,,,,,,,,,,3,,2,,
com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,,,,,,,,,,,1,
com.esotericsoftware.kryo5.io,,,1,,,,,,,,,,,,,,,,,,,,,1,
com.fasterxml.jackson.core,,,1,,,,,,,,,,,,,,,,,,,,,1,
com.fasterxml.jackson.databind,,,5,,,,,,,,,,,,,,,,,,,,,5,
com.google.common.base,,,85,,,,,,,,,,,,,,,,,,,,,62,23
com.google.common.cache,,,17,,,,,,,,,,,,,,,,,,,,,,17
com.google.common.collect,,,553,,,,,,,,,,,,,,,,,,,,,2,551
com.google.common.io,6,,73,,,,,,,,,,,,,,6,,,,,,,72,1
com.opensymphony.xwork2.ognl,3,,,,,,,,,,,,3,,,,,,,,,,,,
com.unboundid.ldap.sdk,17,,,,,,,,,,17,,,,,,,,,,,,,,
flexjson,,,1,,,,,,,,,,,,,,,,,,,,,,1
groovy.lang,26,,,,,26,,,,,,,,,,,,,,,,,,,
groovy.util,5,,,,,5,,,,,,,,,,,,,,,,,,,
jakarta.faces.context,2,7,,,,,,,,,,,,,,,,,,,2,,7,,
jakarta.json,,,123,,,,,,,,,,,,,,,,,,,,,100,23
jakarta.ws.rs.client,1,,,,,,,,,,,,,1,,,,,,,,,,,
jakarta.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,9,,
jakarta.ws.rs.core,2,,149,,,,,,,,,,,,,,,2,,,,,,94,55
java.beans,,,1,,,,,,,,,,,,,,,,,,,,,1,
java.io,3,,27,,3,,,,,,,,,,,,,,,,,,,26,1
java.lang,,,50,,,,,,,,,,,,,,,,,,,,,41,9
java.net,10,3,7,,,,,,,,,,,10,,,,,,,,,3,7,
java.nio,10,,4,,10,,,,,,,,,,,,,,,,,,,4,
java.sql,7,,,,,,,,,,,,,,,7,,,,,,,,,
java.util,,,337,,,,,,,,,,,,,,,,,,,,,15,322
javax.faces.context,2,7,,,,,,,,,,,,,,,,,,,2,,7,,
javax.json,,,123,,,,,,,,,,,,,,,,,,,,,100,23
javax.management.remote,2,,,,,,,,,2,,,,,,,,,,,,,,,
javax.naming,7,,,,,,,,,6,1,,,,,,,,,,,,,,
javax.net.ssl,2,,,,,,,,,,,,,,2,,,,,,,,,,
javax.script,1,,,,,,,,,,,1,,,,,,,,,,,,,
javax.servlet,4,21,2,,,,3,1,,,,,,,,,,,,,,,21,2,
javax.validation,1,1,,1,,,,,,,,,,,,,,,,,,,1,,
javax.ws.rs.client,1,,,,,,,,,,,,,1,,,,,,,,,,,
javax.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,9,,
javax.ws.rs.core,3,,149,,,,1,,,,,,,,,,,2,,,,,,94,55
javax.xml.transform,1,,6,,,,,,,,,,,,,,,,,1,,,,6,
javax.xml.xpath,3,,,,,,,,,,,,,,,,,,3,,,,,,
jodd.json,,,10,,,,,,,,,,,,,,,,,,,,,,10
net.sf.saxon.s9api,5,,,,,,,,,,,,,,,,,,,5,,,,,
ognl,6,,,,,,,,,,,,6,,,,,,,,,,,,
org.apache.commons.codec,,,6,,,,,,,,,,,,,,,,,,,,,6,
org.apache.commons.collections,,,800,,,,,,,,,,,,,,,,,,,,,17,783
org.apache.commons.collections4,,,800,,,,,,,,,,,,,,,,,,,,,17,783
org.apache.commons.io,,,22,,,,,,,,,,,,,,,,,,,,,22,
org.apache.commons.jexl2,15,,,,,,,,15,,,,,,,,,,,,,,,,
org.apache.commons.jexl3,15,,,,,,,,15,,,,,,,,,,,,,,,,
org.apache.commons.lang3,,,423,,,,,,,,,,,,,,,,,,,,,292,131
org.apache.commons.ognl,6,,,,,,,,,,,,6,,,,,,,,,,,,
org.apache.commons.text,,,272,,,,,,,,,,,,,,,,,,,,,220,52
org.apache.directory.ldap.client.api,1,,,,,,,,,,1,,,,,,,,,,,,,,
org.apache.hc.core5.function,,,1,,,,,,,,,,,,,,,,,,,,,1,
org.apache.hc.core5.http,1,2,39,,,,,,,,,,,,,,,,,,1,,2,39,
org.apache.hc.core5.net,,,2,,,,,,,,,,,,,,,,,,,,,2,
org.apache.hc.core5.util,,,24,,,,,,,,,,,,,,,,,,,,,18,6
org.apache.http,27,3,70,,,,,,,,,,,25,,,,,,,2,,3,62,8
org.apache.ibatis.jdbc,6,,,,,,,,,,,,,,,6,,,,,,,,,
org.apache.shiro.jndi,1,,,,,,,,,1,,,,,,,,,,,,,,,
org.codehaus.groovy.control,1,,,,,1,,,,,,,,,,,,,,,,,,,
org.dom4j,20,,,,,,,,,,,,,,,,,,20,,,,,,
org.hibernate,7,,,,,,,,,,,,,,,7,,,,,,,,,
org.jooq,1,,,,,,,,,,,,,,,1,,,,,,,,,
org.json,,,236,,,,,,,,,,,,,,,,,,,,,198,38
org.mvel2,16,,,,,,,,,,,16,,,,,,,,,,,,,
org.springframework.beans,,,26,,,,,,,,,,,,,,,,,,,,,,26
org.springframework.cache,,,13,,,,,,,,,,,,,,,,,,,,,,13
org.springframework.http,14,,70,,,,,,,,,,,14,,,,,,,,,,60,10
org.springframework.jdbc.core,10,,,,,,,,,,,,,,,10,,,,,,,,,
org.springframework.jdbc.object,9,,,,,,,,,,,,,,,9,,,,,,,,,
org.springframework.jndi,1,,,,,,,,,1,,,,,,,,,,,,,,,
org.springframework.ldap,42,,,,,,,,,28,14,,,,,,,,,,,,,,
org.springframework.security.web.savedrequest,,6,,,,,,,,,,,,,,,,,,,,,6,,
org.springframework.ui,,,32,,,,,,,,,,,,,,,,,,,,,,32
org.springframework.util,,,139,,,,,,,,,,,,,,,,,,,,,87,52
org.springframework.validation,,,13,,,,,,,,,,,,,,,,,,,,,13,
org.springframework.web.client,13,3,,,,,,,,,,,,13,,,,,,,,,3,,
org.springframework.web.context.request,,8,,,,,,,,,,,,,,,,,,,,,8,,
org.springframework.web.multipart,,12,13,,,,,,,,,,,,,,,,,,,,12,13,
org.springframework.web.reactive.function.client,2,,,,,,,,,,,,,2,,,,,,,,,,,
org.springframework.web.util,,,163,,,,,,,,,,,,,,,,,,,,,138,25
org.xml.sax,,,1,,,,,,,,,,,,,,,,,,,,,1,
org.xmlpull.v1,,3,,,,,,,,,,,,,,,,,,,,,3,,
play.mvc,,4,,,,,,,,,,,,,,,,,,,,,4,,
1 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
2 android.content 8 27 4 8 27 4
3 android.database 59 30 59 30
4 android.net 60 45 15
5 android.util 16 16
6 android.webkit 3 2 3 2
7 com.esotericsoftware.kryo.io 1 1
8 com.esotericsoftware.kryo5.io 1 1
9 com.fasterxml.jackson.core 1 1
10 com.fasterxml.jackson.databind 5 5
11 com.google.common.base 85 62 23
12 com.google.common.cache 17 17
13 com.google.common.collect 553 2 551
14 com.google.common.io 6 73 6 72 1
15 com.opensymphony.xwork2.ognl 3 3
16 com.unboundid.ldap.sdk 17 17
17 flexjson 1 1
18 groovy.lang 26 26
19 groovy.util 5 5
20 jakarta.faces.context 2 7 2 7
21 jakarta.json 123 100 23
22 jakarta.ws.rs.client 1 1
23 jakarta.ws.rs.container 9 9
24 jakarta.ws.rs.core 2 149 2 94 55
25 java.beans 1 1
26 java.io 3 27 3 26 1
27 java.lang 47 50 41 6 9
28 java.net 10 3 7 10 3 7
29 java.nio 10 4 10 4
30 java.sql 7 7
31 java.util 337 15 322
32 javax.faces.context 2 7 2 7
33 javax.json 123 100 23
34 javax.management.remote 2 2
35 javax.naming 7 6 1
36 javax.net.ssl 2 2
37 javax.script 1 1
38 javax.servlet 4 21 2 3 1 21 2
39 javax.validation 1 1 1 1
40 javax.ws.rs.client 1 1
41 javax.ws.rs.container 9 9
42 javax.ws.rs.core 3 149 1 2 94 55
43 javax.xml.transform.sax javax.xml.transform 1 4 6 1 4 6
44 javax.xml.transform.stream javax.xml.xpath 3 2 3 2
45 javax.xml.xpath jodd.json 3 10 3 10
46 jodd.json net.sf.saxon.s9api 5 10 5 10
47 ognl 6 6
48 org.apache.commons.codec 6 6
49 org.apache.commons.collections 394 800 9 17 385 783
50 org.apache.commons.collections4 394 800 9 17 385 783
51 org.apache.commons.io 22 22
52 org.apache.commons.jexl2 15 15
53 org.apache.commons.jexl3 15 15
54 org.apache.commons.lang3 423 292 131
55 org.apache.commons.ognl 6 6
56 org.apache.commons.text 272 220 52
57 org.apache.directory.ldap.client.api 1 1
58 org.apache.hc.core5.function 1 1
59 org.apache.hc.core5.http 1 2 39 1 2 39
60 org.apache.hc.core5.net 2 2
61 org.apache.hc.core5.util 24 18 6
62 org.apache.http 27 3 70 25 2 3 62 8
63 org.apache.ibatis.jdbc 6 6
64 org.apache.shiro.jndi 1 1
65 org.codehaus.groovy.control 1 1
66 org.dom4j 20 20
67 org.hibernate 7 7
68 org.jooq 1 1
69 org.json 236 198 38
70 org.mvel2 16 16
71 org.springframework.beans 26 26
72 org.springframework.cache 13 13
73 org.springframework.http 14 70 14 60 10
74 org.springframework.jdbc.core 10 10
75 org.springframework.jdbc.object 9 9
76 org.springframework.jndi 1 1
77 org.springframework.ldap 42 28 14
78 org.springframework.security.web.savedrequest 6 6
79 org.springframework.ui 32 32
80 org.springframework.util 139 87 52
81 org.springframework.validation 13 13
82 org.springframework.web.client 13 3 13 3
83 org.springframework.web.context.request 8 8
84 org.springframework.web.multipart 12 13 12 13
85 org.springframework.web.reactive.function.client 2 2
86 org.springframework.web.util 163 138 25
87 org.xml.sax 1 1
88 org.xmlpull.v1 3 3
89 play.mvc 4 4

View File

@@ -7,17 +7,17 @@ Java framework & library support
:widths: auto
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE022` :sub:`Path injection`,`CWE036` :sub:`Path traversal`,`CWE079` :sub:`Cross-site scripting`,`CWE089` :sub:`SQL injection`,`CWE090` :sub:`LDAP injection`,`CWE094` :sub:`Code injection`,`CWE319` :sub:`Cleartext transmission`
Android,``android.*``,18,94,70,,,3,67,,,
`Apache Commons Collections <https://commons.apache.org/proper/commons-collections/>`_,"``org.apache.commons.collections``, ``org.apache.commons.collections4``",,788,,,,,,,,
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``",,1600,,,,,,,,
`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 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
`Google Guava <https://guava.dev/>`_,``com.google.common.*``,,728,6,,6,,,,,
`JSON-java <https://github.com/stleary/JSON-java>`_,``org.json``,,236,,,,,,,,
Java Standard Library,``java.*``,3,423,30,13,,,7,,,10
Java extensions,"``javax.*``, ``jakarta.*``",54,552,31,,,4,,1,1,2
Java Standard Library,``java.*``,3,426,30,13,,,7,,,10
Java extensions,"``javax.*``, ``jakarta.*``",54,552,32,,,4,,1,1,2
`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,,
Totals,,116,4169,402,13,6,10,107,33,1,66
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,,143,4984,408,13,6,10,107,33,1,66

View File

@@ -726,6 +726,9 @@ class StringLiteral extends Literal, @stringliteral {
*/
string getRepresentedString() { result = getValue() }
/** Holds if this string literal is a text block (`""" ... """`). */
predicate isTextBlock() { getLiteral().matches("\"\"\"%") }
override string getAPrimaryQlClass() { result = "StringLiteral" }
}

View File

@@ -110,6 +110,7 @@ private module Frameworks {
private import semmle.code.java.security.MvelInjection
private import semmle.code.java.security.OgnlInjection
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.SQLite
private import semmle.code.java.frameworks.Jdbc

View File

@@ -247,3 +247,20 @@ class ExportedAndroidIntentInput extends RemoteFlowSource, AndroidIntentInput {
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" }
}

View File

@@ -95,6 +95,9 @@ private class ContainerFlowSummaries extends SummaryModelCsv {
override predicate row(string 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;getValue;;;MapValue of Argument[-1];ReturnValue;value",
"java.util;Map$Entry;true;setValue;;;MapValue of Argument[-1];ReturnValue;value",

View File

@@ -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`. */
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) {
exists(FunctionalExpr func, FunctionalInterface interface |
exists(ClassInstanceExpr func, Interface t, FunctionalInterface interface |
creation.asExpr() = func and
func.asMethod() = c and
func.getType().(RefType).getSourceDeclaration() = interface and
kind = interface.getRunMethod()
func.getAnonymousClass().getAMethod() = c and
func.getConstructedType().extendsOrImplements+(t) and
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. */
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
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. */

View File

@@ -72,6 +72,14 @@ class AndroidContentProvider extends ExportableAndroidComponent {
AndroidContentProvider() {
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. */
@@ -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"
]
}
}

View File

@@ -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`.
*/
@@ -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;(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;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;;;Argument[1];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`.
*/
@@ -217,7 +792,7 @@ private class ApacheMapUtilsModel extends SummaryModelCsv {
";MapUtils;true;orderedMap;;;MapKey of Argument[0];MapKey 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;(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;;;MapValue of Argument[0];MapValue 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;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;;;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;;;MapValue of Argument[0];MapValue of ReturnValue;value"
";MultiMapUtils;true;unmodifiableMultiValuedMap;;;Element of MapValue of Argument[0];Element of MapValue of ReturnValue;value"
]
}
}

View File

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

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

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

View 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") }
}

View 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")
)
}
}

View File

@@ -79,6 +79,47 @@ class AndroidReceiverXmlElement extends AndroidComponentXmlElement {
*/
class AndroidProviderXmlElement extends AndroidComponentXmlElement {
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")
}
}
/**

View File

@@ -4,12 +4,12 @@
<qhelp>
<overview>
<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
let attacker to read arbitrary files from the filesystem or to execute arbitrary code.</p>
documents into other XML documents or other formats. Processing unvalidated XSLT stylesheets can
allow attackers to read arbitrary files from the filesystem or to execute arbitrary code.</p>
</overview>
<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>
</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>
<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>

View File

@@ -1,6 +1,6 @@
/**
* @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.
* @kind path-problem
* @problem.severity error
@@ -11,8 +11,7 @@
*/
import java
import semmle.code.java.dataflow.FlowSources
import XsltInjectionLib
import semmle.code.java.security.XsltInjectionQuery
import DataFlow::PathGraph
from DataFlow::PathNode source, DataFlow::PathNode sink, XsltInjectionFlowConfig conf

View File

@@ -4,7 +4,7 @@
<overview>
<p>
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.
If a SpEL expression is built using attacker-controlled data,
and then evaluated in a powerful context,
@@ -31,7 +31,7 @@ that doesn't allow arbitrary method invocation.
<example>
<p>
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>
<sample src="UnsafeSpelExpressionEvaluation.java" />
@@ -53,4 +53,4 @@ However, it's recommended to avoid using untrusted input in SpEL expressions.
<a href="https://owasp.org/www-community/vulnerabilities/Expression_Language_Injection">Expression Language Injection</a>.
</li>
</references>
</qhelp>
</qhelp>

View File

@@ -11,9 +11,10 @@
*/
import java
import SpelInjectionLib
import semmle.code.java.security.SpelInjectionQuery
import semmle.code.java.dataflow.DataFlow
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)
select sink.getNode(), source, sink, "SpEL injection from $@.", source.getNode(), "this user input"

View File

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

View File

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

View File

@@ -1,21 +1,6 @@
import java
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.
*/
@@ -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 {
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") }
}

View File

@@ -361,6 +361,12 @@ private predicate excludedMember(Member m) {
m.(Method).getDeclaringType() instanceof EnumType and
m.hasName(["values", "valueOf"]) and
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) {

View File

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

View File

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

View File

@@ -1 +0,0 @@
experimental/Security/CWE/CWE-074/XsltInjection.ql

View File

@@ -1 +0,0 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/Saxon-HE-9.9.1-7

View File

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

View File

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

View File

@@ -1 +0,0 @@
experimental/Security/CWE/CWE-094/SpelInjection.ql

View File

@@ -48,6 +48,8 @@ public class A {
return null;
}
public interface Producer1Consumer3<E> extends Producer1<E[]>, Consumer3<E[]> { }
static Object source(int i) { return null; }
static void sink(Object o) { }
@@ -71,7 +73,7 @@ public class A {
applyConsumer1(source(4), new Consumer1() {
@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(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
}
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/google-android-9.0.0

View File

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

View File

@@ -1,7 +1,4 @@
import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.ExternalFlow
import semmle.code.java.dataflow.TaintTracking
import TestUtilities.InlineFlowTest
class SummaryModelTest extends SummaryModelCsv {
@@ -9,8 +6,6 @@ class SummaryModelTest extends SummaryModelCsv {
row =
[
//"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;newRBWithMapKey;;;Argument[0];MapKey of ReturnValue;value"
]

View 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
}
}

View File

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

View File

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

View 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
}
}

View File

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