-
Bug
-
Resolution: Unresolved
-
P4
-
20, 21
-
generic
-
generic
ADDITIONAL SYSTEM INFORMATION :
OpenJDK 20. This bug is OS-independent. It was introduced inJDK-8246095 and the code is not fixed in the latest master of openjdk
A DESCRIPTION OF THE PROBLEM :
AbstractMemorySegmentImpl.mismatch() assumes that any two ranges within the same MemorySegment will contain the exact same bytes. This behavior is not clearly stated in the docs, which refer to Arrays.mismatch, which makes no such assumption.
Suppose one has a MemorySegment containing "bobrob":
```
byte[] u8 = "bobrob".getBytes(StandardCharsets.UTF_8);
var segment = MemorySegment.ofArray(u8);
```
Then `MemorySegment.mismatch(segment, 0, 3, segment, 3, 6)` should return 0 as "bob" and "rob" mismatch at the first byte. The current implementation returns -1 since it assumes that any two ranges within the same segment are equal. See the first if in AbstractMemorySegmentImpl.mismatch (line 636 on master):
```
if (dstImpl == srcImpl) {
srcImpl.checkValidState();
return -1;
}
```
Fix: the condition should instead be `dstImpl == srcImpl && srcFromOffset == dstFromOffset`.
That `if` appeared inJDK-8246095 together with the mismatch method. Since the foreign API is in preview, it would be sensible to change the behavior to align with Arrays.mismatch() rather than changing the javadoc.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
The following code will print "m=-1" if the bug is present, where "m=0" would be the expected result from the docs.
Note: must be run with --enable-preview JVM argument
```
public static void main(String[] args) {
byte[] u8 = "bobrob".getBytes(StandardCharsets.UTF_8);
var segment = MemorySegment.ofArray(u8);
long m = MemorySegment.mismatch(segment, 0, 3, segment, 3, 6);
System.out.printf("m=%d", m);
}
```
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
m=0
(the two ranges mismatch at byte zero, relative to their starts)
ACTUAL -
m=-1
(mismatch() claims the ranges have the same bytes, when they do not)
---------- BEGIN SOURCE ----------
byte[] u8 = "bobrob".getBytes(StandardCharsets.UTF_8);
var segment = MemorySegment.ofArray(u8);
long m = MemorySegment.mismatch(segment, 0, 3, segment, 3, 6);
assertEquals(0, m);
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Manually compare ranges calling MemorySegment.get(JAVA_BYTE, i) in a for loop.
FREQUENCY : always
OpenJDK 20. This bug is OS-independent. It was introduced in
A DESCRIPTION OF THE PROBLEM :
AbstractMemorySegmentImpl.mismatch() assumes that any two ranges within the same MemorySegment will contain the exact same bytes. This behavior is not clearly stated in the docs, which refer to Arrays.mismatch, which makes no such assumption.
Suppose one has a MemorySegment containing "bobrob":
```
byte[] u8 = "bobrob".getBytes(StandardCharsets.UTF_8);
var segment = MemorySegment.ofArray(u8);
```
Then `MemorySegment.mismatch(segment, 0, 3, segment, 3, 6)` should return 0 as "bob" and "rob" mismatch at the first byte. The current implementation returns -1 since it assumes that any two ranges within the same segment are equal. See the first if in AbstractMemorySegmentImpl.mismatch (line 636 on master):
```
if (dstImpl == srcImpl) {
srcImpl.checkValidState();
return -1;
}
```
Fix: the condition should instead be `dstImpl == srcImpl && srcFromOffset == dstFromOffset`.
That `if` appeared in
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
The following code will print "m=-1" if the bug is present, where "m=0" would be the expected result from the docs.
Note: must be run with --enable-preview JVM argument
```
public static void main(String[] args) {
byte[] u8 = "bobrob".getBytes(StandardCharsets.UTF_8);
var segment = MemorySegment.ofArray(u8);
long m = MemorySegment.mismatch(segment, 0, 3, segment, 3, 6);
System.out.printf("m=%d", m);
}
```
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
m=0
(the two ranges mismatch at byte zero, relative to their starts)
ACTUAL -
m=-1
(mismatch() claims the ranges have the same bytes, when they do not)
---------- BEGIN SOURCE ----------
byte[] u8 = "bobrob".getBytes(StandardCharsets.UTF_8);
var segment = MemorySegment.ofArray(u8);
long m = MemorySegment.mismatch(segment, 0, 3, segment, 3, 6);
assertEquals(0, m);
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Manually compare ranges calling MemorySegment.get(JAVA_BYTE, i) in a for loop.
FREQUENCY : always
- relates to
-
JDK-8246095 Tweaks to memory access API
-
- Resolved
-