[Expat-discuss] Heap corruption after successive XML_ParserFree/XML_ParserCreate calls

Dan Clusin dclusin at enernoc.com
Fri Jul 20 18:18:37 CEST 2007


Greetings,

 

I've run into a problem concerning heap corruption using expat and I'm
not really sure what to make of it.

Any suggestion would be much appreciated.

 

Description:

I'm writing an XMPP client currently on a FC 7 Linux machine. For those
of you who aren't aware, XMPP

is an instant messaging protocol that uses XML as a stream for the
underlying data formatting of the protocol. Part

of the specification requires that the stream be renegotiated once the
socket connection between the client

and server becomes encrypted.

 

So for example, the client would send its initial handshake such as:

<?xml version='1.0'?>
   <stream:stream
       to='example.com'
       xmlns='jabber:client'
       xmlns:stream='http://etherx.jabber.org/streams'
       version='1.0'>
 
Then the server would respond as with its own opening XML stream that is
similar.
All of the data retrieved from the server is considered its own XML
document. That is to say,
The XML data my program sends to the server is not considered to be part
of the data that is
Being processed by the expat library.
 
So as I said before, once the connection becomes encrypted during the
handshake process
(using SSL), my client needs to send its own stream header again
(similar to example above)
And the server will respond with its response to the handshake. The
stream before encryption
And the stream after encryption are required to be (as per the spec)
thought of as 2 different
XML streams (or documents if you prefer).
 
It made sense to me at the time to have these processed by two different
parsers, since
The streams are not related. So my solution to this was to destroy the
first parser using XML_ParserFree
Once the SSL negotiation completed. An XML_ParserCreate would
immediately proceed the XML_ParserFree
Call.
 
How this is handled in my program is as follows:
1.       Program starts up, creates a parser, etc.
2.    Parser is configured and supplied the various handlers.
3.    Connection is made, handshake is sent, etc.
4.    All further responses from the server are fed to the expat parser
5.    SSL is negotiated and set up.
6.    Outside of the handler functions (in the main socket listener loop
to be precise), the current parser
Is destroyed and a new one is created. 
7.       The new parser is now fed all the data from the secure
connection.
 
So now my problem: My program crashes sometime later (approximately 3
calls later to my element start handler
When the attribute being processed is the namespace.). Specifically, it
crashes on a malloc call. I'm fairly confident
That this is due to heap corruption because my machine has 2GB of
memory, and I have inspected the application
Using valgrind and it doesn't use more than 1MB of memory.
 
It always crashes in the exact same manner and sequence of element
handler calls. I noticed that if I take out the
XML_ParserFree call for the original call and just create the new one it
works fine and does not destroy the heap.
This isn't an optimal solution for obvious reasons.
 
Some more information that could help:
The reference to the XML parser is contained inside a structure that is
being used as the userData for the XML parser.
 
The form of that structure is as follows:

typedef struct xmpp_session {

      linked_queue_t *outbound;

      login_phase_t connection_state;

      tcp_socket_t *server;

      xml_node_t *current_node;

      

      XML_Parser the_parser;

} xmpp_session_t;

 

My XML_Parser init and delete routines are as follows:

void xml_parser_init( xmpp_session_t *a_connection ) {

      a_connection->the_parser = XML_ParserCreate( NULL );

      

      XML_SetStartElementHandler( a_connection->the_parser,
xml_element_start );

      XML_SetEndElementHandler( a_connection->the_parser,
xml_element_end );

      XML_SetCharacterDataHandler( a_connection->the_parser,
xml_cdata_handler );

      XML_SetUserData( a_connection->the_parser, a_connection ); }

 

void xml_parser_destroy( xmpp_session_t *a_session ) {

      XML_ParserFree( a_session->the_parser );

      

      a_session->current_node = NULL;

      

}

 

The code inside the main socket loop for restarting the parser is as
follows:

printf("restarting parser.\n");

//xml_parser_destroy( the_session );

xml_parser_init( the_session );
 
 
As I said before, it only corrupts the heap when I have the parser
destroy call un-commented out.
Also, something to note is that the xmpp_session_t instance is kept the
same (not copied or a new
One create), and just passed to the new parser instance.
 
If anyone has any suggestions I would very much appreciate it.
 
 
Kindest regards,
 
Daniel Clusin
 


More information about the Expat-discuss mailing list