xref: /llvm-project/libc/fuzzing/stdlib/strtointeger_differential_fuzz.cpp (revision b6bc9d72f65a5086f310f321e969d96e9a559e75)
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