Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

A fundamental principle of object-oriented design is that when a subclass extends a superclass, the subclass's methods should preserve the invariants provided by the superclass. Unfortunately, attackers are not constrained by design principles . They can fail to constrain attackers, who can (and do!) construct malicious classes which that extend benign classes and provide methods that deliberately violate the invariants of the benign classes.

For instance, if an immutable class is not declared final, it might be possible to write that lacks the final qualifier can be extended by a malicious subclass capable of changing that can change the state of the supposedly-immutable object. It would definitely be possible for Further, the malicious subclass to can impersonate the immutable object without while actually being immutableremaining mutable. Such malicious subclasses would be capable of violating can then violate program invariants on which clients depend, thus introducing security vulnerabilities.

Therefore, classes with invariants that on which other code depends on ought to should be declared final, thereby preventing malicious subclasses from subverting their invariants. Furthermore, immutable classes must be declared final.

Some classes (hereafter known as superclasses) must permit extension by trusted subclasses while simultaneously preventing extension by untrusted code. ThereforeConsequently, declaring such superclasses to be final is not an optioninfeasible, because it would prevent the required extension by trusted code. Such problems require careful design for inheritance.

...

A method which receives an untrusted, non-final input argument must beware that other methods or threads might modify the input object. Some methods try attempt to prevent modification by making a local copy of the input object. This does not provide sufficient protection, as is insufficient, because a shallow copy of an object may still allow it to point to mutable sub-objects, which may still be modified by other methods or threads. Some methods go farther and perform a deep copy of the input object. This mitigates the problem of modifiable sub-objects, but the method might still be passed receive as an argument a mutable object that extends the input object class.

...

This malicious BigInteger class is clearly mutable, thanks due to the setValue() method. Furthermore, the modPow() method is subject to precision loss (see NUM00-J. Detect or prevent integer overflow, NUM11-J. Check floating point inputs for exceptional values, NUM15-J. Ensure conversions of numeric types to narrower types do not result in lost or misinterpreted data and NUM17-J. Beware of precision loss when converting primitive integers to floating-point for more information). Any code that receives an object of this class, and assumes it that the object is immutable will have unexpected behavior. (The BigInteger.modPow() method has several useful cryptographic applications.)

...

Wiki Markup
When instances of non-final classes are obtained from untrusted sources, such instances shouldmust be used with care, because their method calls might be overridden by malicious methods. This potential vulnerability can be mitigated by making defensive copies of the acquired instances prior to use. This compliant solution demonstrates this technique for a {{BigInteger}} argument \[[Bloch 2008|AA. Bibliography#Bloch 08]\].

...

Wiki Markup
This solution thwarts the finalizer attack.; Itit is specific to Java SE 6 and onwards, where a finalizer is prevented from being executed when throwing an exception is thrown before the {{java.lang.Object}} constructor exits prevents execution of finalizers \[[SCG 2009|AA. Bibliography#SCG 09]\].

...