| // 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; |
| } |