Skip to content

Add models for Apache Commons Lang's tuple types #5772

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

Merged
merged 9 commits into from
Jun 18, 2021

Conversation

smowton
Copy link
Contributor

@smowton smowton commented Apr 26, 2021

This also adds support for (fully-qualified) fields.

My approach here is to keep the models to the concrete types (Im)?mutable(Pair|Triple), relying on virtual dispatch to determine what happens to calls against the interfaces Pair and Triple. This can fail when neither type is referred to explicitly and tuples are provided by external code already constructed, however I don't add the synthetic field needed for this case in this PR.

@smowton smowton requested a review from a team as a code owner April 26, 2021 14:42
@github-actions github-actions bot added the Java label Apr 26, 2021
Copy link
Contributor

@hvitved hvitved left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice! Did you forget to check in the test .ql and .expected files?

private SummaryComponent interpretComponent(string c) {
specSplit(_, c, _) and
(
exists(int pos | parseArg(c, pos) and result = SummaryComponent::argument(pos))
or
exists(int pos | parseParam(c, pos) and result = SummaryComponent::parameter(pos))
or
c.matches("Field%") and result = SummaryComponent::field(interpretField(c.splitAt(" ", 1)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Field %"?

@@ -137,10 +137,10 @@ class MapValueContent extends Content, TMapValueContent {
* Thus, `node2` references an object with a field `f` that contains the
* value of `node1`.
*/
predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
predicate storeStep(Node node1, Content f, Node node2) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just verifying that this change is expected.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, because we now have storeSteps pointed at synthetic nodes that don't have PUNs (perhaps they should?)

@smowton
Copy link
Contributor Author

smowton commented Apr 27, 2021

No files are forgotten; the flow.ql and empty .expected (for an inline-expectation test) are already present in the commons-lang3 directory.

Copy link
Contributor

@Marcono1234 Marcono1234 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the public constructors are not modeled, is that on purpose?

Comment on lines 656 to 657
"org.apache.commons.lang3.tuple;ImmutablePair;false;right;;;Argument[0];Field org.apache.commons.lang3.tuple.ImmutablePair.right of ReturnValue;value",
"org.apache.commons.lang3.tuple;ImmutablePair;false;left;;;Argument[0];Field org.apache.commons.lang3.tuple.ImmutablePair.left of ReturnValue;value",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really minor, but is it intended that here "right" is listed before "left"? In all other cases it seems to be the other way around.


void sink(Object o) {}

void test() throws Exception {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be missing a test for Triple.of(left, middle, right)
Might be good to add it for completeness?


void sink(Object o) {}

void test() throws Exception {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be missing a test for Pair.of(left, right)
Might be good to add it for completeness?

@smowton
Copy link
Contributor Author

smowton commented May 11, 2021

@Marcono1234 thanks, done

Comment on lines 682 to 692
bindingset[name]
private Field interpretField(string name) {
exists(string splitRegex, string package, string className, string fieldName |
splitRegex = "^(.*)\\.([^.]+)\\.([^.]+)$" and
package = name.regexpCapture(splitRegex, 1) and
className = name.regexpCapture(splitRegex, 2) and
fieldName = name.regexpCapture(splitRegex, 3)
|
result = any(Field f | f.hasQualifiedName(package, className, fieldName))
)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of having a bindingset-annotated predicate, I'd prefer to match the style of parseArg and parseParam.

Suggested change
bindingset[name]
private Field interpretField(string name) {
exists(string splitRegex, string package, string className, string fieldName |
splitRegex = "^(.*)\\.([^.]+)\\.([^.]+)$" and
package = name.regexpCapture(splitRegex, 1) and
className = name.regexpCapture(splitRegex, 2) and
fieldName = name.regexpCapture(splitRegex, 3)
|
result = any(Field f | f.hasQualifiedName(package, className, fieldName))
)
}
private predicate parseField(string c, Field f) {
specSplit(_, c, _) and
exists(string splitRegex, string package, string className, string fieldName |
fieldRegex = "^Field (.*)\\.([^.]+)\\.([^.]+)$" and
package = c.regexpCapture(fieldRegex, 1) and
className = c.regexpCapture(fieldRegex, 2) and
fieldName = c.regexpCapture(fieldRegex, 3) and
f.hasQualifiedName(package, className, fieldName)
)
}

@smowton smowton force-pushed the smowton/feature/apache-tuple-flow branch from d91a3e9 to d28c95d Compare June 17, 2021 11:49
@smowton
Copy link
Contributor Author

smowton commented Jun 17, 2021

@aschackmull done, and style changed from Field foo of to Field[foo] of

@aschackmull
Copy link
Contributor

I've got a feeling that the tests in java/ql/test/library-tests/dataflow/external-models/ might fail...

@smowton
Copy link
Contributor Author

smowton commented Jun 17, 2021

Nope, those tests seem fine. I don't immediately see what trouble you would expect.

@aschackmull
Copy link
Contributor

I was thinking of query predicate invalidModelRow.

@smowton
Copy link
Contributor Author

smowton commented Jun 17, 2021

I think that's fine because it defers to invalidSpecComponent which in turn uses not exists(interpretComponent(c)), so there is no longer a need to double-specify valid formats as of 14f9a5c which deleted the line part.regexpMatch("|ReturnValue|ArrayElement|Element|MapKey|MapValue")

@aschackmull
Copy link
Contributor

Ah, perfect!

@aschackmull aschackmull merged commit 7eb6da3 into github:main Jun 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants