mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-06 07:51:47 +00:00
fuzz: wire Logger output for single-input repro runs
Logger::SetOutput was never called by the harness, so every parse warning/error (e.g. "Overwriting instance with name #N") was silently discarded. This directly cost time root-causing a leak: grepping stdout for an expected warning found nothing, looking like it ruled out a hypothesis that was actually correct, because the message was just never printed anywhere. Only enable it when the binary is given an explicit file argument (single-input repro, e.g. `-runs=1 <file>`), not during a real campaign against a corpus directory, where logging on every execution would dominate the runtime. Verified with -fsyntax-only against this branch's headers (a real CMake build of ifcviewer-wgpu wasn't attempted, same as the harness's prior namespace-rename commit). Generated with the assistance of an AI coding tool. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -56,6 +56,14 @@ invalid `.ifc` files works as a starting corpus; a dictionary of STEP/IFC
|
||||
tokens (`ISO-10303-21`, `HEADER`, common `IFCxxx` entity names, etc.) passed
|
||||
via `-dict=` measurably helps the mutator get past the header boilerplate.
|
||||
|
||||
### Log output
|
||||
|
||||
`Logger` output is only wired up when the binary is run against an explicit
|
||||
file argument (e.g. `-runs=1 <file>`), not during a real campaign against a
|
||||
corpus directory - logging every parse warning on every execution of a
|
||||
fuzzing campaign would dominate the runtime. Repro runs print
|
||||
`[Warning]`/`[Error]` messages to stderr.
|
||||
|
||||
### Leak detection
|
||||
|
||||
`run.sh` sets `ASAN_OPTIONS=detect_leaks=0` by default. A leak that used to
|
||||
|
||||
@@ -23,11 +23,37 @@
|
||||
// observing IfcConvert's exit code.
|
||||
|
||||
#include "ifcparse/file.h"
|
||||
#include "ifcparse/logger.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <sys/stat.h>
|
||||
|
||||
namespace {
|
||||
bool is_regular_file(const char* path) {
|
||||
struct stat st;
|
||||
return ::stat(path, &st) == 0 && S_ISREG(st.st_mode);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// libFuzzer runs in two modes: a real fuzzing campaign (given corpus
|
||||
// directories to mutate from, executed millions of times) and a
|
||||
// single-input repro (given one or more explicit file paths, e.g.
|
||||
// `-runs=1 crashes/<hash>/input`). logger::set_output is only wired up for
|
||||
// the latter -- logging every parse warning to a stream on every execution
|
||||
// of a real campaign would dominate the runtime.
|
||||
extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
|
||||
for (int i = 1; i < *argc; ++i) {
|
||||
if (is_regular_file((*argv)[i])) {
|
||||
logger::root().set_output(&std::cerr, &std::cerr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
if (size == 0 || size > static_cast<size_t>(std::numeric_limits<int>::max())) {
|
||||
|
||||
Reference in New Issue
Block a user