Files
carbon-lang/toolchain/lexer/tokenized_buffer_fuzzer.cpp
T
Jon Meow 8a2ef22c2a Validate source text size and fix empty buffer bugs. (#1113)
There's currently a bug with empty files, in that it initializes SourceBuffer with an invalid StringRef that results in a crash. That got me looking at the std::optional TODO, but the issue is that there are really three states:

- Buffered
- mmapped (not buffered)
- Moved out of (no longer initialized)

Technically an optional could work if we initialize the buffer on move out, indicating the mmap is gone. But the mode setup felt better to me.

And then this also adds the size check. Which is really how I started looking at this.
2022-03-02 13:43:03 -08:00

53 lines
1.9 KiB
C++

// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include <cstdint>
#include <cstring>
#include "common/check.h"
#include "llvm/ADT/StringRef.h"
#include "toolchain/diagnostics/diagnostic_emitter.h"
#include "toolchain/diagnostics/null_diagnostics.h"
#include "toolchain/lexer/tokenized_buffer.h"
namespace Carbon::Testing {
// NOLINTNEXTLINE: Match the documented fuzzer entry point declaration style.
extern "C" int LLVMFuzzerTestOneInput(const unsigned char* data,
std::size_t size) {
// Ignore large inputs.
// TODO: Investigate replacement with an error limit. Content with errors on
// escaped quotes (`\"` repeated) have O(M * N) behavior for M errors in a
// file length N, so either that will need to also be fixed or M will need to
// shrink for large (1MB+) inputs.
// This also affects parse_tree_fuzzer.cpp.
if (size > 100000) {
return 0;
}
auto source = SourceBuffer::CreateFromText(
llvm::StringRef(reinterpret_cast<const char*>(data), size));
auto buffer = TokenizedBuffer::Lex(*source, NullDiagnosticConsumer());
if (buffer.HasErrors()) {
return 0;
}
// Walk the lexed and tokenized buffer to ensure it isn't corrupt in some way.
//
// TODO: We should enhance this to do more sanity checks on the resulting
// token stream.
for (TokenizedBuffer::Token token : buffer.Tokens()) {
int line_number = buffer.GetLineNumber(token);
CHECK(line_number > 0) << "Invalid line number!";
CHECK(line_number < INT_MAX) << "Invalid line number!";
int column_number = buffer.GetColumnNumber(token);
CHECK(column_number > 0) << "Invalid line number!";
CHECK(column_number < INT_MAX) << "Invalid line number!";
}
return 0;
}
} // namespace Carbon::Testing