xref: /llvm-project/libc/fuzzing/stdio/printf_parser_fuzz.cpp (revision b6bc9d72f65a5086f310f321e969d96e9a559e75)
1f6b724f1SMichael Jones //===-- printf_parser_fuzz.cpp --------------------------------------------===//
2f6b724f1SMichael Jones //
3f6b724f1SMichael Jones // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4f6b724f1SMichael Jones // See https://llvm.org/LICENSE.txt for license information.
5f6b724f1SMichael Jones // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f6b724f1SMichael Jones //
7f6b724f1SMichael Jones //===----------------------------------------------------------------------===//
8f6b724f1SMichael Jones ///
9f6b724f1SMichael Jones /// Fuzzing test for llvm-libc qsort implementation.
10f6b724f1SMichael Jones ///
11f6b724f1SMichael Jones //===----------------------------------------------------------------------===//
12f6b724f1SMichael Jones 
13f6b724f1SMichael Jones #include "src/__support/arg_list.h"
14f6b724f1SMichael Jones #include "src/stdio/printf_core/parser.h"
15f6b724f1SMichael Jones 
16f6b724f1SMichael Jones #include <stdarg.h>
17f6b724f1SMichael Jones #include <stdint.h>
18f6b724f1SMichael Jones 
19*b6bc9d72SGuillaume Chatelet using namespace LIBC_NAMESPACE;
20f6b724f1SMichael Jones 
21f6b724f1SMichael Jones // The design for the printf parser fuzzer is fairly simple. The parser uses a
22f6b724f1SMichael Jones // mock arg list that will never fail, and is passed a randomized string. The
23f6b724f1SMichael Jones // format sections it outputs are checked against a count of the number of '%'
24f6b724f1SMichael Jones // signs are in the original string. This is a fairly basic test, and the main
25f6b724f1SMichael Jones // intent is to run this under sanitizers, which will check for buffer overruns.
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)26f6b724f1SMichael Jones extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
27f6b724f1SMichael Jones   char *in_str = new char[size + 1];
28f6b724f1SMichael Jones 
29f6b724f1SMichael Jones   for (size_t i = 0; i < size; ++i)
30f6b724f1SMichael Jones     in_str[i] = data[i];
31f6b724f1SMichael Jones 
32f6b724f1SMichael Jones   in_str[size] = '\0';
33f6b724f1SMichael Jones 
34f6b724f1SMichael Jones   auto mock_arg_list = internal::MockArgList();
35f6b724f1SMichael Jones 
36e0be78beSJoseph Huber   auto parser =
37e0be78beSJoseph Huber       printf_core::Parser<internal::MockArgList>(in_str, mock_arg_list);
38f6b724f1SMichael Jones 
39f6b724f1SMichael Jones   int str_percent_count = 0;
40f6b724f1SMichael Jones 
41f6b724f1SMichael Jones   for (size_t i = 0; i < size && in_str[i] != '\0'; ++i) {
42f6b724f1SMichael Jones     if (in_str[i] == '%') {
43f6b724f1SMichael Jones       ++str_percent_count;
44f6b724f1SMichael Jones     }
45f6b724f1SMichael Jones   }
46f6b724f1SMichael Jones 
47f6b724f1SMichael Jones   int section_percent_count = 0;
48f6b724f1SMichael Jones 
49f6b724f1SMichael Jones   for (printf_core::FormatSection cur_section = parser.get_next_section();
50f6b724f1SMichael Jones        !cur_section.raw_string.empty();
51f6b724f1SMichael Jones        cur_section = parser.get_next_section()) {
52f6b724f1SMichael Jones     if (cur_section.has_conv) {
53f6b724f1SMichael Jones       ++section_percent_count;
54f6b724f1SMichael Jones       if (cur_section.conv_name == '%') {
55f6b724f1SMichael Jones         ++section_percent_count;
56f6b724f1SMichael Jones       }
57f6b724f1SMichael Jones     } else if (cur_section.raw_string[0] == '%') {
58f6b724f1SMichael Jones       // If the conversion would be undefined, it's instead raw, but it still
59f6b724f1SMichael Jones       // starts with a %.
60f6b724f1SMichael Jones       ++section_percent_count;
61f6b724f1SMichael Jones     }
62f6b724f1SMichael Jones   }
63f6b724f1SMichael Jones 
64f6b724f1SMichael Jones   if (str_percent_count != section_percent_count) {
65f6b724f1SMichael Jones     __builtin_trap();
66f6b724f1SMichael Jones   }
67f6b724f1SMichael Jones 
68f6b724f1SMichael Jones   delete[] in_str;
69f6b724f1SMichael Jones   return 0;
70f6b724f1SMichael Jones }
71