Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8281623

(ch) FileLock: negative param and overflow issues

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P4 P4
    • 19
    • core-libs
    • None
    • behavioral
    • low
    • Hide
      It's highly unlikely that there is code calling the "overlaps" method with a negative size and expecting the method to return true. The change to the lock method to promote a size of 0 to Long.MAX_VALUE - position is more significant but unlikely as it would be relying on unspecified (and platform specific) behavior. Overall we think the compatibility risk of this change is low.
      Show
      It's highly unlikely that there is code calling the "overlaps" method with a negative size and expecting the method to return true. The change to the lock method to promote a size of 0 to Long.MAX_VALUE - position is more significant but unlikely as it would be relying on unspecified (and platform specific) behavior. Overall we think the compatibility risk of this change is low.
    • Java API
    • SE

      Summary

      Improve the specification of java.nio.channels.FileLock.overlaps() and adjust its behavior to match. In the java.nio.channels classes AsynchronousFileChannel and FileChannel, clarify and make consistent the behavior of creating a FileLock when the size parameter is zero.

      Problem

      The method FileLock.overlaps(position,size) does not place any constraints on its parameters unlike the constructors of the class, and does not behave in a useful way when the size parameter is negative, or the sum of the position and size parameters overflows a long.

      The lock creation methods in AsynchronousFileChannel and FileChannel which accept position and size parameters are not sufficiently clear that a size parameter of zero means to lock all bytes from the position onward whether or not the size of the file subsequently changes.

      Solution

      Make FileLock.overlaps handle a negative size and an overflowing sum of position and size in a reasonable way.

      Make it clear that the lock creation methods in AsynchronousFileChannel and FileChannel which accept position and size parameters will create a lock of size Long.MAX_VALUE - position when the size parameter is zero, and that this means that all bytes from position onward are locked regardless of file size changes.

      Specification

              --- a/src/java.base/share/classes/java/nio/channels/AsynchronousFileChannel.java
              +++ b/src/java.base/share/classes/java/nio/channels/AsynchronousFileChannel.java
      @@ -425,10 +425,13 @@ public abstract class AsynchronousFileChannel
            * required then a region starting at zero, and no smaller than the
            * expected maximum size of the file, should be locked.  The two-argument
            * {@link #lock(Object,CompletionHandler)} method simply locks a region
      -     * of size {@link Long#MAX_VALUE}. If a lock that overlaps the requested
      -     * region is already held by this Java virtual machine, or this method has
      -     * been invoked to lock an overlapping region and that operation has not
      -     * completed, then this method throws {@link OverlappingFileLockException}.
      +     * of size {@link Long#MAX_VALUE}.  If the {@code position} is non-negative
      +     * and the {@code size} is zero, then a lock of size
      +     * {@code Long.MAX_VALUE - position} is returned.  If a lock that
      +     * overlaps the requested region is already held by this Java virtual
      +     * machine, or this method has been invoked to lock an overlapping region
      +     * and that operation has not completed, then this method throws
      +     * {@link OverlappingFileLockException}.
            *
            * <p> Some operating systems do not support a mechanism to acquire a file
            * lock in an asynchronous manner. Consequently an implementation may
      @@ -454,7 +457,10 @@ public abstract class AsynchronousFileChannel
            *          non-negative
            * @param   size
            *          The size of the locked region; must be non-negative, and the sum
      -     *          {@code position}&nbsp;+&nbsp;{@code size} must be non-negative
      +     *          {@code position}&nbsp;+&nbsp;{@code size} must be non-negative.
      +     *          A value of zero means to lock all bytes from the specified
      +     *          starting position to the end of the file, regardless of whether
      +     *          the file is subsequently extended or truncated
            * @param   shared
            *          {@code true} to request a shared lock, in which case this
            *          channel must be open for reading (and possibly writing);
      @@ -532,7 +538,10 @@ public abstract class AsynchronousFileChannel
            *          non-negative
            * @param   size
            *          The size of the locked region; must be non-negative, and the sum
      -     *          {@code position}&nbsp;+&nbsp;{@code size} must be non-negative
      +     *          {@code position}&nbsp;+&nbsp;{@code size} must be non-negative.
      +     *          A value of zero means to lock all bytes from the specified
      +     *          starting position to the end of the file, regardless of whether
      +     *          the file is subsequently extended or truncated
            * @param   shared
            *          {@code true} to request a shared lock, in which case this
            *          channel must be open for reading (and possibly writing);
      @@ -586,7 +595,9 @@ public abstract class AsynchronousFileChannel
            * either having acquired a lock on the requested region or having failed to
            * do so.  If it fails to acquire a lock because an overlapping lock is held
            * by another program then it returns {@code null}.  If it fails to acquire
      -     * a lock for any other reason then an appropriate exception is thrown.
      +     * a lock for any other reason then an appropriate exception is thrown.  If
      +     * the {@code position} is non-negative and the {@code size} is zero, then a
      +     * lock of size {@code Long.MAX_VALUE - position} is returned.
            *
            * @param  position
            *         The position at which the locked region is to start; must be
      @@ -594,7 +605,10 @@ public abstract class AsynchronousFileChannel
            *
            * @param  size
            *         The size of the locked region; must be non-negative, and the sum
      -     *         {@code position}&nbsp;+&nbsp;{@code size} must be non-negative
      +     *         {@code position}&nbsp;+&nbsp;{@code size} must be non-negative.
      +     *         A value of zero means to lock all bytes from the specified
      +     *         starting position to the end of the file, regardless of whether
      +     *         the file is subsequently extended or truncated
            *
            * @param  shared
            *         {@code true} to request a shared lock,
      --- a/src/java.base/share/classes/java/nio/channels/FileChannel.java
      +++ b/src/java.base/share/classes/java/nio/channels/FileChannel.java
      @@ -981,7 +981,9 @@ public abstract class FileChannel
            * required then a region starting at zero, and no smaller than the
            * expected maximum size of the file, should be locked.  The zero-argument
            * {@link #lock()} method simply locks a region of size {@link
      -     * Long#MAX_VALUE}.
      +     * Long#MAX_VALUE}.  If the {@code position} is non-negative and the
      +     * {@code size} is zero, then a lock of size
      +     * {@code Long.MAX_VALUE - position} is returned.
            *
            * <p> Some operating systems do not support shared locks, in which case a
            * request for a shared lock is automatically converted into a request for
      @@ -999,7 +1001,10 @@ public abstract class FileChannel
            *
            * @param  size
            *         The size of the locked region; must be non-negative, and the sum
      -     *         {@code position}&nbsp;+&nbsp;{@code size} must be non-negative
      +     *         {@code position}&nbsp;+&nbsp;{@code size} must be non-negative.
      +     *         A value of zero means to lock all bytes from the specified
      +     *         starting position to the end of the file, regardless of whether
      +     *         the file is subsequently extended or truncated
            *
            * @param  shared
            *         {@code true} to request a shared lock, in which case this
      @@ -1108,7 +1113,9 @@ public abstract class FileChannel
            * required then a region starting at zero, and no smaller than the
            * expected maximum size of the file, should be locked.  The zero-argument
            * {@link #tryLock()} method simply locks a region of size {@link
      -     * Long#MAX_VALUE}.
      +     * Long#MAX_VALUE}.  If the {@code position} is non-negative and the 
      +     * {@code size} is zero, then a lock of size
      +     * {@code Long.MAX_VALUE - position} is returned.
            *
            * <p> Some operating systems do not support shared locks, in which case a
            * request for a shared lock is automatically converted into a request for
      @@ -1126,7 +1133,10 @@ public abstract class FileChannel
            *
            * @param  size
            *         The size of the locked region; must be non-negative, and the sum
      -     *         {@code position}&nbsp;+&nbsp;{@code size} must be non-negative
      +     *         {@code position}&nbsp;+&nbsp;{@code size} must be non-negative.
      +     *         A value of zero means to lock all bytes from the specified
      +     *         starting position to the end of the file, regardless of whether
      +     *         the file is subsequently extended or truncated
            *
            * @param  shared
            *         {@code true} to request a shared lock,
              --- a/src/java.base/share/classes/java/nio/channels/FileLock.java
              +++ b/src/java.base/share/classes/java/nio/channels/FileLock.java
              @@ -269,14 +269,34 @@ public abstract class FileLock implements AutoCloseable {
                    * @param   size
                    *          The size of the lock range
                    *
              -     * @return  {@code true} if, and only if, this lock and the given lock
              -     *          range overlap by at least one byte
              +     * @return  {@code true} if this lock and the given lock range overlap
              +     *          by at least one byte; {@code false} if {@code size} is
              +     *          negative or the lock range does not overlap this lock
                    */
                   public final boolean overlaps(long position, long size) {

            bpb Brian Burkhalter
            mmcclosksunw Michael Mccloskey (Inactive)
            Alan Bateman
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: