Base: Fixed segfault on destructing cached string (#20563)
* Base: Fixed segfault on destructing cached string Xerces default memory manager is deleted before destructing static local variable and segfault. --------- Co-authored-by: Chris Hennes <chennes@pioneerlibrarysystem.org>
This commit is contained in:
@@ -67,6 +67,7 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <new>
|
||||
#include <numbers>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
@@ -82,6 +83,7 @@
|
||||
#include <sstream>
|
||||
|
||||
// Xerces
|
||||
#include <xercesc/util/OutOfMemoryException.hpp>
|
||||
#include <xercesc/util/PlatformUtils.hpp>
|
||||
#include <xercesc/util/XercesVersion.hpp>
|
||||
#include <xercesc/dom/DOM.hpp>
|
||||
@@ -95,6 +97,7 @@
|
||||
#include <xercesc/framework/LocalFileInputSource.hpp>
|
||||
#include <xercesc/framework/MemBufFormatTarget.hpp>
|
||||
#include <xercesc/framework/MemBufInputSource.hpp>
|
||||
#include <xercesc/framework/MemoryManager.hpp>
|
||||
#include <xercesc/parsers/XercesDOMParser.hpp>
|
||||
#include <xercesc/util/XMLUni.hpp>
|
||||
#include <xercesc/util/XMLUniDefs.hpp>
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
#include <xercesc/framework/MemoryManager.hpp>
|
||||
#include <xercesc/util/OutOfMemoryException.hpp>
|
||||
#endif
|
||||
|
||||
#include "Exception.h"
|
||||
#include "XMLTools.h"
|
||||
|
||||
@@ -128,3 +133,19 @@ void XMLTools::terminate()
|
||||
{
|
||||
transcoder.reset();
|
||||
}
|
||||
|
||||
void* XStrMemoryManager::allocate(XMLSize_t size)
|
||||
{
|
||||
auto ptr = ::operator new(static_cast<size_t>(size),
|
||||
static_cast<std::align_val_t>(alignof(XMLCh)),
|
||||
std::nothrow);
|
||||
if (ptr == nullptr && size != 0) {
|
||||
throw XERCES_CPP_NAMESPACE::OutOfMemoryException();
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void XStrMemoryManager::deallocate(void* p)
|
||||
{
|
||||
::operator delete(p);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <xercesc/util/TransService.hpp>
|
||||
#include <xercesc/framework/MemoryManager.hpp>
|
||||
|
||||
#ifndef XERCES_CPP_NAMESPACE_BEGIN
|
||||
#define XERCES_CPP_NAMESPACE_QUALIFIER
|
||||
@@ -58,6 +59,23 @@ private:
|
||||
static std::unique_ptr<XERCES_CPP_NAMESPACE::XMLTranscoder> transcoder; // NOLINT
|
||||
};
|
||||
|
||||
// Helper class for XStrLiteral macro
|
||||
// This implementation is almost same as Xerces default memory manager.
|
||||
class BaseExport XStrMemoryManager final: public XERCES_CPP_NAMESPACE::MemoryManager
|
||||
{
|
||||
public:
|
||||
XStrMemoryManager() = default;
|
||||
~XStrMemoryManager() = default;
|
||||
|
||||
MemoryManager* getExceptionMemoryManager() override
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void* allocate(XMLSize_t size) override;
|
||||
void deallocate(void* p) override;
|
||||
};
|
||||
|
||||
//**************************************************************************
|
||||
//**************************************************************************
|
||||
// StrXLocal
|
||||
@@ -149,6 +167,8 @@ class XStr
|
||||
public:
|
||||
/// Constructors and Destructor
|
||||
explicit XStr(const char* const toTranscode);
|
||||
explicit XStr(const char* const toTranscode,
|
||||
XERCES_CPP_NAMESPACE_QUALIFIER MemoryManager* memMgr);
|
||||
~XStr();
|
||||
|
||||
|
||||
@@ -159,24 +179,35 @@ public:
|
||||
private:
|
||||
/// This is the Unicode XMLCh format of the string.
|
||||
XMLCh* fUnicodeForm;
|
||||
XERCES_CPP_NAMESPACE_QUALIFIER MemoryManager* memMgr;
|
||||
};
|
||||
|
||||
|
||||
inline XStr::XStr(const char* const toTranscode)
|
||||
: fUnicodeForm(XERCES_CPP_NAMESPACE_QUALIFIER XMLString::transcode(toTranscode))
|
||||
: XStr(toTranscode, XERCES_CPP_NAMESPACE_QUALIFIER XMLPlatformUtils::fgMemoryManager)
|
||||
{}
|
||||
|
||||
inline XStr::XStr(const char* const toTranscode,
|
||||
XERCES_CPP_NAMESPACE_QUALIFIER MemoryManager* memMgr)
|
||||
: fUnicodeForm(XERCES_CPP_NAMESPACE_QUALIFIER XMLString::transcode(toTranscode, memMgr))
|
||||
, memMgr(memMgr)
|
||||
{}
|
||||
|
||||
inline XStr::~XStr()
|
||||
{
|
||||
XERCES_CPP_NAMESPACE_QUALIFIER XMLString::release(&fUnicodeForm);
|
||||
XERCES_CPP_NAMESPACE_QUALIFIER XMLString::release(&fUnicodeForm, memMgr);
|
||||
}
|
||||
|
||||
// Uses the compiler to create a cache of transcoded string literals so that each subsequent call
|
||||
// can reuse the data from the lambda's initial creation. Permits the same usage as
|
||||
// XStr("literal").unicodeForm()
|
||||
// XStrLiteral macro use local memory manager instance to prevent segfault on releasing cached
|
||||
// string because xerces default memory manager is already deleted when destructing local static
|
||||
// variable.
|
||||
#define XStrLiteral(literal) \
|
||||
([]() -> const XStr& { \
|
||||
static const XStr str {literal}; \
|
||||
static XStrMemoryManager memMgr; \
|
||||
static const XStr str {literal, &memMgr}; \
|
||||
return str; \
|
||||
}())
|
||||
|
||||
|
||||
Reference in New Issue
Block a user