@@ -78,14 +78,12 @@ public final class CharsToNameCanonicalizer
78
78
/**
79
79
* Also: to thwart attacks based on hash collisions (which may or may not
80
80
* be cheap to calculate), we will need to detect "too long"
81
- * collision chains. Let's start with static value of 255 entries
81
+ * collision chains. Let's start with static value of 100 entries
82
82
* for the longest legal chain.
83
83
*<p>
84
84
* Note: longest chain we have been able to produce without malicious
85
85
* intent has been 38 (with "com.fasterxml.jackson.core.main.TestWithTonsaSymbols");
86
86
* our setting should be reasonable here.
87
- *<p>
88
- * Also note that value was lowered from 255 (2.3 and earlier) to 100 for 2.4
89
87
*
90
88
* @since 2.1
91
89
*/
@@ -481,7 +479,7 @@ private String _addSymbol(char[] buffer, int start, int len, int h, int index)
481
479
_hashShared = false ;
482
480
} else if (_size >= _sizeThreshold ) { // Need to expand?
483
481
rehash ();
484
- // Need to recalc hash; rare occurence (index mask has been
482
+ // Need to recalc hash; rare occurrence (index mask has been
485
483
// recalculated as part of rehash)
486
484
index = _hashToIndex (calcHash (buffer , start , len ));
487
485
}
@@ -501,7 +499,7 @@ private String _addSymbol(char[] buffer, int start, int len, int h, int index)
501
499
if (collLen > MAX_COLL_CHAIN_LENGTH ) {
502
500
// 23-May-2014, tatu: Instead of throwing an exception right away,
503
501
// let's handle in bit smarter way.
504
- _handleSpillOverflow (bix , newB );
502
+ _handleSpillOverflow (bix , newB , index );
505
503
} else {
506
504
_buckets [bix ] = newB ;
507
505
_longestCollisionList = Math .max (collLen , _longestCollisionList );
@@ -510,27 +508,36 @@ private String _addSymbol(char[] buffer, int start, int len, int h, int index)
510
508
return newSymbol ;
511
509
}
512
510
513
- private void _handleSpillOverflow (int bindex , Bucket newBucket )
511
+ /**
512
+ * Method called when an overflow bucket has hit the maximum expected length:
513
+ * this may be a case of DoS attack. Deal with it based on settings by either
514
+ * clearing up bucket (to avoid indefinite expansion) or throwing exception.
515
+ * Currently the first overflow for any single bucket DOES NOT throw an exception,
516
+ * only second time (per symbol table instance)
517
+ */
518
+ private void _handleSpillOverflow (int bucketIndex , Bucket newBucket , int mainIndex )
514
519
{
515
520
if (_overflows == null ) {
516
521
_overflows = new BitSet ();
517
- _overflows .set (bindex );
522
+ _overflows .set (bucketIndex );
518
523
} else {
519
- if (_overflows .get (bindex )) {
520
- // Has happened once already, so not a coincident ...
524
+ if (_overflows .get (bucketIndex )) {
525
+ // Has happened once already for this bucket index , so probably not coincidental ...
521
526
if (JsonFactory .Feature .FAIL_ON_SYMBOL_HASH_OVERFLOW .enabledIn (_flags )) {
522
527
reportTooManyCollisions (MAX_COLL_CHAIN_LENGTH );
523
528
}
524
- // but even if we don't fail, we will stop canonicalizing:
529
+ // but even if we don't fail, we will stop canonicalizing as safety measure
530
+ // (so as not to cause problems with PermGen)
525
531
_canonicalize = false ;
526
532
} else {
527
- _overflows .set (bindex );
533
+ _overflows .set (bucketIndex );
528
534
}
529
535
}
536
+
530
537
// regardless, if we get this far, clear up the bucket, adjust size appropriately.
531
- _symbols [bindex + bindex ] = newBucket .symbol ;
532
- _buckets [bindex ] = null ;
533
- // newBucket contains new symbol; but we wil
538
+ _symbols [mainIndex ] = newBucket .symbol ;
539
+ _buckets [bucketIndex ] = null ;
540
+ // newBucket contains new symbol; but we will
534
541
_size -= (newBucket .length );
535
542
// we could calculate longest; but for now just mark as invalid
536
543
_longestCollisionList = -1 ;
0 commit comments