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