Upgrade to tinyxml2 7.0.1 (2018-11-17)

Test: builds, boots, tinyxml2 tests pass
Change-Id: Ia4ca2327925f9a678cbae6febdb5341151a1ec10
diff --git a/xmltest.cpp b/xmltest.cpp
index 91494ec..a0aaee7 100644
--- a/xmltest.cpp
+++ b/xmltest.cpp
@@ -34,7 +34,7 @@
 		pass = true;

 	else if ( !expected || !found )

 		pass = false;

-	else 

+	else

 		pass = !strcmp( expected, found );

 	if ( pass )

 		printf ("[pass]");

@@ -82,8 +82,15 @@
 

 	if ( !echo )

 		printf (" %s\n", testString);

-	else

-		printf (" %s [%d][%d]\n", testString, static_cast<int>(expected), static_cast<int>(found) );

+	else {

+		char expectedAsString[64];

+		XMLUtil::ToStr(expected, expectedAsString, sizeof(expectedAsString));

+

+		char foundAsString[64];

+		XMLUtil::ToStr(found, foundAsString, sizeof(foundAsString));

+

+		printf (" %s [%s][%s]\n", testString, expectedAsString, foundAsString );

+	}

 

 	if ( pass )

 		++gPass;

@@ -112,7 +119,7 @@
 

 	return doc.ErrorID();

 }

-/** @page Example-1 Load an XML File

+/** @page Example_1 Load an XML File

  *  @dontinclude ./xmltest.cpp

  *  Basic XML file loading.

  *  The basic syntax to load an XML file from

@@ -121,7 +128,7 @@
  *  @skip example_1()

  *  @until }

  */

- 

+

 

 int example_2()

 {

@@ -131,7 +138,7 @@
 

 	return doc.ErrorID();

 }

-/** @page Example-2 Parse an XML from char buffer

+/** @page Example_2 Parse an XML from char buffer

  *  @dontinclude ./xmltest.cpp

  *  Basic XML string parsing.

  *  The basic syntax to parse an XML for

@@ -164,7 +171,7 @@
 

 	return doc.ErrorID();

 }

-/** @page Example-3 Get information out of XML

+/** @page Example_3 Get information out of XML

 	@dontinclude ./xmltest.cpp

 	In this example, we navigate a simple XML

 	file, and read some interesting text. Note

@@ -172,8 +179,8 @@
 	checking; working code should check for null

 	pointers when walking an XML tree, or use

 	XMLHandle.

-	

-	(The XML is an excerpt from "dream.xml"). 

+

+	(The XML is an excerpt from "dream.xml").

 

 	@skip example_3()

 	@until </PLAY>";

@@ -192,7 +199,7 @@
 		</ul>

 	</ul>

 

-	For this example, we want to print out the 

+	For this example, we want to print out the

 	title of the play. The text of the title (what

 	we want) is child of the "TITLE" element which

 	is a child of the "PLAY" element.

@@ -212,8 +219,8 @@
 

 	Text is just another Node in the XML DOM. And in

 	fact you should be a little cautious with it, as

-	text nodes can contain elements. 

-	

+	text nodes can contain elements.

+

 	@verbatim

 	Consider: A Midsummer Night's <b>Dream</b>

 	@endverbatim

@@ -225,7 +232,7 @@
 

 	Noting that here we use FirstChild() since we are

 	looking for XMLText, not an element, and ToText()

-	is a cast from a Node to a XMLText. 

+	is a cast from a Node to a XMLText.

 */

 

 

@@ -255,7 +262,7 @@
 

 	return !doc.Error() && ( v0 == v1 );

 }

-/** @page Example-4 Read attributes and text information.

+/** @page Example_4 Read attributes and text information.

 	@dontinclude ./xmltest.cpp

 

 	There are fundamentally 2 ways of writing a key-value

@@ -269,7 +276,7 @@
 	@skip example_4()

 	@until "</information>";

 

-	TinyXML-2 has accessors for both approaches. 

+	TinyXML-2 has accessors for both approaches.

 

 	When using an attribute, you navigate to the XMLElement

 	with that attribute and use the QueryIntAttribute()

@@ -292,7 +299,7 @@
 

 int main( int argc, const char ** argv )

 {

-	#if defined( _MSC_VER ) && defined( DEBUG )

+	#if defined( _MSC_VER ) && defined( TINYXML2_DEBUG )

 		_CrtMemCheckpoint( &startMemState );

 		// Enable MS Visual C++ debug heap memory leaks dump on exit

 		_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);

@@ -338,10 +345,10 @@
 	}

 	fclose( fp );

 

-	XMLTest( "Example-1", 0, example_1() );

-	XMLTest( "Example-2", 0, example_2() );

-	XMLTest( "Example-3", 0, example_3() );

-	XMLTest( "Example-4", true, example_4() );

+	XMLTest( "Example_1", 0, example_1() );

+	XMLTest( "Example_2", 0, example_2() );

+	XMLTest( "Example_3", 0, example_3() );

+	XMLTest( "Example_4", true, example_4() );

 

 	/* ------ Example 2: Lookup information. ---- */

 

