From 5bc959263b894435043150e62983964c12a11784 Mon Sep 17 00:00:00 2001 From: Michael McCandless Date: Thu, 9 Sep 2010 12:52:45 +0000 Subject: [PATCH] LUCENE-2633: fix int/long overflow issue in packed ints impl git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@995409 13f79535-47bb-0310-9956-ffa450edef68 --- lucene/CHANGES.txt | 5 +++++ .../apache/lucene/util/packed/Packed32.java | 4 ++-- .../apache/lucene/util/packed/Packed64.java | 4 ++-- .../lucene/util/packed/TestPackedInts.java | 22 +++++++++++++++++++ 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index 51e050a6302..90ac97c2c46 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -243,6 +243,11 @@ Documentation Java NOI behavior when a Thread is interrupted while blocking on IO. (Simon Willnauer, Robert Muir) +Bug fixes + +* LUCENE-2633: PackedInts Packed32 and Packed64 did not support internal + structures larger than 256MB (Toke Eskildsen via Mike McCandless) + ======================= Lucene 3.x (not yet released) ======================= Changes in backwards compatibility policy diff --git a/lucene/src/java/org/apache/lucene/util/packed/Packed32.java b/lucene/src/java/org/apache/lucene/util/packed/Packed32.java index a7289a6026d..c8bb011c209 100644 --- a/lucene/src/java/org/apache/lucene/util/packed/Packed32.java +++ b/lucene/src/java/org/apache/lucene/util/packed/Packed32.java @@ -186,7 +186,7 @@ class Packed32 extends PackedInts.ReaderImpl implements PackedInts.Mutable { * @return the value at the given index. */ public long get(final int index) { - final long majorBitPos = index * bitsPerValue; + final long majorBitPos = (long)index * bitsPerValue; final int elementPos = (int)(majorBitPos >>> BLOCK_BITS); // / BLOCK_SIZE final int bitPos = (int)(majorBitPos & MOD_MASK); // % BLOCK_SIZE); @@ -198,7 +198,7 @@ class Packed32 extends PackedInts.ReaderImpl implements PackedInts.Mutable { public void set(final int index, final long value) { final int intValue = (int)value; - final long majorBitPos = index * bitsPerValue; + final long majorBitPos = (long)index * bitsPerValue; final int elementPos = (int)(majorBitPos >>> BLOCK_BITS); // / BLOCK_SIZE final int bitPos = (int)(majorBitPos & MOD_MASK); // % BLOCK_SIZE); final int base = bitPos * FAC_BITPOS; diff --git a/lucene/src/java/org/apache/lucene/util/packed/Packed64.java b/lucene/src/java/org/apache/lucene/util/packed/Packed64.java index b7c487a213a..b3826676503 100644 --- a/lucene/src/java/org/apache/lucene/util/packed/Packed64.java +++ b/lucene/src/java/org/apache/lucene/util/packed/Packed64.java @@ -177,7 +177,7 @@ class Packed64 extends PackedInts.ReaderImpl implements PackedInts.Mutable { * @return the value at the given index. */ public long get(final int index) { - final long majorBitPos = index * bitsPerValue; + final long majorBitPos = (long)index * bitsPerValue; final int elementPos = (int)(majorBitPos >>> BLOCK_BITS); // / BLOCK_SIZE final int bitPos = (int)(majorBitPos & MOD_MASK); // % BLOCK_SIZE); @@ -188,7 +188,7 @@ class Packed64 extends PackedInts.ReaderImpl implements PackedInts.Mutable { } public void set(final int index, final long value) { - final long majorBitPos = index * bitsPerValue; + final long majorBitPos = (long)index * bitsPerValue; final int elementPos = (int)(majorBitPos >>> BLOCK_BITS); // / BLOCK_SIZE final int bitPos = (int)(majorBitPos & MOD_MASK); // % BLOCK_SIZE); final int base = bitPos * FAC_BITPOS; diff --git a/lucene/src/test/org/apache/lucene/util/packed/TestPackedInts.java b/lucene/src/test/org/apache/lucene/util/packed/TestPackedInts.java index 55e9f07a541..33fb72d788c 100644 --- a/lucene/src/test/org/apache/lucene/util/packed/TestPackedInts.java +++ b/lucene/src/test/org/apache/lucene/util/packed/TestPackedInts.java @@ -232,4 +232,26 @@ public class TestPackedInts extends LuceneTestCase { mutable.set(4, 16); assertEquals("The value #24 should remain unchanged", 31, mutable.get(24)); } + + /* + Check if the structures properly handle the case where + index * bitsPerValue > Integer.MAX_VALUE + + NOTE: this test allocates 256 MB + */ + public void testIntOverflow() { + int INDEX = (int)Math.pow(2, 30)+1; + int BITS = 2; + + Packed32 p32 = new Packed32(INDEX, BITS); + p32.set(INDEX-1, 1); + assertEquals("The value at position " + (INDEX-1) + + " should be correct for Packed32", 1, p32.get(INDEX-1)); + p32 = null; // To free the 256MB used + + Packed64 p64 = new Packed64(INDEX, BITS); + p64.set(INDEX-1, 1); + assertEquals("The value at position " + (INDEX-1) + + " should be correct for Packed64", 1, p64.get(INDEX-1)); + } }