Fix segfault caused by wrong size of path sprites bytes length

Previously, we were using `size_of` but passing the wrong type in
(MonochromeSprite instead of PathSprite). This caused us to read outside
of the `sprites` smallvec and triggered the segfault.
This commit is contained in:
Antonio Scandurra 2024-01-17 09:45:46 +01:00
parent 26a3f68080
commit 97bd3e1fde

View file

@ -14,6 +14,7 @@ use foreign_types::ForeignType;
use media::core_video::CVMetalTextureCache;
use metal::{CommandQueue, MTLPixelFormat, MTLResourceOptions, NSRange};
use objc::{self, msg_send, sel, sel_impl};
use smallvec::SmallVec;
use std::{ffi::c_void, mem, ptr, sync::Arc};
const SHADERS_METALLIB: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/shaders.metallib"));
@ -81,7 +82,7 @@ impl MetalRenderer {
];
let unit_vertices = device.new_buffer_with_data(
unit_vertices.as_ptr() as *const c_void,
(unit_vertices.len() * mem::size_of::<u64>()) as u64,
mem::size_of_val(&unit_vertices) as u64,
MTLResourceOptions::StorageModeManaged,
);
let instances = device.new_buffer(
@ -339,7 +340,8 @@ impl MetalRenderer {
for (texture_id, vertices) in vertices_by_texture_id {
align_offset(offset);
let next_offset = *offset + vertices.len() * mem::size_of::<PathVertex<ScaledPixels>>();
let vertices_bytes_len = mem::size_of_val(vertices.as_slice());
let next_offset = *offset + vertices_bytes_len;
if next_offset > INSTANCE_BUFFER_SIZE {
return None;
}
@ -372,7 +374,6 @@ impl MetalRenderer {
&texture_size as *const Size<DevicePixels> as *const _,
);
let vertices_bytes_len = mem::size_of::<PathVertex<ScaledPixels>>() * vertices.len();
let buffer_contents = unsafe { (self.instances.contents() as *mut u8).add(*offset) };
unsafe {
ptr::copy_nonoverlapping(
@ -429,7 +430,7 @@ impl MetalRenderer {
&viewport_size as *const Size<DevicePixels> as *const _,
);
let shadow_bytes_len = std::mem::size_of_val(shadows);
let shadow_bytes_len = mem::size_of_val(shadows);
let buffer_contents = unsafe { (self.instances.contents() as *mut u8).add(*offset) };
let next_offset = *offset + shadow_bytes_len;
@ -490,7 +491,7 @@ impl MetalRenderer {
&viewport_size as *const Size<DevicePixels> as *const _,
);
let quad_bytes_len = std::mem::size_of_val(quads);
let quad_bytes_len = mem::size_of_val(quads);
let buffer_contents = unsafe { (self.instances.contents() as *mut u8).add(*offset) };
let next_offset = *offset + quad_bytes_len;
@ -537,7 +538,7 @@ impl MetalRenderer {
);
let mut prev_texture_id = None;
let mut sprites = Vec::new();
let mut sprites = SmallVec::<[_; 1]>::new();
let mut paths_and_tiles = paths
.iter()
.map(|path| (path, tiles_by_path_id.get(&path.id).unwrap()))
@ -590,7 +591,7 @@ impl MetalRenderer {
command_encoder
.set_fragment_texture(SpriteInputIndex::AtlasTexture as u64, Some(&texture));
let sprite_bytes_len = mem::size_of::<MonochromeSprite>() * sprites.len();
let sprite_bytes_len = mem::size_of_val(sprites.as_slice());
let next_offset = *offset + sprite_bytes_len;
if next_offset > INSTANCE_BUFFER_SIZE {
return false;
@ -655,17 +656,17 @@ impl MetalRenderer {
&viewport_size as *const Size<DevicePixels> as *const _,
);
let quad_bytes_len = std::mem::size_of_val(underlines);
let underline_bytes_len = mem::size_of_val(underlines);
let buffer_contents = unsafe { (self.instances.contents() as *mut u8).add(*offset) };
unsafe {
ptr::copy_nonoverlapping(
underlines.as_ptr() as *const u8,
buffer_contents,
quad_bytes_len,
underline_bytes_len,
);
}
let next_offset = *offset + quad_bytes_len;
let next_offset = *offset + underline_bytes_len;
if next_offset > INSTANCE_BUFFER_SIZE {
return false;
}
@ -726,7 +727,7 @@ impl MetalRenderer {
);
command_encoder.set_fragment_texture(SpriteInputIndex::AtlasTexture as u64, Some(&texture));
let sprite_bytes_len = std::mem::size_of_val(sprites);
let sprite_bytes_len = mem::size_of_val(sprites);
let buffer_contents = unsafe { (self.instances.contents() as *mut u8).add(*offset) };
let next_offset = *offset + sprite_bytes_len;
@ -798,7 +799,7 @@ impl MetalRenderer {
);
command_encoder.set_fragment_texture(SpriteInputIndex::AtlasTexture as u64, Some(&texture));
let sprite_bytes_len = std::mem::size_of_val(sprites);
let sprite_bytes_len = mem::size_of_val(sprites);
let buffer_contents = unsafe { (self.instances.contents() as *mut u8).add(*offset) };
let next_offset = *offset + sprite_bytes_len;