Andrew Nguyen : msxml3: Extend the lifetime of the SAX callback BSTRs beyond the callback invocation .

Alexandre Julliard julliard at winehq.org
Fri Jul 15 11:45:21 CDT 2011


Module: wine
Branch: master
Commit: 9c5d5d8ed5b95e60b61b8a31e85d5c5edee28c24
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=9c5d5d8ed5b95e60b61b8a31e85d5c5edee28c24

Author: Andrew Nguyen <anguyen at codeweavers.com>
Date:   Fri Jul 15 07:38:07 2011 -0500

msxml3: Extend the lifetime of the SAX callback BSTRs beyond the callback invocation.

---

 dlls/msxml3/saxreader.c |  135 +++++++++++++++++++++++++++++++++++++----------
 1 files changed, 106 insertions(+), 29 deletions(-)

diff --git a/dlls/msxml3/saxreader.c b/dlls/msxml3/saxreader.c
index 4f0a5f1..5bf6eda 100644
--- a/dlls/msxml3/saxreader.c
+++ b/dlls/msxml3/saxreader.c
@@ -49,6 +49,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml);
 
 #ifdef HAVE_LIBXML2
 
+struct bstrpool
+{
+    BSTR *pool;
+    unsigned int index;
+    unsigned int len;
+};
+
 typedef struct _saxreader
 {
     IVBSAXXMLReader IVBSAXXMLReader_iface;
@@ -64,6 +71,7 @@ typedef struct _saxreader
     struct IVBSAXDeclHandler *vbdeclHandler;
     xmlSAXHandler sax;
     BOOL isParsing;
+    struct bstrpool pool;
 } saxreader;
 
 typedef struct _saxlocator
@@ -164,6 +172,45 @@ static int namespacePop(saxlocator *locator)
     return locator->nsStack[--locator->nsStackLast];
 }
 
+static BOOL bstr_pool_insert(struct bstrpool *pool, BSTR pool_entry)
+{
+    if (!pool->pool)
+    {
+        pool->pool = HeapAlloc(GetProcessHeap(), 0, 16 * sizeof(*pool->pool));
+        if (!pool->pool)
+            return FALSE;
+
+        pool->index = 0;
+        pool->len = 16;
+    }
+    else if (pool->index == pool->len)
+    {
+        BSTR *realloc = HeapReAlloc(GetProcessHeap(), 0, pool->pool, pool->len * 2 * sizeof(*realloc));
+
+        if (!realloc)
+            return FALSE;
+
+        pool->pool = realloc;
+        pool->len *= 2;
+    }
+
+    pool->pool[pool->index++] = pool_entry;
+    return TRUE;
+}
+
+static void free_bstr_pool(struct bstrpool *pool)
+{
+    unsigned int i;
+
+    for (i = 0; i < pool->index; i++)
+        SysFreeString(pool->pool[i]);
+
+    HeapFree(GetProcessHeap(), 0, pool->pool);
+
+    pool->pool = NULL;
+    pool->index = pool->len = 0;
+}
+
 static BSTR bstr_from_xmlCharN(const xmlChar *buf, int len)
 {
     DWORD dLen;
@@ -200,6 +247,45 @@ static BSTR QName_from_xmlChar(const xmlChar *prefix, const xmlChar *name)
     return bstr;
 }
 
