Fix emulator build error
[platform/framework/web/chromium-efl.git] / base / command_line_fuzzer.cc
1 // Copyright 2022 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <fuzzer/FuzzedDataProvider.h>
6 #include <stdint.h>
7
8 #include <algorithm>
9 #include <string>
10 #include <tuple>
11
12 #include "base/check.h"
13 #include "base/command_line.h"
14 #include "base/files/file_path.h"
15 #include "base/ranges/algorithm.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "build/build_config.h"
19
20 namespace base {
21
22 namespace {
23
24 CommandLine::StringType GenerateNativeString(FuzzedDataProvider& provider) {
25   const std::string raw_string = provider.ConsumeRandomLengthString();
26 #if BUILDFLAG(IS_WIN)
27   return UTF8ToWide(raw_string);
28 #else
29   return raw_string;
30 #endif
31 }
32
33 CommandLine::StringVector GenerateNativeStringVector(
34     FuzzedDataProvider& provider) {
35   CommandLine::StringVector strings(
36       provider.ConsumeIntegralInRange<int>(0, 100));
37   for (auto& item : strings)
38     item = GenerateNativeString(provider);
39   return strings;
40 }
41
42 FilePath GenerateFilePath(FuzzedDataProvider& provider) {
43   return FilePath(GenerateNativeString(provider));
44 }
45
46 bool IsForbiddenSwitchCharacter(char c) {
47   return IsAsciiWhitespace(c) || c == '=' || c != ToLowerASCII(c);
48 }
49
50 bool IsValidSwitchName(const std::string& text) {
51   // This duplicates the logic in command_line.cc, but it's not exposed in form
52   // of public interface.
53   return !text.empty() && !ranges::any_of(text, IsForbiddenSwitchCharacter) &&
54          !StartsWith(text, "-") && !StartsWith(text, "/");
55 }
56
57 }  // namespace
58
59 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
60   FuzzedDataProvider provider(data, size);
61
62   // Create a randomly initialized command line.
63   CommandLine command_line(CommandLine::NO_PROGRAM);
64   switch (provider.ConsumeIntegralInRange<int>(0, 3)) {
65     case 0:
66       // Leave empty.
67       break;
68     case 1:
69       command_line = CommandLine(GenerateFilePath(provider));
70       break;
71     case 2:
72       command_line = CommandLine(GenerateNativeStringVector(provider));
73       break;
74     case 3:
75 #if BUILDFLAG(IS_WIN)
76       command_line.ParseFromString(GenerateNativeString(provider));
77 #endif
78       break;
79   }
80
81   // Do a few mutations of the command line.
82   while (provider.remaining_bytes() > 0) {
83     switch (provider.ConsumeIntegralInRange<int>(0, 4)) {
84       case 0: {
85         // Add a switch.
86         std::string name = provider.ConsumeRandomLengthString();
87         if (IsValidSwitchName(name)) {
88           CommandLine::StringType value = GenerateNativeString(provider);
89           command_line.AppendSwitchNative(name, value);
90           CHECK(command_line.HasSwitch(name));
91           CHECK(command_line.GetSwitchValueNative(name) == value);
92         }
93         break;
94       }
95       case 1: {
96         // Remove a switch.
97         std::string name = provider.ConsumeRandomLengthString();
98         if (IsValidSwitchName(name)) {
99           command_line.RemoveSwitch(name);
100           CHECK(!command_line.HasSwitch(name));
101           CHECK(command_line.GetSwitchValueNative(name).empty());
102         }
103         break;
104       }
105       case 2: {
106         // Add an argument.
107         CommandLine::StringType arg = GenerateNativeString(provider);
108         if (!arg.empty() && IsStringASCII(arg))
109           command_line.AppendArgNative(arg);
110         break;
111       }
112       case 3: {
113         // Add a wrapper.
114         CommandLine::StringType wrapper = GenerateNativeString(provider);
115         if (!wrapper.empty())
116           command_line.PrependWrapper(wrapper);
117         break;
118       }
119       case 4: {
120         // Check a switch.
121         std::string name = provider.ConsumeRandomLengthString();
122         if (IsValidSwitchName(name)) {
123           std::ignore = command_line.HasSwitch(name);
124           std::ignore = command_line.GetSwitchValueNative(name);
125         }
126         break;
127       }
128     }
129
130     // Smoke-test various accessors.
131     std::ignore = command_line.GetCommandLineString();
132     std::ignore = command_line.GetArgumentsString();
133 #if BUILDFLAG(IS_WIN)
134     std::ignore = command_line.GetCommandLineStringForShell();
135     std::ignore = command_line.GetCommandLineStringWithUnsafeInsertSequences();
136 #endif
137   }
138
139   return 0;
140 }
141
142 }  // namespace base