blob: 0513772a765c329c1b214f764623b209b3d2b165 [file] [log] [blame]
// Copyright 2022 The Centipede 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.
// Centipede puzzle: almost no control flow, needs paths to find the goal.
// We disable use_dataflow_features because on this puzzle
// it is also effective.
// RUN: Run --use_dataflow_features=0 --path_level=10
// RUN: ExpectInLog "Input bytes.*: .x1.x2.x3"
// This puzzle aborts on input "\x1\x2\x3"
// The code here has very little control flow, but an exponential number of
// call paths. The input above triggers a call sequence F1->F2->F3.
// The value `sink` generated by these functions represents the call sequence.
// The goal of this test is to verify that "bounded-path" features work.
#include <cstddef>
#include <cstdint>
static volatile uint64_t sink;
using Func = void (*)();
template <size_t kIdx>
static void F() {
sink = sink * 16 + kIdx;
}
void FN() {}
// All functions in an array.
static Func table[256] = {
F<0>, F<1>, F<2>, F<3>, F<4>, F<5>, F<6>, F<7>,
F<8>, F<9>, F<10>, F<11>, F<12>, F<13>, F<14>, F<15>,
// The rest are set to FN below.
};
// Set table[16:256] to FN.
struct TableCtor {
TableCtor() {
for (size_t i = 16; i < 256; ++i) table[i] = FN;
}
};
[[maybe_unused]] static TableCtor table_ctor;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
if (size != 3) return -1;
sink = 0;
table[data[0]]();
table[data[1]]();
table[data[2]]();
sink /= 0x123 - sink; // Generates a crash (div by zero) w/o a control flow.
return 0;
}