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

jmclean pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new 0372c01df9 [#10125] fix(server): prevent NPE when statistics update 
request body is null (#10190)
0372c01df9 is described below

commit 0372c01df95b3a271235a7a048db5920a547f8f2
Author: ChangJun Rho <[email protected]>
AuthorDate: Wed Apr 8 14:02:42 2026 +0900

    [#10125] fix(server): prevent NPE when statistics update request body is 
null (#10190)
    
    Summary
    - Added an explicit null check for `StatisticsUpdateRequest` in
    `StatisticOperations.updateStatistics(...)`
    - Returned a proper client error (`IllegalArgumentException` -> `400
    BAD_REQUEST`) for null request bodies
    - Made error handling null-safe to avoid a secondary NPE in the catch
    path
    - Refactored request validation/statistic-name extraction into helper
    methods for readability
    - Added a regression test for `PUT /statistics` with JSON `null` body
    
    Verification
    - Ran:
    `export JAVA_HOME=$(/usr/libexec/java_home -v 17); ./gradlew
    :server:test --tests
    org.apache.gravitino.server.web.rest.TestStatisticOperations -PskipITs`
    - `TestStatisticOperations` passed locally
    
    Fix: #10125
    
    Feedback and suggestions are very welcome. Thank you!
---
 .../server/web/rest/StatisticOperations.java       |  6 +++++
 .../server/web/rest/TestStatisticOperations.java   | 29 ++++++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git 
a/server/src/main/java/org/apache/gravitino/server/web/rest/StatisticOperations.java
 
b/server/src/main/java/org/apache/gravitino/server/web/rest/StatisticOperations.java
index 1f4999dfcf..420869c020 100644
--- 
a/server/src/main/java/org/apache/gravitino/server/web/rest/StatisticOperations.java
+++ 
b/server/src/main/java/org/apache/gravitino/server/web/rest/StatisticOperations.java
@@ -81,6 +81,9 @@ public class StatisticOperations {
 
   private static final Logger LOG = 
LoggerFactory.getLogger(StatisticOperations.class);
 
+  private static final String NULL_STATS_UPDATE_REQUEST_BODY_ERROR =
+      "Statistics update request body cannot be null";
+
   @Context private HttpServletRequest httpRequest;
 
   private final StatisticDispatcher statisticDispatcher;
@@ -160,6 +163,9 @@ public class StatisticOperations {
       return Utils.doAs(
           httpRequest,
           () -> {
+            if (request == null) {
+              throw new 
IllegalArgumentException(NULL_STATS_UPDATE_REQUEST_BODY_ERROR);
+            }
             request.validate();
             MetadataObject object =
                 MetadataObjects.parse(
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestStatisticOperations.java
 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestStatisticOperations.java
index dc3055a550..992dd73ebe 100644
--- 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestStatisticOperations.java
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestStatisticOperations.java
@@ -371,6 +371,35 @@ public class TestStatisticOperations extends JerseyTest {
         UnmodifiableStatisticException.class.getSimpleName(), 
errorResp4.getType());
   }
 
+  @Test
+  public void testUpdateTableStatisticsWithNullRequestBody() {
+    when(tableDispatcher.tableExists(any())).thenReturn(true);
+
+    MetadataObject tableObject =
+        MetadataObjects.parse(
+            String.format("%s.%s.%s", catalog, schema, table), 
MetadataObject.Type.TABLE);
+
+    Response resp =
+        target(
+                "/metalakes/"
+                    + metalake
+                    + "/objects/"
+                    + tableObject.type()
+                    + "/"
+                    + tableObject.fullName()
+                    + "/statistics")
+            .request(MediaType.APPLICATION_JSON_TYPE)
+            .accept("application/vnd.gravitino.v1+json")
+            .put(entity("null", MediaType.APPLICATION_JSON_TYPE));
+
+    Assertions.assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), 
resp.getStatus());
+    Assertions.assertEquals(MediaType.APPLICATION_JSON_TYPE, 
resp.getMediaType());
+
+    ErrorResponse errorResp = resp.readEntity(ErrorResponse.class);
+    Assertions.assertEquals(ErrorConstants.ILLEGAL_ARGUMENTS_CODE, 
errorResp.getCode());
+    Assertions.assertEquals(IllegalArgumentException.class.getSimpleName(), 
errorResp.getType());
+  }
+
   @Test
   public void testDropTableStatistics() {
     StatisticsDropRequest req = new StatisticsDropRequest(new String[] 
{"test1", "test2"});

Reply via email to