From db70364559032b8415545922fd148b320e8f0c4d Mon Sep 17 00:00:00 2001 From: JinWang An Date: Fri, 30 Oct 2020 14:35:10 +0900 Subject: [PATCH] Imported Upstream version 7.0.0 --- CMakeLists.txt | 89 ++++++------------------- Config.cmake.in | 4 ++ Makefile | 1 + dox | 4 +- readme.md | 114 +++++++++++++++------------------ resources/xmltest-5662204197076992.xml | 1 + tinyxml2.cpp | 47 ++++++++------ tinyxml2.h | 109 +++++++++++++++---------------- xmltest.cpp | 87 +++++++++++++++++-------- 9 files changed, 219 insertions(+), 237 deletions(-) create mode 100644 Config.cmake.in create mode 100644 resources/xmltest-5662204197076992.xml diff --git a/CMakeLists.txt b/CMakeLists.txt index a64e68e..bd8005e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,17 +21,15 @@ include(CTest) ################################ # set lib version here -set(GENERIC_LIB_VERSION "6.2.0") -set(GENERIC_LIB_SOVERSION "6") +set(GENERIC_LIB_VERSION "7.0.0") +set(GENERIC_LIB_SOVERSION "7") ################################ # Add definitions -set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DTINYXML2_DEBUG") - ################################ # Add targets -# By Default shared libray is being built +# By Default shared library is being built # To build static libs also - Do cmake . -DBUILD_STATIC_LIBS:BOOL=ON # User can choose not to build shared library by using cmake -DBUILD_SHARED_LIBS:BOOL=OFF # To build only static libs use cmake . -DBUILD_SHARED_LIBS:BOOL=OFF -DBUILD_STATIC_LIBS:BOOL=ON @@ -39,28 +37,30 @@ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DTINYXML2_DEBUG") # To disable the building of the tests, use cmake . -DBUILD_TESTS:BOOL=OFF option(BUILD_SHARED_LIBS "build as shared library" ON) -option(BUILD_STATIC_LIBS "build as static library" OFF) option(BUILD_TESTS "build xmltest (deprecated: Use BUILD_TESTING)" ON) +# To allow using tinyxml in another shared library +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + set(CMAKE_CXX_VISIBILITY_PRESET hidden) set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) # to distinguish between debug and release lib set(CMAKE_DEBUG_POSTFIX "d") -if(BUILD_SHARED_LIBS) -add_library(tinyxml2 SHARED tinyxml2.cpp tinyxml2.h) +add_library(tinyxml2 tinyxml2.cpp tinyxml2.h) set_target_properties(tinyxml2 PROPERTIES COMPILE_DEFINITIONS "TINYXML2_EXPORT" VERSION "${GENERIC_LIB_VERSION}" SOVERSION "${GENERIC_LIB_SOVERSION}") +target_compile_definitions(tinyxml2 PUBLIC $<$:TINYXML2_DEBUG>) if(DEFINED CMAKE_VERSION AND NOT "${CMAKE_VERSION}" VERSION_LESS "2.8.11") target_include_directories(tinyxml2 PUBLIC $ - $) + $) if(MSVC) target_compile_definitions(tinyxml2 PUBLIC -D_CRT_SECURE_NO_WARNINGS) @@ -82,60 +82,17 @@ install(TARGETS tinyxml2 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) -endif() - -if(BUILD_STATIC_LIBS) -add_library(tinyxml2_static STATIC tinyxml2.cpp tinyxml2.h) -set_target_properties(tinyxml2_static PROPERTIES - COMPILE_DEFINITONS "TINYXML2_EXPORT" - VERSION "${GENERIC_LIB_VERSION}" - SOVERSION "${GENERIC_LIB_SOVERSION}") -set_target_properties( tinyxml2_static PROPERTIES OUTPUT_NAME tinyxml2 ) - -target_compile_definitions(tinyxml2_static PUBLIC -D_CRT_SECURE_NO_WARNINGS) - -if(DEFINED CMAKE_VERSION AND NOT "${CMAKE_VERSION}" VERSION_LESS "2.8.11") - target_include_directories(tinyxml2_static PUBLIC - $ - $) - - if(MSVC) - target_compile_definitions(tinyxml2_static PUBLIC -D_CRT_SECURE_NO_WARNINGS) - endif(MSVC) -else() - include_directories(${PROJECT_SOURCE_DIR}) - - if(MSVC) - add_definitions(-D_CRT_SECURE_NO_WARNINGS) - endif(MSVC) -endif() - -# export targets for find_package config mode -export(TARGETS tinyxml2_static - FILE ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}Targets.cmake) - -install(TARGETS tinyxml2_static - EXPORT ${CMAKE_PROJECT_NAME}Targets - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) -endif() if(BUILD_TESTING AND BUILD_TESTS) add_executable(xmltest xmltest.cpp) - if(BUILD_SHARED_LIBS) - add_dependencies(xmltest tinyxml2) - target_link_libraries(xmltest tinyxml2) - else(BUILD_STATIC_LIBS) - add_dependencies(xmltest tinyxml2_static) - target_link_libraries(xmltest tinyxml2_static) - endif() + add_dependencies(xmltest tinyxml2) + target_link_libraries(xmltest tinyxml2) # Copy test resources and create test output directory add_custom_command(TARGET xmltest POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/resources $/resources + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/resources $/resources COMMAND ${CMAKE_COMMAND} -E make_directory $/resources/out - COMMENT "Configuring xmltest resources directory: ${CMAKE_BINARY_DIR}/resources" + COMMENT "Configuring xmltest resources directory: ${CMAKE_CURRENT_BINARY_DIR}/resources" ) add_test(NAME xmltest COMMAND xmltest WORKING_DIRECTORY $) @@ -143,13 +100,6 @@ endif() install(FILES tinyxml2.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) -foreach(p LIB INCLUDE) - set(var CMAKE_INSTALL_${p}DIR) - if(NOT IS_ABSOLUTE "${${var}}") - set(${var} "${CMAKE_INSTALL_PREFIX}/${${var}}") - endif() -endforeach() - configure_file(tinyxml2.pc.in tinyxml2.pc @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/tinyxml2.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) @@ -164,13 +114,16 @@ if(NOT TARGET uninstall) COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) endif() -file(WRITE - ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}Config.cmake - "include(\${CMAKE_CURRENT_LIST_DIR}/${CMAKE_PROJECT_NAME}Targets.cmake)\n") - +include(CMakePackageConfigHelpers) +set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") +configure_package_config_file( + "Config.cmake.in" + "${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}Config.cmake" + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${CMAKE_PROJECT_NAME}" +) install(FILES ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}Config.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${CMAKE_PROJECT_NAME}) -install(EXPORT ${CMAKE_PROJECT_NAME}Targets +install(EXPORT ${CMAKE_PROJECT_NAME}Targets NAMESPACE tinyxml2:: DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${CMAKE_PROJECT_NAME}) diff --git a/Config.cmake.in b/Config.cmake.in new file mode 100644 index 0000000..38bbde7 --- /dev/null +++ b/Config.cmake.in @@ -0,0 +1,4 @@ +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake") +check_required_components("@PROJECT_NAME@") diff --git a/Makefile b/Makefile index 66b1bc9..5989b95 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ ARFLAGS = cr RM = rm -f RANLIB = ranlib MKDIR = mkdir -p +CXXFLAGS = -fPIC INSTALL = install INSTALL_PROGRAM = $(INSTALL) diff --git a/dox b/dox index 4f8dbb3..9756283 100644 --- a/dox +++ b/dox @@ -39,9 +39,9 @@ PROJECT_NAME = "TinyXML-2" # control system is used. <<<<<<< HEAD -PROJECT_NUMBER = 6.2.0 +PROJECT_NUMBER = 7.0.0 ======= -PROJECT_NUMBER = 6.2.0 +PROJECT_NUMBER = 7.0.0 >>>>>>> master # Using the PROJECT_BRIEF tag one can provide an optional one line description diff --git a/readme.md b/readme.md index c5bc5a4..a519bfa 100644 --- a/readme.md +++ b/readme.md @@ -5,7 +5,7 @@ TinyXML-2 ![TinyXML-2 Logo](http://www.grinninglizard.com/tinyxml2/TinyXML2_small.png) -TinyXML-2 is a simple, small, efficient, C++ XML parser that can be +TinyXML-2 is a simple, small, efficient, C++ XML parser that can be easily integrated into other programs. The master is hosted on github: @@ -18,30 +18,30 @@ Examples are in the "related pages" tab of the HTML docs. What it does. ------------- - -In brief, TinyXML-2 parses an XML document, and builds from that a + +In brief, TinyXML-2 parses an XML document, and builds from that a Document Object Model (DOM) that can be read, modified, and saved. XML stands for "eXtensible Markup Language." It is a general purpose human and machine readable markup language to describe arbitrary data. -All those random file formats created to store application data can +All those random file formats created to store application data can all be replaced with XML. One parser for everything. http://en.wikipedia.org/wiki/XML There are different ways to access and interact with XML data. TinyXML-2 uses a Document Object Model (DOM), meaning the XML data is parsed -into a C++ objects that can be browsed and manipulated, and then -written to disk or another output stream. You can also construct an XML document +into a C++ objects that can be browsed and manipulated, and then +written to disk or another output stream. You can also construct an XML document from scratch with C++ objects and write this to disk or another output stream. You can even use TinyXML-2 to stream XML programmatically from code without creating a document first. TinyXML-2 is designed to be easy and fast to learn. It is one header and -one cpp file. Simply add these to your project and off you go. -There is an example file - xmltest.cpp - to get you started. +one cpp file. Simply add these to your project and off you go. +There is an example file - xmltest.cpp - to get you started. -TinyXML-2 is released under the ZLib license, +TinyXML-2 is released under the ZLib license, so you can use it in open source or commercial code. The details of the license are at the top of every source file. @@ -53,49 +53,37 @@ What it doesn't do. ------------------- TinyXML-2 doesn't parse or use DTDs (Document Type Definitions) or XSLs -(eXtensible Stylesheet Language.) There are other parsers out there -that are much more fully featured. But they are also much bigger, -take longer to set up in your project, have a higher learning curve, -and often have a more restrictive license. If you are working with +(eXtensible Stylesheet Language.) There are other parsers out there +that are much more fully featured. But they are also much bigger, +take longer to set up in your project, have a higher learning curve, +and often have a more restrictive license. If you are working with browsers or have more complete XML needs, TinyXML-2 is not the parser for you. TinyXML-1 vs. TinyXML-2 ----------------------- TinyXML-2 is now the focus of all development, well tested, and your -best choice unless you have a requirement to maintain TinyXML-1 code. +best choice between the two APIs. At this point, unless you are maintaining +legacy code, you should choose TinyXML-2. TinyXML-2 uses a similar API to TinyXML-1 and the same rich test cases. But the implementation of the parser is completely re-written to make it more appropriate for use in a game. It uses less memory, is faster, and uses far fewer memory allocations. -TinyXML-2 has no requirement for STL, but has also dropped all STL support. All -strings are query and set as 'const char*'. This allows the use of internal -allocators, and keeps the code much simpler. - -Both parsers: - -1. Simple to use with similar APIs. -2. DOM based parser. -3. UTF-8 Unicode support. http://en.wikipedia.org/wiki/UTF-8 +TinyXML-2 has no requirement or support for STL. By returning `const char*` +TinyXML-2 can be much more efficient with memory usage. (TinyXML-1 did support +and use STL, but consumed much more memory for the DOM representation.) -Advantages of TinyXML-2 - -1. The focus of all future dev. -2. Many fewer memory allocation (1/10th to 1/100th), uses less memory - (about 40% of TinyXML-1), and faster. -3. No STL requirement. -4. More modern C++, including a proper namespace. -5. Proper and useful handling of whitespace +Features +-------- -Advantages of TinyXML-1 +### Code Page -1. Support for some C++ STL conventions: streams and strings -2. Very mature and well debugged code base. +TinyXML-2 uses UTF-8 exclusively when interpreting XML. All XML is assumed to +be UTF-8. -Features --------- +Filenames for loading / saving are passed unchanged to the underlying OS. ### Memory Model @@ -123,13 +111,13 @@ White space in text is preserved. For example: Hello, World -The leading space before the "Hello" and the double space after the comma are +The leading space before the "Hello" and the double space after the comma are preserved. Line-feeds are preserved, as in this example: - Hello again, + Hello again, World -However, white space between elements is **not** preserved. Although not strictly +However, white space between elements is **not** preserved. Although not strictly compliant, tracking and reporting inter-element space is awkward, and not normally valuable. TinyXML-2 sees these as the same XML: @@ -145,7 +133,7 @@ valuable. TinyXML-2 sees these as the same XML: For some applications, it is preferable to collapse whitespace. Collapsing whitespace gives you "HTML-like" behavior, which is sometimes more suitable -for hand typed documents. +for hand typed documents. TinyXML-2 supports this with the 'whitespace' parameter to the XMLDocument constructor. (The default is to preserve whitespace, as described above.) @@ -166,7 +154,7 @@ cannot be parsed correctly. In addition, all nodes (elements, declarations, text, comments etc.) and attributes have a line number recorded as they are parsed. This allows an application that performs additional validation of the parsed XML document (e.g. application-implemented DTD validation) to report -line number information in it's errors. +line number information for error messages. ### Entities @@ -185,10 +173,10 @@ UTF-8 equivalents. For instance, text with the XML of: Far & Away will have the Value() of "Far & Away" when queried from the XMLText object, -and will be written back to the XML stream/file as an ampersand. +and will be written back to the XML stream/file as an ampersand. Additionally, any character can be specified by its Unicode code point: -The syntax ` ` or ` ` are both to the non-breaking space character. +The syntax ` ` or ` ` are both to the non-breaking space character. This is called a 'numeric character reference'. Any numeric character reference that isn't one of the special entities above, will be read, but written as a regular code point. The output is correct, but the entity syntax isn't preserved. @@ -234,7 +222,7 @@ Examples #### Load and parse an XML file. - /* ------ Example 1: Load and parse an XML file. ---- */ + /* ------ Example 1: Load and parse an XML file. ---- */ { XMLDocument doc; doc.LoadFile( "dream.xml" ); @@ -242,22 +230,22 @@ Examples #### Lookup information. - /* ------ Example 2: Lookup information. ---- */ + /* ------ Example 2: Lookup information. ---- */ { XMLDocument doc; doc.LoadFile( "dream.xml" ); // Structure of the XML file: - // - Element "PLAY" the root Element, which is the + // - Element "PLAY" the root Element, which is the // FirstChildElement of the Document // - - Element "TITLE" child of the root PLAY Element // - - - Text child of the TITLE Element - + // Navigate to the title, using the convenience function, // with a dangerous lack of error checking. const char* title = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" )->GetText(); printf( "Name of play (1): %s\n", title ); - + // Text is just another Node to TinyXML-2. The more // general way to get to the XMLText: XMLText* textNode = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" )->FirstChild()->ToText(); @@ -275,10 +263,10 @@ There are 2 files in TinyXML-2: And additionally a test file: * xmltest.cpp -Simply compile and run. There is a visual studio 2015 project included, a simple Makefile, -an Xcode project, a Code::Blocks project, and a cmake CMakeLists.txt included to help you. -The top of tinyxml.h even has a simple g++ command line if you are are *nix and don't want -to use a build system. +Simply compile and run. There is a visual studio 2017 project included, a simple Makefile, +an Xcode project, a Code::Blocks project, and a cmake CMakeLists.txt included to help you. +The top of tinyxml.h even has a simple g++ command line if you are are Unix/Linuk/BSD and +don't want to use a build system. Versioning ---------- @@ -291,7 +279,7 @@ common. Documentation ------------- -The documentation is build with Doxygen, using the 'dox' +The documentation is build with Doxygen, using the 'dox' configuration file. License @@ -299,27 +287,27 @@ License TinyXML-2 is released under the zlib license: -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source +3. This notice may not be removed or altered from any source distribution. Contributors ------------ -Thanks very much to everyone who sends suggestions, bugs, ideas, and +Thanks very much to everyone who sends suggestions, bugs, ideas, and encouragement. It all helps, and makes this project fun. The original TinyXML-1 has many contributors, who all deserve thanks diff --git a/resources/xmltest-5662204197076992.xml b/resources/xmltest-5662204197076992.xml new file mode 100644 index 0000000..71325d3 --- /dev/null +++ b/resources/xmltest-5662204197076992.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/tinyxml2.cpp b/tinyxml2.cpp index 89b7913..fd27f78 100755 --- a/tinyxml2.cpp +++ b/tinyxml2.cpp @@ -1032,15 +1032,25 @@ char* XMLNode::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) XMLDeclaration* decl = node->ToDeclaration(); if ( decl ) { // Declarations are only allowed at document level - bool wellLocated = ( ToDocument() != 0 ); - if ( wellLocated ) { - // Multiple declarations are allowed but all declarations - // must occur before anything else - for ( const XMLNode* existingNode = _document->FirstChild(); existingNode; existingNode = existingNode->NextSibling() ) { - if ( !existingNode->ToDeclaration() ) { - wellLocated = false; - break; - } + // + // Multiple declarations are allowed but all declarations + // must occur before anything else. + // + // Optimized due to a security test case. If the first node is + // a declaration, and the last node is a declaration, then only + // declarations have so far been addded. + bool wellLocated = false; + + if (ToDocument()) { + if (FirstChild()) { + wellLocated = + FirstChild() && + FirstChild()->ToDeclaration() && + LastChild() && + LastChild()->ToDeclaration(); + } + else { + wellLocated = true; } } if ( !wellLocated ) { @@ -1977,10 +1987,8 @@ const char* XMLDocument::_errorNames[XML_ERROR_COUNT] = { "XML_ERROR_FILE_NOT_FOUND", "XML_ERROR_FILE_COULD_NOT_BE_OPENED", "XML_ERROR_FILE_READ_ERROR", - "UNUSED_XML_ERROR_ELEMENT_MISMATCH", "XML_ERROR_PARSING_ELEMENT", "XML_ERROR_PARSING_ATTRIBUTE", - "UNUSED_XML_ERROR_IDENTIFYING_TAG", "XML_ERROR_PARSING_TEXT", "XML_ERROR_PARSING_CDATA", "XML_ERROR_PARSING_COMMENT", @@ -2327,6 +2335,7 @@ void XMLDocument::SetError( XMLError error, int lineNum, const char* format, ... size_t BUFFER_SIZE = 1000; char* buffer = new char[BUFFER_SIZE]; + TIXMLASSERT(sizeof(error) <= sizeof(int)); TIXML_SNPRINTF(buffer, BUFFER_SIZE, "Error=%s ErrorID=%d (0x%x) Line number=%d", ErrorIDToName(error), int(error), int(error), lineNum); if (format) { @@ -2523,14 +2532,16 @@ void XMLPrinter::PrintString( const char* p, bool restricted ) ++q; TIXMLASSERT( p <= q ); } + // Flush the remaining string. This will be the entire + // string if an entity wasn't found. + if ( p < q ) { + const size_t delta = q - p; + const int toPrint = ( INT_MAX < delta ) ? INT_MAX : (int)delta; + Write( p, toPrint ); + } } - // Flush the remaining string. This will be the entire - // string if an entity wasn't found. - TIXMLASSERT( p <= q ); - if ( !_processEntities || ( p < q ) ) { - const size_t delta = q - p; - const int toPrint = ( INT_MAX < delta ) ? INT_MAX : (int)delta; - Write( p, toPrint ); + else { + Write( p ); } } diff --git a/tinyxml2.h b/tinyxml2.h index 66d7b7e..a79e0db 100755 --- a/tinyxml2.h +++ b/tinyxml2.h @@ -98,18 +98,18 @@ distribution. /* Versioning, past 1.0.14: http://semver.org/ */ -static const int TIXML2_MAJOR_VERSION = 6; -static const int TIXML2_MINOR_VERSION = 2; +static const int TIXML2_MAJOR_VERSION = 7; +static const int TIXML2_MINOR_VERSION = 0; static const int TIXML2_PATCH_VERSION = 0; -#define TINYXML2_MAJOR_VERSION 6 -#define TINYXML2_MINOR_VERSION 2 +#define TINYXML2_MAJOR_VERSION 7 +#define TINYXML2_MINOR_VERSION 0 #define TINYXML2_PATCH_VERSION 0 -// A fixed element depth limit is problematic. There needs to be a -// limit to avoid a stack overflow. However, that limit varies per -// system, and the capacity of the stack. On the other hand, it's a trivial -// attack that can result from ill, malicious, or even correctly formed XML, +// A fixed element depth limit is problematic. There needs to be a +// limit to avoid a stack overflow. However, that limit varies per +// system, and the capacity of the stack. On the other hand, it's a trivial +// attack that can result from ill, malicious, or even correctly formed XML, // so there needs to be a limit in place. static const int TINYXML2_MAX_ELEMENT_DEPTH = 100; @@ -190,7 +190,7 @@ private: char* _end; StrPair( const StrPair& other ); // not supported - void operator=( StrPair& other ); // not supported, use TransferTo() + void operator=( const StrPair& other ); // not supported, use TransferTo() }; @@ -288,7 +288,7 @@ public: return _mem; } - T* Mem() { + T* Mem() { TIXMLASSERT( _mem ); return _mem; } @@ -334,7 +334,6 @@ public: virtual void* Alloc() = 0; virtual void Free( void* ) = 0; virtual void SetTracked() = 0; - virtual void Clear() = 0; }; @@ -347,9 +346,9 @@ class MemPoolT : public MemPool public: MemPoolT() : _blockPtrs(), _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {} ~MemPoolT() { - Clear(); + MemPoolT< ITEM_SIZE >::Clear(); } - + void Clear() { // Delete the blocks. while( !_blockPtrs.Empty()) { @@ -395,7 +394,7 @@ public: ++_nUntracked; return result; } - + virtual void Free( void* mem ) { if ( !mem ) { return; @@ -525,10 +524,8 @@ enum XMLError { XML_ERROR_FILE_NOT_FOUND, XML_ERROR_FILE_COULD_NOT_BE_OPENED, XML_ERROR_FILE_READ_ERROR, - UNUSED_XML_ERROR_ELEMENT_MISMATCH, // remove at next major version XML_ERROR_PARSING_ELEMENT, XML_ERROR_PARSING_ATTRIBUTE, - UNUSED_XML_ERROR_IDENTIFYING_TAG, // remove at next major version XML_ERROR_PARSING_TEXT, XML_ERROR_PARSING_CDATA, XML_ERROR_PARSING_COMMENT, @@ -572,7 +569,7 @@ public: static bool IsWhiteSpace( char p ) { return !IsUTF8Continuation(p) && isspace( static_cast(p) ); } - + inline static bool IsNameStartChar( unsigned char ch ) { if ( ch >= 128 ) { // This is a heuristic guess in attempt to not implement Unicode-aware isalpha() @@ -583,7 +580,7 @@ public: } return ch == ':' || ch == '_'; } - + inline static bool IsNameChar( unsigned char ch ) { return IsNameStartChar( ch ) || isdigit( ch ) @@ -600,7 +597,7 @@ public: TIXMLASSERT( nChar >= 0 ); return strncmp( p, q, nChar ) == 0; } - + inline static bool IsUTF8Continuation( char p ) { return ( p & 0x80 ) != 0; } @@ -882,11 +879,11 @@ public: Make a copy of this node and all its children. If the 'target' is null, then the nodes will - be allocated in the current document. If 'target' - is specified, the memory will be allocated is the + be allocated in the current document. If 'target' + is specified, the memory will be allocated is the specified XMLDocument. - NOTE: This is probably not the correct tool to + NOTE: This is probably not the correct tool to copy a document, since XMLDocuments can have multiple top level XMLNodes. You probably want to use XMLDocument::DeepCopy() @@ -925,8 +922,8 @@ public: */ virtual bool Accept( XMLVisitor* visitor ) const = 0; - /** - Set user data into the XMLNode. TinyXML-2 in + /** + Set user data into the XMLNode. TinyXML-2 in no way processes or interprets user data. It is initially 0. */ @@ -940,7 +937,7 @@ public: void* GetUserData() const { return _userData; } protected: - XMLNode( XMLDocument* ); + explicit XMLNode( XMLDocument* ); virtual ~XMLNode(); virtual char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr); @@ -1008,7 +1005,7 @@ public: virtual bool ShallowEqual( const XMLNode* compare ) const; protected: - XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {} + explicit XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {} virtual ~XMLText() {} char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); @@ -1039,7 +1036,7 @@ public: virtual bool ShallowEqual( const XMLNode* compare ) const; protected: - XMLComment( XMLDocument* doc ); + explicit XMLComment( XMLDocument* doc ); virtual ~XMLComment(); char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr); @@ -1078,7 +1075,7 @@ public: virtual bool ShallowEqual( const XMLNode* compare ) const; protected: - XMLDeclaration( XMLDocument* doc ); + explicit XMLDeclaration( XMLDocument* doc ); virtual ~XMLDeclaration(); char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); @@ -1113,7 +1110,7 @@ public: virtual bool ShallowEqual( const XMLNode* compare ) const; protected: - XMLUnknown( XMLDocument* doc ); + explicit XMLUnknown( XMLDocument* doc ); virtual ~XMLUnknown(); char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); @@ -1384,14 +1381,14 @@ public: } - + /** Given an attribute name, QueryAttribute() returns XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion can't be performed, or XML_NO_ATTRIBUTE if the attribute doesn't exist. It is overloaded for the primitive types, and is a generally more convenient replacement of QueryIntAttribute() and related functions. - + If successful, the result of the conversion will be written to 'value'. If not successful, nothing will be written to 'value'. This allows you to provide default @@ -1402,27 +1399,27 @@ public: QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10 @endverbatim */ - int QueryAttribute( const char* name, int* value ) const { + XMLError QueryAttribute( const char* name, int* value ) const { return QueryIntAttribute( name, value ); } - int QueryAttribute( const char* name, unsigned int* value ) const { + XMLError QueryAttribute( const char* name, unsigned int* value ) const { return QueryUnsignedAttribute( name, value ); } - int QueryAttribute(const char* name, int64_t* value) const { + XMLError QueryAttribute(const char* name, int64_t* value) const { return QueryInt64Attribute(name, value); } - int QueryAttribute( const char* name, bool* value ) const { + XMLError QueryAttribute( const char* name, bool* value ) const { return QueryBoolAttribute( name, value ); } - int QueryAttribute( const char* name, double* value ) const { + XMLError QueryAttribute( const char* name, double* value ) const { return QueryDoubleAttribute( name, value ); } - int QueryAttribute( const char* name, float* value ) const { + XMLError QueryAttribute( const char* name, float* value ) const { return QueryFloatAttribute( name, value ); } @@ -1530,7 +1527,7 @@ public: @verbatim Hullaballoo!This is text @endverbatim - + For this XML: @verbatim @@ -1544,15 +1541,15 @@ public: /// Convenience method for setting text inside an element. See SetText() for important limitations. void SetText( int value ); /// Convenience method for setting text inside an element. See SetText() for important limitations. - void SetText( unsigned value ); + void SetText( unsigned value ); /// Convenience method for setting text inside an element. See SetText() for important limitations. void SetText(int64_t value); /// Convenience method for setting text inside an element. See SetText() for important limitations. - void SetText( bool value ); + void SetText( bool value ); /// Convenience method for setting text inside an element. See SetText() for important limitations. - void SetText( double value ); + void SetText( double value ); /// Convenience method for setting text inside an element. See SetText() for important limitations. - void SetText( float value ); + void SetText( float value ); /** Convenience method to query the value of a child text node. This is probably best @@ -1626,11 +1623,7 @@ private: XMLElement( const XMLElement& ); // not supported void operator=( const XMLElement& ); // not supported - XMLAttribute* FindAttribute( const char* name ) { - return const_cast(const_cast(this)->FindAttribute( name )); - } XMLAttribute* FindOrCreateAttribute( const char* name ); - //void LinkAttribute( XMLAttribute* attrib ); char* ParseAttributes( char* p, int* curLineNumPtr ); static void DeleteAttribute( XMLAttribute* attribute ); XMLAttribute* CreateAttribute(); @@ -1660,7 +1653,7 @@ class TINYXML2_LIB XMLDocument : public XMLNode friend class XMLElement; // Gives access to SetError and Push/PopDepth, but over-access for everything else. // Wishing C++ had "internal" scope. - friend class XMLNode; + friend class XMLNode; friend class XMLText; friend class XMLComment; friend class XMLDeclaration; @@ -1700,8 +1693,8 @@ public: /** Load an XML file from disk. You are responsible - for providing and closing the FILE*. - + for providing and closing the FILE*. + NOTE: The file should be opened as binary ("rb") not text in order for TinyXML-2 to correctly do newline normalization. @@ -1831,7 +1824,7 @@ public: const char* ErrorName() const; static const char* ErrorIDToName(XMLError errorID); - /** Returns a "long form" error description. A hopefully helpful + /** Returns a "long form" error description. A hopefully helpful diagnostic with location, line number, and/or additional info. */ const char* ErrorStr() const; @@ -1839,12 +1832,12 @@ public: /// A (trivial) utility function that prints the ErrorStr() to stdout. void PrintError() const; - /// Return the line where the error occured, or zero if unknown. + /// Return the line where the error occurred, or zero if unknown. int ErrorLineNum() const { return _errorLineNum; } - + /// Clear the document, resetting it to the initial state. void Clear(); @@ -1907,8 +1900,8 @@ private: // the stack. Track stack depth, and error out if needed. class DepthTracker { public: - DepthTracker(XMLDocument * document) { - this->_document = document; + explicit DepthTracker(XMLDocument * document) { + this->_document = document; document->PushDepth(); } ~DepthTracker() { @@ -1996,10 +1989,10 @@ class TINYXML2_LIB XMLHandle { public: /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. - XMLHandle( XMLNode* node ) : _node( node ) { + explicit XMLHandle( XMLNode* node ) : _node( node ) { } /// Create a handle from a node. - XMLHandle( XMLNode& node ) : _node( &node ) { + explicit XMLHandle( XMLNode& node ) : _node( &node ) { } /// Copy constructor XMLHandle( const XMLHandle& ref ) : _node( ref._node ) { @@ -2076,9 +2069,9 @@ private: class TINYXML2_LIB XMLConstHandle { public: - XMLConstHandle( const XMLNode* node ) : _node( node ) { + explicit XMLConstHandle( const XMLNode* node ) : _node( node ) { } - XMLConstHandle( const XMLNode& node ) : _node( &node ) { + explicit XMLConstHandle( const XMLNode& node ) : _node( &node ) { } XMLConstHandle( const XMLConstHandle& ref ) : _node( ref._node ) { } diff --git a/xmltest.cpp b/xmltest.cpp index 7160fe9..a0aaee7 100644 --- a/xmltest.cpp +++ b/xmltest.cpp @@ -34,7 +34,7 @@ bool XMLTest (const char* testString, const char* expected, const char* found, b pass = true; else if ( !expected || !found ) pass = false; - else + else pass = !strcmp( expected, found ); if ( pass ) printf ("[pass]"); @@ -82,8 +82,15 @@ template< class T > bool XMLTest( const char* testString, T expected, T found, b if ( !echo ) printf (" %s\n", testString); - else - printf (" %s [%d][%d]\n", testString, static_cast(expected), static_cast(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; @@ -121,7 +128,7 @@ int example_1() * @skip example_1() * @until } */ - + int example_2() { @@ -172,8 +179,8 @@ int example_3() 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 "; @@ -192,7 +199,7 @@ int example_3() - 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 @@ int example_3() 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 Dream @endverbatim @@ -225,7 +232,7 @@ int example_3() 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. */ @@ -269,7 +276,7 @@ bool example_4() @skip example_4() @until ""; - 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() @@ -569,7 +576,7 @@ int main( int argc, const char ** argv ) XMLTest( "Bad XML", XML_ERROR_PARSING_ATTRIBUTE, doc.ErrorID() ); const char* errorStr = doc.ErrorStr(); XMLTest("Formatted error string", - "Error=XML_ERROR_PARSING_ATTRIBUTE ErrorID=8 (0x8) Line number=3: XMLElement name=wrong", + "Error=XML_ERROR_PARSING_ATTRIBUTE ErrorID=7 (0x7) Line number=3: XMLElement name=wrong", errorStr); } @@ -651,7 +658,7 @@ int main( int argc, const char ** argv ) 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") ); } { @@ -766,7 +773,7 @@ int main( int argc, const char ** argv ) 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() ); @@ -774,7 +781,7 @@ int main( int argc, const char ** argv ) 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() ); @@ -1176,7 +1183,7 @@ int main( int argc, const char ** argv ) // 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=15 (0xf) Line number=0", + "Error=XML_ERROR_EMPTY_DOCUMENT ErrorID=13 (0xd) Line number=0", errorStr); } @@ -1567,14 +1574,14 @@ int main( int argc, const char ** argv ) doc.Parse( xml ); XMLTest( "Non-alpha element lead letter parses.", false, doc.Error() ); } - + { const char* xml = ""; XMLDocument doc; doc.Parse( xml ); XMLTest("Non-alpha attribute lead character parses.", false, doc.Error()); } - + { const char* xml = "<3lement>"; XMLDocument doc; @@ -1610,7 +1617,7 @@ int main( int argc, const char ** argv ) doc.Clear(); XMLTest( "No error after Clear()", false, doc.Error() ); } - + // ----------- Whitespace ------------ { const char* xml = "" @@ -1782,6 +1789,7 @@ int main( int argc, const char ** argv ) XMLTest( "Insertion with removal parse round 4", false, doc.Error() ); subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree"); two = doc.RootElement()->FirstChildElement("two"); + XMLTest(" is the last child at root level", true, two == doc.RootElement()->LastChildElement()); doc.RootElement()->InsertEndChild(subtree); XMLPrinter printer4(0, true); acceptResult = doc.Accept(&printer4); @@ -1809,7 +1817,7 @@ int main( int argc, const char ** argv ) } #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 = ""; @@ -1836,14 +1844,14 @@ int main( int argc, const char ** argv ) /* 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.", "\n", - printer.CStr(), + printer.CStr(), true ); */ } #endif - + { // Issue #184 // If it doesn't assert, it passes. Caused by objects @@ -1862,7 +1870,7 @@ int main( int argc, const char ** argv ) doc.Clear(); } } - + { // If this doesn't assert in TINYXML2_DEBUG, all is well. tinyxml2::XMLDocument doc; @@ -1904,7 +1912,7 @@ int main( int argc, const char ** argv ) 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" ); @@ -1967,7 +1975,7 @@ int main( int argc, const char ** argv ) { // 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 = "" "" ""; @@ -1996,7 +2004,18 @@ int main( int argc, const char ** argv ) } { - // Evil memory leaks. + const char* html("

test


"); + 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? // @@ -2039,6 +2058,18 @@ int main( int argc, const char ** argv ) 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 = @@ -2093,7 +2124,7 @@ int main( int argc, const char ** argv ) 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")) { -- 2.7.4