aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main
diff options
context:
space:
mode:
authorGravatar Kristina Chodorow <kchodorow@google.com>2015-09-18 13:45:55 +0000
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2015-09-21 08:57:26 +0000
commite76dd5e223acbf1b9fea9a4764a6226f8b42edd1 (patch)
treea9ef8afe58e287806ee1ac59991b5658e207b105 /src/main
parent391d67ca07c15b2383e14c6bbeefd42149361626 (diff)
Tighten up the requirements on workspace names
Fixes #462. RELNOTES: Workspace names are now restricted to being in their base directory (that is, the names cannot contain up-level references or /./). -- MOS_MIGRATED_REVID=103379893
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/com/google/devtools/build/lib/cmdline/PackageIdentifier.java99
1 files changed, 77 insertions, 22 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/cmdline/PackageIdentifier.java b/src/main/java/com/google/devtools/build/lib/cmdline/PackageIdentifier.java
index 9d0ef0edcf..89167dd433 100644
--- a/src/main/java/com/google/devtools/build/lib/cmdline/PackageIdentifier.java
+++ b/src/main/java/com/google/devtools/build/lib/cmdline/PackageIdentifier.java
@@ -85,35 +85,90 @@ public final class PackageIdentifier implements Comparable<PackageIdentifier>, S
this.name = name;
}
- /**
- * Performs validity checking. Returns null on success, an error message otherwise.
- */
- private static String validate(String name) {
- if (name.isEmpty()) {
- return null;
- }
+ private static class Lexer {
+ private static final char EOF = '\0';
- if (!name.startsWith("@")) {
- return "workspace name must start with '@'";
+ private final String name;
+ private int pos;
+
+ public Lexer(String name) {
+ this.name = name;
+ this.pos = 0;
}
- // Check for any character outside of [/0-9A-Za-z_.-]. Try to evaluate the
- // conditional quickly (by looking in decreasing order of character class
- // likelihood).
- if (name.startsWith("@/") || name.endsWith("/")) {
- return "workspace names cannot start nor end with '/'";
- } else if (name.contains("//")) {
- return "workspace names cannot contain multiple '/'s in a row";
+ public String lex() {
+ if (name.isEmpty()) {
+ return null;
+ }
+
+ if (name.charAt(pos) != '@') {
+ return "workspace names must start with '@'";
+ }
+
+ // @// is valid.
+ if (name.length() == 1) {
+ return null;
+ }
+
+ pos++;
+ // Disallow strings starting with “/”, “./”, or “../”
+ // Disallow strings identical to ".", or “..”
+ if (name.charAt(pos) == '/') {
+ return "workspace names are not allowed to start with '@/'";
+ } else if (name.charAt(pos) == '.') {
+ char next = peek(1);
+ char nextNext = peek(2);
+ // Forbid '@.' and '@..' as complete labels and '@./' and '@../' as label starts.
+ if (next == EOF) {
+ return "workspace names are not allowed to be '@.'";
+ } else if (next == '/') {
+ return "workspace names are not allowed to start with '@./'";
+ } else if (next == '.' && (nextNext == '/' || nextNext == EOF)) {
+ return "workspace names are not allowed to start with '@..'";
+ }
+ }
+
+ // This lexes the first letter a second time, to make sure it fulfills the general
+ // workspace name criteria (as well as the more strict criteria for the beginning of a
+ // workspace name).
+ // Disallow strings containing “//”, “/./”, or “/../”
+ // Disallow strings ending in “/”, "/.", or “/..”
+ // name = @( <alphanum> | [/._-] )*
+ for (; pos < name.length(); pos++) {
+ char c = name.charAt(pos);
+ if (c == '/') {
+ char next = peek(1);
+ if (next == '/') {
+ return "workspace names are not allowed to contain '//'";
+ } else if (next == EOF) {
+ return "workspace names are not allowed to end with '/'";
+ } else if (next == '.' && (peek(2) == '/' || peek(2) == EOF)) {
+ return "workspace names are not allowed to contain '/./'";
+ } else if (next == '.' && peek(2) == '.' && (peek(3) == '/' || peek(3) == EOF)) {
+ return "workspace names are not allowed to contain '/../'";
+ }
+ } else if ((c < 'a' || c > 'z') && c != '_' && c != '-' && c != '/' && c != '.'
+ && (c < '0' || c > '9') && (c < 'A' || c > 'Z')) {
+ return "workspace names may contain only A-Z, a-z, 0-9, '-', '_', '.', and '/'";
+ }
+ }
+
+ return null;
}
- for (int i = name.length() - 1; i >= 1; --i) {
- char c = name.charAt(i);
- if ((c < 'a' || c > 'z') && c != '_' && c != '-' && c != '/' && c != '.'
- && (c < '0' || c > '9') && (c < 'A' || c > 'Z')) {
- return "workspace names may contain only A-Z, a-z, 0-9, '-', '_', '.', and '/'";
+ private char peek(int num) {
+ if (pos + num >= name.length()) {
+ return EOF;
}
+ return name.charAt(pos + num);
}
- return null;
+ }
+
+ /**
+ * Performs validity checking. Returns null on success, an error message otherwise.
+ */
+ private static String validate(String name) {
+ return new Lexer(name).lex();
}
/**