xref: /aosp_15_r20/external/gptfdisk/fuzzer/libgptf_fuzzer.cc (revision 57696d54d05c64fd1b1787f8371dbcf104911cfb)
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13 
14 #include <fstream>
15 #include <iostream>
16 #include <functional>
17 #include "diskio.h"
18 #include "gpt.h"
19 #include "parttypes.h"
20 
21 #include <fuzzer/FuzzedDataProvider.h>
22 
23 const int8_t kQuiet = 1;
24 const int8_t kMinRuns = 1;
25 const int8_t kGPTMaxRuns = 24;
26 const int16_t kMaxByte = 256;
27 const std::string kShowCommand = "show";
28 const std::string kGetCommand = "get";
29 const std::string kTempFile = "/dev/tempfile";
30 const std::string kNull = "/dev/null";
31 const std::string kBackup = "/dev/gptbackup";
32 const std::string kDoesNotExist = "/dev/does_not_exist";
33 
34 std::ofstream silence(kNull);
35 
36 class GptfFuzzer {
37 public:
GptfFuzzer(const uint8_t * data,size_t size)38   GptfFuzzer(const uint8_t *data, size_t size) : mFdp(data, size) {
39     mDisk.OpenForRead(static_cast<const unsigned char *>(data), size);
40   }
41 
~GptfFuzzer()42   ~GptfFuzzer() { mDisk.Close(); }
43 
44   void process();
45 
46 private:
47   void init();
48   FuzzedDataProvider mFdp;
49   DiskIO mDisk;
50   GPTData mGptData;
51 };
52 
init()53 void GptfFuzzer::init() {
54   if (mFdp.ConsumeBool()) {
55     mGptData.SetDisk(mDisk);
56   } else {
57     mGptData.SetDisk(kTempFile);
58   }
59 
60   uint64_t startSector = mFdp.ConsumeIntegral<uint64_t>();
61   uint64_t endSector =
62       mFdp.ConsumeIntegralInRange<uint64_t>(startSector, UINT64_MAX);
63   mGptData.CreatePartition(mFdp.ConsumeIntegral<uint8_t>() /* partNum */,
64                            startSector, endSector);
65 
66   const UnicodeString name = mFdp.ConsumeRandomLengthString(NAME_SIZE);
67   uint8_t partNum = mFdp.ConsumeIntegral<uint8_t>();
68   if (mGptData.SetName(partNum, name)) {
69     PartType pType;
70     mGptData.ChangePartType(partNum, pType);
71   }
72 
73   if (mFdp.ConsumeBool()) {
74     mGptData.SetAlignment(mFdp.ConsumeIntegral<uint32_t>() /* n */);
75   }
76 
77   if (mFdp.ConsumeBool()) {
78     GUIDData gData(mFdp.ConsumeRandomLengthString(kMaxByte));
79     gData.Randomize();
80     mGptData.SetDiskGUID(gData);
81     mGptData.SaveGPTBackup(kBackup);
82     mGptData.SetPartitionGUID(mFdp.ConsumeIntegral<uint8_t>() /* pn */, gData);
83   }
84 
85   if (mFdp.ConsumeBool()) {
86     mGptData.RandomizeGUIDs();
87   }
88 
89   if (mFdp.ConsumeBool()) {
90     mGptData.LoadGPTBackup(kBackup);
91   }
92 
93   if (mFdp.ConsumeBool()) {
94     mGptData.SaveGPTData(kQuiet);
95   }
96 
97   if (mFdp.ConsumeBool()) {
98     mGptData.SaveMBR();
99   }
100 }
101 
process()102 void GptfFuzzer::process() {
103   init();
104   int8_t runs = mFdp.ConsumeIntegralInRange<int32_t>(kMinRuns, kGPTMaxRuns);
105 
106   while (--runs && mFdp.remaining_bytes()) {
107     auto invokeGPTAPI = mFdp.PickValueInArray<const std::function<void()>>({
108         [&]() {
109           mGptData.XFormDisklabel(
110               mFdp.ConsumeIntegral<uint8_t>() /* partNum */);
111         },
112         [&]() {
113           mGptData.OnePartToMBR(mFdp.ConsumeIntegral<uint8_t>() /* gptPart */,
114                                 mFdp.ConsumeIntegral<uint8_t>() /* mbrPart */);
115         },
116         [&]() {
117           uint32_t numSegments;
118           uint64_t largestSegment;
119           mGptData.FindFreeBlocks(&numSegments, &largestSegment);
120         },
121         [&]() {
122           mGptData.FindFirstInLargest();
123         },
124         [&]() {
125           mGptData.FindLastAvailable();
126         },
127         [&]() {
128           mGptData.FindFirstFreePart();
129         },
130         [&]() {
131           mGptData.MoveMainTable(
132               mFdp.ConsumeIntegral<uint64_t>() /* pteSector */);
133         },
134         [&]() {
135           mGptData.Verify();
136         },
137         [&]() {
138           mGptData.SortGPT();
139         },
140         [&]() {
141           std::string command = mFdp.ConsumeBool() ? kShowCommand : kGetCommand;
142           std::string randomCommand = mFdp.ConsumeRandomLengthString(kMaxByte);
143           mGptData.ManageAttributes(
144               mFdp.ConsumeIntegral<uint8_t>() /* partNum */,
145               mFdp.ConsumeBool() ? command : randomCommand,
146               mFdp.ConsumeRandomLengthString(kMaxByte) /* bits */);
147         },
148     });
149     invokeGPTAPI();
150   }
151   if (mFdp.ConsumeBool()) {
152     mGptData.LoadPartitions(kDoesNotExist);
153   }
154   if (mFdp.ConsumeBool()) {
155     mGptData.SwapPartitions(mFdp.ConsumeIntegral<uint8_t>() /* partNum1 */,
156                             mFdp.ConsumeIntegral<uint8_t>() /* partNum2 */);
157   }
158   mGptData.DeletePartition(mFdp.ConsumeIntegral<uint8_t>() /* partNum */);
159   mGptData.DestroyMBR();
160   mGptData.DestroyGPT();
161 }
162 
LLVMFuzzerInitialize(int *,char ***)163 extern "C" int LLVMFuzzerInitialize(int *, char ***) {
164   std::cout.rdbuf(silence.rdbuf());
165   std::cerr.rdbuf(silence.rdbuf());
166   return 0;
167 }
168 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)169 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
170   GptfFuzzer gptfFuzzer(data, size);
171   gptfFuzzer.process();
172   return 0;
173 }
174