filter/source/msfilter/eschesdo.cxx | 2 include/svx/svdsob.hxx | 12 +++-- include/svx/svdtypes.hxx | 4 - reportdesign/source/core/api/ReportDefinition.cxx | 6 +- sc/qa/extras/macros-test.cxx | 48 +++++++++++++++++++++ sc/qa/unit/scshapetest.cxx | 12 ++--- sc/source/core/data/drwlayer.cxx | 10 ++-- sc/source/filter/xml/XMLTableShapeImportHelper.cxx | 2 sc/source/filter/xml/xmlwrap.cxx | 10 ++-- sc/source/ui/Accessibility/AccessibleDocument.cxx | 8 +-- svx/inc/sxlayitm.hxx | 6 +- svx/source/uitest/sdrobject.cxx | 2 svx/source/unodraw/unoshape.cxx | 2 sw/source/uibase/shells/drwbassh.cxx | 2 14 files changed, 90 insertions(+), 36 deletions(-)
New commits: commit f4a62e5479b47d90d6de518f38a97ac0b5322c54 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Tue Sep 7 12:16:24 2021 +0200 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Wed Feb 23 16:00:28 2022 +0100 SdrLayerID must be based on sal_Int16 ... which is the type corresponding to the related published property "LayerID" of com.sun.star.drawing.Shape service. Without this, the code asserts on values passed to the published API from external sources to be in the 8-bit limits, which is incorrect. Change-Id: I0449a7dd313f7e6c4adbc1c1f7b8c50b6a51434e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/121760 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/filter/source/msfilter/eschesdo.cxx b/filter/source/msfilter/eschesdo.cxx index 12e6e62be0a2..d052b5968780 100644 --- a/filter/source/msfilter/eschesdo.cxx +++ b/filter/source/msfilter/eschesdo.cxx @@ -669,7 +669,7 @@ sal_uInt32 ImplEESdrWriter::ImplWriteShape( ImplEESdrObject& rObj, if( SDRLAYER_NOTFOUND != mpEscherEx->GetHellLayerId() && rObj.ImplGetPropertyValue( "LayerID" ) && - *o3tl::doAccess<sal_uInt16>(rObj.GetUsrAny()) == sal_uInt8(mpEscherEx->GetHellLayerId()) ) + *o3tl::doAccess<sal_Int16>(rObj.GetUsrAny()) == mpEscherEx->GetHellLayerId().get() ) { aPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x200020 ); } diff --git a/include/svx/svdsob.hxx b/include/svx/svdsob.hxx index 2d17ab05640a..7e2b8578e01d 100644 --- a/include/svx/svdsob.hxx +++ b/include/svx/svdsob.hxx @@ -30,6 +30,7 @@ class SVXCORE_DLLPUBLIC SdrLayerIDSet final { + // For now, have up to 256 layers sal_uInt8 aData[32]; public: @@ -45,12 +46,16 @@ public: void Set(SdrLayerID a) { - aData[sal_uInt8(a)/8] |= 1 << (sal_uInt8(a) % 8); + const sal_Int16 nId = a.get(); + if (nId >= 0 && nId < 256) + aData[nId / 8] |= 1 << (nId % 8); } void Clear(SdrLayerID a) { - aData[sal_uInt8(a)/8] &= ~(1 << (sal_uInt8(a) % 8)); + const sal_Int16 nId = a.get(); + if (nId >= 0 && nId < 256) + aData[nId / 8] &= ~(1 << (nId % 8)); } void Set(SdrLayerID a, bool b) @@ -63,7 +68,8 @@ public: bool IsSet(SdrLayerID a) const { - return (aData[sal_uInt8(a)/8] & 1<<sal_uInt8(a)%8) != 0; + const sal_Int16 nId = a.get(); + return nId >= 0 && nId < 256 && (aData[nId / 8] & 1 << nId % 8) != 0; } void SetAll() diff --git a/include/svx/svdtypes.hxx b/include/svx/svdtypes.hxx index 5b73552a5719..1009b0314923 100644 --- a/include/svx/svdtypes.hxx +++ b/include/svx/svdtypes.hxx @@ -53,11 +53,11 @@ enum class SdrDragMode // You can use this value in the methods of SdrLayerSet, but false is returned // every time or the method does nothing. // type declaration for Layer-IDs -typedef o3tl::strong_int<sal_uInt8, struct SdrLayerIDTag> SdrLayerID; +typedef o3tl::strong_int<sal_Int16, struct SdrLayerIDTag> SdrLayerID; // If there is no layer when it should be identified, then // SdrLayerAdmin::GetLayerID(const String&) returns a value. -constexpr SdrLayerID SDRLAYER_NOTFOUND(0xff); +constexpr SdrLayerID SDRLAYER_NOTFOUND(-1); /* * Repeat diff --git a/reportdesign/source/core/api/ReportDefinition.cxx b/reportdesign/source/core/api/ReportDefinition.cxx index 636346a163c3..9954b50c359e 100644 --- a/reportdesign/source/core/api/ReportDefinition.cxx +++ b/reportdesign/source/core/api/ReportDefinition.cxx @@ -588,9 +588,9 @@ void OReportDefinition::init() m_pImpl->m_pReportModel->GetItemPool().FreezeIdRanges(); m_pImpl->m_pReportModel->SetScaleUnit( MapUnit::Map100thMM ); SdrLayerAdmin& rAdmin = m_pImpl->m_pReportModel->GetLayerAdmin(); - rAdmin.NewLayer("front", sal_uInt8(RPT_LAYER_FRONT)); - rAdmin.NewLayer("back", sal_uInt8(RPT_LAYER_BACK)); - rAdmin.NewLayer("HiddenLayer", sal_uInt8(RPT_LAYER_HIDDEN)); + rAdmin.NewLayer("front", RPT_LAYER_FRONT.get()); + rAdmin.NewLayer("back", RPT_LAYER_BACK.get()); + rAdmin.NewLayer("HiddenLayer", RPT_LAYER_HIDDEN.get()); m_pImpl->m_pUndoManager = new ::dbaui::UndoManager( *this, m_aMutex ); m_pImpl->m_pReportModel->SetSdrUndoManager( &m_pImpl->m_pUndoManager->GetSfxUndoManager() ); diff --git a/sc/qa/extras/macros-test.cxx b/sc/qa/extras/macros-test.cxx index 6c41b269111e..cc77943ab879 100644 --- a/sc/qa/extras/macros-test.cxx +++ b/sc/qa/extras/macros-test.cxx @@ -64,6 +64,7 @@ public: void testTdf130307(); void testTdf146742(); void testMacroButtonFormControlXlsxExport(); + void testShapeLayerId(); CPPUNIT_TEST_SUITE(ScMacrosTest); CPPUNIT_TEST(testStarBasic); @@ -92,6 +93,7 @@ public: CPPUNIT_TEST(testTdf130307); CPPUNIT_TEST(testTdf146742); CPPUNIT_TEST(testMacroButtonFormControlXlsxExport); + CPPUNIT_TEST(testShapeLayerId); CPPUNIT_TEST_SUITE_END(); }; @@ -999,6 +1001,52 @@ void ScMacrosTest::testTdf105558() xCloseable->close(true); } +void ScMacrosTest::testShapeLayerId() +{ + auto xComponent = loadFromDesktop("private:factory/scalc"); + + // insert initial library + css::uno::Reference<css::document::XEmbeddedScripts> xDocScr(xComponent, UNO_QUERY_THROW); + auto xLibs = xDocScr->getBasicLibraries(); + auto xLibrary = xLibs->createLibrary("TestLibrary"); + xLibrary->insertByName( + "TestModule", + uno::Any( + OUString("Function TestLayerID\n" + " xShape = thisComponent.createInstance(\"com.sun.star.drawing.TextShape\")\n" + " thisComponent.DrawPages(0).Add(xShape)\n" + " origID = xShape.LayerID\n" + " On Error Goto handler\n" + " xShape.LayerID = 257 ' 1 if wrongly converted to unsigned 8-bit type\n" + " TestLayerID = origID & \" \" & xShape.LayerID ' Should not happen\n" + " Exit Function\n" + "handler:\n" + " ' This is expected to happen\n" + " TestLayerID = origID & \" Expected runtime error happened\"\n" + "End Function\n"))); + + Any aRet; + Sequence<sal_Int16> aOutParamIndex; + Sequence<Any> aOutParam; + + SfxObjectShell* pFoundShell = SfxObjectShell::GetShellFromComponent(xComponent); + ScDocShell* pDocSh = static_cast<ScDocShell*>(pFoundShell); + CPPUNIT_ASSERT(pDocSh); + + SfxObjectShell::CallXScript( + xComponent, + "vnd.sun.Star.script:TestLibrary.TestModule.TestLayerID?language=Basic&location=document", + {}, aRet, aOutParamIndex, aOutParam); + // Without the fix in place, this test would have failed in non-debug builds with + // - Expected : <Any: (string) 0 Expected runtime error happened> + // - Actual : <Any: (string) 0 1> + // In debug builds, it would crash on assertion inside strong_int ctor. + // The LayerID property of com.sun.star.drawing.Shape service has 'short' IDL type. + // The expected run-time error is because there are only 5 layers there. + CPPUNIT_ASSERT_EQUAL(Any(OUString("0 Expected runtime error happened")), aRet); + pDocSh->DoClose(); +} + ScMacrosTest::ScMacrosTest() : UnoApiTest("/sc/qa/extras/testdocuments") { diff --git a/sc/qa/unit/scshapetest.cxx b/sc/qa/unit/scshapetest.cxx index 96bbbc3c8912..761db2da687c 100644 --- a/sc/qa/unit/scshapetest.cxx +++ b/sc/qa/unit/scshapetest.cxx @@ -362,8 +362,8 @@ void ScShapeTest::testTdf140252_DragCreateFormControl() SdrUnoObj* pObj = static_cast<SdrUnoObj*>(lcl_getSdrObjectWithAssert(rDoc, 0)); // Without the fix in place, the shape would be on layer SC_LAYER_FRONT (0) - sal_uInt8 nExpectedID = sal_uInt8(SC_LAYER_CONTROLS); - sal_uInt8 nActualID = pObj->GetLayer().get(); + sal_Int16 nExpectedID = SC_LAYER_CONTROLS.get(); + sal_Int16 nActualID = pObj->GetLayer().get(); CPPUNIT_ASSERT_EQUAL(nExpectedID, nActualID); pDocSh->DoClose(); @@ -407,8 +407,8 @@ void ScShapeTest::testTdf134355_DragCreateCustomShape() SdrObjCustomShape* pObj = static_cast<SdrObjCustomShape*>(lcl_getSdrObjectWithAssert(rDoc, 0)); // Without the fix in place, the shape would be on layer SC_LAYER_CONTROLS (3) - sal_uInt8 nExpectedID = sal_uInt8(SC_LAYER_FRONT); - sal_uInt8 nActualID = pObj->GetLayer().get(); + sal_Int16 nExpectedID = SC_LAYER_FRONT.get(); + sal_Int16 nActualID = pObj->GetLayer().get(); CPPUNIT_ASSERT_EQUAL(nExpectedID, nActualID); pDocSh->DoClose(); @@ -441,8 +441,8 @@ void ScShapeTest::testTdf140252_LayerOfControl() SdrObject* pObj = lcl_getSdrObjectWithAssert(rDoc, 0); // Check LayerID of object. Without the fix in place it was 0. - sal_uInt8 nExpectedID = sal_uInt8(SC_LAYER_CONTROLS); - sal_uInt8 nActualID = pObj->GetLayer().get(); + sal_Int16 nExpectedID = SC_LAYER_CONTROLS.get(); + sal_Int16 nActualID = pObj->GetLayer().get(); CPPUNIT_ASSERT_EQUAL(nExpectedID, nActualID); pDocSh->DoClose(); diff --git a/sc/source/core/data/drwlayer.cxx b/sc/source/core/data/drwlayer.cxx index 47985ebeda51..0c1aa0216581 100644 --- a/sc/source/core/data/drwlayer.cxx +++ b/sc/source/core/data/drwlayer.cxx @@ -279,12 +279,12 @@ ScDrawLayer::ScDrawLayer( ScDocument* pDocument, const OUString& rName ) : rPool.FreezeIdRanges(); // the pool is also used directly SdrLayerAdmin& rAdmin = GetLayerAdmin(); - rAdmin.NewLayer("vorne", sal_uInt8(SC_LAYER_FRONT)); - rAdmin.NewLayer("hinten", sal_uInt8(SC_LAYER_BACK)); - rAdmin.NewLayer("intern", sal_uInt8(SC_LAYER_INTERN)); + rAdmin.NewLayer("vorne", SC_LAYER_FRONT.get()); + rAdmin.NewLayer("hinten", SC_LAYER_BACK.get()); + rAdmin.NewLayer("intern", SC_LAYER_INTERN.get()); // tdf#140252 use same name as in ctor of SdrLayerAdmin - rAdmin.NewLayer(rAdmin.GetControlLayerName(), sal_uInt8(SC_LAYER_CONTROLS)); - rAdmin.NewLayer("hidden", sal_uInt8(SC_LAYER_HIDDEN)); + rAdmin.NewLayer(rAdmin.GetControlLayerName(), SC_LAYER_CONTROLS.get()); + rAdmin.NewLayer("hidden", SC_LAYER_HIDDEN.get()); // Set link for URL-Fields ScModule* pScMod = SC_MOD(); diff --git a/sc/source/filter/xml/XMLTableShapeImportHelper.cxx b/sc/source/filter/xml/XMLTableShapeImportHelper.cxx index f4a27c152a5a..ba2382580eba 100644 --- a/sc/source/filter/xml/XMLTableShapeImportHelper.cxx +++ b/sc/source/filter/xml/XMLTableShapeImportHelper.cxx @@ -56,7 +56,7 @@ void XMLTableShapeImportHelper::SetLayer(const uno::Reference<drawing::XShape>& { uno::Reference< beans::XPropertySet > xShapeProp( rShape, uno::UNO_QUERY ); if( xShapeProp.is() ) - xShapeProp->setPropertyValue( SC_LAYERID, uno::makeAny<sal_uInt16>(sal_uInt8(nLayerID)) ); + xShapeProp->setPropertyValue( SC_LAYERID, uno::makeAny(nLayerID.get()) ); } } diff --git a/sc/source/filter/xml/xmlwrap.cxx b/sc/source/filter/xml/xmlwrap.cxx index 1d19f18be4b3..c0aac4c43e9f 100644 --- a/sc/source/filter/xml/xmlwrap.cxx +++ b/sc/source/filter/xml/xmlwrap.cxx @@ -786,15 +786,15 @@ bool ScXMLImportWrapper::Export(bool bStylesOnly) xShape->getPropertyValue("LayerID") >>= nLayerID; switch (nLayerID) { - case sal_uInt8(SC_LAYER_FRONT): + case sal_Int16(SC_LAYER_FRONT): return 1; - case sal_uInt8(SC_LAYER_BACK): + case sal_Int16(SC_LAYER_BACK): return 0; - case sal_uInt8(SC_LAYER_INTERN): + case sal_Int16(SC_LAYER_INTERN): return 2; - case sal_uInt8(SC_LAYER_CONTROLS): + case sal_Int16(SC_LAYER_CONTROLS): return 3; - case sal_uInt8(SC_LAYER_HIDDEN): + case sal_Int16(SC_LAYER_HIDDEN): return 1; // treat as equivalent to front default: O3TL_UNREACHABLE; diff --git a/sc/source/ui/Accessibility/AccessibleDocument.cxx b/sc/source/ui/Accessibility/AccessibleDocument.cxx index c619bc4c44c2..1d58af05fe2a 100644 --- a/sc/source/ui/Accessibility/AccessibleDocument.cxx +++ b/sc/source/ui/Accessibility/AccessibleDocument.cxx @@ -136,19 +136,19 @@ struct ScShapeDataLess static void ConvertLayerId(sal_Int16& rLayerID) // changes the number of the LayerId so it the accessibility order { // note: MSVC 2017 ICE's if this is written as "switch" so use "if" - if (sal_uInt8(SC_LAYER_FRONT) == rLayerID) + if (SC_LAYER_FRONT.get() == rLayerID) { rLayerID = 1; } - else if (sal_uInt8(SC_LAYER_BACK) == rLayerID) + else if (SC_LAYER_BACK.get() == rLayerID) { rLayerID = 0; } - else if (sal_uInt8(SC_LAYER_INTERN) == rLayerID) + else if (SC_LAYER_INTERN.get() == rLayerID) { rLayerID = 2; } - else if (sal_uInt8(SC_LAYER_CONTROLS) == rLayerID) + else if (SC_LAYER_CONTROLS.get() == rLayerID) { rLayerID = 3; } diff --git a/svx/inc/sxlayitm.hxx b/svx/inc/sxlayitm.hxx index a52c47f3d9af..be444bec33dd 100644 --- a/svx/inc/sxlayitm.hxx +++ b/svx/inc/sxlayitm.hxx @@ -24,10 +24,10 @@ #include <svl/intitem.hxx> #include <svx/svdtypes.hxx> -class SdrLayerIdItem final : public SfxUInt16Item { +class SdrLayerIdItem final : public SfxInt16Item { public: - SdrLayerIdItem(SdrLayerID nId): SfxUInt16Item(SDRATTR_LAYERID,sal_uInt8(nId)) {} - SdrLayerID GetValue() const { return SdrLayerID(SfxUInt16Item::GetValue()); } + SdrLayerIdItem(SdrLayerID nId): SfxInt16Item(SDRATTR_LAYERID,nId.get()) {} + SdrLayerID GetValue() const { return SdrLayerID(SfxInt16Item::GetValue()); } virtual SdrLayerIdItem* Clone(SfxItemPool* pPool=nullptr) const override; }; diff --git a/svx/source/uitest/sdrobject.cxx b/svx/source/uitest/sdrobject.cxx index 0d287de2a8a7..bc72ee2a8c93 100644 --- a/svx/source/uitest/sdrobject.cxx +++ b/svx/source/uitest/sdrobject.cxx @@ -28,7 +28,7 @@ StringMap SdrUIObject::get_state() aMap["Description"] = pObject->GetDescription(); aMap["Title"] = pObject->GetTitle(); aMap["Z-Order"] = OUString::number(pObject->GetOrdNum()); - aMap["Layer"] = OUString::number(sal_uInt8(pObject->GetLayer())); + aMap["Layer"] = OUString::number(pObject->GetLayer().get()); aMap["IsGroupObject"] = OUString::boolean(pObject->IsGroupObject()); aMap["IsPolyObject"] = OUString::boolean(pObject->IsPolyObj()); aMap["PointCount"] = OUString::number(pObject->GetPointCount()); diff --git a/svx/source/unodraw/unoshape.cxx b/svx/source/unodraw/unoshape.cxx index 86c2cb74af5f..4591c49c5899 100644 --- a/svx/source/unodraw/unoshape.cxx +++ b/svx/source/unodraw/unoshape.cxx @@ -2778,7 +2778,7 @@ bool SvxShape::getPropertyValueImpl( const OUString&, const SfxItemPropertyMapEn break; } case SDRATTR_LAYERID: - rValue <<= sal_uInt16(sal_uInt8(GetSdrObject()->GetLayer())); + rValue <<= GetSdrObject()->GetLayer().get(); break; case SDRATTR_LAYERNAME: diff --git a/sw/source/uibase/shells/drwbassh.cxx b/sw/source/uibase/shells/drwbassh.cxx index 9aaf727f7155..8cafe328f74a 100644 --- a/sw/source/uibase/shells/drwbassh.cxx +++ b/sw/source/uibase/shells/drwbassh.cxx @@ -136,7 +136,7 @@ void SwDrawBaseShell::Execute(SfxRequest const &rReq) aSet.Put(SfxBoolItem(SID_HTML_MODE, 0 != ::GetHtmlMode(pSh->GetView().GetDocShell()))); - aSet.Put(SfxInt16Item(FN_DRAW_WRAP_DLG, sal_uInt8(pSh->GetLayerId()))); + aSet.Put(SfxInt16Item(FN_DRAW_WRAP_DLG, pSh->GetLayerId().get())); pSh->GetObjAttr(aSet); SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();