-
Bug
-
Resolution: Unresolved
-
P4
-
None
-
24
-
generic
-
generic
A DESCRIPTION OF THE PROBLEM :
A fundamental contract of java.lang.Object is that for any non-null reference value x, x.hashCode() must return an integer value. The implementation of java.net.InterfaceAddress.hashCode() violates this contract.
The hashCode() method directly invokes this.address.hashCode() without checking if the address field is null.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
java --add-opens java.base/java.net=ALL-UNNAMED InterfaceAddressNPE.java
---------- BEGIN SOURCE ----------
import java.net.InterfaceAddress;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class InterfaceAddressNPE {
public static void main(String[] args) {
try {
// Step 1: Get the hidden, parameter-less constructor of InterfaceAddress.
// This is our secret entrance, as we can't use "new InterfaceAddress()".
Constructor<InterfaceAddress> constructor = InterfaceAddress.class.getDeclaredConstructor();
constructor.setAccessible(true); // Disable Java's access control checks.
// Step 2: Create a "blank" instance of the object.
// At this point, all its internal fields are uninitialized (i.e., null or 0).
InterfaceAddress instance = constructor.newInstance();
// Step 3: Get the private "address" field. This is the field that
// the hashCode() method incorrectly assumes is never null.
Field addressField = InterfaceAddress.class.getDeclaredField("address");
addressField.setAccessible(true); // Again, disable access checks.
// Step 4: The critical move. We explicitly set the "address" field to null.
// We are creating a state that the class's public methods would never produce,
// but which its hashCode() implementation fails to handle.
addressField.set(instance, null);
// Step 5: The moment of truth. Call hashCode() on our crafted object.
// This is the landmine we are intentionally stepping on.
instance.hashCode();
// If we reach this line, it means no exception was thrown.
// This would indicate the bug has been fixed in the JDK version being used.
System.out.println("TEST FAILED: No NullPointerException was thrown. The bug might be fixed.");
} catch (NullPointerException e) {
// SUCCESS! The expected exception was caught.
System.out.println("TEST PASSED: Successfully triggered the NullPointerException in hashCode().");
System.out.println("This confirms the bug: a non-null object's hashCode() method must not throw an exception.");
} catch (Exception e) {
// This catches any other exceptions, like from the reflection setup.
System.out.println("TEST FAILED: An unexpected exception occurred during setup.");
e.printStackTrace();
}
}
}
---------- END SOURCE ----------
A fundamental contract of java.lang.Object is that for any non-null reference value x, x.hashCode() must return an integer value. The implementation of java.net.InterfaceAddress.hashCode() violates this contract.
The hashCode() method directly invokes this.address.hashCode() without checking if the address field is null.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
java --add-opens java.base/java.net=ALL-UNNAMED InterfaceAddressNPE.java
---------- BEGIN SOURCE ----------
import java.net.InterfaceAddress;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class InterfaceAddressNPE {
public static void main(String[] args) {
try {
// Step 1: Get the hidden, parameter-less constructor of InterfaceAddress.
// This is our secret entrance, as we can't use "new InterfaceAddress()".
Constructor<InterfaceAddress> constructor = InterfaceAddress.class.getDeclaredConstructor();
constructor.setAccessible(true); // Disable Java's access control checks.
// Step 2: Create a "blank" instance of the object.
// At this point, all its internal fields are uninitialized (i.e., null or 0).
InterfaceAddress instance = constructor.newInstance();
// Step 3: Get the private "address" field. This is the field that
// the hashCode() method incorrectly assumes is never null.
Field addressField = InterfaceAddress.class.getDeclaredField("address");
addressField.setAccessible(true); // Again, disable access checks.
// Step 4: The critical move. We explicitly set the "address" field to null.
// We are creating a state that the class's public methods would never produce,
// but which its hashCode() implementation fails to handle.
addressField.set(instance, null);
// Step 5: The moment of truth. Call hashCode() on our crafted object.
// This is the landmine we are intentionally stepping on.
instance.hashCode();
// If we reach this line, it means no exception was thrown.
// This would indicate the bug has been fixed in the JDK version being used.
System.out.println("TEST FAILED: No NullPointerException was thrown. The bug might be fixed.");
} catch (NullPointerException e) {
// SUCCESS! The expected exception was caught.
System.out.println("TEST PASSED: Successfully triggered the NullPointerException in hashCode().");
System.out.println("This confirms the bug: a non-null object's hashCode() method must not throw an exception.");
} catch (Exception e) {
// This catches any other exceptions, like from the reflection setup.
System.out.println("TEST FAILED: An unexpected exception occurred during setup.");
e.printStackTrace();
}
}
}
---------- END SOURCE ----------