1*12e0d316SStefan Eßer /*
2*12e0d316SStefan Eßer * *****************************************************************************
3*12e0d316SStefan Eßer *
4*12e0d316SStefan Eßer * SPDX-License-Identifier: BSD-2-Clause
5*12e0d316SStefan Eßer *
6*12e0d316SStefan Eßer * Copyright (c) 2018-2024 Gavin D. Howard and contributors.
7*12e0d316SStefan Eßer *
8*12e0d316SStefan Eßer * Redistribution and use in source and binary forms, with or without
9*12e0d316SStefan Eßer * modification, are permitted provided that the following conditions are met:
10*12e0d316SStefan Eßer *
11*12e0d316SStefan Eßer * * Redistributions of source code must retain the above copyright notice, this
12*12e0d316SStefan Eßer * list of conditions and the following disclaimer.
13*12e0d316SStefan Eßer *
14*12e0d316SStefan Eßer * * Redistributions in binary form must reproduce the above copyright notice,
15*12e0d316SStefan Eßer * this list of conditions and the following disclaimer in the documentation
16*12e0d316SStefan Eßer * and/or other materials provided with the distribution.
17*12e0d316SStefan Eßer *
18*12e0d316SStefan Eßer * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19*12e0d316SStefan Eßer * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*12e0d316SStefan Eßer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*12e0d316SStefan Eßer * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22*12e0d316SStefan Eßer * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23*12e0d316SStefan Eßer * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24*12e0d316SStefan Eßer * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25*12e0d316SStefan Eßer * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26*12e0d316SStefan Eßer * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27*12e0d316SStefan Eßer * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28*12e0d316SStefan Eßer * POSSIBILITY OF SUCH DAMAGE.
29*12e0d316SStefan Eßer *
30*12e0d316SStefan Eßer * *****************************************************************************
31*12e0d316SStefan Eßer *
32*12e0d316SStefan Eßer * The entry point for libFuzzer when fuzzing dc.
33*12e0d316SStefan Eßer *
34*12e0d316SStefan Eßer */
35*12e0d316SStefan Eßer
36*12e0d316SStefan Eßer #include <setjmp.h>
37*12e0d316SStefan Eßer #include <string.h>
38*12e0d316SStefan Eßer
39*12e0d316SStefan Eßer #include <version.h>
40*12e0d316SStefan Eßer #include <status.h>
41*12e0d316SStefan Eßer #include <ossfuzz.h>
42*12e0d316SStefan Eßer #include <vm.h>
43*12e0d316SStefan Eßer #include <bc.h>
44*12e0d316SStefan Eßer #include <dc.h>
45*12e0d316SStefan Eßer
46*12e0d316SStefan Eßer uint8_t* bc_fuzzer_data;
47*12e0d316SStefan Eßer
48*12e0d316SStefan Eßer /// A boolean about whether we should use -c (false) or -C (true).
49*12e0d316SStefan Eßer static bool dc_C;
50*12e0d316SStefan Eßer
51*12e0d316SStefan Eßer int
LLVMFuzzerInitialize(int * argc,char *** argv)52*12e0d316SStefan Eßer LLVMFuzzerInitialize(int* argc, char*** argv)
53*12e0d316SStefan Eßer {
54*12e0d316SStefan Eßer BC_UNUSED(argc);
55*12e0d316SStefan Eßer
56*12e0d316SStefan Eßer if (argv == NULL || *argv == NULL)
57*12e0d316SStefan Eßer {
58*12e0d316SStefan Eßer dc_C = false;
59*12e0d316SStefan Eßer }
60*12e0d316SStefan Eßer else
61*12e0d316SStefan Eßer {
62*12e0d316SStefan Eßer char* name;
63*12e0d316SStefan Eßer
64*12e0d316SStefan Eßer // Get the basename
65*12e0d316SStefan Eßer name = strrchr((*argv)[0], BC_FILE_SEP);
66*12e0d316SStefan Eßer name = name == NULL ? (*argv)[0] : name + 1;
67*12e0d316SStefan Eßer
68*12e0d316SStefan Eßer // Figure out which to use.
69*12e0d316SStefan Eßer dc_C = (strcmp(name, "dc_fuzzer_C") == 0);
70*12e0d316SStefan Eßer }
71*12e0d316SStefan Eßer
72*12e0d316SStefan Eßer return 0;
73*12e0d316SStefan Eßer }
74*12e0d316SStefan Eßer
75*12e0d316SStefan Eßer int
LLVMFuzzerTestOneInput(const uint8_t * Data,size_t Size)76*12e0d316SStefan Eßer LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size)
77*12e0d316SStefan Eßer {
78*12e0d316SStefan Eßer BcStatus s;
79*12e0d316SStefan Eßer
80*12e0d316SStefan Eßer // I've already tested empty input, so just ignore.
81*12e0d316SStefan Eßer if (Size == 0 || Data[0] == '\0') return 0;
82*12e0d316SStefan Eßer
83*12e0d316SStefan Eßer // Clear the global. This is to ensure a clean start.
84*12e0d316SStefan Eßer memset(vm, 0, sizeof(BcVm));
85*12e0d316SStefan Eßer
86*12e0d316SStefan Eßer // Make sure to set the name.
87*12e0d316SStefan Eßer vm->name = "dc";
88*12e0d316SStefan Eßer
89*12e0d316SStefan Eßer BC_SIG_LOCK;
90*12e0d316SStefan Eßer
91*12e0d316SStefan Eßer // We *must* do this here. Otherwise, other code could not jump out all of
92*12e0d316SStefan Eßer // the way.
93*12e0d316SStefan Eßer bc_vec_init(&vm->jmp_bufs, sizeof(sigjmp_buf), BC_DTOR_NONE);
94*12e0d316SStefan Eßer
95*12e0d316SStefan Eßer BC_SETJMP_LOCKED(vm, exit);
96*12e0d316SStefan Eßer
97*12e0d316SStefan Eßer // Create a string with the data.
98*12e0d316SStefan Eßer bc_fuzzer_data = bc_vm_malloc(Size + 1);
99*12e0d316SStefan Eßer memcpy(bc_fuzzer_data, Data, Size);
100*12e0d316SStefan Eßer bc_fuzzer_data[Size] = '\0';
101*12e0d316SStefan Eßer
102*12e0d316SStefan Eßer s = dc_main((int) (bc_fuzzer_args_len - 1),
103*12e0d316SStefan Eßer dc_C ? dc_fuzzer_args_C : dc_fuzzer_args_c);
104*12e0d316SStefan Eßer
105*12e0d316SStefan Eßer exit:
106*12e0d316SStefan Eßer
107*12e0d316SStefan Eßer BC_SIG_MAYLOCK;
108*12e0d316SStefan Eßer
109*12e0d316SStefan Eßer free(bc_fuzzer_data);
110*12e0d316SStefan Eßer
111*12e0d316SStefan Eßer return s == BC_STATUS_SUCCESS || s == BC_STATUS_QUIT ? 0 : -1;
112*12e0d316SStefan Eßer }
113