Răsfoiți Sursa

Merge branch 'properStrPairAssignment' of https://github.com/Dmitry-Me/tinyxml2 into Dmitry-Me-properStrPairAssignment

Lee Thomason 11 ani în urmă
părinte
comite
327d5c142e
4 a modificat fișierele cu 115 adăugiri și 41 ștergeri
  1. 63 30
      tinyxml2.cpp
  2. 27 10
      tinyxml2.h
  3. 7 0
      tinyxml2/tinyxml2.xcodeproj/project.pbxproj
  4. 18 1
      xmltest.cpp

+ 63 - 30
tinyxml2.cpp

@@ -70,6 +70,29 @@ StrPair::~StrPair()
 }
 }
 
 
 
 
+void StrPair::TransferTo( StrPair& other )
+{
+    if ( this == &other ) {
+        return;
+    }
+    // This in effect implements the assignment operator by "moving"
+    // ownership (as in auto_ptr).
+
+    TIXMLASSERT( other._flags == 0 );
+    TIXMLASSERT( other._start == 0 );
+    TIXMLASSERT( other._end == 0 );
+
+    other.Reset();
+
+    other._flags = _flags;
+    other._start = _start;
+    other._end = _end;
+
+    _flags = 0;
+    _start = 0;
+    _end = 0;
+}
+
 void StrPair::Reset()
 void StrPair::Reset()
 {
 {
     if ( _flags & NEEDS_DELETE ) {
     if ( _flags & NEEDS_DELETE ) {
@@ -212,12 +235,13 @@ const char* StrPair::GetStr()
                     else {
                     else {
                         int i=0;
                         int i=0;
                         for(; i<NUM_ENTITIES; ++i ) {
                         for(; i<NUM_ENTITIES; ++i ) {
-                            if (    strncmp( p+1, entities[i].pattern, entities[i].length ) == 0
-                                    && *(p+entities[i].length+1) == ';' ) {
-                                // Found an entity convert;
-                                *q = entities[i].value;
+                            const Entity& entity = entities[i];
+                            if ( strncmp( p + 1, entity.pattern, entity.length ) == 0
+                                    && *( p + entity.length + 1 ) == ';' ) {
+                                // Found an entity - convert.
+                                *q = entity.value;
                                 ++q;
                                 ++q;
-                                p += entities[i].length + 2;
+                                p += entity.length + 2;
                                 break;
                                 break;
                             }
                             }
                         }
                         }
@@ -823,7 +847,7 @@ char* XMLNode::ParseDeep( char* p, StrPair* parentEnd )
         // We read the end tag. Return it to the parent.
         // We read the end tag. Return it to the parent.
         if ( ele && ele->ClosingType() == XMLElement::CLOSING ) {
         if ( ele && ele->ClosingType() == XMLElement::CLOSING ) {
             if ( parentEnd ) {
             if ( parentEnd ) {
-                *parentEnd = ele->_value;
+                ele->_value.TransferTo( *parentEnd );
             }
             }
 			node->_memPool->SetTracked();	// created and then immediately deleted.
 			node->_memPool->SetTracked();	// created and then immediately deleted.
             DeleteNode( node );
             DeleteNode( node );
@@ -1257,7 +1281,7 @@ const char* XMLElement::Attribute( const char* name, const char* value ) const
 const char* XMLElement::GetText() const
 const char* XMLElement::GetText() const
 {
 {
     if ( FirstChild() && FirstChild()->ToText() ) {
     if ( FirstChild() && FirstChild()->ToText() ) {
-        return FirstChild()->ToText()->Value();
+        return FirstChild()->Value();
     }
     }
     return 0;
     return 0;
 }
 }
@@ -1317,7 +1341,7 @@ void XMLElement::SetText( double v )
 XMLError XMLElement::QueryIntText( int* ival ) const
 XMLError XMLElement::QueryIntText( int* ival ) const
 {
 {
     if ( FirstChild() && FirstChild()->ToText() ) {
     if ( FirstChild() && FirstChild()->ToText() ) {
-        const char* t = FirstChild()->ToText()->Value();
+        const char* t = FirstChild()->Value();
         if ( XMLUtil::ToInt( t, ival ) ) {
         if ( XMLUtil::ToInt( t, ival ) ) {
             return XML_SUCCESS;
             return XML_SUCCESS;
         }
         }
@@ -1330,7 +1354,7 @@ XMLError XMLElement::QueryIntText( int* ival ) const
 XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const
 XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const
 {
 {
     if ( FirstChild() && FirstChild()->ToText() ) {
     if ( FirstChild() && FirstChild()->ToText() ) {
-        const char* t = FirstChild()->ToText()->Value();
+        const char* t = FirstChild()->Value();
         if ( XMLUtil::ToUnsigned( t, uval ) ) {
         if ( XMLUtil::ToUnsigned( t, uval ) ) {
             return XML_SUCCESS;
             return XML_SUCCESS;
         }
         }
@@ -1343,7 +1367,7 @@ XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const
 XMLError XMLElement::QueryBoolText( bool* bval ) const
 XMLError XMLElement::QueryBoolText( bool* bval ) const
 {
 {
     if ( FirstChild() && FirstChild()->ToText() ) {
     if ( FirstChild() && FirstChild()->ToText() ) {
-        const char* t = FirstChild()->ToText()->Value();
+        const char* t = FirstChild()->Value();
         if ( XMLUtil::ToBool( t, bval ) ) {
         if ( XMLUtil::ToBool( t, bval ) ) {
             return XML_SUCCESS;
             return XML_SUCCESS;
         }
         }
@@ -1356,7 +1380,7 @@ XMLError XMLElement::QueryBoolText( bool* bval ) const
 XMLError XMLElement::QueryDoubleText( double* dval ) const
 XMLError XMLElement::QueryDoubleText( double* dval ) const
 {
 {
     if ( FirstChild() && FirstChild()->ToText() ) {
     if ( FirstChild() && FirstChild()->ToText() ) {
-        const char* t = FirstChild()->ToText()->Value();
+        const char* t = FirstChild()->Value();
         if ( XMLUtil::ToDouble( t, dval ) ) {
         if ( XMLUtil::ToDouble( t, dval ) ) {
             return XML_SUCCESS;
             return XML_SUCCESS;
         }
         }
@@ -1369,7 +1393,7 @@ XMLError XMLElement::QueryDoubleText( double* dval ) const
 XMLError XMLElement::QueryFloatText( float* fval ) const
 XMLError XMLElement::QueryFloatText( float* fval ) const
 {
 {
     if ( FirstChild() && FirstChild()->ToText() ) {
     if ( FirstChild() && FirstChild()->ToText() ) {
-        const char* t = FirstChild()->ToText()->Value();
+        const char* t = FirstChild()->Value();
         if ( XMLUtil::ToFloat( t, fval ) ) {
         if ( XMLUtil::ToFloat( t, fval ) ) {
             return XML_SUCCESS;
             return XML_SUCCESS;
         }
         }
@@ -1622,24 +1646,7 @@ XMLDocument::XMLDocument( bool processEntities, Whitespace whitespace ) :
 
 
 XMLDocument::~XMLDocument()
 XMLDocument::~XMLDocument()
 {
 {
-    DeleteChildren();
-    delete [] _charBuffer;
-
-#if 0
-    _textPool.Trace( "text" );
-    _elementPool.Trace( "element" );
-    _commentPool.Trace( "comment" );
-    _attributePool.Trace( "attribute" );
-#endif
-
-#ifdef DEBUG
-	if ( Error() == false ) {
-		TIXMLASSERT( _elementPool.CurrentAllocs()   == _elementPool.Untracked() );
-		TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() );
-		TIXMLASSERT( _textPool.CurrentAllocs()      == _textPool.Untracked() );
-		TIXMLASSERT( _commentPool.CurrentAllocs()   == _commentPool.Untracked() );
-	}
-#endif
+    Clear();
 }
 }
 
 
 
 
@@ -1653,6 +1660,22 @@ void XMLDocument::Clear()
 
 
     delete [] _charBuffer;
     delete [] _charBuffer;
     _charBuffer = 0;
     _charBuffer = 0;
+
+#if 0
+    _textPool.Trace( "text" );
+    _elementPool.Trace( "element" );
+    _commentPool.Trace( "comment" );
+    _attributePool.Trace( "attribute" );
+#endif
+    
+#ifdef DEBUG
+    if ( Error() == false ) {
+        TIXMLASSERT( _elementPool.CurrentAllocs()   == _elementPool.Untracked() );
+        TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() );
+        TIXMLASSERT( _textPool.CurrentAllocs()      == _textPool.Untracked() );
+        TIXMLASSERT( _commentPool.CurrentAllocs()   == _commentPool.Untracked() );
+    }
+#endif
 }
 }
 
 
 
 
@@ -1820,6 +1843,16 @@ XMLError XMLDocument::Parse( const char* p, size_t len )
 
 
     ptrdiff_t delta = p - start;	// skip initial whitespace, BOM, etc.
     ptrdiff_t delta = p - start;	// skip initial whitespace, BOM, etc.
     ParseDeep( _charBuffer+delta, 0 );
     ParseDeep( _charBuffer+delta, 0 );
+    if (_errorID) {
+        // clean up now essentially dangling memory.
+        // and the parse fail can put objects in the
+        // pools that are dead and inaccessible.
+        DeleteChildren();
+        _elementPool.Clear();
+        _attributePool.Clear();
+        _textPool.Clear();
+        _commentPool.Clear();
+    }
     return _errorID;
     return _errorID;
 }
 }
 
 

+ 27 - 10
tinyxml2.h

@@ -14,7 +14,6 @@ not claim that you wrote the original software. If you use this
 software in a product, an acknowledgment in the product documentation
 software in a product, an acknowledgment in the product documentation
 would be appreciated but is not required.
 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.
 must not be misrepresented as being the original software.
 
 
@@ -122,9 +121,9 @@ inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
 /* Versioning, past 1.0.14:
 /* Versioning, past 1.0.14:
 	http://semver.org/
 	http://semver.org/
 */
 */
-static const int TIXML2_MAJOR_VERSION = 2;
-static const int TIXML2_MINOR_VERSION = 2;
-static const int TIXML2_PATCH_VERSION = 0;
+static const int TIXML2_MAJOR_VERSION = 2;
+static const int TIXML2_MINOR_VERSION = 2;
+static const int TIXML2_PATCH_VERSION = 0;
 
 
 namespace tinyxml2
 namespace tinyxml2
 {
 {
@@ -185,6 +184,8 @@ public:
     char* ParseText( char* in, const char* endTag, int strFlags );
     char* ParseText( char* in, const char* endTag, int strFlags );
     char* ParseName( char* in );
     char* ParseName( char* in );
 
 
+    void TransferTo( StrPair& other );
+
 private:
 private:
 	void operator=(const StrPair& rhs);
 	void operator=(const StrPair& rhs);
 
 
@@ -200,6 +201,9 @@ private:
     int     _flags;
     int     _flags;
     char*   _start;
     char*   _start;
     char*   _end;
     char*   _end;
+
+    StrPair( const StrPair& other );	// not supported
+    void operator=( StrPair& other );	// not supported, use TransferTo()
 };
 };
 
 
 
 
@@ -263,7 +267,7 @@ public:
         return _mem[i];
         return _mem[i];
     }
     }
 
 
-    const T& PeekTop() const                            {
+    const T& PeekTop() const            {
         TIXMLASSERT( _size > 0 );
         TIXMLASSERT( _size > 0 );
         return _mem[ _size - 1];
         return _mem[ _size - 1];
     }
     }
@@ -319,6 +323,7 @@ public:
     virtual void* Alloc() = 0;
     virtual void* Alloc() = 0;
     virtual void Free( void* ) = 0;
     virtual void Free( void* ) = 0;
     virtual void SetTracked() = 0;
     virtual void SetTracked() = 0;
+    virtual void Clear() = 0;
 };
 };
 
 
 
 
@@ -331,10 +336,20 @@ class MemPoolT : public MemPool
 public:
 public:
     MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0)	{}
     MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0)	{}
     ~MemPoolT() {
     ~MemPoolT() {
+        Clear();
+    }
+    
+    void Clear() {
         // Delete the blocks.
         // Delete the blocks.
-        for( int i=0; i<_blockPtrs.Size(); ++i ) {
-            delete _blockPtrs[i];
+        while( !_blockPtrs.Empty()) {
+            Block* b  = _blockPtrs.Pop();
+            delete b;
         }
         }
+        _root = 0;
+        _currentAllocs = 0;
+        _nAllocs = 0;
+        _maxAllocs = 0;
+        _nUntracked = 0;
     }
     }
 
 
     virtual int ItemSize() const	{
     virtual int ItemSize() const	{
@@ -367,6 +382,7 @@ public:
         _nUntracked++;
         _nUntracked++;
         return result;
         return result;
     }
     }
+    
     virtual void Free( void* mem ) {
     virtual void Free( void* mem ) {
         if ( !mem ) {
         if ( !mem ) {
             return;
             return;
@@ -516,10 +532,8 @@ enum XMLError {
 class XMLUtil
 class XMLUtil
 {
 {
 public:
 public:
-    // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
-    // correct, but simple, and usually works.
     static const char* SkipWhiteSpace( const char* p )	{
     static const char* SkipWhiteSpace( const char* p )	{
-        while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
+        while( IsWhiteSpace(*p) ) {
             ++p;
             ++p;
         }
         }
         return p;
         return p;
@@ -527,6 +541,9 @@ public:
     static char* SkipWhiteSpace( char* p )				{
     static char* SkipWhiteSpace( char* p )				{
         return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p) ) );
         return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p) ) );
     }
     }
+
+    // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
+    // correct, but simple, and usually works.
     static bool IsWhiteSpace( char p )					{
     static bool IsWhiteSpace( char p )					{
         return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
         return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
     }
     }

+ 7 - 0
tinyxml2/tinyxml2.xcodeproj/project.pbxproj

@@ -96,6 +96,9 @@
 /* Begin PBXProject section */
 /* Begin PBXProject section */
 		037AE058151CCC5200E0F29F /* Project object */ = {
 		037AE058151CCC5200E0F29F /* Project object */ = {
 			isa = PBXProject;
 			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 0610;
+			};
 			buildConfigurationList = 037AE05B151CCC5200E0F29F /* Build configuration list for PBXProject "tinyxml2" */;
 			buildConfigurationList = 037AE05B151CCC5200E0F29F /* Build configuration list for PBXProject "tinyxml2" */;
 			compatibilityVersion = "Xcode 3.2";
 			compatibilityVersion = "Xcode 3.2";
 			developmentRegion = English;
 			developmentRegion = English;
@@ -134,6 +137,8 @@
 			buildSettings = {
 			buildSettings = {
 				CONFIGURATION_BUILD_DIR = "$(SYMROOT)/Debug";
 				CONFIGURATION_BUILD_DIR = "$(SYMROOT)/Debug";
 				COPY_PHASE_STRIP = NO;
 				COPY_PHASE_STRIP = NO;
+				"GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = DEBUG;
+				ONLY_ACTIVE_ARCH = YES;
 				SYMROOT = build;
 				SYMROOT = build;
 			};
 			};
 			name = Debug;
 			name = Debug;
@@ -156,6 +161,7 @@
 				GCC_MODEL_TUNING = G5;
 				GCC_MODEL_TUNING = G5;
 				GCC_OPTIMIZATION_LEVEL = 0;
 				GCC_OPTIMIZATION_LEVEL = 0;
 				INSTALL_PATH = /usr/local/bin;
 				INSTALL_PATH = /usr/local/bin;
+				MACOSX_DEPLOYMENT_TARGET = "";
 				PREBINDING = NO;
 				PREBINDING = NO;
 				PRODUCT_NAME = xmltest;
 				PRODUCT_NAME = xmltest;
 			};
 			};
@@ -171,6 +177,7 @@
 				GCC_ENABLE_FIX_AND_CONTINUE = NO;
 				GCC_ENABLE_FIX_AND_CONTINUE = NO;
 				GCC_MODEL_TUNING = G5;
 				GCC_MODEL_TUNING = G5;
 				INSTALL_PATH = /usr/local/bin;
 				INSTALL_PATH = /usr/local/bin;
+				MACOSX_DEPLOYMENT_TARGET = "";
 				PREBINDING = NO;
 				PREBINDING = NO;
 				PRODUCT_NAME = tinyxml2;
 				PRODUCT_NAME = tinyxml2;
 				ZERO_LINK = NO;
 				ZERO_LINK = NO;

+ 18 - 1
xmltest.cpp

@@ -279,6 +279,8 @@ int main( int argc, const char ** argv )
 {
 {
 	#if defined( _MSC_VER ) && defined( DEBUG )
 	#if defined( _MSC_VER ) && defined( DEBUG )
 		_CrtMemCheckpoint( &startMemState );
 		_CrtMemCheckpoint( &startMemState );
+		// Enable MS Visual C++ debug heap memory leaks dump on exit
+		_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
 	#endif
 	#endif
 
 
 	#if defined(_MSC_VER) || defined(MINGW32) || defined(__MINGW32__)
 	#if defined(_MSC_VER) || defined(MINGW32) || defined(__MINGW32__)
@@ -1371,7 +1373,22 @@ int main( int argc, const char ** argv )
 		*/
 		*/
 	}
 	}
 #endif
 #endif
-
+    
+    {
+        // Issue #184
+        // If it doesn't assert, it passes. Caused by objects
+        // getting created during parsing which are then
+        // inaccessible in the memory pools.
+        {
+            XMLDocument doc;
+            doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
+        }
+        {
+            XMLDocument doc;
+            doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
+            doc.Clear();
+        }
+    }
 
 
 
 
 	// ----------- Performance tracking --------------
 	// ----------- Performance tracking --------------