diff --git a/CVE-2018-1311.patch b/CVE-2018-1311.patch deleted file mode 100644 index 74da73f46f5c98675d3b650a22dc8888ee1c2a63..0000000000000000000000000000000000000000 --- a/CVE-2018-1311.patch +++ /dev/null @@ -1,650 +0,0 @@ -From e0024267504188e42ace4dd9031d936786914835 Mon Sep 17 00:00:00 2001 -From: Karen Arutyunov -Date: Wed, 13 Dec 2023 09:59:07 +0200 -Subject: [PATCH] XERCESC-2188 - Use-after-free on external DTD scan - (CVE-2018-1311) - -Origin: https://github.com/apache/xerces-c/commit/e0024267504188e42ace4dd9031d936786914835 - -These are the instructions for observing the bug (before this commit): - -$ git clone https://github.com/apache/xerces-c.git -$ cd xerces-c -$ mkdir build -$ cd build -$ cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug .. -$ make -j8 -$ cp ../samples/data/personal.xml . - -$ cat <personal.dtd - - -%nonExistentEntity; -EOF - -$ gdb samples/StdInParse -(gdb) b IGXMLScanner.cpp:1544 -(gdb) run isExternal()) -(gdb) p curEntity -$2 = (const xercesc_4_0::XMLEntityDecl *) 0x49ac68 ---- - src/xercesc/internal/DGXMLScanner.cpp | 6 +- - src/xercesc/internal/IGXMLScanner.cpp | 6 +- - src/xercesc/internal/ReaderMgr.cpp | 207 ++++++++++++++++++-------- - src/xercesc/internal/ReaderMgr.hpp | 92 ++++++++++-- - 4 files changed, 229 insertions(+), 82 deletions(-) - -diff --git a/src/xercesc/internal/DGXMLScanner.cpp b/src/xercesc/internal/DGXMLScanner.cpp -index 43342235a..895dfeb06 100644 ---- a/src/xercesc/internal/DGXMLScanner.cpp -+++ b/src/xercesc/internal/DGXMLScanner.cpp -@@ -1052,13 +1052,12 @@ void DGXMLScanner::scanDocTypeDecl() - DTDEntityDecl* declDTD = new (fMemoryManager) DTDEntityDecl(gDTDStr, false, fMemoryManager); - declDTD->setSystemId(sysId); - declDTD->setIsExternal(true); -- Janitor janDecl(declDTD); - - // Mark this one as a throw at end - reader->setThrowAtEnd(true); - - // And push it onto the stack, with its pseudo name -- fReaderMgr.pushReader(reader, declDTD); -+ fReaderMgr.pushReaderAdoptEntity(reader, declDTD); - - // Tell it its not in an include section - dtdScanner.scanExtSubsetDecl(false, true); -@@ -2131,13 +2130,12 @@ Grammar* DGXMLScanner::loadDTDGrammar(const InputSource& src, - DTDEntityDecl* declDTD = new (fMemoryManager) DTDEntityDecl(gDTDStr, false, fMemoryManager); - declDTD->setSystemId(src.getSystemId()); - declDTD->setIsExternal(true); -- Janitor janDecl(declDTD); - - // Mark this one as a throw at end - newReader->setThrowAtEnd(true); - - // And push it onto the stack, with its pseudo name -- fReaderMgr.pushReader(newReader, declDTD); -+ fReaderMgr.pushReaderAdoptEntity(newReader, declDTD); - - // If we have a doc type handler and advanced callbacks are enabled, - // call the doctype event. -diff --git a/src/xercesc/internal/IGXMLScanner.cpp b/src/xercesc/internal/IGXMLScanner.cpp -index 912ec0c62..d694b23e6 100644 ---- a/src/xercesc/internal/IGXMLScanner.cpp -+++ b/src/xercesc/internal/IGXMLScanner.cpp -@@ -1535,13 +1535,12 @@ void IGXMLScanner::scanDocTypeDecl() - DTDEntityDecl* declDTD = new (fMemoryManager) DTDEntityDecl(gDTDStr, false, fMemoryManager); - declDTD->setSystemId(sysId); - declDTD->setIsExternal(true); -- Janitor janDecl(declDTD); - - // Mark this one as a throw at end - reader->setThrowAtEnd(true); - - // And push it onto the stack, with its pseudo name -- fReaderMgr.pushReader(reader, declDTD); -+ fReaderMgr.pushReaderAdoptEntity(reader, declDTD); - - // Tell it its not in an include section - dtdScanner.scanExtSubsetDecl(false, true); -@@ -3098,13 +3097,12 @@ Grammar* IGXMLScanner::loadDTDGrammar(const InputSource& src, - DTDEntityDecl* declDTD = new (fMemoryManager) DTDEntityDecl(gDTDStr, false, fMemoryManager); - declDTD->setSystemId(src.getSystemId()); - declDTD->setIsExternal(true); -- Janitor janDecl(declDTD); - - // Mark this one as a throw at end - newReader->setThrowAtEnd(true); - - // And push it onto the stack, with its pseudo name -- fReaderMgr.pushReader(newReader, declDTD); -+ fReaderMgr.pushReaderAdoptEntity(newReader, declDTD); - - // If we have a doc type handler and advanced callbacks are enabled, - // call the doctype event. -diff --git a/src/xercesc/internal/ReaderMgr.cpp b/src/xercesc/internal/ReaderMgr.cpp -index d14483e3c..9f363a071 100644 ---- a/src/xercesc/internal/ReaderMgr.cpp -+++ b/src/xercesc/internal/ReaderMgr.cpp -@@ -45,12 +45,61 @@ - - XERCES_CPP_NAMESPACE_BEGIN - -+// --------------------------------------------------------------------------- -+// ReaderMgr::ReaderData: Constructors and Destructor -+// --------------------------------------------------------------------------- -+ReaderMgr::ReaderData::ReaderData( XMLReader* const reader -+ , XMLEntityDecl* const entity -+ , const bool adoptEntity) : -+ -+ fReader(reader) -+ , fEntity(entity) -+ , fEntityAdopted(adoptEntity) -+{ -+} -+ -+ReaderMgr::ReaderData::~ReaderData() -+{ -+ delete fReader; -+ -+ if (fEntityAdopted) -+ delete fEntity; -+} -+ -+// --------------------------------------------------------------------------- -+// ReaderMgr::ReaderData: Getter methods -+// --------------------------------------------------------------------------- -+XMLReader* ReaderMgr::ReaderData::getReader() const -+{ -+ return fReader; -+} -+ -+XMLEntityDecl* ReaderMgr::ReaderData::getEntity() const -+{ -+ return fEntity; -+} -+ -+bool ReaderMgr::ReaderData::getEntityAdopted() const -+{ -+ return fEntityAdopted; -+} -+ -+// -+// This method gives up the entity object ownership but leaves the fEntity -+// pointer intact. -+// -+XMLEntityDecl* ReaderMgr::ReaderData::releaseEntity() -+{ -+ fEntityAdopted = false; -+ return fEntity; -+} -+ - // --------------------------------------------------------------------------- - // ReaderMgr: Constructors and Destructor - // --------------------------------------------------------------------------- - ReaderMgr::ReaderMgr(MemoryManager* const manager) : - -- fCurEntity(0) -+ fCurReaderData(0) - , fCurReader(0) - , fEntityHandler(0) - , fEntityStack(0) -@@ -66,12 +115,11 @@ ReaderMgr::ReaderMgr(MemoryManager* const manager) : - ReaderMgr::~ReaderMgr() - { - // -- // Clean up the reader and entity stacks. Note that we don't own the -- // entities, so we don't delete the current entity (and the entity stack -- // does not own its elements either, so deleting it will not delete the -- // entities it still references!) -+ // Clean up the reader stack and orphan entities container. Note that -+ // all adopted entities (potentially contained in fCurReaderData, -+ // fReaderStack, and fEntityStack) are deleted here. - // -- delete fCurReader; -+ delete fCurReaderData; - delete fReaderStack; - delete fEntityStack; - } -@@ -357,9 +405,9 @@ void ReaderMgr::cleanStackBackTo(const XMLSize_t readerNum) - if (fReaderStack->empty()) - ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::RdrMgr_ReaderIdNotFound, fMemoryManager); - -- delete fCurReader; -- fCurReader = fReaderStack->pop(); -- fCurEntity = fEntityStack->pop(); -+ delete fCurReaderData; -+ fCurReaderData = fReaderStack->pop(); -+ fCurReader = fCurReaderData->getReader (); - } - } - -@@ -795,20 +843,20 @@ const XMLCh* ReaderMgr::getCurrentEncodingStr() const - - const XMLEntityDecl* ReaderMgr::getCurrentEntity() const - { -- return fCurEntity; -+ return fCurReaderData? fCurReaderData->getEntity() : 0; - } - - - XMLEntityDecl* ReaderMgr::getCurrentEntity() - { -- return fCurEntity; -+ return fCurReaderData? fCurReaderData->getEntity() : 0; - } - - - XMLSize_t ReaderMgr::getReaderDepth() const - { - // If the stack doesn't exist, its obviously zero -- if (!fEntityStack) -+ if (!fReaderStack) - return 0; - - // -@@ -816,7 +864,7 @@ XMLSize_t ReaderMgr::getReaderDepth() const - // reader. So if there is no current reader and none on the stack, - // its zero, else its some non-zero value. - // -- XMLSize_t retVal = fEntityStack->size(); -+ XMLSize_t retVal = fReaderStack->size(); - if (fCurReader) - retVal++; - return retVal; -@@ -852,7 +900,7 @@ void ReaderMgr::getLastExtEntityInfo(LastExtEntityInfo& lastInfo) const - bool ReaderMgr::isScanningPERefOutOfLiteral() const - { - // If the current reader is not for an entity, then definitely not -- if (!fCurEntity) -+ if (!fCurReaderData || !fCurReaderData->getEntity()) - return false; - - // -@@ -867,13 +915,19 @@ bool ReaderMgr::isScanningPERefOutOfLiteral() const - return false; - } - -- - bool ReaderMgr::pushReader( XMLReader* const reader - , XMLEntityDecl* const entity) -+{ -+ return pushReaderAdoptEntity(reader, entity, false); -+} -+ -+bool ReaderMgr::pushReaderAdoptEntity( XMLReader* const reader -+ , XMLEntityDecl* const entity -+ , const bool adoptEntity) - { - // - // First, if an entity was passed, we have to confirm that this entity -- // is not already on the entity stack. If so, then this is a recursive -+ // is not already on the reader stack. If so, then this is a recursive - // entity expansion, so we issue an error and refuse to put the reader - // on the stack. - // -@@ -881,19 +935,30 @@ bool ReaderMgr::pushReader( XMLReader* const reader - // nothing to do. If there is no entity stack yet, then of coures it - // cannot already be there. - // -- if (entity && fEntityStack) -+ if (entity && fReaderStack) - { -- const XMLSize_t count = fEntityStack->size(); -+ // @@ Strangely, we don't check the entity at the top of the stack -+ // (fCurReaderData). Is it a bug? -+ // -+ const XMLSize_t count = fReaderStack->size(); - const XMLCh* const theName = entity->getName(); - for (XMLSize_t index = 0; index < count; index++) - { -- const XMLEntityDecl* curDecl = fEntityStack->elementAt(index); -+ const XMLEntityDecl* curDecl = -+ fReaderStack->elementAt(index)->getEntity(); -+ - if (curDecl) - { - if (XMLString::equals(theName, curDecl->getName())) - { -- // Oops, already there so delete reader and return -+ // Oops, already there so delete reader and entity and -+ // return. -+ // - delete reader; -+ -+ if (adoptEntity) -+ delete entity; -+ - return false; - } - } -@@ -905,52 +970,37 @@ bool ReaderMgr::pushReader( XMLReader* const reader - // tell it it does own its elements. - // - if (!fReaderStack) -- fReaderStack = new (fMemoryManager) RefStackOf(16, true, fMemoryManager); -- -- // And the entity stack, which does not own its elements -- if (!fEntityStack) -- fEntityStack = new (fMemoryManager) RefStackOf(16, false, fMemoryManager); -+ fReaderStack = new (fMemoryManager) RefStackOf(16, true, fMemoryManager); - - // -- // Push the current reader and entity onto their respective stacks. -- // Note that the the current entity can be null if the current reader -- // is not for an entity. -+ // Push the current reader and entity onto the stack. Note that -+ // the current entity can be null if the current reader is not for -+ // an entity. - // -- if (fCurReader) -- { -- fReaderStack->push(fCurReader); -- fEntityStack->push(fCurEntity); -- } -+ if (fCurReaderData) -+ fReaderStack->push(fCurReaderData); - - // - // Make the passed reader and entity the current top of stack. The - // passed entity can (and often is) null. - // -+ fCurReaderData = new (fMemoryManager) ReaderData(reader, entity, adoptEntity); - fCurReader = reader; -- fCurEntity = entity; - - return true; - } - -- - void ReaderMgr::reset() - { - // Reset all of the flags - fThrowEOE = false; - - // Delete the current reader and flush the reader stack -- delete fCurReader; -+ delete fCurReaderData; -+ fCurReaderData = 0; - fCurReader = 0; - if (fReaderStack) - fReaderStack->removeAllElements(); -- -- // -- // And do the same for the entity stack, but don't delete the current -- // entity (if any) since we don't own them. -- // -- fCurEntity = 0; -- if (fEntityStack) -- fEntityStack->removeAllElements(); - } - - -@@ -1014,7 +1064,9 @@ ReaderMgr::getLastExtEntity(const XMLEntityDecl*& itsEntity) const - // search the stack; else, keep the reader that we've got since its - // either an external entity reader or the main file reader. - // -- const XMLEntityDecl* curEntity = fCurEntity; -+ const XMLEntityDecl* curEntity = -+ fCurReaderData? fCurReaderData->getEntity() : 0; -+ - if (curEntity && !curEntity->isExternal()) - { - XMLSize_t index = fReaderStack->size(); -@@ -1024,7 +1076,7 @@ ReaderMgr::getLastExtEntity(const XMLEntityDecl*& itsEntity) const - { - // Move down to the previous element and get a pointer to it - index--; -- curEntity = fEntityStack->elementAt(index); -+ curEntity = fReaderStack->elementAt(index)->getEntity(); - - // - // If its null or its an external entity, then this reader -@@ -1032,12 +1084,12 @@ ReaderMgr::getLastExtEntity(const XMLEntityDecl*& itsEntity) const - // - if (!curEntity) - { -- theReader = fReaderStack->elementAt(index); -+ theReader = fReaderStack->elementAt(index)->getReader (); - break; - } - else if (curEntity->isExternal()) - { -- theReader = fReaderStack->elementAt(index); -+ theReader = fReaderStack->elementAt(index)->getReader (); - break; - } - -@@ -1048,6 +1100,11 @@ ReaderMgr::getLastExtEntity(const XMLEntityDecl*& itsEntity) const - } - } - -+ // @@ It feels like we may end up with theReader being from the top of -+ // the stack (fCurReader) and itsEntity being from the bottom of the -+ // stack (if there are no null or external entities on the stack). -+ // Is it a bug? -+ // - itsEntity = curEntity; - return theReader; - } -@@ -1059,31 +1116,59 @@ bool ReaderMgr::popReader() - // We didn't get any more, so try to pop off a reader. If the reader - // stack is empty, then we are at the end, so return false. - // -+ // @@ It feels like we never pop the reader pushed to the stack first -+ // (think of fReaderStack empty but fCurReader not null). Is it a -+ // bug? -+ // - if (fReaderStack->empty()) - return false; - - // -- // Remember the current entity, before we pop off a new one. We might -+ // Remember the current reader, before we pop off a new one. We might - // need this to throw the end of entity exception at the end. - // -- XMLEntityDecl* prevEntity = fCurEntity; -+ ReaderData* prevReaderData = fCurReaderData; - const bool prevReaderThrowAtEnd = fCurReader->getThrowAtEnd(); - const XMLSize_t readerNum = fCurReader->getReaderNum(); - - // -- // Delete the current reader and pop a new reader and entity off -- // the stacks. -+ // Pop a new reader and entity off the stack. - // -- delete fCurReader; -- fCurReader = fReaderStack->pop(); -- fCurEntity = fEntityStack->pop(); -+ fCurReaderData = fReaderStack->pop(); -+ fCurReader = fCurReaderData->getReader(); - - // - // If there was a previous entity, and either the fThrowEOE flag is set -- // or reader was marked as such, then throw an end of entity. -+ // or reader was marked as such, then throw an end of entity. Otherwise, -+ // delete the previous reader data. - // -- if (prevEntity && (fThrowEOE || prevReaderThrowAtEnd)) -- throw EndOfEntityException(prevEntity, readerNum); -+ if (prevReaderData->getEntity() && (fThrowEOE || prevReaderThrowAtEnd)) -+ { -+ // -+ // If the entity is adopted, then move it to fEntityStack so that -+ // its life-time is prolonged to the life-time of this reader -+ // manager. Also delete the previous reader data before throwing -+ // EndOfEntityException. -+ // -+ XMLEntityDecl* entity; -+ -+ if (prevReaderData->getEntityAdopted()) -+ { -+ if (!fEntityStack) -+ fEntityStack = new (fMemoryManager) RefStackOf(16, true, fMemoryManager); -+ -+ entity = prevReaderData->releaseEntity(); -+ fEntityStack->push(entity); -+ } -+ else -+ entity = prevReaderData->getEntity(); -+ -+ delete prevReaderData; -+ -+ throw EndOfEntityException(entity, readerNum); -+ } -+ else -+ delete prevReaderData; - - while (true) - { -@@ -1113,9 +1198,9 @@ bool ReaderMgr::popReader() - return false; - - // Else pop again and try it one more time -- delete fCurReader; -- fCurReader = fReaderStack->pop(); -- fCurEntity = fEntityStack->pop(); -+ delete fCurReaderData; -+ fCurReaderData = fReaderStack->pop(); -+ fCurReader = fCurReaderData->getReader(); - } - return true; - } -diff --git a/src/xercesc/internal/ReaderMgr.hpp b/src/xercesc/internal/ReaderMgr.hpp -index f63b2194e..0855ed77a 100644 ---- a/src/xercesc/internal/ReaderMgr.hpp -+++ b/src/xercesc/internal/ReaderMgr.hpp -@@ -160,6 +160,12 @@ public : - XMLReader* const reader - , XMLEntityDecl* const entity - ); -+ bool pushReaderAdoptEntity -+ ( -+ XMLReader* const reader -+ , XMLEntityDecl* const entity -+ , const bool adoptEntity = true -+ ); - void reset(); - - -@@ -208,16 +214,72 @@ private : - ReaderMgr(const ReaderMgr&); - ReaderMgr& operator=(const ReaderMgr&); - -+ // ----------------------------------------------------------------------- -+ // Private data types -+ // ----------------------------------------------------------------------- -+ class ReaderData : public XMemory -+ { -+ public : -+ // --------------------------------------------------------------------- -+ // Constructors and Destructor -+ // --------------------------------------------------------------------- -+ ReaderData -+ ( XMLReader* const reader -+ , XMLEntityDecl* const entity -+ , const bool adoptEntity -+ ); -+ -+ ~ReaderData(); -+ -+ // ---------------------------------------------------------------------- -+ // Getter methods -+ // ---------------------------------------------------------------------- -+ XMLReader* getReader() const; -+ XMLEntityDecl* getEntity() const; -+ bool getEntityAdopted() const; -+ -+ XMLEntityDecl* releaseEntity(); -+ -+ private : -+ // --------------------------------------------------------------------- -+ // Unimplemented constructors and operators -+ // --------------------------------------------------------------------- -+ ReaderData(); -+ ReaderData(const ReaderData&); -+ ReaderData& operator=(const ReaderData&); -+ -+ // --------------------------------------------------------------------- -+ // Private data members -+ // -+ // fReader -+ // This is the pointer to the reader object that must be destroyed -+ // when this object is destroyed. -+ // -+ // fEntity -+ // fEntityAdopted -+ // This is the pointer to the entity object that, if adopted, must -+ // be destroyed when this object is destroyed. -+ // -+ // Note that we need to keep up with which of the pushed readers -+ // are pushed entity values that are being spooled. This is done -+ // to avoid the problem of recursive definitions. -+ // --------------------------------------------------------------------- -+ XMLReader* fReader; -+ XMLEntityDecl* fEntity; -+ bool fEntityAdopted; -+ }; -+ - // ----------------------------------------------------------------------- - // Private data members - // -- // fCurEntity -- // This is the current top of stack entity. We pull it off the stack -- // and store it here for efficiency. -+ // fCurReaderData -+ // This is the current top of the reader data stack. We pull it off -+ // the stack and store it here for efficiency. - // - // fCurReader -- // This is the current top of stack reader. We pull it off the -- // stack and store it here for efficiency. -+ // This is the reader of the current top of the reader data stack. -+ // It contains the same value as fCurReaderData->fReader or NULL, -+ // if fCurReaderData is NULL. We store it here for efficiency. - // - // fEntityHandler - // This is the installed entity handler. Its installed via the -@@ -225,10 +287,14 @@ private : - // process of creating external entity readers. - // - // fEntityStack -- // We need to keep up with which of the pushed readers are pushed -- // entity values that are being spooled. This is done to avoid the -- // problem of recursive definitions. This stack consists of refs to -- // EntityDecl objects for the pushed entities. -+ // This is a storage of orphaned XMLEntityDecl objects. The -+ // popReader() function adds a reader manager-adopted entity object -+ // to this storage before passing its pointer to the constructor -+ // of the being thrown EndOfEntityException exception. This makes -+ // sure that the life-time of an entity exposed to the exception -+ // handlers is the same as the life-time of reader manager (and so -+ // normally the life-time of the scanner which embeds the reader -+ // manager). - // - // fNextReaderNum - // This is the reader serial number value. Each new reader that is -@@ -236,8 +302,8 @@ private : - // us catch things like partial markup errors and such. - // - // fReaderStack -- // This is the stack of reader references. We own all the readers -- // and destroy them when they are used up. -+ // This is the stack of reader data references. We own all the -+ // entries and destroy them when they are used up. - // - // fThrowEOE - // This flag controls whether we throw an exception when we hit an -@@ -252,12 +318,12 @@ private : - // fStandardUriConformant - // This flag controls whether we force conformant URI - // ----------------------------------------------------------------------- -- XMLEntityDecl* fCurEntity; -+ ReaderData* fCurReaderData; - XMLReader* fCurReader; - XMLEntityHandler* fEntityHandler; - RefStackOf* fEntityStack; - unsigned int fNextReaderNum; -- RefStackOf* fReaderStack; -+ RefStackOf* fReaderStack; - bool fThrowEOE; - XMLReader::XMLVersion fXMLVersion; - bool fStandardUriConformant; diff --git a/xerces-c-3.2.4.tar.gz b/xerces-c-3.2.5.tar.gz similarity index 49% rename from xerces-c-3.2.4.tar.gz rename to xerces-c-3.2.5.tar.gz index 102c3c4f5e5d1ef32ea341f3d432a92166d4b3f4..8650c2ed3149562c51fef26df8dcb43d22ee118c 100644 Binary files a/xerces-c-3.2.4.tar.gz and b/xerces-c-3.2.5.tar.gz differ diff --git a/xerces-c.spec b/xerces-c.spec index 11772ea9a66cd93872adcebf5f91c25b19e1eeca..eca5d52541ac987b9aff04c6a0199b8358a71626 100644 --- a/xerces-c.spec +++ b/xerces-c.spec @@ -1,11 +1,10 @@ Name: xerces-c -Version: 3.2.4 -Release: 2 +Version: 3.2.5 +Release: 1 Summary: A Validating XML Parser License: ASL 2.0 URL: http://xml.apache.org/xerces-c/ Source0: http://archive.apache.org/dist/xerces/c/3/sources/xerces-c-%{version}.tar.gz -Patch1: CVE-2018-1311.patch BuildRequires: dos2unix gcc-c++ @@ -66,6 +65,9 @@ rm -rf $RPM_BUILD_ROOT%{_bindir} %doc README NOTICE CREDITS doc _docs/* %changelog +* Thu Mar 21 2024 maqi - 3.2.5-1 +- Upgrade package to 3.2.5 version + * Wed Feb 21 2024 wangkai <13474090681@163.com> - 3.2.4-2 - Refix CVE-2018-1311