Fix a use-after-free in OKLab picker rendering
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