From 67d4ba9f76470a7ff1f3e7609119cdbb9d33024c Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Sat, 4 May 2024 15:53:28 -0700 Subject: [PATCH] fix when running on rust 1.78 std::slice::from_raw_parts will now panic if the ptr is null. Resolve this by adding our own wrapper that translates that case to an empty slice. --- wezterm-font/src/ftwrap.rs | 60 +++++++++++-------------- wezterm-font/src/rasterizer/freetype.rs | 4 +- 2 files changed, 29 insertions(+), 35 deletions(-) diff --git a/wezterm-font/src/ftwrap.rs b/wezterm-font/src/ftwrap.rs index 5f06a3fb8..5c9bf1286 100644 --- a/wezterm-font/src/ftwrap.rs +++ b/wezterm-font/src/ftwrap.rs @@ -260,10 +260,7 @@ impl Face { } let bytes = unsafe { - std::slice::from_raw_parts( - sfnt_name.string as *const u8, - sfnt_name.string_len as usize, - ) + from_raw_parts(sfnt_name.string as *const u8, sfnt_name.string_len as usize) }; let encoding = match (sfnt_name.platform_id as u32, sfnt_name.encoding_id as u32) { @@ -350,14 +347,12 @@ impl Face { { let mm = &*mm; - let styles = - std::slice::from_raw_parts(mm.namedstyle, mm.num_namedstyles as usize); + let styles = from_raw_parts(mm.namedstyle, mm.num_namedstyles as usize); let instance = &styles[vidx]; - let axes = std::slice::from_raw_parts(mm.axis, mm.num_axis as usize); + let axes = from_raw_parts(mm.axis, mm.num_axis as usize); for (i, axis) in axes.iter().enumerate() { - let coords = - std::slice::from_raw_parts(instance.coords, mm.num_axis as usize); + let coords = from_raw_parts(instance.coords, mm.num_axis as usize); let value = coords[i].to_num::(); let default_value = axis.def.to_num::(); let scale = if default_value != 0. { @@ -436,7 +431,7 @@ impl Face { pub fn pixel_sizes(&self) -> Vec { let sizes = unsafe { let rec = &(*self.face); - std::slice::from_raw_parts(rec.available_sizes, rec.num_fixed_sizes as usize) + from_raw_parts(rec.available_sizes, rec.num_fixed_sizes as usize) }; sizes .iter() @@ -494,7 +489,7 @@ impl Face { let sizes = unsafe { let rec = &(*self.face); - std::slice::from_raw_parts(rec.available_sizes, rec.num_fixed_sizes as usize) + from_raw_parts(rec.available_sizes, rec.num_fixed_sizes as usize) }; if sizes.is_empty() { return Err(err); @@ -723,24 +718,12 @@ impl Face { let data = result.assume_init(); let mut palettes = vec![]; - let name_ids = if data.palette_name_ids.is_null() { - &[] - } else { - std::slice::from_raw_parts(data.palette_name_ids, data.num_palettes as usize) - }; - let flagses = if data.palette_flags.is_null() { - &[] - } else { - std::slice::from_raw_parts(data.palette_flags, data.num_palettes as usize) - }; - let entry_name_ids = if data.palette_entry_name_ids.is_null() { - &[] - } else { - std::slice::from_raw_parts( - data.palette_entry_name_ids, - data.num_palette_entries as usize, - ) - }; + let name_ids = from_raw_parts(data.palette_name_ids, data.num_palettes as usize); + let flagses = from_raw_parts(data.palette_flags, data.num_palettes as usize); + let entry_name_ids = from_raw_parts( + data.palette_entry_name_ids, + data.num_palette_entries as usize, + ); let entry_names: Vec = entry_name_ids .iter() @@ -777,10 +760,8 @@ impl Face { ft_result(FT_Get_Sfnt_Name(self.face, i, sfnt_name.as_mut_ptr()), ()) .context("FT_Get_Sfnt_Name")?; let sfnt_name = sfnt_name.assume_init(); - let bytes = std::slice::from_raw_parts( - sfnt_name.string as *const u8, - sfnt_name.string_len as usize, - ); + let bytes = + from_raw_parts(sfnt_name.string as *const u8, sfnt_name.string_len as usize); let encoding = match (sfnt_name.platform_id as u32, sfnt_name.encoding_id as u32) { (TT_PLATFORM_MACINTOSH, TT_MAC_ID_JAPANESE) @@ -1472,6 +1453,19 @@ impl FreeTypeStream { } } +/// Wrapper around std::slice::from_raw_parts that allows for ptr to be +/// null. In the null ptr case, an empty slice is returned. +/// This is necessary because it is common for freetype to encode +/// empty arrays in that way, and rust 1.78 will panic if a null +/// ptr is passed in. +pub(crate) unsafe fn from_raw_parts<'a, T>(ptr: *const T, size: usize) -> &'a [T] { + if ptr.is_null() { + &[] + } else { + std::slice::from_raw_parts(ptr, size) + } +} + #[derive(Debug)] pub struct PaletteInfo { pub num_palettes: usize, diff --git a/wezterm-font/src/rasterizer/freetype.rs b/wezterm-font/src/rasterizer/freetype.rs index 9f9cf3342..2e7a366a1 100644 --- a/wezterm-font/src/rasterizer/freetype.rs +++ b/wezterm-font/src/rasterizer/freetype.rs @@ -20,8 +20,8 @@ use cairo::{Content, Context, Extend, Format, ImageSurface, Matrix, Operator, Re use config::{DisplayPixelGeometry, FreeTypeLoadFlags, FreeTypeLoadTarget}; use std::cell::RefCell; use std::f64::consts::PI; +use std::mem; use std::mem::MaybeUninit; -use std::{mem, slice}; use wezterm_color_types::{linear_u8_to_srgb8, SrgbaPixel}; pub struct FreeTypeRasterizer { @@ -93,7 +93,7 @@ impl FontRasterizer for FreeTypeRasterizer { // pitch is the number of bytes per source row let pitch = ft_glyph.bitmap.pitch.abs() as usize; let data = unsafe { - slice::from_raw_parts_mut( + crate::ftwrap::from_raw_parts( ft_glyph.bitmap.buffer, ft_glyph.bitmap.rows as usize * pitch, )