1 /* 2 * Copyright (c) Yann Collet, Meta Platforms, Inc. 3 * All rights reserved. 4 * 5 * This source code is licensed under both the BSD-style license (found in the 6 * LICENSE file in the root directory of this source tree) and the GPLv2 (found 7 * in the COPYING file in the root directory of this source tree). 8 * You may select, at your option, one of the above-listed licenses. 9 */ 10 11 #ifndef EXAMPLE_SEQ_PROD_H 12 #define EXAMPLE_SEQ_PROD_H 13 14 #define ZSTD_STATIC_LINKING_ONLY 15 #include "zstd.h" 16 17 #include <stdint.h> 18 19 #ifdef __cplusplus 20 extern "C" { 21 #endif 22 23 /* *** INTERFACE FOR FUZZING THIRD-PARTY SEQUENCE PRODUCER PLUGINS *** 24 * Fuzz-testing for the external sequence producer API was introduced in PR #3437. 25 * However, the setup in #3437 only allows fuzzers to exercise the implementation of the 26 * API itself (the code in the core zstd library which interacts with your plugin). 27 * 28 * This header defines an interface for plugin authors to link their code into the fuzzer 29 * build. Plugin authors can provide an object file implementing the symbols below, 30 * and those symbols will replace the default ones provided by #3437. 31 * 32 * To fuzz your plugin, follow these steps: 33 * - Build your object file with a recent version of clang. Building with gcc is not supported. 34 * - Build your object file using appropriate flags for fuzzing. For example: 35 * `-g -fno-omit-frame-pointer -fsanitize=undefined,address,fuzzer` 36 * - Build the fuzzer binaries with options corresponding to the flags you chose. Use --custom-seq-prod= to pass in your object file: 37 * `./fuzz.py build all --enable-fuzzer --enable-asan --enable-ubsan --cc clang --cxx clang++ --custom-seq-prod=your_object.o` 38 * 39 * An example implementation of this header is provided at tests/fuzz/seq_prod_fuzz_example/. 40 * Use these commands to fuzz with the example code: 41 * $ make corpora 42 * $ make -C seq_prod_fuzz_example/ 43 * $ python3 ./fuzz.py build all --enable-fuzzer --enable-asan --enable-ubsan --cc clang --cxx clang++ --custom-seq-prod=seq_prod_fuzz_example/example_seq_prod.o 44 * $ python3 ./fuzz.py libfuzzer simple_round_trip 45 */ 46 47 /* The fuzzer will call this function before each test-case. It should run any 48 * setup actions (such as starting a hardware device) needed for fuzzing. 49 * 50 * The fuzzer will assert() that the return value is zero. To signal an error, 51 * please return a non-zero value. */ 52 size_t FUZZ_seqProdSetup(void); 53 54 /* The fuzzer will call this function after each test-case. It should free 55 * resources acquired by FUZZ_seqProdSetup() to prevent leaks across test-cases. 56 * 57 * The fuzzer will assert() that the return value is zero. To signal an error, 58 * please return a non-zero value. */ 59 size_t FUZZ_seqProdTearDown(void); 60 61 /* The fuzzer will call this function before each test-case, only after calling 62 * FUZZ_seqProdSetup(), to obtain a sequence producer state which can be passed 63 * into ZSTD_registerSequenceProducer(). 64 * 65 * All compressions which are part of a test-case will share a single sequence 66 * producer state. Sharing the state object is safe because the fuzzers currently 67 * don't exercise the sequence producer API in multi-threaded scenarios. We may 68 * need a new approach in the future to support multi-threaded fuzzing. 69 * 70 * The fuzzer will assert() that the return value is not NULL. To signal an error, 71 * please return NULL. */ 72 void* FUZZ_createSeqProdState(void); 73 74 /* The fuzzer will call this function after each test-case. It should free any 75 * resources acquired by FUZZ_createSeqProdState(). 76 * 77 * The fuzzer will assert() that the return value is zero. To signal an error, 78 * please return a non-zero value. */ 79 size_t FUZZ_freeSeqProdState(void* sequenceProducerState); 80 81 /* This is the sequence producer function you would like to fuzz! It will receive 82 * the void* returned by FUZZ_createSeqProdState() on each invocation. */ 83 size_t FUZZ_thirdPartySeqProd(void* sequenceProducerState, 84 ZSTD_Sequence* outSeqs, size_t outSeqsCapacity, 85 const void* src, size_t srcSize, 86 const void* dict, size_t dictSize, 87 int compressionLevel, 88 size_t windowSize); 89 90 /* These macros are internal helpers. You do not need to worry about them. */ 91 #ifdef FUZZ_THIRD_PARTY_SEQ_PROD 92 #define FUZZ_SEQ_PROD_SETUP() \ 93 do { \ 94 FUZZ_ASSERT(FUZZ_seqProdSetup() == 0); \ 95 FUZZ_seqProdState = FUZZ_createSeqProdState(); \ 96 FUZZ_ASSERT(FUZZ_seqProdState != NULL); \ 97 } while (0) 98 #else 99 #define FUZZ_SEQ_PROD_SETUP() 100 #endif 101 102 #ifdef FUZZ_THIRD_PARTY_SEQ_PROD 103 #define FUZZ_SEQ_PROD_TEARDOWN() \ 104 do { \ 105 FUZZ_ASSERT(FUZZ_freeSeqProdState(FUZZ_seqProdState) == 0); \ 106 FUZZ_ASSERT(FUZZ_seqProdTearDown() == 0); \ 107 } while (0) 108 #else 109 #define FUZZ_SEQ_PROD_TEARDOWN() 110 #endif 111 112 #ifdef __cplusplus 113 } 114 #endif 115 116 #endif /* EXAMPLE_SEQ_PROD_H */ 117