You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by zh...@apache.org on 2026/06/15 14:39:33 UTC

(lucene) branch branch_10x updated: Fix RoaringDocIdSet#add(min, max) corruption at exactly 4096 block cardinality (#16256)

This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/lucene.git


The following commit(s) were added to refs/heads/branch_10x by this push:
     new 52028df1511 Fix RoaringDocIdSet#add(min, max) corruption at exactly 4096 block cardinality (#16256)
52028df1511 is described below

commit 52028df1511ed36aee07ab288b5603456a531dd4
Author: Zhang Chao <80...@qq.com>
AuthorDate: Mon Jun 15 20:05:59 2026 +0800

    Fix RoaringDocIdSet#add(min, max) corruption at exactly 4096 block cardinality (#16256)
    
    * Fix RoaringDocIdSet range-add corruption at exactly 4096 block cardinality
    
    (cherry picked from commit 136fbb344c9da2bab7c3ad50323f7b739ebdaaee)
---
 lucene/CHANGES.txt                                      |  2 +-
 .../java/org/apache/lucene/util/RoaringDocIdSet.java    |  2 +-
 .../org/apache/lucene/util/TestRoaringDocIdSet.java     | 17 +++++++++++++++++
 3 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index 73c8244ad6c..66d2a83d0b4 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -219,7 +219,7 @@ Optimizations
 
 * GITHUB#16080: Add a BulkScrer implementation spcialized for filters that match dense ranges. (Ignacio Vera)
 
-* GITHUB#16081: Implement LeafCollector#collectRange in the collectors used in LRUCache. (Ignacio Vera)
+* GITHUB#16081, GITHUB#16256: Implement LeafCollector#collectRange in the collectors used in LRUCache. (Ignacio Vera, Zhang Chao)
 
 * GITHUB#16084: Added range encoding to  RoaringDocIdSet. (Ignacio Vera)
 
diff --git a/lucene/core/src/java/org/apache/lucene/util/RoaringDocIdSet.java b/lucene/core/src/java/org/apache/lucene/util/RoaringDocIdSet.java
index ccb725b4bb3..9e354e7e2c5 100644
--- a/lucene/core/src/java/org/apache/lucene/util/RoaringDocIdSet.java
+++ b/lucene/core/src/java/org/apache/lucene/util/RoaringDocIdSet.java
@@ -199,7 +199,7 @@ public class RoaringDocIdSet extends DocIdSet {
       assert (toDocExclusive >>> 16) == block || toDocExclusive == (block + 1) << 16;
       assert fromDoc < toDocExclusive;
       final int span = toDocExclusive - fromDoc;
-      if (currentBlockCardinality + span < MAX_ARRAY_LENGTH) {
+      if (currentBlockCardinality + span <= MAX_ARRAY_LENGTH) {
         for (int d = fromDoc; d < toDocExclusive; d++) {
           buffer[currentBlockCardinality++] = (short) d;
         }
diff --git a/lucene/core/src/test/org/apache/lucene/util/TestRoaringDocIdSet.java b/lucene/core/src/test/org/apache/lucene/util/TestRoaringDocIdSet.java
index 30582da3e47..59e449f8e4c 100644
--- a/lucene/core/src/test/org/apache/lucene/util/TestRoaringDocIdSet.java
+++ b/lucene/core/src/test/org/apache/lucene/util/TestRoaringDocIdSet.java
@@ -198,6 +198,23 @@ public class TestRoaringDocIdSet extends BaseDocIdSetTestCase<RoaringDocIdSet> {
     assertEquals(maxDoc, expected, b.build());
   }
 
+  public void testAddRangeBlockCardinalityAtSparseBufferCapacity() throws IOException {
+    int maxDoc = 5_000;
+    // Cover the boundary at the sparse buffer capacity
+    for (int blockCardinality : new int[] {4095, 4096, 4097}) {
+      BitSet expected = new BitSet(maxDoc);
+      expected.set(0);
+
+      int docsInRange = blockCardinality - 1; // contiguous-range after the singleton at doc 0
+      int rangeEnd = 2 + docsInRange; // added via the contiguous-range add(min, max)
+      expected.set(2, rangeEnd);
+      RoaringDocIdSet.Builder b = new RoaringDocIdSet.Builder(maxDoc);
+      b.add(0);
+      b.add(2, rangeEnd);
+      assertEquals(maxDoc, expected, b.build());
+    }
+  }
+
   public void testAddRangeEmptyNoOp() throws IOException {
     int maxDoc = 100;
     RoaringDocIdSet.Builder b = new RoaringDocIdSet.Builder(maxDoc);