Skip to content

Commit ceec93c

Browse files
benjaminpcopybara-github
authored andcommitted
Don't ever claim /dev/null is an execpath.
SpawnInputExpander.EMPTY_FILE claimed an execpath of /dev/null, which could lead to clients trying to do mutating filesystem operations in /dev. In this change, SpawnInputExpander.EMPTY_FILE is replaced with an EmptyVirtualInput with no execpath. This way errant callers will explode before trying filesystem operations on it. Such a EmptyVirtualInput doesn't really meet the contract of being an ActionInput but that was really already true. Closes bazelbuild#12516. PiperOrigin-RevId: 350427786
1 parent 73011da commit ceec93c

File tree

4 files changed

+18
-24
lines changed

4 files changed

+18
-24
lines changed

src/main/java/com/google/devtools/build/lib/actions/cache/VirtualActionInput.java

+9-13
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
// limitations under the License.
1414
package com.google.devtools.build.lib.actions.cache;
1515

16-
import com.google.common.base.Preconditions;
1716
import com.google.devtools.build.lib.actions.ActionInput;
1817
import com.google.devtools.build.lib.actions.FileArtifactValue;
1918
import com.google.devtools.build.lib.util.StreamWriter;
@@ -27,6 +26,11 @@
2726
* OutputStream.
2827
*/
2928
public interface VirtualActionInput extends ActionInput, StreamWriter {
29+
/**
30+
* An empty virtual artifact <b>without</b> an execpath. This is used to denote empty files in
31+
* runfiles and filesets.
32+
*/
33+
public static final VirtualActionInput EMPTY_MARKER = new EmptyActionInput();
3034

3135
/**
3236
* Gets a {@link ByteString} representation of the fake file. Used to avoid copying if the fake
@@ -48,15 +52,7 @@ default FileArtifactValue getMetadata() throws IOException {
4852
* use instances of this class to represent those files.
4953
*/
5054
final class EmptyActionInput implements VirtualActionInput {
51-
private final PathFragment execPath;
52-
53-
public EmptyActionInput(PathFragment execPath) {
54-
this.execPath = Preconditions.checkNotNull(execPath);
55-
}
56-
57-
public EmptyActionInput(String execPath) {
58-
this(PathFragment.create(execPath));
59-
}
55+
private EmptyActionInput() {}
6056

6157
@Override
6258
public boolean isSymlink() {
@@ -65,12 +61,12 @@ public boolean isSymlink() {
6561

6662
@Override
6763
public String getExecPathString() {
68-
return execPath.getPathString();
64+
throw new UnsupportedOperationException("empty virtual artifact doesn't have an execpath");
6965
}
7066

7167
@Override
7268
public PathFragment getExecPath() {
73-
return execPath;
69+
throw new UnsupportedOperationException("empty virtual artifact doesn't have an execpath");
7470
}
7571

7672
@Override
@@ -85,7 +81,7 @@ public ByteString getBytes() throws IOException {
8581

8682
@Override
8783
public String toString() {
88-
return "EmptyActionInput: " + execPath;
84+
return "EmptyActionInput";
8985
}
9086
}
9187
}

src/main/java/com/google/devtools/build/lib/exec/SpawnInputExpander.java

+6-8
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
import com.google.devtools.build.lib.actions.MetadataProvider;
3131
import com.google.devtools.build.lib.actions.RunfilesSupplier;
3232
import com.google.devtools.build.lib.actions.Spawn;
33-
import com.google.devtools.build.lib.actions.cache.VirtualActionInput.EmptyActionInput;
33+
import com.google.devtools.build.lib.actions.cache.VirtualActionInput;
3434
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
3535
import com.google.devtools.build.lib.collect.nestedset.Order;
3636
import com.google.devtools.build.lib.vfs.Path;
@@ -48,8 +48,6 @@
4848
* laid out.
4949
*/
5050
public class SpawnInputExpander {
51-
public static final ActionInput EMPTY_FILE = new EmptyActionInput("/dev/null");
52-
5351
private final Path execRoot;
5452
private final boolean strict;
5553
private final RelativeSymlinkBehavior relSymlinkBehavior;
@@ -148,7 +146,7 @@ void addRunfilesToInputs(
148146
addMapping(inputMap, location, localArtifact);
149147
}
150148
} else {
151-
addMapping(inputMap, location, EMPTY_FILE);
149+
addMapping(inputMap, location, VirtualActionInput.EMPTY_MARKER);
152150
}
153151
}
154152
}
@@ -196,10 +194,10 @@ void addFilesetManifest(
196194

197195
for (Map.Entry<PathFragment, String> mapping : filesetManifest.getEntries().entrySet()) {
198196
String value = mapping.getValue();
199-
ActionInput artifact =
200-
value == null
201-
? EMPTY_FILE
202-
: ActionInputHelper.fromPath(execRoot.getRelative(value).getPathString());
197+
ActionInput artifact =
198+
value == null
199+
? VirtualActionInput.EMPTY_MARKER
200+
: ActionInputHelper.fromPath(execRoot.getRelative(value).getPathString());
203201
addMapping(inputMappings, mapping.getKey(), artifact);
204202
}
205203
}

src/test/java/com/google/devtools/build/lib/exec/SpawnInputExpanderTest.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import com.google.devtools.build.lib.actions.FilesetOutputSymlink;
3636
import com.google.devtools.build.lib.actions.RunfilesSupplier;
3737
import com.google.devtools.build.lib.actions.Spawn;
38+
import com.google.devtools.build.lib.actions.cache.VirtualActionInput;
3839
import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
3940
import com.google.devtools.build.lib.analysis.Runfiles;
4041
import com.google.devtools.build.lib.analysis.RunfilesSupplierImpl;
@@ -251,7 +252,7 @@ public void testRunfilesRootSymlink() throws Exception {
251252
// directory gets created.
252253
assertThat(inputMappings)
253254
.containsEntry(
254-
PathFragment.create("runfiles/workspace/.runfile"), SpawnInputExpander.EMPTY_FILE);
255+
PathFragment.create("runfiles/workspace/.runfile"), VirtualActionInput.EMPTY_MARKER);
255256
}
256257

257258
@Test

src/test/java/com/google/devtools/build/lib/remote/RemoteActionInputFetcherTest.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
import com.google.devtools.build.lib.actions.cache.VirtualActionInput;
3737
import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
3838
import com.google.devtools.build.lib.clock.JavaClock;
39-
import com.google.devtools.build.lib.exec.SpawnInputExpander;
4039
import com.google.devtools.build.lib.remote.options.RemoteOptions;
4140
import com.google.devtools.build.lib.remote.util.DigestUtil;
4241
import com.google.devtools.build.lib.remote.util.InMemoryCacheClient;
@@ -141,7 +140,7 @@ public void testStagingEmptyVirtualActionInput() throws Exception {
141140

142141
// act
143142
actionInputFetcher.prefetchFiles(
144-
ImmutableList.of(SpawnInputExpander.EMPTY_FILE), metadataProvider);
143+
ImmutableList.of(VirtualActionInput.EMPTY_MARKER), metadataProvider);
145144

146145
// assert that nothing happened
147146
assertThat(actionInputFetcher.downloadedFiles()).isEmpty();

0 commit comments

Comments
 (0)