1f1990febSMichael Jones //===-- strtointeger_differential_fuzz.cpp --------------------------------===//
2f1990febSMichael Jones //
3f1990febSMichael Jones // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4f1990febSMichael Jones // See https://llvm.org/LICENSE.txt for license information.
5f1990febSMichael Jones // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f1990febSMichael Jones //
7f1990febSMichael Jones //===----------------------------------------------------------------------===//
8f1990febSMichael Jones ///
9f1990febSMichael Jones /// Fuzzing test for llvm-libc atof implementation.
10f1990febSMichael Jones ///
11f1990febSMichael Jones //===----------------------------------------------------------------------===//
12f1990febSMichael Jones #include "src/stdlib/atoi.h"
13f1990febSMichael Jones #include "src/stdlib/atol.h"
14f1990febSMichael Jones #include "src/stdlib/atoll.h"
15f1990febSMichael Jones #include "src/stdlib/strtol.h"
16f1990febSMichael Jones #include "src/stdlib/strtoll.h"
17f1990febSMichael Jones #include "src/stdlib/strtoul.h"
18f1990febSMichael Jones #include "src/stdlib/strtoull.h"
19f1990febSMichael Jones #include <stddef.h>
20f1990febSMichael Jones #include <stdint.h>
21f1990febSMichael Jones #include <stdlib.h>
22f1990febSMichael Jones
23f1990febSMichael Jones #include "fuzzing/stdlib/StringParserOutputDiff.h"
24f1990febSMichael Jones
25f1990febSMichael Jones // This list contains (almost) all character that can possibly be accepted by a
26f1990febSMichael Jones // string to integer conversion. Those are: space, tab, +/- signs, any digit,
27f1990febSMichael Jones // and any letter. Technically there are some space characters accepted by
28f1990febSMichael Jones // isspace that aren't in this list, but since space characters are just skipped
29f1990febSMichael Jones // over anyways I'm not really worried.
30f1990febSMichael Jones [[maybe_unused]] constexpr char VALID_CHARS[] = {
31f1990febSMichael Jones ' ', '\t', '-', '+', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
32f1990febSMichael Jones 'a', 'A', 'b', 'B', 'c', 'C', 'd', 'D', 'e', 'E', 'f', 'F', 'g', 'G',
33f1990febSMichael Jones 'h', 'H', 'i', 'I', 'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N',
34f1990febSMichael Jones 'o', 'O', 'p', 'P', 'q', 'Q', 'r', 'R', 's', 'S', 't', 'T', 'u', 'U',
35f1990febSMichael Jones 'v', 'V', 'w', 'W', 'x', 'X', 'y', 'Y', 'z', 'Z'};
36f1990febSMichael Jones
37f1990febSMichael Jones // This takes the randomized bytes in data and interprets the first byte as the
38f1990febSMichael Jones // base for the string to integer conversion and the rest of them as a string to
39f1990febSMichael Jones // be passed to the string to integer conversion.
40f1990febSMichael Jones // If the CLEANER_INPUT flag is set, the string is modified so that it's only
41f1990febSMichael Jones // made of characters that the string to integer functions could accept. This is
42f1990febSMichael Jones // because every other character is effectively identical, and will be treated
43f1990febSMichael Jones // as the end of the integer. For the fully randomized string this gives a
44f1990febSMichael Jones // greater than 50% chance for each character to end the string, making the odds
45f1990febSMichael Jones // of getting long numbers very low.
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)46f1990febSMichael Jones extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
47f1990febSMichael Jones uint8_t *container = new uint8_t[size + 1];
48f1990febSMichael Jones if (!container)
49f1990febSMichael Jones __builtin_trap();
50f1990febSMichael Jones size_t i;
51f1990febSMichael Jones
52f1990febSMichael Jones for (i = 0; i < size; ++i) {
53c3228714SGuillaume Chatelet #ifdef LIBC_COPT_FUZZ_ATOI_CLEANER_INPUT
54f1990febSMichael Jones container[i] = VALID_CHARS[data[i] % sizeof(VALID_CHARS)];
55f1990febSMichael Jones #else
56f1990febSMichael Jones container[i] = data[i];
57f1990febSMichael Jones #endif
58f1990febSMichael Jones }
59f1990febSMichael Jones container[size] = '\0'; // Add null terminator to container.
60f1990febSMichael Jones // the first character is interpreted as the base, so it should be fully
61f1990febSMichael Jones // random even when the input is cleaned.
62f1990febSMichael Jones container[0] = data[0];
63f1990febSMichael Jones
64*b6bc9d72SGuillaume Chatelet StringParserOutputDiff<int>(&LIBC_NAMESPACE::atoi, &::atoi, container, size);
65*b6bc9d72SGuillaume Chatelet StringParserOutputDiff<long>(&LIBC_NAMESPACE::atol, &::atol, container, size);
66*b6bc9d72SGuillaume Chatelet StringParserOutputDiff<long long>(&LIBC_NAMESPACE::atoll, &::atoll, container,
67f1990febSMichael Jones size);
68f1990febSMichael Jones
69*b6bc9d72SGuillaume Chatelet StringToNumberOutputDiff<long>(&LIBC_NAMESPACE::strtol, &::strtol, container,
70f1990febSMichael Jones size);
71*b6bc9d72SGuillaume Chatelet StringToNumberOutputDiff<long long>(&LIBC_NAMESPACE::strtoll, &::strtoll,
72f1990febSMichael Jones container, size);
73f1990febSMichael Jones
74*b6bc9d72SGuillaume Chatelet StringToNumberOutputDiff<unsigned long>(&LIBC_NAMESPACE::strtoul, &::strtoul,
75f1990febSMichael Jones container, size);
76*b6bc9d72SGuillaume Chatelet StringToNumberOutputDiff<unsigned long long>(&LIBC_NAMESPACE::strtoull,
77f1990febSMichael Jones &::strtoull, container, size);
78f1990febSMichael Jones
79f1990febSMichael Jones delete[] container;
80f1990febSMichael Jones return 0;
81f1990febSMichael Jones }
82