Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: changed code samples

...

This noncompliant code example consists of class Modifiable Mutable, which allows the internal ArrayList array object to be modified. An untrusted invoker may call the mutator method listItsetArray() 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.

Code Block
bgColor#ffcccc
lang#FFccccjava
class ModifiableMutable {	
    private List<Integer>int[] listarray = new ArrayList<Integer>()int[10];

  public void listIt() {
    addSomething(list);
    // ...
  }

  private void addSomething(Collection<Integer> collection) {
    collection.add(1); 
  }
}

Compliant Solution

This compliant solution recommends an unmodifiable wrapper to shield the mutator method(s) and provide an unmodifiable view to the caller. Internally, the unmodifiable Collection's mutator methods are designed to throw an UnsupportedOperationException in such events.

Code Block
bgColor#ccccff
// ...
public void listIt() {
  addSomething(Collections.unmodifiableCollection(list));
  // ...
}

private void addSomething(Collection<Integer> collection) {
  collection.add(1); // throws java.lang.UnsupportedOperationException
} 

It should be noted that objects present within the Collection may not be thread-safe, making them mutable in multithreaded contexts. Consider, for example, an ArrayList of ArrayLists wherein the contained ArrayList is still susceptible to modification.

Noncompliant Code Example

This noncompliant code example shows an interface MutableInterface that declares an accessor and a mutator method. This class does not expose an unmodifiable view to implementing clients.

Code Block
bgColor#FFcccc
interface MutableInterface {
  int[] getArray(); // accessor
 public int[] getArray() {
        return array;
    }

    public void setArray(int[] i); //mutator
}

class SensitiveMutable implements MutableInterface {
  int[]{
        array = new int[10]; // mutable array

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

  public void setArray(int[] i) {
    array = i;
  }
}
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 implementing providing wrappers for all the methods defined by the core interface, including the mutator methods. In this case, the difference is that the mutators 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 UnmodifiableSensitiveMutable MutableProtector object by extending the Mutable class SensitiveMutable. An interface UnmodifiableInterface consists of the method unmodifiableView. This wrapper overrides the getArray(), which accepts a SensitiveMutable object as the sole parameter. It returns an equivalent object that is a subtype of the same class and is unmodifiable. An exception is thrown 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 the mutator this method on the returned object. This object can be passed to untrusted code as required.

Code Block
bgColor#ccccff
langjava
class MutableProtectorinterface UnmodifiableInterface {
  SensitiveMutable unmodifiableView(SensitiveMutable sm);
}

class UnmodifiableSensitiveMutable extends SensitiveMutable Mutable {
  int[] array = new int[10];

  public void setArray(int[] igetArray() {
    throw new UnsupportedOperationException();
  }
}

class UnmodifiableWrapper extends UnmodifiableSensitiveMutable implements UnmodifiableInterface {
  public SensitiveMutable unmodifiableView(SensitiveMutable sm) { 
    return new UnmodifiableWrapperreturn super.getArray().clone();
 // subtype of SensitiveMutable}
  }
}

class Invoker {
  public static void mainsetArray(Stringint[] argsi) {
      UnmodifiableWrapper uw =throw new UnmodifiableWrapperUnsupportedOperationException();
    SensitiveMutable s = uw.unmodifiableView(sm);
    s.setArray(new int[10]); // throws UnsupportedOperationException unlike s.getArray()    
  }
}
}

// ...
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.

...