mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 20:12:31 +01:00
- Fix memory leak in libdoc.cpp in LIBXMLDOC::GetNodeList replacing
xmlXPathFreeNodeSetList(Xop); // Caused memory leak, by xmlXPathFreeObject(Xop); modified: storage/connect/libdoc.cpp
This commit is contained in:
parent
29f10f0ff1
commit
37fce46f66
1 changed files with 138 additions and 15 deletions
|
@ -30,6 +30,53 @@ extern char version[];
|
|||
extern int trace;
|
||||
} // "C"
|
||||
|
||||
#if defined(_DEBUG)
|
||||
static xmlFreeFunc Free;
|
||||
static xmlMallocFunc Malloc;
|
||||
static xmlMallocFunc MallocA;
|
||||
static xmlReallocFunc Realloc;
|
||||
static xmlStrdupFunc Strdup;
|
||||
|
||||
void xmlMyFree(void *mem)
|
||||
{
|
||||
if (trace)
|
||||
htrc("Freeing at %p\n", mem);
|
||||
Free(mem);
|
||||
} // end of xmlMyFree
|
||||
|
||||
void *xmlMyMalloc(size_t size)
|
||||
{
|
||||
void *p = Malloc(size);
|
||||
if (trace)
|
||||
htrc("Allocating %.5d at %p\n", size, p);
|
||||
return p;
|
||||
} // end of xmlMyMalloc
|
||||
|
||||
void *xmlMyMallocAtomic(size_t size)
|
||||
{
|
||||
void *p = MallocA(size);
|
||||
if (trace)
|
||||
htrc("Atom alloc %.5d at %p\n", size, p);
|
||||
return p;
|
||||
} // end of xmlMyMallocAtomic
|
||||
|
||||
void *xmlMyRealloc(void *mem, size_t size)
|
||||
{
|
||||
void *p = Realloc(mem, size);
|
||||
if (trace)
|
||||
htrc("ReAlloc %.5d to %p from %p\n", size, p, mem);
|
||||
return p;
|
||||
} // end of xmlMyRealloc
|
||||
|
||||
char *xmlMyStrdup(const char *str)
|
||||
{
|
||||
char *p = Strdup(str);
|
||||
if (trace)
|
||||
htrc("Duplicating to %p from %p %s\n", p, str, str);
|
||||
return p;
|
||||
} // end of xmlMyStrdup
|
||||
#endif // _DEBUG
|
||||
|
||||
/******************************************************************/
|
||||
/* Return a LIBXMLDOC as a XMLDOC. */
|
||||
/******************************************************************/
|
||||
|
@ -44,6 +91,17 @@ PXDOC GetLibxmlDoc(PGLOBAL g, char *nsl, char *nsdf,
|
|||
/******************************************************************/
|
||||
void XmlInitParserLib(void)
|
||||
{
|
||||
#if defined(_DEBUG)
|
||||
int rc = xmlGcMemGet(&Free, &Malloc, &MallocA, &Realloc, &Strdup);
|
||||
|
||||
if (!rc)
|
||||
rc = xmlGcMemSetup(xmlMyFree,
|
||||
xmlMyMalloc,
|
||||
xmlMyMallocAtomic,
|
||||
xmlMyRealloc,
|
||||
xmlMyStrdup);
|
||||
|
||||
#endif // _DEBUG
|
||||
xmlInitParser();
|
||||
} // end of XmlInitParserLib
|
||||
|
||||
|
@ -63,6 +121,9 @@ void CloseXML2File(PGLOBAL g, PFBLOCK fp, bool all)
|
|||
{
|
||||
PX2BLOCK xp = (PX2BLOCK)fp;
|
||||
|
||||
if (trace)
|
||||
htrc("CloseXML2File: xp=%p count=%d\n", xp, (xp) ? xp->Count : 0);
|
||||
|
||||
if (xp && xp->Count > 1 && !all) {
|
||||
xp->Count--;
|
||||
} else if (xp && xp->Count > 0) {
|
||||
|
@ -101,6 +162,9 @@ bool LIBXMLDOC::Initialize(PGLOBAL g)
|
|||
/******************************************************************/
|
||||
bool LIBXMLDOC::ParseFile(char *fn)
|
||||
{
|
||||
if (trace)
|
||||
htrc("ParseFile\n");
|
||||
|
||||
if ((Docp = xmlParseFile(fn))) {
|
||||
if (Docp->encoding)
|
||||
Encoding = (char*)Docp->encoding;
|
||||
|
@ -149,6 +213,9 @@ bool LIBXMLDOC::NewDoc(PGLOBAL g, char *ver)
|
|||
/******************************************************************/
|
||||
void LIBXMLDOC::AddComment(PGLOBAL g, char *txtp)
|
||||
{
|
||||
if (trace)
|
||||
htrc("AddComment: %s\n", txtp);
|
||||
|
||||
xmlNodePtr cp = xmlNewDocComment(Docp, BAD_CAST txtp);
|
||||
xmlAddChild((xmlNodePtr)Docp, cp);
|
||||
} // end of AddText
|
||||
|
@ -158,6 +225,9 @@ void LIBXMLDOC::AddComment(PGLOBAL g, char *txtp)
|
|||
/******************************************************************/
|
||||
PXNODE LIBXMLDOC::GetRoot(PGLOBAL g)
|
||||
{
|
||||
if (trace)
|
||||
htrc("GetRoot\n");
|
||||
|
||||
xmlNodePtr root = xmlDocGetRootElement(Docp);
|
||||
|
||||
if (!root)
|
||||
|
@ -171,6 +241,9 @@ PXNODE LIBXMLDOC::GetRoot(PGLOBAL g)
|
|||
/******************************************************************/
|
||||
PXNODE LIBXMLDOC::NewRoot(PGLOBAL g, char *name)
|
||||
{
|
||||
if (trace)
|
||||
htrc("NewRoot: %s\n", name);
|
||||
|
||||
xmlNodePtr root = xmlNewDocNode(Docp, NULL, BAD_CAST name, NULL);
|
||||
|
||||
if (root) {
|
||||
|
@ -186,6 +259,9 @@ PXNODE LIBXMLDOC::NewRoot(PGLOBAL g, char *name)
|
|||
/******************************************************************/
|
||||
PXNODE LIBXMLDOC::NewPnode(PGLOBAL g, char *name)
|
||||
{
|
||||
if (trace)
|
||||
htrc("NewNode: %s\n", name);
|
||||
|
||||
xmlNodePtr nop;
|
||||
|
||||
if (name) {
|
||||
|
@ -224,6 +300,9 @@ int LIBXMLDOC::DumpDoc(PGLOBAL g, char *ofn)
|
|||
int rc = 0;
|
||||
FILE *of;
|
||||
|
||||
if (trace)
|
||||
htrc("DumpDoc: %s\n", ofn);
|
||||
|
||||
if (!(of= global_fopen(g, MSGID_CANNOT_OPEN, ofn, "w")))
|
||||
return -1;
|
||||
|
||||
|
@ -264,6 +343,9 @@ int LIBXMLDOC::DumpDoc(PGLOBAL g, char *ofn)
|
|||
/******************************************************************/
|
||||
void LIBXMLDOC::CloseDoc(PGLOBAL g, PFBLOCK xp)
|
||||
{
|
||||
if (trace)
|
||||
htrc("CloseDoc: xp=%p count=%d\n", xp, (xp) ? xp->Count : 0);
|
||||
|
||||
if (xp && xp->Count == 1) {
|
||||
if (Xop)
|
||||
xmlXPathFreeObject(Xop);
|
||||
|
@ -284,12 +366,18 @@ xmlNodeSetPtr LIBXMLDOC::GetNodeList(PGLOBAL g, xmlNodePtr np, char *xp)
|
|||
xmlNodeSetPtr nl;
|
||||
|
||||
if (trace)
|
||||
htrc("GetNodeList %s np=%p\n", xp, np);
|
||||
htrc("GetNodeList: %s np=%p\n", xp, np);
|
||||
|
||||
if (!Ctxp) {
|
||||
// Init Xpath
|
||||
if (trace)
|
||||
htrc("Calling xmlPathInit\n");
|
||||
|
||||
xmlXPathInit();
|
||||
|
||||
if (trace)
|
||||
htrc("Calling xmlXPathNewContext Docp=%p\n", Docp);
|
||||
|
||||
// Create xpath evaluation context
|
||||
if (!(Ctxp = xmlXPathNewContext(Docp))) {
|
||||
strcpy(g->Message, MSG(XPATH_CNTX_ERR));
|
||||
|
@ -301,7 +389,11 @@ xmlNodeSetPtr LIBXMLDOC::GetNodeList(PGLOBAL g, xmlNodePtr np, char *xp)
|
|||
} // endif xpathCtx
|
||||
|
||||
// Register namespaces from list (if any)
|
||||
for (PNS nsp = Namespaces; nsp; nsp = nsp->Next)
|
||||
for (PNS nsp = Namespaces; nsp; nsp = nsp->Next) {
|
||||
if (trace)
|
||||
htrc("Calling xmlXPathRegisterNs Prefix=%s Uri=%s\n",
|
||||
nsp->Prefix, nsp->Uri);
|
||||
|
||||
if (xmlXPathRegisterNs(Ctxp, BAD_CAST nsp->Prefix,
|
||||
BAD_CAST nsp->Uri)) {
|
||||
sprintf(g->Message, MSG(REGISTER_ERR), nsp->Prefix, nsp->Uri);
|
||||
|
@ -312,12 +404,22 @@ xmlNodeSetPtr LIBXMLDOC::GetNodeList(PGLOBAL g, xmlNodePtr np, char *xp)
|
|||
return NULL;
|
||||
} // endif Registering
|
||||
|
||||
} else
|
||||
xmlXPathFreeNodeSetList(Xop); // To be checked
|
||||
} // endfor nsp
|
||||
|
||||
} else {
|
||||
if (trace)
|
||||
htrc("Calling xmlXPathFreeNodeSetList Xop=%p\n", Xop);
|
||||
|
||||
xmlXPathFreeObject(Xop);
|
||||
// xmlXPathFreeNodeSetList(Xop); // Caused memory leak
|
||||
} // endif Ctxp
|
||||
|
||||
// Set the context to the calling node
|
||||
Ctxp->node = np;
|
||||
|
||||
if (trace)
|
||||
htrc("Calling xmlXPathEval %s Ctxp=%p\n", xp, Ctxp);
|
||||
|
||||
// Evaluate table xpath
|
||||
if (!(Xop = xmlXPathEval(BAD_CAST xp, Ctxp))) {
|
||||
sprintf(g->Message, MSG(XPATH_EVAL_ERR), xp);
|
||||
|
@ -439,6 +541,9 @@ int XML2NODE::GetType(void)
|
|||
/******************************************************************/
|
||||
PXNODE XML2NODE::GetNext(PGLOBAL g)
|
||||
{
|
||||
if (trace)
|
||||
htrc("GetNext\n");
|
||||
|
||||
if (!Nodep->next)
|
||||
Next = NULL;
|
||||
else if (!Next)
|
||||
|
@ -452,6 +557,9 @@ PXNODE XML2NODE::GetNext(PGLOBAL g)
|
|||
/******************************************************************/
|
||||
PXNODE XML2NODE::GetChild(PGLOBAL g)
|
||||
{
|
||||
if (trace)
|
||||
htrc("GetChild\n");
|
||||
|
||||
if (!Nodep->children)
|
||||
Children = NULL;
|
||||
else if (!Children)
|
||||
|
@ -467,6 +575,9 @@ RCODE XML2NODE::GetContent(PGLOBAL g, char *buf, int len)
|
|||
{
|
||||
RCODE rc = RC_OK;
|
||||
|
||||
if (trace)
|
||||
htrc("GetContent\n");
|
||||
|
||||
if (Content)
|
||||
xmlFree(Content);
|
||||
|
||||
|
@ -505,18 +616,24 @@ RCODE XML2NODE::GetContent(PGLOBAL g, char *buf, int len)
|
|||
} else
|
||||
*buf = '\0';
|
||||
|
||||
if (trace)
|
||||
htrc("GetContent: %s\n", buf);
|
||||
|
||||
return rc;
|
||||
} // end of GetText
|
||||
} // end of GetContent
|
||||
|
||||
/******************************************************************/
|
||||
/* Set the content of a node. */
|
||||
/******************************************************************/
|
||||
bool XML2NODE::SetContent(PGLOBAL g, char *txtp, int len)
|
||||
{
|
||||
if (trace)
|
||||
htrc("SetContent: %s\n", txtp);
|
||||
|
||||
xmlChar *buf = xmlEncodeEntitiesReentrant(Docp, BAD_CAST txtp);
|
||||
|
||||
if (trace)
|
||||
htrc("SetContent %s -> %s\n", txtp, buf);
|
||||
htrc("SetContent: %s -> %s\n", txtp, buf);
|
||||
|
||||
xmlNodeSetContent(Nodep, buf);
|
||||
xmlFree(buf);
|
||||
|
@ -528,6 +645,9 @@ bool XML2NODE::SetContent(PGLOBAL g, char *txtp, int len)
|
|||
/******************************************************************/
|
||||
PXNODE XML2NODE::Clone(PGLOBAL g, PXNODE np)
|
||||
{
|
||||
if (trace)
|
||||
htrc("Clone: np=%p\n", np);
|
||||
|
||||
if (np) {
|
||||
((PNODE2)np)->Nodep = Nodep;
|
||||
return np;
|
||||
|
@ -542,7 +662,7 @@ PXNODE XML2NODE::Clone(PGLOBAL g, PXNODE np)
|
|||
PXLIST XML2NODE::GetChildElements(PGLOBAL g, char *xp, PXLIST lp)
|
||||
{
|
||||
if (trace)
|
||||
htrc("GetChildElements %s\n", xp);
|
||||
htrc("GetChildElements: %s\n", xp);
|
||||
|
||||
return SelectNodes(g, (xp) ? xp : (char*)"*", lp);
|
||||
} // end of GetChildElements
|
||||
|
@ -553,7 +673,7 @@ PXLIST XML2NODE::GetChildElements(PGLOBAL g, char *xp, PXLIST lp)
|
|||
PXLIST XML2NODE::SelectNodes(PGLOBAL g, char *xp, PXLIST lp)
|
||||
{
|
||||
if (trace)
|
||||
htrc("SelectNodes %s\n", xp);
|
||||
htrc("SelectNodes: %s\n", xp);
|
||||
|
||||
xmlNodeSetPtr nl = ((PXDOC2)Doc)->GetNodeList(g, Nodep, xp);
|
||||
|
||||
|
@ -571,7 +691,7 @@ PXLIST XML2NODE::SelectNodes(PGLOBAL g, char *xp, PXLIST lp)
|
|||
PXNODE XML2NODE::SelectSingleNode(PGLOBAL g, char *xp, PXNODE np)
|
||||
{
|
||||
if (trace)
|
||||
htrc("SelectSingleNode %s\n", xp);
|
||||
htrc("SelectSingleNode: %s\n", xp);
|
||||
|
||||
xmlNodeSetPtr nl = ((PXDOC2)Doc)->GetNodeList(g, Nodep, xp);
|
||||
|
||||
|
@ -593,7 +713,7 @@ PXNODE XML2NODE::SelectSingleNode(PGLOBAL g, char *xp, PXNODE np)
|
|||
PXATTR XML2NODE::GetAttribute(PGLOBAL g, char *name, PXATTR ap)
|
||||
{
|
||||
if (trace)
|
||||
htrc("GetAttribute %s\n", name);
|
||||
htrc("GetAttribute: %s\n", name);
|
||||
|
||||
xmlAttrPtr atp = xmlHasProp(Nodep, BAD_CAST name);
|
||||
|
||||
|
@ -618,7 +738,7 @@ PXNODE XML2NODE::AddChildNode(PGLOBAL g, char *name, PXNODE np)
|
|||
char *p, *pn, *pf = NULL;
|
||||
|
||||
if (trace)
|
||||
htrc("AddChildNode %s\n", name);
|
||||
htrc("AddChildNode: %s\n", name);
|
||||
|
||||
// Is a prefix specified
|
||||
if ((pn = strchr(name, ':'))) {
|
||||
|
@ -669,7 +789,7 @@ PXNODE XML2NODE::AddChildNode(PGLOBAL g, char *name, PXNODE np)
|
|||
PXATTR XML2NODE::AddProperty(PGLOBAL g, char *name, PXATTR ap)
|
||||
{
|
||||
if (trace)
|
||||
htrc("AddProperty %s\n", name);
|
||||
htrc("AddProperty: %s\n", name);
|
||||
|
||||
xmlAttrPtr atp = xmlNewProp(Nodep, BAD_CAST name, NULL);
|
||||
|
||||
|
@ -692,7 +812,7 @@ PXATTR XML2NODE::AddProperty(PGLOBAL g, char *name, PXATTR ap)
|
|||
void XML2NODE::AddText(PGLOBAL g, char *txtp)
|
||||
{
|
||||
if (trace)
|
||||
htrc("AddText %s\n", txtp);
|
||||
htrc("AddText: %s\n", txtp);
|
||||
|
||||
// This is to avoid a blank line when inserting a new line
|
||||
xmlNodePtr np = xmlGetLastChild(Nodep);
|
||||
|
@ -711,6 +831,9 @@ void XML2NODE::AddText(PGLOBAL g, char *txtp)
|
|||
/******************************************************************/
|
||||
void XML2NODE::DeleteChild(PGLOBAL g, PXNODE dnp)
|
||||
{
|
||||
if (trace)
|
||||
htrc("DeleteChild: node=%p\n", dnp);
|
||||
|
||||
xmlNodePtr np = ((PNODE2)dnp)->Nodep;
|
||||
xmlNodePtr text = np->next;
|
||||
|
||||
|
@ -750,7 +873,7 @@ int XML2NODELIST::GetLength(void)
|
|||
PXNODE XML2NODELIST::GetItem(PGLOBAL g, int n, PXNODE np)
|
||||
{
|
||||
if (trace)
|
||||
htrc("GetItem %d\n", n);
|
||||
htrc("GetItem: %d\n", n);
|
||||
|
||||
if (!Listp || Listp->nodeNr <= n)
|
||||
return NULL;
|
||||
|
@ -781,7 +904,7 @@ XML2ATTR::XML2ATTR(PXDOC dp, xmlAttrPtr ap, xmlNodePtr np)
|
|||
bool XML2ATTR::SetText(PGLOBAL g, char *txtp, int len)
|
||||
{
|
||||
if (trace)
|
||||
htrc("SetText %s %d\n", txtp, len);
|
||||
htrc("SetText: %s %d\n", txtp, len);
|
||||
|
||||
xmlSetProp(Parent, Atrp->name, BAD_CAST txtp);
|
||||
return false;
|
||||
|
|
Loading…
Reference in a new issue