8288534: Out of bound errors for memory segment access mentions wrong values

Reviewed-by: psandoz
This commit is contained in:
Maurizio Cimadamore 2022-06-16 15:59:22 +00:00
parent 729164f534
commit ff3db52044
3 changed files with 26 additions and 3 deletions

View file

@ -28,6 +28,7 @@ package java.lang.foreign;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import jdk.internal.foreign.Utils; import jdk.internal.foreign.Utils;
import jdk.internal.vm.annotation.ForceInline;
import jdk.internal.vm.annotation.Stable; import jdk.internal.vm.annotation.Stable;
abstract non-sealed class AbstractLayout implements MemoryLayout { abstract non-sealed class AbstractLayout implements MemoryLayout {
@ -86,6 +87,7 @@ abstract non-sealed class AbstractLayout implements MemoryLayout {
} }
@Override @Override
@ForceInline
public long byteSize() { public long byteSize() {
if (cachedSize == 0) { if (cachedSize == 0) {
cachedSize = Utils.bitsToBytesOrThrow(bitSize(), cachedSize = Utils.bitsToBytesOrThrow(bitSize(),

View file

@ -41,6 +41,7 @@ import java.nio.IntBuffer;
import java.nio.LongBuffer; import java.nio.LongBuffer;
import java.nio.ShortBuffer; import java.nio.ShortBuffer;
import java.util.*; import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.IntFunction; import java.util.function.IntFunction;
@ -51,6 +52,7 @@ import jdk.internal.access.SharedSecrets;
import jdk.internal.access.foreign.UnmapperProxy; import jdk.internal.access.foreign.UnmapperProxy;
import jdk.internal.misc.ScopedMemoryAccess; import jdk.internal.misc.ScopedMemoryAccess;
import jdk.internal.util.ArraysSupport; import jdk.internal.util.ArraysSupport;
import jdk.internal.util.Preconditions;
import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.annotation.ForceInline;
import static java.lang.foreign.ValueLayout.JAVA_BYTE; import static java.lang.foreign.ValueLayout.JAVA_BYTE;
@ -64,7 +66,7 @@ import static java.lang.foreign.ValueLayout.JAVA_BYTE;
* are defined for each memory segment kind, see {@link NativeMemorySegmentImpl}, {@link HeapMemorySegmentImpl} and * are defined for each memory segment kind, see {@link NativeMemorySegmentImpl}, {@link HeapMemorySegmentImpl} and
* {@link MappedMemorySegmentImpl}. * {@link MappedMemorySegmentImpl}.
*/ */
public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegment, SegmentAllocator, Scoped { public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegment, SegmentAllocator, Scoped, BiFunction<String, List<Number>, RuntimeException> {
private static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess(); private static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();
@ -394,13 +396,20 @@ public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegm
@ForceInline @ForceInline
void checkBounds(long offset, long length) { void checkBounds(long offset, long length) {
if (length > 0) { if (length > 0) {
Objects.checkIndex(offset, this.length - length + 1); Preconditions.checkIndex(offset, this.length - length + 1, this);
} else if (length < 0 || offset < 0 || } else if (length < 0 || offset < 0 ||
offset > this.length - length) { offset > this.length - length) {
throw outOfBoundException(offset, length); throw outOfBoundException(offset, length);
} }
} }
@Override
public RuntimeException apply(String s, List<Number> numbers) {
long offset = numbers.get(0).longValue();
long length = byteSize() - numbers.get(1).longValue() + 1;
return outOfBoundException(offset, length);
}
@Override @Override
@ForceInline @ForceInline
public MemorySessionImpl sessionImpl() { public MemorySessionImpl sessionImpl() {
@ -413,7 +422,7 @@ public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegm
} }
private IndexOutOfBoundsException outOfBoundException(long offset, long length) { private IndexOutOfBoundsException outOfBoundException(long offset, long length) {
return new IndexOutOfBoundsException(String.format("Out of bound access on segment %s; new offset = %d; new length = %d", return new IndexOutOfBoundsException(String.format("Out of bound access on segment %s; offset = %d; length = %d",
this, offset, length)); this, offset, length));
} }

View file

@ -154,6 +154,18 @@ public class TestSegments {
memorySegment.get(JAVA_INT, offset); memorySegment.get(JAVA_INT, offset);
} }
@Test
public void testSegmentOOBMessage() {
try {
var segment = MemorySegment.allocateNative(10, MemorySession.global());
segment.getAtIndex(ValueLayout.JAVA_INT, 2);
} catch (IndexOutOfBoundsException ex) {
assertTrue(ex.getMessage().contains("Out of bound access"));
assertTrue(ex.getMessage().contains("offset = 8"));
assertTrue(ex.getMessage().contains("length = 4"));
}
}
@Test(dataProvider = "segmentFactories") @Test(dataProvider = "segmentFactories")
public void testAccessModesOfFactories(Supplier<MemorySegment> segmentSupplier) { public void testAccessModesOfFactories(Supplier<MemorySegment> segmentSupplier) {
MemorySegment segment = segmentSupplier.get(); MemorySegment segment = segmentSupplier.get();