Skip to content

Commit 0a6880d

Browse files
committed
Ignore invalid entries in the marker file
Especially due to #23127, older marker files may contain entries that don't even parse correctly. Instead of crashing Bazel, we should just ignore such entries. Fixes #23322.
1 parent c299b39 commit 0a6880d

File tree

2 files changed

+89
-11
lines changed

2 files changed

+89
-11
lines changed

src/main/java/com/google/devtools/build/lib/rules/repository/RepoRecordedInput.java

+45-11
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.google.devtools.build.lib.actions.FileValue;
2727
import com.google.devtools.build.lib.analysis.BlazeDirectories;
2828
import com.google.devtools.build.lib.cmdline.LabelConstants;
29+
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
2930
import com.google.devtools.build.lib.cmdline.LabelValidator;
3031
import com.google.devtools.build.lib.cmdline.RepositoryName;
3132
import com.google.devtools.build.lib.skyframe.ActionEnvironmentFunction;
@@ -76,8 +77,10 @@ public abstract static class Parser {
7677

7778
/**
7879
* Parses a recorded input from the post-colon substring that identifies the specific input: for
79-
* example, the {@code MY_ENV_VAR} part of {@code ENV:MY_ENV_VAR}.
80+
* example, the {@code MY_ENV_VAR} part of {@code ENV:MY_ENV_VAR}. Returns null if the parsed
81+
* part is invalid.
8082
*/
83+
@Nullable
8184
public abstract RepoRecordedInput parse(String s);
8285
}
8386

@@ -95,6 +98,9 @@ public abstract static class Parser {
9598
@Nullable
9699
public static RepoRecordedInput parse(String s) {
97100
List<String> parts = Splitter.on(':').limit(2).splitToList(s);
101+
if (parts.size() < 2) {
102+
return null;
103+
}
98104
for (Parser parser :
99105
new Parser[] {
100106
File.PARSER, Dirents.PARSER, DirTree.PARSER, EnvVar.PARSER, RecordedRepoMapping.PARSER
@@ -213,12 +219,12 @@ public final String toString() {
213219
return repoName().map(repoName -> repoName + "//" + path()).orElse(path().toString());
214220
}
215221

216-
public static RepoCacheFriendlyPath parse(String s) {
222+
public static RepoCacheFriendlyPath parse(String s) throws LabelSyntaxException {
217223
if (LabelValidator.isAbsolute(s)) {
218224
int doubleSlash = s.indexOf("//");
219225
int skipAts = s.startsWith("@@") ? 2 : s.startsWith("@") ? 1 : 0;
220226
return createInsideWorkspace(
221-
RepositoryName.createUnvalidated(s.substring(skipAts, doubleSlash)),
227+
RepositoryName.create(s.substring(skipAts, doubleSlash)),
222228
PathFragment.create(s.substring(doubleSlash + 2)));
223229
}
224230
return createOutsideWorkspace(PathFragment.create(s));
@@ -262,9 +268,15 @@ public String getPrefix() {
262268
return "FILE";
263269
}
264270

271+
@Nullable
265272
@Override
266273
public RepoRecordedInput parse(String s) {
267-
return new File(RepoCacheFriendlyPath.parse(s));
274+
try {
275+
return new File(RepoCacheFriendlyPath.parse(s));
276+
} catch (LabelSyntaxException e) {
277+
// ignore malformed input
278+
return null;
279+
}
268280
}
269281
};
270282

@@ -354,9 +366,15 @@ public String getPrefix() {
354366
return "DIRENTS";
355367
}
356368

369+
@Nullable
357370
@Override
358371
public RepoRecordedInput parse(String s) {
359-
return new Dirents(RepoCacheFriendlyPath.parse(s));
372+
try {
373+
return new Dirents(RepoCacheFriendlyPath.parse(s));
374+
} catch (LabelSyntaxException e) {
375+
// Ignore malformed input.
376+
return null;
377+
}
360378
}
361379
};
362380

@@ -437,9 +455,15 @@ public String getPrefix() {
437455
return "DIRTREE";
438456
}
439457

458+
@Nullable
440459
@Override
441460
public RepoRecordedInput parse(String s) {
442-
return new DirTree(RepoCacheFriendlyPath.parse(s));
461+
try {
462+
return new DirTree(RepoCacheFriendlyPath.parse(s));
463+
} catch (LabelSyntaxException e) {
464+
// ignore malformed input
465+
return null;
466+
}
443467
}
444468
};
445469

@@ -573,11 +597,16 @@ public String getPrefix() {
573597
return "REPO_MAPPING";
574598
}
575599

600+
@Nullable
576601
@Override
577602
public RepoRecordedInput parse(String s) {
578603
List<String> parts = Splitter.on(',').limit(2).splitToList(s);
579-
return new RecordedRepoMapping(
580-
RepositoryName.createUnvalidated(parts.get(0)), parts.get(1));
604+
try {
605+
return new RecordedRepoMapping(RepositoryName.create(parts.get(0)), parts.get(1));
606+
} catch (LabelSyntaxException | IndexOutOfBoundsException e) {
607+
// ignore malformed input
608+
return null;
609+
}
581610
}
582611
};
583612

@@ -632,9 +661,14 @@ public boolean isUpToDate(
632661
throws InterruptedException {
633662
RepositoryMappingValue repoMappingValue =
634663
(RepositoryMappingValue) env.getValue(getSkyKey(directories));
635-
return repoMappingValue != RepositoryMappingValue.NOT_FOUND_VALUE
636-
&& RepositoryName.createUnvalidated(oldValue)
637-
.equals(repoMappingValue.getRepositoryMapping().get(apparentName));
664+
try {
665+
return repoMappingValue != RepositoryMappingValue.NOT_FOUND_VALUE
666+
&& RepositoryName.create(oldValue)
667+
.equals(repoMappingValue.getRepositoryMapping().get(apparentName));
668+
} catch (LabelSyntaxException e) {
669+
// ignore malformed old value
670+
return false;
671+
}
638672
}
639673
}
640674
}

src/test/shell/bazel/starlark_repository_test.sh

+44
Original file line numberDiff line numberDiff line change
@@ -2864,6 +2864,50 @@ EOF
28642864
expect_log "I see: something"
28652865
}
28662866

