Skip to main content

flash_lso/amf3/
read.rs

1use crate::amf3::custom_encoder::CustomDecoder;
2use crate::amf3::type_marker::TypeMarker;
3use nom::Parser;
4
5use crate::PADDING;
6use crate::amf3::length::Length;
7use crate::nom_utils::AMFResult;
8use crate::types::*;
9use crate::types::{Element, Value};
10use enumset::EnumSet;
11use nom::Err;
12use nom::bytes::complete::{tag, take};
13use nom::combinator::{map, map_res};
14use nom::error::{ErrorKind, make_error};
15use nom::lib::std::collections::HashMap;
16use nom::multi::{many_m_n, separated_list0};
17use nom::number::complete::{be_f64, be_i32, be_u8, be_u32};
18
19use std::convert::{TryFrom, TryInto};
20use std::rc::Rc;
21
22const REFERENCE_FLAG: u32 = 0x01;
23
24#[cfg(fuzzing)]
25/// For fuzzing
26pub fn fuzz_read_int_signed(i: &[u8]) -> AMFResult<'_, i32> {
27    read_int_signed(i)
28}
29
30#[allow(clippy::unusual_byte_groupings)]
31fn read_int_signed(i: &[u8]) -> AMFResult<'_, i32> {
32    // Read the first byte of the number
33    let (mut i, num) = be_u8(i)?;
34    let mut value = (num & 0b01111111) as i32;
35    // Check if we have another byte
36    if num & 0b10000000 == 0 {
37        return Ok((i, value));
38    }
39
40    for _ in 0..2 {
41        let (j, num) = be_u8(i)?;
42        i = j;
43        value = (value << 7) | ((num & 0b01111111) as i32);
44        // Check if we have another byte
45        if num & 0b10000000 == 0 {
46            return Ok((i, value));
47        }
48    }
49    let (i, num) = be_u8(i)?;
50    value = (value << 8) | (num as i32);
51
52    // Negate if negative
53    if value & 0b000_1000000_0000000_0000000_00000000 != 0 {
54        value -= 0b001_0000000_0000000_0000000_00000000;
55    }
56
57    Ok((i, value))
58}
59
60#[cfg(fuzzing)]
61/// For fuzzing
62pub fn fuzz_read_int(i: &[u8]) -> AMFResult<'_, u32> {
63    read_int(i)
64}
65
66#[allow(clippy::unusual_byte_groupings)]
67fn read_int(i: &[u8]) -> AMFResult<'_, u32> {
68    // Read the first byte of the number
69    let (mut i, num) = be_u8(i)?;
70    let mut value = (num & 0b01111111) as u32;
71    // Check if we have another byte
72    if num & 0b10000000 == 0 {
73        return Ok((i, value));
74    }
75
76    for _ in 0..2 {
77        let (j, num) = be_u8(i)?;
78        i = j;
79        value = (value << 7) | ((num & 0b01111111) as u32);
80        // Check if we have another byte
81        if num & 0b10000000 == 0 {
82            return Ok((i, value));
83        }
84    }
85    let (i, num) = be_u8(i)?;
86    value = (value << 8) | (num as u32);
87
88    if value & 0b000_1000000_0000000_0000000_00000000 != 0 {
89        value <<= 1;
90        value += 1;
91    }
92
93    Ok((i, value))
94}
95
96#[cfg(test)]
97mod read_number_tests {
98    use crate::amf3::read::{read_int, read_int_signed};
99
100    #[test]
101    fn test_read_1byte_number() {
102        assert_eq!(
103            0b00101011,
104            read_int_signed(&[0b00101011]).expect("Test fail").1
105        )
106    }
107
108    #[test]
109    fn test_read_4byte_number() {
110        let i = &[0b10000000, 0b11000000, 0b10000000, 0b10000000];
111        assert_eq!(2097280, read_int_signed(i).expect("Test fail").1);
112    }
113
114    #[test]
115    fn read_neg_number() {
116        assert_eq!(
117            -268435455,
118            read_int_signed(&[192, 128, 128, 1]).expect("Test fail").1
119        );
120    }
121
122    #[test]
123    fn test_read_1byte_number_unsigned() {
124        assert_eq!(0b00101011, read_int(&[0b00101011]).expect("Test fail").1)
125    }
126
127    #[test]
128    fn test_read_4byte_number_unsigned() {
129        let i = &[0b10000000, 0b11000000, 0b10000000, 0b10000000];
130        assert_eq!(2097280, read_int(i).expect("Test fail").1);
131    }
132
133    #[test]
134    fn read_neg_number_unsigned() {
135        assert_eq!(
136            536870915,
137            read_int(&[192, 128, 128, 1]).expect("Test fail").1
138        );
139    }
140}
141
142fn read_length(i: &[u8]) -> AMFResult<'_, Length> {
143    let (i, val) = read_int(i)?;
144    Ok((
145        i,
146        match val & REFERENCE_FLAG == 0 {
147            true => Length::Reference(val as usize >> 1),
148            false => Length::Size(val >> 1),
149        },
150    ))
151}
152
153fn parse_element_int(i: &[u8]) -> AMFResult<'_, Value> {
154    let (i, s) = map(read_int_signed, Value::Integer).parse(i)?;
155    Ok((i, (s)))
156}
157
158/// Handles decoding AMF3
159#[derive(Default)]
160pub struct AMF3Decoder {
161    /// The table used to cache repeated byte strings
162    pub string_reference_table: Vec<Vec<u8>>,
163
164    /// The table used to cache repeated trait definitions
165    pub trait_reference_table: Vec<ClassDefinition>,
166
167    /// Encoders used for handling externalized types
168    external_decoders: HashMap<String, Rc<dyn CustomDecoder>>,
169
170    /// Tracks the id of the last object we have read, used to generate `ObjectId`s for `Amf3Reference`
171    /// Not an `ObjectId` itself as they don't impl `Default`
172    object_id: i64,
173}
174
175fn parse_element_number(i: &[u8]) -> AMFResult<'_, Value> {
176    let (i, v) = map(be_f64, Value::Number).parse(i)?;
177    Ok((i, v))
178}
179
180impl AMF3Decoder {
181    /// Register a custom decoder for external data formats
182    pub fn register_custom_decoder<T: CustomDecoder + Default + 'static>(&mut self, name: &str) {
183        self.external_decoders
184            .insert(name.to_string(), Rc::new(T::default()));
185    }
186
187    fn parse_element_string<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
188        let (i, s) = map(|i| self.parse_string(i), Value::String).parse(i)?;
189        Ok((i, (s)))
190    }
191
192    #[cfg(fuzzing)]
193    /// For fuzzing
194    pub fn fuzz_parse_string<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, String> {
195        self.parse_string(i)
196    }
197
198    fn parse_string<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, String> {
199        let (i, bytes) = self.parse_byte_stream(i)?;
200        let bytes_str =
201            String::from_utf8(bytes).map_err(|_| Err::Error(make_error(i, ErrorKind::Alpha)))?;
202        Ok((i, bytes_str))
203    }
204
205    fn parse_class_def<'a>(&mut self, length: u32, i: &'a [u8]) -> AMFResult<'a, ClassDefinition> {
206        if length & REFERENCE_FLAG == 0 {
207            let len_usize: usize = (length >> 1)
208                .try_into()
209                .map_err(|_| Err::Error(make_error(i, ErrorKind::Digit)))?;
210
211            let class_def = self
212                .trait_reference_table
213                .get(len_usize)
214                .ok_or_else(|| Err::Error(make_error(i, ErrorKind::Digit)))?
215                .clone();
216
217            return Ok((i, class_def));
218        }
219        let length = length >> 1;
220
221        //TODO: should name be Option<String>
222        let (i, name) = self.parse_byte_stream(i)?;
223        let name_str = if name.is_empty() {
224            "".to_string()
225        } else {
226            String::from_utf8(name).map_err(|_| Err::Error(make_error(i, ErrorKind::Alpha)))?
227        };
228
229        let encoding = (length & 0x03) as u8;
230
231        let attributes_count = length >> 2;
232
233        let attr_count_usize: usize = attributes_count
234            .try_into()
235            .map_err(|_| Err::Error(make_error(i, ErrorKind::Digit)))?;
236
237        // Read static attributes if they exist
238        let (i, static_props) =
239            many_m_n(attr_count_usize, attr_count_usize, |i| self.parse_string(i)).parse(i)?;
240
241        let is_external = encoding & 0b1 == 1;
242        let is_dynamic = encoding & 0b10 == 0b10;
243
244        let mut attributes = EnumSet::empty();
245
246        if is_external {
247            attributes |= Attribute::External;
248        }
249        if is_dynamic {
250            attributes |= Attribute::Dynamic;
251        }
252
253        let class_def = ClassDefinition {
254            name: name_str,
255            attributes,
256            static_properties: static_props,
257        };
258
259        self.trait_reference_table.push(class_def.clone());
260        Ok((i, class_def))
261    }
262
263    fn parse_reference_or_val<'a>(
264        &mut self,
265        i: &'a [u8],
266        parser: impl FnOnce(&mut Self, &'a [u8], usize, ObjectId) -> AMFResult<'a, Value>,
267    ) -> AMFResult<'a, Value> {
268        let (i, len) = read_length(i)?;
269
270        match len {
271            Length::Reference(index) => Ok((i, Value::Amf3ObjectReference(ObjectId(index as _)))),
272            Length::Size(len) => {
273                let len_usize: usize = len
274                    .try_into()
275                    .map_err(|_| Err::Error(make_error(i, ErrorKind::Digit)))?;
276
277                let index = self.object_id;
278                self.object_id += 1;
279
280                let (i, res) = parser(self, i, len_usize, ObjectId(index))?;
281
282                Ok((i, res))
283            }
284        }
285    }
286
287    fn parse_byte_stream<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Vec<u8>> {
288        let (i, len) = read_length(i)?;
289
290        match len {
291            Length::Size(len) => {
292                if len == 0 {
293                    Ok((i, Vec::new()))
294                } else {
295                    let (i, bytes) = take(len)(i)?;
296                    self.string_reference_table.push(bytes.to_vec());
297                    Ok((i, bytes.to_vec()))
298                }
299            }
300            Length::Reference(index) => {
301                let ref_result = self
302                    .string_reference_table
303                    .get(index)
304                    .ok_or_else(|| Err::Error(make_error(i, ErrorKind::Digit)))?
305                    .clone();
306
307                Ok((i, ref_result))
308            }
309        }
310    }
311
312    fn parse_object_static<'a>(
313        &mut self,
314        i: &'a [u8],
315        class_def: &ClassDefinition,
316    ) -> AMFResult<'a, Vec<Element>> {
317        let mut elements = Vec::new();
318        let mut i = i;
319
320        for name in class_def.static_properties.iter() {
321            let (j, e) = self.parse_single_element(i)?;
322
323            elements.push(Element {
324                name: name.clone(),
325                value: e,
326            });
327
328            i = j;
329        }
330
331        Ok((i, elements))
332    }
333
334    pub(crate) fn parse_element_object<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
335        let (i, mut length) = read_int(i)?;
336
337        if length & REFERENCE_FLAG == 0 {
338            let len_usize: usize = (length >> 1)
339                .try_into()
340                .map_err(|_| Err::Error(make_error(i, ErrorKind::Digit)))?;
341            return Ok((i, Value::Amf3ObjectReference(ObjectId(len_usize as _))));
342        }
343        length >>= 1;
344
345        let mut obj = Value::Object {
346            id: ObjectId(self.object_id),
347            data: ObjectValue {
348                elements: Vec::new(),
349                class_definition: None,
350            },
351        };
352        self.object_id += 1;
353
354        // Class def
355        let (i, class_def) = self.parse_class_def(length, i)?;
356
357        if let Value::Object { id: _, data } = &mut obj {
358            data.class_definition = Some(class_def.clone());
359        }
360
361        let mut elements = Vec::new();
362        let external_elements;
363
364        let mut i = i;
365        if class_def.attributes.contains(Attribute::External) {
366            let dec = self.external_decoders.get(&class_def.name).map(Rc::clone);
367            return if let Some(decoder) = dec {
368                let (j, v) = decoder.decode(i, self)?;
369                external_elements = v;
370                i = j;
371                //TODO: should it be possible to have both dynamic and external together
372                let value = Value::Custom(CustomObjectValue {
373                    elements: external_elements,
374                    dynamic_elements: Vec::new(),
375                    class_definition: class_def.clone(),
376                });
377
378                Ok((i, value))
379            } else {
380                Err(Err::Error(make_error(i, ErrorKind::Tag)))
381            };
382        }
383
384        if class_def.attributes.contains(Attribute::Dynamic) {
385            let (j, x) = self.parse_object_static(i, &class_def)?;
386            elements.extend(x);
387
388            // Read dynamic
389            let (mut j, mut attr) = self.parse_byte_stream(j)?;
390            while !attr.is_empty() {
391                let attr_str = String::from_utf8(attr)
392                    .map_err(|_| Err::Error(make_error(i, ErrorKind::Alpha)))?;
393                let (k, val) = self.parse_single_element(j)?;
394                elements.push(Element {
395                    name: attr_str,
396                    value: val,
397                });
398
399                let (k, attr2) = self.parse_byte_stream(k)?;
400                j = k;
401                attr = attr2;
402            }
403            i = j;
404        }
405        if class_def.attributes.is_empty() {
406            let (j, x) = self.parse_object_static(i, &class_def)?;
407            elements.extend(x);
408
409            i = j;
410        }
411
412        if let Value::Object { id: _, data } = &mut obj {
413            data.elements = elements;
414        }
415
416        Ok((i, obj))
417    }
418
419    fn parse_element_byte_array<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
420        self.parse_reference_or_val(i, |_this, i, len, _| {
421            let (i, bytes) = take(len)(i)?;
422            Ok((i, Value::ByteArray(bytes.to_vec())))
423        })
424    }
425
426    fn parse_element_vector_int<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
427        self.parse_reference_or_val(i, |_this, i, len, _| {
428            // There must be at least `len * 4` (i32 = 4 bytes) bytes to read this, this prevents OOM errors with v.large vecs
429            if i.len() < len * 4 {
430                return Err(Err::Error(make_error(i, ErrorKind::TooLarge)));
431            }
432
433            let (i, fixed_length) = be_u8(i)?;
434
435            let (i, values) = many_m_n(len, len, be_i32).parse(i)?;
436
437            Ok((
438                i,
439                Value::VectorInt(VectorPrimitiveValue {
440                    values,
441                    fixed_length: fixed_length == 1,
442                }),
443            ))
444        })
445    }
446
447    fn parse_element_vector_uint<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
448        self.parse_reference_or_val(i, |_this, i, len, _| {
449            // There must be at least `len * 4` (u32 = 4 bytes) bytes to read this, this prevents OOM errors with v.large vecs
450            if i.len() < len * 4 {
451                return Err(Err::Error(make_error(i, ErrorKind::TooLarge)));
452            }
453            let (i, fixed_length) = be_u8(i)?;
454
455            let (i, values) = many_m_n(len, len, be_u32).parse(i)?;
456
457            Ok((
458                i,
459                Value::VectorUInt(VectorPrimitiveValue {
460                    values,
461                    fixed_length: fixed_length == 1,
462                }),
463            ))
464        })
465    }
466
467    fn parse_element_vector_double<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
468        self.parse_reference_or_val(i, |_this, i, len, _| {
469            // There must be at least `len * 8` (f64 = 8 bytes) bytes to read this, this prevents OOM errors with v.large dicts
470            if i.len() < len * 8 {
471                return Err(Err::Error(make_error(i, ErrorKind::TooLarge)));
472            }
473            let (i, fixed_length) = be_u8(i)?;
474
475            let (i, values) = many_m_n(len, len, be_f64).parse(i)?;
476
477            Ok((
478                i,
479                Value::VectorDouble(VectorPrimitiveValue {
480                    values,
481                    fixed_length: fixed_length == 1,
482                }),
483            ))
484        })
485    }
486
487    fn parse_element_object_vector<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
488        self.parse_reference_or_val(i, |this, i, len, id| {
489            let (i, fixed_length) = be_u8(i)?;
490
491            let (i, object_type_name) = this.parse_string(i)?;
492
493            let (i, elems) = many_m_n(len, len, |i| this.parse_single_element(i)).parse(i)?;
494
495            Ok((
496                i,
497                Value::VectorObject {
498                    id,
499                    data: VectorObjectValue {
500                        values: elems,
501                        object_type_name,
502                        fixed_length: fixed_length == 1,
503                    },
504                },
505            ))
506        })
507    }
508
509    fn parse_element_array<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
510        self.parse_reference_or_val(i, |this, i, length_usize, id| {
511            // There must be at least `length_usize` bytes to read this, this prevents OOM errors with v.large dicts
512            if i.len() < length_usize {
513                return Err(Err::Error(make_error(i, ErrorKind::TooLarge)));
514            }
515
516            let (i, mut key) = this.parse_byte_stream(i)?;
517
518            if key.is_empty() {
519                let (i, values) =
520                    many_m_n(length_usize, length_usize, |i| this.parse_single_element(i))
521                        .parse(i)?;
522
523                return Ok((i, Value::StrictArray { id, values }));
524            }
525
526            let mut elements = Vec::with_capacity(length_usize);
527
528            let mut i = i;
529            while !key.is_empty() {
530                let (j, e) = this.parse_single_element(i)?;
531                let key_str = String::from_utf8(key)
532                    .map_err(|_| Err::Error(make_error(i, ErrorKind::Alpha)))?;
533
534                elements.push(Element {
535                    name: key_str,
536                    value: e,
537                });
538                let (j, k) = this.parse_byte_stream(j)?;
539                i = j;
540                key = k;
541            }
542
543            // Must parse `length` elements
544            let (i, el) =
545                many_m_n(length_usize, length_usize, |i| this.parse_single_element(i)).parse(i)?;
546
547            let elements_len = elements.len() as u32;
548
549            Ok((
550                i,
551                Value::ECMAArray {
552                    id,
553                    data: ECMAArrayObjectValue {
554                        dense: el,
555                        elements,
556                        length: elements_len,
557                    },
558                },
559            ))
560        })
561    }
562
563    fn parse_element_dict<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
564        self.parse_reference_or_val(i, |this, i, len, id| {
565            //TODO: implications of this
566            let (i, weak_keys) = be_u8(i)?;
567
568            // There must be at least `len * 2` bytes (due to (key,val) pairs) to read this, this prevents OOM errors with v.large dicts
569            if i.len() < len * 2 {
570                return Err(Err::Error(make_error(i, ErrorKind::TooLarge)));
571            }
572
573            let (i, pairs) =
574                many_m_n(len * 2, len * 2, |i| this.parse_single_element(i)).parse(i)?;
575
576            let pairs = pairs
577                .as_chunks::<2>()
578                .0
579                .iter()
580                .map(|[key, value]| DictionaryEntry {
581                    key: key.clone(),
582                    value: value.clone(),
583                })
584                .collect::<Vec<_>>();
585
586            Ok((
587                i,
588                Value::Dictionary {
589                    id,
590                    data: DictionaryObjectValue {
591                        weak_keys: weak_keys == 1,
592                        elements: pairs,
593                    },
594                },
595            ))
596        })
597    }
598
599    fn parse_element_date<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
600        self.parse_reference_or_val(i, |_this, i, _len, _| {
601            let (i, time) = be_f64(i)?;
602            Ok((
603                i,
604                Value::Date {
605                    time,
606                    timezone_or_utc: None,
607                },
608            ))
609        })
610    }
611
612    fn parse_element_xml<'a>(&mut self, i: &'a [u8], string: bool) -> AMFResult<'a, Value> {
613        self.parse_reference_or_val(i, |_this, i, len, _| {
614            let (i, data) = map_res(take(len as u32), std::str::from_utf8).parse(i)?;
615            Ok((
616                i,
617                Value::XML {
618                    value: data.to_string(),
619                    is_string: string,
620                },
621            ))
622        })
623    }
624
625    fn read_type_marker<'a>(&self, i: &'a [u8]) -> AMFResult<'a, TypeMarker> {
626        let (i, type_) = be_u8(i)?;
627        if let Ok(type_) = TypeMarker::try_from(type_) {
628            Ok((i, type_))
629        } else {
630            Err(Err::Error(crate::errors::Error::UnsupportedType(type_)))
631        }
632    }
633
634    /// Parse a single AMF3 element from the input
635    pub fn parse_single_element<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
636        let (i, type_) = self.read_type_marker(i)?;
637
638        match type_ {
639            TypeMarker::Undefined => Ok((i, (Value::Undefined))),
640            TypeMarker::Null => Ok((i, (Value::Null))),
641            TypeMarker::False => Ok((i, (Value::Bool(false)))),
642            TypeMarker::True => Ok((i, (Value::Bool(true)))),
643            TypeMarker::Integer => parse_element_int(i),
644            TypeMarker::Number => parse_element_number(i),
645            TypeMarker::String => self.parse_element_string(i),
646            TypeMarker::Xml => self.parse_element_xml(i, false),
647            TypeMarker::Date => self.parse_element_date(i),
648            TypeMarker::Array => self.parse_element_array(i),
649            TypeMarker::Object => self.parse_element_object(i),
650            TypeMarker::XmlString => self.parse_element_xml(i, true),
651            TypeMarker::ByteArray => self.parse_element_byte_array(i),
652            TypeMarker::VectorObject => self.parse_element_object_vector(i),
653            TypeMarker::VectorInt => self.parse_element_vector_int(i),
654            TypeMarker::VectorUInt => self.parse_element_vector_uint(i),
655            TypeMarker::VectorDouble => self.parse_element_vector_double(i),
656            TypeMarker::Dictionary => self.parse_element_dict(i),
657        }
658    }
659
660    fn parse_element<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Element> {
661        let (i, name) = self.parse_string(i)?;
662
663        map(
664            |i| self.parse_single_element(i),
665            move |v| Element {
666                name: name.clone(),
667                value: v,
668            },
669        )
670        .parse(i)
671    }
672
673    /// Parse an AMF3 body from a slice into a list of elements
674    pub fn parse_body<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Vec<Element>> {
675        let (i, elements) =
676            separated_list0(tag(PADDING.as_slice()), |i| self.parse_element(i)).parse(i)?;
677        let (i, _) = tag(PADDING.as_slice())(i)?;
678        Ok((i, elements))
679    }
680}