1 | //===-- strtointeger_fuzz.cpp ---------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | /// |
9 | /// Fuzzing test for llvm-libc atof implementation. |
10 | /// |
11 | //===----------------------------------------------------------------------===// |
12 | #include "src/stdlib/atoi.h" |
13 | #include "src/stdlib/atol.h" |
14 | #include "src/stdlib/atoll.h" |
15 | #include "src/stdlib/strtol.h" |
16 | #include "src/stdlib/strtoll.h" |
17 | #include "src/stdlib/strtoul.h" |
18 | #include "src/stdlib/strtoull.h" |
19 | #include <stddef.h> |
20 | #include <stdint.h> |
21 | |
22 | // This takes the randomized bytes in data and interprets the first byte as the |
23 | // base for the string to integer conversion and the rest of them as a string to |
24 | // be passed to the string to integer conversion. |
25 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
26 | size_t container_size = 0; |
27 | if (size == 0) { |
28 | container_size = 1; |
29 | } else { |
30 | container_size = size; |
31 | } |
32 | uint8_t *container = new uint8_t[container_size]; |
33 | if (!container) |
34 | __builtin_trap(); |
35 | |
36 | int base = 0; |
37 | if (size > 0) { |
38 | base = data[0] % 36; |
39 | base = base + ((base == 0) ? 0 : 1); |
40 | } |
41 | for (size_t i = 1; i < size; ++i) { |
42 | container[i - 1] = data[i]; |
43 | } |
44 | |
45 | container[container_size - 1] = '\0'; // Add null terminator to container. |
46 | |
47 | const char *str_ptr = reinterpret_cast<const char *>(container); |
48 | |
49 | char *out_ptr = nullptr; |
50 | |
51 | auto volatile atoi_output = LIBC_NAMESPACE::atoi(str: str_ptr); |
52 | auto volatile atol_output = LIBC_NAMESPACE::atol(str: str_ptr); |
53 | auto volatile atoll_output = LIBC_NAMESPACE::atoll(str: str_ptr); |
54 | auto volatile strtol_output = LIBC_NAMESPACE::strtol(str: str_ptr, str_end: &out_ptr, base); |
55 | if (str_ptr + container_size - 1 < out_ptr) |
56 | __builtin_trap(); |
57 | auto volatile strtoll_output = |
58 | LIBC_NAMESPACE::strtoll(str: str_ptr, str_end: &out_ptr, base); |
59 | if (str_ptr + container_size - 1 < out_ptr) |
60 | __builtin_trap(); |
61 | auto volatile strtoul_output = |
62 | LIBC_NAMESPACE::strtoul(str: str_ptr, str_end: &out_ptr, base); |
63 | if (str_ptr + container_size - 1 < out_ptr) |
64 | __builtin_trap(); |
65 | auto volatile strtoull_output = |
66 | LIBC_NAMESPACE::strtoull(str: str_ptr, str_end: &out_ptr, base); |
67 | if (str_ptr + container_size - 1 < out_ptr) |
68 | __builtin_trap(); |
69 | |
70 | // If atoi is non-zero and the base is at least 10 |
71 | if (atoi_output != 0 && base >= 10) { |
72 | // Then all of the other functions should output non-zero values as well. |
73 | // This is a trivial check meant to silence the "unused variable" warnings. |
74 | if (atol_output == 0 || atoll_output == 0 || strtol_output == 0 || |
75 | strtoll_output == 0 || strtoul_output == 0 || strtoull_output == 0) { |
76 | __builtin_trap(); |
77 | } |
78 | } |
79 | |
80 | delete[] container; |
81 | return 0; |
82 | } |
83 | |