fix(gui): startup crash in clang/LLVM builds, null pointer UB in create_scaled_bitmap (#14521)

fix(gui): avoid null-pointer UB in create_scaled_bitmap with win == nullptr

create_scaled_bitmap() documents that win may be nullptr, but called
win->FromDIP() on it. Calling a member function through a null pointer
is undefined behavior: clang assumes `this` is non-null and deletes the
subsequent `win ?` null check added in #13117, turning the fallback
branch into an unconditional virtual call through a null vtable.
This crashed LLVM/clang-cl builds at startup (access violation reading
0x0 in BBLTopbar creation); MSVC builds were unaffected by luck.

Use the static, null-safe wxWindow::FromDIP(x, win) overload instead,
which falls back to the primary display DPI. Behavior is unchanged for
non-null windows.
This commit is contained in:
Gabriel Monteiro
2026-07-06 00:28:03 -03:00
committed by GitHub
parent db2f861a11
commit fd80ded5a8

View File

@@ -436,7 +436,9 @@ wxBitmap create_scaled_bitmap( const std::string& bmp_name_in,
return create_scaled_bitmap2(bmp_name_in, cache, win, px_cnt, grayscale, resize, array_new_color);
}
unsigned int width = 0;
unsigned int height = (unsigned int) (win->FromDIP(px_cnt) + 0.5f);
// win may be nullptr; use the static overload, which falls back to the primary display DPI.
// Calling win->FromDIP() on a null win is UB and lets the optimizer drop later null checks.
unsigned int height = (unsigned int) (wxWindow::FromDIP(px_cnt, win) + 0.5f);
std::string bmp_name = bmp_name_in;
boost::replace_last(bmp_name, ".png", "");
@@ -450,7 +452,7 @@ wxBitmap create_scaled_bitmap( const std::string& bmp_name_in,
// Try loading an SVG first, then PNG if SVG was not found:
wxBitmap *bmp = cache.load_svg(bmp_name, width, height, grayscale, dark_mode, new_color, resize ? em_unit(win) * 0.1f : 0.f);
if (bmp == nullptr) {
bmp = cache.load_png(bmp_name, width, height, grayscale, resize ? win->FromDIP(10) * 0.1f : 0.f);
bmp = cache.load_png(bmp_name, width, height, grayscale, resize ? wxWindow::FromDIP(10, win) * 0.1f : 0.f);
}
if (bmp == nullptr) {
@@ -471,7 +473,8 @@ wxBitmap create_scaled_bitmap2(const std::string& bmp_name_in, Slic3r::GUI::Bitm
const vector<std::string>& array_new_color/* = vector<std::string>()*/) // color witch will used instead of orange
{
unsigned int width = 0;
unsigned int height = (unsigned int)(win->FromDIP(px_cnt) + 0.5f);
// win may be nullptr; see create_scaled_bitmap() above.
unsigned int height = (unsigned int)(wxWindow::FromDIP(px_cnt, win) + 0.5f);
std::string bmp_name = bmp_name_in;
boost::replace_last(bmp_name, ".png", "");