xref: /cloud-hypervisor/fuzz/fuzz_targets/vhdx.rs (revision 2fe7f54ece2a8f0461ed29aaeab41614f1f2da75)
1 // Copyright © 2021 Intel Corporation
2 //
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #![no_main]
6 use std::ffi;
7 use std::fs::File;
8 use std::io::{self, Read, Seek, SeekFrom, Write};
9 use std::os::unix::io::{FromRawFd, RawFd};
10 
11 use block::vhdx::Vhdx;
12 use libfuzzer_sys::{fuzz_target, Corpus};
13 
14 // Populate the corpus directory with a test file:
15 // truncate -s 16M /tmp/source
16 // qemu-img convert -O vhdx /tmp/source fuzz/corpus/vhdx/test.vhdx
17 // Run with:
18 // cargo fuzz run vhdx -j 32 -- -max_len=16777216
19 fuzz_target!(|bytes: &[u8]| -> Corpus {
20     let shm = memfd_create(&ffi::CString::new("fuzz").unwrap(), 0).unwrap();
21     let mut disk_file: File = unsafe { File::from_raw_fd(shm) };
22     disk_file.write_all(&bytes[..]).unwrap();
23     disk_file.seek(SeekFrom::Start(0)).unwrap();
24 
25     let mut vhdx = match Vhdx::new(disk_file) {
26         Ok(vhdx) => vhdx,
27         Err(_) => return Corpus::Reject,
28     };
29 
30     if matches!(vhdx.seek(SeekFrom::Start(0)).is_err(), true) {
31         return Corpus::Reject;
32     };
33 
34     let mut offset = 0;
35     while offset < bytes.len() {
36         let mut data = vec![0; 8192];
37         vhdx.read_exact(&mut data).ok();
38         offset += data.len();
39     }
40 
41     if matches!(vhdx.seek(SeekFrom::Start(0)).is_err(), true) {
42         return Corpus::Reject;
43     };
44 
45     offset = 0;
46     while offset < bytes.len() {
47         let data = vec![0; 8192];
48         vhdx.write_all(&data).ok();
49         offset += data.len();
50     }
51 
52     Corpus::Keep
53 });
54 
55 fn memfd_create(name: &ffi::CStr, flags: u32) -> Result<RawFd, io::Error> {
56     let res = unsafe { libc::syscall(libc::SYS_memfd_create, name.as_ptr(), flags) };
57 
58     if res < 0 {
59         Err(io::Error::last_os_error())
60     } else {
61         Ok(res as RawFd)
62     }
63 }
64