Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix broken fuzz targets #63

Merged
merged 4 commits into from
Jul 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[workspace]
resolver = "2"
members = [
"flash-lso",
"lso-to-json",
Expand Down
16 changes: 10 additions & 6 deletions flash-lso/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,26 @@ categories = ["data-structures", "encoding", "parser-implementations"]

[dependencies]
nom = "7.1.3"
enumset = "1.0.12"
thiserror = "1.0.38"
serde = { version = "1.0.152", optional = true, features = ["derive", "rc"] }
enumset = "1.1.3"
thiserror = "1.0.61"
serde = { version = "1.0.203", optional = true, features = ["derive", "rc"] }
byteorder = "1.5.0"

[dev-dependencies]
pretty_assertions = "1.2.1"
serde_json = "1.0.91"
pretty_assertions = "1.4.0"
serde_json = "1.0.120"
criterion = "0.5.1"

[[bench]]
name = "benchmarks"
harness = false

[features]
default = []
default = ["amf3"]
flex = []
serde = ["dep:serde", "enumset/serde"]
all = ["serde", "flex"]
amf3 = []

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(fuzzing)'] }
24 changes: 20 additions & 4 deletions flash-lso/src/amf0/read.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
//! Support for decoding AMF0 data
use crate::amf0::type_marker::TypeMarker;

#[cfg(feature = "amf3")]
use crate::amf3;
use crate::nom_utils::{take_str, AMFResult};
use crate::types::{ClassDefinition, Element, Reference, Value};
use crate::{amf3, PADDING};
use crate::PADDING;
use nom::bytes::complete::{tag, take};
use nom::combinator::{map, map_res};
use nom::error::{make_error, ErrorKind};
Expand Down Expand Up @@ -56,9 +58,16 @@ fn parse_element_xml(i: &[u8]) -> AMFResult<'_, Rc<Value>> {
}

fn parse_element_amf3(i: &[u8]) -> AMFResult<'_, Rc<Value>> {
// Hopefully amf3 objects wont have references
let (i, x) = amf3::read::AMF3Decoder::default().parse_single_element(i)?;
Ok((i, Rc::new(Value::AMF3(x))))
#[cfg(feature = "amf3")]
{
// Hopefully amf3 objects won't have references
let (i, x) = amf3::read::AMF3Decoder::default().parse_single_element(i)?;
Ok((i, Rc::new(Value::AMF3(x))))
}
#[cfg(not(feature = "amf3"))]
{
Ok((i, Rc::new(Value::Unsupported)))
}
}

fn read_type_marker(i: &[u8]) -> AMFResult<'_, TypeMarker> {
Expand Down Expand Up @@ -110,6 +119,13 @@ impl AMF0Decoder {
Ok((i, Rc::new(Value::Object(v, None))))
}

#[cfg(fuzzing)]
/// For fuzzing
pub fn fuzz_parse_element_array<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Rc<Value>> {
self.parse_element_array(i)
}

/// Parse an array of elements
fn parse_element_array<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Rc<Value>> {
let (i, length) = be_u32(i)?;

Expand Down
5 changes: 4 additions & 1 deletion flash-lso/src/amf0/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ use crate::PADDING;
use std::io::Write;

use crate::amf0::type_marker::TypeMarker;
use crate::amf3::write::AMF3Encoder;
use crate::nom_utils::write_string;
use byteorder::{BigEndian, WriteBytesExt};
use std::io::Result;
use std::ops::Deref;
use std::rc::Rc;

#[cfg(feature = "amf3")]
use crate::amf3::write::AMF3Encoder;

fn write_type_marker<'a, 'b: 'a, W: Write + 'a>(writer: &mut W, type_: TypeMarker) -> Result<()> {
writer.write_u8(type_ as u8)
}
Expand Down Expand Up @@ -183,6 +185,7 @@ pub(crate) fn write_value<'a, 'b: 'a, W: Write + 'a>(
Value::ECMAArray(dense, elems, elems_length) => {
write_mixed_array(writer, dense, elems, *elems_length)
}
#[cfg(feature = "amf3")]
Value::AMF3(e) => {
write_type_marker(writer, TypeMarker::AMF3)?;
let encoder = AMF3Encoder::default();
Expand Down
18 changes: 18 additions & 0 deletions flash-lso/src/amf3/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ use std::rc::Rc;

const REFERENCE_FLAG: u32 = 0x01;

#[cfg(fuzzing)]
/// For fuzzing
pub fn fuzz_read_int_signed(i: &[u8]) -> AMFResult<'_, i32> {
read_int_signed(i)
}

#[allow(clippy::unusual_byte_groupings)]
fn read_int_signed(i: &[u8]) -> AMFResult<'_, i32> {
// Read the first byte of the number
Expand Down Expand Up @@ -51,6 +57,12 @@ fn read_int_signed(i: &[u8]) -> AMFResult<'_, i32> {
Ok((i, value))
}

#[cfg(fuzzing)]
/// For fuzzing
pub fn fuzz_read_int(i: &[u8]) -> AMFResult<'_, u32> {
read_int(i)
}