@@ -535,7 +542,7 @@
 

 		XMLTest( "Dream", "xml version=\"1.0\"",

 						  doc.FirstChild()->ToDeclaration()->Value() );

-		XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false );

+		XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() != 0 );

 		XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",

 						  doc.FirstChild()->NextSibling()->ToUnknown()->Value() );

 		XMLTest( "Dream", "And Robin shall restore amends.",

@@ -548,7 +555,7 @@
 		XMLTest( "Load dreamout.xml", false, doc2.Error() );

 		XMLTest( "Dream-out", "xml version=\"1.0\"",

 						  doc2.FirstChild()->ToDeclaration()->Value() );

-		XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false );

+		XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() != 0 );

 		XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",

 						  doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );

 		XMLTest( "Dream-out", "And Robin shall restore amends.",

@@ -567,6 +574,10 @@
 		XMLDocument doc;

 		doc.Parse( error );

 		XMLTest( "Bad XML", XML_ERROR_PARSING_ATTRIBUTE, doc.ErrorID() );

+		const char* errorStr = doc.ErrorStr();

+		XMLTest("Formatted error string",

+			"Error=XML_ERROR_PARSING_ATTRIBUTE ErrorID=7 (0x7) Line number=3: XMLElement name=wrong",

+			errorStr);

 	}

 

 	{

@@ -647,7 +658,7 @@
 		XMLTest( "Alternate query", true, iVal == iVal2 );

 		XMLTest( "Alternate query", true, dVal == dVal2 );

 		XMLTest( "Alternate query", true, iVal == ele->IntAttribute("int") );

-		XMLTest( "Alternate query", true, dVal == ele->DoubleAttribute("double") );		

+		XMLTest( "Alternate query", true, dVal == ele->DoubleAttribute("double") );

 	}

 

 	{

@@ -762,7 +773,7 @@
 		doc.Parse( str );

 		XMLTest( "Text in nested element", false, doc.Error() );

 		element = doc.RootElement();

-		

+

 		element->SetText("wolves");

 		XMLTest( "SetText() prefix to nested non-text children.", "wolves", element->GetText() );

 

@@ -770,7 +781,7 @@
 		doc.Parse( str );

 		XMLTest( "Empty self-closed element round 2", false, doc.Error() );

 		element = doc.RootElement();

-		

+

 		element->SetText( "str" );

 		XMLTest( "SetText types", "str", element->GetText() );

 

@@ -827,6 +838,14 @@
 				XMLTest("Attribute: unsigned", (int)XML_SUCCESS, queryResult, true);

 				XMLTest("Attribute: unsigned", unsigned(100), v, true);

 			}

+			{

+				const char* v = "failed";

+				XMLError queryResult = element->QueryStringAttribute("not-attrib", &v);

+				XMLTest("Attribute: string default", false, queryResult == XML_SUCCESS);

+				queryResult = element->QueryStringAttribute("attrib", &v);

+				XMLTest("Attribute: string", XML_SUCCESS, queryResult, true);

+				XMLTest("Attribute: string", "100", v);

+			}

 			XMLTest("Attribute: unsigned", unsigned(100), element->UnsignedAttribute("attrib"), true);

 		}

 		{

@@ -1160,6 +1179,12 @@
 		XMLDocument doc;

 		doc.Parse( str );

 		XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );

+

+		// But be sure there is an error string!

+		const char* errorStr = doc.ErrorStr();

+		XMLTest("Error string should be set",

+			"Error=XML_ERROR_EMPTY_DOCUMENT ErrorID=13 (0xd) Line number=0",

+			errorStr);

 	}

 

 	{

@@ -1452,28 +1477,31 @@
 		static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";

 		XMLDocument doc;

 		doc.Parse( xml );

-		XMLTest( "Parse element with attribute and nested element round 1", false, doc.Error() );

+		XMLTest( "Handle, parse element with attribute and nested element", false, doc.Error() );

 

-		XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();

-		XMLTest( "Handle, success, mutable", "sub", ele->Value() );

+		{

+			XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();

+			XMLTest( "Handle, non-const, element is found", true, ele != 0 );

+			XMLTest( "Handle, non-const, element name matches", "sub", ele->Value() );

+		}

 

-		XMLHandle docH( doc );

-		ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();

-		XMLTest( "Handle, dne, mutable", true, ele == 0 );

-	}

