Skip to content

Commit

Permalink
Auto merge of #186 - warpdotdev:add_bound_safety_checks, r=jdm
Browse files Browse the repository at this point in the history
Add bound safety checks

Thank you guys for making this awesome library!

I noticed that there are a couple of places in the library where corrupted / non-standard font header file could cause panicking rather than returning a parsing error. These panics are mainly caused by out of bounds errors when slicing with wrong indices. Thus, I added some bound safety checks to return a proper parsing error when these scenarios happen. This PR does not change anything functionality-wise.
  • Loading branch information
bors-servo authored Oct 9, 2021
2 parents 20f5aca + aa33343 commit 589e626
Showing 1 changed file with 25 additions and 14 deletions.
39 changes: 25 additions & 14 deletions src/loaders/core_text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -822,18 +822,24 @@ fn read_number_of_fonts_from_otc_header(header: &[u8]) -> Result<u32, FontLoadin
Ok((&header[8..]).read_u32::<BigEndian>()?)
}

fn get_slice_from_start(slice: &[u8], start: usize) -> Result<&[u8], FontLoadingError> {
slice.get(start..).ok_or(FontLoadingError::Parse)
}

// Unpacks an OTC font "in-place".
fn unpack_otc_font(data: &mut [u8], font_index: u32) -> Result<(), FontLoadingError> {
if font_index >= read_number_of_fonts_from_otc_header(data)? {
return Err(FontLoadingError::NoSuchFontInCollection);
}

let offset_table_pos_pos = 12 + 4 * font_index as usize;
let offset_table_pos = (&data[offset_table_pos_pos..]).read_u32::<BigEndian>()? as usize;

let offset_table_pos =
get_slice_from_start(&data, offset_table_pos_pos)?.read_u32::<BigEndian>()? as usize;
debug_assert!(utils::SFNT_VERSIONS
.iter()
.any(|version| { data[offset_table_pos..(offset_table_pos + 4)] == *version }));
let num_tables = (&data[(offset_table_pos + 4)..]).read_u16::<BigEndian>()?;
let num_tables = get_slice_from_start(&data, offset_table_pos + 4)?.read_u16::<BigEndian>()?;

// Must copy forward in order to avoid problems with overlapping memory.
let offset_table_and_table_record_size = 12 + (num_tables as usize) * 16;
Expand Down Expand Up @@ -868,26 +874,31 @@ fn font_is_single_otf(header: &[u8]) -> bool {
/// https://developer.apple.com/library/archive/documentation/mac/pdf/MoreMacintoshToolbox.pdf#page=151
fn unpack_data_fork_font(data: &mut [u8]) -> Result<(), FontLoadingError> {
let data_offset = (&data[..]).read_u32::<BigEndian>()? as usize;
let map_offset = (&data[4..]).read_u32::<BigEndian>()? as usize;
let num_types = (&data[map_offset + 28..]).read_u16::<BigEndian>()? as usize + 1;
let map_offset = get_slice_from_start(&data, 4)?.read_u32::<BigEndian>()? as usize;
let num_types =
get_slice_from_start(&data, map_offset + 28)?.read_u16::<BigEndian>()? as usize + 1;

let mut font_data_offset = 0;
let mut font_data_len = 0;

let type_list_offset =
(&data[map_offset + 24..]).read_u16::<BigEndian>()? as usize + map_offset;
let type_list_offset = get_slice_from_start(&data, map_offset + 24)?.read_u16::<BigEndian>()?
as usize
+ map_offset;
for i in 0..num_types {
let res_type = (&data[map_offset + 30 + i * 8..]).read_u32::<BigEndian>()?;
let res_type =
get_slice_from_start(&data, map_offset + 30 + i * 8)?.read_u32::<BigEndian>()?;

if res_type == SFNT_HEX {
let ref_list_offset =
(&data[map_offset + 30 + i * 8 + 6..]).read_u16::<BigEndian>()? as usize;
let ref_list_offset = get_slice_from_start(&data, map_offset + 30 + i * 8 + 6)?
.read_u16::<BigEndian>()? as usize;
let res_data_offset =
(&data[type_list_offset + ref_list_offset + 5..]).read_u24::<BigEndian>()? as usize;
font_data_len =
(&data[data_offset + res_data_offset..]).read_u32::<BigEndian>()? as usize;
get_slice_from_start(&data, type_list_offset + ref_list_offset + 5)?
.read_u24::<BigEndian>()? as usize;
font_data_len = get_slice_from_start(&data, data_offset + res_data_offset)?
.read_u32::<BigEndian>()? as usize;
font_data_offset = data_offset + res_data_offset + 4;
let sfnt_version = (&data[font_data_offset..]).read_u32::<BigEndian>()?;
let sfnt_version =
get_slice_from_start(&data, font_data_offset)?.read_u32::<BigEndian>()?;

// TrueType outline, 'OTTO', 'true', 'typ1'
if sfnt_version == 0x00010000
Expand Down Expand Up @@ -984,7 +995,7 @@ pub(crate) fn piecewise_linear_find_index(query_value: f32, mapping: &[f32]) ->
Ok(index) => return index as f32,
Err(upper_index) => upper_index,
};
if upper_index == 0 {
if upper_index == 0 || upper_index >= mapping.len() {
return upper_index as f32;
}
let lower_index = upper_index - 1;
Expand Down

0 comments on commit 589e626

Please sign in to comment.