Solve potential corpus name conflict
Solve potential corpus name conflict
Fuzzing_corpus copies all corpus files into the same output directory,
if the name of any two corpus files are the same, then the process can't
be completed.
The make_corpus_dir.py will change the name a/b/c.txt to a-b-c.txt to
avoid the name conflict.
Signed-off-by: tengpeng <tengpeng.li2020@gmail.com>
modified: fuzzing/common.bzl
modified: fuzzing/tools/BUILD
new file: fuzzing/tools/make_corpus_dir.py
diff --git a/fuzzing/common.bzl b/fuzzing/common.bzl
index c1604a9..89e6555 100644
--- a/fuzzing/common.bzl
+++ b/fuzzing/common.bzl
@@ -84,16 +84,14 @@
def _fuzzing_corpus_impl(ctx):
corpus_dir = ctx.actions.declare_directory(ctx.attr.name)
cp_args = ctx.actions.args()
- cp_args.add_all(ctx.files.srcs)
+ cp_args.add_joined("--corpus_list", ctx.files.srcs, join_with = ",")
+ cp_args.add("--output_dir=" + corpus_dir.path)
- # Add destination to the arguments
- cp_args.add(corpus_dir.path)
-
- ctx.actions.run_shell(
+ ctx.actions.run(
inputs = ctx.files.srcs,
outputs = [corpus_dir],
arguments = [cp_args],
- command = "mkdir " + corpus_dir.path + "; cp -r $@",
+ executable = ctx.executable._corpus_tool,
)
return [DefaultInfo(
@@ -108,6 +106,12 @@
specified in the srcs attribute.
""",
attrs = {
+ "_corpus_tool": attr.label(
+ default = Label("//fuzzing/tools:make_corpus_dir"),
+ doc = "The tool script to copy and rename the corpus.",
+ executable = True,
+ cfg = "host",
+ ),
"srcs": attr.label_list(
doc = "The corpus files for the fuzzing test.",
allow_files = True,
diff --git a/fuzzing/tools/BUILD b/fuzzing/tools/BUILD
index c559a8f..bf81d24 100644
--- a/fuzzing/tools/BUILD
+++ b/fuzzing/tools/BUILD
@@ -27,6 +27,12 @@
)
py_binary(
+ name = "make_corpus_dir",
+ srcs = ["make_corpus_dir.py"],
+ visibility = ["//visibility:public"],
+)
+
+py_binary(
name = "validate_dict",
srcs = ["validate_dict.py"],
visibility = ["//visibility:public"],
diff --git a/fuzzing/tools/make_corpus_dir.py b/fuzzing/tools/make_corpus_dir.py
new file mode 100644
index 0000000..fd8a65f
--- /dev/null
+++ b/fuzzing/tools/make_corpus_dir.py
@@ -0,0 +1,65 @@
+#
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Lint as: python3
+"""
+Copies and renames a set of corpus files into a given directory.
+"""
+
+from absl import app
+from absl import flags
+from sys import stderr
+import glob
+import os
+import shutil
+
+FLAGS = flags.FLAGS
+
+flags.DEFINE_list("corpus_list", [],
+ "Each element in the list stands for a corpus file")
+
+flags.DEFINE_string("output_dir", None, "The path of the output directory")
+
+flags.mark_flag_as_required("output_dir")
+
+
+def main(argv):
+ if not os.path.exists(FLAGS.output_dir):
+ os.makedirs(FLAGS.output_dir)
+
+ expanded_file_list = []
+ for corpus in FLAGS.corpus_list:
+ if not os.path.exists(corpus):
+ print("ERROR: file " + corpus + " doesn't exist.", file=stderr)
+ return -1
+ if os.path.isdir(corpus):
+ # The first element in glob("dir/**") is "dir/", which needs to be excluded
+ expanded_file_list += glob.glob(os.path.join(corpus, "**"), recursive=True)[1:]
+ else:
+ expanded_file_list.append(corpus)
+
+ for corpus in expanded_file_list:
+ dest = os.path.join(FLAGS.output_dir, corpus.replace("/", "-"))
+ # Whatever the separator we choose, there is an chance that
+ # the dest name conflicts with another file
+ if os.path.exists(dest):
+ print("ERROR: file " + dest + " existed.", file=stderr)
+ return -1
+ shutil.copy(corpus, dest)
+ return 0
+
+
+if __name__ == '__main__':
+ app.run(main)