-
Bug
-
Resolution: Unresolved
-
P4
-
None
-
11, 17, 19, 20, 21
-
generic
-
generic
A DESCRIPTION OF THE PROBLEM :
The ParameterizedTypeImpl toString() method might give an incorrect result in the very rare corner case of an inner class of a packageless class if the inner class name is the outer class name followed by "$" followed by a suffix.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the provided source code.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
It should output "It is good!"
ACTUAL -
It outputs "BAD: PackagelessConfusion<java.lang.Integer>$xxx<java.lang.Integer>"
---------- BEGIN SOURCE ----------
// No package declaration!
import java.lang.reflect.ParameterizedType;
public class PackagelessConfusion<A> {
public class PackagelessConfusion$xxx<B> {
}
public static PackagelessConfusion<Integer>.PackagelessConfusion$xxx<Integer> blah() {
throw new UnsupportedOperationException();
}
public static void main(String... args) throws Exception {
var actual = PackagelessConfusion.class.getDeclaredMethod("blah").getGenericReturnType().toString();
var expected = "PackagelessConfusion<java.lang.Integer>$PackagelessConfusion$xxx<java.lang.Integer>";
if (actual.equals(expected)) {
System.out.println("It is good!");
} else {
System.out.println("BAD: " + actual);
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
This is a very rare corner-case that shows up only in a very contrieved made up situation built just to show that the bug exists. I don't think that it has any real use cases (at least until some cracker is able to use this somehow as part of an exploit to attack some system somewhere, but even this seems improbable). But nevertheless, this is still a bug.
BUT: I have a fix for this and I am willing to open a PR.
The bug comes from this line in the toString() method in the sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl class:
sb.append(rawType.getName().replace(((ParameterizedType) ownerType).getRawType().getTypeName() + "$", ""));
The problem is that the replace method might do more than one replacement. I propose as a solution to use this instead:
sb.append(rawType.getName().substring(((ParameterizedType) ownerType).getRawType().getTypeName().length() + 1));
FREQUENCY : always
The ParameterizedTypeImpl toString() method might give an incorrect result in the very rare corner case of an inner class of a packageless class if the inner class name is the outer class name followed by "$" followed by a suffix.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the provided source code.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
It should output "It is good!"
ACTUAL -
It outputs "BAD: PackagelessConfusion<java.lang.Integer>$xxx<java.lang.Integer>"
---------- BEGIN SOURCE ----------
// No package declaration!
import java.lang.reflect.ParameterizedType;
public class PackagelessConfusion<A> {
public class PackagelessConfusion$xxx<B> {
}
public static PackagelessConfusion<Integer>.PackagelessConfusion$xxx<Integer> blah() {
throw new UnsupportedOperationException();
}
public static void main(String... args) throws Exception {
var actual = PackagelessConfusion.class.getDeclaredMethod("blah").getGenericReturnType().toString();
var expected = "PackagelessConfusion<java.lang.Integer>$PackagelessConfusion$xxx<java.lang.Integer>";
if (actual.equals(expected)) {
System.out.println("It is good!");
} else {
System.out.println("BAD: " + actual);
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
This is a very rare corner-case that shows up only in a very contrieved made up situation built just to show that the bug exists. I don't think that it has any real use cases (at least until some cracker is able to use this somehow as part of an exploit to attack some system somewhere, but even this seems improbable). But nevertheless, this is still a bug.
BUT: I have a fix for this and I am willing to open a PR.
The bug comes from this line in the toString() method in the sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl class:
sb.append(rawType.getName().replace(((ParameterizedType) ownerType).getRawType().getTypeName() + "$", ""));
The problem is that the replace method might do more than one replacement. I propose as a solution to use this instead:
sb.append(rawType.getName().substring(((ParameterizedType) ownerType).getRawType().getTypeName().length() + 1));
FREQUENCY : always