Skip to content

Commit 30f6c82

Browse files
comiuscopybara-github
authored andcommitted
Escape tilde more gracefully
Tilde needs to be escaped only when it's the first character after the white space. Otherwise, we can keep the string unescaped. This supports bzlmod better, because tilde is used in the directory names. Users often already escape location function, for example `SJ="$(location @bazel_tools//tools/jdk:singlejar)"; $SJ`. Without the change this becomes `'external/repo~name/singlejar'` and the script fails (no file found). Location function shouldn't be escaped. But without this change we risk a lot of users will need to fix their scripts. Closes bazelbuild#16560. PiperOrigin-RevId: 484226256 Change-Id: I6b71f89a649f8494b76a4446b8f6384421eb89d1
1 parent 5895fd3 commit 30f6c82

File tree

2 files changed

+14
-3
lines changed

2 files changed

+14
-3
lines changed

src/main/java/com/google/devtools/build/lib/util/ShellEscaper.java

+9-3
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ public final class ShellEscaper extends Escaper {
6363
.or(CharMatcher.inRange('a', 'z')) // that would also accept non-ASCII digits and
6464
.or(CharMatcher.inRange('A', 'Z')) // letters.
6565
.precomputed();
66+
private static final CharMatcher SAFECHAR_MATCHER_WITH_TILDE =
67+
SAFECHAR_MATCHER.or(CharMatcher.is('~')).precomputed();
6668

6769
/**
6870
* Escapes a string by adding strong (single) quotes around it if necessary.
@@ -98,9 +100,13 @@ public String escape(String unescaped) {
98100
// gets treated as a separate argument.
99101
return "''";
100102
} else {
101-
return SAFECHAR_MATCHER.matchesAllOf(s)
102-
? s
103-
: "'" + STRONGQUOTE_ESCAPER.escape(s) + "'";
103+
if (SAFECHAR_MATCHER.matchesAllOf(s)) {
104+
return s;
105+
}
106+
if (SAFECHAR_MATCHER_WITH_TILDE.matchesAllOf(s) && s.charAt(0) != '~') {
107+
return s;
108+
}
109+
return "'" + STRONGQUOTE_ESCAPER.escape(s) + "'";
104110
}
105111
}
106112

src/test/java/com/google/devtools/build/lib/util/ShellEscaperTest.java

+5
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ public void shellEscape() throws Exception {
4141
assertThat(escapeString("\\'foo\\'")).isEqualTo("'\\'\\''foo\\'\\'''");
4242
assertThat(escapeString("${filename%.c}.o")).isEqualTo("'${filename%.c}.o'");
4343
assertThat(escapeString("<html!>")).isEqualTo("'<html!>'");
44+
assertThat(escapeString("~not_home")).isEqualTo("'~not_home'");
45+
assertThat(escapeString("external/protobuf~3.19.6/src/google"))
46+
.isEqualTo("external/protobuf~3.19.6/src/google");
47+
assertThat(escapeString("external/~install_dev_dependencies~foo/pkg"))
48+
.isEqualTo("external/~install_dev_dependencies~foo/pkg");
4449
}
4550

4651
@Test

0 commit comments

Comments
 (0)