summaryrefslogtreecommitdiff
path: root/tests/cgpt_fuzzer.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/cgpt_fuzzer.c')
-rw-r--r--tests/cgpt_fuzzer.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/tests/cgpt_fuzzer.c b/tests/cgpt_fuzzer.c
new file mode 100644
index 00000000..51ba72a3
--- /dev/null
+++ b/tests/cgpt_fuzzer.c
@@ -0,0 +1,86 @@
+// Copyright 2019 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "cgptlib.h"
+#include "gpt.h"
+
+struct MockDisk {
+ size_t sector_shift;
+ const uint8_t* data;
+ size_t size;
+};
+
+// GPT disk parameters provided by the fuzzer test case. See GptData type
+// definition for details.
+struct GptDataParams {
+ uint32_t sector_shift;
+ uint32_t flags;
+ uint64_t streaming_drive_sectors;
+ uint64_t gpt_drive_sectors;
+} __attribute__((packed));
+
+static struct MockDisk mock_disk;
+
+vb2_error_t VbExDiskRead(VbExDiskHandle_t h, uint64_t lba_start,
+ uint64_t lba_count, void *buffer)
+{
+ size_t lba_size = mock_disk.size >> mock_disk.sector_shift;
+ if (lba_start > lba_size || lba_size - lba_start < lba_count) {
+ return VB2_ERROR_UNKNOWN;
+ }
+
+ size_t start = lba_start << mock_disk.sector_shift;
+ size_t size = lba_count << mock_disk.sector_shift;
+
+ memcpy(buffer, &mock_disk.data[start], size);
+ return VB2_SUCCESS;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
+
+int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ struct GptDataParams params;
+ if (size < sizeof(params)) {
+ return 0;
+ }
+ memcpy(&params, data, sizeof(params));
+
+ // Enforce a sane sector size. The sector size must accommodate the GPT
+ // header (the code assumes this) and large values don't make sense
+ // either (both in terms of actual hardware parameters and ability for
+ // the fuzzer to deal with effectively).
+ if (params.sector_shift < 9) {
+ params.sector_shift = 9; // 512 byte sectors min.
+ }
+ if (params.sector_shift > 12) {
+ params.sector_shift = 12; // 4K sectors max.
+ }
+
+ mock_disk.sector_shift = params.sector_shift;
+ mock_disk.data = data + sizeof(params);
+ mock_disk.size = size - sizeof(params);
+
+ GptData gpt;
+ memset(&gpt, 0, sizeof(gpt));
+ gpt.sector_bytes = 1ULL << params.sector_shift;
+ gpt.streaming_drive_sectors = params.streaming_drive_sectors;
+ gpt.gpt_drive_sectors = params.gpt_drive_sectors;
+ gpt.flags = params.flags;
+
+ if (0 == AllocAndReadGptData(0, &gpt)) {
+ int result = GptInit(&gpt);
+ while (GPT_SUCCESS == result) {
+ uint64_t part_start, part_size;
+ result = GptNextKernelEntry(&gpt, &part_start,
+ &part_size);
+ }
+ }
+
+ WriteAndFreeGptData(0, &gpt);
+
+ return 0;
+}