Skip to content

Commit bf10cc1

Browse files
fniksiccopybara-github
authored andcommitted
Reimplement ReadFilesFromDirectory(std::string_view) using an overload.
Note: This implementation check-fails in case of errors like non-existent path or files that cannot be read. This may break existing tests that were silently ignoring such errors. I included a number of smaller clean-ups (improving includes and dependencies). PiperOrigin-RevId: 748298417
1 parent 09422aa commit bf10cc1

File tree

4 files changed

+37
-46
lines changed

4 files changed

+37
-46
lines changed

fuzztest/BUILD

+1-3
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,13 @@ cc_library(
7676
"fuzztest_macros.h",
7777
],
7878
deps = [
79-
":io",
8079
":logging",
8180
":registration",
8281
":registry",
83-
"@abseil-cpp//absl/log:absl_check",
82+
":runtime",
8483
"@abseil-cpp//absl/status",
8584
"@abseil-cpp//absl/status:statusor",
8685
"@abseil-cpp//absl/strings",
87-
"@abseil-cpp//absl/strings:str_format",
8886
"@abseil-cpp//absl/strings:string_view",
8987
],
9088
)

fuzztest/CMakeLists.txt

+1-3
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,13 @@ fuzztest_cc_library(
6464
SRCS
6565
"fuzztest_macros.cc"
6666
DEPS
67-
fuzztest::io
6867
fuzztest::logging
6968
fuzztest::registration
7069
fuzztest::registry
71-
absl::absl_check
70+
fuzztest::runtime
7271
absl::status
7372
absl::statusor
7473
absl::strings
75-
absl::str_format
7674
absl::string_view
7775
)
7876

fuzztest/fuzztest_macros.cc

+29-30
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
// Copyright 2024 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
115
#include "./fuzztest/fuzztest_macros.h"
216

317
#include <cerrno>
@@ -12,14 +26,14 @@
1226
#include <utility>
1327
#include <vector>
1428

15-
#include "absl/log/absl_check.h"
1629
#include "absl/status/status.h"
30+
#include "absl/status/statusor.h"
1731
#include "absl/strings/escaping.h"
1832
#include "absl/strings/str_cat.h"
1933
#include "absl/strings/str_split.h"
2034
#include "absl/strings/string_view.h"
21-
#include "./fuzztest/internal/io.h"
2235
#include "./fuzztest/internal/logging.h"
36+
#include "./fuzztest/internal/runtime.h"
2337