2867+
function test_bad_marker_file_ignored() {
2868+
# when reading a file in another repo, we should watch it.
2869+
local outside_dir="${TEST_TMPDIR}/outside_dir"
2870+
mkdir -p "${outside_dir}"
2871+
echo nothing > ${outside_dir}/data.txt
2872+
2873+
create_new_workspace
2874+
cat > $(setup_module_dot_bazel) <<EOF
2875+
foo = use_repo_rule("//:r.bzl", "foo")
2876+
foo(name = "foo")
2877+
bar = use_repo_rule("//:r.bzl", "bar")
2878+
bar(name = "bar", data = "nothing")
2879+
EOF
2880+
touch BUILD
2881+
cat > r.bzl <<EOF
2882+
def _foo(rctx):
2883+
rctx.file("BUILD", "filegroup(name='foo')")
2884+
# intentionally grab a file that's not directly addressable by a label
2885+
otherfile = rctx.path(Label("@bar//subpkg:BUILD")).dirname.dirname.get_child("data.txt")
2886+
print("I see: " + rctx.read(otherfile))
2887+
foo=repository_rule(_foo)
2888+
def _bar(rctx):
2889+
rctx.file("subpkg/BUILD")
2890+
rctx.file("data.txt", rctx.attr.data)
2891+
bar=repository_rule(_bar, attrs={"data":attr.string()})
2892+
EOF
2893+
2894+
bazel build @foo >& $TEST_log || fail "expected bazel to succeed"
2895+
expect_log "I see: nothing"
2896+
2897+
local marker_file=$(bazel info output_base)/external/@+_repo_rules+foo.marker
2898+
# the marker file for this repo should contain a reference to "@@+_repo_rules+bar". Mangle that.
2899+
sed -i'' -e 's/@@+_repo_rules+bar/@@LOL@@LOL/g' ${marker_file}
2900+
# add some more nonsensical lines for good measure...
2901+
echo 'BLAH:BLEH:BLOO BLEE' > ${marker_file}
2902+
echo 'no colons at all' > ${marker_file}
2903+
echo 'REPO_MAPPING:bad**bad,worse**worse gaaa'
2904+
echo 'REPO_MAPPING:bad,worse worst**worst'
2905+
2906+
# Running Bazel again shouldn't crash.
2907+
bazel shutdown
2908+
bazel build @foo >& $TEST_log || fail "expected bazel to succeed"
2909+
}
2910+
28672911
function test_file_watching_in_undefined_repo() {
28682912
create_new_workspace
28692913
cat > $(setup_module_dot_bazel) <<EOF

0 commit comments

Comments
 (0)