Skip to content

Java: Support for With[out]Element for MaD. #13546

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
Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,8 @@ The following components are supported:
- **SyntheticGlobal[**\ `name`\ **]** selects the synthetic global with name `name`.
- **ArrayElement** selects the elements of an array.
- **Element** selects the elements of a collection-like container.
- **WithoutElement** selects a collection-like container without its elements. This is for input only.
- **WithElement** selects the elements of a collection-like container, but points to the container itself. This is for input only.
- **MapKey** selects the element keys of a map.
- **MapValue** selects the element values of a map.

Expand Down
4 changes: 4 additions & 0 deletions java/ql/lib/change-notes/2023-08-04-mad-withoutelement.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Add support for `WithElement` and `WithoutElement` for MaD access paths.
6 changes: 3 additions & 3 deletions java/ql/lib/ext/java.util.model.yml
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ extensions:
- ["java.util", "LinkedHashSet", False, "LinkedHashSet", "(Collection)", "", "Argument[0].Element", "Argument[this].Element", "value", "manual"]
- ["java.util", "LinkedList", False, "LinkedList", "(Collection)", "", "Argument[0].Element", "Argument[this].Element", "value", "manual"]
- ["java.util", "List", True, "add", "(int,Object)", "", "Argument[1]", "Argument[this].Element", "value", "manual"]
- ["java.util", "List", True, "addAll", "(int,Collection)", "", "Argument[1].Element", "Argument[this].Element", "value", "manual"]
- ["java.util", "List", True, "addAll", "(int,Collection)", "", "Argument[1].WithElement", "Argument[this]", "value", "manual"]
- ["java.util", "List", True, "clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"]
- ["java.util", "List", False, "copyOf", "(Collection)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["java.util", "List", True, "get", "(int)", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["java.util", "List", True, "listIterator", "", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
Expand Down Expand Up @@ -313,6 +314,7 @@ extensions:
- ["java.util", "Scanner", True, "useLocale", "", "", "Argument[this]", "ReturnValue", "value", "manual"]
- ["java.util", "Scanner", True, "useRadix", "", "", "Argument[this]", "ReturnValue", "value", "manual"]
- ["java.util", "Set", False, "copyOf", "(Collection)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["java.util", "Set", False, "clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"]
- ["java.util", "Set", False, "of", "(Object)", "", "Argument[0]", "ReturnValue.Element", "value", "manual"]
- ["java.util", "Set", False, "of", "(Object,Object)", "", "Argument[0..1]", "ReturnValue.Element", "value", "manual"]
- ["java.util", "Set", False, "of", "(Object,Object,Object)", "", "Argument[0..2]", "ReturnValue.Element", "value", "manual"]
Expand Down Expand Up @@ -424,10 +426,8 @@ extensions:
# When `WithoutElement` is implemented, these should be changed to summary models of the form `Argument[this].WithoutElement -> Argument[this]`.
- ["java.util", "Collection", "removeIf", "(Predicate)", "summary", "manual"]
- ["java.util", "Iterator", "remove", "()", "summary", "manual"]
- ["java.util", "List", "clear", "()", "summary", "manual"]
- ["java.util", "List", "remove", "(Object)", "summary", "manual"]
- ["java.util", "Map", "clear", "()", "summary", "manual"]
- ["java.util", "Set", "clear", "()", "summary", "manual"]
- ["java.util", "Set", "remove", "(Object)", "summary", "manual"]
- ["java.util", "Set", "removeAll", "(Collection)", "summary", "manual"]

Expand Down
16 changes: 12 additions & 4 deletions java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,25 @@
* or method, or a parameter.
* 7. The `input` column specifies how data enters the element selected by the
* first 6 columns, and the `output` column specifies how data leaves the
* element selected by the first 6 columns. An `input` can be either "",
* "Argument[n]", "Argument[n1..n2]", "ReturnValue":
* element selected by the first 6 columns. An `input` can be a dot separated
* path consisting of either "", "Argument[n]", "Argument[n1..n2]",
* "ReturnValue", "Element", "WithoutElement", or "WithElement":
* - "": Selects a write to the selected element in case this is a field.
* - "Argument[n]": Selects an argument in a call to the selected element.
* The arguments are zero-indexed, and `this` specifies the qualifier.
* - "Argument[n1..n2]": Similar to "Argument[n]" but select any argument in
* the given range. The range is inclusive at both ends.
* - "ReturnValue": Selects a value being returned by the selected element.
* This requires that the selected element is a method with a body.
* - "Element": Selects the collection elements of the selected element.
* - "WithoutElement": Selects the selected element but without
* its collection elements.
* - "WithElement": Selects the collection elements of the selected element, but
* points to the selected element.
*
* An `output` can be either "", "Argument[n]", "Argument[n1..n2]", "Parameter",
* "Parameter[n]", "Parameter[n1..n2]", or "ReturnValue":
* An `output` can be can be a dot separated path consisting of either "",
* "Argument[n]", "Argument[n1..n2]", "Parameter", "Parameter[n]",
* "Parameter[n1..n2]", "ReturnValue", or "Element":
* - "": Selects a read of a selected field, or a selected parameter.
* - "Argument[n]": Selects the post-update value of an argument in a call to the
* selected element. That is, the value of the argument after the call returns.
Expand All @@ -61,6 +68,7 @@
* - "Parameter[n1..n2]": Similar to "Parameter[n]" but selects any parameter
* in the given range. The range is inclusive at both ends.
* - "ReturnValue": Selects the return value of a call to the selected element.
* - "Element": Selects the collection elements of the selected element.
* 8. The `kind` column is a tag that can be referenced from QL to determine to
* which classes the interpreted elements should be added. For example, for
* sources "remote" indicates a default remote flow source, and for summaries
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,10 @@ predicate neutralSummaryElement(SummarizedCallableBase c, string provenance) {
bindingset[c]
SummaryComponent interpretComponentSpecific(AccessPathToken c) {
exists(Content content | parseContent(c, content) and result = SummaryComponent::content(content))
or
c = "WithoutElement" and result = SummaryComponent::withoutContent(any(CollectionContent cc))
or
c = "WithElement" and result = SummaryComponent::withContent(any(CollectionContent cc))
}

/** Gets the summary component for specification component `c`, if any. */
Expand All @@ -196,6 +200,10 @@ private string getContentSpecific(Content c) {
/** Gets the textual representation of the content in the format used for MaD models. */
string getMadRepresentationSpecific(SummaryComponent sc) {
exists(Content c | sc = TContentSummaryComponent(c) and result = getContentSpecific(c))
or
sc = TWithoutContentSummaryComponent(_) and result = "WithoutElement"
or
sc = TWithContentSummaryComponent(_) and result = "WithElement"
}

bindingset[pos]
Expand Down
Loading