Skip to content

Commit 5188ad1

Browse files
authored
Merge pull request #5126 from smowton/smowton/feature/commons-stringutils
Java: Add support for Apache Commons Lang StringUtils
2 parents 8db234f + a2eeffa commit 5188ad1

File tree

10 files changed

+1685
-0
lines changed

10 files changed

+1685
-0
lines changed

config/identical-files.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@
356356
],
357357
"Inline Test Expectations": [
358358
"cpp/ql/test/TestUtilities/InlineExpectationsTest.qll",
359+
"java/ql/test/TestUtilities/InlineExpectationsTest.qll",
359360
"python/ql/test/TestUtilities/InlineExpectationsTest.qll"
360361
],
361362
"C++ ExternalAPIs": [
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lgtm,codescanning
2+
* Added support for the Apache Commons Lang StringUtils library.

java/ql/src/semmle/code/java/frameworks/apache/Lang.qll

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,58 @@ private class ApacheLangArrayUtilsTaintPreservingMethod extends TaintPreservingC
6363
src = [0, 2]
6464
}
6565
}
66+
67+
private Type getAnExcludedParameterType() {
68+
result instanceof PrimitiveType or
69+
result.(RefType).hasQualifiedName("java.nio.charset", "Charset") or
70+
result.(RefType).hasQualifiedName("java.util", "Locale")
71+
}
72+
73+
private class ApacheStringUtilsTaintPreservingMethod extends TaintPreservingCallable {
74+
ApacheStringUtilsTaintPreservingMethod() {
75+
this.getDeclaringType().hasQualifiedName("org.apache.commons.lang3", "StringUtils") and
76+
this.hasName([
77+
"abbreviate", "abbreviateMiddle", "appendIfMissing", "appendIfMissingIgnoreCase",
78+
"capitalize", "center", "chomp", "chop", "defaultIfBlank", "defaultIfEmpty",
79+
"defaultString", "deleteWhitespace", "difference", "firstNonBlank", "firstNonEmpty",
80+
"getBytes", "getCommonPrefix", "getDigits", "getIfBlank", "getIfEmpty", "join", "joinWith",
81+
"left", "leftPad", "lowerCase", "mid", "normalizeSpace", "overlay", "prependIfMissing",
82+
"prependIfMissingIgnoreCase", "remove", "removeAll", "removeEnd", "removeEndIgnoreCase",
83+
"removeFirst", "removeIgnoreCase", "removePattern", "removeStart", "removeStartIgnoreCase",
84+
"repeat", "replace", "replaceAll", "replaceChars", "replaceEach", "replaceEachRepeatedly",
85+
"replaceFirst", "replaceIgnoreCase", "replaceOnce", "replaceOnceIgnoreCase",
86+
"replacePattern", "reverse", "reverseDelimited", "right", "rightPad", "rotate", "split",
87+
"splitByCharacterType", "splitByCharacterTypeCamelCase", "splitByWholeSeparator",
88+
"splitByWholeSeparatorPreserveAllTokens", "splitPreserveAllTokens", "strip", "stripAccents",
89+
"stripAll", "stripEnd", "stripStart", "stripToEmpty", "stripToNull", "substring",
90+
"substringAfter", "substringAfterLast", "substringBefore", "substringBeforeLast",
91+
"substringBetween", "substringsBetween", "swapCase", "toCodePoints", "toEncodedString",
92+
"toRootLowerCase", "toRootUpperCase", "toString", "trim", "trimToEmpty", "trimToNull",
93+
"truncate", "uncapitalize", "unwrap", "upperCase", "valueOf", "wrap", "wrapIfMissing"
94+
])
95+
}
96+
97+
private predicate isExcludedParameter(int arg) {
98+
this.getName().matches(["appendIfMissing%", "prependIfMissing%"]) and arg = [2, 3]
99+
or
100+
this.getName().matches(["remove%", "split%", "substring%", "strip%"]) and
101+
arg = [1 .. getNumberOfParameters() - 1]
102+
or
103+
this.getName().matches(["chomp", "getBytes", "replace%", "toString", "unwrap"]) and arg = 1
104+
or
105+
this.getName() = "join" and
106+
// Exclude joins of types that render numerically (char[] and non-primitive arrays
107+
// are still considered taint sources)
108+
exists(PrimitiveType pt |
109+
this.getParameterType(arg).(Array).getComponentType() = pt and
110+
not pt instanceof CharacterType
111+
) and
112+
arg = 0
113+
}
114+
115+
override predicate returnsTaintFrom(int arg) {
116+
arg = [0 .. getNumberOfParameters() - 1] and
117+
not this.getParameterType(arg) = getAnExcludedParameterType() and
118+
not isExcludedParameter(arg)
119+
}
120+
}

0 commit comments

Comments
 (0)