[Libreoffice-commits] core.git: Branch 'feature/cib_contract891' - 5 commits - comphelper/source external/icu framework/source .gitreview include/o3tl package/source sfx2/source
Samuel Mehrbrodt (via logerrit)
logerrit at kemper.freedesktop.org
Tue Sep 29 13:26:01 UTC 2020
Rebased ref, commits from common ancestor:
commit ca9206fd7a8137b9546ace52c9403b53f4b02a0b
Author: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
AuthorDate: Tue Sep 29 11:26:37 2020 +0200
Commit: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
CommitDate: Tue Sep 29 15:17:41 2020 +0200
Update .gitreview
Change-Id: I999d8a5c1ecad30849ac906ec7cdf3b48604e87e
diff --git a/.gitreview b/.gitreview
index 710fd1e8178e..a8e0ea8b49cc 100644
--- a/.gitreview
+++ b/.gitreview
@@ -3,5 +3,5 @@ host=logerrit
port=29418
project=core
defaultremote=logerrit
-defaultbranch=libreoffice-4-2
+defaultbranch=feature/cib_contract891
commit 1d3ebf5d677ece6cd18c3adedcaf2a73827912b3
Author: Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Fri Jan 3 22:40:07 2020 +0300
Commit: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
CommitDate: Tue Sep 29 15:17:41 2020 +0200
tdf#93389: keep encryption information for autorecovered MS formats
The autorecovery data is stored in ODF, regardless of the original
document format. When restoring, type detection generates ODF data,
which is stored in the media descriptor attached to document, even
after real filter was restored (see AutoRecovery::implts_openDocs).
If real filter is not ODF, then at the save time, it doesn't find
necessary information in encryption data, and makes not encrypted
package.
This patch adds both MS binary data, and OOXML data, to existing
ODF data for recovered password-protected documents (regardless of
their real filter).
TODO: only add required information to encryption data: pass real
filter name to DocPasswordHelper::requestAndVerifyDocPassword from
AutoRecovery::implts_openDocs.
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86201
Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>
Tested-by: Mike Kaganski <mike.kaganski at collabora.com>
(cherry picked from commit dd198398b6e5c84ab1255a90ef96e6445b66a64f)
Conflicts:
comphelper/source/misc/docpasswordhelper.cxx
(cherry picked from commit 6017cdff264afc3b98beeba1330d6df28102fe7a)
Change-Id: I4717f067ad3c40167312b99eefef5584a467bfed
diff --git a/comphelper/source/misc/docpasswordhelper.cxx b/comphelper/source/misc/docpasswordhelper.cxx
index 2120b4a3e3cc..16405276fdcb 100644
--- a/comphelper/source/misc/docpasswordhelper.cxx
+++ b/comphelper/source/misc/docpasswordhelper.cxx
@@ -19,6 +19,8 @@
#include "comphelper/docpasswordhelper.hxx"
+#include <comphelper/propertysequence.hxx>
+#include <comphelper/storagehelper.hxx>
#include <comphelper/sequence.hxx>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/task/XInteractionHandler.hpp>
@@ -351,6 +353,25 @@ Sequence< sal_Int8 > DocPasswordHelper::GetXLHashAsSequence(
OUString aPassword;
DocPasswordVerifierResult eResult = DocPasswordVerifierResult_WRONG_PASSWORD;
+ sal_Int32 nMediaEncDataCount = rMediaEncData.getLength();
+
+ // tdf#93389: if the document is being restored from autorecovery, we need to add encryption
+ // data also for real document type.
+ // TODO: get real filter name here (from CheckPasswd_Impl), to only add necessary data
+ bool bForSalvage = false;
+ if (nMediaEncDataCount)
+ {
+ for (auto& val : rMediaEncData)
+ {
+ if (val.Name == "ForSalvage")
+ {
+ --nMediaEncDataCount; // don't consider this element below
+ val.Value >>= bForSalvage;
+ break;
+ }
+ }
+ }
+
// first, try provided default passwords
if( pbIsDefaultPassword )
*pbIsDefaultPassword = false;
@@ -375,7 +396,7 @@ Sequence< sal_Int8 > DocPasswordHelper::GetXLHashAsSequence(
// try media encryption data (skip, if result is OK or ABORT)
if( eResult == DocPasswordVerifierResult_WRONG_PASSWORD )
{
- if( rMediaEncData.getLength() > 0 )
+ if (nMediaEncDataCount)
{
eResult = rVerifier.verifyEncryptionData( rMediaEncData );
if( eResult == DocPasswordVerifierResult_OK )
@@ -434,6 +455,26 @@ Sequence< sal_Int8 > DocPasswordHelper::GetXLHashAsSequence(
aEncData = comphelper::concatSequences(
aEncData, OStorageHelper::CreatePackageEncryptionData(aPassword));
}
+
+ if (bForSalvage)
+ {
+ // TODO: add individual methods for different target filter, and only call what's needed
+
+ // 1. Prepare binary MS formats encryption data
+ auto aUniqueID = GenerateRandomByteSequence(16);
+ auto aEnc97Key = GenerateStd97Key(aPassword.getStr(), aUniqueID);
+ // 2. Add MS binary and OOXML encryption data to result
+ uno::Sequence< beans::NamedValue > aContainer(3);
+ aContainer[0].Name = "STD97EncryptionKey";
+ aContainer[0].Value <<= aEnc97Key;
+ aContainer[1].Name = "STD97UniqueID";
+ aContainer[1].Value <<= aUniqueID;
+ aContainer[2].Name = "OOXPassword";
+ aContainer[2].Value <<= aPassword;
+
+ aEncData = comphelper::concatSequences(
+ aEncData, aContainer);
+ }
}
return (eResult == DocPasswordVerifierResult_OK) ? aEncData : uno::Sequence< beans::NamedValue >();
diff --git a/package/source/xstor/owriteablestream.cxx b/package/source/xstor/owriteablestream.cxx
index c3a25910cbe5..85571898fb8f 100644
--- a/package/source/xstor/owriteablestream.cxx
+++ b/package/source/xstor/owriteablestream.cxx
@@ -57,9 +57,11 @@ using namespace ::com::sun::star;
namespace package
{
-bool PackageEncryptionDatasEqual( const ::comphelper::SequenceAsHashMap& aHash1, const ::comphelper::SequenceAsHashMap& aHash2 )
+bool PackageEncryptionDataLessOrEqual( const ::comphelper::SequenceAsHashMap& aHash1, const ::comphelper::SequenceAsHashMap& aHash2 )
{
- bool bResult = ( aHash1.size() && aHash1.size() == aHash2.size() );
+ // tdf#93389: aHash2 may contain more than in aHash1, if it contains also data for other package
+ // formats (as in case of autorecovery)
+ bool bResult = !aHash1.empty() && aHash1.size() <= aHash2.size();
for ( ::comphelper::SequenceAsHashMap::const_iterator aIter = aHash1.begin();
bResult && aIter != aHash1.end();
++aIter )
@@ -1207,7 +1209,7 @@ uno::Reference< io::XStream > OWriteStream_Impl::GetStream( sal_Int32 nStreamMod
if ( m_bHasCachedEncryptionData )
{
- if ( !::package::PackageEncryptionDatasEqual( m_aEncryptionData, aEncryptionData ) )
+ if ( !::package::PackageEncryptionDataLessOrEqual( m_aEncryptionData, aEncryptionData ) )
throw packages::WrongPasswordException();
// the correct key must be set already
diff --git a/package/source/xstor/owriteablestream.hxx b/package/source/xstor/owriteablestream.hxx
index 22fcb3f83d06..edd6827366ac 100644
--- a/package/source/xstor/owriteablestream.hxx
+++ b/package/source/xstor/owriteablestream.hxx
@@ -67,7 +67,8 @@ namespace cppu {
namespace package {
void StaticAddLog( const OUString& aMessage );
- bool PackageEncryptionDatasEqual( const ::comphelper::SequenceAsHashMap& aHash1, const ::comphelper::SequenceAsHashMap& aHash2 );
+ // all data in aHash1 is contained in aHash2
+ bool PackageEncryptionDataLessOrEqual( const ::comphelper::SequenceAsHashMap& aHash1, const ::comphelper::SequenceAsHashMap& aHash2 );
}
struct WSInternalData_Impl
diff --git a/package/source/xstor/xstorage.cxx b/package/source/xstor/xstorage.cxx
index 8775561dde77..1c3b8e1915b0 100644
--- a/package/source/xstor/xstorage.cxx
+++ b/package/source/xstor/xstorage.cxx
@@ -914,7 +914,7 @@ void OStorage_Impl::CopyStorageElement( SotElement_Impl* pElement,
AddLog( OSL_LOG_PREFIX "No Encryption" );
}
- if ( bHasCommonEncryptionData && ::package::PackageEncryptionDatasEqual( pElement->m_pStream->GetCachedEncryptionData(), aCommonEncryptionData ) )
+ if (bHasCommonEncryptionData && ::package::PackageEncryptionDataLessOrEqual(pElement->m_xStream->GetCachedEncryptionData(), aCommonEncryptionData))
{
// If the stream can be opened with the common storage password
// it must be stored with the common storage password as well
diff --git a/sfx2/source/appl/appopen.cxx b/sfx2/source/appl/appopen.cxx
index e8e23c5d1a4c..6afce40ff50c 100644
--- a/sfx2/source/appl/appopen.cxx
+++ b/sfx2/source/appl/appopen.cxx
@@ -49,6 +49,7 @@
#include <comphelper/sequenceasvector.hxx>
#include <comphelper/storagehelper.hxx>
#include <comphelper/string.hxx>
+#include <comphelper/sequence.hxx>
#include <comphelper/synchronousdispatch.hxx>
#include <vcl/wrkwin.hxx>
@@ -270,8 +271,21 @@ sal_uInt32 CheckPasswd_Impl
if ( pEncryptionDataItem )
pEncryptionDataItem->GetValue() >>= aEncryptionData;
- OUString aDocumentName = INetURLObject( pFile->GetOrigURL() ).GetMainURL( INetURLObject::DECODE_WITH_CHARSET );
+ // tdf#93389: if recoverying a document, encryption data should contain
+ // entries for the real filter, not only for recovery ODF, to keep it
+ // encrypted. Pass this in encryption data.
+ // TODO: pass here the real filter (from AutoRecovery::implts_openDocs)
+ // to marshal this to requestAndVerifyDocPassword
+ if (pSet->GetItemState(SID_DOC_SALVAGE, false) == SfxItemState::SET)
+ {
+ uno::Sequence< beans::NamedValue > aContainer(1);
+ aContainer[0].Name = "ForSalvage";
+ aContainer[0].Value <<= true;
+ aEncryptionData = comphelper::concatSequences(
+ aEncryptionData, aContainer);
+ }
+ OUString aDocumentName = INetURLObject( pFile->GetOrigURL() ).GetMainURL( INetURLObject::DECODE_WITH_CHARSET );
SfxDocPasswordVerifier aVerifier( xStorage );
aEncryptionData = ::comphelper::DocPasswordHelper::requestAndVerifyDocPassword(
aVerifier, aEncryptionData, aPassword, xInteractionHandler, aDocumentName, comphelper::DocPasswordRequestType_STANDARD );
commit 90ba9d7f39ae6008f796e46d9ec325585933518a
Author: Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Fri Nov 29 13:07:57 2019 +0300
Commit: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
CommitDate: Tue Sep 29 15:17:41 2020 +0200
tdf#118639: store ODF encryption data for autorecovery
When saving autorecovery information, ODF is used. If the original
document is password-protected, its autorecovery is also generated
password-protected (since ef87ff6680f79362a431db6e7ef2f40cfc576219).
But when the stored encryption data for non-ODF document does not
contain "PackageSHA256UTF8EncryptionKey" value, following
ZipPackage::GetEncryptionKey fails, so the whole save fails.
So just generate and append ODF encryption keys where we still have
user password.
Reviewed-on: https://gerrit.libreoffice.org/84052
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>
(cherry picked from commit 63634738dd03cc74806ce6843c16ff5e51a371a0)
Reviewed-on: https://gerrit.libreoffice.org/84133
Reviewed-by: Xisco Faulí <xiscofauli at libreoffice.org>
(cherry picked from commit e569dc9824e95617d921bb8f115d243aea0125b9)
Reviewed-on: https://gerrit.libreoffice.org/84232
Reviewed-by: Adolfo Jayme Barrientos <fitojb at ubuntu.com>
Change-Id: I776e28de784489521e4941d1075690f90c056014
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/94355
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
Reviewed-by: Andras Timar <andras.timar at collabora.com>
diff --git a/comphelper/source/misc/docpasswordhelper.cxx b/comphelper/source/misc/docpasswordhelper.cxx
index 9d312a341f58..2120b4a3e3cc 100644
--- a/comphelper/source/misc/docpasswordhelper.cxx
+++ b/comphelper/source/misc/docpasswordhelper.cxx
@@ -19,6 +19,7 @@
#include "comphelper/docpasswordhelper.hxx"
+#include <comphelper/sequence.hxx>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/task/XInteractionHandler.hpp>
@@ -347,6 +348,7 @@ Sequence< sal_Int8 > DocPasswordHelper::GetXLHashAsSequence(
bool* pbIsDefaultPassword )
{
::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue > aEncData;
+ OUString aPassword;
DocPasswordVerifierResult eResult = DocPasswordVerifierResult_WRONG_PASSWORD;
// first, try provided default passwords
@@ -360,8 +362,12 @@ Sequence< sal_Int8 > DocPasswordHelper::GetXLHashAsSequence(
if( !aIt->isEmpty() )
{
eResult = rVerifier.verifyPassword( *aIt, aEncData );
- if( pbIsDefaultPassword )
- *pbIsDefaultPassword = eResult == DocPasswordVerifierResult_OK;
+ if (eResult == DocPasswordVerifierResult_OK)
+ {
+ aPassword = *aIt;
+ if (pbIsDefaultPassword)
+ *pbIsDefaultPassword = true;
+ }
}
}
}
@@ -381,7 +387,11 @@ Sequence< sal_Int8 > DocPasswordHelper::GetXLHashAsSequence(
if( eResult == DocPasswordVerifierResult_WRONG_PASSWORD )
{
if( !rMediaPassword.isEmpty() )
+ {
eResult = rVerifier.verifyPassword( rMediaPassword, aEncData );
+ if (eResult == DocPasswordVerifierResult_OK)
+ aPassword = rMediaPassword;
+ }
}
// request a password (skip, if result is OK or ABORT)
@@ -397,6 +407,8 @@ Sequence< sal_Int8 > DocPasswordHelper::GetXLHashAsSequence(
{
if( !pRequest->getPassword().isEmpty() )
eResult = rVerifier.verifyPassword( pRequest->getPassword(), aEncData );
+ if (eResult == DocPasswordVerifierResult_OK)
+ aPassword = pRequest->getPassword();
}
else
{
@@ -409,6 +421,21 @@ Sequence< sal_Int8 > DocPasswordHelper::GetXLHashAsSequence(
{
}
+ if (eResult == DocPasswordVerifierResult_OK && !aPassword.isEmpty())
+ {
+ if (std::find_if(std::cbegin(aEncData), std::cend(aEncData),
+ [](const css::beans::NamedValue& val) {
+ return val.Name == PACKAGE_ENCRYPTIONDATA_SHA256UTF8;
+ })
+ == std::cend(aEncData))
+ {
+ // tdf#118639: We need ODF encryption data for autorecovery, where password
+ // will already be unavailable, so generate and append it here
+ aEncData = comphelper::concatSequences(
+ aEncData, OStorageHelper::CreatePackageEncryptionData(aPassword));
+ }
+ }
+
return (eResult == DocPasswordVerifierResult_OK) ? aEncData : uno::Sequence< beans::NamedValue >();
}
diff --git a/sfx2/source/dialog/filedlghelper.cxx b/sfx2/source/dialog/filedlghelper.cxx
index 28a8060dcc86..3186b4af4abf 100644
--- a/sfx2/source/dialog/filedlghelper.cxx
+++ b/sfx2/source/dialog/filedlghelper.cxx
@@ -2654,6 +2654,8 @@ ErrCode RequestPassword(const SfxFilter* pCurrentFilter, OUString& aURL, SfxItem
{
if ( pPasswordRequest->getPassword().getLength() )
{
+ css::uno::Sequence< css::beans::NamedValue > aEncryptionData;
+
// TODO/LATER: The filters should show the password dialog themself in future
if ( bMSType )
{
@@ -2662,7 +2664,7 @@ ErrCode RequestPassword(const SfxFilter* pCurrentFilter, OUString& aURL, SfxItem
{
::comphelper::SequenceAsHashMap aHashData;
aHashData[ OUString( "OOXPassword" ) ] <<= pPasswordRequest->getPassword();
- pSet->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aHashData.getAsConstNamedValueList() ) ) );
+ aEncryptionData = aHashData.getAsConstNamedValueList();
}
else
{
@@ -2675,7 +2677,7 @@ ErrCode RequestPassword(const SfxFilter* pCurrentFilter, OUString& aURL, SfxItem
aHashData[ OUString( "STD97EncryptionKey" ) ] <<= aEncryptionKey;
aHashData[ OUString( "STD97UniqueID" ) ] <<= aUniqueID;
- pSet->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aHashData.getAsConstNamedValueList() ) ) );
+ aEncryptionData = aHashData.getAsConstNamedValueList();
}
else
{
@@ -2683,10 +2685,14 @@ ErrCode RequestPassword(const SfxFilter* pCurrentFilter, OUString& aURL, SfxItem
}
}
}
- else
- {
- pSet->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( ::comphelper::OStorageHelper::CreatePackageEncryptionData( pPasswordRequest->getPassword() ) ) ) );
- }
+
+ // tdf#118639: We need ODF encryption data for autorecovery where password will already
+ // be unavailable, even for non-ODF documents, so append it here unconditionally
+ pSet->Put(SfxUnoAnyItem(
+ SID_ENCRYPTIONDATA,
+ uno::makeAny(comphelper::concatSequences(
+ aEncryptionData, comphelper::OStorageHelper::CreatePackageEncryptionData(
+ pPasswordRequest->getPassword())))));
}
if ( pPasswordRequest->getRecommendReadOnly() )
commit c03d395466577e415c8d1683983a2d1951451bf9
Author: Vasily Melenchuk <vasily.melenchuk at cib.de>
AuthorDate: Mon Feb 17 10:52:11 2020 +0300
Commit: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
CommitDate: Tue Sep 29 15:17:40 2020 +0200
tdf#129096: Document Recovery: Use TypeDetection on load
Loading of recovered document happend before via XFilter::filter
is not updating media descriptor of document. But this is
important for password protected documents to store entered password
and used encryption type.
To avoid this problem let's use TypeDetection which during its work
will ask user for password and store all the info in modified media
descriptor before actual recovery attempt.
Change-Id: Ide2ebf0955e0937cdc7c9d7165593b71f904649b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/88844
Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>
Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
Tested-by: Jenkins
(cherry picked from commit 8461127750e1fe92a615409505256132e54fb8e8)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/89789
Reviewed-by: Vasily Melenchuk <vasily.melenchuk at cib.de>
(cherry picked from commit b05c87f00433987b10542866696f0b4aaad015cc)
(cherry picked from commit ba8b744086443b197e88397aa09a67fb263eb9d9)
diff --git a/framework/source/services/autorecovery.cxx b/framework/source/services/autorecovery.cxx
index 4dfa3edc38ee..ed951718a0f6 100644
--- a/framework/source/services/autorecovery.cxx
+++ b/framework/source/services/autorecovery.cxx
@@ -63,6 +63,7 @@
#include <com/sun/star/container/XContainerQuery.hpp>
#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
#include <com/sun/star/document/XDocumentRecovery.hpp>
+#include <com/sun/star/document/XExtendedFilterDetection.hpp>
#include <com/sun/star/util/XCloseable.hpp>
#include <com/sun/star/awt/XWindow2.hpp>
#include <com/sun/star/task/XStatusIndicatorFactory.hpp>
@@ -2665,6 +2666,37 @@ void AutoRecovery::implts_openOneDoc(const OUString& sURL ,
}
else
{
+ OUString sFilterName;
+ lDescriptor[utl::MediaDescriptor::PROP_FILTERNAME()] >>= sFilterName;
+ if (!sFilterName.isEmpty()
+ && ( sFilterName == "Calc MS Excel 2007 XML"
+ || sFilterName == "Impress MS PowerPoint 2007 XML"
+ || sFilterName == "MS Word 2007 XML"))
+ // TODO: Propbably need to check other affected formats + templates?
+ {
+ // tdf#129096: in case of recovery of password protected OOXML document it is done not
+ // the same way as ordinal loading. Inside XDocumentRecovery::recoverFromFile
+ // there is a call to XFilter::filter which has constant media descriptor and thus
+ // all encryption data used in document is lost. To avoid this try to walkaround
+ // with explicit call to FormatDetector. It will try to load document, prompt for password
+ // and store this info in media descriptor we will use for recoverFromFile call.
+ Reference< css::document::XExtendedFilterDetection > xDetection(
+ m_xContext->getServiceManager()->createInstanceWithContext(
+ "com.sun.star.comp.oox.FormatDetector", m_xContext),
+ UNO_QUERY_THROW);
+ lDescriptor[utl::MediaDescriptor::PROP_URL()] <<= sURL;
+ Sequence< css::beans::PropertyValue > aDescriptorSeq = lDescriptor.getAsConstPropertyValueList();
+ OUString sType = xDetection->detect(aDescriptorSeq);
+
+ OUString sNewFilterName;
+ lDescriptor[utl::MediaDescriptor::PROP_FILTERNAME()] >>= sNewFilterName;
+ if (!sType.isEmpty() && sNewFilterName == sFilterName)
+ {
+ // Filter detection was okay, update media descriptor with one received from FilterDetect
+ lDescriptor = aDescriptorSeq;
+ }
+ }
+
// let it recover itself
Reference< XDocumentRecovery > xDocRecover( xModel, UNO_QUERY_THROW );
xDocRecover->recoverFromFile(
commit 556f5c28bc5b898ec9ddd799dd21177cc4200025
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Mar 24 10:48:04 2020 +0100
Commit: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
CommitDate: Tue Sep 29 15:17:17 2020 +0200
icu: add patch to fix CVE-2020-10531
Added include/o3tl/safeint.hxx to this 4.2 branch which was missing here
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/90971
Tested-by: Jenkins
Reviewed-by: Michael Stahl <michael.stahl at cib.de>
(cherry picked from commit 002d1152dc418f7d624409e76cd9d4ac0b42c7f8)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/90975
Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
(cherry picked from commit 63b573faf984875cda7a879e696ea75fae81df57)
Change-Id: I0aca4af1bd79f28bf1c920a4d05e80948106aaac
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/90998
Tested-by: Michael Stahl <michael.stahl at cib.de>
Reviewed-by: Michael Stahl <michael.stahl at cib.de>
diff --git a/external/icu/ExternalProject_icu.mk b/external/icu/ExternalProject_icu.mk
index 1da4727c2fe9..5f74fdcbabb6 100644
--- a/external/icu/ExternalProject_icu.mk
+++ b/external/icu/ExternalProject_icu.mk
@@ -13,7 +13,10 @@ $(eval $(call gb_ExternalProject_register_targets,icu,\
build \
))
-icu_CPPFLAGS:="-DHAVE_GCC_ATOMICS=$(if $(filter TRUE,$(GCC_HAVE_BUILTIN_ATOMIC)),1,0)"
+# -I to find o3tl headers
+icu_CPPFLAGS:=" \
+ -DHAVE_GCC_ATOMICS=$(if $(filter TRUE,$(GCC_HAVE_BUILTIN_ATOMIC)),1,0) \
+ -I$(SRCDIR)/include"
ifeq ($(OS),WNT)
diff --git a/external/icu/UnpackedTarball_icu.mk b/external/icu/UnpackedTarball_icu.mk
index 710ba70aa9ad..8f9dcfe4d6b0 100644
--- a/external/icu/UnpackedTarball_icu.mk
+++ b/external/icu/UnpackedTarball_icu.mk
@@ -23,6 +23,7 @@ $(eval $(call gb_UnpackedTarball_add_patches,icu,\
external/icu/icu4c-scriptrun.patch \
external/icu/icu4c-changeset-39671.patch.1 \
external/icu/icu4c-changeset-40324.patch.1 \
+ external/icu/b7d08bc04a4296982fcef8b6b8a354a9e4e7afca.patch.2 \
))
# vim: set noet sw=4 ts=4:
diff --git a/external/icu/b7d08bc04a4296982fcef8b6b8a354a9e4e7afca.patch.2 b/external/icu/b7d08bc04a4296982fcef8b6b8a354a9e4e7afca.patch.2
new file mode 100644
index 000000000000..3f9cfcee8504
--- /dev/null
+++ b/external/icu/b7d08bc04a4296982fcef8b6b8a354a9e4e7afca.patch.2
@@ -0,0 +1,38 @@
+From b7d08bc04a4296982fcef8b6b8a354a9e4e7afca Mon Sep 17 00:00:00 2001
+From: Frank Tang <ftang at chromium.org>
+Date: Sat, 1 Feb 2020 02:39:04 +0000
+Subject: [PATCH] ICU-20958 Prevent SEGV_MAPERR in append
+
+See #971
+---
+ icu4c/source/common/unistr.cpp | 6 ++-
+ icu4c/source/test/intltest/ustrtest.cpp | 62 +++++++++++++++++++++++++
+ icu4c/source/test/intltest/ustrtest.h | 1 +
+ 3 files changed, 68 insertions(+), 1 deletion(-)
+
+diff --git a/icu4c/source/common/unistr.cpp b/icu4c/source/common/unistr.cpp
+index 901bb3358ba..077b4d6ef20 100644
+--- a/icu4c/source/common/unistr.cpp
++++ b/icu4c/source/common/unistr.cpp
+@@ -31,6 +31,7 @@
+ #include "ustr_imp.h"
+ #include "umutex.h"
+ #include "uassert.h"
++#include <o3tl/safeint.hxx>
+
+ #if 0
+
+@@ -1510,7 +1511,11 @@
+ }
+
+ int32_t oldLength = length();
+- int32_t newLength = oldLength + srcLength;
++ int32_t newLength;
++ if (o3tl::checked_add(oldLength, srcLength, newLength)) {
++ setToBogus();
++ return *this;
++ }
+ // optimize append() onto a large-enough, owned string
+ if((newLength <= getCapacity() && isBufferWritable()) ||
+ cloneArrayIfNeeded(newLength, newLength + (newLength >> 2) + kGrowSize)) {
+
diff --git a/include/o3tl/safeint.hxx b/include/o3tl/safeint.hxx
new file mode 100644
index 000000000000..1c8bf280171e
--- /dev/null
+++ b/include/o3tl/safeint.hxx
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_O3TL_SAFEINT_HXX
+#define INCLUDED_O3TL_SAFEINT_HXX
+
+#include <sal/config.h>
+
+#include <limits>
+#include <type_traits>
+
+#if defined(_MSC_VER)
+#include <safeint.h>
+#else
+#ifndef __has_builtin
+# define __has_builtin(x) 0
+#endif
+#endif
+
+namespace o3tl
+{
+
+template<typename T> inline
+typename std::enable_if<std::is_signed<T>::value, T>::type saturating_add(
+ T a, T b)
+{
+ if (b >= 0) {
+ if (a <= std::numeric_limits<T>::max() - b) {
+ return a + b;
+ } else {
+ return std::numeric_limits<T>::max();
+ }
+ } else {
+ if (a >= std::numeric_limits<T>::min() + b) {
+ return a - b;
+ } else {
+ return std::numeric_limits<T>::min();
+ }
+ }
+}
+
+template<typename T> inline
+typename std::enable_if<std::is_unsigned<T>::value, T>::type saturating_add(
+ T a, T b)
+{
+ if (a <= std::numeric_limits<T>::max() - b) {
+ return a + b;
+ } else {
+ return std::numeric_limits<T>::max();
+ }
+}
+
+#if defined(_MSC_VER)
+
+template<typename T> inline bool checked_multiply(T a, T b, T& result)
+{
+ return !msl::utilities::SafeMultiply(a, b, result);
+}
+
+template<typename T> inline bool checked_add(T a, T b, T& result)
+{
+ return !msl::utilities::SafeAdd(a, b, result);
+}
+
+#elif (defined __GNUC__ && __GNUC__ >= 5) || (__has_builtin(__builtin_mul_overflow) && !(defined ANDROID && defined __clang__))
+
+template<typename T> inline bool checked_multiply(T a, T b, T& result)
+{
+ return __builtin_mul_overflow(a, b, &result);
+}
+
+template<typename T> inline bool checked_add(T a, T b, T& result)
+{
+ return __builtin_add_overflow(a, b, &result);
+}
+
+#else
+
+//https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow
+template<typename T> inline typename std::enable_if<std::is_signed<T>::value, bool>::type checked_multiply(T a, T b, T& result)
+{
+ if (a > 0) { /* a is positive */
+ if (b > 0) { /* a and b are positive */
+ if (a > (std::numeric_limits<T>::max() / b)) {
+ return true; /* Handle error */
+ }
+ } else { /* a positive, b nonpositive */
+ if (b < (std::numeric_limits<T>::min() / a)) {
+ return true; /* Handle error */
+ }
+ } /* a positive, b nonpositive */
+ } else { /* a is nonpositive */
+ if (b > 0) { /* a is nonpositive, b is positive */
+ if (a < (std::numeric_limits<T>::min() / b)) {
+ return true; /* Handle error */
+ }
+ } else { /* a and b are nonpositive */
+ if ( (a != 0) && (b < (std::numeric_limits<T>::max() / a))) {
+ return true; /* Handle error */
+ }
+ } /* End if a and b are nonpositive */
+ } /* End if a is nonpositive */
+
+ result = a * b;
+
+ return false;
+}
+
+//https://www.securecoding.cert.org/confluence/display/c/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap
+template<typename T> inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type checked_multiply(T a, T b, T& result)
+{
+ if (b && a > std::numeric_limits<T>::max() / b) {
+ return true;/* Handle error */
+ }
+
+ result = a * b;
+
+ return false;
+}
+
+//https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow
+template<typename T> inline typename std::enable_if<std::is_signed<T>::value, bool>::type checked_add(T a, T b, T& result)
+{
+ if (((b > 0) && (a > (std::numeric_limits<T>::max() - b))) ||
+ ((b < 0) && (a < (std::numeric_limits<T>::min() - b)))) {
+ return true;
+ }
+
+ result = a + b;
+
+ return false;
+}
+
+//https://www.securecoding.cert.org/confluence/display/c/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap
+template<typename T> inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type checked_add(T a, T b, T& result)
+{
+ if (std::numeric_limits<T>::max() - a < b) {
+ return true;/* Handle error */
+ }
+
+ result = a + b;
+
+ return false;
+}
+
+#endif
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
More information about the Libreoffice-commits
mailing list