[Libreoffice-commits] core.git: Branch 'feature/cib_contract57' - 27 commits - basic/source configure.ac download.lst embeddedobj/source external/expat external/lcms2 external/libxml2 framework/source i18npool/qa i18npool/source lotuswordpro/qa lotuswordpro/source starmath/source sw/qa sw/source wizards/com writerfilter/qa writerfilter/source

Thorsten Behrens Thorsten.Behrens at CIB.de
Tue Sep 27 12:53:13 UTC 2016


 basic/source/sbx/sbxscan.cxx                                        |    7 
 configure.ac                                                        |    2 
 download.lst                                                        |    9 
 embeddedobj/source/msole/olecomponent.cxx                           |   17 
 external/expat/CVE-2015-1283-refix.patch.1                          |   37 
 external/expat/CVE-2016-0718-v2-2-1.patch.1                         |  755 ++++++++++
 external/expat/UnpackedTarball_expat.mk                             |    4 
 external/expat/expat-2.1.0.patch                                    |   13 
 external/lcms2/0001-Added-an-extra-check-to-MLU-bounds.patch.1      |   25 
 external/lcms2/UnpackedTarball_lcms2.mk                             |    1 
 external/libxml2/ExternalPackage_xml2.mk                            |    2 
 framework/source/services/autorecovery.cxx                          |   13 
 i18npool/qa/cppunit/test_breakiterator.cxx                          |   16 
 i18npool/source/breakiterator/breakiterator_unicode.cxx             |    2 
 lotuswordpro/qa/cppunit/data/fail/recurse-3.lwp                     |binary
 lotuswordpro/source/filter/xfilter/xfcell.hxx                       |    2 
 lotuswordpro/source/filter/xfilter/xftable.cxx                      |    7 
 starmath/source/node.cxx                                            |    3 
 sw/qa/core/data/rtf/pass/tabbox-1.rtf                               |binary
 sw/source/core/docnode/ndtbl.cxx                                    |    2 
 wizards/com/sun/star/wizards/table/FieldFormatter.java              |   14 
 writerfilter/qa/cppunittests/rtftok/data/fail/destinationtest-1.rtf |binary
 writerfilter/qa/cppunittests/rtftok/data/fail/destinationtest-2.rtf |binary
 writerfilter/qa/cppunittests/rtftok/data/fail/nopropertyset-1.rtf   |binary
 writerfilter/qa/cppunittests/rtftok/data/fail/popstate-1.rtf        |binary
 writerfilter/qa/cppunittests/rtftok/data/fail/popstate-2.rtf        |    1 
 writerfilter/qa/cppunittests/rtftok/data/fail/propheight-1.rtf      |binary
 writerfilter/qa/cppunittests/rtftok/data/fail/tablemanager-5.rtf    |binary
 writerfilter/qa/cppunittests/rtftok/data/fail/tablemanager-6.rtf    |binary
 writerfilter/qa/cppunittests/rtftok/data/fail/tablemanager-7.rtf    |binary
 writerfilter/qa/cppunittests/rtftok/data/fail/topcontext-2.rtf      |binary
 writerfilter/qa/cppunittests/rtftok/data/pass/tablemanager-1.rtf    |binary
 writerfilter/qa/cppunittests/rtftok/data/pass/tablemanager-4.rtf    |binary
 writerfilter/qa/cppunittests/rtftok/testrtftok.cxx                  |    4 
 writerfilter/source/dmapper/DomainMapper.cxx                        |   16 
 writerfilter/source/dmapper/DomainMapper_Impl.cxx                   |   32 
 writerfilter/source/dmapper/DomainMapper_Impl.hxx                   |    9 
 writerfilter/source/dmapper/PropertyMap.cxx                         |    2 
 writerfilter/source/rtftok/rtfdocumentimpl.cxx                      |   51 
 writerfilter/source/rtftok/rtfdocumentimpl.hxx                      |   37 
 40 files changed, 1002 insertions(+), 81 deletions(-)

New commits:
commit 229ad2273401a350c5788f40e4ebe1377e98ac97
Author: Thorsten Behrens <Thorsten.Behrens at CIB.de>
Date:   Tue Sep 27 14:51:13 2016 +0200

    bump custom version to 5.0.8.0.0+
    
    Change-Id: Ib6152c6f3af744e2208119a61783357ce47ca8d6

diff --git a/configure.ac b/configure.ac
index 1c175c0..c42327b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -9,7 +9,7 @@ dnl in order to create a configure script.
 # several non-alphanumeric characters, those are split off and used only for the
 # ABOUTBOXPRODUCTVERSIONSUFFIX in openoffice.lst. Why that is necessary, no idea.
 
