Fix crash on commandless reports and export missing page-break attributes

Change-Id: I5ff69b78c72310a9996b4a2d8ed149bb1698e20b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/208316
Tested-by: Jenkins
Reviewed-by: Vissarion Fisikopoulos <vfisikop@libreoffice.org>
This commit is contained in:
Vissarion Fisikopoulos
2026-07-30 15:13:07 +02:00
parent 4337c29fb1
commit 060b020466
3 changed files with 56 additions and 7 deletions
@@ -25,6 +25,10 @@
#include <osl/process.h>
#include <com/sun/star/text/XTextTablesSupplier.hpp>
#include <com/sun/star/text/XTextTable.hpp>
#include <com/sun/star/report/XReportDefinition.hpp>
#include <com/sun/star/lang/IllegalArgumentException.hpp>
#include <com/sun/star/sdb/XSubDocument.hpp>
#include <comphelper/scopeguard.hxx>
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
@@ -173,6 +177,45 @@ CPPUNIT_TEST_FIXTURE(RptBasicTest, nestedGroupBoundary)
nPentahoHeaders, nCppHeaders);
}
CPPUNIT_TEST_FIXTURE(RptBasicTest, emptyCommandNoCrash)
{
// Executing a report with no Command (query/table) set must fail cleanly
// (IllegalArgumentException) under the C++ ReportBuilder path, same as the
// Pentaho path already does - not reach the undefined behavior that used to
// sit behind an unguarded empty-column-list access in getColumnNameString().
loadURLCopy(u"nested_group_boundary.odb");
Reference<frame::XModel> xModel(mxComponent, UNO_QUERY_THROW);
Reference<frame::XController> xController(xModel->getCurrentController());
Reference<sdb::application::XDatabaseDocumentUI> xUI(xController, UNO_QUERY_THROW);
xUI->connect();
Reference<XConnection> xActiveConnection = xUI->getActiveConnection();
Reference<XReportDocumentsSupplier> xSupp(xModel, UNO_QUERY_THROW);
Reference<container::XNameAccess> xNameAccess = xSupp->getReportDocuments();
const Sequence<OUString> aReportNames(xNameAccess->getElementNames());
CPPUNIT_ASSERT(aReportNames.hasElements());
Reference<sdb::XSubDocument> xSubDoc(xNameAccess->getByName(aReportNames[0]), UNO_QUERY_THROW);
Reference<report::XReportDefinition> xReportDef(xSubDoc->openDesign(), UNO_QUERY_THROW);
xReportDef->setCommand(u""_ustr);
xSubDoc->store();
xSubDoc->close();
const OUString sVarName(u"SAL_ENABLE_PENTAHO_FREE_REPORTBUILDER"_ustr);
osl_setEnvironment(sVarName.pData, u"1"_ustr.pData);
comphelper::ScopeGuard aEnvGuard([&sVarName] { osl_clearEnvironment(sVarName.pData); });
::comphelper::NamedValueCollection aLoadArgs;
aLoadArgs.put(u"ActiveConnection"_ustr, xActiveConnection);
Reference<frame::XComponentLoader> xComponentLoader(xNameAccess, UNO_QUERY_THROW);
CPPUNIT_ASSERT_THROW(xComponentLoader->loadComponentFromURL(aReportNames[0], u"_blank"_ustr, 0,
aLoadArgs.getPropertyValues()),
lang::IllegalArgumentException);
}
OUString RptBasicTest::renderReportText(const OUString& rReportName,
const Reference<frame::XComponentLoader>& xComponentLoader,
const Reference<XConnection>& xActiveConnection,
@@ -183,6 +226,7 @@ OUString RptBasicTest::renderReportText(const OUString& rReportName,
osl_setEnvironment(sVarName.pData, u"1"_ustr.pData);
else
osl_clearEnvironment(sVarName.pData);
comphelper::ScopeGuard aEnvGuard([&sVarName] { osl_clearEnvironment(sVarName.pData); });
::comphelper::NamedValueCollection aLoadArgs;
aLoadArgs.put(u"ActiveConnection"_ustr, xActiveConnection);
@@ -190,8 +234,6 @@ OUString RptBasicTest::renderReportText(const OUString& rReportName,
Reference<lang::XComponent> xComponent = xComponentLoader->loadComponentFromURL(
rReportName, u"_blank"_ustr, 0, aLoadArgs.getPropertyValues());
osl_clearEnvironment(sVarName.pData);
Reference<text::XTextDocument> xTextDoc(xComponent, UNO_QUERY_THROW);
OUStringBuffer sText(xTextDoc->getText()->getString());
@@ -21,6 +21,7 @@
#include <comphelper/storagehelper.hxx>
#include <connectivity/dbtools.hxx>
#include <comphelper/mimeconfighelper.hxx>
#include <comphelper/scopeguard.hxx>
#include <comphelper/string.hxx>
#include <cppuhelper/supportsservice.hxx>
#include <com/sun/star/beans/NamedValue.hpp>
@@ -199,11 +200,15 @@ OUString OReportEngineJFree::getNewOutputName()
if (bCppReportBuilder)
{
// C++ ReportBuilder path: uses ORptExecuteExport for direct export with data
m_pReport->setUseRPTTags(false);
m_pReport->storeToStorage(xOut, aEmpty);
m_pReport->setUseRPTTags(true);
if ( xStorageProp.is() )
sOutputName = sFileURL;
if (!m_pReport->getCommand().isEmpty())
{
m_pReport->setUseRPTTags(false);
comphelper::ScopeGuard aRestoreRPTTags(
[this]() { m_pReport->setUseRPTTags(true); });
m_pReport->storeToStorage(xOut, aEmpty);
if ( xStorageProp.is() )
sOutputName = sFileURL;
}
}
else
{
@@ -654,6 +654,8 @@ ORptExecuteExport::getColumnNameString(const Reference<XReportDefinition>& _xRep
_xReportDefinition->getCommand(), xHoldAlive);
OUString sColumnNameList;
Sequence<OUString> sColumnNames = xColumns->getElementNames();
if (!sColumnNames.hasElements())
return sColumnNameList;
for (sal_Int32 i = 0; i < sColumnNames.getLength() - 1; i++)
{