You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
109 lines
3.6 KiB
109 lines
3.6 KiB
// Copyright 2020 The Pigweed Authors
|
|
//
|
|
// 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.
|
|
|
|
// This file implements a basic fuzz test for the Detokenizer.
|
|
// An instance of the Detokenizer is created from a minimal, nearly-empty token
|
|
// database. Fuzz data is fed to the detokenizer in various supported input
|
|
// argument formats at random, when then decodes this data and tries to match
|
|
// it to tokens in the database.
|
|
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
#include <vector>
|
|
|
|
#include "pw_fuzzer/fuzzed_data_provider.h"
|
|
#include "pw_preprocessor/util.h"
|
|
#include "pw_tokenizer/detokenize.h"
|
|
|
|
namespace pw::tokenizer {
|
|
namespace {
|
|
|
|
constexpr size_t kFuzzRangeMin = 0;
|
|
constexpr size_t kFuzzRangeMax = 10000;
|
|
|
|
enum DetokenizeBufferArgumentType : uint8_t {
|
|
kSpan = 0,
|
|
kStringView,
|
|
kPtrAndLength,
|
|
kMaxValue = kPtrAndLength
|
|
};
|
|
|
|
// In order to better fuzz the detokenizer, rather than use an empty token
|
|
// database, we construct a minimal database with 4 entries out of a string
|
|
// literal array that matches the token database format (see token_database.h
|
|
// for detailed info on the database entry format)
|
|
alignas(TokenDatabase::RawEntry) constexpr char kBasicData[] =
|
|
"TOKENS\0\0"
|
|
"\x04\x00\x00\x00"
|
|
"\0\0\0\0"
|
|
"\x01\x00\x00\x00----"
|
|
"\x05\x00\x00\x00----"
|
|
"\xFF\x00\x00\x00----"
|
|
"\xFF\xEE\xEE\xDD----"
|
|
"One\0"
|
|
"TWO\0"
|
|
"333\0"
|
|
"FOUR";
|
|
|
|
} // namespace
|
|
|
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
|
static Detokenizer detokenizer(TokenDatabase::Create<kBasicData>());
|
|
|
|
FuzzedDataProvider provider(data, size);
|
|
|
|
while (provider.remaining_bytes() != 0) {
|
|
// Map the first word of the remaining fuzz data to a buffer argument
|
|
// type, and feed the Detokenizer with a random length buffer to be
|
|
// detokenized in the relevant format. The detokenized string returned
|
|
// is itself of little consequence to this test.
|
|
switch (provider.ConsumeEnum<DetokenizeBufferArgumentType>()) {
|
|
case kSpan: {
|
|
size_t consumed_size = provider.ConsumeIntegralInRange<size_t>(
|
|
kFuzzRangeMin, kFuzzRangeMax);
|
|
std::vector<uint8_t> buffer =
|
|
provider.ConsumeBytes<uint8_t>(consumed_size);
|
|
auto detokenized_string =
|
|
detokenizer.Detokenize(std::span(&buffer[0], buffer.size()));
|
|
static_cast<void>(detokenized_string);
|
|
break;
|
|
}
|
|
|
|
case kStringView: {
|
|
std::string str =
|
|
provider.ConsumeRandomLengthString(provider.remaining_bytes());
|
|
auto detokenized_string = detokenizer.Detokenize(str);
|
|
static_cast<void>(detokenized_string);
|
|
break;
|
|
}
|
|
|
|
case kPtrAndLength: {
|
|
size_t consumed_size = provider.ConsumeIntegralInRange<size_t>(
|
|
kFuzzRangeMin, kFuzzRangeMax);
|
|
std::vector<uint8_t> buffer =
|
|
provider.ConsumeBytes<uint8_t>(consumed_size);
|
|
auto detokenized_string =
|
|
detokenizer.Detokenize(&buffer[0], buffer.size());
|
|
static_cast<void>(detokenized_string);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
} // namespace pw::tokenizer
|