-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Java: Add support for Apache Commons Lang StringUtils #5126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Java: Add support for Apache Commons Lang StringUtils #5126
Conversation
} | ||
|
||
override predicate returnsTaintFrom(int arg) { | ||
arg = [0 .. getNumberOfParameters()] and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
arg = [0 .. getNumberOfParameters()] and | |
arg = [0 .. getNumberOfParameters() - 1] and |
Not sure if this makes a difference, but since the index is 0-based, 1 has to be subtracted from the number of parameters.
private Type getAnExcludedParameterType() { | ||
result instanceof PrimitiveType or | ||
result.(RefType).hasQualifiedName("java.nio.charset", "Charset") or | ||
result.(RefType).hasQualifiedName("java.util", "Locale") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we also want to exclude the primitive array types (besides char[]
) in the join
methods?
bindingset[arg, methodName] | ||
private predicate isExcludedParameter(string methodName, int arg) { | ||
methodName.matches(["appendIfMissing%", "prependIfMissing%"]) and arg = [2, 3] | ||
or | ||
methodName.matches(["remove%", "split%", "substring%", "strip%"]) and arg != 0 | ||
or | ||
methodName.matches(["chomp", "getBytes", "replace%", "toString", "unwrap"]) and arg = 1 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This predicate and getAnExcludedParameterType
don't depend on this
. Would it be better to make them top-level predicates?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, no need to make a spurious cartesian product like this (although the optimiser is likely able to fix this problem). Definitely make getAnExcludedParameterType
top-level. As for this one, you could instead change methodName
to this.getName()
, that would also remove the need for bindingset
.
void test() throws Exception { | ||
|
||
// All these calls should convey taint to `sink` except as noted. | ||
sink(StringUtils.abbreviate(taint(), 0)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These sort of data flow tests quickly become unwieldy - perhaps it's time to slowly start using the inline test expectation library?
247f098
to
1b80a97
Compare
@aschackmull @joefarebrother all suggestions applied, including writing the binding for inline-expectations vs. Java. |
( | ||
this.getName().matches(["appendIfMissing%", "prependIfMissing%"]) and arg = [2, 3] | ||
or | ||
this.getName().matches(["remove%", "split%", "substring%", "strip%"]) and arg != 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we replace arg != 0
with arg = [1 .. getNumberOfParameters() - 1]
then we don't need the first line of this predicate since then arg
will be bound in all the disjuncts.
The inline expectations library copy should be added in |
SafeJoinArrayType() { getName().regexpMatch("byte|double|float|int|long|short") } | ||
} | ||
|
||
private class ApacheStringUtilsTaintPreservingMethod extends TaintPreservingCallable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of this might fit nicer in java/ql/src/semmle/code/java/frameworks/apache/Lang.qll
. See also #5134
1b80a97
to
985766d
Compare
@aschackmull all changes applied |
5fea772
to
ae83a93
Compare
@aschackmull changes applied except as noted |
private class SafeJoinArrayType extends PrimitiveType { | ||
SafeJoinArrayType() { getName().regexpMatch("byte|double|float|int|long|short") } | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private class SafeJoinArrayType extends PrimitiveType { | |
SafeJoinArrayType() { getName().regexpMatch("byte|double|float|int|long|short") } | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doh. Mind approving so I can merge once this is done?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't approve just yet, as there are still changes I expect (and any push will remove approval). Also, could you please keep the review fixes in their own commits? Force-pushes make review difficult. (Force-pushing when rebasing is fine, though).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK will do in future. This change is pushed already.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Protip btw, you can click the words "force-pushed" to see the diff before vs. after the push
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know, but in my experience that doesn't always work very well. It seems like what you get is somewhat ill-defined and a best-effort approach at most.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
E.g. clicking on the second-to-last "force-pushed" shows me several unrelated changes, possibly related to a rebase, but if that's then mixed with actual changes then those parts are very hard to separate.
ae83a93
to
9a667dc
Compare
f58220f
to
a2eeffa
Compare
No description provided.