提交 0c05828b authored 作者: noelgrandin@gmail.com's avatar noelgrandin@gmail.com

Fix bug which could generate a NegativeArraySizeException when performing large…

Fix bug which could generate a NegativeArraySizeException when performing large (>40M) row union operations (v2)
上级 bbc36837
...@@ -11,7 +11,8 @@ package org.h2.util; ...@@ -11,7 +11,8 @@ package org.h2.util;
*/ */
public abstract class HashBase { public abstract class HashBase {
private static final int MAX_LOAD = 90; /** declared as long so we do long arithmetic so we don't overflow */
private static final long MAX_LOAD = 90;
/** /**
* The bit mask to get the index from the hash code. * The bit mask to get the index from the hash code.
...@@ -98,14 +99,14 @@ public abstract class HashBase { ...@@ -98,14 +99,14 @@ public abstract class HashBase {
protected void reset(int newLevel) { protected void reset(int newLevel) {
// can't exceed 30 or we will generate a negative value for the "len" field // can't exceed 30 or we will generate a negative value for the "len" field
if (newLevel > 30) { if (newLevel > 30) {
newLevel = 30; throw new IllegalStateException("exceeded max size of hash table");
} }
minSize = size * 3 / 4; minSize = size * 3 / 4;
size = 0; size = 0;
level = newLevel; level = newLevel;
len = 2 << level; len = 2 << level;
mask = len - 1; mask = len - 1;
maxSize = (int) (len * MAX_LOAD / 100L); maxSize = (int) (len * MAX_LOAD / 100);
deletedCount = 0; deletedCount = 0;
maxDeleted = 20 + len / 2; maxDeleted = 20 + len / 2;
} }
......
...@@ -45,6 +45,10 @@ public class IntIntHashMap extends HashBase { ...@@ -45,6 +45,10 @@ public class IntIntHashMap extends HashBase {
return; return;
} }
checkSizePut(); checkSizePut();
internalPut(key, value);
}
private void internalPut(int key, int value) {
int index = getIndex(key); int index = getIndex(key);
int plus = 1; int plus = 1;
int deleted = -1; int deleted = -1;
...@@ -116,7 +120,8 @@ public class IntIntHashMap extends HashBase { ...@@ -116,7 +120,8 @@ public class IntIntHashMap extends HashBase {
for (int i = 0; i < oldKeys.length; i++) { for (int i = 0; i < oldKeys.length; i++) {
int k = oldKeys[i]; int k = oldKeys[i];
if (k != 0) { if (k != 0) {
put(k, oldValues[i]); // skip the checkSizePut so we don't end up accidentally recursing
internalPut(k, oldValues[i]);
} }
} }
} }
......
...@@ -46,7 +46,8 @@ public class ValueHashMap<V> extends HashBase { ...@@ -46,7 +46,8 @@ public class ValueHashMap<V> extends HashBase {
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
Value k = oldKeys[i]; Value k = oldKeys[i];
if (k != null && k != ValueNull.DELETED) { if (k != null && k != ValueNull.DELETED) {
put(k, oldValues[i]); // skip the checkSizePut so we don't end up accidentally recursing
internalPut(k, oldValues[i]);
} }
} }
} }
...@@ -63,6 +64,10 @@ public class ValueHashMap<V> extends HashBase { ...@@ -63,6 +64,10 @@ public class ValueHashMap<V> extends HashBase {
*/ */
public void put(Value key, V value) { public void put(Value key, V value) {
checkSizePut(); checkSizePut();
internalPut(key, value);
}
private void internalPut(Value key, V value) {
int index = getIndex(key); int index = getIndex(key);
int plus = 1; int plus = 1;
int deleted = -1; int deleted = -1;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论