Commit 9c5d5d8e authored by Andrew Nguyen's avatar Andrew Nguyen Committed by Alexandre Julliard

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

parent d599813b
...@@ -49,6 +49,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml); ...@@ -49,6 +49,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml);
#ifdef HAVE_LIBXML2 #ifdef HAVE_LIBXML2
struct bstrpool
{
BSTR *pool;
unsigned int index;
unsigned int len;
};
typedef struct _saxreader typedef struct _saxreader
{ {
IVBSAXXMLReader IVBSAXXMLReader_iface; IVBSAXXMLReader IVBSAXXMLReader_iface;
...@@ -64,6 +71,7 @@ typedef struct _saxreader ...@@ -64,6 +71,7 @@ typedef struct _saxreader
struct IVBSAXDeclHandler *vbdeclHandler; struct IVBSAXDeclHandler *vbdeclHandler;
xmlSAXHandler sax; xmlSAXHandler sax;
BOOL isParsing; BOOL isParsing;
struct bstrpool pool;
} saxreader; } saxreader;
typedef struct _saxlocator typedef struct _saxlocator
...@@ -164,6 +172,45 @@ static int namespacePop(saxlocator *locator) ...@@ -164,6 +172,45 @@ static int namespacePop(saxlocator *locator)
return locator->nsStack[--locator->nsStackLast]; 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) static BSTR bstr_from_xmlCharN(const xmlChar *buf, int len)
{ {
DWORD dLen; DWORD dLen;
...@@ -200,6 +247,45 @@ static BSTR QName_from_xmlChar(const xmlChar *prefix, const xmlChar *name) ...@@ -200,6 +247,45 @@ static BSTR QName_from_xmlChar(const xmlChar *prefix, const xmlChar *name)
return bstr; 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) static void format_error_message_from_id(saxlocator *This, HRESULT hr)
{ {
xmlStopParser(This->pParserCtxt); xmlStopParser(This->pParserCtxt);
...@@ -1021,8 +1107,8 @@ static void libxmlStartElementNS( ...@@ -1021,8 +1107,8 @@ static void libxmlStartElementNS(
{ {
for(index=0; index<nb_namespaces; index++) for(index=0; index<nb_namespaces; index++)
{ {
Prefix = bstr_from_xmlChar(namespaces[2*index]); Prefix = pooled_bstr_from_xmlChar(&This->saxreader->pool, namespaces[2*index]);
Uri = bstr_from_xmlChar(namespaces[2*index+1]); Uri = pooled_bstr_from_xmlChar(&This->saxreader->pool, namespaces[2*index+1]);
if(This->vbInterface) if(This->vbInterface)
hr = IVBSAXContentHandler_startPrefixMapping( hr = IVBSAXContentHandler_startPrefixMapping(
...@@ -1034,9 +1120,6 @@ static void libxmlStartElementNS( ...@@ -1034,9 +1120,6 @@ static void libxmlStartElementNS(
Prefix, SysStringLen(Prefix), Prefix, SysStringLen(Prefix),
Uri, SysStringLen(Uri)); Uri, SysStringLen(Uri));
SysFreeString(Prefix);
SysFreeString(Uri);
if(hr != S_OK) if(hr != S_OK)
{ {
format_error_message_from_id(This, hr); format_error_message_from_id(This, hr);
...@@ -1044,9 +1127,9 @@ static void libxmlStartElementNS( ...@@ -1044,9 +1127,9 @@ static void libxmlStartElementNS(
} }
} }
NamespaceUri = bstr_from_xmlChar(URI); NamespaceUri = pooled_bstr_from_xmlChar(&This->saxreader->pool, URI);
LocalName = bstr_from_xmlChar(localname); LocalName = pooled_bstr_from_xmlChar(&This->saxreader->pool, localname);
QName = QName_from_xmlChar(prefix, localname); QName = pooled_QName_from_xmlChar(&This->saxreader->pool, prefix, localname);
hr = SAXAttributes_create(&attr, nb_namespaces, namespaces, nb_attributes, attributes); hr = SAXAttributes_create(&attr, nb_namespaces, namespaces, nb_attributes, attributes);
if(hr == S_OK) if(hr == S_OK)
...@@ -1061,10 +1144,6 @@ static void libxmlStartElementNS( ...@@ -1061,10 +1144,6 @@ static void libxmlStartElementNS(
ISAXAttributes_Release(&attr->ISAXAttributes_iface); ISAXAttributes_Release(&attr->ISAXAttributes_iface);
} }
SysFreeString(NamespaceUri);
SysFreeString(LocalName);
SysFreeString(QName);
} }
if(hr != S_OK) if(hr != S_OK)
...@@ -1094,9 +1173,9 @@ static void libxmlEndElementNS( ...@@ -1094,9 +1173,9 @@ static void libxmlEndElementNS(
if(has_content_handler(This)) if(has_content_handler(This))
{ {
NamespaceUri = bstr_from_xmlChar(URI); NamespaceUri = pooled_bstr_from_xmlChar(&This->saxreader->pool, URI);
LocalName = bstr_from_xmlChar(localname); LocalName = pooled_bstr_from_xmlChar(&This->saxreader->pool, localname);
QName = QName_from_xmlChar(prefix, localname); QName = pooled_QName_from_xmlChar(&This->saxreader->pool, prefix, localname);
if(This->vbInterface) if(This->vbInterface)
hr = IVBSAXContentHandler_endElement( hr = IVBSAXContentHandler_endElement(
...@@ -1109,10 +1188,6 @@ static void libxmlEndElementNS( ...@@ -1109,10 +1188,6 @@ static void libxmlEndElementNS(
LocalName, SysStringLen(LocalName), LocalName, SysStringLen(LocalName),
QName, SysStringLen(QName)); QName, SysStringLen(QName));
SysFreeString(NamespaceUri);
SysFreeString(LocalName);
SysFreeString(QName);
if(hr != S_OK) if(hr != S_OK)
{ {
format_error_message_from_id(This, hr); format_error_message_from_id(This, hr);
...@@ -1122,7 +1197,7 @@ static void libxmlEndElementNS( ...@@ -1122,7 +1197,7 @@ static void libxmlEndElementNS(
for(index=This->pParserCtxt->nsNr-2; for(index=This->pParserCtxt->nsNr-2;
index>=This->pParserCtxt->nsNr-nsNr*2; index-=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) if(This->vbInterface)
hr = IVBSAXContentHandler_endPrefixMapping( hr = IVBSAXContentHandler_endPrefixMapping(
...@@ -1132,8 +1207,6 @@ static void libxmlEndElementNS( ...@@ -1132,8 +1207,6 @@ static void libxmlEndElementNS(
This->saxreader->contentHandler, This->saxreader->contentHandler,
Prefix, SysStringLen(Prefix)); Prefix, SysStringLen(Prefix));
SysFreeString(Prefix);
if(hr != S_OK) if(hr != S_OK)
{ {
format_error_message_from_id(This, hr); format_error_message_from_id(This, hr);
...@@ -1178,7 +1251,7 @@ static void libxmlCharacters( ...@@ -1178,7 +1251,7 @@ static void libxmlCharacters(
if(!lastEvent) *end = '\n'; 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) if(This->vbInterface)
hr = IVBSAXContentHandler_characters( hr = IVBSAXContentHandler_characters(
This->saxreader->vbcontentHandler, &Chars); This->saxreader->vbcontentHandler, &Chars);
...@@ -1186,7 +1259,6 @@ static void libxmlCharacters( ...@@ -1186,7 +1259,6 @@ static void libxmlCharacters(
hr = ISAXContentHandler_characters( hr = ISAXContentHandler_characters(
This->saxreader->contentHandler, This->saxreader->contentHandler,
Chars, SysStringLen(Chars)); Chars, SysStringLen(Chars));
SysFreeString(Chars);
if(hr != S_OK) if(hr != S_OK)
{ {
...@@ -1251,7 +1323,7 @@ static void libxmlComment(void *ctx, const xmlChar *value) ...@@ -1251,7 +1323,7 @@ static void libxmlComment(void *ctx, const xmlChar *value)
if(!This->vbInterface && !This->saxreader->lexicalHandler) return; if(!This->vbInterface && !This->saxreader->lexicalHandler) return;
if(This->vbInterface && !This->saxreader->vblexicalHandler) 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) if(This->vbInterface)
hr = IVBSAXLexicalHandler_comment( hr = IVBSAXLexicalHandler_comment(
...@@ -1261,8 +1333,6 @@ static void libxmlComment(void *ctx, const xmlChar *value) ...@@ -1261,8 +1333,6 @@ static void libxmlComment(void *ctx, const xmlChar *value)
This->saxreader->lexicalHandler, This->saxreader->lexicalHandler,
bValue, SysStringLen(bValue)); bValue, SysStringLen(bValue));
SysFreeString(bValue);
if(FAILED(hr)) if(FAILED(hr))
format_error_message_from_id(This, hr); format_error_message_from_id(This, hr);
...@@ -1363,7 +1433,7 @@ static void libxmlCDataBlock(void *ctx, const xmlChar *value, int len) ...@@ -1363,7 +1433,7 @@ static void libxmlCDataBlock(void *ctx, const xmlChar *value, int len)
if(has_content_handler(This)) 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) if(This->vbInterface)
hr = IVBSAXContentHandler_characters( hr = IVBSAXContentHandler_characters(
This->saxreader->vbcontentHandler, &Chars); This->saxreader->vbcontentHandler, &Chars);
...@@ -1371,7 +1441,6 @@ static void libxmlCDataBlock(void *ctx, const xmlChar *value, int len) ...@@ -1371,7 +1441,6 @@ static void libxmlCDataBlock(void *ctx, const xmlChar *value, int len)
hr = ISAXContentHandler_characters( hr = ISAXContentHandler_characters(
This->saxreader->contentHandler, This->saxreader->contentHandler,
Chars, SysStringLen(Chars)); Chars, SysStringLen(Chars));
SysFreeString(Chars);
} }
if(change) *end = '\r'; if(change) *end = '\r';
...@@ -1998,6 +2067,9 @@ static HRESULT internal_parse( ...@@ -1998,6 +2067,9 @@ static HRESULT internal_parse(
TRACE("(%p)->(%s)\n", This, debugstr_variant(&varInput)); 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)) switch(V_VT(&varInput))
{ {
case VT_BSTR: case VT_BSTR:
...@@ -2320,6 +2392,8 @@ static ULONG WINAPI saxxmlreader_Release( ...@@ -2320,6 +2392,8 @@ static ULONG WINAPI saxxmlreader_Release(
if(This->vbdeclHandler) if(This->vbdeclHandler)
IVBSAXDeclHandler_Release(This->vbdeclHandler); IVBSAXDeclHandler_Release(This->vbdeclHandler);
free_bstr_pool(&This->pool);
heap_free( This ); heap_free( This );
} }
...@@ -2817,6 +2891,9 @@ HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj) ...@@ -2817,6 +2891,9 @@ HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj)
reader->declHandler = NULL; reader->declHandler = NULL;
reader->vbdeclHandler = NULL; reader->vbdeclHandler = NULL;
reader->isParsing = FALSE; reader->isParsing = FALSE;
reader->pool.pool = NULL;
reader->pool.index = 0;
reader->pool.len = 0;
memset(&reader->sax, 0, sizeof(xmlSAXHandler)); memset(&reader->sax, 0, sizeof(xmlSAXHandler));
reader->sax.initialized = XML_SAX2_MAGIC; reader->sax.initialized = XML_SAX2_MAGIC;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment