Skip to content

Commit 0df0579

Browse files
prevent packer's buffer from getting into unmarked state
1 parent e8deb7b commit 0df0579

2 files changed

Lines changed: 65 additions & 3 deletions

File tree

dd-trace-core/src/main/java/datadog/trace/core/serialization/msgpack/Packer.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,18 @@ public Packer(Codec codec, ByteBufferConsumer sink, ByteBuffer buffer) {
6060
this.codec = codec;
6161
this.sink = sink;
6262
this.buffer = buffer;
63-
this.buffer.position(MAX_ARRAY_HEADER_SIZE);
64-
buffer.mark();
63+
initBuffer();
6564
}
6665

6766
public Packer(ByteBufferConsumer sink, ByteBuffer buffer) {
6867
this(Codec.INSTANCE, sink, buffer);
6968
}
7069

70+
private void initBuffer() {
71+
this.buffer.position(MAX_ARRAY_HEADER_SIZE);
72+
buffer.mark();
73+
}
74+
7175
@Override
7276
public <T> void format(T message, Mapper<T> mapper) {
7377
try {
@@ -118,7 +122,7 @@ public void flush() {
118122
writeArrayHeader(messageCount);
119123
buffer.position(pos);
120124
sink.accept(messageCount, buffer.slice());
121-
buffer.position(MAX_ARRAY_HEADER_SIZE);
125+
initBuffer();
122126
buffer.limit(buffer.capacity());
123127
messageCount = 0;
124128
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package datadog.trace.core.serialization.msgpack;
2+
3+
import java.nio.BufferOverflowException;
4+
import java.nio.ByteBuffer;
5+
import java.nio.InvalidMarkException;
6+
import java.util.concurrent.ThreadLocalRandom;
7+
import org.junit.Assert;
8+
import org.junit.Test;
9+
import org.junit.runner.RunWith;
10+
import org.junit.runners.Parameterized;
11+
12+
@RunWith(Parameterized.class)
13+
public class VerifyThatPackerDoesNotThrowInvalidMarkException {
14+
15+
@Parameterized.Parameters
16+
public static Object[][] bufferSizes() {
17+
return new Object[][] {{10}, {16}, {100}, {128}, {1000}, {1024}};
18+
}
19+
20+
private final int bufferSize;
21+
22+
public VerifyThatPackerDoesNotThrowInvalidMarkException(int bufferSize) {
23+
this.bufferSize = bufferSize;
24+
}
25+
26+
@Test
27+
public void provokeInvalidMarkException() {
28+
ByteBuffer buffer = ByteBuffer.allocate(bufferSize);
29+
Packer packer =
30+
new Packer(
31+
new ByteBufferConsumer() {
32+
@Override
33+
public void accept(int messageCount, ByteBuffer buffer) {}
34+
},
35+
buffer);
36+
Mapper<byte[]> mapper =
37+
new Mapper<byte[]>() {
38+
@Override
39+
public void map(byte[] data, Writable packer) {
40+
packer.writeBinary(data, 0, data.length);
41+
}
42+
};
43+
int position = buffer.position();
44+
int length = 0;
45+
for (int i = 0; i < 10_000; ++i) {
46+
try {
47+
byte[] message = new byte[ThreadLocalRandom.current().nextInt(0, bufferSize * 2)];
48+
position = buffer.position();
49+
length = message.length;
50+
packer.format(message, mapper);
51+
} catch (BufferOverflowException e) {
52+
// acceptable, need to be able to handle data larger than the limit
53+
} catch (InvalidMarkException e) {
54+
Assert.fail(e.getMessage() + " " + position + " " + length);
55+
}
56+
}
57+
}
58+
}

0 commit comments

Comments
 (0)