I believe that I've discovered a validation scenario that causes a Heap corruption in MSXML6.
I've been using the MSXML6 ISAXXMLReader to validate xml against an xsd schema in my application. The scenario that causes the issue is when you have multiple references to an IDREF that is not found in the xml document. Curiously only having one reference
does not cause the issue. For example with the following schema:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" elementFormDefault="qualified" attributeFormDefault="unqualified" vc:minVersion="1.1"><xs:element name="Example"><xs:annotation><xs:documentation>Comment describing your root element</xs:documentation></xs:annotation><xs:complexType><xs:sequence><xs:element name="ExampleElement" type="xs:IDREF" minOccurs="0" maxOccurs="unbounded"/><xs:element name="IDElement" type="xs:ID" minOccurs="0"/></xs:sequence></xs:complexType></xs:element></xs:schema>
This xml example returns the expected validation message:
example_good.xml
<Example><ExampleElement>ID1</ExampleElement></Example>
output:
Parsing document: example_good.xml
Error Message:
The ID 'ID1' is referenced but not defined in the document.
Error Message:
Validate failed.
Parse result code: c00ce225
However, if you have two referenced ID's that are not found the SAX reader will return the following error message:
example_bad.xml
<Example><ExampleElement>ID1</ExampleElement><ExampleElement>ID1</ExampleElement></Example>
output:
Parsing document: example_bad.xml
Error Message:
System error: -1072898003.
Error Message:
Validate failed.
Parse result code: c00ce225
In addition to that, later in my program's execution (in an entirely different dll) when stopping the thread the whole application would crash with heap corruption error.
To isolate what was causing the issue I made a simple cli version of the SAX validator. My implementation is very similar to the [example on msdn.](https://msdn.microsoft.com/en-us/library/cc507429(v=vs.85).aspx)
#ifdef _MSC_VER #define _CRT_SECURE_NO_WARNINGS #endif #include <stdio.h> #include <tchar.h> #include <windows.h> #include <objbase.h> #if _WIN32 #import <msxml6.dll> no_auto_exclude #else #import <msxml6.dll> #endif #include "SAXErrorHandlerImpl.h" int _tmain(int argc, _TCHAR* argv[]) { if (argc<2) { printf("\nTo run, enter\n\tSaxJumpStart file:///drive:/path/file.xml\n\n"); return 0; // Need URL to read } CoInitialize(NULL); ISAXXMLReader* pRdr = NULL; HRESULT hr = CoCreateInstance( __uuidof(SAXXMLReader60), NULL, CLSCTX_ALL, __uuidof(ISAXXMLReader), (void **)&pRdr); if (!FAILED(hr)) { // Set IATA namespace for NDC transactions and path to schema file _bstr_t bstrNamespace = L""; _bstr_t bstrPath = "Example.xsd"; // Configure Schema Cache MSXML2::IXMLDOMSchemaCollectionPtr pXS; pXS.CreateInstance(__uuidof(XMLSchemaCache60), NULL, CLSCTX_INPROC_SERVER); pXS->add(bstrNamespace, bstrPath); // Configure SAX Reader for schema validation hr = pRdr->putFeature(L"schema-validation", VARIANT_TRUE); hr = pRdr->putFeature(L"exhaustive-errors", VARIANT_TRUE); // Show just one or all errors hr = pRdr->putProperty(L"schemas", _variant_t(pXS.GetInterfacePtr())); // Set error handler SAXErrorHandlerImpl * pEc = new SAXErrorHandlerImpl(); hr = pRdr->putErrorHandler(pEc); printf("\nParsing document: %S\n", argv[1]); hr = pRdr->parseURL(argv[1]); printf("\nParse result code: %08x\n\n", hr); pRdr->Release(); } else { printf("\nError %08X\n\n", hr); } CoUninitialize(); return 0; }
When I run this using the Application Verifier it crashes on the pRdr->parseURL() function. This is the output of the Application Verirfier:
<avrf:logfile xmlns:avrf="Application Verifier"><avrf:logSession TimeStarted="2018-05-11 : 16:18:34" PID="29252" Version="2"><avrf:logEntry Time="2018-05-11 : 16:18:35" LayerName="Heaps" StopCode="0x13" Severity="Error"><avrf:message>First chance access violation for current stack trace.</avrf:message><avrf:parameter1>d25afc8 - Invalid address causing the exception.</avrf:parameter1><avrf:parameter2>fc63f35 - Code address executing the invalid access.</avrf:parameter2><avrf:parameter3>9bf4e8 - Exception record.</avrf:parameter3><avrf:parameter4>9bf538 - Context record.</avrf:parameter4><avrf:stackTrace><avrf:trace>vrfcore!VerifierDisableVerifier+708 ( @ 0)</avrf:trace><avrf:trace>verifier!VerifierStopMessage+74 ( @ 0)</avrf:trace><avrf:trace>ntdll!RtlApplicationVerifierStop+7d ( @ 0)</avrf:trace><avrf:trace>vfbasics!+fa57160 ( @ 0)</avrf:trace><avrf:trace>vfbasics!+fa587e8 ( @ 0)</avrf:trace><avrf:trace>vfbasics!+fa58134 ( @ 0)</avrf:trace><avrf:trace>ntdll!WinSqmEventWrite+1d1ee ( @ 0)</avrf:trace><avrf:trace>ntdll!RtlUnwind+1ba ( @ 0)</avrf:trace><avrf:trace>ntdll!KiUserExceptionDispatcher+f ( @ 0)</avrf:trace><avrf:trace>msxml6!StartUI+5e0a2 ( @ 0)</avrf:trace><avrf:trace>msxml6!StartUI+3c6a5 ( @ 0)</avrf:trace><avrf:trace>msxml6!StartUI+89e4a ( @ 0)</avrf:trace><avrf:trace>msxml6!StartUI+8a707 ( @ 0)</avrf:trace><avrf:trace>msxml6!StartUI+8b76e ( @ 0)</avrf:trace><avrf:trace>msxml6!StartUI+9f12a ( @ 0)</avrf:trace><avrf:trace>SAXErrorHandling!wmain+2ff (c:\users\rmelrose\documents\visual studio 2015\projects\schemalocationproj\schemalocationproj\saxval.cpp @ 57)</avrf:trace><avrf:trace>SAXErrorHandling!invoke_main+1e (f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 79)</avrf:trace><avrf:trace>SAXErrorHandling!__scrt_common_main_seh+150 (f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 253)</avrf:trace><avrf:trace>SAXErrorHandling!__scrt_common_main+d (f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 296)</avrf:trace><avrf:trace>SAXErrorHandling!wmainCRTStartup+8 (f:\dd\vctools\crt\vcstartup\src\startup\exe_wmain.cpp @ 17)</avrf:trace><avrf:trace>KERNEL32!BaseThreadInitThunk+24 ( @ 0)</avrf:trace><avrf:trace>ntdll!RtlSubscribeWnfStateChangeNotification+439 ( @ 0)</avrf:trace><avrf:trace>ntdll!RtlSubscribeWnfStateChangeNotification+404 ( @ 0)</avrf:trace></avrf:stackTrace></avrf:logEntry></avrf:logSession></avrf:logfile>
Is this an issue with MSXML6 or the way that I am using it?
Is there anything I can do to keep it from crashing my application?