Skip to content

Commit 23299da

Browse files
authored
fix(java): fix read primitives error on fill buffer bound (#2064)
## What does this PR do? fix read primitives error on fill buffer bound <!-- Describe the purpose of this PR. --> ## Related issues Closes #2060 ## Does this PR introduce any user-facing change? <!-- If any user-facing interface changes, please [open an issue](https://github.com/apache/fury/issues/new/choose) describing the need to do so and update the document if necessary. --> - [ ] Does this PR introduce any public API change? - [ ] Does this PR introduce any binary protocol compatibility change? ## Benchmark <!-- When the PR has an impact on performance (if you don't know whether the PR will have an impact on performance, you can submit the PR first, and if it will have impact on performance, the code reviewer will explain it), be sure to attach a benchmark data here. -->
1 parent e33a1f7 commit 23299da

File tree

3 files changed

+35
-11
lines changed

3 files changed

+35
-11
lines changed

java/fury-core/src/main/java/org/apache/fury/builder/ObjectCodecBuilder.java

+9-8
Original file line numberDiff line numberDiff line change
@@ -625,14 +625,14 @@ private List<Expression> deserializeUnCompressedPrimitives(
625625
List<Expression> expressions = new ArrayList<>();
626626
int numPrimitiveFields = getNumPrimitiveFields(primitiveGroups);
627627
Literal totalSizeLiteral = Literal.ofInt(totalSize);
628+
// After this check, following read can be totally unsafe without checks
629+
expressions.add(new Invoke(buffer, "checkReadableBytes", totalSizeLiteral));
628630
Expression heapBuffer =
629631
new Invoke(buffer, "getHeapMemory", "heapBuffer", PRIMITIVE_BYTE_ARRAY_TYPE);
630632
Expression readerAddr =
631633
new Invoke(buffer, "getUnsafeReaderAddress", "readerAddr", PRIMITIVE_LONG_TYPE);
632634
expressions.add(heapBuffer);
633635
expressions.add(readerAddr);
634-
// After this check, following read can be totally unsafe without checks
635-
expressions.add(new Invoke(buffer, "checkReadableBytes", totalSizeLiteral));
636636
int acc = 0;
637637
for (List<Descriptor> group : primitiveGroups) {
638638
ListExpression groupExpressions = new ListExpression();
@@ -690,16 +690,17 @@ private List<Expression> deserializeCompressedPrimitives(
690690
Expression bean, Expression buffer, List<List<Descriptor>> primitiveGroups) {
691691
List<Expression> expressions = new ArrayList<>();
692692
int numPrimitiveFields = getNumPrimitiveFields(primitiveGroups);
693-
Expression heapBuffer =
694-
new Invoke(buffer, "getHeapMemory", "heapBuffer", PRIMITIVE_BYTE_ARRAY_TYPE);
695-
expressions.add(heapBuffer);
696693
for (List<Descriptor> group : primitiveGroups) {
697-
ListExpression groupExpressions = new ListExpression();
698-
Expression readerAddr =
699-
new Invoke(buffer, "getUnsafeReaderAddress", "readerAddr", PRIMITIVE_LONG_TYPE);
700694
// After this check, following read can be totally unsafe without checks.
695+
// checkReadableBytes first, `fillBuffer` may create a new heap buffer.
701696
ReplaceStub checkReadableBytesStub = new ReplaceStub();
702697
expressions.add(checkReadableBytesStub);
698+
Expression heapBuffer =
699+
new Invoke(buffer, "getHeapMemory", "heapBuffer", PRIMITIVE_BYTE_ARRAY_TYPE);
700+
expressions.add(heapBuffer);
701+
ListExpression groupExpressions = new ListExpression();
702+
Expression readerAddr =
703+
new Invoke(buffer, "getUnsafeReaderAddress", "readerAddr", PRIMITIVE_LONG_TYPE);
703704
int acc = 0;
704705
boolean compressStarted = false;
705706
for (Descriptor descriptor : group) {

java/fury-core/src/main/java/org/apache/fury/io/FuryInputStream.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,16 @@ public int fillBuffer(int minFillSize) {
7676

7777
private static byte[] growBuffer(int minFillSize, MemoryBuffer buffer) {
7878
int newSize;
79-
int targetSize = buffer.size() + minFillSize;
79+
int size = buffer.size();
80+
int targetSize = size + minFillSize;
8081
newSize =
8182
targetSize < MemoryBuffer.BUFFER_GROW_STEP_THRESHOLD
8283
? targetSize << 2
8384
: (int) Math.min(targetSize * 1.5d, Integer.MAX_VALUE - 8);
8485
byte[] newBuffer = new byte[newSize];
8586
byte[] heapMemory = buffer.getHeapMemory();
86-
System.arraycopy(heapMemory, 0, newBuffer, 0, buffer.size());
87-
buffer.initHeapBuffer(newBuffer, 0, buffer.size());
87+
System.arraycopy(heapMemory, 0, newBuffer, 0, size);
88+
buffer.initHeapBuffer(newBuffer, 0, size);
8889
heapMemory = newBuffer;
8990
return heapMemory;
9091
}

java/fury-core/src/test/java/org/apache/fury/StreamTest.java

+22
Original file line numberDiff line numberDiff line change
@@ -391,4 +391,26 @@ public void testReadNullChunkMapOnFillBound() {
391391
FuryInputStream input = new FuryInputStream(inputStream);
392392
assertEquals(fury.deserialize(input), m);
393393
}
394+
395+
public static class SimpleType {
396+
public double dVal;
397+
398+
public SimpleType() {
399+
dVal = 0.5;
400+
}
401+
}
402+
403+
// For issue https://github.com/apache/fury/issues/2060
404+
@Test
405+
public void testReadPrimitivesOnBufferFillBound() {
406+
Fury fury = builder().build();
407+
fury.register(SimpleType.class);
408+
SimpleType v = new SimpleType();
409+
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
410+
fury.serialize(outputStream, v);
411+
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
412+
FuryInputStream input = new FuryInputStream(inputStream, 11);
413+
SimpleType newValue = (SimpleType) fury.deserialize(input);
414+
Assert.assertEquals(v.dVal, newValue.dVal, 0.001);
415+
}
394416
}

0 commit comments

Comments
 (0)