+static BSTR pooled_bstr_from_xmlChar(struct bstrpool *pool, const xmlChar *buf)
+{
+    BSTR pool_entry = bstr_from_xmlChar(buf);
+
+    if (pool_entry && !bstr_pool_insert(pool, pool_entry))
+    {
+        SysFreeString(pool_entry);
+        return NULL;
+    }
+
+    return pool_entry;
+}
+
+static BSTR pooled_bstr_from_xmlCharN(struct bstrpool *pool, const xmlChar *buf, int len)
+{
+    BSTR pool_entry = bstr_from_xmlCharN(buf, len);
+
+    if (pool_entry && !bstr_pool_insert(pool, pool_entry))
+    {
+        SysFreeString(pool_entry);
+        return NULL;
+    }
+
+    return pool_entry;
+}
+
+static BSTR pooled_QName_from_xmlChar(struct bstrpool *pool, const xmlChar *prefix, const xmlChar *name)
+{
+    BSTR pool_entry = QName_from_xmlChar(prefix, name);
+
+    if (pool_entry && !bstr_pool_insert(pool, pool_entry))
+    {
+        SysFreeString(pool_entry);
+        return NULL;
+    }
+
+    return pool_entry;
+}
+
 static void format_error_message_from_id(saxlocator *This, HRESULT hr)
 {
     xmlStopParser(This->pParserCtxt);
@@ -1021,8 +1107,8 @@ static void libxmlStartElementNS(
     {
         for(index=0; index<nb_namespaces; index++)
         {
-            Prefix = bstr_from_xmlChar(namespaces[2*index]);
-            Uri = bstr_from_xmlChar(namespaces[2*index+1]);
+            Prefix = pooled_bstr_from_xmlChar(&This->saxreader->pool, namespaces[2*index]);
+            Uri = pooled_bstr_from_xmlChar(&This->saxreader->pool, namespaces[2*index+1]);
 
             if(This->vbInterface)
                 hr = IVBSAXContentHandler_startPrefixMapping(
@@ -1034,9 +1120,6 @@ static void libxmlStartElementNS(
                         Prefix, SysStringLen(Prefix),
                         Uri, SysStringLen(Uri));
 
-            SysFreeString(Prefix);
-            SysFreeString(Uri);
-
             if(hr != S_OK)
             {
                 format_error_message_from_id(This, hr);
@@ -1044,9 +1127,9 @@ static void libxmlStartElementNS(
             }
         }
 
-        NamespaceUri = bstr_from_xmlChar(URI);
-        LocalName = bstr_from_xmlChar(localname);
-        QName = QName_from_xmlChar(prefix, localname);
+        NamespaceUri = pooled_bstr_from_xmlChar(&This->saxreader->pool, URI);
+        LocalName = pooled_bstr_from_xmlChar(&This->saxreader->pool, localname);
+        QName = pooled_QName_from_xmlChar(&This->saxreader->pool, prefix, localname);
 
         hr = SAXAttributes_create(&attr, nb_namespaces, namespaces, nb_attributes, attributes);
         if(hr == S_OK)
@@ -1061,10 +1144,6 @@ static void libxmlStartElementNS(
 
             ISAXAttributes_Release(&attr->ISAXAttributes_iface);
         }
-
-        SysFreeString(NamespaceUri);
-        SysFreeString(LocalName);
-        SysFreeString(QName);
     }
 
     if(hr != S_OK)
@@ -1094,9 +1173,9 @@ static void libxmlEndElementNS(
 
     if(has_content_handler(This))
     {
-        NamespaceUri = bstr_from_xmlChar(URI);
-        LocalName = bstr_from_xmlChar(localname);
-        QName = QName_from_xmlChar(prefix, localname);
+        NamespaceUri = pooled_bstr_from_xmlChar(&This->saxreader->pool, URI);
+        LocalName = pooled_bstr_from_xmlChar(&This->saxreader->pool, localname);
+        QName = pooled_QName_from_xmlChar(&This->saxreader->pool, prefix, localname);
 
         if(This->vbInterface)
             hr = IVBSAXContentHandler_endElement(
@@ -1109,10 +1188,6 @@ static void libxmlEndElementNS(
                     LocalName, SysStringLen(LocalName),
                     QName, SysStringLen(QName));
 
-        SysFreeString(NamespaceUri);
-        SysFreeString(LocalName);
-        SysFreeString(QName);
-
         if(hr != S_OK)
         {
             format_error_message_from_id(This, hr);
@@ -1122,7 +1197,7 @@ static void libxmlEndElementNS(
         for(index=This->pParserCtxt->nsNr-2;
                 index>=This->pParserCtxt->nsNr-nsNr*2; index-=2)
         {
-            Prefix = bstr_from_xmlChar(This->pParserCtxt->nsTab[index]);
+            Prefix = pooled_bstr_from_xmlChar(&This->saxreader->pool, This->pParserCtxt->nsTab[index]);
 
             if(This->vbInterface)
                 hr = IVBSAXContentHandler_endPrefixMapping(
@@ -1132,8 +1207,6 @@ static void libxmlEndElementNS(
                         This->saxreader->contentHandler,
                         Prefix, SysStringLen(Prefix));
 
-            SysFreeString(Prefix);
-
             if(hr != S_OK)
             {
                 format_error_message_from_id(This, hr);
@@ -1178,7 +1251,7 @@ static void libxmlCharacters(
 
         if(!lastEvent) *end = '\n';
 
-        Chars = bstr_from_xmlCharN(cur, end-cur+1);
+        Chars = pooled_bstr_from_xmlCharN(&This->saxreader->pool, cur, end-cur+1);
         if(This->vbInterface)
             hr = IVBSAXContentHandler_characters(
                     This->saxreader->vbcontentHandler, &Chars);
@@ -1186,7 +1259,6 @@ static void libxmlCharacters(
             hr = ISAXContentHandler_characters(
                     This->saxreader->contentHandler,
                     Chars, SysStringLen(Chars));
-        SysFreeString(Chars);
 
         if(hr != S_OK)
         {
@@ -1251,7 +1323,7 @@ static void libxmlComment(void *ctx, const xmlChar *value)
     if(!This->vbInterface && !This->saxreader->lexicalHandler) return;
     if(This->vbInterface && !This->saxreader->vblexicalHandler) return;
 
-    bValue = bstr_from_xmlChar(value);
+    bValue = pooled_bstr_from_xmlChar(&This->saxreader->pool, value);
 
     if(This->vbInterface)
         hr = IVBSAXLexicalHandler_comment(
@@ -1261,8 +1333,6 @@ static void libxmlComment(void *ctx, const xmlChar *value)
                 This->saxreader->lexicalHandler,
                 bValue, SysStringLen(bValue));
 
-    SysFreeString(bValue);
-
     if(FAILED(hr))
         format_error_message_from_id(This, hr);
 
@@ -1363,7 +1433,7 @@ static void libxmlCDataBlock(void *ctx, const xmlChar *value, int len)
 
         if(has_content_handler(This))
         {
-            Chars = bstr_from_xmlCharN(cur, end-cur+1);
+            Chars = pooled_bstr_from_xmlCharN(&This->saxreader->pool, cur, end-cur+1);
             if(This->vbInterface)
                 hr = IVBSAXContentHandler_characters(
                         This->saxreader->vbcontentHandler, &Chars);
@@ -1371,7 +1441,6 @@ static void libxmlCDataBlock(void *ctx, const xmlChar *value, int len)
                 hr = ISAXContentHandler_characters(
                         This->saxreader->contentHandler,
                         Chars, SysStringLen(Chars));
-            SysFreeString(Chars);
         }
 
         if(change) *end = '\r';
@@ -1998,6 +2067,9 @@ static HRESULT internal_parse(
 
     TRACE("(%p)->(%s)\n", This, debugstr_variant(&varInput));
 
+    /* Dispose of the BSTRs in the pool from a prior run, if any. */
+    free_bstr_pool(&This->pool);
+
     switch(V_VT(&varInput))
     {
         case VT_BSTR:
@@ -2320,6 +2392,8 @@ static ULONG WINAPI saxxmlreader_Release(
         if(This->vbdeclHandler)
             IVBSAXDeclHandler_Release(This->vbdeclHandler);
 
+        free_bstr_pool(&This->pool);
+
         heap_free( This );
     }
 
@@ -2817,6 +2891,9 @@ HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj)
     reader->declHandler = NULL;
     reader->vbdeclHandler = NULL;
     reader->isParsing = FALSE;
+    reader->pool.pool = NULL;
+    reader->pool.index = 0;
+    reader->pool.len = 0;
 
     memset(&reader->sax, 0, sizeof(xmlSAXHandler));
     reader->sax.initialized = XML_SAX2_MAGIC;




More information about the wine-cvs mailing list