Skip to content

Commit 580c987

Browse files
committed
Add a patch that prevents #548
1 parent 9d4756b commit 580c987

File tree

2 files changed

+48
-4
lines changed

2 files changed

+48
-4
lines changed

src/main/java/com/fasterxml/jackson/core/sym/ByteQuadsCanonicalizer.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public final class ByteQuadsCanonicalizer
1818
{
1919
/**
2020
* Initial size of the primary hash area. Each entry consumes 4 ints (16 bytes),
21-
* and secondary area is same as primary; so default size will use 2kB of memory_tertiaryStart
21+
* and secondary area is same as primary; so default size will use 2kB of memory
2222
* (plus 64x4 or 64x8 (256/512 bytes) for references to Strings, and Strings
2323
* themselves).
2424
*/
@@ -27,7 +27,6 @@ public final class ByteQuadsCanonicalizer
2727

2828
/**
2929
* Let's not expand symbol tables past some maximum size;
30-
* this should protected against OOMEs caused by large documents
3130
* with unique (~= random) names.
3231
* Size is in
3332
*/
@@ -169,7 +168,7 @@ public final class ByteQuadsCanonicalizer
169168

170169
/**
171170
* Offset within {@link #_hashArea} that follows main slots and contains
172-
* quads for longer names (13 bytes or longers), and points to the
171+
* quads for longer names (13 bytes or longer), and points to the
173172
* first available int that may be used for appending quads of the next
174173
* long name.
175174
* Note that long name area follows immediately after the fixed-size
@@ -317,7 +316,8 @@ public ByteQuadsCanonicalizer makeChild(int flags) {
317316
public void release()
318317
{
319318
// we will try to merge if child table has new entries
320-
if (_parent != null && maybeDirty()) {
319+
// 28-Jul-2019, tatu: From [core#548]: do not share if immediate rehash needed
320+
if ((_parent != null) && maybeDirty() && !_needRehash) {
321321
_parent.mergeChild(new TableInfo(this));
322322
// Let's also mark this instance as dirty, so that just in
323323
// case release was too early, there's no corruption of possibly shared data.

src/test/java/com/fasterxml/jackson/core/sym/TestByteBasedSymbols.java

+44
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.io.*;
44
import java.lang.reflect.Field;
5+
import java.util.Random;
56

67
import com.fasterxml.jackson.core.*;
78

@@ -120,6 +121,49 @@ public void testIssue207() throws Exception
120121
p.close();
121122
}
122123

124+
// [core#548]
125+
public void testQuadsIssue548()
126+
{
127+
Random r = new Random(42);
128+
ByteQuadsCanonicalizer root = ByteQuadsCanonicalizer.createRoot();
129+
ByteQuadsCanonicalizer canon = root.makeChild(JsonFactory.Feature.collectDefaults());
130+
131+
int n_collisions = 25;
132+
int[] collisions = new int[n_collisions];
133+
134+
// generate collisions
135+
{
136+
int maybe = r.nextInt();
137+
int hash = canon.calcHash(maybe);
138+
int target = ((hash & (2048-1)) << 2);
139+
140+
for (int i = 0; i < collisions.length; ) {
141+
maybe = r.nextInt();
142+
hash = canon.calcHash(maybe);
143+
int offset = ((hash & (2048-1)) << 2);
144+
145+
if (offset == target) {
146+
collisions[i++] = maybe;
147+
}
148+
}
149+
}
150+
151+
// fill spillover area until _needRehash is true.
152+
for(int i = 0; i < 22 ; i++) {
153+
canon.addName(Integer.toString(i), collisions[i]);
154+
}
155+
// canon._needRehash is now true, since the spillover is full
156+
157+
// release table to update tableinfo with canon's data
158+
canon.release();
159+
160+
// new table pulls data from new tableinfo, that has a full spillover, but set _needRehash to false
161+
canon = root.makeChild(JsonFactory.Feature.collectDefaults());
162+
163+
// canon._needRehash == false, so this will try to add another item to the spillover area, even though it is full
164+
canon.addName(Integer.toString(22), collisions[22]);
165+
}
166+
123167
/*
124168
/**********************************************************
125169
/* Helper methods

0 commit comments

Comments
 (0)