Skip to content

Fix a use-after-free in OKLab picker rendering

Rafał Siejakowski requested to merge S-Rafael/inkscape:okwheel-crash into master

Dormant bug caused by a reallocation of an std::vector causing the raw .data() pointer held by a Cairo surface to dangle, started occurring after the GTK4 update.

The fix is to use an internally managed pixel buffer for the Cairo surface.

=================================================================
==13172==ERROR: AddressSanitizer: heap-use-after-free on address 0x7c54eff4c800 at pc 0x7c5509661003 bp 0x7ffd586d4520 sp 0x7ffd586d3cc8
READ of size 454276 at 0x7c54eff4c800 thread T0
    #0 0x7c5509661002 in __interceptor_memcpy /usr/src/debug/gcc/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:899
    #1 0x7c5509d4c93e  (/usr/lib/libcairo.so.2+0x2c93e) (BuildId: f8be9c9f8b8afa71947a35bb07cff97d83187e37)
    #2 0x7c5509d7b683  (/usr/lib/libcairo.so.2+0x5b683) (BuildId: f8be9c9f8b8afa71947a35bb07cff97d83187e37)
    #3 0x7c5509d88a62  (/usr/lib/libcairo.so.2+0x68a62) (BuildId: f8be9c9f8b8afa71947a35bb07cff97d83187e37)
    #4 0x7c5509d88bb3  (/usr/lib/libcairo.so.2+0x68bb3) (BuildId: f8be9c9f8b8afa71947a35bb07cff97d83187e37)
    #5 0x7c5509d8890c in cairo_surface_destroy (/usr/lib/libcairo.so.2+0x6890c) (BuildId: f8be9c9f8b8afa71947a35bb07cff97d83187e37)
    #6 0x7c5503879c54 in Cairo::Surface::~Surface() (/usr/lib/libcairomm-1.16.so.1+0x18c54) (BuildId: 321661a97c551776ae90a6729c944f403dcdc74f)
    #7 0x7c5503879d89  (/usr/lib/libcairomm-1.16.so.1+0x18d89) (BuildId: 321661a97c551776ae90a6729c944f403dcdc74f)
    #8 0x7c5506843663 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /usr/include/c++/13.2.1/bits/shared_ptr_base.h:346
    #9 0x7c55068dd69b in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() /usr/include/c++/13.2.1/bits/shared_ptr_base.h:1071
    #10 0x7c55068dd69b in std::__shared_ptr<Cairo::ImageSurface, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() /usr/include/c++/13.2.1/bits/shared_ptr_base.h:1524
    #11 0x7c55068dd69b in std::__shared_ptr<Cairo::ImageSurface, (__gnu_cxx::_Lock_policy)2>::operator=(std::__shared_ptr<Cairo::ImageSurface, (__gnu_cxx::_Lock_policy)2>&&) /usr/include/c++/13.2.1/bits/shared_ptr_base.h:1620
    #12 0x7c55084ed09a in std::shared_ptr<Cairo::ImageSurface>::operator=(std::shared_ptr<Cairo::ImageSurface>&&) /usr/include/c++/13.2.1/bits/shared_ptr.h:440
    #13 0x7c55084ed09a in Inkscape::UI::Widget::OKWheel::_redrawDisc() src/ui/widget/oklab-color-wheel.cpp:239
    #14 0x7c55084ed8ff in Inkscape::UI::Widget::OKWheel::on_drawing_area_draw(std::shared_ptr<Cairo::Context> const&, int, int) src/ui/widget/oklab-color-wheel.cpp:176
    #15 0x7c5508497f81 in void std::__invoke_impl<void, void (Inkscape::UI::Widget::ColorWheel::* const&)(std::shared_ptr<Cairo::Context> const&, int, int), Inkscape::UI::Widget::ColorWheel&, std::shared_ptr<Cairo::Context> const&, int const&, int const&>(std::__invoke_memfun_ref, void (Inkscape::UI::Widget::ColorWheel::* const&)(std::shared_ptr<Cairo::Context> const&, int, int), Inkscape::UI::Widget::ColorWheel&, std::shared_ptr<Cairo::Context> const&, int const&, int const&) /usr/include/c++/13.2.1/bits/invoke.h:67
    #16 0x7c5508498000 in std::__invoke_result<void (Inkscape::UI::Widget::ColorWheel::* const&)(std::shared_ptr<Cairo::Context> const&, int, int), Inkscape::UI::Widget::ColorWheel&, std::shared_ptr<Cairo::Context> const&, int const&, int const&>::type std::__invoke<void (Inkscape::UI::Widget::ColorWheel::* const&)(std::shared_ptr<Cairo::Context> const&, int, int), Inkscape::UI::Widget::ColorWheel&, std::shared_ptr<Cairo::Context> const&, int const&, int const&>(void (Inkscape::UI::Widget::ColorWheel::* const&)(std::shared_ptr<Cairo::Context> const&, int, int), Inkscape::UI::Widget::ColorWheel&, std::shared_ptr<Cairo::Context> const&, int const&, int const&) /usr/include/c++/13.2.1/bits/invoke.h:96
    #17 0x7c5508498000 in std::invoke_result<void (Inkscape::UI::Widget::ColorWheel::* const&)(std::shared_ptr<Cairo::Context> const&, int, int), Inkscape::UI::Widget::ColorWheel&, std::shared_ptr<Cairo::Context> const&, int const&, int const&>::type std::invoke<void (Inkscape::UI::Widget::ColorWheel::* const&)(std::shared_ptr<Cairo::Context> const&, int, int), Inkscape::UI::Widget::ColorWheel&, std::shared_ptr<Cairo::Context> const&, int const&, int const&>(void (Inkscape::UI::Widget::ColorWheel::* const&)(std::shared_ptr<Cairo::Context> const&, int, int), Inkscape::UI::Widget::ColorWheel&, std::shared_ptr<Cairo::Context> const&, int const&, int const&) /usr/include/c++/13.2.1/functional:113
    #18 0x7c5508498000 in sigc::bound_mem_functor<void (Inkscape::UI::Widget::ColorWheel::*)(std::shared_ptr<Cairo::Context> const&, int, int), std::shared_ptr<Cairo::Context> const&, int, int>::operator()(std::shared_ptr<Cairo::Context> const&, int const&, int const&) const /usr/include/sigc++-3.0/sigc++/functors/mem_fun.h:151
    #19 0x7c5508498000 in void std::__invoke_impl<void, sigc::bound_mem_functor<void (Inkscape::UI::Widget::ColorWheel::*)(std::shared_ptr<Cairo::Context> const&, int, int), std::shared_ptr<Cairo::Context> const&, int, int>&, std::shared_ptr<Cairo::Context> const&, int const&, int const&>(std::__invoke_other, sigc::bound_mem_functor<void (Inkscape::UI::Widget::ColorWheel::*)(std::shared_ptr<Cairo::Context> const&, int, int), std::shared_ptr<Cairo::Context> const&, int, int>&, std::shared_ptr<Cairo::Context> const&, int const&, int const&) /usr/include/c++/13.2.1/bits/invoke.h:61
    #20 0x7c5508498000 in std::__invoke_result<sigc::bound_mem_functor<void (Inkscape::UI::Widget::ColorWheel::*)(std::shared_ptr<Cairo::Context> const&, int, int), std::shared_ptr<Cairo::Context> const&, int, int>&, std::shared_ptr<Cairo::Context> const&, int const&, int const&>::type std::__invoke<sigc::bound_mem_functor<void (Inkscape::UI::Widget::ColorWheel::*)(std::shared_ptr<Cairo::Context> const&, int, int), std::shared_ptr<Cairo::Context> const&, int, int>&, std::shared_ptr<Cairo::Context> const&, int const&, int const&>(sigc::bound_mem_functor<void (Inkscape::UI::Widget::ColorWheel::*)(std::shared_ptr<Cairo::Context> const&, int, int), std::shared_ptr<Cairo::Context> const&, int, int>&, std::shared_ptr<Cairo::Context> const&, int const&, int const&) /usr/include/c++/13.2.1/bits/invoke.h:96
    #21 0x7c5508498000 in std::invoke_result<sigc::bound_mem_functor<void (Inkscape::UI::Widget::ColorWheel::*)(std::shared_ptr<Cairo::Context> const&, int, int), std::shared_ptr<Cairo::Context> const&, int, int>&, std::shared_ptr<Cairo::Context> const&, int const&, int const&>::type std::invoke<sigc::bound_mem_functor<void (Inkscape::UI::Widget::ColorWheel::*)(std::shared_ptr<Cairo::Context> const&, int, int), std::shared_ptr<Cairo::Context> const&, int, int>&, std::shared_ptr<Cairo::Context> const&, int const&, int const&>(sigc::bound_mem_functor<void (Inkscape::UI::Widget::ColorWheel::*)(std::shared_ptr<Cairo::Context> const&, int, int), std::shared_ptr<Cairo::Context> const&, int, int>&, std::shared_ptr<Cairo::Context> const&, int const&, int const&) /usr/include/c++/13.2.1/functional:113
    #22 0x7c5508498000 in decltype(auto) sigc::adaptor_functor<sigc::bound_mem_functor<void (Inkscape::UI::Widget::ColorWheel::*)(std::shared_ptr<Cairo::Context> const&, int, int), std::shared_ptr<Cairo::Context> const&, int, int> >::operator()<std::shared_ptr<Cairo::Context> const&, int const&, int const&>(std::shared_ptr<Cairo::Context> const&, int const&, int const&) const /usr/include/sigc++-3.0/sigc++/adaptors/adaptor_trait.h:100
    #23 0x7c5508498000 in sigc::internal::slot_call<sigc::bound_mem_functor<void (Inkscape::UI::Widget::ColorWheel::*)(std::shared_ptr<Cairo::Context> const&, int, int), std::shared_ptr<Cairo::Context> const&, int, int>, void, std::shared_ptr<Cairo::Context> const&, int, int>::call_it(sigc::internal::slot_rep*, std::shared_ptr<Cairo::Context> const&, int const&, int const&) /usr/include/sigc++-3.0/sigc++/functors/slot.h:154
(...)
Edited by Rafał Siejakowski

Merge request reports