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

OfAddress setter should disallow heap segments

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P2 P2
    • 20
    • core-libs
    • None
    • behavioral
    • minimal
    • In Java 19 (and previous) this was already the behavior - although such behavior was undocumented.
    • Java API
    • SE

      Summary

      It should not be possible to pass heap segments as a write parameter to a memory segment view var handle.

      Problem

      Memory segment view var handles are created (from layouts) using the MethodHandles.memorySegmentViewVarHandle factory. If the carrier associated with the layout is a MemorySegment, the corresponding memory segment view var handle will allow to write the address of a segment (the parameter of the write operation) into some other segment. This should only be possible if the segment to be written is a native segment, in which case a physical address does exist.

      Solution

      The solution is to reuse the same checks that we apply to downcall method handle parameters. That is, when a struct is passed by reference the Linker already checks that the segment containing the struct bytes is a native segment, or an exception is thrown. The same should happen for memory set operations involving memory segments.

      Specification

      diff --git a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java
      index a1da55b8c0e..11633df2ce7 100644
      --- a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java
      +++ b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java
      @@ -1734,6 +1734,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
            * @throws IndexOutOfBoundsException when the access operation falls outside the <em>spatial bounds</em> of the
            * memory segment.
            * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}.
      +     * @throws UnsupportedOperationException if {@code value} is not a {@linkplain #isNative() native} segment.
            */
           @ForceInline
           default void set(ValueLayout.OfAddress layout, long offset, MemorySegment value) {
      @@ -2079,6 +2080,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
            * @throws IndexOutOfBoundsException when the access operation falls outside the <em>spatial bounds</em> of the
            * memory segment.
            * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}.
      +     * @throws UnsupportedOperationException if {@code value} is not a {@linkplain #isNative() native} segment.
            */
           @ForceInline
           default void setAtIndex(ValueLayout.OfAddress layout, long index, MemorySegment value) {
      diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
      index a63f53d3ca1..4c901afefb1 100644
      --- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
      +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
      @@ -7931,8 +7931,11 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
            * {@code get} and {@code set} access modes will result in an {@code IllegalStateException}. If access is partially aligned,
            * atomic access is only guaranteed with respect to the largest power of two that divides the GCD of {@code A} and {@code S}.
            * <p>
      -     * Finally, in all other cases, we say that a memory access operation is <em>misaligned</em>; in such cases an
      +     * In all other cases, we say that a memory access operation is <em>misaligned</em>; in such cases an
            * {@code IllegalStateException} is thrown, irrespective of the access mode being used.
      +     * <p>
      +     * Finally, if {@code T} is {@code MemorySegment} all write access modes throw {@link IllegalArgumentException}
      +     * unless the value to be written is a {@linkplain MemorySegment#isNative() native} memory segment.
            *
            * @param layout the value layout for which a memory access handle is to be obtained.
            * @return the new memory segment view var handle.

            mcimadamore Maurizio Cimadamore
            jvernee Jorn Vernee
            Jorn Vernee
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: