Skip to content

Conversation

@rombirli
Copy link
Contributor

No description provided.

@hashicorp-vault-sonar-prod
Copy link

hashicorp-vault-sonar-prod bot commented Dec 23, 2025

SONARXML-221

@sonarqube-next
Copy link

@rombirli rombirli requested a review from a team December 23, 2025 13:28
@github-actions
Copy link
Contributor

This PR is stale because it has been open 7 days with no activity. If there is no activity in the next 7 days it will be closed automatically

@github-actions github-actions bot added the stale label Dec 31, 2025
@GabrielFleischer GabrielFleischer self-requested a review January 5, 2026 12:49
Copy link
Contributor

Choose a reason for hiding this comment

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

This solution looks pretty solid. I think there are a couple of things we could do to get to the extra mile:

  1. Cover removeAll like we cover remove
  2. Rename the new test and new utility methods in the check

@GabrielFleischer GabrielFleischer removed their request for review January 5, 2026 12:50
Copy link
Contributor

Choose a reason for hiding this comment

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

The approach looks good but there are a couple of things we need to fix before we can merge.


// finding if any child contains tools:node="removeAll" can be costly if there are many uses-permission nodes
// so we cache the result for each parent node
private final Map<Node, Boolean> removeAllPropertyCache = new HashMap<>();

Choose a reason for hiding this comment

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

AFAIK, we create one instance of check per (module) analysis. This means that this cache is likely to grow with every new file we explore. In addition to the growth in terms of memory, we are likely to void any potential for garbage collection as the nodes are objects within potentially large graphs.
I think we need to do 1 of 2 things:

  1. We decide to keep track of all nodes across the project and replace the key type of the map with a cache and memory-friendlier type
  2. We decide to keep track of all nodes within the file only and reset the map on every call to scanAndroidManifest / scanFile

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As this cache is not static, shouldn't the gc collect it once scanning the module is done ?

However I can still optimize it : I propose the cache to be just an Optional :

  • None : didnt search removeAll in children yet
  • Some(false) : No uses-permission node contains removeAll
  • Some(true) : A uses-permission node contains removeAll

Choose a reason for hiding this comment

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

As this cache is not static, shouldn't the gc collect it once scanning the module is done ?

It should, but keeping things in memory when they no longer serve any purpose (ie: we moved to another file and can no longer encounter the same parent) we might as well clear the cache as we enter a new file.

Comment on lines 129 to 130
if (!hasToolsNodeRemove(node)
&& !hasParentToolsNodeRemoveAll(node)

Choose a reason for hiding this comment

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

Disclaimer: not sure about everything below but I feel like we could avoid doubling the work here.

Since the introduction of removeAll means that we have to look at all <uses-permission> nodes in the parent, and the parent can only be the manifest as far as I understand, we might as well change the approach here.

Could we consider an other approach where we:

  1. Build a list of <uses-permission> nodes as an initial candidate list
  2. Group the candidates by android:name attribute
  3. For each group, loop through the candidates
    a. if a candidate has tools:node="removeAll" as an attribute, remove the group from the candidates, continue to the next group
    b. if a candidate has tools:node="remove" as an attribute, remove from the list of candidates and continue to the next candidate
  4. Report on the remaining candidates

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If I understand correctly your approach, a tools:node="removeAll" removes all emenent with tag:uses-permission AND same name, but I understand the documentation differently, for what i understood, the name is not checked, and elements with same tag in same parent are removed

Choose a reason for hiding this comment

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

Indeed, the logic in the documentation seems to be that all tags of the same type will be dropped from the merged manifest, and we might able to simplify the logic I proposed by skipping the grouping at step 2 and exiting altogether at step 3a if we encounter removeAll.

@github-actions github-actions bot removed the stale label Jan 6, 2026
@rombirli
Copy link
Contributor Author

rombirli commented Jan 6, 2026

I finally managed to completely get rid of the cache, and applied the few refactoring recommendations

Copy link
Contributor

Choose a reason for hiding this comment

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

Thank you for the changes, we are almost there and should be getting there soon.

 - remove @nullable decorator on node argument
 - invert return type, change name accordingly
 - takes uses-permission nodes list instead of manifest node as argument
Copy link
Contributor

Choose a reason for hiding this comment

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

Great job on this one! The checks looks a lot more approachable with this version.

.map(nodeList::item)
.filter(childNode -> "uses-permission".equals(childNode.getNodeName()))
.noneMatch(childNode -> hasToolsNodeValue(childNode, "removeAll"));
private boolean hasToolsNodeRemoveAll(List<Node> permissionNodes) {

Choose a reason for hiding this comment

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

Let's mark this method as static since it does not depend on the check's state

@sonarqube-next
Copy link

sonarqube-next bot commented Jan 7, 2026

@rombirli rombirli merged commit e29d923 into master Jan 7, 2026
8 checks passed
@rombirli rombirli deleted the rombirli/SONARXML-221-dont-raise-on-node-remove branch January 7, 2026 15:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants