Description: crash of "Error: attempt to increment a singular iterator." Steps to Reproduce: 1. with a dbgutil linux build 2. ./instdir/program/soffice --headless --convert-to pdf ~/Downloads/moz766916-1.odg Actual Results: backtrace of: #3 0x00007ffff74a7493 in std::__throw_bad_exception() () at /lib64/libstdc++.so.6 #4 0x00007fffe96eadbe in __gnu_debug::_Safe_iterator<std::__cxx1998::_Deque_iterator<rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D>, rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> const&, rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> const*>, std::__debug::deque<rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D>, std::allocator<rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> > >, std::forward_iterator_tag>::operator++() (this=0x7ffffffef028) at /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13/debug/safe_iterator.h:326 #5 0x00007fffe96eacf9 in __gnu_debug::_Safe_iterator<std::__cxx1998::_Deque_iterator<rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D>, rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> const&, rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> const*>, std::__debug::deque<rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D>, std::allocator<rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> > >, std::bidirectional_iterator_tag>::operator++() (this=0x7ffffffef028) at /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13/debug/safe_iterator.h:594 #6 0x00007fffe96ea479 in __gnu_debug::_Safe_iterator<std::__cxx1998::_Deque_iterator<rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D>, rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> const&, rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> const*>, std::__debug::deque<rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D>, std::allocator<rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> > >, std::random_access_iterator_tag>::operator++() (this=0x7ffffffef028) at /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13/debug/safe_iterator.h:748 #7 0x00007fffe9780eae in drawinglayer::processor2d::BaseProcessor2D::process(drawinglayer::primitive2d::Primitive2DContainer const&) (this=0x5f8e040, rSource=...) at /home/caolan/LibreOffice/core/drawinglayer/source/processor2d/baseprocessor2d.cxx:65 #8 0x00007fffe97ba3bc in drawinglayer::processor2d::VclProcessor2D::RenderTransformPrimitive2D(drawinglayer::primitive2d::TransformPrimitive2D const&) (this=0x5f8e040, rTransformCandidate=...) at /home/caolan/LibreOffice/core/drawinglayer/source/processor2d/vclprocessor2d.cxx:1003 #9 0x00007fffe979abca in drawinglayer::processor2d::VclMetafileProcessor2D::processBasePrimitive2D(drawinglayer::primitive2d::BasePrimitive2D const&) (this=0x5f8e040, rCandidate=...) at /home/caolan/LibreOffice/core/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx:862 #10 0x00007fffe9780e6a in drawinglayer::processor2d::BaseProcessor2D::process(drawinglayer::primitive2d::Primitive2DContainer const&) (this=0x5f8e040, rSource=...) at /home/caolan/LibreOffice/core/drawinglayer/source/processor2d/baseprocessor2d.cxx:68 #11 0x00007fffe9780d4d in drawinglayer::processor2d::BaseProcessor2D::visit(drawinglayer::primitive2d::Primitive2DContainer const&) (this=0x5f8e040, rContainer=...) at /home/caolan/LibreOffice/core/drawinglayer/source/processor2d/baseprocessor2d.cxx:56 #12 0x00007ffff466a4a6 in drawinglayer::primitive2d::BufferedDecompositionPrimitive2D::get2DDecomposition(drawinglayer::primitive2d::Primitive2DDecompositionVisitor&, drawinglayer::geometry::ViewInformation2D const&) const (this=0x5ee0660, rVisitor=..., rViewInformation=...) at /home/caolan/LibreOffice/core/drawinglayer/source/primitive2d/BufferedDecompositionPrimitive2D.cxx:124 #13 0x00007fffe9780ce6 in drawinglayer::processor2d::BaseProcessor2D::process(drawinglayer::primitive2d::BasePrimitive2D const&) (this=0x5f8e040, rCandidate=...) at /home/caolan/LibreOffice/core/drawinglayer/source/processor2d/baseprocessor2d.cxx:46 #14 0x00007fffe979adfb in drawinglayer::processor2d::VclMetafileProcessor2D::processGraphicPrimitive2D(drawinglayer::primitive2d::GraphicPrimitive2D const&) (this=0x5f8e040, rGraphicPrimitive=...) at /home/caolan/LibreOffice/core/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx:1006 #15 0x00007fffe979aa3a in drawinglayer::processor2d::VclMetafileProcessor2D::processBasePrimitive2D(drawinglayer::primitive2d::BasePrimitive2D const&) (this=0x5f8e040, rCandidate=...) at /home/caolan/LibreOffice/core/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx:727 #16 0x00007fffe9780e6a in drawinglayer::processor2d::BaseProcessor2D::process(drawinglayer::primitive2d::Primitive2DContainer const&) (this=0x5f8e040, rSource=...) at /home/caolan/LibreOffice/core/drawinglayer/source/processor2d/baseprocessor2d.cxx:68 #17 0x00007fffe9780d4d in drawinglayer::processor2d::BaseProcessor2D::visit(drawinglayer::primitive2d::Primitive2DContainer const&) (this=0x5f8e040, rContainer=...) at /home/caolan/LibreOffice/core/drawinglayer/source/processor2d/baseprocessor2d.cxx:56 #18 0x00007ffff466a4a6 in drawinglayer::primitive2d::BufferedDecompositionPrimitive2D::get2DDecomposition(drawinglayer::primitive2d::Primitive2DDecompositionVisitor&, drawinglayer::geometry::ViewInformation2D const&) const (this=0x5edd2b0, rVisitor=..., rViewInformation=...) at /home/caolan/LibreOffice/core/drawinglayer/source/primitive2d/BufferedDecompositionPrimitive2D.cxx:124 #19 0x00007fffe9780ce6 in drawinglayer::processor2d::BaseProcessor2D::process(drawinglayer::primitive2d::BasePrimitive2D const&) (this=0x5f8e040, rCandidate=...) at /home/caolan/LibreOffice/core/drawinglayer/source/processor2d/baseprocessor2d.cxx:46 #20 0x00007fffe979ac62 in drawinglayer::processor2d::VclMetafileProcessor2D::processBasePrimitive2D(drawinglayer::primitive2d::BasePrimitive2D const&) (this=0x5f8e040, rCandidate=...) at /home/caolan/LibreOffice/core/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx:921 #21 0x00007fffe9780e6a in drawinglayer::processor2d::BaseProcessor2D::process(drawinglayer::primitive2d::Primitive2DContainer const&) (this=0x5f8e040, rSource=...) at /home/caolan/LibreOffice/core/drawinglayer/source/processor2d/baseprocessor2d.cxx:68 #22 0x00007fffe97a51d1 in drawinglayer::processor2d::VclMetafileProcessor2D::processStructureTagPrimitive2D(drawinglayer::primitive2d::StructureTagPrimitive2D const&) (this=0x5f8e040, rStructureTagCandidate=...) at /home/caolan/LibreOffice/core/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx:2637 #23 0x00007fffe979ac12 in drawinglayer::processor2d::VclMetafileProcessor2D::processBasePrimitive2D(drawinglayer::primitive2d::BasePrimitive2D const&) (this=0x5f8e040, rCandidate=...) at /home/caolan/LibreOffice/core/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx:889 #24 0x00007fffe9780e6a in drawinglayer::processor2d::BaseProcessor2D::process(drawinglayer::primitive2d::Primitive2DContainer const&) (this=0x5f8e040, rSource=...) at /home/caolan/LibreOffice/core/drawinglayer/source/processor2d/baseprocessor2d.cxx:68 #25 0x00007ffff12b13f6 in sdr::contact::ObjectContactOfPageView::DoProcessDisplay(sdr::contact::DisplayInfo&) (this=0x5f2ded0, rDisplayInfo=...) at /home/caolan/LibreOffice/core/svx/source/sdr/contact/objectcontactofpageview.cxx:278 #26 0x00007ffff12b0da2 in sdr::contact::ObjectContactOfPageView::ProcessDisplay(sdr::contact::DisplayInfo&) (this=0x5f2ded0, rDisplayInfo=...) at /home/caolan/LibreOffice/core/svx/source/sdr/contact/objectcontactofpageview.cxx:118 #27 0x00007ffff1348322 in SdrPageWindow::RedrawAll(sdr::contact::ViewObjectContactRedirector*) (this=0x5f87820, pRedirector=0x7fffffff0ab0) at /home/caolan/LibreOffice/core/svx/source/svdraw/sdrpagewindow.cxx:352 #28 0x00007ffff160cef8 in SdrPageView::CompleteRedraw(SdrPaintWindow&, vcl::Region const&, sdr::contact::ViewObjectContactRedirector*) (this=0x5f35ff0, rPaintWindow=..., rReg=..., pRedirector=0x7fffffff0ab0) at /home/caolan/LibreOffice/core/svx/source/svdraw/svdpagv.cxx:239 #29 0x00007ffff162677d in SdrPaintView::DoCompleteRedraw(SdrPaintWindow&, vcl::Region const&, sdr::contact::ViewObjectContactRedirector*) (this=0x7fffffff0b90, rPaintWindow=..., rReg=..., pRedirector=0x7fffffff0ab0) at /home/caolan/LibreOffice/core/svx/source/svdraw/svdpntv.cxx:612 #30 0x00007ffff162668f in SdrPaintView::CompleteRedraw(OutputDevice*, vcl::Region const&, sdr::contact::ViewObjectContactRedirector*) (this=0x7fffffff0b90, pOut=0x5f78260, rReg=..., pRedirector=0x7fffffff0ab0) at /home/caolan/LibreOffice/core/svx/source/svdraw/svdpntv.cxx:525 #31 0x00007fffd550af40 in SdXImpressDocument::render(int, com::sun::star::uno::Any const&, com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) (this=0x1c45d10, nRenderer=0, rSelection=uno::Any("com.sun.star.lang.XComponent": ...), rxOptions=uno::Sequence of length 9 = {...}) at /home/caolan/LibreOffice/core/sd/source/ui/unoidl/unomodel.cxx:2134 Expected Results: no crash Reproducible: Always User Profile Reset: No Additional Info: bisected to: commit 0d512011a695da8dafe9467ec0ff7f564dfe8c88 Date: Mon Dec 18 18:23:37 2023 +0100 Add flush mechanism to buffered Primitives and still seen after: commit 71c555c5ae31d84dff8d9448fd2be4dab23f20a8 Date: Thu Dec 21 15:02:52 2023 +0100 Add flush mechanism to buffered Primitives II with build of 10e7d8d1dcf0e3a45044643ab7b572af997543e9
Created attachment 191618 [details] reproducer
Struggles but manages to convert with debug build from before the bisected commit: Version: 24.8.0.0.alpha0+ (X86_64) / LibreOffice Community Build ID: fdc87dd56548622e13353b4cf9864232ee0110fb CPU threads: 8; OS: Linux 5.15; UI render: default; VCL: gtk3 Locale: en-AU (en_AU.UTF-8); UI: en-US Calc: threaded Reproduced with recent debug build: Version: 24.8.0.0.alpha0+ (X86_64) / LibreOffice Community Build ID: 29097009b1f8c0dcb050367d3f2acfcaf2074a56 CPU threads: 8; OS: Linux 5.15; UI render: default; VCL: gtk3 Locale: en-AU (en_AU.UTF-8); UI: en-US Calc: threaded In console: /opt/rh/gcc-toolset-12/root/usr/include/c++/12/debug/safe_iterator.h:332: In function: gnu_debug::_Safe_iterator<_Iterator, _Sequence, _Category>& gnu_debug::_Safe_iterator<_Iterator, _Sequence, _Category>::operator++() [with _Iterator = std:: _Deque_iterator<rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D>, const rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D>&, const rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D>*>; _Sequence = std:: debug::deque<rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> >; _Category = std::forward_iterator_tag] Error: attempt to increment a singular iterator. Objects involved in the operation: iterator "this" @ 0x7ffe594ee120 { type = std::_Deque_iterator<rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D>, rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> const&, rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> const*> (constant iterator); state = singular; } Unspecified Application Error No repro in non-debug build: Version: 24.8.0.0.alpha0+ (X86_64) / LibreOffice Community Build ID: 40617d867346956588ac023511f31210107217f4 CPU threads: 8; OS: Linux 5.15; UI render: default; VCL: gtk3 Locale: en-AU (en_AU.UTF-8); UI: en-US Calc: threaded
Happens as described. Also quickly found the problem - the Primitive is deleted while being in use. The original concept designing the Primitives was to have read-only, small, unchangeable objects. This is undermined by the 'visitor' concept - the instance owning the Primitive decomposition/representation 'directly' uses that representation, while at the same time that instance is allowed to re-create (and thus also delete) that instance. This can/could not happen without the visitor concept before: The instances were fetched and held safe ref-counted (that's why Primitives can be held by uno::Reference). I see the (small) advantage here by using that visitor concept, but: - less ref-counting (guessed initial reason for visitor concept?) is easily possible by packing decompositions in single references by themselves (Group/transformPrimitive with neutral transformation), so no need to achieve that advantage by 'visitor' concept and pay the security price for it - potentially more usage of multi-threading with Primitives, esp. for expensive decomposition ceations combined with timing stuff So - for the future - I would really prefer safety/ref-counting over small advantages (other achievable, see above) here. For now I will probably just make that safe using a std::mutex to ensure that the local decomposition gets *not* changed while being 'visited' - with the known possible costs for multi-threading. Of course only when really needed, to minimize possible impact(s)...
Added https://gerrit.libreoffice.org/c/core/+/161543 to gerrit, works locally and should do it.
Armin Le Grand (allotropia) committed a patch related to this issue. It has been pushed to "master": https://git.libreoffice.org/core/commit/e1402abc5c6d08ae541ca6ef31b017034232d4cf tdf#158913 secure Primitive 'visit' using mutex It will be available in 24.8.0. The patch should be included in the daily builds available at https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More information about daily builds can be found at: https://wiki.documentfoundation.org/Testing_Daily_Builds Affected users are encouraged to test the fix and report feedback.