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

Aias00 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git


The following commit(s) were added to refs/heads/master by this push:
     new 2418ad8f9c fix: validate keys in unCache methods to prevent index out 
of bounds exceptions and adjust key parsing logic (#6955)
2418ad8f9c is described below

commit 2418ad8f9c11d6b8ac4ac57e6a68aacda038d54f
Author: Limbo <[email protected]>
AuthorDate: Sun Aug 23 18:56:23 2026 +0800

    fix: validate keys in unCache methods to prevent index out of bounds 
exceptions and adjust key parsing logic (#6955)
    
    Co-authored-by: aias00 <[email protected]>
---
 .../data/core/AbstractNodeDataSyncService.java     | 27 ++++++++---
 .../data/core/AbstractNodeDataSyncServiceTest.java | 55 ++++++++++++++++++++--
 2 files changed, 72 insertions(+), 10 deletions(-)

diff --git 
a/shenyu-sync-data-center/shenyu-sync-data-api/src/main/java/org/apache/shenyu/sync/data/core/AbstractNodeDataSyncService.java
 
b/shenyu-sync-data-center/shenyu-sync-data-api/src/main/java/org/apache/shenyu/sync/data/core/AbstractNodeDataSyncService.java
index 8aefd4479e..17a0e6d5cf 100644
--- 
a/shenyu-sync-data-center/shenyu-sync-data-api/src/main/java/org/apache/shenyu/sync/data/core/AbstractNodeDataSyncService.java
+++ 
b/shenyu-sync-data-center/shenyu-sync-data-api/src/main/java/org/apache/shenyu/sync/data/core/AbstractNodeDataSyncService.java
@@ -40,6 +40,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.List;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.function.Consumer;
 
@@ -259,9 +260,13 @@ public abstract class AbstractNodeDataSyncService {
     }
 
     protected void unCacheAuthData(final String removeKey) {
+        final String[] authKeys = StringUtils.split(removeKey, 
DefaultNodeConstants.JOIN_POINT);
+        if (Objects.isNull(authKeys) || authKeys.length < 3) {
+            LOG.warn("AbstractNodeDataSyncService invalid auth data remove 
key: {}", removeKey);
+            return;
+        }
         final AppAuthData appAuthData = new AppAuthData();
-        final String[] ruleKeys = StringUtils.split(removeKey, 
DefaultNodeConstants.JOIN_POINT);
-        appAuthData.setAppKey(ruleKeys[1]);
+        appAuthData.setAppKey(authKeys[2]);
         authDataSubscribers.forEach(e -> e.unSubscribe(appAuthData));
         removeListener(removeKey);
     }
@@ -273,9 +278,13 @@ public abstract class AbstractNodeDataSyncService {
     }
 
     protected void unCacheMetaData(final String removeKey) {
+        final String[] metaKeys = StringUtils.split(removeKey, 
DefaultNodeConstants.JOIN_POINT);
+        if (Objects.isNull(metaKeys) || metaKeys.length < 3) {
+            LOG.warn("AbstractNodeDataSyncService invalid meta data remove 
key: {}", removeKey);
+            return;
+        }
         final MetaData metaData = new MetaData();
-        final String[] ruleKeys = StringUtils.split(removeKey, 
DefaultNodeConstants.JOIN_POINT);
-        metaData.setId(ruleKeys[1]);
+        metaData.setId(metaKeys[2]);
         metaDataSubscribers.forEach(e -> e.unSubscribe(metaData));
         removeListener(removeKey);
     }
@@ -287,10 +296,14 @@ public abstract class AbstractNodeDataSyncService {
     }
 
     protected void unCacheProxySelectorData(final String removeKey) {
-        ProxySelectorData proxySelectorData = new ProxySelectorData();
         final String[] proxySelectorKeys = StringUtils.split(removeKey, 
DefaultNodeConstants.JOIN_POINT);
-        proxySelectorData.setPluginName(proxySelectorKeys[2]);
-        proxySelectorData.setName(proxySelectorKeys[3]);
+        if (Objects.isNull(proxySelectorKeys) || proxySelectorKeys.length < 5) 
{
+            LOG.warn("AbstractNodeDataSyncService invalid proxy selector data 
remove key: {}", removeKey);
+            return;
+        }
+        ProxySelectorData proxySelectorData = new ProxySelectorData();
+        proxySelectorData.setPluginName(proxySelectorKeys[3]);
+        proxySelectorData.setName(proxySelectorKeys[4]);
         proxySelectorDataSubscribers.forEach(e -> 
e.unSubscribe(proxySelectorData));
         removeListener(removeKey);
     }
diff --git 
a/shenyu-sync-data-center/shenyu-sync-data-api/src/test/java/org/apache/shenyu/sync/data/core/AbstractNodeDataSyncServiceTest.java
 
b/shenyu-sync-data-center/shenyu-sync-data-api/src/test/java/org/apache/shenyu/sync/data/core/AbstractNodeDataSyncServiceTest.java
index 6348c08fb9..79178226d5 100644
--- 
a/shenyu-sync-data-center/shenyu-sync-data-api/src/test/java/org/apache/shenyu/sync/data/core/AbstractNodeDataSyncServiceTest.java
+++ 
b/shenyu-sync-data-center/shenyu-sync-data-api/src/test/java/org/apache/shenyu/sync/data/core/AbstractNodeDataSyncServiceTest.java
@@ -18,7 +18,10 @@
 package org.apache.shenyu.sync.data.core;
 
 import org.apache.shenyu.common.config.ShenyuConfig;
+import org.apache.shenyu.common.dto.AppAuthData;
+import org.apache.shenyu.common.dto.MetaData;
 import org.apache.shenyu.common.dto.PluginData;
+import org.apache.shenyu.common.dto.ProxySelectorData;
 import org.apache.shenyu.sync.data.api.AuthDataSubscriber;
 import org.apache.shenyu.sync.data.api.DiscoveryUpstreamDataSubscriber;
 import org.apache.shenyu.sync.data.api.MetaDataSubscriber;
@@ -37,8 +40,10 @@ import java.util.List;
 import java.util.function.Consumer;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
 
 @RunWith(MockitoJUnitRunner.class)
 public class AbstractNodeDataSyncServiceTest {
@@ -49,13 +54,10 @@ public class AbstractNodeDataSyncServiceTest {
     @Mock
     private PluginDataSubscriber pluginDataSubscriber;
 
-    @Mock
     private List<MetaDataSubscriber> metaDataSubscribers;
 
-    @Mock
     private List<AuthDataSubscriber> authDataSubscribers;
 
-    @Mock
     private List<ProxySelectorDataSubscriber> proxySelectorDataSubscribers;
 
     @Mock
@@ -67,6 +69,12 @@ public class AbstractNodeDataSyncServiceTest {
     @Mock
     private AuthDataSubscriber authDataSubscriber;
 
+    @Mock
+    private MetaDataSubscriber metaDataSubscriber;
+
+    @Mock
+    private ProxySelectorDataSubscriber proxySelectorDataSubscriber;
+
     private AbstractNodeDataSyncService nodeDataSyncService;
 
     @Before
@@ -76,6 +84,10 @@ public class AbstractNodeDataSyncServiceTest {
 
         authDataSubscribers = new ArrayList<>();
         authDataSubscribers.add(authDataSubscriber);
+        metaDataSubscribers = new ArrayList<>();
+        metaDataSubscribers.add(metaDataSubscriber);
+        proxySelectorDataSubscribers = new ArrayList<>();
+        proxySelectorDataSubscribers.add(proxySelectorDataSubscriber);
 
         nodeDataSyncService = new AbstractNodeDataSyncServiceImpl(
                 changeData,
@@ -123,6 +135,43 @@ public class AbstractNodeDataSyncServiceTest {
         verify(authDataSubscribers.get(0)).onSubscribe(any());
     }
 
+    @Test
+    public void testUnCacheAuthData() {
+        nodeDataSyncService.unCacheAuthData("namespace.auth.testApp");
+
+        ArgumentCaptor<AppAuthData> captor = 
ArgumentCaptor.forClass(AppAuthData.class);
+        verify(authDataSubscriber).unSubscribe(captor.capture());
+        assertEquals("testApp", captor.getValue().getAppKey());
+    }
+
+    @Test
+    public void testUnCacheMetaData() {
+        nodeDataSyncService.unCacheMetaData("namespace.meta.metaId");
+
+        ArgumentCaptor<MetaData> captor = 
ArgumentCaptor.forClass(MetaData.class);
+        verify(metaDataSubscriber).unSubscribe(captor.capture());
+        assertEquals("metaId", captor.getValue().getId());
+    }
+
+    @Test
+    public void testUnCacheProxySelectorData() {
+        
nodeDataSyncService.unCacheProxySelectorData("namespace.proxy.selector.tcp.selectorName");
+
+        ArgumentCaptor<ProxySelectorData> captor = 
ArgumentCaptor.forClass(ProxySelectorData.class);
+        verify(proxySelectorDataSubscriber).unSubscribe(captor.capture());
+        assertEquals("tcp", captor.getValue().getPluginName());
+        assertEquals("selectorName", captor.getValue().getName());
+    }
+
+    @Test
+    public void testUnCacheDataWithInvalidKey() {
+        assertDoesNotThrow(() -> 
nodeDataSyncService.unCacheAuthData("namespace"));
+        assertDoesNotThrow(() -> 
nodeDataSyncService.unCacheMetaData("namespace"));
+        assertDoesNotThrow(() -> 
nodeDataSyncService.unCacheProxySelectorData("namespace"));
+
+        verifyNoInteractions(authDataSubscriber, metaDataSubscriber, 
proxySelectorDataSubscriber);
+    }
+
     // Mock implementation
     static class AbstractNodeDataSyncServiceImpl extends 
AbstractNodeDataSyncService {
 

Reply via email to