matrix-fuzz

git clone git://archive.git.mtrnord.blog/MTRNord/matrix-fuzz.git
Log | Files | Refs | README | LICENSE

commit a99df25eb4161081e32ce8c817e11848552a1027
parent 32a295afb4bb7d200d17a61030fd9e5b2570ef28
Author: MTRNord <mtrnord1@gmail.com>
Date:   Fri, 12 Aug 2022 17:15:07 +0200

Lazy mans solution to arbitrary json objects

Diffstat:
MREADME.md | 5+++++
Msrc/lib.rs | 5+++--
Msrc/types.rs | 190++++++++++++++++++++++++++++---------------------------------------------------
3 files changed, 76 insertions(+), 124 deletions(-)

diff --git a/README.md b/README.md @@ -30,3 +30,7 @@ Matrix fuzzing is a dumb fuzzer fuzzing a few matrix endpoints. It requires a HS - https://github.com/matrix-org/synapse/issues/13510 - https://github.com/matrix-org/synapse/issues/13511 - https://github.com/matrix-org/synapse/issues/13512 + +# Known bugs in the fuzzer + +The fuzzer generates arbitrary json objects currently very poorly. Resulting in a lot less cases than it should. Its a workaround for now until there is a nicer way. +\ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs @@ -112,7 +112,7 @@ mod tests { #[cfg(all(fuzzing, test))] mod tests { - use crate::types::CreateRoomMagic; + use crate::types::{CreateRoomMagic, CreateRoomMagicJSON}; fn create_room(data: &CreateRoomMagic) -> bool { // FIXME: We probably should set it to null and not do a false positive @@ -134,10 +134,11 @@ mod tests { // TODO: Login once and reuse the access token let access_token = crate::access_token(); let client = crate::client(); + let json_data: CreateRoomMagicJSON = data.into(); let resp = client .post("http://localhost:8008/_matrix/client/v3/createRoom") .header("Authorization", format!("Bearer {}", access_token)) - .json(data) + .json(&json_data) .send(); if let Ok(resp) = resp { let status = resp.status().clone(); diff --git a/src/types.rs b/src/types.rs @@ -1,10 +1,6 @@ -use fuzzcheck::{ - mutators::{grammar::*, map::MapMutator, option::OptionMutator}, - DefaultMutator, Mutator, -}; +use fuzzcheck::DefaultMutator; use serde::{Deserialize, Serialize}; -use serde_json::{Map, Value}; -use std::rc::{Rc, Weak}; +use std::collections::HashMap; #[derive(Debug, Serialize, Deserialize)] pub struct LoginGet { @@ -25,9 +21,9 @@ pub struct LoginPost { } #[derive(Clone, Serialize, Deserialize, Debug, Default)] -pub struct CreateRoomMagic { +pub struct CreateRoomMagicJSON { #[serde(skip_serializing_if = "Option::is_none")] - pub creation_content: Option<Map<String, Value>>, + pub creation_content: Option<HashMap<String, String>>, #[serde(skip_serializing_if = "Option::is_none")] pub invite: Option<Vec<String>>, // Due to https://github.com/matrix-org/synapse/issues/13512 @@ -49,24 +45,71 @@ pub struct CreateRoomMagic { pub visibility: Option<String>, } -fuzzcheck::make_mutator! { - name: CreateRoomMagicMutator, - default: true, - type: - pub struct CreateRoomMagic { - #[field_mutator(OptionMutator<Map<String,Value>, JSONMutator> = { OptionMutator::new(json_object_mutator()) } )] - pub creation_content: Option<Map<String,Value>>, - pub invite: Option<Vec<String>>, - // Due to https://github.com/matrix-org/synapse/issues/13512 - //pub invite_3pid: Option<Vec<Invite3pid>>, - pub is_direct: Option<bool>, - pub name: Option<String>, - pub preset: Option<String>, - pub room_alias_name: Option<String>, - pub room_version: Option<String>, - pub topic: Option<String>, - pub visibility: Option<String>, +// FIXME: This is stupid hacky. +impl From<&CreateRoomMagic> for CreateRoomMagicJSON { + fn from(item: &CreateRoomMagic) -> Self { + let mut creation_content = HashMap::new(); + if let Some(mut creation_content_keys) = item.creation_content_keys.clone() { + if let Some(mut creation_content_values) = item.creation_content_values.clone() { + if creation_content_keys.len() > creation_content_values.len() { + creation_content_keys.truncate(creation_content_values.len()); + } else { + creation_content_values.truncate(creation_content_keys.len()); + } + for (key, value) in creation_content_keys + .iter() + .zip(creation_content_values.iter()) + { + creation_content.insert(key.to_string(), value.to_string()); + } + } } + + CreateRoomMagicJSON { + invite: item.invite.clone(), + is_direct: item.is_direct, + name: item.name.clone(), + preset: item.preset.clone(), + room_alias_name: item.room_alias_name.clone(), + room_version: item.room_version.clone(), + topic: item.topic.clone(), + visibility: item.visibility.clone(), + creation_content: if item.creation_content_keys.is_none() + || item.creation_content_values.is_none() + { + None + } else { + Some(creation_content) + }, + } + } +} + +#[derive(Clone, Serialize, Deserialize, Debug, Default, DefaultMutator)] +pub struct CreateRoomMagic { + #[serde(skip_serializing_if = "Option::is_none")] + pub creation_content_keys: Option<Vec<String>>, + #[serde(skip_serializing_if = "Option::is_none")] + pub creation_content_values: Option<Vec<String>>, + #[serde(skip_serializing_if = "Option::is_none")] + pub invite: Option<Vec<String>>, + // Due to https://github.com/matrix-org/synapse/issues/13512 + //#[serde(skip_serializing_if = "Option::is_none")] + //pub invite_3pid: Option<Vec<Invite3pid>>, + #[serde(skip_serializing_if = "Option::is_none")] + pub is_direct: Option<bool>, + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option<String>, + #[serde(skip_serializing_if = "Option::is_none")] + pub preset: Option<String>, + #[serde(skip_serializing_if = "Option::is_none")] + pub room_alias_name: Option<String>, + #[serde(skip_serializing_if = "Option::is_none")] + pub room_version: Option<String>, + #[serde(skip_serializing_if = "Option::is_none")] + pub topic: Option<String>, + #[serde(skip_serializing_if = "Option::is_none")] + pub visibility: Option<String>, } #[derive(Clone, Serialize, Deserialize, Debug, DefaultMutator, Default)] @@ -76,100 +119,3 @@ pub struct Invite3pid { pub id_server: String, pub medium: String, } -fn null() -> Rc<Grammar> { - regex("null") -} - -fn boolean() -> Rc<Grammar> { - regex("true|false") -} - -fn text() -> Rc<Grammar> { - concatenation([ - literal('"'), - regex("([\u{0020}-\u{0021}]|[\u{0023}-\u{7f}]|.)+"), - literal('"'), - ]) - //concatenation([literal('"'), regex("([\u{0}-\u{7f}]|.)+"), literal('"')]) -} - -fn number() -> Rc<Grammar> { - regex("[0-9]+") -} - -fn json_object_entry(rule: &Weak<Grammar>) -> Rc<Grammar> { - concatenation([text(), literal(':'), json_value(rule, None)]) -} - -fn json_array(outer_rule: &Weak<Grammar>) -> Rc<Grammar> { - recursive(|rule| { - concatenation([ - literal('['), - json_value(outer_rule, Some(rule)), - repetition( - concatenation([literal(','), json_value(outer_rule, Some(rule))]), - 1.., - ), - literal(']'), - ]) - }) -} - -fn json_value(object_rule: &Weak<Grammar>, array_rule: Option<&Weak<Grammar>>) -> Rc<Grammar> { - if let Some(array_rule) = array_rule { - alternation([ - recurse(object_rule), - recurse(array_rule), - text(), - number(), - null(), - boolean(), - ]) - } else { - alternation([ - recurse(object_rule), - json_array(object_rule), - text(), - number(), - null(), - boolean(), - ]) - } -} - -fn json_object() -> Rc<Grammar> { - recursive(|rule| { - concatenation([ - literal('{'), - json_object_entry(rule), - repetition(concatenation([literal(','), json_object_entry(rule)]), 1..), - literal('}'), - ]) - }) -} - -type JSONMutator = impl Mutator<Map<String, Value>>; - -fn json_object_mutator() -> JSONMutator { - MapMutator::new( - grammar_based_ast_mutator(json_object()), - |_string: &Map<String, Value>| { - // FIXME: This is a hack - Some(serde_json::from_str::<AST>(r#"{"Sequence":[{"Token":"{"},{"Sequence":[{"Sequence":[{"Token":"\""},{"Sequence":[{"Token":"񶲼"}]},{"Token":"\""}]},{"Token":":"},{"Sequence":[{"Token":"["},{"Sequence":[{"Token":"\""},{"Sequence":[{"Token":"\u0006"}]},{"Token":"\""}]},{"Sequence":[{"Sequence":[{"Token":","},{"Sequence":[{"Sequence":[{"Token":"{"},{"Sequence":[{"Sequence":[{"Token":"\""},{"Sequence":[{"Token":"J"}]},{"Token":"\""}]},{"Token":":"},{"Sequence":[{"Sequence":[{"Token":"{"},{"Sequence":[{"Sequence":[{"Token":"\""},{"Sequence":[{"Token":"󓯠"}]},{"Token":"\""}]},{"Token":":"},{"Sequence":[{"Token":"6"}]}]},{"Sequence":[{"Sequence":[{"Token":","},{"Sequence":[{"Sequence":[{"Token":"\""},{"Sequence":[{"Token":"|"}]},{"Token":"\""}]},{"Token":":"},{"Sequence":[{"Token":"["},{"Sequence":[{"Sequence":[{"Token":"["},{"Sequence":[{"Token":"n"},{"Token":"u"},{"Token":"l"},{"Token":"l"}]},{"Sequence":[{"Sequence":[{"Token":","},{"Sequence":[{"Sequence":[{"Token":"["},{"Sequence":[{"Token":"\""},{"Sequence":[{"Token":"󻘛"}]},{"Token":"\""}]},{"Sequence":[{"Sequence":[{"Token":","},{"Sequence":[{"Sequence":[{"Token":"["},{"Sequence":[{"Sequence":[{"Token":"{"},{"Sequence":[{"Sequence":[{"Token":"\""},{"Sequence":[{"Token":"𪪍"}]},{"Token":"\""}]},{"Token":":"},{"Sequence":[{"Token":"t"},{"Token":"r"},{"Token":"u"},{"Token":"e"}]}]},{"Sequence":[{"Sequence":[{"Token":","},{"Sequence":[{"Sequence":[{"Token":"\""},{"Sequence":[{"Token":"\u0001"}]},{"Token":"\""}]},{"Token":":"},{"Sequence":[{"Token":"4"}]}]}]}]},{"Token":"}"}]}]},{"Sequence":[{"Sequence":[{"Token":","},{"Sequence":[{"Sequence":[{"Token":"{"},{"Sequence":[{"Sequence":[{"Token":"\""},{"Sequence":[{"Token":"񿊌"}]},{"Token":"\""}]},{"Token":":"},{"Sequence":[{"Token":"f"},{"Token":"a"},{"Token":"l"},{"Token":"s"},{"Token":"e"}]}]},{"Sequence":[{"Sequence":[{"Token":","},{"Sequence":[{"Sequence":[{"Token":"\""},{"Sequence":[{"Token":"m"}]},{"Token":"\""}]},{"Token":":"},{"Sequence":[{"Token":"8"}]}]}]}]},{"Token":"}"}]}]}]}]},{"Token":"]"}]}]}]}]},{"Token":"]"}]}]}]}]},{"Token":"]"}]}]},{"Sequence":[{"Sequence":[{"Token":","},{"Sequence":[{"Token":"n"},{"Token":"u"},{"Token":"l"},{"Token":"l"}]}]}]},{"Token":"]"}]}]}]}]},{"Token":"}"}]}]}]},{"Sequence":[{"Sequence":[{"Token":","},{"Sequence":[{"Sequence":[{"Token":"\""},{"Sequence":[{"Token":"}"}]},{"Token":"\""}]},{"Token":":"},{"Sequence":[{"Token":"\""},{"Sequence":[{"Token":"𬗲"}]},{"Token":"\""}]}]}]}]},{"Token":"}"}]}]}]}]},{"Token":"]"}]}]},{"Sequence":[{"Sequence":[{"Token":","},{"Sequence":[{"Sequence":[{"Token":"\""},{"Sequence":[{"Token":"񡷸"}]},{"Token":"\""}]},{"Token":":"},{"Sequence":[{"Token":"["},{"Sequence":[{"Token":"\""},{"Sequence":[{"Token":"򔾂"}]},{"Token":"\""}]},{"Sequence":[{"Sequence":[{"Token":","},{"Sequence":[{"Token":"0"}]}]}]},{"Token":"]"}]}]}]}]},{"Token":"}"}]}"#).unwrap()) - /*match serde_json::from_str::<AST>(string) { - Ok(ast) => Some(ast), - Err(e) => { - println!("Error: {:?}", e); - - None - } - }*/ - }, - |ast| { - let string = ast.to_string(); - //println!("{}", string); - serde_json::from_str::<Map<String, Value>>(&string).unwrap() - }, - |_, cplx| cplx, - ) -}