8321467: MemorySegment.setString(long, String, Charset) throws IAE(Misaligned access)

Reviewed-by: pminborg
This commit is contained in:
Maurizio Cimadamore 2023-12-07 12:51:42 +00:00
parent c087e9174e
commit 42bb852696
2 changed files with 50 additions and 13 deletions

View File

@ -82,7 +82,7 @@ public final class StringSupport {
private static void writeShort(MemorySegment segment, long offset, Charset charset, String string) { private static void writeShort(MemorySegment segment, long offset, Charset charset, String string) {
int bytes = copyBytes(string, segment, charset, offset); int bytes = copyBytes(string, segment, charset, offset);
segment.set(JAVA_SHORT, offset + bytes, (short)0); segment.set(JAVA_SHORT_UNALIGNED, offset + bytes, (short)0);
} }
private static String readInt(MemorySegment segment, long offset, Charset charset) { private static String readInt(MemorySegment segment, long offset, Charset charset) {
@ -94,7 +94,7 @@ public final class StringSupport {
private static void writeInt(MemorySegment segment, long offset, Charset charset, String string) { private static void writeInt(MemorySegment segment, long offset, Charset charset, String string) {
int bytes = copyBytes(string, segment, charset, offset); int bytes = copyBytes(string, segment, charset, offset);
segment.set(JAVA_INT, offset + bytes, 0); segment.set(JAVA_INT_UNALIGNED, offset + bytes, 0);
} }
/** /**
@ -222,7 +222,7 @@ public final class StringSupport {
int offset = 0; int offset = 0;
for (; offset < headCount; offset += Short.BYTES) { for (; offset < headCount; offset += Short.BYTES) {
short curr = segment.get(JAVA_SHORT, start + offset); short curr = segment.get(JAVA_SHORT_UNALIGNED, start + offset);
if (curr == 0) { if (curr == 0) {
return offset; return offset;
} }

View File

@ -22,8 +22,6 @@
* *
*/ */
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.foreign.Arena; import java.lang.foreign.Arena;
import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.FunctionDescriptor;
import java.lang.foreign.Linker; import java.lang.foreign.Linker;
@ -33,16 +31,12 @@ import java.lang.foreign.SegmentAllocator;
import java.lang.foreign.ValueLayout; import java.lang.foreign.ValueLayout;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.util.ArrayList;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.function.Consumer;
import java.util.function.UnaryOperator; import java.util.function.UnaryOperator;
import jdk.internal.foreign.StringSupport; import jdk.internal.foreign.StringSupport;
@ -333,6 +327,27 @@ public class TestStringEncoding {
} }
} }
@Test(dataProvider = "charsetsAndSegments")
public void testStringGetWithCharset(Charset charset, MemorySegment segment) {
for (int offset = 0 ; offset < Long.BYTES ; offset++) {
segment.getString(offset, charset);
}
}
@Test(dataProvider = "charsetsAndSegments")
public void testStringSetWithCharset(Charset charset, MemorySegment segment) {
for (int offset = 0 ; offset < Long.BYTES ; offset++) {
segment.setString(offset, "H", charset);
}
}
@Test(dataProvider = "charsetsAndSegments")
public void testStringAllocateFromWithCharset(Charset charset, MemorySegment segment) {
for (int offset = 0 ; offset < Long.BYTES ; offset++) {
SegmentAllocator.prefixAllocator(segment.asSlice(offset)).allocateFrom("H", charset);
}
}
@DataProvider @DataProvider
public static Object[][] strings() { public static Object[][] strings() {
return new Object[][]{ return new Object[][]{
@ -361,7 +376,7 @@ public class TestStringEncoding {
.allMatch(c -> Character.isLetterOrDigit((char) c)); .allMatch(c -> Character.isLetterOrDigit((char) c));
} }
boolean isStandard(Charset charset) { static boolean isStandard(Charset charset) {
for (Field standardCharset : StandardCharsets.class.getDeclaredFields()) { for (Field standardCharset : StandardCharsets.class.getDeclaredFields()) {
try { try {
if (standardCharset.get(null) == charset) { if (standardCharset.get(null) == charset) {
@ -374,9 +389,9 @@ public class TestStringEncoding {
return false; return false;
} }
List<Charset> standardCharsets() { static List<Charset> standardCharsets() {
return Charset.availableCharsets().values().stream() return Charset.availableCharsets().values().stream()
.filter(this::isStandard) .filter(TestStringEncoding::isStandard)
.toList(); .toList();
} }
@ -456,4 +471,26 @@ public class TestStringEncoding {
} }
} }
static MemorySegment[] heapSegments() {
return new MemorySegment[]{
MemorySegment.ofArray(new byte[80]),
MemorySegment.ofArray(new char[40]),
MemorySegment.ofArray(new short[40]),
MemorySegment.ofArray(new int[20]),
MemorySegment.ofArray(new float[20]),
MemorySegment.ofArray(new long[10]),
MemorySegment.ofArray(new double[10])
};
}
@DataProvider
public static Object[][] charsetsAndSegments() {
List<Object[]> values = new ArrayList<>();
for (Charset charset : standardCharsets()) {
for (MemorySegment heapSegment : heapSegments()) {
values.add(new Object[] { charset, heapSegment });
}
}
return values.toArray(Object[][]::new);
}
} }