diff --git a/fuzz/.gitignore b/fuzz/.gitignore new file mode 100644 index 00000000000..572e03bdf32 --- /dev/null +++ b/fuzz/.gitignore @@ -0,0 +1,4 @@ + +target +corpus +artifacts diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml new file mode 100644 index 00000000000..2d0358e0d75 --- /dev/null +++ b/fuzz/Cargo.toml @@ -0,0 +1,25 @@ + +[package] +name = "wayland-test-fuzz" +version = "0.0.1" +authors = ["Automatically generated"] +publish = false + +[package.metadata] +cargo-fuzz = true + +[dependencies.wayland-commons] +path = "../wayland-commons/" + +[dependencies.wayland-test] +path = ".." +[dependencies.libfuzzer-sys] +git = "https://github.com/rust-fuzz/libfuzzer-sys.git" + +# Prevent this from interfering with workspaces +[workspace] +members = ["."] + +[[bin]] +name = "message_parser" +path = "fuzz_targets/message_parser.rs" diff --git a/fuzz/fuzz_targets/message_parser.rs b/fuzz/fuzz_targets/message_parser.rs new file mode 100644 index 00000000000..e77173f9984 --- /dev/null +++ b/fuzz/fuzz_targets/message_parser.rs @@ -0,0 +1,46 @@ +#![no_main] +#[macro_use] extern crate libfuzzer_sys; +extern crate wayland_commons; + +use std::{mem, slice}; +use std::os::unix::io::RawFd; +use wayland_commons::wire::{Message, ArgumentType}; + +unsafe fn convert_slice(data: &[u8]) -> &[T] { + let n = mem::size_of::(); + slice::from_raw_parts( + data.as_ptr() as *const T, + data.len()/n, + ) +} + +fn get_arg_types(data: &[u8]) -> [ArgumentType; 16] { + use ArgumentType::*; + + let mut res = [Int; 16]; + assert_eq!(data.len(), 16); + for i in 0..16 { + res[i] = match data[i] & 0b111 { + 0 => Int, + 1 => Uint, + 2 => Fixed, + 3 => Str, + 4 => Object, + 5 => NewId, + 6 => Array, + 7 => Fd, + _ => unreachable!(), + } + } + res +} + +fuzz_target!(|data: &[u8]| { + if data.len() < 32 { return; } + // 4 `RawFd`s + let fds: &[RawFd] = unsafe { convert_slice(&data[..16]) }; + // 16 `ArgumentType`s + let args = get_arg_types(&data[16..32]); + let data: &[u32] = unsafe { convert_slice(&data[32..]) }; + let _res = Message::from_raw(data, &args, fds); +}); diff --git a/wayland-commons/src/wire.rs b/wayland-commons/src/wire.rs index c68ced5c871..5864d3a8c93 100644 --- a/wayland-commons/src/wire.rs +++ b/wayland-commons/src/wire.rs @@ -232,7 +232,7 @@ impl Message { let opcode = (word_2 & 0x0000FFFF) as u16; let len = (word_2 >> 16) as usize / 4; - if len < 2 { + if len < 2 || len > raw.len() { return Err(MessageParseError::Malformed); }