This is an automated email from the ASF dual-hosted git repository. mblow pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/asterixdb.git
commit 1cb3a92e5c28dd8479634ac44d2a613e504f4d7f Author: Michael Blow <[email protected]> AuthorDate: Tue Mar 2 17:01:41 2021 -0500 [ASTERIXDB-2841][*DB][STO] Metadata object name restrictions - names limited to 251 bytes (UTF-8 length) - forbid restricted characters by platform Change-Id: Ib8f7dd09643c61e05a3d1eb798b884f0a5d93aa1 Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/10325 Reviewed-by: Michael Blow <[email protected]> Tested-by: Michael Blow <[email protected]> --- .../asterix/test/metadata/MetadataManagerTest.java | 26 ++++++ .../metadata/MetadataManagerWindowsOsTest.java | 92 ++++++++++++++++++++++ .../metadata/declared/MetadataProvider.java | 4 +- .../asterix/metadata/utils/MetadataConstants.java | 9 ++- 4 files changed, 128 insertions(+), 3 deletions(-) diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/metadata/MetadataManagerTest.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/metadata/MetadataManagerTest.java index f8d6aeb..946d116 100644 --- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/metadata/MetadataManagerTest.java +++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/metadata/MetadataManagerTest.java @@ -18,6 +18,7 @@ */ package org.apache.asterix.test.metadata; +import java.io.File; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -161,4 +162,29 @@ public class MetadataManagerTest { } } } + + @Test + public void testInvalidCharacters() throws Exception { + TestCaseContext.OutputFormat cleanJson = TestCaseContext.OutputFormat.CLEAN_JSON; + + List<DataverseName> dvNameBadCharsList = Arrays.asList( + // #1. nul characters + DataverseName.createSinglePartName("abc\u0000def"), + // #2. leading whitespace + DataverseName.createSinglePartName(" abcdef"), + // #2. file separator + DataverseName.createSinglePartName("abc" + File.separatorChar + "def")); + + ErrorCode invalidNameErrCode = ErrorCode.INVALID_DATABASE_OBJECT_NAME; + for (DataverseName dvNameOk : dvNameBadCharsList) { + String sql = String.format("create dataverse %s;", dvNameOk); + try { + testExecutor.executeSqlppUpdateOrDdl(sql, cleanJson); + Assert.fail("Expected failure: " + invalidNameErrCode); + } catch (Exception e) { + Assert.assertTrue("Unexpected error message: " + e.getMessage(), + e.getMessage().contains(invalidNameErrCode.errorCode())); + } + } + } } diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/metadata/MetadataManagerWindowsOsTest.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/metadata/MetadataManagerWindowsOsTest.java new file mode 100644 index 0000000..b9f25e1 --- /dev/null +++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/metadata/MetadataManagerWindowsOsTest.java @@ -0,0 +1,92 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.asterix.test.metadata; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.asterix.api.common.AsterixHyracksIntegrationUtil; +import org.apache.asterix.common.config.GlobalConfig; +import org.apache.asterix.common.exceptions.ErrorCode; +import org.apache.asterix.common.metadata.DataverseName; +import org.apache.asterix.test.common.TestExecutor; +import org.apache.asterix.testframework.context.TestCaseContext; +import org.apache.commons.lang3.SystemUtils; +import org.jetbrains.annotations.NotNull; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class MetadataManagerWindowsOsTest { + + static { + System.setProperty("os.name", "Windows"); + } + + protected static final String TEST_CONFIG_FILE_NAME = "src/main/resources/cc.conf"; + private static final TestExecutor testExecutor = new TestExecutor(); + private static final AsterixHyracksIntegrationUtil integrationUtil = new AsterixHyracksIntegrationUtil(); + + @Before + public void setUp() throws Exception { + System.setProperty(GlobalConfig.CONFIG_FILE_PROPERTY, TEST_CONFIG_FILE_NAME); + integrationUtil.init(true, TEST_CONFIG_FILE_NAME); + Assert.assertTrue("wrong os reported", SystemUtils.IS_OS_WINDOWS); + } + + @After + public void tearDown() throws Exception { + integrationUtil.deinit(true); + } + + @Test + public void testInvalidCharacters() throws Exception { + TestCaseContext.OutputFormat cleanJson = TestCaseContext.OutputFormat.CLEAN_JSON; + + List<DataverseName> dvNameBadCharsList = new ArrayList<>(); + + for (char c = 0; c <= 0x1F; c++) { + dvNameBadCharsList.add(badCharName(c)); + } + dvNameBadCharsList.add(badCharName('\u007f')); + dvNameBadCharsList.add(badCharName('\\')); + dvNameBadCharsList.add(badCharName('/')); + dvNameBadCharsList.add(badCharName('>')); + dvNameBadCharsList.add(badCharName('\n')); + dvNameBadCharsList.add(badCharName('|')); + + ErrorCode invalidNameErrCode = ErrorCode.INVALID_DATABASE_OBJECT_NAME; + for (DataverseName dvNameOk : dvNameBadCharsList) { + String sql = String.format("create dataverse %s;", dvNameOk); + try { + testExecutor.executeSqlppUpdateOrDdl(sql, cleanJson); + Assert.fail("Expected failure: " + invalidNameErrCode); + } catch (Exception e) { + Assert.assertTrue("Unexpected error message: " + e.getMessage(), + e.getMessage().contains(invalidNameErrCode.errorCode())); + } + } + } + + @NotNull + protected DataverseName badCharName(char c) { + return DataverseName.createSinglePartName("abc" + c + "def"); + } +} diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java index 9b85601..a534954 100644 --- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java +++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java @@ -18,6 +18,8 @@ */ package org.apache.asterix.metadata.declared; +import static org.apache.asterix.metadata.utils.MetadataConstants.METADATA_OBJECT_NAME_INVALID_CHARS; + import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -1768,7 +1770,7 @@ public class MetadataProvider implements IMetadataProvider<DataSourceId, String> if (name == null || name.isEmpty()) { throw new AsterixException(ErrorCode.INVALID_DATABASE_OBJECT_NAME, sourceLoc, "<empty>"); } - if (Character.isWhitespace(name.codePointAt(0))) { + if (Character.isWhitespace(name.codePointAt(0)) || METADATA_OBJECT_NAME_INVALID_CHARS.matcher(name).find()) { throw new AsterixException(ErrorCode.INVALID_DATABASE_OBJECT_NAME, sourceLoc, name); } int lengthUTF8 = name.getBytes(StandardCharsets.UTF_8).length; diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/MetadataConstants.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/MetadataConstants.java index 6bd52fa..f1412db 100644 --- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/MetadataConstants.java +++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/MetadataConstants.java @@ -19,15 +19,20 @@ package org.apache.asterix.metadata.utils; +import java.util.regex.Pattern; + import org.apache.asterix.common.metadata.DataverseName; +import org.apache.commons.lang3.SystemUtils; /** * Contains metadata constants */ public class MetadataConstants { - public static final int METADATA_OBJECT_NAME_LENGTH_LIMIT_UTF8 = 255; - public static final int DATAVERSE_NAME_TOTAL_LENGTH_LIMIT_UTF8 = 1023; + public static final int METADATA_OBJECT_NAME_LENGTH_LIMIT_UTF8 = 251; + public static final int DATAVERSE_NAME_TOTAL_LENGTH_LIMIT_UTF8 = METADATA_OBJECT_NAME_LENGTH_LIMIT_UTF8 * 4; + public static final Pattern METADATA_OBJECT_NAME_INVALID_CHARS = + Pattern.compile(SystemUtils.IS_OS_WINDOWS ? "[\u0000-\u001F\u007F\"*/:<>\\\\|+,.;=\\[\\]\n]" : "[\u0000/]"); // Name of the dataverse the metadata lives in. public static final DataverseName METADATA_DATAVERSE_NAME = DataverseName.createBuiltinDataverseName("Metadata");
