Skip to content

Commit b6fa31a

Browse files
committed
added +
1 parent 8ba9a0a commit b6fa31a

2 files changed

Lines changed: 7 additions & 1 deletion

File tree

src/java/org/apache/cassandra/db/ColumnFamilyStore.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1899,10 +1899,12 @@ private void validateSnapshotName(String snapshotName)
18991899
// Allowed characters are a conservative subset of the AWS S3 "Safe characters" set
19001900
// (https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-keys.html#object-key-guidelines):
19011901
// 0-9 a-z A-Z - _ .
1902+
// plus '+', which is not an S3 "Safe character" but can legitimately appear in system
1903+
// snapshot names via version build metadata (e.g. an upgrade snapshot "<millis>-upgrade-5.0.4+build-...").
19021904
// The remaining S3-safe characters (! * ' ( )) are intentionally excluded as they are
19031905
// shell-significant and error-prone in paths, and the path separator '/' is excluded too,
19041906
// which is what blocks traversal attempts such as "../../mysnapshot"
1905-
if (!Pattern.compile("[a-zA-Z0-9_.-]+").matcher(snapshotName).matches())
1907+
if (!Pattern.compile("[a-zA-Z0-9_.+-]+").matcher(snapshotName).matches())
19061908
{
19071909
throw new IllegalArgumentException("Snapshot name contains illegal characters: " + snapshotName);
19081910
}

test/unit/org/apache/cassandra/db/SnapshotTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ public void testSnapshotNameValidation()
7878
// Dots embedded in a name are not traversal: with '/' excluded, "a..tag" is just a literal directory.
7979
assertThatCode(() -> cfs.snapshot("a..tag")).doesNotThrowAnyException();
8080

81+
// "+" is part of the allowed set because it can appear in a Cassandra version
82+
// (build metadata, e.g. "7.0.0+abc123"), which ends up in system snapshot names.
83+
assertThatCode(() -> cfs.snapshot("this_is_snapshot-7.0.0+abc123")).doesNotThrowAnyException();
84+
8185
String tooLong = repeat('a', SchemaConstants.FILENAME_LENGTH + 1);
8286
assertThatThrownBy(() -> cfs.snapshot(tooLong))
8387
.isInstanceOf(IllegalArgumentException.class)

0 commit comments

Comments
 (0)