2438
namespace fuzztest {
2539

@@ -67,26 +81,7 @@ absl::StatusOr<std::string> ParseDictionaryEntry(absl::string_view entry) {
6781

6882
std::vector<std::tuple<std::string>> ReadFilesFromDirectory(
6983
std::string_view dir) {
70-
std::vector<std::tuple<std::string>> out;
71-
const std::filesystem::path fs_dir(dir);
72-
if (!std::filesystem::is_directory(fs_dir)) return out;
73-
for (const auto& entry :
74-
std::filesystem::recursive_directory_iterator(fs_dir)) {
75-
if (std::filesystem::is_directory(entry)) continue;
76-
std::ifstream stream(entry.path());
77-
if (!stream.good()) {
78-
// Using stderr instead of GetStderr() to avoid
79-
// initialization-order-fiasco when reading files at static init time with
80-
// `.WithSeeds(fuzztest::ReadFilesFromDirectory(...))`.
81-
absl::FPrintF(stderr, "[!] %s:%d: Error reading %s: (%d) %s\n", __FILE__,
82-
__LINE__, entry.path().string(), errno, strerror(errno));
83-
continue;
84-
}
85-
std::stringstream buffer;
86-
buffer << stream.rdbuf();
87-
out.emplace_back(std::move(buffer).str());
88-
}
89-
return out;
84+
return ReadFilesFromDirectory(dir, [](std::string_view) { return true; });
9085
}
9186

9287
std::vector<std::tuple<std::string>> ReadFilesFromDirectory(
@@ -113,10 +108,11 @@ std::vector<std::tuple<std::string>> ReadFilesFromDirectory(
113108
}
114109

115110
absl::StatusOr<std::vector<std::string>> ParseDictionary(
116-
absl::string_view text) {
111+
std::string_view text) {
117112
std::vector<std::string> parsed_entries;
118113
int line_number = 0;
119-
for (absl::string_view line : absl::StrSplit(text, '\n')) {
114+
for (absl::string_view line :
115+
absl::StrSplit(absl::string_view{text.data(), text.size()}, '\n')) {
120116
++line_number;
121117

122118
if (line.empty() || line[0] == '#') continue;
@@ -154,17 +150,20 @@ std::vector<std::string> ReadDictionaryFromFile(
154150
"Not a file: ", dictionary_file);
155151
const std::filesystem::path fs_path(dictionary_file);
156152
std::ifstream stream(fs_path);
157-
ABSL_CHECK(stream.good()) << "Error reading " << fs_path.string() << ": ("
158-
<< errno << ") " << strerror(errno);
153+
FUZZTEST_INTERNAL_CHECK_PRECONDITION(stream.good(), "Error reading ",
154+
fs_path.string(), ": ", strerror(errno));
159155
std::stringstream buffer;
160156
buffer << stream.rdbuf();
161-
// https://llvm.org/docs/LibFuzzer.html#dictionaries
162157
absl::StatusOr<std::vector<std::string>> parsed_entries =
163158
ParseDictionary(buffer.str());
164-
ABSL_CHECK(parsed_entries.status().ok())
165-
<< "Could not parse dictionary file " << fs_path << ": "
166-
<< parsed_entries.status();
159+
FUZZTEST_INTERNAL_CHECK_PRECONDITION(
160+
parsed_entries.status().ok(), "Could not parse dictionary file ",
161+
fs_path.string(), ": ", parsed_entries.status());
167162
return *parsed_entries;
168163
}
169164

165+
void SkipTestsOrCurrentInput() {
166+
internal::Runtime::instance().SetSkippingRequested(true);
167+
}
168+
170169
} // namespace fuzztest

fuzztest/fuzztest_macros.h

+6-10
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,8 @@
2222
#include <tuple>
2323
#include <vector>
2424

25-
// IWYU pragma: begin_exports
2625
#include "absl/status/statusor.h"
27-
#include "absl/strings/str_format.h"
28-
#include "absl/strings/string_view.h"
26+
// IWYU pragma: begin_exports
2927
#include "./fuzztest/internal/registration.h"
3028
#include "./fuzztest/internal/registry.h"
3129
// IWYU pragma: end_exports
@@ -126,8 +124,6 @@ namespace fuzztest {
126124
// FUZZ_TEST(MySuite, MyThingNeverCrashes)
127125
// .WithSeeds(ReadFilesFromDirectory(kCorpusPath));
128126
//
129-
// TODO(b/380934093): Rewrite this function as ReadFilesFromDirectory(dir,
130-
// [](std::string_view name) { return true; });
131127
std::vector<std::tuple<std::string>> ReadFilesFromDirectory(
132128
std::string_view dir);
133129

@@ -150,12 +146,14 @@ std::vector<std::tuple<std::string>> ReadFilesFromDirectory(
150146
// Returns parsed dictionary entries from fuzzer dictionary definition in the
151147
// format specified at https://llvm.org/docs/LibFuzzer.html#dictionaries.
152148
// If dictionary is in wrong format, return error status.
153-
absl::StatusOr<std::vector<std::string>> ParseDictionary(
154-
absl::string_view text);
149+
absl::StatusOr<std::vector<std::string>> ParseDictionary(std::string_view text);
155150

156151
// Reads entries from `dictionary_file` and returns a vector usable by
157152
// .WithDictionary().
158153
//
154+
// The dictionary file should be in the format specified at
155+
// https://llvm.org/docs/LibFuzzer.html#dictionaries.
156+
//
159157
// Example:
160158
//
161159
// void MyThingNeverCrashes(const std::string& s) {
@@ -181,9 +179,7 @@ inline std::vector<uint8_t> ToByteArray(std::string_view str) {
181179
// Note that this function should not be called frequently due to engine
182180
// limitation and efficiency reasons. Consider refining the domain definitions
183181
// to restrict input generation if possible.
184-
inline void SkipTestsOrCurrentInput() {
185-
internal::Runtime::instance().SetSkippingRequested(true);
186-
}
182+
void SkipTestsOrCurrentInput();
187183

188184
} // namespace fuzztest
189185

0 commit comments

Comments
 (0)