commit 443ceeae2bef950794feda3cc090108e20dcca2d
parent e45d65bc757970a561efb2a7102ac63abe4d8dee
Author: MTRNord <mtrnord1@gmail.com>
Date: Fri, 12 Aug 2022 18:28:39 +0200
Add initial_state fuzzing
Diffstat:
| M | Cargo.toml | | | 11 | +++++------ |
| M | src/lib.rs | | | 42 | +++++++++++++++++++++++++++++++++++++----- |
| M | src/types.rs | | | 57 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
3 files changed, 99 insertions(+), 11 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
@@ -1,13 +1,13 @@
[package]
+edition = "2021"
name = "matrix-fuzz"
version = "0.1.0"
-edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-serde = { version = "1.0", features = ["derive"] }
-reqwest = { version = "0.11.11", features = ["blocking","json","gzip"] }
-serde_json = "1.0.83"
+fuzzcheck = {git = "https://github.com/MTRNord/fuzzcheck-rs.git", branch = "patch-1"}
once_cell = "1.13.0"
-fuzzcheck = "0.12"
-\ No newline at end of file
+reqwest = {version = "0.11.11", features = ["blocking", "json", "gzip"]}
+serde = {version = "1.0", features = ["derive"]}
+serde_json = "1.0.83"
diff --git a/src/lib.rs b/src/lib.rs
@@ -12,10 +12,13 @@ use crate::types::{Flow, LoginGet, LoginPost};
mod secrets;
mod types;
+#[no_coverage]
fn access_token() -> &'static String {
static INSTANCE: OnceCell<String> = OnceCell::new();
INSTANCE.get_or_init(login)
}
+
+#[no_coverage]
fn client() -> &'static reqwest::blocking::Client {
static INSTANCE: OnceCell<reqwest::blocking::Client> = OnceCell::new();
INSTANCE.get_or_init(|| {
@@ -28,6 +31,7 @@ fn client() -> &'static reqwest::blocking::Client {
})
}
+#[no_coverage]
fn login() -> String {
let client = crate::client();
let res: LoginGet = client
@@ -59,9 +63,10 @@ fn login() -> String {
mod tests {
use reqwest::header::{HeaderValue, CONTENT_TYPE};
- use crate::types::CreateRoomMagic;
+ use crate::types::{CreateRoomMagic, CreateRoomMagicJSON};
#[test]
+ #[no_coverage]
fn connection_test() {
let client = crate::client();
let resp = client
@@ -72,6 +77,7 @@ mod tests {
}
#[test]
+ #[no_coverage]
fn null_in_room() {
let content = CreateRoomMagic {
name: Some("a".to_string()),
@@ -81,7 +87,6 @@ mod tests {
topic: Some("c".to_string()),
..Default::default()
};
- println!("{}", serde_json::to_string(&content).unwrap());
let access_token = crate::access_token();
let client = crate::client();
let resp = client
@@ -96,6 +101,7 @@ mod tests {
}
#[test]
+ #[no_coverage]
fn weird_req() {
let content = std::fs::read_to_string("./weird_ones/af84a60a1b7997b4.json").unwrap();
let access_token = crate::access_token();
@@ -108,6 +114,18 @@ mod tests {
.send();
assert!(resp.is_err())
}
+
+ #[test]
+ #[no_coverage]
+ fn converter() {
+ let content = std::fs::read_to_string(
+ "./fuzz/tests::fuzz_create_room/artifacts/36d21e863bdd02f6.json",
+ )
+ .unwrap();
+ let typed = serde_json::from_str::<CreateRoomMagic>(&content).unwrap();
+ let typed_json: CreateRoomMagicJSON = (&typed).into();
+ println!("{}", serde_json::to_string(&typed_json).unwrap());
+ }
}
#[cfg(all(fuzzing, test))]
@@ -122,6 +140,17 @@ mod tests {
return true;
}
}
+ // HACK due to NUL in type or state_key
+ if let Some(initial_state) = &data.initial_state {
+ for state in initial_state {
+ if state._type.contains("\0") {
+ return true;
+ }
+ if state.state_key.contains("\0") {
+ return true;
+ }
+ }
+ }
/*// HACK due to https://github.com/matrix-org/synapse/issues/13511
if let Some(pids) = &data.invite_3pid {
for pid in pids {
@@ -147,9 +176,12 @@ mod tests {
let content = resp.text();
if let Ok(ref content) = content {
if content.contains("M_ROOM_IN_USE")
- || content.contains("Invalid characters in room alias")
- || content.contains("':' is not permitted in the room alias name. Please note this expects a local part — 'wombat', not '#wombat:example.com'.")
- || content.contains("M_UNSUPPORTED_ROOM_VERSION") || content.contains("Invalid user_id") || content.contains("is not a valid preset")
+ || content.contains("Invalid characters in room alias")
+ || content.contains("':' is not permitted in the room alias name. Please note this expects a local part — 'wombat', not '#wombat:example.com'.")
+ || content.contains("M_UNSUPPORTED_ROOM_VERSION")
+ || content.contains("Invalid user_id")
+ || content.contains("is not a valid preset")
+ || content.contains("You are not allowed to set others state")
{
return true;
}
diff --git a/src/types.rs b/src/types.rs
@@ -25,6 +25,8 @@ pub struct CreateRoomMagicJSON {
#[serde(skip_serializing_if = "Option::is_none")]
pub creation_content: Option<HashMap<String, String>>,
#[serde(skip_serializing_if = "Option::is_none")]
+ pub initial_state: Option<Vec<StateEventJSON>>,
+ #[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")]
@@ -47,6 +49,7 @@ pub struct CreateRoomMagicJSON {
// FIXME: This is stupid hacky.
impl From<&CreateRoomMagic> for CreateRoomMagicJSON {
+ #[no_coverage]
fn from(item: &CreateRoomMagic) -> Self {
let mut creation_content = HashMap::new();
if let Some(mut creation_content_keys) = item.creation_content_keys.clone() {
@@ -67,6 +70,10 @@ impl From<&CreateRoomMagic> for CreateRoomMagicJSON {
CreateRoomMagicJSON {
invite: item.invite.clone(),
+ initial_state: item
+ .initial_state
+ .clone()
+ .map(|initial_state| initial_state.into_iter().map(Into::into).collect()),
is_direct: item.is_direct,
name: item.name.clone(),
preset: item.preset.clone(),
@@ -92,6 +99,8 @@ pub struct CreateRoomMagic {
#[serde(skip_serializing_if = "Option::is_none")]
pub creation_content_values: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
+ pub initial_state: Option<Vec<StateEvent>>,
+ #[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")]
@@ -119,3 +128,51 @@ pub struct Invite3pid {
pub id_server: String,
pub medium: String,
}
+
+#[derive(Clone, Serialize, Deserialize, Debug, Default)]
+pub struct StateEventJSON {
+ pub content: HashMap<String, String>,
+ #[serde(rename = "type")]
+ pub _type: String,
+ pub state_key: String,
+}
+
+// FIXME: This is stupid hacky.
+impl From<StateEvent> for StateEventJSON {
+ #[no_coverage]
+ fn from(item: StateEvent) -> Self {
+ let mut content = HashMap::new();
+ let mut item_clone = item.clone();
+ if item_clone.content_keys.len() > item_clone.content_values.len() {
+ item_clone
+ .content_keys
+ .truncate(item_clone.content_values.len());
+ } else {
+ item_clone
+ .content_values
+ .truncate(item_clone.content_keys.len());
+ }
+ for (key, value) in item_clone
+ .content_keys
+ .iter()
+ .zip(item_clone.content_values.iter())
+ {
+ content.insert(key.to_string(), value.to_string());
+ }
+
+ StateEventJSON {
+ content,
+ _type: item._type.clone(),
+ state_key: item.state_key,
+ }
+ }
+}
+
+#[derive(Clone, Serialize, Deserialize, Debug, DefaultMutator, Default)]
+pub struct StateEvent {
+ pub content_keys: Vec<String>,
+ pub content_values: Vec<String>,
+ #[serde(rename = "type")]
+ pub _type: String,
+ pub state_key: String,
+}