+		{

+			XMLHandle docH( doc );

+			XMLElement* ele = docH.FirstChildElement( "noSuchElement" ).FirstChildElement( "element" ).ToElement();

+			XMLTest( "Handle, non-const, element not found", true, ele == 0 );

+		}

 

-	{

-		static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";

-		XMLDocument doc;

-		doc.Parse( xml );

-		XMLTest( "Parse element with attribute and nested element round 2", false, doc.Error() );

-		XMLConstHandle docH( doc );

+		{

+			const XMLElement* ele = XMLConstHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();

+			XMLTest( "Handle, const, element is found", true, ele != 0 );

+			XMLTest( "Handle, const, element name matches", "sub", ele->Value() );

+		}

 

-		const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();

-		XMLTest( "Handle, success, const", "sub", ele->Value() );

-

-		ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();

-		XMLTest( "Handle, dne, const", true, ele == 0 );

+		{

+			XMLConstHandle docH( doc );

+			const XMLElement* ele = docH.FirstChildElement( "noSuchElement" ).FirstChildElement( "element" ).ToElement();

+			XMLTest( "Handle, const, element not found", true, ele == 0 );

+		}

 	}

 	{

 		// Default Declaration & BOM

@@ -1546,14 +1574,14 @@
 		doc.Parse( xml );

 		XMLTest( "Non-alpha element lead letter parses.", false, doc.Error() );

 	}

-    

+

     {

         const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";

         XMLDocument doc;

         doc.Parse( xml );

         XMLTest("Non-alpha attribute lead character parses.", false, doc.Error());

     }

-    

+

     {

         const char* xml = "<3lement></3lement>";

         XMLDocument doc;

@@ -1589,7 +1617,7 @@
         doc.Clear();

         XMLTest( "No error after Clear()", false, doc.Error() );

     }

-    

+

 	// ----------- Whitespace ------------

 	{

 		const char* xml = "<element>"

@@ -1761,6 +1789,7 @@
 		XMLTest( "Insertion with removal parse round 4", false, doc.Error() );

 		subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");

 		two = doc.RootElement()->FirstChildElement("two");

+		XMLTest("<two> is the last child at root level", true, two == doc.RootElement()->LastChildElement());

 		doc.RootElement()->InsertEndChild(subtree);

 		XMLPrinter printer4(0, true);

 		acceptResult = doc.Accept(&printer4);

@@ -1788,7 +1817,7 @@
 	}

 

 #if 1

-		// the question being explored is what kind of print to use: 

+		// the question being explored is what kind of print to use:

 		// https://github.com/leethomason/tinyxml2/issues/63

 	{

 		//const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";

@@ -1815,14 +1844,14 @@
 		/* The result of this test is platform, compiler, and library version dependent. :("

 		XMLPrinter printer;

 		doc.Print( &printer );

-		XMLTest( "Float and double formatting.", 

+		XMLTest( "Float and double formatting.",

 			"<element attrA-f64=\"123456789.12345679\" attrB-f64=\"1001000000\" attrC-f64=\"1e+20\" attrD-f64=\"0.123456789\" attrA-f32=\"1.2345679e+08\" attrB-f32=\"1.001e+09\" attrC-f32=\"1e+20\" attrD-f32=\"0.12345679\"/>\n",

-			printer.CStr(), 

+			printer.CStr(),

 			true );

 		*/

 	}

 #endif

-    

+

     {

         // Issue #184

         // If it doesn't assert, it passes. Caused by objects

@@ -1841,9 +1870,9 @@
             doc.Clear();

         }

     }

-    

+

     {

-        // If this doesn't assert in DEBUG, all is well.

+        // If this doesn't assert in TINYXML2_DEBUG, all is well.

         tinyxml2::XMLDocument doc;

         tinyxml2::XMLElement *pRoot = doc.NewElement("Root");

         doc.DeleteNode(pRoot);

@@ -1858,7 +1887,7 @@
     }

 

     {

-        // If this doesn't assert in DEBUG, all is well.

+        // If this doesn't assert in TINYXML2_DEBUG, all is well.

         XMLDocument doc;

         XMLElement* unlinkedRoot = doc.NewElement( "Root" );

         XMLElement* linkedRoot = doc.NewElement( "Root" );

@@ -1868,7 +1897,7 @@
     }

 

 	{

-		// Should not assert in DEBUG

+		// Should not assert in TINYXML2_DEBUG

 		XMLPrinter printer;

 	}

 

