xref: /aosp_15_r20/external/gptfdisk/fuzzer/basicmbr_fuzzer.cc (revision 57696d54d05c64fd1b1787f8371dbcf104911cfb)
1 /*
2  * Copyright (C) 2024 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 "mbr.h"
19 
20 #include <fuzzer/FuzzedDataProvider.h>
21 
22 const std::string kTempFile = "/dev/tempfile";
23 const std::string kNull = "/dev/null";
24 
25 std::ofstream silence(kNull);
26 
27 class BasicMBRFuzzer {
28 public:
BasicMBRFuzzer(const uint8_t * data,size_t size)29   BasicMBRFuzzer(const uint8_t *data, size_t size) : mFdp(data, size) {
30     mDisk.OpenForRead(static_cast<const unsigned char *>(data), size);
31   }
32 
~BasicMBRFuzzer()33   ~BasicMBRFuzzer() { mDisk.Close(); }
34 
35   void process();
36 
37 private:
38   DiskIO mDisk;
39   FuzzedDataProvider mFdp;
40 };
41 
process()42 void BasicMBRFuzzer::process() {
43   BasicMBRData mbrData;
44   if (mFdp.ConsumeBool()) {
45     BasicMBRData mbrDataFile(kTempFile);
46     mbrData = mbrDataFile;
47   }
48 
49   bool isLegal = false;
50 
51   while (mFdp.remaining_bytes()) {
52     auto invokeMBRAPI = mFdp.PickValueInArray<const std::function<void()>>({
53         [&]() {
54           mbrData.SetDisk(&mDisk);
55         },
56         [&]() {
57           if (mDisk.OpenForWrite(kTempFile)) {
58             mbrData.WriteMBRData(kTempFile);
59           }
60           mbrData.ReadMBRData(&mDisk);
61         },
62         [&]() {
63           uint32_t low, high;
64           mbrData.GetPartRange(&low, &high);
65         },
66         [&]() {
67           mbrData.MakeBiggestPart(mFdp.ConsumeIntegral<uint8_t>() /* index */,
68                                   mFdp.ConsumeIntegral<uint8_t>() /* type */);
69         },
70         [&]() {
71           mbrData.SetPartType(mFdp.ConsumeIntegral<uint8_t>() /* num */,
72                               mFdp.ConsumeIntegral<uint8_t>() /* type */);
73         },
74         [&]() {
75           mbrData.FindFirstInFree(mFdp.ConsumeIntegral<uint64_t>() /* start */);
76         },
77         [&]() {
78           mbrData.GetFirstSector(mFdp.ConsumeIntegral<uint8_t>() /* index */);
79         },
80         [&]() {
81           if (!isLegal) {
82             mbrData.MakeItLegal();
83             isLegal = true;
84           }
85         },
86     });
87     invokeMBRAPI();
88   }
89   mbrData.BlankGPTData();
90 }
91 
LLVMFuzzerInitialize(int *,char ***)92 extern "C" int LLVMFuzzerInitialize(int *, char ***) {
93   std::cout.rdbuf(silence.rdbuf());
94   std::cerr.rdbuf(silence.rdbuf());
95   return 0;
96 }
97 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)98 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
99   BasicMBRFuzzer basicMBRFuzzer(data, size);
100   basicMBRFuzzer.process();
101   return 0;
102 }
103