You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 45 Next »

Recall that immutability offers several benefits such as thread-safety, prevention against inadvertent modification of fields, and malicious tampering. Class invariants and state of immutable objects are always consistent with their requirements, so no defensive copying is necessary. However, sometimes it is not possible to make sensitive classes immutable. Fortunately, there is a mechanism that allows code to expose mutable classes to untrusted code by granting read-only access. This is largely achieved through unmodifiable wrappers. For example, the Collection classes include a set of wrappers that allow clients to observe an unmodifiable view of a Collection object.

Noncompliant Code Example

This noncompliant code example consists of class Mutable, which allows the internal array object to be modified. An untrusted invoker may call the mutator method setArray() and violate the object's immutability property. She may instead call the getter method getArray() and modify its contents directly. This is because this class also violates OBJ05-J. Defensively copy private mutable class members before returning their references.

class Mutable {
    private int[] array = new int[10];

    public int[] getArray() {
        return array;
    }

    public void setArray(int[] i) {
        array = i;
    }
}

// ...
private Mutable mutable = new Mutable();
public Mutable getMutable() {return mutable;}

Clearly the best solution would be to modify the Mutable class, but what if this is not possible?

Compliant Solution

In general, sensitive classes can be transformed into safe-view objects by providing wrappers for all the methods defined by the core interface, including the mutator methods. The wrappers for the mutator methods need to throw an UnsupportedOperationException so that clients cannot perform operations that affect the immutability property of the object.

This compliant solution constructs an MutableProtector object by extending the Mutable class. This wrapper overrides the getArray() method, and clones the array. So while untrusted code gets a copy of the mutable object's array, the original array remains unchanged and inaccessable to the untrusted code. Second, the wrapper overrides setArray(), and throws an exception if the caller attempts to use this method on the returned object. This object can be passed to untrusted code as required.

class MutableProtector extends Mutable {
    public int[] getArray() {
        return super.getArray().clone();
    }
 
    public void setArray(int[] i) {
        throw new UnsupportedOperationException();
    }
}

// ...
private Mutable mutable = new MutableProtector();
public Mutable getMutable() {return mutable;}

Applicability

Failure to provide an unmodifiable safe-view of a sensitive mutable object to untrusted code can lead to malicious tampering and corruption of the object.

Bibliography

[Tutorials 2008] Unmodifiable Wrappers


  • No labels