vcl/source/gdi/sallayout.cxx |   22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

New commits:
commit 51244ebe62bb25f7d87ab1332e863720d980db66
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Tue Apr 2 08:55:51 2024 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Tue Apr 2 07:34:32 2024 +0200

    Fix UB after 8962141a12c966b2d891829925e6203bf8d51852
    
    (tdf#160430: Fix glyph bounds calculation, and use basegfx::B2DRectangle, 
2024-04-01).
    As reported by Stephan in 
https://gerrit.libreoffice.org/c/core/+/165553/6#message-fec1e45288c0e87d43c58f777ebe51b03c534d82:
    
     `CppunitTest_sw_rtfexport CPPUNIT_TEST_NAME=testMathEqarray::TestBody` now 
fails with
    
      vcl/source/gdi/sallayout.cxx:245:30: runtime error: inf is outside the 
range of representable values of type 'long'
       #0 in SalLayout::GetBoundRect(tools::Rectangle&) const at 
vcl/source/gdi/sallayout.cxx:245:30
       #1 in OutputDevice::GetTextBoundRect(tools::Rectangle&, rtl::OUString 
const&, int, int, int, unsigned long, KernArraySpan, std::span<unsigned char 
const, 18446744073709551615ul>, SalLayoutGlyphs const*) const at 
vcl/source/outdev/text.cxx:1932:28
       #2 in (anonymous namespace)::SmGetGlyphBoundRect(OutputDevice const&, 
rtl::OUString const&, tools::Rectangle&) at starmath/source/rect.cxx:80:32
       #3 in SmRect::SmRect(OutputDevice const&, SmFormat const*, rtl::OUString 
const&, unsigned short) at starmath/source/rect.cxx:224:21
       #4 in SmMathSymbolNode::AdaptToY(OutputDevice&, unsigned long) at 
starmath/source/node.cxx:2122:18
       #5 in SmBraceNode::Arrange(OutputDevice&, SmFormat const&) at 
starmath/source/node.cxx:1340:17
       #6 in SmBinHorNode::Arrange(OutputDevice&, SmFormat const&) at 
starmath/source/node.cxx:816:13
       #7 in SmLineNode::Arrange(OutputDevice&, SmFormat const&) at 
starmath/source/node.cxx:610:20
       #8 in SmTableNode::Arrange(OutputDevice&, SmFormat const&) at 
starmath/source/node.cxx:534:20
       #9 in SmDocShell::ArrangeFormula() at starmath/source/document.cxx:280:13
       #10 in SmDocShell::GetSize() at starmath/source/document.cxx:405:9
       #11 in SmDocShell::Repaint() at starmath/source/document.cxx:566:21
       #12 in SmDocShell::OnDocumentPrinterChanged(Printer*) at 
starmath/source/document.cxx:552:5
       #13 in SmDocShell::SetText(rtl::OUString const&) at 
starmath/source/document.cxx:188:9
       #14 in SmDocShell::readFormulaOoxml(oox::formulaimport::XmlStream&) at 
starmath/source/document.cxx:848:5
       #15 in SmModel::readFormulaOoxml(oox::formulaimport::XmlStream&) at 
starmath/source/unomodel.cxx:1105:22
       #16 in 
writerfilter::rtftok::RTFDocumentImpl::beforePopState(writerfilter::rtftok::RTFParserState&)
 at writerfilter/source/rtftok/rtfdocumentimpl.cxx:3010:30
       #17 in writerfilter::rtftok::RTFDocumentImpl::popState() at 
writerfilter/source/rtftok/rtfdocumentimpl.cxx:3666:23
       #18 in writerfilter::rtftok::RTFTokenizer::resolveParse() at 
writerfilter/source/rtftok/rtftokenizer.cxx:114:37
       #19 in 
writerfilter::rtftok::RTFDocumentImpl::resolve(writerfilter::Stream&) at 
writerfilter/source/rtftok/rtfdocumentimpl.cxx:856:27
       #20 in (anonymous 
namespace)::RtfFilter::filter(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>
 const&) at writerfilter/source/filter/RtfFilter.cxx:163:20
       #21 in SfxObjectShell::ImportFrom(SfxMedium&, 
com::sun::star::uno::Reference<com::sun::star::text::XTextRange> const&) at 
sfx2/source/doc/objstor.cxx:2392:34
       #22 in SfxObjectShell::DoLoad(SfxMedium*) at 
sfx2/source/doc/objstor.cxx:760:23
       #23 in 
SfxBaseModel::load(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>
 const&) at sfx2/source/doc/sfxbasemodel.cxx:1980:36
       #24 in (anonymous 
