Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: FQNs and discussions on solutions

...

Depending on the function that this code performs, this might introduce a vulnerability to a mix-and-match attack. An attacker can supply code that is the same name as your class; if you rely on comparing the classname as a string, you might end up believing it is privileged code and granting it undue privileges.

Conversely, a source of error is assuming that the same codebase will result in the same class in a JVM. While it is usually true in common user applications, it is not the case with J2EE servers like servlet containers, which could use different instances of classloaders to be able to deploy and undeploy applications at runtime without restarting the JVM. In this situation, 2 objects whose classes come from the same codebase could be different classes to the JVM and it could be confusing to get false from the equals() method on their respective classes.

Non-Compliant Solution

In this non-compliant solution, the code compares the name of the class of object h to the string "DefaultAuthenticationHandler", and proceeds according to whether this comparison succeeds or not.

Code Block
 // determine whether object h has required/expected class name
if (h.getClass().getName().equals("com.example.application.auth.DefaultAuthenticationHandler")) {
    // code assumes it's an authorized class
}

The problem with this solution is that another class could exist with the same name in the same JVM.

Compliant Solution

In this compliant solution, we compare the class object of h itself to the class object of the class that the current class loader would load with our required name.

Code Block
 // determine whether object h has required/expected class name
if (h.getClass() == this.getClassLoader().loadClass("com.example.application.auth.DefaultAuthenticationHandler")) {
    // code determines authorized class loaded by same classloader
}

The call to loadClass() returns the class having the specified name in the current namespace (of the classloader), and the comparison is correctly performed on two class objects.

Non Non-Compliant Solution

This code compares the names of the 2 classes of objects x and y and behaves accordingly.

Code Block
 // determine whether objects x and y have same class name
if (x.getClass().getName().equals( y.getClass().getName() )) {
    // code assumes objects have same class
}

 Compliant Solution

It should compare the two class objects instead.

Compliant Solution

This compliant solution correctly compares the 2 objects' classes

Code Block
 // determine whether objects x and y have same class
if (x.getClass() == y.getClass()) {
    // code determines objects have same class
}

Conversely, a source of error is assuming that the same codebase will result in The class objects will only be equal when they have the same class in a JVM. While it is usually true in common user applications, it is not the case with J2EE servers like servlet containers, which could use different instances of classloaders to be able to deploy and undeploy applications at runtime without restarting the JVM. In this situation, 2 objects whose classes come from the same codebase could be different classes to the JVM and it could be confusing to get false from the equals() method on their respective classesas defined in JVMSpec 99 and repeated above.

References

  1. http://java.sun.com/docs/books/jvms/second_edition/html/Concepts.doc.html
  2. Wiki Markup
    [http://www.javaworld.com/javaworld/jw-12-1998/jw-12-securityrules.html?page=4] \[Mcgraw and Felten\]
  3. http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/java.html
  4. http://www.onjava.com/pub/a/onjava/2005/01/26/classloading.html