On Thu, Feb 16, 2012 at 01:55:44AM +0300, Nikolay Sivov wrote:
The problem is that vsnprintf() was called multiple times with same va_list. Ti fix that it was necessary to get rid of some tracing bits like macro-defined callback calls and a single function for all kinds of error types.
As far as I understand this problem it leads to a stack corruption when va_list is used multiple time without va_start/va_end around it, so it's critical to fix.
If I remember correctly, you can even process a va_list only once on some platforms. If you need to process it multiple times, you need to create a copy with va_copy() first. Ciao, Marcus
From d75433c8ff34e125c7db1fb665bdb9271991b9f5 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov <nsivov(a)codeweavers.com> Date: Thu, 16 Feb 2012 01:06:16 +0300 Subject: [PATCH 1/1] Fix varargs handling in libxml2 error callback implementation
--- dlls/msxml3/domdoc.c | 50 +++++------------------- dlls/msxml3/main.c | 49 +++++++++++++++++------- dlls/msxml3/msxml_private.h | 18 ++------- dlls/msxml3/schema.c | 90 ++++++++++++++----------------------------- dlls/msxml3/selection.c | 4 +- 5 files changed, 80 insertions(+), 131 deletions(-)
diff --git a/dlls/msxml3/domdoc.c b/dlls/msxml3/domdoc.c index 64122ce..9bcecdd 100644 --- a/dlls/msxml3/domdoc.c +++ b/dlls/msxml3/domdoc.c @@ -425,23 +425,7 @@ static void sax_characters(void *ctx, const xmlChar *ch, int len) xmlSAX2Characters(ctxt, ch, len); }
-static void LIBXML2_LOG_CALLBACK sax_error(void* ctx, char const* msg, ...) -{ - va_list ap; - va_start(ap, msg); - LIBXML2_CALLBACK_ERR(doparse, msg, ap); - va_end(ap); -} - -static void LIBXML2_LOG_CALLBACK sax_warning(void* ctx, char const* msg, ...) -{ - va_list ap; - va_start(ap, msg); - LIBXML2_CALLBACK_WARN(doparse, msg, ap); - va_end(ap); -} - -static void sax_serror(void* ctx, xmlErrorPtr err) +static void libxml2_sax_structerror(void* ctx, xmlErrorPtr err) { LIBXML2_CALLBACK_SERROR(doparse, err); } @@ -472,9 +456,9 @@ static xmlDocPtr doparse(domdoc* This, char const* ptr, int len, xmlCharEncoding sax_characters, /* ignorableWhitespace */ xmlSAX2ProcessingInstruction, /* processingInstruction */ xmlSAX2Comment, /* comment */ - sax_warning, /* warning */ - sax_error, /* error */ - sax_error, /* fatalError */ + libxml2_warn_callback, /* warning */ + libxml2_error_callback, /* error */ + libxml2_error_callback, /* fatalError */ xmlSAX2GetParameterEntity, /* getParameterEntity */ xmlSAX2CDataBlock, /* cdataBlock */ xmlSAX2ExternalSubset, /* externalSubset */ @@ -482,10 +466,12 @@ static xmlDocPtr doparse(domdoc* This, char const* ptr, int len, xmlCharEncoding NULL, /* _private */ xmlSAX2StartElementNs, /* startElementNs */ xmlSAX2EndElementNs, /* endElementNs */ - sax_serror /* serror */ + libxml2_sax_structerror /* serror */ }; xmlInitParser();
+ TRACE("(%p)->(%p %d %d)\n", This, ptr, len, encoding); + pctx = xmlCreateMemoryParserCtxt(ptr, len); if (!pctx) { @@ -2634,22 +2620,6 @@ static inline BOOL is_wellformed(xmlDocPtr doc) #endif }
-static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...) -{ - va_list ap; - va_start(ap, msg); - LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap); - va_end(ap); -} - -static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...) -{ - va_list ap; - va_start(ap, msg); - LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap); - va_end(ap); -} - static HRESULT WINAPI domdoc_validateNode( IXMLDOMDocument3* iface, IXMLDOMNode* node, @@ -2695,11 +2665,11 @@ static HRESULT WINAPI domdoc_validateNode( if (get_doc(This)->intSubset || get_doc(This)->extSubset) { xmlValidCtxtPtr vctx = xmlNewValidCtxt(); - vctx->error = validate_error; - vctx->warning = validate_warning; + vctx->error = libxml2_error_callback; + vctx->warning = libxml2_warn_callback; ++validated;
- if (!((node == (IXMLDOMNode*)iface)? + if (!((node == (IXMLDOMNode*)iface) ? xmlValidateDocument(vctx, get_doc(This)) : xmlValidateElement(vctx, get_doc(This), get_node_obj(node)->node))) { diff --git a/dlls/msxml3/main.c b/dlls/msxml3/main.c index 464ef90..4f9b020 100644 --- a/dlls/msxml3/main.c +++ b/dlls/msxml3/main.c @@ -60,28 +60,47 @@ HINSTANCE MSXML_hInstance = NULL;
#ifdef HAVE_LIBXML2
-void wineXmlCallbackLog(char const* caller, xmlErrorLevel lvl, char const* msg, va_list ap) +#define LIBXML2_LOG_CALLBACK __WINE_PRINTF_ATTR(2,3) + +void LIBXML2_LOG_CALLBACK libxml2_error_callback(void *ctxt, const char *msg, ...) { - char* buf = NULL; int len = 32, needed; - enum __wine_debug_class dbcl = __WINE_DBCL_ERR; - switch (lvl) + char* buf = NULL; + va_list ap; + + do { - case XML_ERR_NONE: - dbcl = __WINE_DBCL_TRACE; - break; - case XML_ERR_WARNING: - dbcl = __WINE_DBCL_WARN; - break; - default: - break; + heap_free(buf); + buf = heap_alloc(len); + va_start(ap, msg); + needed = vsnprintf(buf, len, msg, ap); + va_end(ap); + if (needed == -1) + len *= 2; + else if (needed >= len) + len = needed + 1; + else + needed = 0; } + while (needed); + + wine_dbg_log(__WINE_DBCL_ERR, &__wine_dbch_msxml, "libxml2", "%s", buf); + heap_free(buf); +} + +void LIBXML2_LOG_CALLBACK libxml2_warn_callback(void *ctxt, const char *msg, ...) +{ + int len = 32, needed; + char* buf = NULL; + va_list ap;
do { heap_free(buf); buf = heap_alloc(len); + va_start(ap, msg); needed = vsnprintf(buf, len, msg, ap); + va_end(ap); if (needed == -1) len *= 2; else if (needed >= len) @@ -91,11 +110,13 @@ void wineXmlCallbackLog(char const* caller, xmlErrorLevel lvl, char const* msg, } while (needed);
- wine_dbg_log(dbcl, &__wine_dbch_msxml, caller, "%s", buf); + wine_dbg_log(__WINE_DBCL_WARN, &__wine_dbch_msxml, "libxml2", "%s", buf); heap_free(buf); }
-void wineXmlCallbackError(char const* caller, xmlErrorPtr err) +#undef LIBXML2_LOG_CALLBACK + +void libxml2_structured_error(const char* caller, xmlErrorPtr err) { enum __wine_debug_class dbcl;
diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h index e51501b..66c3b89 100644 --- a/dlls/msxml3/msxml_private.h +++ b/dlls/msxml3/msxml_private.h @@ -289,21 +289,11 @@ extern xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc) DECLSPEC_HIDDEN;
extern HRESULT XMLElement_create( IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj, BOOL own ) DECLSPEC_HIDDEN;
-extern void wineXmlCallbackLog(char const* caller, xmlErrorLevel lvl, char const* msg, va_list ap) DECLSPEC_HIDDEN; -extern void wineXmlCallbackError(char const* caller, xmlErrorPtr err) DECLSPEC_HIDDEN; +extern void libxml2_structured_error(const char* caller, xmlErrorPtr err) DECLSPEC_HIDDEN; +extern void libxml2_error_callback(void *ctxt, const char *msg, ...) DECLSPEC_HIDDEN; +extern void libxml2_warn_callback(void *ctxt, const char *msg, ...) DECLSPEC_HIDDEN;
-#define LIBXML2_LOG_CALLBACK __WINE_PRINTF_ATTR(2,3) - -#define LIBXML2_CALLBACK_TRACE(caller, msg, ap) \ - wineXmlCallbackLog(#caller, XML_ERR_NONE, msg, ap) - -#define LIBXML2_CALLBACK_WARN(caller, msg, ap) \ - wineXmlCallbackLog(#caller, XML_ERR_WARNING, msg, ap) - -#define LIBXML2_CALLBACK_ERR(caller, msg, ap) \ - wineXmlCallbackLog(#caller, XML_ERR_ERROR, msg, ap) - -#define LIBXML2_CALLBACK_SERROR(caller, err) wineXmlCallbackError(#caller, err) +#define LIBXML2_CALLBACK_SERROR(caller, err) libxml2_structured_error(#caller, err)
extern BOOL is_preserving_whitespace(xmlNodePtr node) DECLSPEC_HIDDEN; extern BOOL is_xpathmode(const xmlDocPtr doc) DECLSPEC_HIDDEN; diff --git a/dlls/msxml3/schema.c b/dlls/msxml3/schema.c index 253f901..c06bb69 100644 --- a/dlls/msxml3/schema.c +++ b/dlls/msxml3/schema.c @@ -230,85 +230,53 @@ static const BYTE hash_assoc_values[] = 116, 116, 116, 116, 116, 116 };
-static void LIBXML2_LOG_CALLBACK parser_error(void* ctx, char const* msg, ...) -{ - va_list ap; - va_start(ap, msg); - LIBXML2_CALLBACK_ERR(Schema_parse, msg, ap); - va_end(ap); -} - -static void LIBXML2_LOG_CALLBACK parser_warning(void* ctx, char const* msg, ...) -{ - va_list ap; - va_start(ap, msg); - LIBXML2_CALLBACK_WARN(Schema_parse, msg, ap); - va_end(ap); -} - #ifdef HAVE_XMLSCHEMASSETPARSERSTRUCTUREDERRORS -static void parser_serror(void* ctx, xmlErrorPtr err) +static void libxml2_schema_structerror(void* ctx, xmlErrorPtr err) { - LIBXML2_CALLBACK_SERROR(Schema_parse, err); + LIBXML2_CALLBACK_SERROR(schema_parse, err); } #endif
-static inline xmlSchemaPtr Schema_parse(xmlSchemaParserCtxtPtr spctx) +static inline xmlSchemaPtr schema_parse(xmlSchemaParserCtxtPtr ctxt) { - TRACE("(%p)\n", spctx); + TRACE("(%p)\n", ctxt);
- xmlSchemaSetParserErrors(spctx, parser_error, parser_warning, NULL); + xmlSchemaSetParserErrors(ctxt, libxml2_error_callback, libxml2_warn_callback, NULL); #ifdef HAVE_XMLSCHEMASSETPARSERSTRUCTUREDERRORS - xmlSchemaSetParserStructuredErrors(spctx, parser_serror, NULL); + xmlSchemaSetParserStructuredErrors(ctxt, libxml2_schema_structerror, NULL); #endif
- return xmlSchemaParse(spctx); -} - -static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...) -{ - va_list ap; - va_start(ap, msg); - LIBXML2_CALLBACK_ERR(Schema_validate_tree, msg, ap); - va_end(ap); -} - -static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...) -{ - va_list ap; - va_start(ap, msg); - LIBXML2_CALLBACK_WARN(Schema_validate_tree, msg, ap); - va_end(ap); + return xmlSchemaParse(ctxt); }
#ifdef HAVE_XMLSCHEMASSETVALIDSTRUCTUREDERRORS -static void validate_serror(void* ctx, xmlErrorPtr err) +static void libxml2_validate_structerror(void* ctx, xmlErrorPtr err) { - LIBXML2_CALLBACK_SERROR(Schema_validate_tree, err); + LIBXML2_CALLBACK_SERROR(schema_validate_tree, err); } #endif
-static inline HRESULT Schema_validate_tree(xmlSchemaPtr schema, xmlNodePtr tree) +static inline HRESULT schema_validate_tree(xmlSchemaPtr schema, xmlNodePtr tree) { - xmlSchemaValidCtxtPtr svctx; + xmlSchemaValidCtxtPtr ctxt; int err;
TRACE("(%p, %p)\n", schema, tree); /* TODO: if validateOnLoad property is false, * we probably need to validate the schema here. */ - svctx = xmlSchemaNewValidCtxt(schema); - xmlSchemaSetValidErrors(svctx, validate_error, validate_warning, NULL); + ctxt = xmlSchemaNewValidCtxt(schema); + xmlSchemaSetValidErrors(ctxt, libxml2_error_callback, libxml2_warn_callback, NULL); #ifdef HAVE_XMLSCHEMASSETVALIDSTRUCTUREDERRORS - xmlSchemaSetValidStructuredErrors(svctx, validate_serror, NULL); + xmlSchemaSetValidStructuredErrors(ctxt, libxml2_validate_structerror, NULL); #endif
if (tree->type == XML_DOCUMENT_NODE) - err = xmlSchemaValidateDoc(svctx, (xmlDocPtr)tree); + err = xmlSchemaValidateDoc(ctxt, (xmlDocPtr)tree); else - err = xmlSchemaValidateOneElement(svctx, tree); + err = xmlSchemaValidateOneElement(ctxt, tree);
- xmlSchemaFreeValidCtxt(svctx); - return err? S_FALSE : S_OK; + xmlSchemaFreeValidCtxt(ctxt); + return err ? S_FALSE : S_OK; }
static DWORD dt_hash(xmlChar const* str, int len /* calculated if -1 */) @@ -599,11 +567,11 @@ HRESULT dt_validate(XDR_DT dt, xmlChar const* content)
if (!datatypes_schema) { - xmlSchemaParserCtxtPtr spctx; + xmlSchemaParserCtxtPtr ctxt; assert(datatypes_src != NULL); - spctx = xmlSchemaNewMemParserCtxt((char const*)datatypes_src, datatypes_len); - datatypes_schema = Schema_parse(spctx); - xmlSchemaFreeParserCtxt(spctx); + ctxt = xmlSchemaNewMemParserCtxt((char const*)datatypes_src, datatypes_len); + datatypes_schema = schema_parse(ctxt); + xmlSchemaFreeParserCtxt(ctxt); }
switch (dt) @@ -656,7 +624,7 @@ HRESULT dt_validate(XDR_DT dt, xmlChar const* content) xmlSetNs(node, ns); xmlDocSetRootElement(tmp_doc, node);
- hr = Schema_validate_tree(datatypes_schema, (xmlNodePtr)tmp_doc); + hr = schema_validate_tree(datatypes_schema, (xmlNodePtr)tmp_doc); xmlFreeDoc(tmp_doc); } else @@ -844,7 +812,7 @@ static BOOL link_datatypes(xmlDocPtr schema) static cache_entry* cache_entry_from_xsd_doc(xmlDocPtr doc, xmlChar const* nsURI, MSXML_VERSION v) { cache_entry* entry = heap_alloc(sizeof(cache_entry)); - xmlSchemaParserCtxtPtr spctx; + xmlSchemaParserCtxtPtr ctxt; xmlDocPtr new_doc = xmlCopyDoc(doc, 1);
link_datatypes(new_doc); @@ -853,9 +821,9 @@ static cache_entry* cache_entry_from_xsd_doc(xmlDocPtr doc, xmlChar const* nsURI * do we need to do something special here? */ entry->type = CacheEntryType_XSD; entry->ref = 0; - spctx = xmlSchemaNewDocParserCtxt(new_doc); + ctxt = xmlSchemaNewDocParserCtxt(new_doc);
- if ((entry->schema = Schema_parse(spctx))) + if ((entry->schema = schema_parse(ctxt))) { xmldoc_init(entry->schema->doc, v); entry->doc = entry->schema->doc; @@ -868,7 +836,7 @@ static cache_entry* cache_entry_from_xsd_doc(xmlDocPtr doc, xmlChar const* nsURI heap_free(entry); entry = NULL; } - xmlSchemaFreeParserCtxt(spctx); + xmlSchemaFreeParserCtxt(ctxt); return entry; }
@@ -884,7 +852,7 @@ static cache_entry* cache_entry_from_xdr_doc(xmlDocPtr doc, xmlChar const* nsURI entry->ref = 0; spctx = xmlSchemaNewDocParserCtxt(xsd_doc);
- if ((entry->schema = Schema_parse(spctx))) + if ((entry->schema = schema_parse(spctx))) { entry->doc = new_doc; xmldoc_init(entry->schema->doc, version); @@ -1443,7 +1411,7 @@ HRESULT SchemaCache_validate_tree(IXMLDOMSchemaCollection2* iface, xmlNodePtr tr /* TODO: if the ns is not in the cache, and it's a URL, * do we try to load from that? */ if (schema) - return Schema_validate_tree(schema, tree); + return schema_validate_tree(schema, tree); else WARN("no schema found for xmlns=%s\n", get_node_nsURI(tree));
diff --git a/dlls/msxml3/selection.c b/dlls/msxml3/selection.c index ba173f9..61e7f24 100644 --- a/dlls/msxml3/selection.c +++ b/dlls/msxml3/selection.c @@ -738,7 +738,7 @@ static void XSLPattern_OP_IGEq(xmlXPathParserContextPtr pctx, int nargs) xmlFree(arg2); }
-static void query_serror(void* ctx, xmlErrorPtr err) +static void libxml2_selection_structerror(void* ctx, xmlErrorPtr err) { LIBXML2_CALLBACK_SERROR(domselection_create, err); } @@ -767,7 +767,7 @@ HRESULT create_selection(xmlNodePtr node, xmlChar* query, IXMLDOMNodeList **out) init_dispex(&This->dispex, (IUnknown*)&This->IXMLDOMSelection_iface, &domselection_dispex); xmldoc_add_ref(This->node->doc);
- ctxt->error = query_serror; + ctxt->error = libxml2_selection_structerror; ctxt->node = node; registerNamespaces(ctxt);
-- 1.5.6.5