#[rustfmt::skip] mod aat; #[rustfmt::skip] mod ankr; #[rustfmt::skip] mod cff1; #[rustfmt::skip] mod cmap; #[rustfmt::skip] mod colr; #[rustfmt::skip] mod feat; #[rustfmt::skip] mod glyf; #[rustfmt::skip] mod hmtx; #[rustfmt::skip] mod maxp; #[rustfmt::skip] mod sbix; #[rustfmt::skip] mod trak; use ttf_parser::{fonts_in_collection, Face, FaceParsingError}; #[allow(dead_code)] #[derive(Clone, Copy)] pub enum Unit { Raw(&'static [u8]), Int8(i8), UInt8(u8), Int16(i16), UInt16(u16), Int32(i32), UInt32(u32), Fixed(f32), } pub fn convert(units: &[Unit]) -> Vec { let mut data = Vec::with_capacity(256); for v in units { convert_unit(*v, &mut data); } data } fn convert_unit(unit: Unit, data: &mut Vec) { match unit { Unit::Raw(bytes) => { data.extend_from_slice(bytes); } Unit::Int8(n) => { data.extend_from_slice(&i8::to_be_bytes(n)); } Unit::UInt8(n) => { data.extend_from_slice(&u8::to_be_bytes(n)); } Unit::Int16(n) => { data.extend_from_slice(&i16::to_be_bytes(n)); } Unit::UInt16(n) => { data.extend_from_slice(&u16::to_be_bytes(n)); } Unit::Int32(n) => { data.extend_from_slice(&i32::to_be_bytes(n)); } Unit::UInt32(n) => { data.extend_from_slice(&u32::to_be_bytes(n)); } Unit::Fixed(n) => { data.extend_from_slice(&i32::to_be_bytes((n * 65536.0) as i32)); } } } #[test] fn empty_font() { assert_eq!( Face::parse(&[], 0).unwrap_err(), FaceParsingError::UnknownMagic ); } #[test] fn zero_tables() { use Unit::*; let data = convert(&[ Raw(&[0x00, 0x01, 0x00, 0x00]), // magic UInt16(0), // numTables UInt16(0), // searchRange UInt16(0), // entrySelector UInt16(0), // rangeShift ]); assert_eq!( Face::parse(&data, 0).unwrap_err(), FaceParsingError::NoHeadTable ); } #[test] fn tables_count_overflow() { use Unit::*; let data = convert(&[ Raw(&[0x00, 0x01, 0x00, 0x00]), // magic UInt16(std::u16::MAX), // numTables UInt16(0), // searchRange UInt16(0), // entrySelector UInt16(0), // rangeShift ]); assert_eq!( Face::parse(&data, 0).unwrap_err(), FaceParsingError::MalformedFont ); } #[test] fn empty_font_collection() { use Unit::*; let data = convert(&[ Raw(&[0x74, 0x74, 0x63, 0x66]), // magic UInt16(0), // majorVersion UInt16(0), // minorVersion UInt32(0), // numFonts ]); assert_eq!(fonts_in_collection(&data), Some(0)); assert_eq!( Face::parse(&data, 0).unwrap_err(), FaceParsingError::FaceIndexOutOfBounds ); } #[test] fn font_collection_num_fonts_overflow() { use Unit::*; let data = convert(&[ Raw(&[0x74, 0x74, 0x63, 0x66]), // magic UInt16(0), // majorVersion UInt16(0), // minorVersion UInt32(std::u32::MAX), // numFonts ]); assert_eq!(fonts_in_collection(&data), Some(std::u32::MAX)); assert_eq!( Face::parse(&data, 0).unwrap_err(), FaceParsingError::MalformedFont ); } #[test] fn font_index_overflow() { use Unit::*; let data = convert(&[ Raw(&[0x74, 0x74, 0x63, 0x66]), // magic UInt16(0), // majorVersion UInt16(0), // minorVersion UInt32(1), // numFonts UInt32(12), // offset [0] ]); assert_eq!(fonts_in_collection(&data), Some(1)); assert_eq!( Face::parse(&data, std::u32::MAX).unwrap_err(), FaceParsingError::FaceIndexOutOfBounds ); } #[test] fn font_index_overflow_on_regular_font() { use Unit::*; let data = convert(&[ Raw(&[0x00, 0x01, 0x00, 0x00]), // magic UInt16(0), // numTables UInt16(0), // searchRange UInt16(0), // entrySelector UInt16(0), // rangeShift ]); assert_eq!(fonts_in_collection(&data), None); assert_eq!( Face::parse(&data, 1).unwrap_err(), FaceParsingError::FaceIndexOutOfBounds ); }