Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: ok i'm done with this one

Objects in general should — and security critical objects must — be left maintained in a consistent state even when exceptional conditions arise. Common techniques for maintaining object consistency include

  • Input validation (for example, method parameters)
  • Reordering logic so that code that can result in the exceptional condition executes before the object is modified
  • Using rollbacks in the event of failure
  • Performing required operations on a temporary copy of the object and committing changes to the original object only after their successful completion
  • Avoiding the need to modify the object in the first placeat all

Noncompliant Code Example

This noncompliant code example shows a Dimensions class that contains three internal attributes, the length, width, and height of a rectangular box. The getVolumePackage() method is designed to return the total volume required to hold the box, after accounting for packaging material which further adds 2 units to the dimensions of each side. Non-positive values of the dimensions of the box (exclusive of packaging material) are rejected during input validation. No dimension cannot be larger than 10. Also, the weight of the object is passed in as an argument and cannot be more than 20 units.

...

Code Block
bgColor#FFcccc
class Dimensions {
  private int length;
  private int width;
  private int height;
  static public final int PADDING = 2;
  static public final int MAX_DIMENSION = 10;

  public Dimensions(int length, int width, int height) {
    this.length = length;
    this.width = width;
    this.height = height;
  }

  protected int getVolumePackage(int weight) {
    length += PADDING;
    width  += PADDING;
    height += PADDING;
    try {
      if (length <= PADDING || width <= PADDING || height <= PADDING ||
        length > MAX_DIMENSION + PADDING || width > MAX_DIMENSION + PADDING ||
        height > MAX_DIMENSION + PADDING || weight <= 0 || weight > 20) {
        throw new IllegalArgumentException();
      }	

      int volume = length * width * height; // 12 * 12 * 12 = 1728
      length -= PADDING; width -= PADDING; height -= PADDING; // Revert back
      return volume;
    } catch (Throwable t) { 
      MyExceptionReporter mer = new MyExceptionReporter();
      mer.report(t); // Sanitize 
      return -1; // Non-positive error code
    }	
  }

  public static void main(String[] args) {
    Dimensions d = new Dimensions(10, 10, 10);
    System.out.println(d.getVolumePackage(21)); // Prints -1 (error)
    System.out.println(d.getVolumePackage(19)); // Prints 2744 instead of 1728
  }
}

The catch clause is permitted under by exception EXC14-EX0 of guideline rule ERR14-J. Do not catch RuntimeException; as it serves as a general filter passing exceptions to the MyExceptionReporter class, which is dedicated to safely reporting exceptions, as recommended by guideline rule ERR00-J. Do not suppress or ignore checked exceptions. While this code only throws IllegalArgumentException the catch clause is general enough to handle any exception, in case the try block should be modified to throw other exceptions.

...

Code Block
bgColor#ccccff
protected int getVolumePackage(int weight) {
  length += PADDING;
  width  += PADDING;
  height += PADDING;
  try {
    if (length <= PADDING || width <= PADDING || height <= PADDING ||
      length > MAX_DIMENSION + PADDING || width > MAX_DIMENSION + PADDING ||
      height > MAX_DIMENSION + PADDING || weight <= 0 || weight > 20) {
      throw new IllegalArgumentException();
    }	

    int volume = length * width * height; // 12 * 12 * 12 = 1728
    return volume;
  } catch (Throwable t) { 
    MyExceptionReporter mer = new MyExceptionReporter();
    mer.report(t); // Sanitize 
    return -1; // Non-positive error code
  } finally {
    length -= PADDING; width -= PADDING; height -= PADDING; // Revert back
  }
}

Compliant Solution (Input

...

Validation)

This improved compliant solution performs improves upon the previous solution by performing input validation before modifying the state of the object. Note that the try block contains only those statements that could throw the exception; all others have been moved outside the try block.

...

Compliant Solution (Modification Avoided)

This compliant solution entirely avoids the need to modify the object; consequently . Consequently, the fields cannot be violated and rollback becomes is unnecessary. This approach is preferred over the other compliant solutions when possible. This approach to solutions which modify the object but may be infeasible for more complex code.

Code Block
bgColor#ccccff
protected int getVolumePackage(int weight) {
  try {
    if (length <= 0 || width <= 0 || height <= 0 ||
        length > MAX_DIMENSION || width > MAX_DIMENSION || height > MAX_DIMENSION ||
        weight <= 0 || weight > 20) {
      throw new IllegalArgumentException(); // Validate first
    }
  } catch (Throwable t) { MyExceptionReporter mer = new MyExceptionReporter();
    mer.report(t); // Sanitize 
    return -1;
  }		

  int volume = (length + PADDING) * (width + PADDING) * (height + PADDING);
  return volume;
}

...