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)