Skip to main content

flash_lso/amf0/
read.rs

1//! Support for decoding AMF0 data
2use crate::amf0::type_marker::TypeMarker;
3use nom::Parser;
4
5use crate::PADDING;
6#[cfg(feature = "amf3")]
7use crate::amf3;
8use crate::nom_utils::{AMFResult, take_str};
9use crate::types::{
10    ClassDefinition, ECMAArrayObjectValue, Element, ObjectId, ObjectValue, Reference, Value,
11};
12use nom::Err;
13use nom::bytes::complete::{tag, take};
14use nom::combinator::{map, map_res};
15use nom::error::{ErrorKind, make_error};
16use nom::multi::{many_m_n, many0};
17use nom::number::complete::{be_f64, be_u8, be_u16, be_u32};
18use std::convert::{TryFrom, TryInto};
19
20pub(crate) fn parse_string(i: &[u8]) -> AMFResult<'_, &str> {
21    let (i, length) = be_u16(i)?;
22    take_str(i, length)
23}
24
25fn parse_element_number(i: &[u8]) -> AMFResult<'_, Value> {
26    let (i, v) = be_f64(i)?;
27    Ok((i, Value::Number(v)))
28}
29
30fn parse_element_bool(i: &[u8]) -> AMFResult<'_, Value> {
31    let (i, v) = be_u8(i)?;
32    Ok((i, Value::Bool(v > 0)))
33}
34
35fn parse_element_string(i: &[u8]) -> AMFResult<'_, Value> {
36    let (i, v) = parse_string(i)?;
37    Ok((i, Value::String(v.to_string())))
38}
39
40fn parse_element_date(i: &[u8]) -> AMFResult<'_, Value> {
41    let (i, millis) = be_f64(i)?;
42    let (i, time_zone) = be_u16(i)?;
43
44    Ok((
45        i,
46        Value::Date {
47            time: millis,
48            timezone_or_utc: Some(time_zone),
49        },
50    ))
51}
52
53fn parse_long_string_internal(i: &[u8]) -> AMFResult<'_, &str> {
54    let (i, length) = be_u32(i)?;
55    map_res(take(length), std::str::from_utf8).parse(i)
56}
57
58fn parse_element_long_string(i: &[u8]) -> AMFResult<'_, Value> {
59    let (i, str) = parse_long_string_internal(i)?;
60    Ok((i, Value::String(str.to_string())))
61}
62
63fn parse_element_xml(i: &[u8]) -> AMFResult<'_, Value> {
64    let (i, content) = parse_long_string_internal(i)?;
65    Ok((
66        i,
67        Value::XML {
68            value: content.to_string(),
69            is_string: true,
70        },
71    ))
72}
73
74fn read_type_marker(i: &[u8]) -> AMFResult<'_, TypeMarker> {
75    let (i, type_) = be_u8(i)?;
76    Ok((
77        i,
78        TypeMarker::try_from(type_).unwrap_or(TypeMarker::Unsupported),
79    ))
80}
81
82/// Handles decoding AMF0
83#[derive(Default)]
84pub struct AMF0Decoder {
85    /// Cache of previously read values, that can be referenced later
86    cache: Vec<Value>,
87
88    #[cfg(feature = "amf3")]
89    amf3_decoder: amf3::read::AMF3Decoder,
90}
91
92impl AMF0Decoder {
93    fn parse_element_reference<'a>(&self, i: &'a [u8]) -> AMFResult<'a, Value> {
94        let (i, reference_index) = be_u16(i)?;
95
96        Ok((i, Value::Reference(Reference(reference_index))))
97    }
98
99    fn parse_element_ecma_array<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
100        let (i, array_length) = be_u32(i)?;
101        map(
102            |i| self.parse_array_element(i),
103            move |elms: Vec<Element>| Value::ECMAArray {
104                id: ObjectId::INVALID,
105                data: ECMAArrayObjectValue {
106                    dense: Vec::new(),
107                    elements: elms,
108                    length: array_length,
109                },
110            },
111        )
112        .parse(i)
113    }
114
115    fn parse_element_typed_object<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
116        let (i, name) = parse_string(i)?;
117
118        map(
119            |i| self.parse_array_element(i),
120            move |elms: Vec<Element>| Value::Object {
121                id: ObjectId::INVALID,
122                data: ObjectValue {
123                    elements: elms,
124                    class_definition: Some(ClassDefinition::default_with_name(name.to_string())),
125                },
126            },
127        )
128        .parse(i)
129    }
130
131    fn parse_element_object<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
132        let (i, v) = self.parse_array_element(i)?;
133        Ok((
134            i,
135            Value::Object {
136                id: ObjectId::INVALID,
137                data: ObjectValue {
138                    elements: v,
139                    class_definition: None,
140                },
141            },
142        ))
143    }
144
145    #[cfg(fuzzing)]
146    /// For fuzzing
147    pub fn fuzz_parse_element_array<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
148        self.parse_element_strict_array(i)
149    }
150
151    /// Parse an array of elements
152    fn parse_element_strict_array<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
153        let (i, length) = be_u32(i)?;
154
155        let length_usize = length
156            .try_into()
157            .map_err(|_| Err::Error(make_error(i, ErrorKind::Digit)))?;
158
159        // There must be at least `length_usize` bytes (u8) to read this, this prevents OOM errors with v.large arrays
160        if i.len() < length_usize {
161            return Err(Err::Error(make_error(i, ErrorKind::TooLarge)));
162        }
163
164        // This must parse length elements
165        let (i, elements) =
166            many_m_n(length_usize, length_usize, |i| self.parse_single_element(i)).parse(i)?;
167
168        Ok((
169            i,
170            Value::StrictArray {
171                id: ObjectId::INVALID,
172                values: elements,
173            },
174        ))
175    }
176
177    fn parse_array_element<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Vec<Element>> {
178        let mut out = Vec::new();
179
180        let mut i = i;
181        loop {
182            let (k, _) = parse_string(i)?;
183            let (k, next_type) = read_type_marker(k)?;
184            if next_type == TypeMarker::ObjectEnd {
185                i = k;
186                break;
187            }
188
189            let (j, e) = self.parse_element(i)?;
190            i = j;
191
192            out.push(e.clone());
193        }
194
195        Ok((i, out))
196    }
197
198    fn parse_element_amf3<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
199        #[cfg(feature = "amf3")]
200        {
201            let (i, x) = self.amf3_decoder.parse_single_element(i)?;
202            Ok((i, Value::AMF3(Box::new(x))))
203        }
204        #[cfg(not(feature = "amf3"))]
205        {
206            Ok((i, Value::Unsupported))
207        }
208    }
209
210    /// Parse a single AMF0 element
211    pub fn parse_single_element<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
212        // Get the type of the next element
213        let (i, type_) = read_type_marker(i)?;
214
215        self.cache.push(Value::Undefined);
216
217        let (i, v) = match type_ {
218            TypeMarker::Number => parse_element_number(i),
219            TypeMarker::Boolean => parse_element_bool(i),
220            TypeMarker::String => parse_element_string(i),
221            TypeMarker::Object => {
222                let (i, v) = self.parse_element_object(i)?;
223                Ok((i, v))
224            }
225            TypeMarker::Null => Ok((i, (Value::Null))),
226            TypeMarker::Undefined => Ok((i, (Value::Undefined))),
227            TypeMarker::Reference => {
228                let (i, v) = self.parse_element_reference(i)?;
229                Ok((i, v))
230            }
231            TypeMarker::ECMAArray => {
232                let (i, v) = self.parse_element_ecma_array(i)?;
233                Ok((i, v))
234            }
235            TypeMarker::StrictArray => {
236                let (i, v) = self.parse_element_strict_array(i)?;
237                Ok((i, v))
238            }
239            TypeMarker::Date => parse_element_date(i),
240            TypeMarker::LongString => parse_element_long_string(i),
241            TypeMarker::Unsupported => Ok((i, (Value::Unsupported))),
242            TypeMarker::Xml => parse_element_xml(i),
243            TypeMarker::TypedObject => {
244                let (i, v) = self.parse_element_typed_object(i)?;
245                Ok((i, v))
246            }
247            TypeMarker::AMF3 => self.parse_element_amf3(i),
248            TypeMarker::MovieClip | TypeMarker::RecordSet | TypeMarker::ObjectEnd => Err(
249                Err::Error(crate::errors::Error::UnsupportedType(type_ as u8)),
250            ),
251        }?;
252
253        Ok((i, v))
254    }
255
256    fn parse_element<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Element> {
257        let (i, name) = parse_string(i)?;
258
259        map(
260            |i| self.parse_single_element(i),
261            move |v| Element {
262                name: name.to_string(),
263                value: v,
264            },
265        )
266        .parse(i)
267    }
268
269    fn parse_element_and_padding<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Element> {
270        let (i, e) = self.parse_element(i)?;
271        let (i, _) = tag(PADDING.as_slice())(i)?;
272
273        Ok((i, e))
274    }
275
276    /// Parse a sequence of `PADDING` delimited `Values`
277    pub fn parse_body<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Vec<Element>> {
278        many0(|i| self.parse_element_and_padding(i)).parse(i)
279    }
280}