Hi, I think I found a bug in libxml-2: in my multi-threaded application I get a memory leakage when I save an xml file

Here's an example of the output I get from valgrind

==4275== 981,552 bytes in 1,014 blocks are definitely lost in loss record 44 of 44 ==4275== at 0x4C2779D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4275==    by 0x4ED7EF1: xmlGetGlobalState (threads.c:584)
==4275==    by 0x4ED7634: __xmlIndentTreeOutput (globals.c:921)
==4275==    by 0x4F3D12C: xmlNodeListDumpOutput (xmlsave.c:722)
==4275==    by 0x4F3C95E: xmlNodeDumpOutputInternal (xmlsave.c:979)
==4275==    by 0x4F3D112: xmlNodeListDumpOutput (xmlsave.c:730)
==4275==    by 0x4F3C95E: xmlNodeDumpOutputInternal (xmlsave.c:979)
==4275==    by 0x4F3D112: xmlNodeListDumpOutput (xmlsave.c:730)
==4275==    by 0x4F3C95E: xmlNodeDumpOutputInternal (xmlsave.c:979)
==4275==    by 0x4F3D112: xmlNodeListDumpOutput (xmlsave.c:730)
==4275==    by 0x4F3C95E: xmlNodeDumpOutputInternal (xmlsave.c:979)
==4275==    by 0x4F3C4E1: xmlDocContentDumpOutput (xmlsave.c:1139)

In globals.c in case the calling thread is not the main thread, __xmlIndentTreeOutput does

return (&xmlGetGlobalState()->xmlIndentTreeOutput);

but as it can be seen in threads.c:584 every time it is called it mallocs memory for a xmlGlobalState. This memory is never free'd, and this is the only reason why functions calling __xmlIndentTreeOutput get a valid pointer and do not give a segfault.

But, unfortunately, after returning from __xmlIndentTreeOutput, you don't have any way to free the malloc'd memory any more and you have a leakage.

Now, considering that I am a libxml-2.0 internals novice, I tried changing

int * __xmlIndentTreeOutput(void);

to

int __xmlIndentTreeOutput(void);

so that you just return the value and not a pointer. This solution break parserInternals.c:2157 because it breaks

xmlIndentTreeOutput = 1;

since it is not a valid lvalue any more. I know this is bad, but I need a quit fix for my application dying because of memory exhaustion.

I attach my patch,  please evaluate if it is a good strategy.

Ottavio Campana

PS: a similar problem seems to exist in __xmlLastError , __xmlSaveNoEmptyTags , __xmlTreeIndentString , __xmlBufferAllocScheme , __xmlDefaultBufferSize , __xmlOutputBufferCreateFilenameValue , __htmlDefaultSAXHandler and __xmlGenericError . And maybe in others.
diff -ur libxml2-2.7.8.orig/globals.c libxml2-2.7.8/globals.c
--- libxml2-2.7.8.orig/globals.c	2010-10-12 08:25:32.000000000 +0200
+++ libxml2-2.7.8/globals.c	2012-02-06 14:30:30.023997685 +0100
@@ -913,12 +913,23 @@
 }
 
 #undef	xmlIndentTreeOutput
-int *
+int
 __xmlIndentTreeOutput(void) {
     if (IS_MAIN_THREAD)
-	return (&xmlIndentTreeOutput);
+	return xmlIndentTreeOutput;
     else
-	return (&xmlGetGlobalState()->xmlIndentTreeOutput);
+    {
+	int ret;
+	xmlGlobalState *gs;
+
+	gs = xmlGetGlobalState();
+	ret = gs->xmlIndentTreeOutput;
+
+	if (gs)
+	    free (gs);
+    
+	return ret;
+    }
 }
 int xmlThrDefIndentTreeOutput(int v) {
     int ret;
diff -ur libxml2-2.7.8.orig/include/libxml/globals.h libxml2-2.7.8/include/libxml/globals.h
--- libxml2-2.7.8.orig/include/libxml/globals.h	2010-10-12 08:25:32.000000000 +0200
+++ libxml2-2.7.8/include/libxml/globals.h	2012-02-06 14:19:59.244017419 +0100
@@ -374,10 +374,10 @@
 #endif
 XMLPUBFUN int XMLCALL xmlThrDefGetWarningsDefaultValue(int v);
 
-XMLPUBFUN int * XMLCALL __xmlIndentTreeOutput(void);
+XMLPUBFUN int XMLCALL __xmlIndentTreeOutput(void);
 #ifdef LIBXML_THREAD_ENABLED
 #define xmlIndentTreeOutput \
-(*(__xmlIndentTreeOutput()))
+((__xmlIndentTreeOutput()))
 #else
 XMLPUBVAR int xmlIndentTreeOutput;
 #endif
diff -ur libxml2-2.7.8.orig/parserInternals.c libxml2-2.7.8/parserInternals.c
--- libxml2-2.7.8.orig/parserInternals.c	2010-10-12 08:25:32.000000000 +0200
+++ libxml2-2.7.8/parserInternals.c	2012-02-06 14:32:18.827994269 +0100
@@ -2154,7 +2154,6 @@
     int old = xmlKeepBlanksDefaultValue;
 
     xmlKeepBlanksDefaultValue = val;
-    if (!val) xmlIndentTreeOutput = 1;
     return(old);
 }
 
_______________________________________________
xml mailing list, project page  http://xmlsoft.org/
[email protected]
http://mail.gnome.org/mailman/listinfo/xml

Reply via email to