diff --git a/xerces-c-CVE-2016-0729.patch b/xerces-c-CVE-2016-0729.patch new file mode 100644 index 0000000..05f5e1f --- /dev/null +++ b/xerces-c-CVE-2016-0729.patch @@ -0,0 +1,377 @@ +Index: xerces-c-3.1.1/src/xercesc/internal/XMLReader.cpp +=================================================================== +--- xerces-c-3.1.1.orig/src/xercesc/internal/XMLReader.cpp ++++ xerces-c-3.1.1/src/xercesc/internal/XMLReader.cpp +@@ -1460,8 +1460,30 @@ void XMLReader::doInitDecode() + + while (fRawBufIndex < fRawBytesAvail) + { +- // Security fix: make sure there are at least sizeof(UCS4Ch) bytes to consume. ++ // Make sure there are at least sizeof(UCS4Ch) bytes to consume. + if (fRawBufIndex + sizeof(UCS4Ch) > fRawBytesAvail) { ++ fCharsAvail = 0; ++ fRawBufIndex = 0; ++ fMemoryManager->deallocate(fPublicId); ++ fMemoryManager->deallocate(fEncodingStr); ++ ArrayJanitor janValue(fSystemId, fMemoryManager); ++ ThrowXMLwithMemMgr1 ++ ( ++ TranscodingException ++ , XMLExcepts::Reader_CouldNotDecodeFirstLine ++ , fSystemId ++ , fMemoryManager ++ ); ++ } ++ ++ // Make sure we don't exhaust the limited prolog buffer size. ++ // Leave room for a space added at the end of this function. ++ if (fCharsAvail == kCharBufSize - 1) { ++ fCharsAvail = 0; ++ fRawBufIndex = 0; ++ fMemoryManager->deallocate(fPublicId); ++ fMemoryManager->deallocate(fEncodingStr); ++ ArrayJanitor janValue(fSystemId, fMemoryManager); + ThrowXMLwithMemMgr1 + ( + TranscodingException +@@ -1547,6 +1569,23 @@ void XMLReader::doInitDecode() + const char curCh = *asChars++; + fRawBufIndex++; + ++ // Make sure we don't exhaust the limited prolog buffer size. ++ // Leave room for a space added at the end of this function. ++ if (fCharsAvail == kCharBufSize - 1) { ++ fCharsAvail = 0; ++ fRawBufIndex = 0; ++ fMemoryManager->deallocate(fPublicId); ++ fMemoryManager->deallocate(fEncodingStr); ++ ArrayJanitor janValue(fSystemId, fMemoryManager); ++ ThrowXMLwithMemMgr1 ++ ( ++ TranscodingException ++ , XMLExcepts::Reader_CouldNotDecodeFirstLine ++ , fSystemId ++ , fMemoryManager ++ ); ++ } ++ + // Looks ok, so store it + fCharSizeBuf[fCharsAvail] = 1; + fCharBuf[fCharsAvail++] = XMLCh(curCh); +@@ -1630,8 +1669,30 @@ void XMLReader::doInitDecode() + + while (fRawBufIndex < fRawBytesAvail) + { +- // Security fix: make sure there are at least sizeof(UTF16Ch) bytes to consume. ++ // Make sure there are at least sizeof(UTF16Ch) bytes to consume. + if (fRawBufIndex + sizeof(UTF16Ch) > fRawBytesAvail) { ++ fCharsAvail = 0; ++ fRawBufIndex = 0; ++ fMemoryManager->deallocate(fPublicId); ++ fMemoryManager->deallocate(fEncodingStr); ++ ArrayJanitor janValue(fSystemId, fMemoryManager); ++ ThrowXMLwithMemMgr1 ++ ( ++ TranscodingException ++ , XMLExcepts::Reader_CouldNotDecodeFirstLine ++ , fSystemId ++ , fMemoryManager ++ ); ++ } ++ ++ // Make sure we don't exhaust the limited prolog buffer size. ++ // Leave room for a space added at the end of this function. ++ if (fCharsAvail == kCharBufSize - 1) { ++ fCharsAvail = 0; ++ fRawBufIndex = 0; ++ fMemoryManager->deallocate(fPublicId); ++ fMemoryManager->deallocate(fEncodingStr); ++ ArrayJanitor janValue(fSystemId, fMemoryManager); + ThrowXMLwithMemMgr1 + ( + TranscodingException +@@ -1676,6 +1737,24 @@ void XMLReader::doInitDecode() + const XMLCh chCur = XMLEBCDICTranscoder::xlatThisOne(*srcPtr++); + fRawBufIndex++; + ++ // Make sure we don't exhaust the limited prolog buffer size. ++ // Leave room for a space added at the end of this function. ++ if (fCharsAvail == kCharBufSize - 1) { ++ fCharsAvail = 0; ++ fRawBufIndex = 0; ++ fMemoryManager->deallocate(fPublicId); ++ fMemoryManager->deallocate(fEncodingStr); ++ ArrayJanitor janValue(fSystemId, fMemoryManager); ++ ThrowXMLwithMemMgr1 ++ ( ++ TranscodingException ++ , XMLExcepts::Reader_CouldNotDecodeFirstLine ++ , fSystemId ++ , fMemoryManager ++ ); ++ } ++ ++ + // + // And put it into the character buffer. This stuff has to + // look like it was normally transcoded. +@@ -1730,7 +1809,7 @@ void XMLReader::doInitDecode() + // + void XMLReader::refreshRawBuffer() + { +- // Security fix: make sure we don't underflow on the subtraction. ++ // Make sure we don't underflow on the subtraction. + if (fRawBufIndex > fRawBytesAvail) { + ThrowXMLwithMemMgr1 + ( +Index: xerces-c-3.1.1/src/xercesc/util/XMLURL.cpp +=================================================================== +--- xerces-c-3.1.1.orig/src/xercesc/util/XMLURL.cpp ++++ xerces-c-3.1.1/src/xercesc/util/XMLURL.cpp +@@ -611,9 +611,20 @@ BinInputStream* XMLURL::makeNewStream() + + while (percentIndex != -1) { + +- if (percentIndex+2 >= (int)end || +- !isHexDigit(realPath[percentIndex+1]) || +- !isHexDigit(realPath[percentIndex+2])) ++ // Isolate the length/boundary check so we don't try and copy off the end. ++ if (percentIndex+2 >= (int)end) ++ { ++ XMLCh value1[3]; ++ value1[1] = chNull; ++ value1[2] = chNull; ++ XMLString::moveChars(value1, &(realPath[percentIndex]), (percentIndex + 1 >= (int)end ? 1 : 2)); ++ ThrowXMLwithMemMgr2(MalformedURLException ++ , XMLExcepts::XMLNUM_URI_Component_Invalid_EscapeSequence ++ , realPath ++ , value1 ++ , fMemoryManager); ++ } ++ else if (!isHexDigit(realPath[percentIndex+1]) || !isHexDigit(realPath[percentIndex+2])) + { + XMLCh value1[4]; + XMLString::moveChars(value1, &(realPath[percentIndex]), 3); +Index: xerces-c-3.1.1/src/xercesc/util/XMLUri.cpp +=================================================================== +--- xerces-c-3.1.1.orig/src/xercesc/util/XMLUri.cpp ++++ xerces-c-3.1.1/src/xercesc/util/XMLUri.cpp +@@ -875,11 +875,21 @@ void XMLUri::initializePath(const XMLCh* + // check for valid escape sequence + if (testChar == chPercent) + { +- if (index+2 >= end || +- !XMLString::isHex(uriSpec[index+1]) || +- !XMLString::isHex(uriSpec[index+2])) ++ if (index + 2 >= end) + { +- XMLCh value1[BUF_LEN+1]; ++ XMLCh value1[3]; ++ value1[1] = chNull; ++ value1[2] = chNull; ++ XMLString::moveChars(value1, &(uriSpec[index]), (index + 1 >= end ? 1 : 2)); ++ ThrowXMLwithMemMgr2(MalformedURLException ++ , XMLExcepts::XMLNUM_URI_Component_Invalid_EscapeSequence ++ , errMsg_PATH ++ , value1 ++ , fMemoryManager); ++ } ++ else if (!XMLString::isHex(uriSpec[index+1]) || !XMLString::isHex(uriSpec[index+2])) ++ { ++ XMLCh value1[4]; + XMLString::moveChars(value1, &(uriSpec[index]), 3); + value1[3] = chNull; + ThrowXMLwithMemMgr2(MalformedURLException +@@ -892,7 +902,7 @@ void XMLUri::initializePath(const XMLCh* + else if (!isUnreservedCharacter(testChar) && + !isPathCharacter(testChar)) + { +- XMLCh value1[BUF_LEN+1]; ++ XMLCh value1[2]; + value1[0] = testChar; + value1[1] = chNull; + ThrowXMLwithMemMgr2(MalformedURLException +@@ -920,11 +930,21 @@ void XMLUri::initializePath(const XMLCh* + // check for valid escape sequence + if (testChar == chPercent) + { +- if (index+2 >= end || +- !XMLString::isHex(uriSpec[index+1]) || +- !XMLString::isHex(uriSpec[index+2])) ++ if (index + 2 >= end) + { +- XMLCh value1[BUF_LEN+1]; ++ XMLCh value1[3]; ++ value1[1] = chNull; ++ value1[2] = chNull; ++ XMLString::moveChars(value1, &(uriSpec[index]), (index + 1 >= end ? 1 : 2)); ++ ThrowXMLwithMemMgr2(MalformedURLException ++ , XMLExcepts::XMLNUM_URI_Component_Invalid_EscapeSequence ++ , errMsg_PATH ++ , value1 ++ , fMemoryManager); ++ } ++ else if (!XMLString::isHex(uriSpec[index+1]) || !XMLString::isHex(uriSpec[index+2])) ++ { ++ XMLCh value1[4]; + XMLString::moveChars(value1, &(uriSpec[index]), 3); + value1[3] = chNull; + ThrowXMLwithMemMgr2(MalformedURLException +@@ -941,7 +961,7 @@ void XMLUri::initializePath(const XMLCh* + // contains '[' and ']'. + else if (!isReservedOrUnreservedCharacter(testChar)) + { +- XMLCh value1[BUF_LEN+1]; ++ XMLCh value1[2]; + value1[0] = testChar; + value1[1] = chNull; + ThrowXMLwithMemMgr2(MalformedURLException +@@ -979,11 +999,21 @@ void XMLUri::initializePath(const XMLCh* + + if (testChar == chPercent) + { +- if (index+2 >= end || +- !XMLString::isHex(uriSpec[index+1]) || +- !XMLString::isHex(uriSpec[index+2])) ++ if (index + 2 >= end) ++ { ++ XMLCh value1[3]; ++ value1[1] = chNull; ++ value1[2] = chNull; ++ XMLString::moveChars(value1, &(uriSpec[index]), (index + 1 >= end ? 1 : 2)); ++ ThrowXMLwithMemMgr2(MalformedURLException ++ , XMLExcepts::XMLNUM_URI_Component_Invalid_EscapeSequence ++ , errMsg_QUERY ++ , value1 ++ , fMemoryManager); ++ } ++ if (!XMLString::isHex(uriSpec[index+1]) || !XMLString::isHex(uriSpec[index+2])) + { +- XMLCh value1[BUF_LEN+1]; ++ XMLCh value1[4]; + XMLString::moveChars(value1, &(uriSpec[index]), 3); + value1[3] = chNull; + ThrowXMLwithMemMgr2(MalformedURLException +@@ -995,7 +1025,7 @@ void XMLUri::initializePath(const XMLCh* + } + else if (!isReservedOrUnreservedCharacter(testChar)) + { +- XMLCh value1[BUF_LEN+1]; ++ XMLCh value1[2]; + value1[0] = testChar; + value1[1] = chNull; + ThrowXMLwithMemMgr2(MalformedURLException +@@ -1030,11 +1060,21 @@ void XMLUri::initializePath(const XMLCh* + + if (testChar == chPercent) + { +- if (index+2 >= end || +- !XMLString::isHex(uriSpec[index+1]) || +- !XMLString::isHex(uriSpec[index+2])) ++ if (index + 2 >= end) ++ { ++ XMLCh value1[3]; ++ value1[1] = chNull; ++ value1[2] = chNull; ++ XMLString::moveChars(value1, &(uriSpec[index]), (index + 1 >= end ? 1 : 2)); ++ ThrowXMLwithMemMgr2(MalformedURLException ++ , XMLExcepts::XMLNUM_URI_Component_Invalid_EscapeSequence ++ , errMsg_FRAGMENT ++ , value1 ++ , fMemoryManager); ++ } ++ if (!XMLString::isHex(uriSpec[index+1]) || !XMLString::isHex(uriSpec[index+2])) + { +- XMLCh value1[BUF_LEN+1]; ++ XMLCh value1[4]; + XMLString::moveChars(value1, &(uriSpec[index]), 3); + value1[3] = chNull; + ThrowXMLwithMemMgr2(MalformedURLException +@@ -1046,7 +1086,7 @@ void XMLUri::initializePath(const XMLCh* + } + else if (!isReservedOrUnreservedCharacter(testChar)) + { +- XMLCh value1[BUF_LEN+1]; ++ XMLCh value1[2]; + value1[0] = testChar; + value1[1] = chNull; + ThrowXMLwithMemMgr2(MalformedURLException +@@ -1410,14 +1450,15 @@ void XMLUri::isConformantUserInfo(const + } + else if (*tmpStr == chPercent) // '%' + { +- if (XMLString::isHex(*(tmpStr+1)) && // 1st hex +- XMLString::isHex(*(tmpStr+2)) ) // 2nd hex ++ if (XMLString::stringLen(tmpStr) >= 3 ++ && XMLString::isHex(*(tmpStr+1)) // 1st hex ++ && XMLString::isHex(*(tmpStr+2)) ) // 2nd hex + { + tmpStr+=3; + } + else + { +- XMLCh value1[BUF_LEN+1]; ++ XMLCh value1[4]; + value1[0] = chPercent; + value1[1] = *(tmpStr+1); + value1[2] = *(tmpStr+2); +@@ -1468,8 +1509,9 @@ bool XMLUri::isValidServerBasedAuthority + } + else if (userinfo[index] == chPercent) // '%' + { +- if (XMLString::isHex(userinfo[index+1]) && // 1st hex +- XMLString::isHex(userinfo[index+2]) ) // 2nd hex ++ if (index + 2 < userLen ++ && XMLString::isHex(userinfo[index+1]) // 1st hex ++ && XMLString::isHex(userinfo[index+2]) ) // 2nd hex + index +=3; + else + return false; +@@ -1508,8 +1550,9 @@ bool XMLUri::isValidServerBasedAuthority + } + else if (*tmpStr == chPercent) // '%' + { +- if (XMLString::isHex(*(tmpStr+1)) && // 1st hex +- XMLString::isHex(*(tmpStr+2)) ) // 2nd hex ++ if (XMLString::stringLen(tmpStr) >= 3 ++ && XMLString::isHex(*(tmpStr+1)) // 1st hex ++ && XMLString::isHex(*(tmpStr+2)) ) // 2nd hex + { + tmpStr+=3; + } +@@ -1537,8 +1580,9 @@ bool XMLUri::isValidRegistryBasedAuthori + } + else if (authority[index] == chPercent) // '%' + { +- if (XMLString::isHex(authority[index+1]) && // 1st hex +- XMLString::isHex(authority[index+2]) ) // 2nd hex ++ if (index + 2 < authLen ++ && XMLString::isHex(authority[index+1]) // 1st hex ++ && XMLString::isHex(authority[index+2]) ) // 2nd hex + index +=3; + else + return false; +@@ -1566,8 +1610,9 @@ bool XMLUri::isValidRegistryBasedAuthori + } + else if (*tmpStr == chPercent) // '%' + { +- if (XMLString::isHex(*(tmpStr+1)) && // 1st hex +- XMLString::isHex(*(tmpStr+2)) ) // 2nd hex ++ if (XMLString::stringLen(tmpStr) >= 3 ++ && XMLString::isHex(*(tmpStr + 1)) // 1st hex ++ && XMLString::isHex(*(tmpStr + 2))) // 2nd hex + { + tmpStr+=3; + } +@@ -1602,8 +1647,9 @@ bool XMLUri::isURIString(const XMLCh* co + } + else if (*tmpStr == chPercent) // '%' + { +- if (XMLString::isHex(*(tmpStr+1)) && // 1st hex +- XMLString::isHex(*(tmpStr+2)) ) // 2nd hex ++ if (XMLString::stringLen(tmpStr) >=3 ++ && XMLString::isHex(*(tmpStr+1)) // 1st hex ++ && XMLString::isHex(*(tmpStr+2)) ) // 2nd hex + { + tmpStr+=3; + } diff --git a/xerces-c-CVE-2016-2099.patch b/xerces-c-CVE-2016-2099.patch new file mode 100644 index 0000000..dd7d59d --- /dev/null +++ b/xerces-c-CVE-2016-2099.patch @@ -0,0 +1,19 @@ +--- src/xercesc/validators/DTD/DTDScanner.cpp (revision 1741478) ++++ src/xercesc/validators/DTD/DTDScanner.cpp (working copy) +@@ -2509,7 +2509,15 @@ + { + while (true) + { +- const XMLCh nextCh = fReaderMgr->peekNextChar(); ++ XMLCh nextCh; ++ ++ try { ++ nextCh = fReaderMgr->peekNextChar(); ++ } ++ catch (XMLException& ex) { ++ fScanner->emitError(XMLErrs::XMLException_Fatal, ex.getCode(), ex.getMessage(), NULL, NULL); ++ nextCh = chNull; ++ } + + if (!nextCh) + { diff --git a/xerces-c.changes b/xerces-c.changes index d8c51d3..bc80829 100644 --- a/xerces-c.changes +++ b/xerces-c.changes @@ -1,3 +1,15 @@ +------------------------------------------------------------------- +Thu Jun 16 15:43:53 UTC 2016 - pjanouch@suse.de + +- added xerces-c-CVE-2016-2099.patch + Exception handling mistake causing use after free + (bsc#979208, CVE-2016-2099) +- xerces-c-CVE-2016-0729.patch + Fix for mishandling certain kinds of malformed input documents, + resulting in buffer overlows during processing and error reporting. + The overflows can manifest as a segmentation fault or as memory + corruption during a parse operation. (bsc#966822, CVE-2016-0729) + ------------------------------------------------------------------- Mon Sep 28 16:19:17 UTC 2015 - mpluskal@suse.com diff --git a/xerces-c.spec b/xerces-c.spec index 38bf26d..4b53df8 100644 --- a/xerces-c.spec +++ b/xerces-c.spec @@ -1,7 +1,7 @@ # # spec file for package xerces-c # -# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -27,6 +27,10 @@ Source0: http://www.apache.org/dist/xerces/c/3/sources/%{name}-%{version} Source1: http://www.apache.org/dist/xerces/c/3/sources/%{name}-%{version}.tar.gz.asc Source2: %{name}.keyring Source3: baselibs.conf +# PATCH-FIX-UPSTREAM bsc#966822 +Patch2: %{name}-CVE-2016-0729.patch +# PATCH-FIX-UPSTREAM bsc#979208 +Patch3: %{name}-CVE-2016-2099.patch BuildRequires: fdupes BuildRequires: gcc-c++ BuildRequires: libicu-devel @@ -91,6 +95,8 @@ This package includes files needed for development with Xerces-c %prep %setup -q -n xerces-c-%{version} +%patch2 -p1 +%patch3 -p0 %build %configure \