-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Fb jpms - fixes for illegal access to private information in java.* packages. #1328
base: master
Are you sure you want to change the base?
Conversation
this also fixes the Java9++ InaccessibleObjectException for some constellations at least
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.
Hi @struberg
I have a few comments scattered throughout.
src/main/java/org/apache/commons/lang3/builder/CompareToBuilder.java
Outdated
Show resolved
Hide resolved
src/main/java/org/apache/commons/lang3/builder/EqualsBuilder.java
Outdated
Show resolved
Hide resolved
src/main/java/org/apache/commons/lang3/builder/EqualsBuilder.java
Outdated
Show resolved
Hide resolved
src/main/java/org/apache/commons/lang3/builder/HashCodeBuilder.java
Outdated
Show resolved
Hide resolved
src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java
Outdated
Show resolved
Hide resolved
src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java
Outdated
Show resolved
Hide resolved
src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java
Show resolved
Hide resolved
src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java
Outdated
Show resolved
Hide resolved
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.
Hi @struberg
See my comments and @ppkarwasz's.
src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java
Outdated
Show resolved
Hide resolved
* add Character handling * move RefletionToSTringBuilder to unified handling
to make spotbugs happy
already is excluded via .gitignore exclusion it seems
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.
Hi @struberg
We cannot test that an object implements a stock interface like TemporalAccessor
or CharSequence
because this won't work with custom implementations (TemporalAmount
is also not accounted for, and others I am sure).
See the new test I added in git master: EqualsBuilderReflectJreImplementationTest
I think we can only test for an actual class or the the package that class lives in.
TY
Not every CharSequence might implement equals, not every TemporalAccessor might be a java.* class.
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.
Hello @struberg
Checking against an interface in isJavaInternalClass()
is not going to work.
I updated EqualsBuilderReflectJreImplementationTest
in git master.
Gary, this has already long been resolved in f20639a and ec4150b I've even merged your changes (and removed that new --add-opens again...) from main to this very branch. This branch clearly improves the situation with standard jpms setup for a lot of common cases. Of course, this does not yet fix ALL the problems (albeit it's a good start). But if people come across another |
Hello @struberg The issue is not that this PR is a wants to start improving something, the issue is that this PR breaks existing behavior. You cannot check for interfaces to short-circuit logic in The branch is not up to date with master. This fails:
|
Which of those is an interface? The thing you are talking about IS ALREADY RESOLVED since yesterday. And one other thing: commons-lang3 ReflectionToString ReflectionEquals etc was BROKEN on anything Java9++ - period! My spare time to work on this stuff is very limited - as is yours I bet. So please use our both time productively. As I said: not everything will fully work from the beginning. You just added |
Btw, I'm looking for another method name for Further down the road we need some way to tell whether a class is open or not. And all that in a way which also works on Java8 still... |
I guess you could be bothered to look it up? https://docs.oracle.com/javase/8/docs/api/java/time/temporal/Temporal.html |
Indeed, had in the back of my mind that Temporal is an abstract class. Thought about having a static |
* cache for known inaccessible classes * add documentation for that cache.
txs to @erans for the name suggestion!
point was valid in the past, but has already been resolved before the review
Float.class, | ||
Double.class, | ||
java.util.Date.class, | ||
java.sql.Date.class, |
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 is not specific to this PR: I don't think we should introduce a new JPMS module dependency, here on java.sql
. Lang does not use any classes from java.sql
so this would drag in a new JPMS module. For 4.0, we've mentioned dropping our dependency on java.desktop
and only depending on java.base
.
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.
yup true
f.setAccessible(true); | ||
} | ||
|
||
nonIntrospectibleClasses.put(clazz, false); |
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 looks problematic since the map will grow uncontrollably, possibly until every class on your classpath gets referenced, there's no way to know really.
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 is a trade-off vs performance. it will only cache those classes which got hit in a reflection equals, toString, etc. Thus in practice it is a very limited set of classes I'd say. Can you think of a possible place where we can hold such a cache at least during a single invocation? Maybe inside the builder and handing the Map as another parameter to this method?
} | ||
|
||
/** | ||
* Check whether the given class internas can be accessed. This might return false in Java9 |
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.
"internas" spelling
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.
Hi All,
So far, I'm still against this change.
These features are designed to use reflection, and this PR tries to turn some of that off.
It seems to me like it will cause unintended consequences beyond all of the ones I pointed out through the new unit tests I wrote which showed the initial implementation would break existing apps.
Now, we have a different implementation, which brings in a new set of problems:
- It depends on a new JPMS module
java.sql
- it grows a map without any bounds (a CVE waiting to happen IMO)
- you can't turn it off
- The behavior is completely hidden from the user
I agree. All the
The warning might require an update, but it seems clear to me that it also applies to the JPMS access checks. So it is up to caller to ensure that the class is open to |
why is this disussion again NOT happening on any ASF list but here where it does not get reflected to any ASF list afaict? |
This discussion is mirrored on the apache list here: |
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.
Note that this PR is worse than I thought because we already have a feature to bypass reflection! Use EqualsBuilder.setBypassReflectionClasses(List<Class<?>>)
.
further comments over at the commons dev list. |
Are you sure that you really understand that code? If you would setBypassReflectionClasses(ArrayList.class) or HashSet.class or HashMap.class etc, then you would totally break the EqualsBuilder. Because this would also stop looking down into the equality of the elements contained in that List/Set/Map. Funnily you yourself did add hand-tinkered bypasses for those classes in selected places - just not for every use case. So you yourself added code to NOT use reflection for some of the cases. So this rather sounds like a strawman argument to me. |
Well this is way more subtly weird right now. Imagine the following code:
Here we have the case that But that means that right now the EqualsBuilder (even in Java8) does not even adheres to the contract of the Map interface. But those internal details should not matter! Even if I would not have set an initial size - what if I add 30 elements to one of the 2 maps, but then remove everything but the "A" entry again? It will be equals according to the Map contract, but not for the EqualsBuilder. Looks rather broken to me. One might argue that that's exactly how all the reflection stuff in commons-lang was designed from the beginning. |
This is just plain wrong. You cannot use |
Because the reason given is just plain wrong. See my last 2 comments. Either we adhere the Map, Collection, etc equals contracts (as indicated in the JavaDoc of the ReflectionEquals and others commons lang classes) then we need this handling. Or not, then we need to to remove all the references to Effective Java etc. But right now we have rather broken behaviour
please review and give feedback. Can push it later myself or you just apply it - txs!