Skip to content
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

Returning view of method list to avoid CME #1953

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from

Conversation

CirQ
Copy link
Contributor

@CirQ CirQ commented Feb 27, 2023

The modified method getMethodsByNameAndParamCount is used (and only used) in the FastHierarchy.getSignaturePolymorphicMethod for resolving polymorphic methods. The for-loop will return the method list's iterator, but the list itself can be modified by another body pack transform thread, causing a ConcurrentModificationException. The patch fix the issue by returning a copy of this list.

This patch also fixes the issue #1811 , and a similar issue is #1199 (fixed by #1886 ).

The modified method `getMethodsByNameAndParamCount` is used (and only used) in the `FastHierarchy.getSignaturePolymorphicMethod` for resolving polymorphic methods. The for-loop will return the method list's iterator, but the list itself can be modified by another body pack transform thread, causing a `ConcurrentModificationException`. The patch fix the issue by returning a copy of this list.

This patch also fixes the issue soot-oss#1811 , and a similar issue is soot-oss#1199 (fixed by soot-oss#1886 ).
@StevenArzt
Copy link
Contributor

StevenArzt commented Feb 27, 2023

The proposed fix for the multi-threading problem doesn't resolve the root cause. The copy constructor of the lists iterates over the base collection and adds each element. Your fix reduces the time during which a concurrent modification can occur to the time of copying the list. That's for sure muchsorter than the runtime of the transformer itself, but if you're unlucky, you can still hit a ConcurrentModificationException if the list is modified while the copy constructor is running.

I am slightly reluctant to accept an incomplete fix that - on the other hand - migth cost us some performance because the FastHierarchy is called many times.

@CirQ
Copy link
Contributor Author

CirQ commented Feb 27, 2023

The proposed fix for the multi-threading problem doesn't resolve the root cause. The copy constructor of the lists iterates over the base collection and adds each element. Your fix reduces the time during which a concurrent modification can occur to the time of copying the list. That's for sure muchsorter than the runtime of the transformer itself, but if you're unlucky, you can still hit a ConcurrentModificationException if the list is modified while the copy constructor is running.

I am slightly reluctant to accept an incomplete fix that - on the other hand - migth cost us some performance because the FastHierarchy is called many times.

I see. I encountered this issue in an Android analysis project, while in the experiment, a large amount of apks fail due to CME at that site. This patch works fine for these apks.

Anyway, is there any better solution? I found the list itself is a wrapped synchronized collection (https://github.com/soot-oss/soot/blob/develop/src/main/java/soot/SootClass.java#L680), while the iterator returned by this wrapper does not guarantee thread-safety. JDK officially requires synchronization on the iterating site (https://stackoverflow.com/a/1775738). Will this solution be better? If so, I will create a new PR for that.

@StevenArzt
Copy link
Contributor

We should first understand why one thread is searching for a method in a class in which another thread is still creating methods. Let's assume the thread that queries the FastHierarchy runs first. In that case, we don't find the method, because the second threat hasn't created it yet. Let's assume the other way round: We get the method, because the other thread happened to be faster. Does this mean that our results are dependent on thread scheduling, i.e., luck?

My guess would be that we're dealing with phantom methods which are created when resolving a method reference to a callee that doesn't exist. If that is correct, the FastHierarchy would return cast-incompatibility anyway.

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.

2 participants