Related: tdf#149325 Eliminate all unconditional ScRangeList::front() access

... to prevent crashes, and where possible substitute a missing
element with the original sheet object range.

Change-Id: I245844e89fa3eb7d6ec07e279bdd23022fd77958
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135773
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
diff --git a/sc/source/ui/vba/vbarange.cxx b/sc/source/ui/vba/vbarange.cxx
index 44e56570..d277d44 100644
--- a/sc/source/ui/vba/vbarange.cxx
+++ b/sc/source/ui/vba/vbarange.cxx
@@ -874,15 +874,18 @@ protected:
                ScCellRangesBase* pUnoRangesBase = dynamic_cast< ScCellRangesBase* >( xIf.get() );
                if ( pUnoRangesBase )
                {
                    ScRangeList aCellRanges = pUnoRangesBase->GetRangeList();
                    ScCompiler aCompiler( m_rDoc, aCellRanges.front().aStart, m_eGrammar );
                    // compile the string in the format passed in
                    std::unique_ptr<ScTokenArray> pArray(aCompiler.CompileString(sFormula));
                    // convert to API grammar
                    aCompiler.SetGrammar( formula::FormulaGrammar::GRAM_API );
                    OUString sConverted;
                    aCompiler.CreateStringFromTokenArray(sConverted);
                    sFormula = EQUALS + sConverted;
                    const ScRangeList& rCellRanges = pUnoRangesBase->GetRangeList();
                    if (!rCellRanges.empty())
                    {
                        ScCompiler aCompiler( m_rDoc, rCellRanges.front().aStart, m_eGrammar );
                        // compile the string in the format passed in
                        std::unique_ptr<ScTokenArray> pArray(aCompiler.CompileString(sFormula));
                        // convert to API grammar
                        aCompiler.SetGrammar( formula::FormulaGrammar::GRAM_API );
                        OUString sConverted;
                        aCompiler.CreateStringFromTokenArray(sConverted);
                        sFormula = EQUALS + sConverted;
                    }
                }
            }

@@ -920,16 +923,19 @@ public:
            {
                OUString sVal;
                aValue >>= sVal;
                ScRangeList aCellRanges = pUnoRangesBase->GetRangeList();
                // Compile string from API grammar.
                ScCompiler aCompiler( m_rDoc, aCellRanges.front().aStart, formula::FormulaGrammar::GRAM_API );
                std::unique_ptr<ScTokenArray> pArray(aCompiler.CompileString(sVal));
                // Convert to desired grammar.
                aCompiler.SetGrammar( m_eGrammar );
                OUString sConverted;
                aCompiler.CreateStringFromTokenArray(sConverted);
                sVal = EQUALS + sConverted;
                aValue <<= sVal;
                const ScRangeList& rCellRanges = pUnoRangesBase->GetRangeList();
                if (!rCellRanges.empty())
                {
                    // Compile string from API grammar.
                    ScCompiler aCompiler( m_rDoc, rCellRanges.front().aStart, formula::FormulaGrammar::GRAM_API );
                    std::unique_ptr<ScTokenArray> pArray(aCompiler.CompileString(sVal));
                    // Convert to desired grammar.
                    aCompiler.SetGrammar( m_eGrammar );
                    OUString sConverted;
                    aCompiler.CreateStringFromTokenArray(sConverted);
                    sVal = EQUALS + sConverted;
                    aValue <<= sVal;
                }
            }
        }

@@ -1923,7 +1929,8 @@ ScVbaRange::Offset( const ::uno::Any &nRowOff, const uno::Any &nColOff )
        return new ScVbaRange( mxParent, mxContext, xRanges );
    }
    // normal range
    uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( pUnoRangesBase->GetDocShell(), aCellRanges.front() ) );
    const ScRange aRange( obtainRangeEvenIfRangeListIsEmpty( aCellRanges));
    uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( pUnoRangesBase->GetDocShell(), aRange));
    return new ScVbaRange( mxParent, mxContext, xRange  );
}

@@ -2374,12 +2381,11 @@ ScVbaRange::Activate()

}

ScRange ScVbaRange::obtainRangeEvenIfRangeListIsEmpty( const ScCellRangesBase* pUnoRangesBase ) const
ScRange ScVbaRange::obtainRangeEvenIfRangeListIsEmpty( const ScRangeList& rCellRanges ) const
{
    // XXX It may be that using the current range list was never correct, but
    // always the initial sheet range would be instead, history is unclear.

    const ScRangeList& rCellRanges = pUnoRangesBase->GetRangeList();
    if (!rCellRanges.empty())
        return rCellRanges.front();

@@ -2393,7 +2399,7 @@ ScVbaRange::Rows(const uno::Any& aIndex )
    if ( aIndex.hasValue() )
    {
        ScCellRangesBase* pUnoRangesBase = getCellRangesBase();
        ScRange aRange( obtainRangeEvenIfRangeListIsEmpty( pUnoRangesBase));
        ScRange aRange( obtainRangeEvenIfRangeListIsEmpty( pUnoRangesBase->GetRangeList()));

        sal_Int32 nValue = 0;
        OUString sAddress;
@@ -2432,7 +2438,7 @@ uno::Reference< excel::XRange >
ScVbaRange::Columns(const uno::Any& aIndex )
{
    ScCellRangesBase* pUnoRangesBase = getCellRangesBase();
    ScRange aRange( obtainRangeEvenIfRangeListIsEmpty( pUnoRangesBase));
    ScRange aRange( obtainRangeEvenIfRangeListIsEmpty( pUnoRangesBase->GetRangeList()));

    if ( aIndex.hasValue() )
    {
@@ -2946,7 +2952,8 @@ ScVbaRange::getEntireColumnOrRow( bool bColumn )

        return new ScVbaRange( mxParent, mxContext, xRanges, !bColumn, bColumn );
    }
    uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( pUnoRangesBase->GetDocShell(), aCellRanges.front() ) );
    const ScRange aRange( obtainRangeEvenIfRangeListIsEmpty( aCellRanges));
    uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( pUnoRangesBase->GetDocShell(), aRange));
    return new ScVbaRange( mxParent, mxContext, xRange, !bColumn, bColumn  );
}

diff --git a/sc/source/ui/vba/vbarange.hxx b/sc/source/ui/vba/vbarange.hxx
index a893115..118ad04 100644
--- a/sc/source/ui/vba/vbarange.hxx
+++ b/sc/source/ui/vba/vbarange.hxx
@@ -120,7 +120,7 @@ class ScVbaRange : public ScVbaRange_BASE
    void fireChangeEvent();

    /// @throws css::uno::RuntimeException
    ScRange obtainRangeEvenIfRangeListIsEmpty( const ScCellRangesBase* pUnoRangesBase ) const;
    ScRange obtainRangeEvenIfRangeListIsEmpty( const ScRangeList& rCellRanges ) const;

protected:
    virtual ScCellRangesBase* getCellRangesBase() override;