Merge pull request #296 from Dmitry-Me/assertForImpossibleCase

Assert for impossible case
diff --git a/tinyxml2.cpp b/tinyxml2.cpp
index 5b32f40..6d8573b 100755
--- a/tinyxml2.cpp
+++ b/tinyxml2.cpp
@@ -228,11 +228,19 @@
                         const int buflen = 10;

                         char buf[buflen] = { 0 };

                         int len = 0;

-                        p = const_cast<char*>( XMLUtil::GetCharacterRef( p, buf, &len ) );

-                        TIXMLASSERT( 0 <= len && len <= buflen );

-                        TIXMLASSERT( q + len <= p );

-                        memcpy( q, buf, len );

-                        q += len;

+                        char* adjusted = const_cast<char*>( XMLUtil::GetCharacterRef( p, buf, &len ) );

+                        if ( adjusted == 0 ) {

+                            *q = *p;

+                            ++p;

+                            ++q;

+                        }

+                        else {

+                            TIXMLASSERT( 0 <= len && len <= buflen );

+                            TIXMLASSERT( q + len <= adjusted );

+                            p = adjusted;

+                            memcpy( q, buf, len );

+                            q += len;

+                        }

                     }

                     else {

                         int i=0;

@@ -375,18 +383,25 @@
             --q;

 

             while ( *q != 'x' ) {

+                unsigned int digit = 0;

+

                 if ( *q >= '0' && *q <= '9' ) {

-                    ucs += mult * (*q - '0');

+                    digit = *q - '0';

                 }

                 else if ( *q >= 'a' && *q <= 'f' ) {

-                    ucs += mult * (*q - 'a' + 10);

+                    digit = *q - 'a' + 10;

                 }

                 else if ( *q >= 'A' && *q <= 'F' ) {

-                    ucs += mult * (*q - 'A' + 10 );

+                    digit = *q - 'A' + 10;

                 }

                 else {

                     return 0;

                 }

+                TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit );

+				TIXMLASSERT( digit >= 0 && digit < 16);

+                const unsigned int digitScaled = mult * digit;

+                TIXMLASSERT( ucs <= ULONG_MAX - digitScaled );

+                ucs += digitScaled;

                 TIXMLASSERT( mult <= UINT_MAX / 16 );

                 mult *= 16;

                 --q;

@@ -411,7 +426,11 @@
 

             while ( *q != '#' ) {

                 if ( *q >= '0' && *q <= '9' ) {

-                    ucs += mult * (*q - '0');

+                    const unsigned int digit = *q - '0';

+                    TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit );

+                    const unsigned int digitScaled = mult * digit;

+                    TIXMLASSERT( ucs <= ULONG_MAX - digitScaled );

+                    ucs += digitScaled;

                 }

                 else {

                     return 0;

diff --git a/xmltest.cpp b/xmltest.cpp
index c231024..243628c 100644
--- a/xmltest.cpp
+++ b/xmltest.cpp
@@ -1416,6 +1416,16 @@
 		XMLPrinter printer;

 	}

 

+	{

+		// Issue 291. Should not crash

+		const char* xml = "&#0</a>";

+		XMLDocument doc;

+		doc.Parse( xml );

+

+		XMLPrinter printer;

+		doc.Print( &printer );

+	}

+

 	// ----------- Performance tracking --------------

 	{

 #if defined( _MSC_VER )