Skip to content

Commit 8fbfe9c

Browse files
authored
IGNITE-20867 Fixed server nodes crashing if the cache directory contains illegal chars (#11047)
1 parent 5ccbd71 commit 8fbfe9c

File tree

3 files changed

+145
-0
lines changed

3 files changed

+145
-0
lines changed

modules/core/src/main/java/org/apache/ignite/internal/processors/cache/ClusterCachesInfo.java

+24
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
package org.apache.ignite.internal.processors.cache;
1919

2020
import java.io.Serializable;
21+
import java.nio.file.InvalidPathException;
22+
import java.nio.file.Paths;
2123
import java.util.ArrayList;
2224
import java.util.Arrays;
2325
import java.util.Collection;
@@ -95,6 +97,7 @@
9597
import static org.apache.ignite.internal.GridComponent.DiscoveryDataExchangeType.CACHE_PROC;
9698
import static org.apache.ignite.internal.processors.cache.GridCacheProcessor.CLUSTER_READ_ONLY_MODE_ERROR_MSG_FORMAT;
9799
import static org.apache.ignite.internal.processors.cache.GridLocalConfigManager.validateIncomingConfiguration;
100+
import static org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager.cacheDirName;
98101
import static org.apache.ignite.internal.processors.cache.persistence.snapshot.IgniteSnapshotManager.SNP_IN_PROGRESS_ERR_MSG;
99102

100103
/**
@@ -1131,6 +1134,12 @@ else if (encMgr.masterKeyDigest() != null &&
11311134
}
11321135
}
11331136

1137+
if (containsInvalidFileNameChars(ccfg)) {
1138+
err = new IgniteCheckedException("Cache start failed. Cache or group name contains the characters " +
1139+
"that are not allowed in file names [cache= + cacheName " +
1140+
(ccfg.getGroupName() == null ? "" : ", group=" + ccfg.getGroupName()) + ']');
1141+
}
1142+
11341143
if (err != null) {
11351144
if (persistedCfgs)
11361145
res.errs.add(err);
@@ -1196,6 +1205,21 @@ else if (encMgr.masterKeyDigest() != null &&
11961205
return true;
11971206
}
11981207

1208+
/** @return {@code True} if cache directory contains the characters that are not allowed in file names. */
1209+
private boolean containsInvalidFileNameChars(CacheConfiguration<?, ?> ccfg) {
1210+
if (!CU.isPersistentCache(ccfg, ctx.config().getDataStorageConfiguration()))
1211+
return false;
1212+
1213+
String expDir = cacheDirName(ccfg);
1214+
1215+
try {
1216+
return !expDir.equals(Paths.get(expDir).toFile().getName());
1217+
}
1218+
catch (InvalidPathException ignored) {
1219+
return true;
1220+
}
1221+
}
1222+
11991223
/**
12001224
* Validate correcteness of new cache start request.
12011225
*
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.ignite.internal.processors.cache.distributed;
19+
20+
import java.util.ArrayList;
21+
import java.util.Collection;
22+
import java.util.List;
23+
import org.apache.ignite.IgniteCheckedException;
24+
import org.apache.ignite.cluster.ClusterState;
25+
import org.apache.ignite.configuration.CacheConfiguration;
26+
import org.apache.ignite.configuration.DataRegionConfiguration;
27+
import org.apache.ignite.configuration.DataStorageConfiguration;
28+
import org.apache.ignite.configuration.IgniteConfiguration;
29+
import org.apache.ignite.internal.IgniteEx;
30+
import org.apache.ignite.internal.util.typedef.internal.U;
31+
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
32+
import org.junit.Test;
33+
import org.junit.runner.RunWith;
34+
import org.junit.runners.Parameterized;
35+
36+
import static org.apache.ignite.internal.util.lang.GridFunc.asList;
37+
import static org.apache.ignite.testframework.GridTestUtils.assertThrows;
38+
import static org.apache.ignite.testframework.GridTestUtils.cartesianProduct;
39+
40+
/**
41+
* Test cache directory name validation.
42+
*/
43+
@RunWith(Parameterized.class)
44+
public class CacheDirectoryNameTest extends GridCommonAbstractTest {
45+
/** */
46+
@Parameterized.Parameter
47+
public boolean persistenceEnabled;
48+
49+
/** */
50+
@Parameterized.Parameter(1)
51+
public boolean checkGroup;
52+
53+
/** @return Test parameters. */
54+
@Parameterized.Parameters(name = "persistenceEnabled={0}, isGroupName={1}")
55+
public static Collection<?> parameters() {
56+
return cartesianProduct(
57+
asList(false, true), asList(false, true)
58+
);
59+
}
60+
61+
/** {@inheritDoc} */
62+
@Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
63+
return super.getConfiguration(igniteInstanceName)
64+
.setDataStorageConfiguration(new DataStorageConfiguration()
65+
.setDefaultDataRegionConfiguration(new DataRegionConfiguration()
66+
.setPersistenceEnabled(persistenceEnabled)));
67+
}
68+
69+
/** {@inheritDoc} */
70+
@Override protected void beforeTestsStarted() throws Exception {
71+
super.beforeTestsStarted();
72+
73+
cleanPersistenceDir();
74+
}
75+
76+
/** {@inheritDoc} */
77+
@Override protected void afterTest() throws Exception {
78+
stopAllGrids();
79+
80+
cleanPersistenceDir();
81+
}
82+
83+
/** */
84+
@Test
85+
public void testCacheDirectoryContainsInvalidFileNameChars() throws Exception {
86+
IgniteEx srv = startGrid();
87+
88+
srv.cluster().state(ClusterState.ACTIVE);
89+
90+
List<String> illegalNames = new ArrayList<>();
91+
92+
illegalNames.add("/");
93+
illegalNames.add("a/b");
94+
95+
if (U.isWindows()) {
96+
illegalNames.add("a>b");
97+
illegalNames.add("a\\b");
98+
}
99+
100+
for (String name : illegalNames) {
101+
CacheConfiguration<Object, Object> cfg = new CacheConfiguration<>(DEFAULT_CACHE_NAME);
102+
103+
if (checkGroup)
104+
cfg.setGroupName(name);
105+
else
106+
cfg.setName(name);
107+
108+
if (persistenceEnabled) {
109+
assertThrows(log, () -> srv.createCache(cfg), IgniteCheckedException.class,
110+
"Cache start failed. Cache or group name contains the characters that are not allowed in file names");
111+
}
112+
else {
113+
srv.createCache(cfg);
114+
srv.destroyCache(cfg.getName());
115+
}
116+
}
117+
}
118+
}

modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite4.java

+3
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
import org.apache.ignite.internal.processors.cache.IgniteSystemCacheOnClientTest;
9797
import org.apache.ignite.internal.processors.cache.MarshallerCacheJobRunNodeRestartTest;
9898
import org.apache.ignite.internal.processors.cache.distributed.CacheAffinityEarlyTest;
99+
import org.apache.ignite.internal.processors.cache.distributed.CacheDirectoryNameTest;
99100
import org.apache.ignite.internal.processors.cache.distributed.CacheDiscoveryDataConcurrentJoinTest;
100101
import org.apache.ignite.internal.processors.cache.distributed.CacheGetFutureHangsSelfTest;
101102
import org.apache.ignite.internal.processors.cache.distributed.CacheGroupsPreloadTest;
@@ -329,6 +330,8 @@ public static List<Class<?>> suite(Collection<Class> ignoredTests) {
329330

330331
GridTestUtils.addTestIfNeeded(suite, GridCacheProcessorActiveTxTest.class, ignoredTests);
331332

333+
GridTestUtils.addTestIfNeeded(suite, CacheDirectoryNameTest.class, ignoredTests);
334+
332335
return suite;
333336
}
334337
}

0 commit comments

Comments
 (0)