#[allow(clippy::unusual_byte_groupings)]
fn read_int(i: &[u8]) -> AMFResult<'_, u32> {
// Read the first byte of the number
Expand Down Expand Up @@ -158,6 +170,12 @@ impl AMF3Decoder {
Ok((i, Rc::new(s)))
}

#[cfg(fuzzing)]
/// For fuzzing
pub fn fuzz_parse_string<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, String> {
self.parse_string(i)
}

fn parse_string<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, String> {
let (i, bytes) = self.parse_byte_stream(i)?;
let bytes_str =
Expand Down
4 changes: 4 additions & 0 deletions flash-lso/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![type_length_limit = "94603681"]
//! Library for reading and writing the Adobe Flash Local Shared Object (LSO) file format and the contained AMF0/AMF3 data

#![deny(
Expand All @@ -19,6 +20,8 @@ const HEADER_SIGNATURE: [u8; 10] = [0x54, 0x43, 0x53, 0x4f, 0x00, 0x04, 0x00, 0x
const PADDING: [u8; 1] = [0x00];

const FORMAT_VERSION_AMF0: u8 = 0x0;

#[cfg(feature = "amf3")]
const FORMAT_VERSION_AMF3: u8 = 0x3;

#[cfg(feature = "serde")]
Expand All @@ -29,6 +32,7 @@ extern crate serde;
pub mod amf0;

/// Reading and Writing of the AMF3 file format
#[cfg(feature = "amf3")]
pub mod amf3;

/// Decoding error type
Expand Down
1 change: 1 addition & 0 deletions flash-lso/src/packet/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ pub fn write_to_bytes(packet: &Packet, exact_lengths: bool) -> Result<Vec<u8>, E
buffer.push(0);
match packet.version {
AMFVersion::AMF0 => buffer.push(0),
#[cfg(feature = "amf3")]
AMFVersion::AMF3 => buffer.push(3),
}

Expand Down
20 changes: 13 additions & 7 deletions flash-lso/src/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use nom::number::complete::be_u32;

use crate::amf0;
use crate::amf0::read::AMF0Decoder;
#[cfg(feature = "amf3")]
use crate::amf3::read::AMF3Decoder;
use crate::errors::Error;
use crate::nom_utils::AMFResult;
Expand All @@ -17,9 +18,11 @@ const HEADER_SIGNATURE: [u8; 10] = [0x54, 0x43, 0x53, 0x4f, 0x00, 0x04, 0x00, 0x
const PADDING: [u8; 1] = [0x00];

const FORMAT_VERSION_AMF0: u8 = 0x0;

#[cfg(feature = "amf3")]
const FORMAT_VERSION_AMF3: u8 = 0x3;

/// The main entry point of decoding a LSO file
/// The main entry point of decoding an LSO file
/// Example of use
/// ```
/// use std::fs::File;
Expand All @@ -34,6 +37,7 @@ const FORMAT_VERSION_AMF3: u8 = 0x3;
/// }
#[derive(Default)]
pub struct Reader {
#[cfg(feature = "amf3")]
/// Handles reading Amf3 data
pub amf3_decoder: AMF3Decoder,

Expand All @@ -42,7 +46,8 @@ pub struct Reader {
}

impl Reader {
fn parse_header<'a>(&self, i: &'a [u8]) -> AMFResult<'a, Header> {
/// Read a Lso header from the given slice
pub fn parse_header<'a>(&self, i: &'a [u8]) -> AMFResult<'a, Header> {
let (i, _) = tag(HEADER_VERSION)(i)?;
let (i, l) = be_u32(i)?;
let (i, _) = tag(HEADER_SIGNATURE)(i)?;
Expand All @@ -53,11 +58,11 @@ impl Reader {
let (i, _) = tag(PADDING)(i)?;
let (i, _) = tag(PADDING)(i)?;

let (i, version) = alt((tag(&[FORMAT_VERSION_AMF0]), tag(&[FORMAT_VERSION_AMF3])))(i)
.map_err(|e| {
eprintln!("Err: {e:?}");
e
})?;
let (i, version) = alt((
tag(&[FORMAT_VERSION_AMF0]),
#[cfg(feature = "amf3")]
tag(&[FORMAT_VERSION_AMF3]),
))(i)?;

// This unwrap can't fail because of the alt above
let format_version: AMFVersion = version[0].try_into().unwrap();
Expand All @@ -84,6 +89,7 @@ impl Reader {
Ok((i, Lso { header, body }))
}

#[cfg(feature = "amf3")]
AMFVersion::AMF3 => {
let (i, body) = self.amf3_decoder.parse_body(i)?;
Ok((i, Lso { header, body }))
Expand Down
3 changes: 3 additions & 0 deletions flash-lso/src/types/amf_version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub enum AMFVersion {
/// AMF0
AMF0 = 0,

#[cfg(feature = "amf3")]
/// AMF3
AMF3 = 3,
}
Expand All @@ -18,6 +19,7 @@ impl TryFrom<u8> for AMFVersion {
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::AMF0),
#[cfg(feature = "amf3")]
3 => Ok(Self::AMF3),
_ => Err(()),
}
Expand All @@ -28,6 +30,7 @@ impl fmt::Display for AMFVersion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AMFVersion::AMF0 => f.write_str("AMF0"),
#[cfg(feature = "amf3")]
AMFVersion::AMF3 => f.write_str("AMF3"),
}
}
Expand Down
1 change: 1 addition & 0 deletions flash-lso/src/types/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub enum Value {
/// Represent the XML type, (value, is_string)
XML(String, bool),

#[cfg(feature = "amf3")]
/// Represent an amf3 element embedded in an AMF0 file
AMF3(Rc<Value>),

Expand Down
8 changes: 7 additions & 1 deletion flash-lso/src/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@
use byteorder::{BigEndian, WriteBytesExt};
use std::io::Write;

#[cfg(feature = "amf3")]
use crate::amf3::write::AMF3Encoder;
use crate::errors::Error;
use crate::nom_utils::write_string;
use crate::types::{AMFVersion, Header, Lso};
use crate::{FORMAT_VERSION_AMF0, FORMAT_VERSION_AMF3, HEADER_SIGNATURE, HEADER_VERSION, PADDING};
#[cfg(feature = "amf3")]
use crate::FORMAT_VERSION_AMF3;
use crate::{FORMAT_VERSION_AMF0, HEADER_SIGNATURE, HEADER_VERSION, PADDING};

/// Handles writing a given LSO
#[derive(Default)]
pub struct Writer {
/// The encoder used for writing Value::AMF3() wrapped types
#[cfg(feature = "amf3")]
pub amf3_encoder: AMF3Encoder,
}

Expand All @@ -26,6 +30,7 @@ impl Writer {
if lso.header.format_version == AMFVersion::AMF0 {
crate::amf0::write::write_body(&mut buffer, &lso.body)?;
} else {
#[cfg(feature = "amf3")]
self.amf3_encoder.write_body(&mut buffer, &lso.body)?;
}

Expand All @@ -50,6 +55,7 @@ fn write_header<'a, 'b: 'a, W: Write + 'a>(
writer.write_all(&PADDING)?;
match header.format_version {
AMFVersion::AMF0 => writer.write_all(&[FORMAT_VERSION_AMF0])?,
#[cfg(feature = "amf3")]
AMFVersion::AMF3 => writer.write_all(&[FORMAT_VERSION_AMF3])?,
};
Ok(())
Expand Down
Loading