WIP: Fix Class.getMethod() to reject non-public interface methods#23384
WIP: Fix Class.getMethod() to reject non-public interface methods#23384tomal-majumder wants to merge 1 commit intoeclipse-openj9:masterfrom
Conversation
bc81b56 to
a9b77e9
Compare
There was a problem hiding this comment.
The proposed fix may not be the best way to address the reported failure.
Can you try the following fix? The comment above (in line 2057) indicates that no public method was found, which results in a null return value. The private interface method is therefore being correctly filtered. However, directly returning null here ignores the throwException input parameter, which is set to true in the case of Class.getMethod.
| return throwExceptionOrReturnNull(throwException, name, parameterTypes); |
There was a problem hiding this comment.
Yes, this block does correctly filter out private interface methods. I tested the suggested change, and it produces the expected java.lang.NoSuchMethodException when a private interface method is requested via Class.getMethod().
My initial approach was to enforce the visibility constraint earlier by filtering out the private method returned by getDeclaredMethodImpl().
There was a problem hiding this comment.
The initial approach is incomplete because it only filters out non-public methods in the this.isInterface() branch, but does not address the root contract violation in getMethodHelper.
Class.getMethod() must either return a public method or throw NoSuchMethodException. Currently, getMethodHelper can still return null in the initialResultShouldBeReplaced path, even when throwException == true. Your change does not modify that logic.
As a result:
- it fixes the specific interface path scenario,
- but it does not guarantee that
getMethod()will always throw instead of returning null in all non-public cases, and - it does not cover non-interface code paths that may hit the same logic.
We are also missing test coverage. Please also add Java test cases covering these scenarios to ensure the contract is enforced consistently across both interface and non-interface paths.
|
Also, the commit guidelines are not followed: https://github.com/eclipse-openj9/openj9/blob/master/CONTRIBUTING.md#commit-guidelines -> |
d323ab2 to
39ac334
Compare
| if (initialResultShouldBeReplaced) { | ||
| // The initial result is not a public method to be searched, and no other public methods found. | ||
| return null; | ||
| return throwExceptionOrReturnNull(throwException, name, parameterTypes); |
There was a problem hiding this comment.
@babsingh Added tests for Class.getMethod() on private interface methods (static and non-static), which are the only cases that reach this path. Other scenarios involving superinterfaces or implementing classes are handled and rejected earlier in the method.
| @@ -0,0 +1,34 @@ | |||
| /* | |||
| * Copyright IBM Corp. and others 2001 | |||
There was a problem hiding this comment.
this reflects the year when the file was added
| * Copyright IBM Corp. and others 2001 | |
| * Copyright IBM Corp. and others 2026 |
| public interface TestInterfaceForGetMethod { | ||
|
|
||
| private static void privateStaticMethod() { | ||
| } | ||
| private void privateNonStaticMethod() { | ||
| } | ||
| } |
There was a problem hiding this comment.
formatting nit
| public interface TestInterfaceForGetMethod { | |
| private static void privateStaticMethod() { | |
| } | |
| private void privateNonStaticMethod() { | |
| } | |
| } | |
| public interface TestInterfaceForGetMethod { | |
| private static void privateStaticMethod() {} | |
| private void privateNonStaticMethod() {} | |
| } |
| @@ -0,0 +1,60 @@ | |||
| /* | |||
| * Copyright IBM Corp. and others 2001 | |||
There was a problem hiding this comment.
| * Copyright IBM Corp. and others 2001 | |
| * Copyright IBM Corp. and others 2026 |
| private static void privateStaticMethod() { | ||
| } | ||
| private void privateNonStaticMethod() { | ||
| } |
There was a problem hiding this comment.
also include a test case for a public method to verify non-private behavior
| try { | ||
| TestInterfaceForGetMethod.class.getMethod("privateStaticMethod"); | ||
| Assert.fail("Expected NoSuchMethodException for private static method in interface"); | ||
| } catch (NoSuchMethodException e) { | ||
| } | ||
| } |
There was a problem hiding this comment.
the testcases can be concisely written using assertThrows. example:
Update getMethodHelper() to properly throw NoSuchMethodException when Class.getMethod() is called on non-public interface methods. Added test coverage in Java9andUp/GetMethodTests: - Private static methods in interfaces throw NoSuchMethodException - Private non-static methods in interfaces throw NoSuchMethodException - Public methods successfully returns a Method Fixes: eclipse-openj9#22448 Signed-off-by: Tomal Majumder <Tomal.Majumder@ibm.com>
39ac334 to
fc97f64
Compare
|
Updated! Also added tests for public methods. |
Fix Class.getMethod() to throw NoSuchMethodException for non-public interface methods
Problem
Class.getMethod()must return only public methods or throwNoSuchMethodExceptionas per Java specification. Previously, when invoked on interface types with non-public methods (private static or non-static), the method incorrectly returnednullinstead of throwing the required exception.Root Cause
The issue was in the
initialResultShouldBeReplacedcode path ingetMethodHelper(). WhenpublicOnlywas true but the initial result was a non-public method, and no public alternatives were found, the method returnednullinstead of callingthrowExceptionOrReturnNull().Tests
Test coverage added in
Java9andUp/GetMethodTests.Fixes: #22448