@@ -1883,7 +1912,7 @@
 		doc.Print( &printer );

 	}

 	{

-		// Issue 299. Can print elements that are not linked in. 

+		// Issue 299. Can print elements that are not linked in.

 		// Will crash if issue not fixed.

 		XMLDocument doc;

 		XMLElement* newElement = doc.NewElement( "printme" );

@@ -1936,7 +1965,7 @@
 	    doc.Parse(xml1);

 	    XMLTest("Test that the second declaration is allowed", false, doc.Error() );

 	    doc.Parse(xml2);

-	    XMLTest("Test that declaration after a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );

+	    XMLTest("Test that declaration after self-closed child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );

 	    doc.Parse(xml3);

 	    XMLTest("Test that declaration after a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );

 	    doc.Parse(xml4);

@@ -1946,7 +1975,7 @@
     {

 	    // No matter - before or after successfully parsing a text -

 	    // calling XMLDocument::Value() used to cause an assert in debug.

-	    // Null must be retured.

+	    // Null must be returned.

 	    const char* validXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"

 	                           "<first />"

 	                           "<second />";

@@ -1963,13 +1992,30 @@
 		for( int i = 0; i < XML_ERROR_COUNT; i++ ) {

 			const XMLError error = static_cast<XMLError>(i);

 			const char* name = XMLDocument::ErrorIDToName(error);

-			XMLTest( "ErrorName() after ClearError()", true, name != 0 );

-			XMLTest( "ErrorName() after ClearError()", true, strlen(name) > 0 );

+			XMLTest( "ErrorName() not null after ClearError()", true, name != 0 );

+			if( name == 0 ) {

+				// passing null pointer into strlen() is undefined behavior, so

+				// compiler is allowed to optimise away the null test above if it's

+				// as reachable as the strlen() call

+				continue;

+			}

+			XMLTest( "ErrorName() not empty after ClearError()", true, strlen(name) > 0 );

 		}

 	}

 

 	{

-		// Evil memory leaks. 

+		const char* html("<!DOCTYPE html><html><body><p>test</p><p><br/></p></body></html>");

+		XMLDocument doc(false);

+		doc.Parse(html);

+

+		XMLPrinter printer(0, true);

+		doc.Print(&printer);

+

+		XMLTest(html, html, printer.CStr());

+	}

+

+	{

+		// Evil memory leaks.

 		// If an XMLElement (etc) is allocated via NewElement() (etc.)

 		// and NOT added to the XMLDocument, what happens?

 		//

@@ -1999,6 +2045,32 @@
 	}

 

 	{

+		// Bad bad crash. Parsing error results in stack overflow, if uncaught.

+		const char* TESTS[] = {

+			"./resources/xmltest-5330.xml",

+			"./resources/xmltest-4636783552757760.xml",

+			"./resources/xmltest-5720541257269248.xml",

+			0

+		};

+		for (int i=0; TESTS[i]; ++i) {

+			XMLDocument doc;

+			doc.LoadFile(TESTS[i]);

+			XMLTest("Stack overflow prevented.", XML_ELEMENT_DEPTH_EXCEEDED, doc.ErrorID());

+		}

+	}

+    {

+        const char* TESTS[] = {

+            "./resources/xmltest-5662204197076992.xml",     // Security-level performance issue.

+            0

+        };

+        for (int i = 0; TESTS[i]; ++i) {

+            XMLDocument doc;

+            doc.LoadFile(TESTS[i]);

+            // Need only not crash / lock up.

+            XMLTest("Fuzz attack prevented.", true, true);

+        }

+    }

+	{

 		// Crashing reported via email.

 		const char* xml =

 			"<playlist id='playlist1'>"

@@ -2052,7 +2124,7 @@
 		XMLTest("Crash bug parsing - Accept()", true, acceptResult);

 		printf("%s\n", printer.CStr());

 

-		// No test; it only need to not crash. 

+		// No test; it only need to not crash.

 		// Still, wrap it up with a sanity check

 		int nProperty = 0;

 		for (const XMLElement* p = playlist->FirstChildElement("property"); p; p = p->NextSiblingElement("property")) {

@@ -2248,7 +2320,7 @@
 		delete[] mem;

 

 		static const char* note =

-#ifdef DEBUG

+#ifdef TINYXML2_DEBUG

 			"DEBUG";

 #else

 			"Release";

@@ -2262,7 +2334,7 @@
 		printf("\nParsing dream.xml (%s): %.3f milli-seconds\n", note, duration);

 	}

 

-#if defined( _MSC_VER ) &&  defined( DEBUG )

+#if defined( _MSC_VER ) &&  defined( TINYXML2_DEBUG )

 	{

 		_CrtMemCheckpoint( &endMemState );