Skip to end of metadata
Go to start of metadata

Buffer classes defined in the java.nio package, such as IntBuffer, CharBuffer, and ByteBuffer, define a variety of wrap() methods that wrap an array of the corresponding primitive data type into a buffer and return the buffer as a Buffer object. Although these methods create a new Buffer object, the new Buffer is backed by the given input array. According to the Java API for these methods [API 2014],

The new buffer will be backed by the given character array; that is, modifications to the buffer will cause the array to be modified and vice versa.

Exposing these buffers to untrusted code exposes the backing array to malicious modification. Likewise, the duplicate() methods create additional buffers that are backed by the original buffer's backing array; exposing such additional buffers to untrusted code affords the same opportunity for malicious modification.

Noncompliant Code Example (wrap())

This noncompliant code example declares a char array, wraps it within a CharBuffer, and exposes that CharBuffer to untrusted code via the getBufferCopy() method:

final class Wrap {
  private char[] dataArray;

  public Wrap() {
    dataArray = new char[10];
    // Initialize
  }

  public CharBuffer getBufferCopy() {
    return CharBuffer.wrap(dataArray);
  }
}

Compliant Solution (asReadOnlyBuffer())

This compliant solution returns a read-only view of the char array in the form of a read-only CharBuffer. The standard library implementation of CharBuffer guarantees that attempts to modify the elements of a read-only CharBuffer will result in a java.nio.ReadOnlyBufferException.

final class Wrap {
  private char[] dataArray;

  public Wrap() {
    dataArray = new char[10];
    // Initialize
  }

  public CharBuffer getBufferCopy() {
    return CharBuffer.wrap(dataArray).asReadOnlyBuffer();
  }
}

Compliant Solution (Copy)

This compliant solution allocates a new CharBuffer and explicitly copies the contents of the char array into it before returning the copy. Consequently, malicious callers can modify the copy of the array but cannot modify the original.

final class Wrap {
  private char[] dataArray;

  public Wrap() {
    dataArray = new char[10];
    // Initialize
  }

  public CharBuffer getBufferCopy() {
    CharBuffer cb = CharBuffer.allocate(dataArray.length);
    cb.put(dataArray);
    return cb;
  }
}

Noncompliant Code Example (duplicate())

This noncompliant code example invokes the duplicate() method to create and return a copy of the CharBuffer. As stated in the contract for the duplicate() method, the returned buffer is backed by the same array as is the original buffer. Consequently, if a caller were to modify the elements of the backing array, these modifications would also affect the original buffer.

final class Dup {
  CharBuffer cb;

  public Dup() {
    cb = CharBuffer.allocate(10);
    // Initialize
  }

  public CharBuffer getBufferCopy() {
    return cb.duplicate();
  }
}

Compliant Solution (asReadOnlyBuffer())

This compliant solution exposes a read-only view of the CharBuffer to untrusted code:

final class Dup {
  CharBuffer cb;

  public Dup() {
    cb = CharBuffer.allocate(10);
    // Initialize
  }

  public CharBuffer getBufferCopy() {
    return cb.asReadOnlyBuffer();
  }
}

Risk Assessment

Exposing buffers created using the wrap() or duplicate() methods may allow an untrusted caller to alter the contents of the original data.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

FIO05-J

Medium

Likely

Low

P18

L1

Automated Detection

Sound automated detection of this vulnerability is not feasible. Heuristic approaches may be useful.

Bibliography

[API 2014]

Class CharBuffer

[Hitchens 2002]

Section 2.3 "Duplicating Buffers"

 


2 Comments

  1. I think what this says:

    When the CharBuffer created by the duplicate() method is based on a CharBuffer returned by the wrap() method, modifying the CharBuffer returned by the duplicate() method also modifies the contents of the backing char array.

    Is that you can chain these calls together in an arbitrary fashion and still have the original problem. I don't think it is necessary to make this point, but if we do make this point it is better to express the general problem and include it in the introduction.

    1. I just removed the above paragraph. I'm done with this rule, unless someone wants to generalize this observation and move it to the rule description.