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 {