namespace)::SfxFrameLoader_Impl::load(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>
 const&, com::sun::star::uno::Reference<com::sun::star::frame::XFrame> const&) 
at sfx2/source/view/frmload.cxx:720:28
       #25 in framework::LoadEnv::impl_loadContent() at 
framework/source/loadenv/loadenv.cxx:1176:37
       #26 in framework::LoadEnv::start() at 
framework/source/loadenv/loadenv.cxx:412:20
       #27 in framework::LoadEnv::startLoading(rtl::OUString const&, 
com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&, 
com::sun::star::uno::Reference<com::sun::star::frame::XFrame> const&, 
rtl::OUString const&, int, LoadEnvFeatures) at 
framework/source/loadenv/loadenv.cxx:308:5
       #28 in 
framework::LoadEnv::loadComponentFromURL(com::sun::star::uno::Reference<com::sun::star::frame::XComponentLoader>
 const&, com::sun::star::uno::Reference<com::sun::star::uno::XComponentContext> 
const&, rtl::OUString const&, rtl::OUString const&, int, 
com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) at 
framework/source/loadenv/loadenv.cxx:168:14
       #29 in framework::Desktop::loadComponentFromURL(rtl::OUString const&, 
rtl::OUString const&, int, 
com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) at 
framework/source/services/desktop.cxx:591:16
       #30 in non-virtual thunk to 
framework::Desktop::loadComponentFromURL(rtl::OUString const&, rtl::OUString 
const&, int, 
com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) at 
framework/source/services/desktop.cxx
       #31 in unotest::MacrosTest::loadFromDesktop(rtl::OUString const&, 
rtl::OUString const&, 
com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) at 
unotest/source/cpp/macros_test.cxx:71:62
       #32 in UnoApiTest::loadWithParams(rtl::OUString const&, 
com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) at 
test/source/unoapi_test.cxx:126:19
       #33 in UnoApiTest::load(rtl::OUString const&, char const*) at 
test/source/unoapi_test.cxx:108:5
       #34 in SwModelTestBase::loadURL(rtl::OUString const&, char const*) at 
sw/qa/unit/swmodeltestbase.cxx:441:20
       #35 in SwModelTestBase::loadAndReload(char const*) at 
sw/qa/unit/swmodeltestbase.cxx:466:5
       #36 in (anonymous namespace)::testMathEqarray::TestBody() at 
sw/qa/extras/rtfexport/rtfexport.cxx:198:5
    
    Change-Id: I857861f5bc51a1e43bfbf5e0c9dbce542d673ca7
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165664
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx
index d1a29de327ff..3240e481578f 100644
--- a/vcl/source/gdi/sallayout.cxx
+++ b/vcl/source/gdi/sallayout.cxx
@@ -215,7 +215,10 @@ bool SalLayout::GetOutline(basegfx::B2DPolyPolygonVector& 
rVector) const
 }
 
 // No need to expand to the next pixel, when the character only covers its 
tiny fraction
-static double trimInsignificant(double n) { return std::round(n * 1e5) / 1e5; }
+static double trimInsignificant(double n)
+{
+    return std::abs(n) >= 0x1p53 ? n : std::round(n * 1e5) / 1e5;
+}
 
 bool SalLayout::GetBoundRect(tools::Rectangle& rRect) const
 {
@@ -242,10 +245,19 @@ bool SalLayout::GetBoundRect(tools::Rectangle& rRect) 
const
             bRet = true;
         }
     }
-    rRect = 
tools::Rectangle(rtl::math::approxFloor(trimInsignificant(aUnion.getMinX())),
-                             
rtl::math::approxFloor(trimInsignificant(aUnion.getMinY())),
-                             
rtl::math::approxCeil(trimInsignificant(aUnion.getMaxX())),
-                             
rtl::math::approxCeil(trimInsignificant(aUnion.getMaxY())));
+    if (aUnion.isEmpty())
+    {
+        rRect = {};
+    }
+    else
+    {
+        double l = rtl::math::approxFloor(trimInsignificant(aUnion.getMinX())),
+               t = rtl::math::approxFloor(trimInsignificant(aUnion.getMinY())),
+               r = rtl::math::approxCeil(trimInsignificant(aUnion.getMaxX())),
+               b = rtl::math::approxCeil(trimInsignificant(aUnion.getMaxY()));
+        assert(std::isfinite(l) && std::isfinite(t) && std::isfinite(r) && 
std::isfinite(b));
+        rRect = tools::Rectangle(l, t, r, b);
+    }
 
     return bRet;
 }

Reply via email to