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

epugh pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git


The following commit(s) were added to refs/heads/branch_10x by this push:
     new 386a247fdd4 SOLR-18239: Fixed NPE during size estimator calculations 
(#4427)
386a247fdd4 is described below

commit 386a247fdd45cf45b385e5df59e8f633c52b32ef
Author: Jalaz Kumar <[email protected]>
AuthorDate: Sat May 16 00:15:57 2026 +0530

    SOLR-18239: Fixed NPE during size estimator calculations (#4427)
    
    Co-authored-by: Eric Pugh <[email protected]>
---
 .../SOLR-18239-fix-npe-size-estimator.yml          |  7 ++++
 .../IgnoreLargeDocumentProcessorFactory.java       |  1 +
 .../IgnoreLargeDocumentProcessorFactoryTest.java   | 10 ++++--
 .../update/processor/MirroringUpdateProcessor.java |  1 +
 .../processor/MirroringUpdateProcessorTest.java    | 37 ++++++++++++++++++++++
 5 files changed, 53 insertions(+), 3 deletions(-)

diff --git a/changelog/unreleased/SOLR-18239-fix-npe-size-estimator.yml 
b/changelog/unreleased/SOLR-18239-fix-npe-size-estimator.yml
new file mode 100644
index 00000000000..05b9993b452
--- /dev/null
+++ b/changelog/unreleased/SOLR-18239-fix-npe-size-estimator.yml
@@ -0,0 +1,7 @@
+title: Fixed NPE in size estimator for null valued fields
+type: fixed
+authors:
+  - name: Jalaz Kumar
+links:
+  - name: SOLR-18239
+    url: https://issues.apache.org/jira/browse/SOLR-18239
diff --git 
a/solr/core/src/java/org/apache/solr/update/processor/IgnoreLargeDocumentProcessorFactory.java
 
b/solr/core/src/java/org/apache/solr/update/processor/IgnoreLargeDocumentProcessorFactory.java
index e7a58d517bb..7b97d04fc84 100644
--- 
a/solr/core/src/java/org/apache/solr/update/processor/IgnoreLargeDocumentProcessorFactory.java
+++ 
b/solr/core/src/java/org/apache/solr/update/processor/IgnoreLargeDocumentProcessorFactory.java
@@ -170,6 +170,7 @@ public class IgnoreLargeDocumentProcessorFactory extends 
UpdateRequestProcessorF
     }
 
     private static long primitiveEstimate(Object obj, long def) {
+      if (obj == null) return def;
       Class<?> clazz = obj.getClass();
       if (clazz.isPrimitive()) {
         return primitiveSizes.get(clazz);
diff --git 
a/solr/core/src/test/org/apache/solr/update/processor/IgnoreLargeDocumentProcessorFactoryTest.java
 
b/solr/core/src/test/org/apache/solr/update/processor/IgnoreLargeDocumentProcessorFactoryTest.java
index 513b0589157..167aaf14568 100644
--- 
a/solr/core/src/test/org/apache/solr/update/processor/IgnoreLargeDocumentProcessorFactoryTest.java
+++ 
b/solr/core/src/test/org/apache/solr/update/processor/IgnoreLargeDocumentProcessorFactoryTest.java
@@ -86,6 +86,7 @@ public class IgnoreLargeDocumentProcessorFactoryTest extends 
SolrTestCase {
 
   @Test
   public void testEstimateObjectSize() {
+    assertEquals(estimate(null), 0);
     assertEquals(estimate("abc"), 6);
     assertEquals(estimate("abcdefgh"), 16);
     List<String> keys = List.of("int", "long", "double", "float", "str");
@@ -99,7 +100,8 @@ public class IgnoreLargeDocumentProcessorFactoryTest extends 
SolrTestCase {
     map.put("double", 12.0);
     map.put("float", 5.0f);
     map.put("str", "duck");
-    assertEquals(estimate(map), 50);
+    map.put("short", null);
+    assertEquals(estimate(map), 60);
 
     SolrInputDocument document = new SolrInputDocument();
     for (Map.Entry<String, Object> entry : map.entrySet()) {
@@ -134,7 +136,8 @@ public class IgnoreLargeDocumentProcessorFactoryTest 
extends SolrTestCase {
     mapWChild.put("double", 12.0);
     mapWChild.put("float", 5.0f);
     mapWChild.put("str", "duck");
-    assertEquals(estimate(mapWChild), 50);
+    mapWChild.put("short", null);
+    assertEquals(estimate(mapWChild), 60);
     Map<String, Object> childMap = new HashMap<>(mapWChild);
 
     SolrInputDocument document = new SolrInputDocument();
@@ -175,7 +178,8 @@ public class IgnoreLargeDocumentProcessorFactoryTest 
extends SolrTestCase {
     mapWChild.put("double", 12.0);
     mapWChild.put("float", 5.0f);
     mapWChild.put("str", "duck");
-    assertEquals(estimate(mapWChild), 50);
+    mapWChild.put("short", null);
+    assertEquals(estimate(mapWChild), 60);
     Map<String, Object> childMap = new HashMap<>(mapWChild);
 
     SolrInputDocument document = new SolrInputDocument();
diff --git 
a/solr/modules/cross-dc/src/java/org/apache/solr/crossdc/update/processor/MirroringUpdateProcessor.java
 
b/solr/modules/cross-dc/src/java/org/apache/solr/crossdc/update/processor/MirroringUpdateProcessor.java
index 3d10b3beb51..54ad07e3d24 100644
--- 
a/solr/modules/cross-dc/src/java/org/apache/solr/crossdc/update/processor/MirroringUpdateProcessor.java
+++ 
b/solr/modules/cross-dc/src/java/org/apache/solr/crossdc/update/processor/MirroringUpdateProcessor.java
@@ -516,6 +516,7 @@ public class MirroringUpdateProcessor extends 
UpdateRequestProcessor {
     }
 
     private static long primitiveEstimate(Object obj, long def) {
+      if (obj == null) return def;
       Class<?> clazz = obj.getClass();
       if (clazz.isPrimitive()) {
         return primitiveSizes.get(clazz);
diff --git 
a/solr/modules/cross-dc/src/test/org/apache/solr/crossdc/update/processor/MirroringUpdateProcessorTest.java
 
b/solr/modules/cross-dc/src/test/org/apache/solr/crossdc/update/processor/MirroringUpdateProcessorTest.java
index b8e01a62efa..77b3adf7a49 100644
--- 
a/solr/modules/cross-dc/src/test/org/apache/solr/crossdc/update/processor/MirroringUpdateProcessorTest.java
+++ 
b/solr/modules/cross-dc/src/test/org/apache/solr/crossdc/update/processor/MirroringUpdateProcessorTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.solr.crossdc.update.processor;
 
+import static 
org.apache.solr.crossdc.update.processor.MirroringUpdateProcessor.ObjectSizeEstimator.estimate;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.Mockito.doAnswer;
@@ -27,6 +28,8 @@ import static org.mockito.Mockito.when;
 
 import io.opentelemetry.api.common.Attributes;
 import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicLong;
@@ -570,6 +573,40 @@ public class MirroringUpdateProcessorTest extends 
SolrTestCaseJ4 {
     assertEquals(1, counters.get("submittedDeleteByQuery").get());
   }
 
+  @Test
+  public void testEstimateObjectSize() {
+    assertEquals(estimate(null), 0);
+    assertEquals(estimate("abc"), 6);
+    assertEquals(estimate("abcdefgh"), 16);
+    List<String> keys = List.of("int", "long", "double", "float", "str");
+    assertEquals(estimate(keys), 42);
+    List<Object> values = List.of(12, 5L, 12.0, 5.0, "duck");
+    assertEquals(estimate(values), 8);
+
+    Map<String, Object> map = new HashMap<>();
+    map.put("int", 12);
+    map.put("long", 5L);
+    map.put("double", 12.0);
+    map.put("float", 5.0f);
+    map.put("str", "duck");
+    map.put("short", null);
+    assertEquals(estimate(map), 60);
+
+    SolrInputDocument document = new SolrInputDocument();
+    for (Map.Entry<String, Object> entry : map.entrySet()) {
+      document.addField(entry.getKey(), entry.getValue());
+    }
+    
assertEquals(MirroringUpdateProcessor.ObjectSizeEstimator.estimate(document), 
estimate(map));
+
+    SolrInputDocument childDocument = new SolrInputDocument();
+    for (Map.Entry<String, Object> entry : map.entrySet()) {
+      childDocument.addField(entry.getKey(), entry.getValue());
+    }
+    document.addChildDocument(childDocument);
+    assertEquals(
+        MirroringUpdateProcessor.ObjectSizeEstimator.estimate(document), 
estimate(map) * 2);
+  }
+
   @Test
   public void testFinish() throws IOException {
     processor.finish();

Reply via email to