-AC_INIT([LibreOffice],[5.0.7.0.0+],[],[],[http://documentfoundation.org/])
+AC_INIT([LibreOffice],[5.0.8.0.0+],[],[],[http://documentfoundation.org/])
 
 AC_PREREQ([2.59])
 
commit 07b0835dac3243b8863e11b3a4d5240c9861686e
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Thu Sep 22 21:11:56 2016 +0100

    Resolves: tdf#101971 OleLoad under structured exception guards
    
    sample pptx crashes down in the depths of (apparently pre-installed on
    32bit Windows 10) Flash.ocx
    
    Change-Id: I4e083d492e56e72df47b2c172d7f07f0e39b82ea
    Reviewed-on: https://gerrit.libreoffice.org/29199
    Reviewed-by: Stephan Bergmann <sbergman at redhat.com>
    Tested-by: Stephan Bergmann <sbergman at redhat.com>
    (cherry picked from commit 373b44a2fcbe78e8a3ff14cd410826af151a6adf)
    Reviewed-on: https://gerrit.libreoffice.org/29213
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Michael Stahl <mstahl at redhat.com>
    (cherry picked from commit dafcb32f09c3acea8e2fa12e1d39261b13c740db)

diff --git a/embeddedobj/source/msole/olecomponent.cxx b/embeddedobj/source/msole/olecomponent.cxx
index edafa43..682ef5a 100644
--- a/embeddedobj/source/msole/olecomponent.cxx
+++ b/embeddedobj/source/msole/olecomponent.cxx
@@ -715,6 +715,19 @@ sal_Bool OleComponent::InitializeObject_Impl()
     return sal_True;
 }
 
+namespace
+{
+    HRESULT OleLoadSeh(LPSTORAGE pIStorage, LPVOID* ppObj)
+    {
+        HRESULT hr = E_FAIL;
+        __try {
+            hr = OleLoad(pIStorage, IID_IUnknown, NULL, ppObj);
+        } __except( EXCEPTION_EXECUTE_HANDLER ) {
+            return E_FAIL;
+        }
+        return hr;
+    }
+}
 
 void OleComponent::LoadEmbeddedObject( const OUString& aTempURL )
 {
@@ -730,7 +743,7 @@ void OleComponent::LoadEmbeddedObject( const OUString& aTempURL )
     if ( FAILED( hr ) || !m_pNativeImpl->m_pIStorage )
         throw io::IOException(); // TODO: transport error code?
 
-    hr = OleLoad( m_pNativeImpl->m_pIStorage, IID_IUnknown, NULL, (void**)&m_pNativeImpl->m_pObj );
+    hr = OleLoadSeh(m_pNativeImpl->m_pIStorage, (void**)&m_pNativeImpl->m_pObj);
     if ( FAILED( hr ) || !m_pNativeImpl->m_pObj )
     {
         throw uno::RuntimeException();
@@ -963,7 +976,7 @@ void OleComponent::InitEmbeddedCopyOfLink( OleComponent* pOleLinkComponent )
                 {
                     hr = pObjectStorage->CopyTo( 0, NULL, NULL, m_pNativeImpl->m_pIStorage );
                     if ( SUCCEEDED( hr ) )
-                        hr = OleLoad( m_pNativeImpl->m_pIStorage, IID_IUnknown, NULL, (void**)&m_pNativeImpl->m_pObj );
+                        hr = OleLoadSeh(m_pNativeImpl->m_pIStorage, (void**)&m_pNativeImpl->m_pObj);
                 }
             }
         }
commit eed7c576ecd5d076974074b63a20549b09b912ce
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Mon Sep 12 09:34:21 2016 +0100

    fftester: no table manager
    
    Change-Id: Icb3c640e04416f9120d37558646a570daeddf0a4
    Reviewed-on: https://gerrit.libreoffice.org/28827
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    (cherry picked from commit d7c00a1e54f72427aeadded00a3c5be03c1c997b)

diff --git a/writerfilter/qa/cppunittests/rtftok/data/fail/tablemanager-7.rtf b/writerfilter/qa/cppunittests/rtftok/data/fail/tablemanager-7.rtf
new file mode 100644
index 0000000..df41b1f
Binary files /dev/null and b/writerfilter/qa/cppunittests/rtftok/data/fail/tablemanager-7.rtf differ
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index f5c3476..bc05546 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -835,7 +835,7 @@ void DomainMapper_Impl::CheckUnregisteredFrameConversion( )
     TextAppendContext& rAppendContext = m_aTextAppendStack.top();
     // n#779642: ignore fly frame inside table as it could lead to messy situations
     if( rAppendContext.pLastParagraphProperties.get() && rAppendContext.pLastParagraphProperties->IsFrameMode()
-        && !getTableManager().isInTable() )
+        && hasTableManager() && !getTableManager().isInTable() )
     {
         try
         {
commit 00bcaeb1047ebd0762a38d7cc0384b542cbefe15
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Sat Sep 10 13:46:47 2016 +0100

    fftester: no table manager
    
    Change-Id: I033454670d1ee662bc80bc07578690155d97ce28
    Reviewed-on: https://gerrit.libreoffice.org/28807
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    (cherry picked from commit 951c8ee5a5fdf1d57570dd4c1134a88ce7c22e22)

diff --git a/writerfilter/qa/cppunittests/rtftok/data/fail/tablemanager-6.rtf b/writerfilter/qa/cppunittests/rtftok/data/fail/tablemanager-6.rtf
new file mode 100644
index 0000000..67a0ea1
Binary files /dev/null and b/writerfilter/qa/cppunittests/rtftok/data/fail/tablemanager-6.rtf differ
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index a819c53..f5c3476 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -1226,7 +1226,7 @@ void DomainMapper_Impl::appendTextPortion( const OUString& rString, PropertyMapP
     if( pPropertyMap == m_pTopContext && !deferredCharacterProperties.empty() && (GetTopContextType() == CONTEXT_CHARACTER) )
         processDeferredCharacterProperties();
     uno::Reference< text::XTextAppend >  xTextAppend = m_aTextAppendStack.top().xTextAppend;
-    if(xTextAppend.is() && ! getTableManager( ).isIgnore())
+    if (xTextAppend.is() && hasTableManager() && !getTableManager().isIgnore())
     {
         try
         {
commit 43dc3d6f2b141765d157b97ff30f1eccc1040675
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Fri Sep 2 21:12:43 2016 +0100

    fftester: apparent wrong property tested for existence
    
    Change-Id: I5d208bb2a85d7aa4eea9b1c950eeb6f35493f759
    (cherry picked from commit a42f4aaba352a4d33ce77898e7b7b7bc0c10f1f8)
    Reviewed-on: https://gerrit.libreoffice.org/28631
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Michael Stahl <mstahl at redhat.com>
    (cherry picked from commit ea8be52737f74edb89eb459bcef6d2d697ea48e4)

diff --git a/writerfilter/qa/cppunittests/rtftok/data/fail/propheight-1.rtf b/writerfilter/qa/cppunittests/rtftok/data/fail/propheight-1.rtf
new file mode 100644
index 0000000..130ff3f
Binary files /dev/null and b/writerfilter/qa/cppunittests/rtftok/data/fail/propheight-1.rtf differ
diff --git a/writerfilter/source/dmapper/PropertyMap.cxx b/writerfilter/source/dmapper/PropertyMap.cxx
index d2e1b41..c7e9250 100644
--- a/writerfilter/source/dmapper/PropertyMap.cxx
+++ b/writerfilter/source/dmapper/PropertyMap.cxx
@@ -1231,7 +1231,7 @@ void SectionPropertyMap::CloseSectionGroup( DomainMapper_Impl& rDM_Impl )
         if( pEntry.get( ) )
         {
             boost::optional<PropertyMap::Property> pPropHeight = pEntry->pProperties->getProperty(PROP_CHAR_HEIGHT_ASIAN);
-            if(pProp)
+            if (pPropHeight)
             {
                 double fHeight = 0;
                 if( pPropHeight->second >>= fHeight )
commit e0a501e2acb6e29d90c824a86dc6235f6457cff3
Author: Michael Stahl <mstahl at redhat.com>
Date:   Wed Aug 24 14:46:44 2016 +0200

    libpng: upgrade to release 1.5.27
    
    Reviewed-on: https://gerrit.libreoffice.org/28364
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Michael Stahl <mstahl at redhat.com>
    (cherry picked from commit 1efbdfcffff97ec0834274d13abe0f0d318b5f3c)
    Reviewed-on: https://gerrit.libreoffice.org/28367
    Reviewed-by: Christian Lohmaier <lohmaier+LibreOffice at googlemail.com>
    (cherry picked from commit f90be96ed400a5471d6c3a5cfa5087957803a9fe)
    
    Reviewed-on: https://gerrit.libreoffice.org/28553
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>
    (cherry picked from commit c663ffa4a1a5d2ad15a5b114c15ea5484b1dbb9c)
    
    Conflicts:
    	download.lst
    
    Change-Id: I5528522d866262655eadcfcf09c038e0c6097bb9

diff --git a/download.lst b/download.lst
index e356b61..711b67f 100644
--- a/download.lst
+++ b/download.lst
@@ -123,8 +123,8 @@ export ORCUS_TARBALL := 7681383be6ce489d84c1c74f4e7f9643-liborcus-0.7.0.tar.bz2
 export PAGEMAKER_MD5SUM := 795cc7a59ace4db2b12586971d668671
 export PAGEMAKER_TARBALL := libpagemaker-0.0.2.tar.bz2
 export PIXMAN_TARBALL := c63f411b3ad147db2bcce1bf262a0e02-pixman-0.24.4.tar.bz2
-export PNG_MD5SUM := 6652e428d1d3fc3c6cb1362159b1cf3b
-export PNG_TARBALL := libpng-1.5.24.tar.gz
+export PNG_MD5SUM := 046cb01d627917c492bb65d9399e14f8
+export PNG_TARBALL := libpng-1.5.27.tar.gz
 export POPPLER_MD5SUM := 35c0660065d023365e9854c13e289d12
 export POPPLER_TARBALL := poppler-0.26.4.tar.gz
 export POSTGRESQL_TARBALL := c0b4799ea9850eae3ead14f0a60e9418-postgresql-9.2.1.tar.bz2
commit 468d9e142b40c4bb9db130e92051234f6b9c9979
Author: Michael Stahl <mstahl at redhat.com>
Date:   Mon Aug 29 13:07:03 2016 +0200

    lcms2: Out-of-bounds read in Type_MLU_Read() (rhbz#1367357)
    
    Change-Id: I9c5a442125476412435ebefea29ad1b166faab8a
    (cherry picked from commit da7d3f708d0619fdb17128ffbaa430becb79121f)
    Reviewed-on: https://gerrit.libreoffice.org/28552
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>
    (cherry picked from commit 94497dcf3006a22111f32c7335771b7e97cc9a33)

diff --git a/external/lcms2/0001-Added-an-extra-check-to-MLU-bounds.patch.1 b/external/lcms2/0001-Added-an-extra-check-to-MLU-bounds.patch.1
new file mode 100644
index 0000000..913f828
--- /dev/null
+++ b/external/lcms2/0001-Added-an-extra-check-to-MLU-bounds.patch.1
@@ -0,0 +1,25 @@
+From 5ca71a7bc18b6897ab21d815d15e218e204581e2 Mon Sep 17 00:00:00 2001
+From: Marti <marti.maria at tktbrainpower.com>
+Date: Mon, 15 Aug 2016 23:31:39 +0200
+Subject: [PATCH] Added an extra check to MLU bounds
+
+Thanks to Ibrahim el-sayed for spotting the bug
+---
+ src/cmstypes.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/cmstypes.c b/src/cmstypes.c
+index cb61860..c7328b9 100644
+--- a/src/cmstypes.c
++++ b/src/cmstypes.c
+@@ -1460,6 +1460,7 @@ void *Type_MLU_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsU
+ 
+         // Check for overflow
+         if (Offset < (SizeOfHeader + 8)) goto Error;
++        if ((Offset + Len) > SizeOfTag + 8) goto Error;
+ 
+         // True begin of the string
+         BeginOfThisString = Offset - SizeOfHeader - 8;
+-- 
+2.7.4
+
diff --git a/external/lcms2/UnpackedTarball_lcms2.mk b/external/lcms2/UnpackedTarball_lcms2.mk
index 6490110..db22934 100644
--- a/external/lcms2/UnpackedTarball_lcms2.mk
+++ b/external/lcms2/UnpackedTarball_lcms2.mk
@@ -19,6 +19,7 @@ $(eval $(call gb_UnpackedTarball_add_patches,lcms2,\
 	external/lcms2/lcms2-vc2013-project.patch \
 	external/lcms2/lcms2-config-guess.patch.0 \
 	external/lcms2/ubsan.patch.0 \
+	external/lcms2/0001-Added-an-extra-check-to-MLU-bounds.patch.1 \
 ))
 
 # vim: set noet sw=4 ts=4:
commit 31cfffb65c6be4a30bfa6e781e39c6db8030121b
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Sat Aug 27 14:16:22 2016 +0100

    fftester: empty tabbox protection
    
    Change-Id: I56b0845205d6968355b3327721bf9ca0930903e1
    (cherry picked from commit b3533883fd0397dbe9110145d62ef35944b64f69)
    Reviewed-on: https://gerrit.libreoffice.org/28425
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: David Tardon <dtardon at redhat.com>
    (cherry picked from commit e3cc5adb5999c51aa732befdfbe328c8e885fb22)

diff --git a/sw/qa/core/data/rtf/pass/tabbox-1.rtf b/sw/qa/core/data/rtf/pass/tabbox-1.rtf
new file mode 100644
index 0000000..19d3851
Binary files /dev/null and b/sw/qa/core/data/rtf/pass/tabbox-1.rtf differ
diff --git a/sw/source/core/docnode/ndtbl.cxx b/sw/source/core/docnode/ndtbl.cxx
index 0b9b1dc..31cde2d 100644
--- a/sw/source/core/docnode/ndtbl.cxx
+++ b/sw/source/core/docnode/ndtbl.cxx
@@ -1329,6 +1329,8 @@ lcl_SetTableBoxWidths2(SwTable & rTable, size_t const nMaxBoxes,
     for (size_t nTmpLine = 0; nTmpLine < rLines.size(); ++nTmpLine)
     {
         SwTableBoxes & rBoxes = rLines[nTmpLine]->GetTabBoxes();
+        if (rBoxes.empty())
+            continue;
         size_t const nMissing = nMaxBoxes - rBoxes.size();
         if (nMissing)
         {
commit 5f92426a9a554be1274e8bf06a61523df987d1bd
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Sat Aug 27 13:31:14 2016 +0100

    fftester: topcontext check
    
    Change-Id: I2045ce82a1d536ab566e6a1218bea9c6a6696024
    (cherry picked from commit a3d74764d89e396dd7e8e7812ea64a062d6aed85)
    Reviewed-on: https://gerrit.libreoffice.org/28422
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: David Tardon <dtardon at redhat.com>
    (cherry picked from commit b85ce724410ef0a54f63cf68445e0f59641d5ab4)

diff --git a/writerfilter/qa/cppunittests/rtftok/data/fail/topcontext-2.rtf b/writerfilter/qa/cppunittests/rtftok/data/fail/topcontext-2.rtf
new file mode 100644
index 0000000..c0bd269
Binary files /dev/null and b/writerfilter/qa/cppunittests/rtftok/data/fail/topcontext-2.rtf differ
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index 3c45bd6..bd1526e 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -261,7 +261,8 @@ void DomainMapper::lcl_attribute(Id nName, Value & val)
             m_pImpl->SetSymbolFont(sStringValue);
         break;
         case NS_ooxml::LN_CT_Underline_val:
-            handleUnderlineType(nIntValue, m_pImpl->GetTopContext());
+            if (m_pImpl->GetTopContext())
+                handleUnderlineType(nIntValue, m_pImpl->GetTopContext());
             break;
         case NS_ooxml::LN_CT_Color_val:
             if (m_pImpl->GetTopContext())
commit d200a0f8d05aec7b9aa8f5a674db124ded1a9d1d
Author: anwilli5 <anwilli5 at ncsu.edu>
Date:   Sun Jun 5 23:06:05 2016 -0400

    tdf#96607 'Save as' doesn't update global auto-recovery state
    
    The auto-recovery service maintains a list of structures (one for each open
    document) containing information needed to carry out the auto-save
    functionality. One such piece of information is the location of the backup
    file, stored in a struct member named 'OldTempURL'.  At every auto-save
    interval, this list is iterated through and a function (implts_saveOneDoc)
    is called during each iteration to save the current state of the associated
    document.
    
    The algorithm works as follows:
     1. A new backup file URL is chosen so as not to conflict with any already
        existing backup files in the backup directory.  This URL is based on the
        file name and incorporates a number (starting at 0) that is incremented
        until a name is chosen that doesn't conflict.
    
     2. The document is saved to this new backup file URL
    
     3. The previous backup file (indicated by its structure's 'OldTempURL') is
        deleted
    
     4. The new backup file URL is stored (in its structure's 'OldTempURL') for the
        next time the file needs to be saved.
    
    Assuming you start with a new Writer doc and then make some changes, when it is
    time to auto-save, the backup file name 'untitled_0.odt' (excluding path) will
    be selected, the latest state of the open file will be written to that backup
    file, and the full URL for the backup file will be saved into the struct
    'OldTempURL' member.
    
    The next time changes are made and an auto-save occurs, this algorithm will
    result in the name 'untitled_1.odt' being selected, the file contents saved
    into this new file, 'untitled_0.odt' being deleted, and the full URL for the
    new backup file being saved in 'OldTempURL'.
    
    The third time through results in 'untitled_0.odt' being selected (since this
    file doesn't exist on disk), and subsequent iterations of auto-saving cause
    the backup file name to alternate between the two aforementioned.
    
    The problem occurs during a 'Save as' operation. When this happens, the backup
    file is deleted (which is fine - it was just saved, and the next auto-save will
    back it up) but 'OldTempURL' is not properly reset (see below for more info.)
    During the next auto-save, 'untitled_0.odt' will be selected for the new backup
    file name (since no file exists by this name), and one of two things will
    happen (based on how many auto-saves have occurred):
    
     1. 'OldTempURL' points to 'untitled_1.odt', and the algorithm above continues
        to work correctly (at least in that it continues to backup file contents.)
    
     2. 'OldTempURL' points to 'untitled_0.odt', the name chosen for the new backup
        file.  In this case, the document contents will be saved to this file
        (step 2) but then the file will be deleted (step 3).  'OldTempURL' will
        maintain this URL from then on out, causing this case to be hit for all
        future auto-save intervals.
    
    So, 50% of the time (30 minutes out of every hour) auto-save will stop backing
    up file contents on a 'Save as'.
    
    The function that handles the 'Save as' case (implts_markDocumentAsSaved)
    clears 'OldTempURL' and sets other relavent struct members for a local variable
    copy of the global struct, but doesn't copy them back. :(  These changes are
    effectively lost when the function returns.
    
    There are several other cases where this appears to be happening as well, but
    more work is needed to determine whether this is actually the case:
     - implts_prepareSessionShutdown
     - implts_saveDocs, handling the 'dangerousDocs' and in a few other places
     - implts_openDocs
     - implts_resetHandleStates
    
    Also, there is some JUnitTest code for auto-save, but it is currently disabled
    (and fails to run successfully.) It'd be great to get these working again, or
    to just write python equivalents. Implementing this would like take me a while,
    though, so for now I just tested manually to ensure that this fixes the issue.
    
    When I have some more time I'd like to work more on this, but I wanted to send
    this patch in for now to address bug #96607.
    
    This may also address bug #99890, since some of the struct members that don't
    make it into the global state relate to the file name.  I haven't explicitly
    tested this case, though.
    
    Change-Id: Ic702d6f78e60c7cf828a1564ccca118dd45d152b
    Reviewed-on: https://gerrit.libreoffice.org/25948
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: jan iversen <jani at documentfoundation.org>
    Reviewed-on: https://gerrit.libreoffice.org/27921
    Reviewed-by: Eike Rathke <erack at redhat.com>
    (cherry picked from commit e3759a3154de534a5edfd69f7face5b5c29c1ea9)

diff --git a/framework/source/services/autorecovery.cxx b/framework/source/services/autorecovery.cxx
index b05fdc3..e70b3f1 100644
--- a/framework/source/services/autorecovery.cxx
+++ b/framework/source/services/autorecovery.cxx
@@ -2694,11 +2694,22 @@ void AutoRecovery::implts_markDocumentAsSaved(const css::uno::Reference< css::fr
         return;
     aInfo = *pIt;
 
+    /* Since the document has been saved, update its entry in the document
+     * cache. We essentially reset the state of the document from an
+     * autorecovery perspective, updating things like the filename (which
+     * would change in the case of a 'Save as' operation) and the associated
+     * backup file URL.  */
+
     aInfo.DocumentState = AutoRecovery::E_UNKNOWN;
     // TODO replace getLocation() with getURL() ... it's a workaround currently only!
     css::uno::Reference< css::frame::XStorable > xDoc(aInfo.Document, css::uno::UNO_QUERY);
     aInfo.OrgURL = xDoc->getLocation();
 
+    /* Save off the backup file URLs and then clear them. NOTE - it is
+     * important that we clear them - otherwise, we could enter a state
+     * where pIt->OldTempURL == pIt->NewTempURL and our backup algorithm
+     * in implts_saveOneDoc will write to that URL and then delete the file
+     * at that URL (bug #96607) */
     sRemoveURL1 = aInfo.OldTempURL;
     sRemoveURL2 = aInfo.NewTempURL;
     aInfo.OldTempURL.clear();
@@ -2719,6 +2730,8 @@ void AutoRecovery::implts_markDocumentAsSaved(const css::uno::Reference< css::fr
 
     aInfo.UsedForSaving = false;
 
+    *pIt = aInfo;
+
     } /* SAFE */
 
     implts_flushConfigItem(aInfo);
commit 588d240db3c184ace9eac53a736ae2f5716a7eba
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Sun Aug 7 16:58:22 2016 +0100

    fftester: guard against empty table manager stack
    
    (cherry picked from commit 145e2dfc4501cb3fa01a1771cb6829b5945df4a6)
    
    Change-Id: Ibb4cadb58aa17eacfc9741f7f13c780be347cd8b
    Reviewed-on: https://gerrit.libreoffice.org/27938
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: David Tardon <dtardon at redhat.com>
    (cherry picked from commit 329f8d8b96d8abdaed31b8a5bcc417604d388931)

diff --git a/writerfilter/qa/cppunittests/rtftok/data/fail/tablemanager-5.rtf b/writerfilter/qa/cppunittests/rtftok/data/fail/tablemanager-5.rtf
new file mode 100644
index 0000000..a03be13
Binary files /dev/null and b/writerfilter/qa/cppunittests/rtftok/data/fail/tablemanager-5.rtf differ
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 59c72ec..a819c53 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -1302,7 +1302,6 @@ void DomainMapper_Impl::appendTextPortion( const OUString& rString, PropertyMapP
     }
 }
 
-
 void DomainMapper_Impl::appendTextContent(
     const uno::Reference< text::XTextContent >& xContent,
     const uno::Sequence< beans::PropertyValue >& xPropertyValues
@@ -1313,7 +1312,7 @@ void DomainMapper_Impl::appendTextContent(
         return;
     uno::Reference< text::XTextAppendAndConvert >  xTextAppendAndConvert( m_aTextAppendStack.top().xTextAppend, uno::UNO_QUERY );
     OSL_ENSURE( xTextAppendAndConvert.is(), "trying to append a text content without XTextAppendAndConvert" );
-    if(xTextAppendAndConvert.is() && ! getTableManager( ).isIgnore())
+    if (xTextAppendAndConvert.is() && hasTableManager() && !getTableManager().isIgnore())
     {
         try
         {
@@ -1331,8 +1330,6 @@ void DomainMapper_Impl::appendTextContent(
     }
 }
 
-
-
 void DomainMapper_Impl::appendOLE( const OUString& rStreamName, OLEHandlerPtr pOLEHandler )
 {
     static const char sEmbeddedService[] = "com.sun.star.text.TextEmbeddedObject";
commit ce9d2236f57cb37bb7a8fdbb62583784e12f2efd
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Fri Jul 29 08:48:22 2016 +0100

    fftester: null DestinationText
    
    (cherry picked from commit 0dd22165346f4296718656d17ae98ebbfe563719)
    
    Change-Id: Icdd71733c4e9f4b36e6e957e4dea772087890faa
    Reviewed-on: https://gerrit.libreoffice.org/27670
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    (cherry picked from commit 51ea0875a7d3c6cd794cdec885b610efe635544c)

diff --git a/writerfilter/qa/cppunittests/rtftok/data/fail/destinationtest-1.rtf b/writerfilter/qa/cppunittests/rtftok/data/fail/destinationtest-1.rtf
new file mode 100644
index 0000000..63465b0
Binary files /dev/null and b/writerfilter/qa/cppunittests/rtftok/data/fail/destinationtest-1.rtf differ
diff --git a/writerfilter/qa/cppunittests/rtftok/data/fail/destinationtest-2.rtf b/writerfilter/qa/cppunittests/rtftok/data/fail/destinationtest-2.rtf
new file mode 100644
index 0000000..f0152b0
Binary files /dev/null and b/writerfilter/qa/cppunittests/rtftok/data/fail/destinationtest-2.rtf differ
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
index e493c28..f01ebe7 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
@@ -187,26 +187,27 @@ static util::DateTime lcl_getDateTime(RTFParserState& aState)
                           aState.nDay, aState.nMonth, aState.nYear, false);
 }
 
-static void lcl_DestinationToMath(OUStringBuffer& rDestinationText, oox::formulaimport::XmlStreamBuilder& rMathBuffer, bool& rMathNor)
+static void lcl_DestinationToMath(OUStringBuffer* pDestinationText, oox::formulaimport::XmlStreamBuilder& rMathBuffer, bool& rMathNor)
 {
-    OUString aStr = rDestinationText.makeStringAndClear();
-    if (!aStr.isEmpty())
-    {
-        rMathBuffer.appendOpeningTag(M_TOKEN(r));
-        if (rMathNor)
-        {
-            rMathBuffer.appendOpeningTag(M_TOKEN(rPr));
-            // Same as M_TOKEN(lit)
-            rMathBuffer.appendOpeningTag(M_TOKEN(nor));
-            rMathBuffer.appendClosingTag(M_TOKEN(nor));
-            rMathBuffer.appendClosingTag(M_TOKEN(rPr));
-            rMathNor = false;
-        }
-        rMathBuffer.appendOpeningTag(M_TOKEN(t));
-        rMathBuffer.appendCharacters(aStr);
-        rMathBuffer.appendClosingTag(M_TOKEN(t));
-        rMathBuffer.appendClosingTag(M_TOKEN(r));
-    }
+    if (!pDestinationText)
+        return;
+    OUString aStr = pDestinationText->makeStringAndClear();
+    if (aStr.isEmpty())
+        return;
+    rMathBuffer.appendOpeningTag(M_TOKEN(r));
+    if (rMathNor)
+    {
+        rMathBuffer.appendOpeningTag(M_TOKEN(rPr));
+        // Same as M_TOKEN(lit)
+        rMathBuffer.appendOpeningTag(M_TOKEN(nor));
+        rMathBuffer.appendClosingTag(M_TOKEN(nor));
+        rMathBuffer.appendClosingTag(M_TOKEN(rPr));
+        rMathNor = false;
+    }
+    rMathBuffer.appendOpeningTag(M_TOKEN(t));
+    rMathBuffer.appendCharacters(aStr);
+    rMathBuffer.appendClosingTag(M_TOKEN(t));
+    rMathBuffer.appendClosingTag(M_TOKEN(r));
 }
 
 RTFDocumentImpl::RTFDocumentImpl(uno::Reference<uno::XComponentContext> const& xContext,
@@ -1186,7 +1187,7 @@ void RTFDocumentImpl::text(OUString& rString)
             rString = rString.copy(0, rString.getLength() - 1);
             bEnd = true;
         }
-        m_aStates.top().pDestinationText->append(rString);
+        m_aStates.top().appendDestinationText(rString);
         if (bEnd)
         {
             // always clear, necessary in case of group-less fonttable
@@ -1290,7 +1291,7 @@ void RTFDocumentImpl::text(OUString& rString)
     case Destination::MGROW:
     case Destination::INDEXENTRY:
     case Destination::TOCENTRY:
-        m_aStates.top().pDestinationText->append(rString);
+        m_aStates.top().appendDestinationText(rString);
         break;
     default:
         bRet = false;
@@ -1319,7 +1320,7 @@ void RTFDocumentImpl::text(OUString& rString)
     // Don't return earlier, a bookmark start has to be in a paragraph group.
     if (m_aStates.top().eDestination == Destination::BOOKMARKSTART)
     {
-        m_aStates.top().pDestinationText->append(rString);
+        m_aStates.top().appendDestinationText(rString);
         return;
     }
 
@@ -4987,7 +4988,7 @@ RTFError RTFDocumentImpl::pushState()
         m_aStates.top().eRunType = RTFParserState::LOCH;
 
         if (m_aStates.top().eDestination == Destination::MR)
-            lcl_DestinationToMath(*m_aStates.top().pDestinationText, m_aMathBuffer, m_bMathNor);
+            lcl_DestinationToMath(m_aStates.top().pDestinationText, m_aMathBuffer, m_bMathNor);
         m_aStates.push(m_aStates.top());
     }
     m_aStates.top().aDestinationText.setLength(0); // was copied: always reset!
@@ -5657,7 +5658,7 @@ RTFError RTFDocumentImpl::popState()
     }
     break;
     case Destination::MR:
-        lcl_DestinationToMath(*m_aStates.top().pDestinationText, m_aMathBuffer, m_bMathNor);
+        lcl_DestinationToMath(m_aStates.top().pDestinationText, m_aMathBuffer, m_bMathNor);
         break;
     case Destination::MF:
         m_aMathBuffer.appendClosingTag(M_TOKEN(f));
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.hxx b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
index 5d1dbc4..9e5edec 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.hxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
@@ -280,6 +280,12 @@ public:
     /// point to the buffer of the current destination
     OUStringBuffer* pDestinationText;
 
+    void appendDestinationText(const OUString &rString)
+    {
+        if (pDestinationText)
+            pDestinationText->append(rString);
+    }
+
     /// Index of the current style.
     int nCurrentStyleIndex;
     /// Index of the current character style.
commit ceaf81fa6ee42bb3fe830c6d5c910b19810208e1
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Tue Aug 2 16:05:53 2016 +0100

    fftester: guard against no drawing object property set
    
    (cherry picked from commit db686815b41c52598f0952613ff8c6be34b2f0e0)
    
    Change-Id: I51736459f9f098d9d793bff3b9a1a403962e099d
    Reviewed-on: https://gerrit.libreoffice.org/27801
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    (cherry picked from commit f9b830d7cd47c61cff3162fd396d81f29d205ce9)

diff --git a/writerfilter/qa/cppunittests/rtftok/data/fail/nopropertyset-1.rtf b/writerfilter/qa/cppunittests/rtftok/data/fail/nopropertyset-1.rtf
new file mode 100644
index 0000000..59c3630
Binary files /dev/null and b/writerfilter/qa/cppunittests/rtftok/data/fail/nopropertyset-1.rtf differ
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
index 995772a..e493c28 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
@@ -4709,7 +4709,7 @@ RTFError RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam)
         {
             rDrawingObject.aPolyLinePoints.back().Y = convertTwipToMm100(nParam);
             rDrawingObject.nPolyLineCount--;
-            if (rDrawingObject.nPolyLineCount == 0)
+            if (rDrawingObject.nPolyLineCount == 0 && rDrawingObject.xPropertySet.is())
             {
                 uno::Sequence< uno::Sequence<awt::Point> >aPointSequenceSequence =
                 {
commit 9f44819fcba2c94961db35d4f2c8be9894db4adf
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Sun Jul 31 19:58:18 2016 +0100

    fftester: another table manager stack checks
    
    and a m_xTextFactory check too
    
    Change-Id: I9352410c42048b4dd7d6dbc3514351ab8f16790b
    (cherry picked from commit 8a6b2fb5b94de43316ab3ea95ff07cf5f46b6134)
    Reviewed-on: https://gerrit.libreoffice.org/27760
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    (cherry picked from commit fbed48db0b09cfed8070d7644b0922c79d3d7512)

diff --git a/writerfilter/qa/cppunittests/rtftok/data/pass/tablemanager-4.rtf b/writerfilter/qa/cppunittests/rtftok/data/pass/tablemanager-4.rtf
new file mode 100644
index 0000000..28093f2
Binary files /dev/null and b/writerfilter/qa/cppunittests/rtftok/data/pass/tablemanager-4.rtf differ
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 7ba7622..59c72ec 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -1041,7 +1041,7 @@ void DomainMapper_Impl::finishParagraph( PropertyMapPtr pPropertyMap )
     TagLogger::getInstance().attribute("isTextAppend", sal_uInt32(xTextAppend.is()));
 #endif
 
-    if (xTextAppend.is() && pParaContext != nullptr && !getTableManager().isIgnore())
+    if (xTextAppend.is() && pParaContext && hasTableManager() && !getTableManager().isIgnore())
     {
         try
         {
@@ -4143,7 +4143,7 @@ void DomainMapper_Impl::CloseFieldCommand()
                  */
                 OUString aCode( pContext->GetCommand().trim() );
                 // Don't waste resources on wrapping shapes inside a fieldmark.
-                if (aCode != "SHAPE")
+                if (aCode != "SHAPE" && m_xTextFactory.is())
                 {
                     xFieldInterface = m_xTextFactory->createInstance("com.sun.star.text.Fieldmark");
                     const uno::Reference<text::XTextContent> xTextContent(xFieldInterface, uno::UNO_QUERY_THROW);
commit 372d5b4dc89b4302c481522eb20ab7dc5f563a8d
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Thu Jul 28 13:58:33 2016 +0100

    fftester: throw on empty stack access
    
    rather than spend the rest of my life protecting each one
    
    Change-Id: I181df33b052a0303f072ce0252d98562231569e2
    (cherry picked from commit 2710211eb2333cafdb894742a8fa73fb02dc513b)
    
    fftester: empty states stack
    
    Change-Id: I05dfffced9a8677650a46b43f65a29e9b21c5524
    (cherry picked from commit 5de2d02806669812d43e7f23db58ab7a16373ce6)
    
    Related: tdf#75757 remove inheritance from std::deque
    
    Change-Id: Ia50ea146052c2014ea16474186e2d15ce93581c1
    (cherry picked from commit 7a887df4db129ac5222fd4068173b5a06d107a59)
    Reviewed-on: https://gerrit.libreoffice.org/27640
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Markus Mohrhard <markus.mohrhard at googlemail.com>
    (cherry picked from commit 3e0fad77595438e1d36b94bfd6c17d8de8f8ceb0)

diff --git a/writerfilter/qa/cppunittests/rtftok/data/fail/popstate-1.rtf b/writerfilter/qa/cppunittests/rtftok/data/fail/popstate-1.rtf
new file mode 100644
index 0000000..0418917
Binary files /dev/null and b/writerfilter/qa/cppunittests/rtftok/data/fail/popstate-1.rtf differ
diff --git a/writerfilter/qa/cppunittests/rtftok/data/fail/popstate-2.rtf b/writerfilter/qa/cppunittests/rtftok/data/fail/popstate-2.rtf
new file mode 100644
index 0000000..273bb13
--- /dev/null
+++ b/writerfilter/qa/cppunittests/rtftok/data/fail/popstate-2.rtf
@@ -0,0 +1 @@
+\\rttt\noTidqtpúúúúúúëúúúúúúúúúúúúúúúúdôp{\"pb18}\€p{\"ptxtbr }
diff --git a/writerfilter/qa/cppunittests/rtftok/testrtftok.cxx b/writerfilter/qa/cppunittests/rtftok/testrtftok.cxx
index dd9e474..e6c3cc5 100644
--- a/writerfilter/qa/cppunittests/rtftok/testrtftok.cxx
+++ b/writerfilter/qa/cppunittests/rtftok/testrtftok.cxx
@@ -74,6 +74,10 @@ bool RtfTest::load(const OUString&,
         }
         throw;
     }
+    catch (const std::exception&)
+    {
+        return false;
+    }
 }
 
 void RtfTest::test()
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.hxx b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
index 823ccc2..5d1dbc4 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.hxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
@@ -302,19 +302,42 @@ public:
 };
 
 /// An RTF stack is similar to std::stack, except that it has an operator[].
-struct RTFStack : public std::deque<RTFParserState>
+struct RTFStack
 {
+private:
+    std::deque<RTFParserState> m_Impl;
+public:
     RTFParserState& top()
     {
-        return back();
+        if (m_Impl.empty())
+            throw std::out_of_range("empty rtf state stack");
+        return m_Impl.back();
     }
     void pop()
     {
-        return pop_back();
+        if (m_Impl.empty())
+            throw std::out_of_range("empty rtf state stack");
+        return m_Impl.pop_back();
     }
     void push(RTFParserState const& rState)
     {
-        return push_back(rState);
+        return m_Impl.push_back(rState);
+    }
+    bool empty() const
+    {
+        return m_Impl.empty();
+    }
+    size_t size() const
+    {
+        return m_Impl.size();
+    }
+    const RTFParserState& operator[](size_t nIndex) const
+    {
+        return m_Impl[nIndex];
+    }
+    RTFParserState& operator[](size_t nIndex)
+    {
+        return m_Impl[nIndex];
     }
 };
 
commit 6d5e0d3241b92bf0e6005a333f4a1c6e8c312198
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Thu Jul 28 13:49:13 2016 +0100

    fftester: empty table manager stack
    
    Change-Id: Ia7f7ace8130d5dfe290207e0cd3d2e6a43b8ab46
    (cherry picked from commit df9414084b46c1712dc7151f50023438c62301e2)
    Reviewed-on: https://gerrit.libreoffice.org/27633
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    (cherry picked from commit 3f320c21d27c409aa086d044502acf42f60a1a36)

diff --git a/writerfilter/qa/cppunittests/rtftok/data/pass/tablemanager-1.rtf b/writerfilter/qa/cppunittests/rtftok/data/pass/tablemanager-1.rtf
new file mode 100644
index 0000000..5b34e7f
Binary files /dev/null and b/writerfilter/qa/cppunittests/rtftok/data/pass/tablemanager-1.rtf differ
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index 67b40c0..3c45bd6 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -3068,6 +3068,9 @@ void DomainMapper::lcl_utext(const sal_uInt8 * data_, size_t len)
         return;
     }
 
+    if (!m_pImpl->hasTableManager())
+        return;
+
     try
     {
         m_pImpl->getTableManager().utext(data_, len);
commit 68f5233f91d5c3ea8d13950e25644cfec742e0a1
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Fri Jul 22 12:59:13 2016 +0100

    crashtesting: fix tdf92993-1.docx failure
    
    Change-Id: I76f09a09fd6c3b114ba74737d4a1ba5dad0fd28f
    (cherry picked from commit 5e46e382694587e88ecdebc7fa57e90fbaca7a76)
    Reviewed-on: https://gerrit.libreoffice.org/27436
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    (cherry picked from commit e213a7cfe79f594065b6d64114749c5f49f2380c)

diff --git a/i18npool/qa/cppunit/test_breakiterator.cxx b/i18npool/qa/cppunit/test_breakiterator.cxx
index be4dd6d..69d1d87 100644
--- a/i18npool/qa/cppunit/test_breakiterator.cxx
+++ b/i18npool/qa/cppunit/test_breakiterator.cxx
@@ -142,6 +142,22 @@ void TestBreakIterator::testLineBreaking()
             CPPUNIT_ASSERT_MESSAGE("Expected a break at the start of the line, not at ]", aResult.breakIndex == 0);
         }
     }
+
+    //this is an example sequence from tdf92993-1.docx caught by the load crashtesting
+    {
+        const sal_Unicode WEIRD1[] = { 0xd83c, 0xdf56, 0xd83c, 0xdf57, 0xd83c, 0xdf46,
+                                       0xd83c, 0xdf64, 0x2668, 0xfe0f, 0xd83c, 0xdfc6};
+
+        OUString aTest(WEIRD1, SAL_N_ELEMENTS(WEIRD1));
+
+        aLocale.Language = "en";
+        aLocale.Country = "US";
+
+        {
+            //This must not assert/crash
+            (void)m_xBreak->getLineBreak(aTest, 0, aLocale, 0, aHyphOptions, aUserOptions);
+        }
+    }
 }
 
 //See https://bugs.libreoffice.org/show_bug.cgi?id=49629
diff --git a/i18npool/source/breakiterator/breakiterator_unicode.cxx b/i18npool/source/breakiterator/breakiterator_unicode.cxx
index 126114c..3353921 100644
--- a/i18npool/source/breakiterator/breakiterator_unicode.cxx
+++ b/i18npool/source/breakiterator/breakiterator_unicode.cxx
@@ -425,7 +425,7 @@ LineBreakResults SAL_CALL BreakIterator_Unicode::getLineBreak(
         GlueSpace=false;
         if (lbr.breakType == BreakType::WORDBOUNDARY) {
             nStartPos = lbr.breakIndex;
-            if (Text[nStartPos--] == WJ)
+            if (nStartPos >= 0 && Text[nStartPos--] == WJ)
                 GlueSpace=true;
             while (nStartPos >= 0 &&
                     (u_isWhitespace(Text.iterateCodePoints(&nStartPos, 0)) || Text[nStartPos] == WJ)) {
commit bfd8bf7ad2aade2dbddd5391cd8e86382c90f38f
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Wed Jul 20 16:30:16 2016 +0100

    Resolves: tdf#98778 fix parsing of exponents
    
    regression from...
    
    commit 9e9f39d171cafa035d7b8e74187e25c3581cb89d
    Date:   Tue Mar 19 23:23:16 2013 +0100
    
        resolved rhbz#919020 Basic CDbl() and CSng() scan localized number
    
    Change-Id: I96535fd9bc9ec59d6e07739a3118c96eb2d8bd05
    Reviewed-on: https://gerrit.libreoffice.org/27342
    Reviewed-by: Eike Rathke <erack at redhat.com>
    Tested-by: Eike Rathke <erack at redhat.com>
    (cherry picked from commit 2aed0d49d7891b9360916b65771222810aeeac96)
    Reviewed-on: https://gerrit.libreoffice.org/27350
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/basic/source/sbx/sbxscan.cxx b/basic/source/sbx/sbxscan.cxx
index 6ba986d..d5e247b 100644
--- a/basic/source/sbx/sbxscan.cxx
+++ b/basic/source/sbx/sbxscan.cxx
@@ -160,6 +160,13 @@ SbxError ImpScan( const OUString& rWSrc, double& nVal, SbxDataType& rType,
                     eScanType = SbxDOUBLE;
                 aBuf[ p - pStart ] = 'E';
                 p++;
+                if (*p == '+')
+                    ++p;
+                else if (*p == '-')
+                {
+                    aBuf.append('-');
+                    ++p;
+                }
             }
             else
             {
commit 713efa809591c79bcd232bde3639a418e45ff258
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Mon Jul 18 10:42:02 2016 +0100

    protect against empty m_aTableManagers stack
    
    Change-Id: I29fecc5e0efb3b3d907f0c6505d42818fa464ffc
    (cherry picked from commit 9d76d9d9abb08788f2882612cfe6d0df6e19af39)
    Reviewed-on: https://gerrit.libreoffice.org/27281
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    (cherry picked from commit 808d72592aa6e9a9f9a8eddd4dada0fa9f14749c)

diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index 61ff534..67b40c0 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -1042,8 +1042,8 @@ void DomainMapper::lcl_attribute(Id nName, Value & val)
 
 void DomainMapper::lcl_sprm(Sprm & rSprm)
 {
-    if( !m_pImpl->getTableManager().sprm(rSprm))
-        sprmWithProps( rSprm, m_pImpl->GetTopContext() );
+    if (!m_pImpl->hasTableManager() || !m_pImpl->getTableManager().sprm(rSprm))
+        sprmWithProps(rSprm, m_pImpl->GetTopContext());
 }
 
 sal_Int32 lcl_getCurrentNumberingProperty(
@@ -2715,7 +2715,8 @@ void DomainMapper::lcl_endSectionGroup()
 
 void DomainMapper::lcl_startParagraphGroup()
 {
-    m_pImpl->getTableManager().startParagraphGroup();
+    if (m_pImpl->hasTableManager())
+        m_pImpl->getTableManager().startParagraphGroup();
     /*
      * Add new para properties only if paragraph is not split
      * or the top context is not of paragraph properties
@@ -2752,7 +2753,8 @@ void DomainMapper::lcl_startParagraphGroup()
 void DomainMapper::lcl_endParagraphGroup()
 {
     m_pImpl->PopProperties(CONTEXT_PARAGRAPH);
-    m_pImpl->getTableManager().endParagraphGroup();
+    if (m_pImpl->hasTableManager())
+       m_pImpl->getTableManager().endParagraphGroup();
     //frame conversion has to be executed after table conversion
     m_pImpl->ExecuteFrameConversion();
     m_pImpl->SetIsOutsideAParagraph(true);
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index a2add9d..7ba7622 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -267,11 +267,13 @@ DomainMapper_Impl::~DomainMapper_Impl()
     // Don't remove last paragraph when pasting, sw expects that empty paragraph.
     if (m_bIsNewDoc)
         RemoveLastParagraph();
-    getTableManager( ).endLevel();
-    popTableManager( );
+    if (hasTableManager())
+    {
+        getTableManager().endLevel();
+        popTableManager();
+    }
 }
 
-
 uno::Reference< container::XNameContainer >    DomainMapper_Impl::GetPageStyles()
 {
     if(!m_xPageStyles.is())
@@ -1039,7 +1041,7 @@ void DomainMapper_Impl::finishParagraph( PropertyMapPtr pPropertyMap )
     TagLogger::getInstance().attribute("isTextAppend", sal_uInt32(xTextAppend.is()));
 #endif
 
-    if (xTextAppend.is() && !getTableManager( ).isIgnore() && pParaContext != nullptr)
+    if (xTextAppend.is() && pParaContext != nullptr && !getTableManager().isIgnore())
     {
         try
         {
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index 0fa9ce7..c4840ce 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -693,6 +693,11 @@ public:
         const bool bStart,
         const sal_Int32 nAnnotationId );
 
+    bool hasTableManager() const
+    {
+        return !m_aTableManagers.empty();
+    }
+
     DomainMapperTableManager& getTableManager()
     {
         std::shared_ptr< DomainMapperTableManager > pMngr = m_aTableManagers.top();
@@ -713,8 +718,8 @@ public:
 
     void popTableManager( )
     {
-        if ( m_aTableManagers.size( ) > 0 )
-            m_aTableManagers.pop( );
+        if (hasTableManager())
+            m_aTableManagers.pop();
     }
 
     void SetLineNumbering( sal_Int32 nLnnMod, sal_uInt32 nLnc, sal_Int32 ndxaLnn );
commit 021d377c008b935f81b05e82a39926107a165f78
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Tue Jul 5 10:52:29 2016 +0100

    Resolves: tdf#100770 crash on loading specific docx
    
    use same safeguards as RemoveLastParagraph does
    
    Change-Id: I43ed4eb28f44654054fd266bc464840af7014fea
    (cherry picked from commit 000263f799d4aa9ad21e63f474def55438ce601e)
    Reviewed-on: https://gerrit.libreoffice.org/26944
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    (cherry picked from commit 57144fae2bd2296fe9a842ab87addf9dda5ff91a)

diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 2906e24..a2add9d 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -329,7 +329,14 @@ void DomainMapper_Impl::RemoveDummyParaForTableInSection()
     SectionPropertyMap* pSectionContext = dynamic_cast< SectionPropertyMap* >( pContext.get() );
     if (!pSectionContext)
         return;
-    uno::Reference< text::XTextCursor > xCursor = GetTopTextAppend()->createTextCursorByRange(pSectionContext->GetStartingRange());
+
+    if (m_aTextAppendStack.empty())
+        return;
+    uno::Reference< text::XTextAppend > xTextAppend = m_aTextAppendStack.top().xTextAppend;
+    if (!xTextAppend.is())
+        return;
+
+    uno::Reference< text::XTextCursor > xCursor = xTextAppend->createTextCursorByRange(pSectionContext->GetStartingRange());
 
     // Remove the extra NumPicBullets from the document,
     // which get attached to the first paragraph in the
@@ -368,7 +375,7 @@ void DomainMapper_Impl::RemoveLastParagraph( )
 {
     if (m_aTextAppendStack.empty())
         return;
-    uno::Reference< text::XTextAppend >  xTextAppend = m_aTextAppendStack.top().xTextAppend;
+    uno::Reference< text::XTextAppend > xTextAppend = m_aTextAppendStack.top().xTextAppend;
     if (!xTextAppend.is())
         return;
     try
commit 14a851562b8bc40b8477ea09c2bda8c14161b3cc
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Tue May 24 11:38:52 2016 +0100

    CVE-2016-0718 and CVE-2015-1283 expat woes
    
    Change-Id: I83691e616bf964db2cb1e708b57f65b92ea2697e
    Reviewed-on: https://gerrit.libreoffice.org/25401
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>
    (cherry picked from commit b33fb0a8a09c2c383b5ed7915da52742cd457fec)
    Reviewed-on: https://gerrit.libreoffice.org/25407
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    (cherry picked from commit a39d43b1c1e57b0bd5aa0c2f7da2f78da102735b)

diff --git a/external/expat/CVE-2015-1283-refix.patch.1 b/external/expat/CVE-2015-1283-refix.patch.1
new file mode 100644
index 0000000..f7d971d
--- /dev/null
+++ b/external/expat/CVE-2015-1283-refix.patch.1
@@ -0,0 +1,37 @@
+From 29a11774d8ebbafe8418b4a5ffb4cc1160b194a1 Mon Sep 17 00:00:00 2001
+From: Pascal Cuoq <cuoq at trust-in-soft.com>
+Date: Sun, 15 May 2016 09:05:46 +0200
+Subject: [PATCH] Avoid relying on undefined behavior in CVE-2015-1283 fix. It
+ does not really work: https://godbolt.org/g/Zl8gdF
+
+---
+ expat/lib/xmlparse.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/lib/xmlparse.c b/lib/xmlparse.c
+index 13e080d..cdb12ef 100644
+--- a/lib/xmlparse.c
++++ b/lib/xmlparse.c
+@@ -1693,7 +1693,8 @@ XML_GetBuffer(XML_Parser parser, int len)
+   }
+ 
+   if (len > bufferLim - bufferEnd) {
+-    int neededSize = len + (int)(bufferEnd - bufferPtr);
++    /* Do not invoke signed arithmetic overflow: */
++    int neededSize = (int) ((unsigned)len + (unsigned)(bufferEnd - bufferPtr));
+     if (neededSize < 0) {
+       errorCode = XML_ERROR_NO_MEMORY;
+       return NULL;
+@@ -1725,7 +1726,8 @@ XML_GetBuffer(XML_Parser parser, int len)
+       if (bufferSize == 0)
+         bufferSize = INIT_BUFFER_SIZE;
+       do {
+-        bufferSize *= 2;
++        /* Do not invoke signed arithmetic overflow: */
++        bufferSize = (int) (2U * (unsigned) bufferSize);
+       } while (bufferSize < neededSize && bufferSize > 0);
+       if (bufferSize <= 0) {
+         errorCode = XML_ERROR_NO_MEMORY;
+-- 
+2.8.2
+
diff --git a/external/expat/CVE-2016-0718-v2-2-1.patch.1 b/external/expat/CVE-2016-0718-v2-2-1.patch.1
new file mode 100644
index 0000000..a4a7963
--- /dev/null
+++ b/external/expat/CVE-2016-0718-v2-2-1.patch.1
@@ -0,0 +1,755 @@
+From cdfcb1b5c95e93b00ae9e9d25708b4a3bee72c15 Mon Sep 17 00:00:00 2001
+From: Sebastian Pipping <sebastian at pipping.org>
+Date: Mon, 2 May 2016 00:02:44 +0200
+Subject: [PATCH] Address CVE-2016-0718 (/patch/ version 2.2.1)
+
+* Out of bounds memory access when doing text conversion on malformed input
+* Integer overflow related to memory allocation
+
+Reported by Gustavo Grieco
+
+Patch credits go to
+* Christian Heimes
+* Karl Waclawek
+* Gustavo Grieco
+* Sebastian Pipping
+* Pascal Cuoq
+---
+ expat/lib/xmlparse.c    |  34 +++++++++-----
+ expat/lib/xmltok.c      | 115 +++++++++++++++++++++++++++++++++++-------------
+ expat/lib/xmltok.h      |  10 ++++-
+ expat/lib/xmltok_impl.c |  62 +++++++++++++-------------
+ 4 files changed, 146 insertions(+), 75 deletions(-)
+
+diff --git a/lib/xmlparse.c b/lib/xmlparse.c
+index e308c79..13e080d 100644
+--- a/lib/xmlparse.c
++++ b/lib/xmlparse.c
+@@ -2426,11 +2426,11 @@ doContent(XML_Parser parser,
+           for (;;) {
+             int bufSize;
+             int convLen;
+-            XmlConvert(enc,
++            const enum XML_Convert_Result convert_res = XmlConvert(enc,
+                        &fromPtr, rawNameEnd,
+                        (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
+             convLen = (int)(toPtr - (XML_Char *)tag->buf);
+-            if (fromPtr == rawNameEnd) {
++            if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) {
+               tag->name.strLen = convLen;
+               break;
+             }
+@@ -2651,11 +2651,11 @@ doContent(XML_Parser parser,
+           if (MUST_CONVERT(enc, s)) {
+             for (;;) {
+               ICHAR *dataPtr = (ICHAR *)dataBuf;
+-              XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
++              const enum XML_Convert_Result convert_res = XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
+               *eventEndPP = s;
+               charDataHandler(handlerArg, dataBuf,
+                               (int)(dataPtr - (ICHAR *)dataBuf));
+-              if (s == next)
++              if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
+                 break;
+               *eventPP = s;
+             }
+@@ -3261,11 +3261,11 @@ doCdataSection(XML_Parser parser,
+           if (MUST_CONVERT(enc, s)) {
+             for (;;) {
+               ICHAR *dataPtr = (ICHAR *)dataBuf;
+-              XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
++              const enum XML_Convert_Result convert_res = XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
+               *eventEndPP = next;
+               charDataHandler(handlerArg, dataBuf,
+                               (int)(dataPtr - (ICHAR *)dataBuf));
+-              if (s == next)
++              if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
+                 break;
+               *eventPP = s;
+             }
+@@ -5342,6 +5342,7 @@ reportDefault(XML_Parser parser, const ENCODING *enc,
+               const char *s, const char *end)
+ {
+   if (MUST_CONVERT(enc, s)) {
++    enum XML_Convert_Result convert_res;
+     const char **eventPP;
+     const char **eventEndPP;
+     if (enc == encoding) {
+@@ -5354,11 +5355,11 @@ reportDefault(XML_Parser parser, const ENCODING *enc,
+     }
+     do {
+       ICHAR *dataPtr = (ICHAR *)dataBuf;
+-      XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
++      convert_res = XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
+       *eventEndPP = s;
+       defaultHandler(handlerArg, dataBuf, (int)(dataPtr - (ICHAR *)dataBuf));
+       *eventPP = s;
+-    } while (s != end);
++    } while ((convert_res != XML_CONVERT_COMPLETED) && (convert_res != XML_CONVERT_INPUT_INCOMPLETE));
+   }
+   else
+     defaultHandler(handlerArg, (XML_Char *)s, (int)((XML_Char *)end - (XML_Char *)s));
+@@ -6163,8 +6164,8 @@ poolAppend(STRING_POOL *pool, const ENCODING *enc,
+   if (!pool->ptr && !poolGrow(pool))
+     return NULL;
+   for (;;) {
+-    XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
+-    if (ptr == end)
++    const enum XML_Convert_Result convert_res = XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
++    if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
+       break;
+     if (!poolGrow(pool))
+       return NULL;
+@@ -6248,8 +6249,13 @@ poolGrow(STRING_POOL *pool)
+     }
+   }
+   if (pool->blocks && pool->start == pool->blocks->s) {
+-    int blockSize = (int)(pool->end - pool->start)*2;
+-    BLOCK *temp = (BLOCK *)
++    BLOCK *temp;
++    int blockSize = (int)((unsigned)(pool->end - pool->start)*2U);
++
++    if (blockSize < 0)
++      return XML_FALSE;
++
++    temp = (BLOCK *)
+       pool->mem->realloc_fcn(pool->blocks,
+                              (offsetof(BLOCK, s)
+                               + blockSize * sizeof(XML_Char)));
+@@ -6264,6 +6270,10 @@ poolGrow(STRING_POOL *pool)
+   else {
+     BLOCK *tem;
+     int blockSize = (int)(pool->end - pool->start);
++
++    if (blockSize < 0)
++      return XML_FALSE;
++
+     if (blockSize < INIT_BLOCK_SIZE)
+       blockSize = INIT_BLOCK_SIZE;
+     else
+diff --git a/lib/xmltok.c b/lib/xmltok.c
+index bf09dfc..cb98ce1 100644
+--- a/lib/xmltok.c
++++ b/lib/xmltok.c
+@@ -318,39 +318,55 @@ enum {  /* UTF8_cvalN is value of masked first byte of N byte sequence */
+   UTF8_cval4 = 0xf0
+ };
+ 
+-static void PTRCALL
++static enum XML_Convert_Result PTRCALL
+ utf8_toUtf8(const ENCODING *enc,
+             const char **fromP, const char *fromLim,
+             char **toP, const char *toLim)
+ {
++  enum XML_Convert_Result res = XML_CONVERT_COMPLETED;
+   char *to;
+   const char *from;
+   if (fromLim - *fromP > toLim - *toP) {
+     /* Avoid copying partial characters. */
++    res = XML_CONVERT_OUTPUT_EXHAUSTED;
+     for (fromLim = *fromP + (toLim - *toP); fromLim > *fromP; fromLim--)
+       if (((unsigned char)fromLim[-1] & 0xc0) != 0x80)
+         break;
+   }
+-  for (to = *toP, from = *fromP; from != fromLim; from++, to++)
++  for (to = *toP, from = *fromP; (from < fromLim) && (to < toLim); from++, to++)
+     *to = *from;
+   *fromP = from;
+   *toP = to;
++
++  if ((to == toLim) && (from < fromLim))
++    return XML_CONVERT_OUTPUT_EXHAUSTED;
++  else
++    return res;
+ }
+ 
+-static void PTRCALL
++static enum XML_Convert_Result PTRCALL
+ utf8_toUtf16(const ENCODING *enc,
+              const char **fromP, const char *fromLim,
+              unsigned short **toP, const unsigned short *toLim)
+ {
++  enum XML_Convert_Result res = XML_CONVERT_COMPLETED;
+   unsigned short *to = *toP;
+   const char *from = *fromP;
+-  while (from != fromLim && to != toLim) {
++  while (from < fromLim && to < toLim) {
+     switch (((struct normal_encoding *)enc)->type[(unsigned char)*from]) {
+     case BT_LEAD2:
++      if (fromLim - from < 2) {
++        res = XML_CONVERT_INPUT_INCOMPLETE;
++        break;
++      }
+       *to++ = (unsigned short)(((from[0] & 0x1f) << 6) | (from[1] & 0x3f));
+       from += 2;
+       break;
+     case BT_LEAD3:
++      if (fromLim - from < 3) {
++        res = XML_CONVERT_INPUT_INCOMPLETE;
++        break;
++      }
+       *to++ = (unsigned short)(((from[0] & 0xf) << 12)
+                                | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f));
+       from += 3;
+@@ -358,8 +374,14 @@ utf8_toUtf16(const ENCODING *enc,
+     case BT_LEAD4:
+       {
+         unsigned long n;
+-        if (to + 1 == toLim)
++        if (toLim - to < 2) {
++          res = XML_CONVERT_OUTPUT_EXHAUSTED;
+           goto after;
++        }
++        if (fromLim - from < 4) {
++          res = XML_CONVERT_INPUT_INCOMPLETE;
++          goto after;
++        }
+         n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12)
+             | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f);
+         n -= 0x10000;
+@@ -377,6 +399,7 @@ utf8_toUtf16(const ENCODING *enc,
+ after:
+   *fromP = from;
+   *toP = to;
++  return res;
+ }
+ 
+ #ifdef XML_NS
+@@ -425,7 +448,7 @@ static const struct normal_encoding internal_utf8_encoding = {
+   STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+ };
+ 
+-static void PTRCALL
++static enum XML_Convert_Result PTRCALL
+ latin1_toUtf8(const ENCODING *enc,
+               const char **fromP, const char *fromLim,
+               char **toP, const char *toLim)
+@@ -433,30 +456,35 @@ latin1_toUtf8(const ENCODING *enc,
+   for (;;) {
+     unsigned char c;
+     if (*fromP == fromLim)
+-      break;
++      return XML_CONVERT_COMPLETED;
+     c = (unsigned char)**fromP;
+     if (c & 0x80) {
+       if (toLim - *toP < 2)
+-        break;
++        return XML_CONVERT_OUTPUT_EXHAUSTED;
+       *(*toP)++ = (char)((c >> 6) | UTF8_cval2);
+       *(*toP)++ = (char)((c & 0x3f) | 0x80);
+       (*fromP)++;
+     }
+     else {
+       if (*toP == toLim)
+-        break;
++        return XML_CONVERT_OUTPUT_EXHAUSTED;
+       *(*toP)++ = *(*fromP)++;
+     }
+   }
+ }
+ 
+-static void PTRCALL
++static enum XML_Convert_Result PTRCALL
+ latin1_toUtf16(const ENCODING *enc,
+                const char **fromP, const char *fromLim,
+                unsigned short **toP, const unsigned short *toLim)
+ {
+-  while (*fromP != fromLim && *toP != toLim)
++  while (*fromP < fromLim && *toP < toLim)
+     *(*toP)++ = (unsigned char)*(*fromP)++;
++
++  if ((*toP == toLim) && (*fromP < fromLim))
++    return XML_CONVERT_OUTPUT_EXHAUSTED;
++  else
++    return XML_CONVERT_COMPLETED;
+ }
+ 
+ #ifdef XML_NS
+@@ -483,13 +511,18 @@ static const struct normal_encoding latin1_encoding = {
+   STANDARD_VTABLE(sb_)
+ };
+ 
+-static void PTRCALL
++static enum XML_Convert_Result PTRCALL
+ ascii_toUtf8(const ENCODING *enc,
+              const char **fromP, const char *fromLim,
+              char **toP, const char *toLim)
+ {
+-  while (*fromP != fromLim && *toP != toLim)
++  while (*fromP < fromLim && *toP < toLim)
+     *(*toP)++ = *(*fromP)++;
++
++  if ((*toP == toLim) && (*fromP < fromLim))
++    return XML_CONVERT_OUTPUT_EXHAUSTED;
++  else
++    return XML_CONVERT_COMPLETED;
+ }
+ 
+ #ifdef XML_NS
+@@ -536,13 +569,14 @@ unicode_byte_type(char hi, char lo)
+ }
+ 
+ #define DEFINE_UTF16_TO_UTF8(E) \
+-static void  PTRCALL \
++static enum XML_Convert_Result  PTRCALL \
+ E ## toUtf8(const ENCODING *enc, \
+             const char **fromP, const char *fromLim, \
+             char **toP, const char *toLim) \
+ { \
+-  const char *from; \
+-  for (from = *fromP; from != fromLim; from += 2) { \
++  const char *from = *fromP; \
++  fromLim = from + (((fromLim - from) >> 1) << 1);  /* shrink to even */ \
++  for (; from < fromLim; from += 2) { \
+     int plane; \
+     unsigned char lo2; \
+     unsigned char lo = GET_LO(from); \
+@@ -552,7 +586,7 @@ E ## toUtf8(const ENCODING *enc, \
+       if (lo < 0x80) { \
+         if (*toP == toLim) { \
+           *fromP = from; \
+-          return; \
++          return XML_CONVERT_OUTPUT_EXHAUSTED; \
+         } \
+         *(*toP)++ = lo; \
+         break; \
+@@ -562,7 +596,7 @@ E ## toUtf8(const ENCODING *enc, \
+     case 0x4: case 0x5: case 0x6: case 0x7: \
+       if (toLim -  *toP < 2) { \
+         *fromP = from; \
+-        return; \
++        return XML_CONVERT_OUTPUT_EXHAUSTED; \
+       } \
+       *(*toP)++ = ((lo >> 6) | (hi << 2) |  UTF8_cval2); \
+       *(*toP)++ = ((lo & 0x3f) | 0x80); \
+@@ -570,7 +604,7 @@ E ## toUtf8(const ENCODING *enc, \
+     default: \
+       if (toLim -  *toP < 3)  { \
+         *fromP = from; \
+-        return; \
++        return XML_CONVERT_OUTPUT_EXHAUSTED; \
+       } \
+       /* 16 bits divided 4, 6, 6 amongst 3 bytes */ \
+       *(*toP)++ = ((hi >> 4) | UTF8_cval3); \
+@@ -580,7 +614,11 @@ E ## toUtf8(const ENCODING *enc, \
+     case 0xD8: case 0xD9: case 0xDA: case 0xDB: \
+       if (toLim -  *toP < 4) { \
+         *fromP = from; \
+-        return; \
++        return XML_CONVERT_OUTPUT_EXHAUSTED; \
++      } \
++      if (fromLim - from < 4) { \
++        *fromP = from; \
++        return XML_CONVERT_INPUT_INCOMPLETE; \
+       } \
+       plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1; \
+       *(*toP)++ = ((plane >> 2) | UTF8_cval4); \
+@@ -596,20 +634,32 @@ E ## toUtf8(const ENCODING *enc, \
+     } \
+   } \
+   *fromP = from; \
++  if (from < fromLim) \
++    return XML_CONVERT_INPUT_INCOMPLETE; \
++  else \
++    return XML_CONVERT_COMPLETED; \
+ }
+ 
+ #define DEFINE_UTF16_TO_UTF16(E) \
+-static void  PTRCALL \
++static enum XML_Convert_Result  PTRCALL \
+ E ## toUtf16(const ENCODING *enc, \
+              const char **fromP, const char *fromLim, \
+              unsigned short **toP, const unsigned short *toLim) \
+ { \
++  enum XML_Convert_Result res = XML_CONVERT_COMPLETED; \
++  fromLim = *fromP + (((fromLim - *fromP) >> 1) << 1);  /* shrink to even */ \
+   /* Avoid copying first half only of surrogate */ \
+   if (fromLim - *fromP > ((toLim - *toP) << 1) \
+-      && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) \
++      && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) { \
+     fromLim -= 2; \
+-  for (; *fromP != fromLim && *toP != toLim; *fromP += 2) \
++    res = XML_CONVERT_INPUT_INCOMPLETE; \
++  } \
++  for (; *fromP < fromLim && *toP < toLim; *fromP += 2) \
+     *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \
++  if ((*toP == toLim) && (*fromP < fromLim)) \
++    return XML_CONVERT_OUTPUT_EXHAUSTED; \
++  else \
++    return res; \
+ }
+ 
+ #define SET2(ptr, ch) \
+@@ -1288,7 +1338,7 @@ unknown_isInvalid(const ENCODING *enc, const char *p)
+   return (c & ~0xFFFF) || checkCharRefNumber(c) < 0;
+ }
+ 
+-static void PTRCALL
++static enum XML_Convert_Result PTRCALL
+ unknown_toUtf8(const ENCODING *enc,
+                const char **fromP, const char *fromLim,
+                char **toP, const char *toLim)
+@@ -1299,21 +1349,21 @@ unknown_toUtf8(const ENCODING *enc,
+     const char *utf8;
+     int n;
+     if (*fromP == fromLim)
+-      break;
++      return XML_CONVERT_COMPLETED;
+     utf8 = uenc->utf8[(unsigned char)**fromP];
+     n = *utf8++;
+     if (n == 0) {
+       int c = uenc->convert(uenc->userData, *fromP);
+       n = XmlUtf8Encode(c, buf);
+       if (n > toLim - *toP)
+-        break;
++        return XML_CONVERT_OUTPUT_EXHAUSTED;
+       utf8 = buf;
+       *fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP]
+                  - (BT_LEAD2 - 2));
+     }
+     else {
+       if (n > toLim - *toP)
+-        break;
++        return XML_CONVERT_OUTPUT_EXHAUSTED;
+       (*fromP)++;
+     }
+     do {
+@@ -1322,13 +1372,13 @@ unknown_toUtf8(const ENCODING *enc,
+   }
+ }
+ 
+-static void PTRCALL
++static enum XML_Convert_Result PTRCALL
+ unknown_toUtf16(const ENCODING *enc,
+                 const char **fromP, const char *fromLim,
+                 unsigned short **toP, const unsigned short *toLim)
+ {
+   const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
+-  while (*fromP != fromLim && *toP != toLim) {
++  while (*fromP < fromLim && *toP < toLim) {
+     unsigned short c = uenc->utf16[(unsigned char)**fromP];
+     if (c == 0) {
+       c = (unsigned short)
+@@ -1340,6 +1390,11 @@ unknown_toUtf16(const ENCODING *enc,
+       (*fromP)++;
+     *(*toP)++ = c;
+   }
++
++  if ((*toP == toLim) && (*fromP < fromLim))
++    return XML_CONVERT_OUTPUT_EXHAUSTED;
++  else
++    return XML_CONVERT_COMPLETED;
+ }
+ 
+ ENCODING *
+@@ -1503,7 +1558,7 @@ initScan(const ENCODING * const *encodingTable,
+ {
+   const ENCODING **encPtr;
+ 
+-  if (ptr == end)
++  if (ptr >= end)
+     return XML_TOK_NONE;
+   encPtr = enc->encPtr;
+   if (ptr + 1 == end) {
+diff --git a/lib/xmltok.h b/lib/xmltok.h
+index ca867aa..752007e 100644
+--- a/lib/xmltok.h
++++ b/lib/xmltok.h
+@@ -130,6 +130,12 @@ typedef int (PTRCALL *SCANNER)(const ENCODING *,
+                                const char *,
+                                const char **);
+ 
++enum XML_Convert_Result {
++  XML_CONVERT_COMPLETED = 0,
++  XML_CONVERT_INPUT_INCOMPLETE = 1,
++  XML_CONVERT_OUTPUT_EXHAUSTED = 2  /* and therefore potentially input remaining as well */
++};
++
+ struct encoding {
+   SCANNER scanners[XML_N_STATES];
+   SCANNER literalScanners[XML_N_LITERAL_TYPES];
+@@ -158,12 +164,12 @@ struct encoding {
+                             const char *ptr,
+                             const char *end,
+                             const char **badPtr);
+-  void (PTRCALL *utf8Convert)(const ENCODING *enc,
++  enum XML_Convert_Result (PTRCALL *utf8Convert)(const ENCODING *enc,
+                               const char **fromP,
+                               const char *fromLim,
+                               char **toP,
+                               const char *toLim);
+-  void (PTRCALL *utf16Convert)(const ENCODING *enc,
++  enum XML_Convert_Result (PTRCALL *utf16Convert)(const ENCODING *enc,
+                                const char **fromP,
+                                const char *fromLim,
+                                unsigned short **toP,
+diff --git a/lib/xmltok_impl.c b/lib/xmltok_impl.c
+index 9c2895b..6c5a3ba 100644
+--- a/lib/xmltok_impl.c
++++ b/lib/xmltok_impl.c
+@@ -93,13 +93,13 @@ static int PTRCALL
+ PREFIX(scanComment)(const ENCODING *enc, const char *ptr,
+                     const char *end, const char **nextTokPtr)
+ {
+-  if (ptr != end) {
++  if (ptr < end) {
+     if (!CHAR_MATCHES(enc, ptr, ASCII_MINUS)) {
+       *nextTokPtr = ptr;
+       return XML_TOK_INVALID;
+     }
+     ptr += MINBPC(enc);
+-    while (ptr != end) {
++    while (ptr < end) {
+       switch (BYTE_TYPE(enc, ptr)) {
+       INVALID_CASES(ptr, nextTokPtr)
+       case BT_MINUS:
+@@ -147,7 +147,7 @@ PREFIX(scanDecl)(const ENCODING *enc, const char *ptr,
+     *nextTokPtr = ptr;
+     return XML_TOK_INVALID;
+   }
+-  while (ptr != end) {
++  while (ptr < end) {
+     switch (BYTE_TYPE(enc, ptr)) {
+     case BT_PERCNT:
+       if (ptr + MINBPC(enc) == end)
+@@ -233,7 +233,7 @@ PREFIX(scanPi)(const ENCODING *enc, const char *ptr,
+     *nextTokPtr = ptr;
+     return XML_TOK_INVALID;
+   }
+-  while (ptr != end) {
++  while (ptr < end) {
+     switch (BYTE_TYPE(enc, ptr)) {
+     CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+     case BT_S: case BT_CR: case BT_LF:
+@@ -242,7 +242,7 @@ PREFIX(scanPi)(const ENCODING *enc, const char *ptr,
+         return XML_TOK_INVALID;
+       }
+       ptr += MINBPC(enc);
+-      while (ptr != end) {
++      while (ptr < end) {
+         switch (BYTE_TYPE(enc, ptr)) {
+         INVALID_CASES(ptr, nextTokPtr)
+         case BT_QUEST:
+@@ -305,7 +305,7 @@ static int PTRCALL
+ PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr,
+                         const char *end, const char **nextTokPtr)
+ {
+-  if (ptr == end)
++  if (ptr >= end)
+     return XML_TOK_NONE;
+   if (MINBPC(enc) > 1) {
+     size_t n = end - ptr;
+@@ -348,7 +348,7 @@ PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr,
+     ptr += MINBPC(enc);
+     break;
+   }
+-  while (ptr != end) {
++  while (ptr < end) {
+     switch (BYTE_TYPE(enc, ptr)) {
+ #define LEAD_CASE(n) \
+     case BT_LEAD ## n: \
+@@ -391,11 +391,11 @@ PREFIX(scanEndTag)(const ENCODING *enc, const char *ptr,
+     *nextTokPtr = ptr;
+     return XML_TOK_INVALID;
+   }
+-  while (ptr != end) {
++  while (ptr < end) {
+     switch (BYTE_TYPE(enc, ptr)) {
+     CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+     case BT_S: case BT_CR: case BT_LF:
+-      for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
++      for (ptr += MINBPC(enc); ptr < end; ptr += MINBPC(enc)) {
+         switch (BYTE_TYPE(enc, ptr)) {
+         case BT_S: case BT_CR: case BT_LF:
+           break;
+@@ -432,7 +432,7 @@ static int PTRCALL
+ PREFIX(scanHexCharRef)(const ENCODING *enc, const char *ptr,
+                        const char *end, const char **nextTokPtr)
+ {
+-  if (ptr != end) {
++  if (ptr < end) {
+     switch (BYTE_TYPE(enc, ptr)) {
+     case BT_DIGIT:
+     case BT_HEX:
+@@ -441,7 +441,7 @@ PREFIX(scanHexCharRef)(const ENCODING *enc, const char *ptr,
+       *nextTokPtr = ptr;
+       return XML_TOK_INVALID;
+     }
+-    for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
++    for (ptr += MINBPC(enc); ptr < end; ptr += MINBPC(enc)) {
+       switch (BYTE_TYPE(enc, ptr)) {
+       case BT_DIGIT:
+       case BT_HEX:
+@@ -464,7 +464,7 @@ static int PTRCALL
+ PREFIX(scanCharRef)(const ENCODING *enc, const char *ptr,
+                     const char *end, const char **nextTokPtr)
+ {
+-  if (ptr != end) {
++  if (ptr < end) {
+     if (CHAR_MATCHES(enc, ptr, ASCII_x))
+       return PREFIX(scanHexCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+     switch (BYTE_TYPE(enc, ptr)) {
+@@ -474,7 +474,7 @@ PREFIX(scanCharRef)(const ENCODING *enc, const char *ptr,
+       *nextTokPtr = ptr;
+       return XML_TOK_INVALID;
+     }
+-    for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
++    for (ptr += MINBPC(enc); ptr < end; ptr += MINBPC(enc)) {
+       switch (BYTE_TYPE(enc, ptr)) {
+       case BT_DIGIT:
+         break;
+@@ -506,7 +506,7 @@ PREFIX(scanRef)(const ENCODING *enc, const char *ptr, const char *end,
+     *nextTokPtr = ptr;
+     return XML_TOK_INVALID;
+   }
+-  while (ptr != end) {
++  while (ptr < end) {
+     switch (BYTE_TYPE(enc, ptr)) {
+     CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+     case BT_SEMI:
+@@ -529,7 +529,7 @@ PREFIX(scanAtts)(const ENCODING *enc, const char *ptr, const char *end,
+ #ifdef XML_NS
+   int hadColon = 0;
+ #endif
+-  while (ptr != end) {
++  while (ptr < end) {
+     switch (BYTE_TYPE(enc, ptr)) {
+     CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ #ifdef XML_NS
+@@ -716,7 +716,7 @@ PREFIX(scanLt)(const ENCODING *enc, const char *ptr, const char *end,
+   hadColon = 0;
+ #endif
+   /* we have a start-tag */
+-  while (ptr != end) {
++  while (ptr < end) {
+     switch (BYTE_TYPE(enc, ptr)) {
+     CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ #ifdef XML_NS
+@@ -740,7 +740,7 @@ PREFIX(scanLt)(const ENCODING *enc, const char *ptr, const char *end,
+     case BT_S: case BT_CR: case BT_LF:
+       {
+         ptr += MINBPC(enc);
+-        while (ptr != end) {
++        while (ptr < end) {
+           switch (BYTE_TYPE(enc, ptr)) {
+           CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+           case BT_GT:
+@@ -785,7 +785,7 @@ static int PTRCALL
+ PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end,
+                    const char **nextTokPtr)
+ {
+-  if (ptr == end)
++  if (ptr >= end)
+     return XML_TOK_NONE;
+   if (MINBPC(enc) > 1) {
+     size_t n = end - ptr;
+@@ -832,7 +832,7 @@ PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end,
+     ptr += MINBPC(enc);
+     break;
+   }
+-  while (ptr != end) {
++  while (ptr < end) {
+     switch (BYTE_TYPE(enc, ptr)) {
+ #define LEAD_CASE(n) \
+     case BT_LEAD ## n: \
+@@ -895,7 +895,7 @@ PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end,
+     *nextTokPtr = ptr;
+     return XML_TOK_INVALID;
+   }
+-  while (ptr != end) {
++  while (ptr < end) {
+     switch (BYTE_TYPE(enc, ptr)) {
+     CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+     case BT_SEMI:
+@@ -921,7 +921,7 @@ PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end,
+     *nextTokPtr = ptr;
+     return XML_TOK_INVALID;
+   }
+-  while (ptr != end) {
++  while (ptr < end) {
+     switch (BYTE_TYPE(enc, ptr)) {
+     CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+     case BT_CR: case BT_LF: case BT_S:
+@@ -941,7 +941,7 @@ PREFIX(scanLit)(int open, const ENCODING *enc,
+                 const char *ptr, const char *end,
+                 const char **nextTokPtr)
+ {
+-  while (ptr != end) {
++  while (ptr < end) {
+     int t = BYTE_TYPE(enc, ptr);
+     switch (t) {
+     INVALID_CASES(ptr, nextTokPtr)
+@@ -973,7 +973,7 @@ PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end,
+                   const char **nextTokPtr)
+ {
+   int tok;
+-  if (ptr == end)
++  if (ptr >= end)
+     return XML_TOK_NONE;
+   if (MINBPC(enc) > 1) {
+     size_t n = end - ptr;
+@@ -1141,7 +1141,7 @@ PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end,
+     *nextTokPtr = ptr;
+     return XML_TOK_INVALID;
+   }
+-  while (ptr != end) {
++  while (ptr < end) {
+     switch (BYTE_TYPE(enc, ptr)) {
+     CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+     case BT_GT: case BT_RPAR: case BT_COMMA:
+@@ -1204,10 +1204,10 @@ PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr,
+                           const char *end, const char **nextTokPtr)
+ {
+   const char *start;
+-  if (ptr == end)
++  if (ptr >= end)
+     return XML_TOK_NONE;
+   start = ptr;
+-  while (ptr != end) {
++  while (ptr < end) {
+     switch (BYTE_TYPE(enc, ptr)) {
+ #define LEAD_CASE(n) \
+     case BT_LEAD ## n: ptr += n; break;
+@@ -1262,10 +1262,10 @@ PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr,
+                        const char *end, const char **nextTokPtr)
+ {
+   const char *start;
+-  if (ptr == end)
++  if (ptr >= end)
+     return XML_TOK_NONE;
+   start = ptr;
+-  while (ptr != end) {
++  while (ptr < end) {
+     switch (BYTE_TYPE(enc, ptr)) {
+ #define LEAD_CASE(n) \
+     case BT_LEAD ## n: ptr += n; break;
+@@ -1326,7 +1326,7 @@ PREFIX(ignoreSectionTok)(const ENCODING *enc, const char *ptr,
+       end = ptr + n;
+     }
+   }
+-  while (ptr != end) {
++  while (ptr < end) {
+     switch (BYTE_TYPE(enc, ptr)) {
+     INVALID_CASES(ptr, nextTokPtr)
+     case BT_LT:
+@@ -1373,7 +1373,7 @@ PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
+ {
+   ptr += MINBPC(enc);
+   end -= MINBPC(enc);
+-  for (; ptr != end; ptr += MINBPC(enc)) {
++  for (; ptr < end; ptr += MINBPC(enc)) {
+     switch (BYTE_TYPE(enc, ptr)) {
+     case BT_DIGIT:
+     case BT_HEX:
+@@ -1760,7 +1760,7 @@ PREFIX(updatePosition)(const ENCODING *enc,
+     case BT_CR:
+       pos->lineNumber++;
+       ptr += MINBPC(enc);
+-      if (ptr != end && BYTE_TYPE(enc, ptr) == BT_LF)
++      if (ptr < end && BYTE_TYPE(enc, ptr) == BT_LF)
+         ptr += MINBPC(enc);
+       pos->columnNumber = (XML_Size)-1;
+       break;
+-- 
+2.8.2
+
diff --git a/external/expat/UnpackedTarball_expat.mk b/external/expat/UnpackedTarball_expat.mk
index 60e933d..b82e9e0 100644
--- a/external/expat/UnpackedTarball_expat.mk
+++ b/external/expat/UnpackedTarball_expat.mk
@@ -13,6 +13,8 @@ $(eval $(call gb_UnpackedTarball_set_tarball,expat,$(EXPAT_TARBALL)))
 
 $(eval $(call gb_UnpackedTarball_add_patches,expat,\
 	external/expat/expat-winapi.patch \
+	external/expat/CVE-2015-1283-refix.patch.1 \
+	external/expat/CVE-2016-0718-v2-2-1.patch.1 \
 ))
 
 # This is a bit hackish.
commit 48e65a74f5e66ffcf4d81a12f13573f7875bd61a
Author: Michael Stahl <mstahl at redhat.com>
Date:   Fri Jun 26 14:20:02 2015 +0200

    expat: remove duplicate patch
    
    Change-Id: Ie813234b78b9f8d2c61c9640546317d754f66004
    (cherry picked from commit 6d0a9ccffe57d0438f46ccd0f4e63c06a9e1c9eb)

diff --git a/external/expat/UnpackedTarball_expat.mk b/external/expat/UnpackedTarball_expat.mk
index 1ea97b5..60e933d 100644
--- a/external/expat/UnpackedTarball_expat.mk
+++ b/external/expat/UnpackedTarball_expat.mk
@@ -12,7 +12,7 @@ $(eval $(call gb_UnpackedTarball_UnpackedTarball,expat))
 $(eval $(call gb_UnpackedTarball_set_tarball,expat,$(EXPAT_TARBALL)))
 
 $(eval $(call gb_UnpackedTarball_add_patches,expat,\
-	external/expat/expat-2.1.0.patch \
+	external/expat/expat-winapi.patch \
 ))
 
 # This is a bit hackish.
diff --git a/external/expat/expat-2.1.0.patch b/external/expat/expat-2.1.0.patch
deleted file mode 100644
index 070dafc..0000000
--- a/external/expat/expat-2.1.0.patch
+++ /dev/null
@@ -1,13 +0,0 @@
---- misc/expat-2.1.0/lib/expat_external.h	2009-11-16 08:53:17.375000000 +0000
-+++ misc/build/expat-2.1.0/lib/expat_external.h	2009-11-16 08:53:34.703125000 +0000
-@@ -7,10 +7,6 @@
- 
- /* External API definitions */
- 
--#if defined(_MSC_EXTENSIONS) && !defined(__BEOS__) && !defined(__CYGWIN__)
--#define XML_USE_MSC_EXTENSIONS 1
--#endif
--
- /* Expat tries very hard to make the API boundary very specifically
-    defined.  There are two macros defined to control this boundary;
-    each of these can be defined before including this header to
commit b5c276417073f05367beb8521b58d58674096cd9
Author: David Tardon <dtardon at redhat.com>
Date:   Mon Apr 4 14:52:37 2016 +0200

    tdf#99078 upload expat 2.1.1
    
    Reviewed-on: https://gerrit.libreoffice.org/23809
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: David Tardon <dtardon at redhat.com>
    (cherry picked from commit ac19ed0fed3197af2ed3f07e00185befcb90a8fe)
    
    Reviewed-on: https://gerrit.libreoffice.org/23835
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Michael Stahl <mstahl at redhat.com>
    
    Conflicts:
    	download.lst
    
    Change-Id: I2b8b1c9ac42830548287a580b53002ba74e2483e

diff --git a/download.lst b/download.lst
index c8219cd..e356b61 100644
--- a/download.lst
+++ b/download.lst
@@ -37,7 +37,8 @@ export EPM_TARBALL := 3ade8cfe7e59ca8e65052644fed9fca4-epm-3.7.tar.gz
 export ETONYEK_MD5SUM := e5947373dd7834f27e93f1636faa419f
 export ETONYEK_VERSION_MICRO := 3
 export ETONYEK_TARBALL := libetonyek-0.1.$(ETONYEK_VERSION_MICRO).tar.bz2
-export EXPAT_TARBALL := dd7dab7a5fea97d2a6a43f511449b7cd-expat-2.1.0.tar.gz
+export EXPAT_MD5SUM := 7380a64a8e3a9d66a9887b01d0d7ea81
+export EXPAT_TARBALL := expat-2.1.1.tar.bz2
 export FIREBIRD_MD5SUM := 21154d2004e025c8a3666625b0357bb5
 export FIREBIRD_TARBALL := Firebird-2.5.2.26540-0.tar.bz2
 # FIREBIRD_MD5SUM := b259c2d1c60a03bd104108405ae990a7
commit 3a526ca19a289d2e8b47b9496190e3256c3bde5f
Author: Michael Stahl <mstahl at redhat.com>
Date:   Tue May 24 17:27:14 2016 +0200

    libxml2: upgrade to release 2.9.4
    
    Reviewed-on: https://gerrit.libreoffice.org/25412
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Michael Stahl <mstahl at redhat.com>
    (cherry picked from commit 469aa7fb9e42757267347b986f0e2b1184ebb508)
    
    Change-Id: Ia3109b704155b9baa28f2a5f224e55af161f4fa1
    Reviewed-on: https://gerrit.libreoffice.org/25417
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/download.lst b/download.lst
index 3d0e924..c8219cd 100644
--- a/download.lst
+++ b/download.lst
@@ -95,7 +95,7 @@ export LIBGLTF_MD5SUM := d63a9f47ab048f5009d90693d6aa6424
 export LIBGLTF_TARBALL := libgltf-0.0.2.tar.bz2
 export LIBLANGTAG_TARBALL := 36271d3fa0d9dec1632029b6d7aac925-liblangtag-0.5.1.tar.bz2
 export LIBXMLSEC_TARBALL := 1f24ab1d39f4a51faf22244c94a6203f-xmlsec1-1.2.14.tar.gz
-export LIBXML_TARBALL := daece17e045f1c107610e137ab50c179-libxml2-2.9.3.tar.gz
+export LIBXML_TARBALL := ae249165c173b1ff386ee8ad676815f5-libxml2-2.9.4.tar.gz
 export LIBXSLT_TARBALL := 9667bf6f9310b957254fdcf6596600b7-libxslt-1.1.28.tar.gz
 export LPSOLVE_TARBALL := 26b3e95ddf3d9c077c480ea45874b3b8-lp_solve_5.5.tar.gz
 export MARIADB_TARBALL := a233181e03d3c307668b4c722d881661-mariadb_client-2.0.0-src.tar.gz
diff --git a/external/libxml2/ExternalPackage_xml2.mk b/external/libxml2/ExternalPackage_xml2.mk
index 3694937..3878b3e 100644
--- a/external/libxml2/ExternalPackage_xml2.mk
+++ b/external/libxml2/ExternalPackage_xml2.mk
@@ -21,7 +21,7 @@ else # COM=MSC
 $(eval $(call gb_ExternalPackage_add_file,xml2,$(LIBO_URE_LIB_FOLDER)/libxml2.dll,win32/bin.msvc/libxml2.dll))
 endif
 else # OS!=WNT
-$(eval $(call gb_ExternalPackage_add_file,xml2,$(LIBO_URE_LIB_FOLDER)/libxml2.so.2,.libs/libxml2.so.2.9.3))
+$(eval $(call gb_ExternalPackage_add_file,xml2,$(LIBO_URE_LIB_FOLDER)/libxml2.so.2,.libs/libxml2.so.2.9.4))
 endif
 endif # DISABLE_DYNLOADING
 
commit ce5b20c0772d872a2090e35040f6b70143af713a
Author: Oliver Specht <oliver.specht at cib.de>
Date:   Fri Feb 26 10:40:45 2016 +0100

    tdf#98088: prevent access to invalid sub node
    
    Change-Id: I73bd77682bfb60474ba18ca85bc5d008c70a7f97
    Reviewed-on: https://gerrit.libreoffice.org/22715
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>
    (cherry picked from commit 529e06a1b855ac83468230a15903aeafe1ac89a7)
    (cherry picked from commit cda827958eefb636a4dbe57e1df7d21b5878171f)

diff --git a/starmath/source/node.cxx b/starmath/source/node.cxx
index 311df24..660ca4e 100644
--- a/starmath/source/node.cxx
+++ b/starmath/source/node.cxx
@@ -2127,7 +2127,8 @@ void SmFontNode::CreateTextFromNode(OUString &rText)
         default:
             break;
     }
-    GetSubNode(1)->CreateTextFromNode(rText);
+    if(GetNumSubNodes() > 1)
+        GetSubNode(1)->CreateTextFromNode(rText);
 }
 
 void SmFontNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
commit 3b6b3ca5022f3a6423c2ec4529db9c35cb603c5c
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Fri May 13 10:10:50 2016 +0100

    Resolves: tdf#99272 new Short[] used instead of new short[]
    
    bridge code expects to see short[] not Short[] so the mapping
    doesn't work and office blows up
    
    regression from...
    
    commit ecc90694175190cd6e2b9d1bed8f32850d41ce88
    Date:   Wed Oct 15 14:14:28 2014 +0200
    
        java: use 'Short.valueOf' instead of 'new Short'
    
    git grep "new Short\[\]" shows two suspicious cases of this in odk, but they
    were always thus, so leaving them untouched.
    
    Change-Id: I3306659b5c3f4e0643c200373da777da248bbd42
    (cherry picked from commit f53e427291321eabe8d060a737e750a94739f911)
    Reviewed-on: https://gerrit.libreoffice.org/24954
    Reviewed-by: Lionel Elie Mamane <lionel at mamane.lu>
    Tested-by: Noel Grandin <noelgrandin at gmail.com>
    Tested-by: Jenkins <ci at libreoffice.org>
    (cherry picked from commit c1ca17f916541ba127765a9f5392fabd761cd946)

diff --git a/wizards/com/sun/star/wizards/table/FieldFormatter.java b/wizards/com/sun/star/wizards/table/FieldFormatter.java
index 9822b4c..df1d305 100644
--- a/wizards/com/sun/star/wizards/table/FieldFormatter.java
+++ b/wizards/com/sun/star/wizards/table/FieldFormatter.java
@@ -225,7 +225,7 @@ public class FieldFormatter implements XItemListener
             }
         }
         Helper.setUnoPropertyValue(UnoDialog.getModel(xlstFieldNames), PropertyNames.STRING_ITEM_LIST, _fieldnames);
-        Helper.setUnoPropertyValue(UnoDialog.getModel(xlstFieldNames), PropertyNames.SELECTED_ITEMS, new Short[]
+        Helper.setUnoPropertyValue(UnoDialog.getModel(xlstFieldNames), PropertyNames.SELECTED_ITEMS, new short[]
                 {
                     0
                 });
@@ -260,7 +260,7 @@ public class FieldFormatter implements XItemListener
         if (CurUnoDialog.verifyfieldcount(icount))
         {
             xlstFieldNames.addItem(snewfieldname, icount);
-            Helper.setUnoPropertyValue(UnoDialog.getModel(xlstFieldNames), PropertyNames.SELECTED_ITEMS, new Short[]
+            Helper.setUnoPropertyValue(UnoDialog.getModel(xlstFieldNames), PropertyNames.SELECTED_ITEMS, new short[]
                     {
                         icount
                     });
@@ -284,7 +284,7 @@ public class FieldFormatter implements XItemListener
         int ilistcount = /* xlstFieldNames.getItemCount();*/ UnoDialog.getListBoxItemCount(xlstFieldNames);
         if ((ipos) < ilistcount)
         {
-            Helper.setUnoPropertyValue(UnoDialog.getModel(xlstFieldNames), PropertyNames.SELECTED_ITEMS, new Short[]
+            Helper.setUnoPropertyValue(UnoDialog.getModel(xlstFieldNames), PropertyNames.SELECTED_ITEMS, new short[]
                     {
                         ipos
                     });
@@ -294,7 +294,7 @@ public class FieldFormatter implements XItemListener
             if (ilistcount > -1)
             {
                 ipos = (short) ((short) ilistcount - (short) 1);
-                Helper.setUnoPropertyValue(UnoDialog.getModel(xlstFieldNames), PropertyNames.SELECTED_ITEMS, new Short[]
+                Helper.setUnoPropertyValue(UnoDialog.getModel(xlstFieldNames), PropertyNames.SELECTED_ITEMS, new short[]
                         {
                             ipos
                         });
@@ -338,7 +338,7 @@ public class FieldFormatter implements XItemListener
                 short ipos = xlstFieldNames.getSelectedItemPos();
                 fieldnames[ipos] = newfieldname;
                 Helper.setUnoPropertyValue(UnoDialog.getModel(xlstFieldNames), PropertyNames.STRING_ITEM_LIST, fieldnames);
-                Helper.setUnoPropertyValue(UnoDialog.getModel(xlstFieldNames), PropertyNames.SELECTED_ITEMS, new Short[]
+                Helper.setUnoPropertyValue(UnoDialog.getModel(xlstFieldNames), PropertyNames.SELECTED_ITEMS, new short[]
                         {
                             ipos
                         });
@@ -353,7 +353,7 @@ public class FieldFormatter implements XItemListener
         Helper.setUnoPropertyValue(UnoDialog.getModel(xlstFieldNames), PropertyNames.STRING_ITEM_LIST, snewlist);
         if ((ipos - 1) > -1)
         {
-            Helper.setUnoPropertyValue(UnoDialog.getModel(xlstFieldNames), PropertyNames.SELECTED_ITEMS, new Short[]
+            Helper.setUnoPropertyValue(UnoDialog.getModel(xlstFieldNames), PropertyNames.SELECTED_ITEMS, new short[]
                     {
                         (short) (ipos - 1)
                     });
@@ -369,7 +369,7 @@ public class FieldFormatter implements XItemListener
         Helper.setUnoPropertyValue(UnoDialog.getModel(xlstFieldNames), PropertyNames.STRING_ITEM_LIST, snewlist);
         if ((ipos + 1) < xlstFieldNames.getItemCount())
         {
-            Helper.setUnoPropertyValue(UnoDialog.getModel(xlstFieldNames), PropertyNames.SELECTED_ITEMS, new Short[]
+            Helper.setUnoPropertyValue(UnoDialog.getModel(xlstFieldNames), PropertyNames.SELECTED_ITEMS, new short[]
                     {
                         (short) (ipos + 1)
                     });
commit 825282723d0e45b344a49978c67d43f3cca0fdcc
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Mon May 9 10:55:39 2016 +0100

    fftester: subtable is a subtable of itself
    
    Change-Id: I9de983e3c9436ab3a37d3482b0f18f04c7cdaaca
    (cherry picked from commit b18d49e09a66b9ad29e1c75796ebbf75d407c8d5)
    Reviewed-on: https://gerrit.libreoffice.org/24791
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Michael Stahl <mstahl at redhat.com>
    (cherry picked from commit 930c8d14c554428e5b75a9c43d7ed349f742e1a8)

diff --git a/lotuswordpro/qa/cppunit/data/fail/recurse-3.lwp b/lotuswordpro/qa/cppunit/data/fail/recurse-3.lwp
new file mode 100644
index 0000000..acb8c93
Binary files /dev/null and b/lotuswordpro/qa/cppunit/data/fail/recurse-3.lwp differ
diff --git a/lotuswordpro/source/filter/xfilter/xfcell.hxx b/lotuswordpro/source/filter/xfilter/xfcell.hxx
index 9ae0010..c35783a 100644
--- a/lotuswordpro/source/filter/xfilter/xfcell.hxx
+++ b/lotuswordpro/source/filter/xfilter/xfcell.hxx
@@ -156,6 +156,8 @@ public:
      */
     virtual void    ToXml(IXFStream *pStrm) SAL_OVERRIDE;
 
+    const XFTable*  GetSubTable() const { return m_pSubTable; }
+
 private:
     XFRow       *m_pOwnerRow;
     XFTable     *m_pSubTable;
diff --git a/lotuswordpro/source/filter/xfilter/xftable.cxx b/lotuswordpro/source/filter/xfilter/xftable.cxx
index 652e9e7..bfd842c 100644
--- a/lotuswordpro/source/filter/xfilter/xftable.cxx
+++ b/lotuswordpro/source/filter/xfilter/xftable.cxx
@@ -91,6 +91,13 @@ void XFTable::AddRow(XFRow *pRow)
 {
     assert(pRow);
 
+    for (sal_Int32 i = 0; i < pRow->GetCellCount(); ++i)
+    {
+        XFCell* pFirstCell = pRow->GetCell(i + 1); //starts at 1, not 0
+        if (pFirstCell->GetSubTable() == this)
+            throw std::runtime_error("table is a subtable of itself");
+    }
+
     int row = pRow->GetRow();
 
     if( row<1 )


More information about the Libreoffice-commits mailing list