Skip to content

Commit

Permalink
Merge branch '2.15'
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Mar 14, 2023
2 parents f8cdc7c + ff8b1cc commit f17ca08
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 42 deletions.
2 changes: 2 additions & 0 deletions release-notes/VERSION-2.x
Expand Up @@ -37,6 +37,8 @@ JSON library.
allow for deferred decoding in some cases
#921: Add `JsonFactory.Feature` to disable charset detection
(contributed by @yawkat)
#948: Use `StreamConstraintsException` in name canonicalizers
(contributed by @pjfanning)
- Build uses package type "jar" but still produces valid OSGi bundle
(changed needed to keep class timestamps with Reproducible Build)

Expand Down
67 changes: 50 additions & 17 deletions src/main/java/tools/jackson/core/sym/ByteQuadsCanonicalizer.java
Expand Up @@ -3,7 +3,7 @@
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicReference;

import tools.jackson.core.exc.StreamReadException;
import tools.jackson.core.exc.StreamConstraintsException;
import tools.jackson.core.json.JsonFactory;
import tools.jackson.core.util.InternCache;

Expand Down Expand Up @@ -858,7 +858,13 @@ private boolean _verifyLongName2(int[] q, int qlen, int spillOffset)
/**********************************************************
*/

public String addName(String name, int q1) {
/**
* @param name
* @param q1
* @return name (possibly interned)
* @throws StreamConstraintsException if the constraint exceptions
*/
public String addName(String name, int q1) throws StreamConstraintsException {
_verifySharing();
if (_intern) {
name = InternCache.instance.intern(name);
Expand All @@ -871,7 +877,14 @@ public String addName(String name, int q1) {
return name;
}

public String addName(String name, int q1, int q2) {
/**
* @param name
* @param q1
* @param q2
* @return name (possibly interned)
* @throws StreamConstraintsException if the constraint exceptions
*/
public String addName(String name, int q1, int q2) throws StreamConstraintsException {
_verifySharing();
if (_intern) {
name = InternCache.instance.intern(name);
Expand All @@ -891,7 +904,15 @@ public String addName(String name, int q1, int q2) {
return name;
}

public String addName(String name, int q1, int q2, int q3) {
/**
* @param name
* @param q1
* @param q2
* @param q3
* @return name (possibly interned)
* @throws StreamConstraintsException if the constraint exceptions
*/
public String addName(String name, int q1, int q2, int q3) throws StreamConstraintsException {
_verifySharing();
if (_intern) {
name = InternCache.instance.intern(name);
Expand All @@ -906,7 +927,14 @@ public String addName(String name, int q1, int q2, int q3) {
return name;
}

public String addName(String name, int[] q, int qlen)
/**
* @param name
* @param q
* @param qlen
* @return name (possibly interned)
* @throws StreamConstraintsException if the constraint exceptions
*/
public String addName(String name, int[] q, int qlen) throws StreamConstraintsException
{
_verifySharing();
if (_intern) {
Expand All @@ -915,7 +943,8 @@ public String addName(String name, int[] q, int qlen)
int offset;

switch (qlen) {
case 1: {
case 1:
{
offset = _findOffsetForAdd(calcHash(q[0]));
_hashArea[offset] = q[0];
_hashArea[offset+3] = 1;
Expand Down Expand Up @@ -961,9 +990,9 @@ private void _verifySharing()
// parent tables
if (_parent == null) {
if (_count == 0) { // root
throw new IllegalStateException("Cannot add names to Root symbol table");
throw new IllegalStateException("Internal error: Cannot add names to Root symbol table");
}
throw new IllegalStateException("Cannot add names to Placeholder symbol table");
throw new IllegalStateException("Internal error: Cannot add names to Placeholder symbol table");
}

_hashArea = Arrays.copyOf(_hashArea, _hashArea.length);
Expand All @@ -975,7 +1004,7 @@ private void _verifySharing()
/**
* Method called to find the location within hash table to add a new symbol in.
*/
private int _findOffsetForAdd(int hash)
private int _findOffsetForAdd(int hash) throws StreamConstraintsException
{
// first, check the primary: if slot found, no need for resize
int offset = _calcOffset(hash);
Expand Down Expand Up @@ -1030,7 +1059,7 @@ private int _findOffsetForAdd(int hash)
}

// @since 2.10
private int _resizeAndFindOffsetForAdd(int hash)
private int _resizeAndFindOffsetForAdd(int hash) throws StreamConstraintsException
{
// First things first: we need to resize+rehash (or, if too big, nuke contents)
rehash();
Expand Down Expand Up @@ -1158,10 +1187,16 @@ public int calcHash(int q1, int q2, int q3)
return hash;
}

/**
* @param q int array
* @param qlen length
* @return hash
* @throws IllegalArgumentException if <code>qlen</code> is less than 4
*/
public int calcHash(int[] q, int qlen)
{
if (qlen < 4) {
throw new IllegalArgumentException();
throw new IllegalArgumentException("qlen is too short, needs to be at least 4");
}
/* And then change handling again for "multi-quad" case; mostly
* to make calculation of collisions less fun. For example,
Expand Down Expand Up @@ -1195,7 +1230,7 @@ public int calcHash(int[] q, int qlen)
/**********************************************************
*/

private void rehash()
private void rehash() throws StreamConstraintsException
{
// Note: since we'll make copies, no need to unshare, can just mark as such:
_hashShared = false;
Expand Down Expand Up @@ -1272,7 +1307,7 @@ private void rehash()
// Sanity checks: since corruption difficult to detect, assert explicitly
// with production code
if (copyCount != oldCount) {
throw new IllegalStateException("Failed rehash(): old count="+oldCount+", copyCount="+copyCount);
throw new IllegalStateException("Internal error: Failed rehash(), old count="+oldCount+", copyCount="+copyCount);
}
}

Expand Down Expand Up @@ -1308,15 +1343,13 @@ private final int _spilloverStart() {
return (offset << 3) - offset;
}

protected void _reportTooManyCollisions()
protected void _reportTooManyCollisions() throws StreamConstraintsException
{
// First: do not fuzz about small symbol tables; may get balanced by doubling up
if (_hashSize <= 1024) { // would have spill-over area of 128 entries
return;
}
// 20-Mar-2021, tatu: [core#686]: should use Jackson-specific exception
// (to use new "processing limit" exception when available)
throw new StreamReadException(null,
throw new StreamConstraintsException(
"Spill-over slots in symbol table with "+_count
+" entries, hash area of "+_hashSize+" slots is now full (all "
+(_hashSize >> 3)+" slots -- suspect a DoS attack based on hash collisions."
Expand Down
Expand Up @@ -4,7 +4,7 @@
import java.util.BitSet;
import java.util.concurrent.atomic.AtomicReference;

import tools.jackson.core.exc.StreamReadException;
import tools.jackson.core.exc.StreamConstraintsException;
import tools.jackson.core.json.JsonFactory;
import tools.jackson.core.util.InternCache;

Expand Down Expand Up @@ -517,7 +517,7 @@ private String _addSymbol(char[] buffer, int start, int len, int h, int index)
* Method called when an overflow bucket has hit the maximum expected length:
* this may be a case of DoS attack. Deal with it based on settings by either
* clearing up bucket (to avoid indefinite expansion) or throwing exception.
* Currently the first overflow for any single bucket DOES NOT throw an exception,
* Currently, the first overflow for any single bucket DOES NOT throw an exception,
* only second time (per symbol table instance)
*/
private void _handleSpillOverflow(int bucketIndex, Bucket newBucket, int mainIndex)
Expand Down Expand Up @@ -698,10 +698,8 @@ private void rehash() {
}
}

// 20-Mar-2021, tatu: [core#686]: should use Jackson-specific exception
// (to use new "processing limit" exception when available)
protected void _reportTooManyCollisions(int maxLen) {
throw new StreamReadException(null,
throw new StreamConstraintsException(
"Longest collision chain in symbol table (of size "+_size
+") now exceeds maximum, "+maxLen+" -- suspect a DoS attack based on hash collisions."
+" You can disable the check via `TokenStreamFactory.Feature.FAIL_ON_SYMBOL_HASH_OVERFLOW`");
Expand All @@ -727,8 +725,9 @@ protected void verifyInternalConsistency() {
}
}
if (count != _size) {
throw new IllegalStateException(String.format("Internal error: expected internal size %d vs calculated count %d",
_size, count));
throw new IllegalStateException(
String.format("Internal error: expected internal size %d vs calculated count %d",
_size, count));
}
}

Expand Down
Expand Up @@ -2,6 +2,7 @@

import java.io.*;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.Random;

import tools.jackson.core.*;
Expand Down Expand Up @@ -116,13 +117,13 @@ public void testIssue207() throws Exception
}
stringBuilder.append("\n}");

JsonParser p = jsonF.createParser(ObjectReadContext.empty(), stringBuilder.toString().getBytes("UTF-8"));
JsonParser p = jsonF.createParser(ObjectReadContext.empty(), stringBuilder.toString().getBytes(StandardCharsets.UTF_8));
while (p.nextToken() != null) { }
p.close();
}

// [core#548]
public void testQuadsIssue548()
public void testQuadsIssue548() throws Exception
{
Random r = new Random(42);
ByteQuadsCanonicalizer root = ByteQuadsCanonicalizer.createRoot();
Expand Down Expand Up @@ -170,9 +171,9 @@ public void testQuadsIssue548()
/**********************************************************
*/

protected JsonParser createParser(JsonFactory jf, String input) throws IOException
protected JsonParser createParser(JsonFactory jf, String input) throws Exception
{
byte[] data = input.getBytes("UTF-8");
byte[] data = input.getBytes(StandardCharsets.UTF_8);
InputStream is = new ByteArrayInputStream(data);
return jf.createParser(ObjectReadContext.empty(), is);
}
Expand Down
12 changes: 0 additions & 12 deletions src/test/java/tools/jackson/core/sym/TestHashCollisionChars.java
Expand Up @@ -153,18 +153,6 @@ void printString(String s) {
System.out.println(s.length() + " " + s.hashCode() + " \"" + s + "\"");
}

String asIntArray(String s) {
StringBuilder result = new StringBuilder().append("[");
for (int c = 0; c < s.length(); c++) {
if (c > 0) {
result.append(", ");
}
result.append((int) s.charAt(c));
}
result.append("]");
return result.toString();
}

}

public static void main(String[] args) {
Expand Down
5 changes: 3 additions & 2 deletions src/test/java/tools/jackson/core/sym/TestSymbolTables.java
Expand Up @@ -3,6 +3,7 @@
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

import tools.jackson.core.*;
import tools.jackson.core.json.JsonFactory;
Expand All @@ -15,7 +16,7 @@ public class TestSymbolTables extends tools.jackson.core.BaseTest
{
// Test for verifying stability of hashCode, wrt collisions, using
// synthetic field name generation and character-based input
public void testSyntheticWithChars()
public void testSyntheticWithChars() throws IOException
{
// pass seed, to keep results consistent:
CharsToNameCanonicalizer symbols = CharsToNameCanonicalizer.createRoot(1).makeChild(-1);
Expand Down Expand Up @@ -109,7 +110,7 @@ public void testThousandsOfSymbolsWithNew() throws IOException
final int SEED = 33333;

ByteQuadsCanonicalizer symbolsBRoot = ByteQuadsCanonicalizer.createRoot(SEED);
final Charset utf8 = Charset.forName("UTF-8");
final Charset utf8 = StandardCharsets.UTF_8;
int exp = 0;
ByteQuadsCanonicalizer symbolsB = null;

Expand Down

0 comments on commit f17ca08

Please sign in to comment.