diff --git a/Justfile b/Justfile index 5c32701..0f7a232 100644 --- a/Justfile +++ b/Justfile @@ -5,4 +5,9 @@ doc: cargo doc --workspace --no-deps watch: - cargo watch -c \ No newline at end of file + cargo watch -c + +fuzz-imap: + #!/bin/bash + cd imap + cargo +nightly fuzz run parse_response \ No newline at end of file diff --git a/imap/Justfile b/imap/Justfile index 7050d24..ebaadba 100644 --- a/imap/Justfile +++ b/imap/Justfile @@ -3,7 +3,4 @@ afl: cd imap-parsing-fuzz-target pwd cargo afl build - cargo afl fuzz -i in -o out target/debug/imap-parsing-fuzz-target - -fuzz: - cargo +nightly fuzz run parse_response \ No newline at end of file + cargo afl fuzz -i in -o out target/debug/imap-parsing-fuzz-target \ No newline at end of file diff --git a/imap/src/proto/response.rs b/imap/src/proto/response.rs index eaf63e5..5fcc682 100644 --- a/imap/src/proto/response.rs +++ b/imap/src/proto/response.rs @@ -57,6 +57,17 @@ pub enum Response { impl DisplayBytes for Response { fn display_bytes(&self, w: &mut dyn Write) -> io::Result<()> { match self { + Response::Capabilities(caps) => { + write_bytes!(w, b"CAPABILITY")?; + for cap in caps { + write_bytes!(w, b" {}", cap)?; + } + Ok(()) + } + Response::Condition(cond) => write_bytes!(w, b"* {}", cond), + Response::Done(done) => write_bytes!(w, b""), + Response::MailboxData(data) => write_bytes!(w, b"* {}\r\n", data), + Response::Expunge(n) => write_bytes!(w, b"{} EXPUNGE", n), _ => todo!(), } } @@ -126,6 +137,16 @@ pub struct Condition { pub info: Bytes, } +impl DisplayBytes for Condition { + fn display_bytes(&self, w: &mut dyn Write) -> io::Result<()> { + write_bytes!(w, b"{} ", self.status)?; + if let Some(code) = &self.code { + write_bytes!(w, b"[{}] ", code)?; + } + write_bytes!(w, b"{}", self.info) + } +} + #[derive(Debug)] #[cfg_attr(feature = "fuzzing", derive(Arbitrary))] pub enum Status { @@ -136,6 +157,18 @@ pub enum Status { Bye, } +impl DisplayBytes for Status { + fn display_bytes(&self, w: &mut dyn Write) -> io::Result<()> { + match self { + Status::Ok => write_bytes!(w, b"OK"), + Status::No => write_bytes!(w, b"NO"), + Status::Bad => write_bytes!(w, b"BAD"), + Status::PreAuth => write_bytes!(w, b"PREAUTH"), + Status::Bye => write_bytes!(w, b"BYE"), + } + } +} + #[derive(Debug)] #[non_exhaustive] #[cfg_attr(feature = "fuzzing", derive(Arbitrary))] @@ -158,6 +191,14 @@ pub enum ResponseCode { Other(Bytes, Option), } +impl DisplayBytes for ResponseCode { + fn display_bytes(&self, w: &mut dyn Write) -> io::Result<()> { + match self { + _ => todo!(), + } + } +} + #[derive(Debug)] #[cfg_attr(feature = "fuzzing", derive(Arbitrary))] pub enum UidSetMember { @@ -173,6 +214,16 @@ pub enum Capability { Atom(Atom), } +impl DisplayBytes for Capability { + fn display_bytes(&self, w: &mut dyn Write) -> io::Result<()> { + match self { + Capability::Imap4rev1 => write_bytes!(w, b"IMAP4rev1"), + Capability::Auth(a) => write_bytes!(w, b"AUTH={}", a), + Capability::Atom(a) => write_bytes!(w, b"{}", a), + } + } +} + #[derive(Debug)] #[cfg_attr(feature = "fuzzing", derive(Arbitrary))] pub enum MailboxData { @@ -185,6 +236,24 @@ pub enum MailboxData { Recent(u32), } +impl DisplayBytes for MailboxData { + fn display_bytes(&self, w: &mut dyn Write) -> io::Result<()> { + match self { + MailboxData::Flags(flags) => { + write_bytes!(w, b"(")?; + for (i, flag) in flags.iter().enumerate() { + if i != 0 { + write_bytes!(w, b" ")?; + } + write_bytes!(w, b"{}", flag)?; + } + write_bytes!(w, b")") + } + _ => todo!(), + } + } +} + #[derive(Debug)] #[cfg_attr(feature = "fuzzing", derive(Arbitrary))] pub enum Mailbox { @@ -205,6 +274,21 @@ pub enum Flag { Extension(Atom), } +impl DisplayBytes for Flag { + fn display_bytes(&self, w: &mut dyn Write) -> io::Result<()> { + match self { + Flag::Answered => write_bytes!(w, b"\\Answered"), + Flag::Flagged => write_bytes!(w, b"\\Flagged"), + Flag::Deleted => write_bytes!(w, b"\\Deleted"), + Flag::Seen => write_bytes!(w, b"\\Seen"), + Flag::Draft => write_bytes!(w, b"\\Draft"), + Flag::Recent => write_bytes!(w, b"\\Recent"), + Flag::Keyword(atom) => write_bytes!(w, b"{}", atom), + Flag::Extension(atom) => write_bytes!(w, b"\\{}", atom), + } + } +} + #[derive(Debug)] #[cfg_attr(feature = "fuzzing", derive(Arbitrary))] pub struct MailboxList {