Skip to content

Commit 98add13

Browse files
authored
Workaround libpng crash on macos by not creating NSImage from png data (#7252)
1 parent c8b844c commit 98add13

File tree

1 file changed

+39
-10
lines changed

1 file changed

+39
-10
lines changed

crates/eframe/src/native/app_icon.rs

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -205,13 +205,18 @@ fn set_title_and_icon_mac(title: &str, icon_data: Option<&IconData>) -> AppIconS
205205

206206
use objc2::ClassType as _;
207207
use objc2_app_kit::{NSApplication, NSImage};
208-
use objc2_foundation::{NSData, NSString};
208+
use objc2_foundation::NSString;
209209

210-
let png_bytes = if let Some(icon_data) = icon_data {
211-
match icon_data.to_png_bytes() {
212-
Ok(png_bytes) => Some(png_bytes),
210+
// Do NOT use png even though creating `NSImage` from it is much easier than from raw images data!
211+
//
212+
// Some MacOS versions have a bug where creating an `NSImage` from a png will cause it to load an arbitrary `libpng.dylib`.
213+
// If this dylib isn't the right version, the application will crash with SIGBUS.
214+
// For details see https://github.com/emilk/egui/issues/7155
215+
let image = if let Some(icon_data) = icon_data {
216+
match icon_data.to_image() {
217+
Ok(image) => Some(image),
213218
Err(err) => {
214-
log::warn!("Failed to convert IconData to png: {err}");
219+
log::warn!("Failed to read icon data: {err}");
215220
return AppIconStatus::NotSetIgnored;
216221
}
217222
}
@@ -231,15 +236,39 @@ fn set_title_and_icon_mac(title: &str, icon_data: Option<&IconData>) -> AppIconS
231236
return AppIconStatus::NotSetIgnored;
232237
};
233238

234-
if let Some(png_bytes) = png_bytes {
235-
let data = NSData::from_vec(png_bytes);
239+
if let Some(image) = image {
240+
use objc2_app_kit::{NSBitmapImageRep, NSDeviceRGBColorSpace};
241+
use objc2_foundation::NSSize;
242+
243+
log::trace!("NSBitmapImageRep::initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bytesPerRow_bitsPerPixel");
244+
let Some(image_rep) = NSBitmapImageRep::initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bytesPerRow_bitsPerPixel(
245+
NSBitmapImageRep::alloc(),
246+
[image.as_raw().as_ptr().cast_mut()].as_mut_ptr(),
247+
image.width() as isize,
248+
image.height() as isize,
249+
8, // bits per sample
250+
4, // samples per pixel
251+
true, // has alpha
252+
false, // is not planar
253+
NSDeviceRGBColorSpace,
254+
(image.width() * 4) as isize, // bytes per row
255+
32 // bits per pixel
256+
) else {
257+
log::warn!("Failed to create NSBitmapImageRep from app icon data.");
258+
return AppIconStatus::NotSetIgnored;
259+
};
236260

237-
log::trace!("NSImage::initWithData…");
238-
let app_icon = NSImage::initWithData(NSImage::alloc(), &data);
261+
log::trace!("NSImage::initWithSize");
262+
let app_icon = NSImage::initWithSize(
263+
NSImage::alloc(),
264+
NSSize::new(image.width() as f64, image.height() as f64),
265+
);
266+
log::trace!("NSImage::addRepresentation");
267+
app_icon.addRepresentation(&image_rep);
239268

240269
profiling::scope!("setApplicationIconImage_");
241270
log::trace!("setApplicationIconImage…");
242-
app.setApplicationIconImage(app_icon.as_deref());
271+
app.setApplicationIconImage(Some(&app_icon));
243272
}
244273

245274
// Change the title in the top bar - for python processes this would be again "python" otherwise.

0 commit comments

Comments
 (0)