Do not detect file names starting `..` as having up-level references.
`PathFragment::containsUplevelReferences` detects whether a path has an
up-level reference (`..`). The logic looks at the beginning of the normalized
path whether it starts with a `..`. This is incorrect for path segments which
have a `..` prefix, but are not `..`, e.g. `..file`. This causes bazel to crash
when we create a tree artifact with a file starting with a `..`.
Fix the detection to only recognize paths with `..` segments.
PiperOrigin-RevId: 351624019
diff --git a/src/test/java/com/google/devtools/build/lib/vfs/PathFragmentTest.java b/src/test/java/com/google/devtools/build/lib/vfs/PathFragmentTest.java
index a94daf3..9b39d42 100644
--- a/src/test/java/com/google/devtools/build/lib/vfs/PathFragmentTest.java
+++ b/src/test/java/com/google/devtools/build/lib/vfs/PathFragmentTest.java
@@ -15,6 +15,7 @@
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.devtools.build.lib.vfs.PathFragment.EMPTY_FRAGMENT;
import static com.google.devtools.build.lib.vfs.PathFragment.create;
import static org.junit.Assert.assertThrows;
@@ -600,4 +601,43 @@
(PathFragment) TestUtils.fromBytes(new DeserializationContext(ImmutableMap.of()), sa);
assertThat(a2).isEqualTo(a);
}
+
+ @Test
+ public void containsUplevelReference_emptyPath_returnsFalse() {
+ assertThat(EMPTY_FRAGMENT.containsUplevelReferences()).isFalse();
+ }
+
+ @Test
+ public void containsUplevelReference_uplevelOnlyPath_returnsTrue() {
+ PathFragment pathFragment = create("..");
+ assertThat(pathFragment.containsUplevelReferences()).isTrue();
+ }
+
+ @Test
+ public void containsUplevelReferences_firstSegmentStartingWithDotDot_returnsFalse() {
+ PathFragment pathFragment = create("..file");
+ assertThat(pathFragment.containsUplevelReferences()).isFalse();
+ }
+
+ @Test
+ public void containsUplevelReferences_startsWithUplevelReference_returnsTrue() {
+ PathFragment pathFragment = create("../file");
+ assertThat(pathFragment.containsUplevelReferences()).isTrue();
+ }
+
+ @Test
+ public void containsUplevelReferences_uplevelReferenceMidPath_normalizesAndReturnsFalse() {
+ PathFragment pathFragment = create("a/../b");
+
+ assertThat(pathFragment.containsUplevelReferences()).isFalse();
+ assertThat(pathFragment.getPathString()).isEqualTo("b");
+ }
+
+ @Test
+ public void containsUplevelReferenes_uplevelReferenceMidGlobalPath_normalizesAndReturnsFalse() {
+ PathFragment pathFragment = create("/dir1/dir2/../file");
+
+ assertThat(pathFragment.containsUplevelReferences()).isFalse();
+ assertThat(pathFragment.getPathString()).isEqualTo("/dir1/file");
+ }
}