From 5d6df77291f0845e801b174f9f4d85c704b016c2 Mon Sep 17 00:00:00 2001 From: Morten Tokle Date: Thu, 11 Aug 2022 09:10:01 +0200 Subject: Path validation --- .../java/ai/vespa/validation/PathValidator.java | 36 ++++++++++++++++++++++ .../ai/vespa/validation/PathValidatorTest.java | 35 +++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 vespajlib/src/main/java/ai/vespa/validation/PathValidator.java create mode 100644 vespajlib/src/test/java/ai/vespa/validation/PathValidatorTest.java (limited to 'vespajlib/src') diff --git a/vespajlib/src/main/java/ai/vespa/validation/PathValidator.java b/vespajlib/src/main/java/ai/vespa/validation/PathValidator.java new file mode 100644 index 00000000000..0ae81e2315d --- /dev/null +++ b/vespajlib/src/main/java/ai/vespa/validation/PathValidator.java @@ -0,0 +1,36 @@ +package ai.vespa.validation; + +import java.nio.file.Path; + +/** + * Path validations + * + * @author mortent + */ +public class PathValidator { + + /** + * Validate that file is a child of basedir + * @param root Root directory to use for validation + * @param path Path to validate + * @throws IllegalArgumentException if path is not a child of root + */ + public static void validateChildOf(Path root, Path path) { + if (!path.normalize().startsWith(root)) { + throw new IllegalArgumentException("Invalid path %s".formatted(path)); + } + } + + /** + * Resolves a path under a root path + * @param root root poth + * @param path child to resolve + * @return The resolved path + * @throws IllegalArgumentException If the provided child path does not resolve as child of root + */ + public static Path resolveChildOf(Path root, String path) { + Path resolved = root.resolve(path); + validateChildOf(root, resolved); + return resolved; + } +} diff --git a/vespajlib/src/test/java/ai/vespa/validation/PathValidatorTest.java b/vespajlib/src/test/java/ai/vespa/validation/PathValidatorTest.java new file mode 100644 index 00000000000..a2c1bd6bd0c --- /dev/null +++ b/vespajlib/src/test/java/ai/vespa/validation/PathValidatorTest.java @@ -0,0 +1,35 @@ +package ai.vespa.validation; + +import org.junit.Test; + +import java.nio.file.Path; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class PathValidatorTest { + + @Test + public void testPathValidation() { + Path root = Path.of("/foo/"); + + assertOk(Path.of("/foo/bar"), root); + assertOk(Path.of("/foo/foo2/bar"), root); + assertOk(Path.of("/foo/foo2/../bar"), root); + assertOk(Path.of("/foo/../foo/bar"), root); + assertOk(Path.of("/bar/../foo/../foo/bar"), root); + + assertInvalid(Path.of("/foo/../bar"), root); + assertInvalid(Path.of("/foo/bar/../../bar"), root); + } + + private void assertOk(Path path, Path root) { + PathValidator.validateChildOf(root, path); + } + + private void assertInvalid(Path path, Path root) { + IllegalArgumentException illegalArgumentException = assertThrows(IllegalArgumentException.class, + () -> PathValidator.validateChildOf(root, path)); + assertEquals("Invalid path %s".formatted(path), illegalArgumentException.getMessage()); + } +} -- cgit v1.2.3