Skip to content

Commit 6e11243

Browse files
committed
Fix ByteBuffer copy offsets for sliced and read-only buffers
Signed-off-by: Jaehong Park <105151063+PHJ2000@users.noreply.github.com>
1 parent a1b994c commit 6e11243

2 files changed

Lines changed: 74 additions & 3 deletions

File tree

‎msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -556,16 +556,16 @@ public void putByteBuffer(int index, ByteBuffer src, int len)
556556
}
557557
else if (src.hasArray()) {
558558
byte[] srcArray = src.array();
559-
unsafe.copyMemory(srcArray, ARRAY_BYTE_BASE_OFFSET + src.position(), base, address + index, len);
559+
unsafe.copyMemory(srcArray, ARRAY_BYTE_BASE_OFFSET + src.arrayOffset() + src.position(), base, address + index, len);
560560
src.position(src.position() + len);
561561
}
562562
else {
563563
if (hasArray()) {
564-
src.get((byte[]) base, index, len);
564+
src.get((byte[]) base, arrayOffset() + index, len);
565565
}
566566
else {
567567
for (int i = 0; i < len; ++i) {
568-
unsafe.putByte(base, address + index, src.get());
568+
unsafe.putByte(base, address + index + i, src.get());
569569
}
570570
}
571571
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
//
2+
// MessagePack for Java
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
//
16+
package org.msgpack.core.buffer
17+
18+
import java.nio.ByteBuffer
19+
import wvlet.airspec.AirSpec
20+
21+
class MessageBufferCopyTest extends AirSpec:
22+
private def byteBuffer(data: Array[Byte], direct: Boolean): ByteBuffer =
23+
if direct then
24+
val buffer = ByteBuffer.allocateDirect(data.length)
25+
buffer.put(data)
26+
buffer.flip()
27+
buffer
28+
else
29+
ByteBuffer.wrap(data)
30+
31+
for
32+
directSource <- Seq(false, true)
33+
readOnly <- Seq(false, true)
34+
directDestination <- Seq(false, true)
35+
sourceOffset <- Seq(0, 2)
36+
destinationOffset <- Seq(0, 3)
37+
length <- Seq(0, 3)
38+
do
39+
test(
40+
s"copy directSource=$directSource readOnly=$readOnly directDestination=$directDestination sourceOffset=$sourceOffset destinationOffset=$destinationOffset length=$length"
41+
) {
42+
val data = Array.tabulate[Byte](12)(i => (10 + i).toByte)
43+
val sourceBuffer = byteBuffer(data, directSource)
44+
sourceBuffer.position(sourceOffset)
45+
val sourceSlice = sourceBuffer.slice()
46+
val source =
47+
if readOnly then
48+
sourceSlice.asReadOnlyBuffer()
49+
else
50+
sourceSlice
51+
source.position(1)
52+
source.limit(6)
53+
source.mark()
54+
55+
val destination = MessageBuffer.wrap(byteBuffer(Array.fill[Byte](12)(-1), directDestination))
56+
val destinationSlice = destination.slice(destinationOffset, 8)
57+
destinationSlice.putByteBuffer(2, source, length)
58+
59+
val expected = Array.fill[Byte](12)(-1)
60+
Array.copy(data, sourceOffset + 1, expected, destinationOffset + 2, length)
61+
destination.toByteArray() shouldBe expected
62+
source.position() shouldBe 1 + length
63+
source.limit() shouldBe 6
64+
source.reset()
65+
source.position() shouldBe 1
66+
sourceBuffer.position() shouldBe sourceOffset
67+
}
68+
69+
end for
70+
71+
end MessageBufferCopyTest

0 commit comments

Comments
 (0)