@@ -235,13 +235,13 @@ char* StrPair::ParseName( char* p )
235235 if ( !p || !(*p) ) {
236236 return 0 ;
237237 }
238- if ( !XMLUtil::IsNameStartChar ( ( unsigned char ) *p ) ) {
238+ if ( !XMLUtil::IsNameStartChar ( static_cast < unsigned char >(*p) ) ) {
239239 return 0 ;
240240 }
241241
242242 char * const start = p;
243243 ++p;
244- while ( *p && XMLUtil::IsNameChar ( ( unsigned char ) *p ) ) {
244+ while ( *p && XMLUtil::IsNameChar ( static_cast < unsigned char >(*p) ) ) {
245245 ++p;
246246 }
247247
@@ -468,102 +468,94 @@ void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length
468468}
469469
470470
471- const char * XMLUtil::GetCharacterRef ( const char * p, char * value, int * length )
471+ const char * XMLUtil::GetCharacterRef (const char * p, char * value, int * length)
472472{
473- // Presume an entity, and pull it out.
473+ // Assume an entity, and pull it out.
474474 *length = 0 ;
475475
476- if ( *(p+1 ) == ' #' && *(p+2 ) ) {
477- unsigned long ucs = 0 ;
478- TIXMLASSERT ( sizeof ( ucs ) >= 4 );
476+ static const uint32_t MAX_CODE_POINT = 0x10FFFF ;
477+
478+ if (*(p + 1 ) == ' #' && *(p + 2 )) {
479+ uint32_t ucs = 0 ;
479480 ptrdiff_t delta = 0 ;
480- unsigned mult = 1 ;
481+ uint32_t mult = 1 ;
481482 static const char SEMICOLON = ' ;' ;
482483
483- if ( *(p+2 ) == ' x' ) {
484+ bool hex = false ;
485+ uint32_t radix = 10 ;
486+ const char * q = 0 ;
487+ char terminator = ' #' ;
488+
489+ if (*(p + 2 ) == ' x' ) {
484490 // Hexadecimal.
485- const char * q = p+3 ;
486- if ( !(*q) ) {
487- return 0 ;
488- }
491+ hex = true ;
492+ radix = 16 ;
493+ terminator = ' x' ;
489494
490- q = strchr ( q, SEMICOLON );
495+ q = p + 3 ;
496+ }
497+ else {
498+ // Decimal.
499+ q = p + 2 ;
500+ }
501+ if (!(*q)) {
502+ return 0 ;
503+ }
491504
492- if ( !q ) {
493- return 0 ;
494- }
495- TIXMLASSERT ( *q == SEMICOLON );
505+ q = strchr (q, SEMICOLON);
506+ if (!q) {
507+ return 0 ;
508+ }
509+ TIXMLASSERT (*q == SEMICOLON);
496510
497- delta = q- p;
498- --q;
511+ delta = q - p;
512+ --q;
499513
500- while ( *q != ' x ' ) {
501- unsigned int digit = 0 ;
514+ while (*q != terminator ) {
515+ uint32_t digit = 0 ;
502516
503- if ( *q >= ' 0' && *q <= ' 9' ) {
504- digit = *q - ' 0' ;
505- }
506- else if ( *q >= ' a' && *q <= ' f' ) {
507- digit = *q - ' a' + 10 ;
508- }
509- else if ( *q >= ' A' && *q <= ' F' ) {
510- digit = *q - ' A' + 10 ;
511- }
512- else {
513- return 0 ;
514- }
515- TIXMLASSERT ( digit < 16 );
516- TIXMLASSERT ( digit == 0 || mult <= UINT_MAX / digit );
517- const unsigned int digitScaled = mult * digit;
518- TIXMLASSERT ( ucs <= ULONG_MAX - digitScaled );
519- ucs += digitScaled;
520- TIXMLASSERT ( mult <= UINT_MAX / 16 );
521- mult *= 16 ;
522- --q;
517+ if (*q >= ' 0' && *q <= ' 9' ) {
518+ digit = *q - ' 0' ;
523519 }
524- }
525- else {
526- // Decimal.
527- const char * q = p+2 ;
528- if ( !(*q) ) {
529- return 0 ;
520+ else if (hex && (*q >= ' a' && *q <= ' f' )) {
521+ digit = *q - ' a' + 10 ;
530522 }
531-
532- q = strchr ( q, SEMICOLON ) ;
533-
534- if ( !q ) {
523+ else if (hex && (*q >= ' A ' && *q <= ' F ' )) {
524+ digit = *q - ' A ' + 10 ;
525+ }
526+ else {
535527 return 0 ;
536528 }
537- TIXMLASSERT ( *q == SEMICOLON );
538-
539- delta = q-p;
540- --q;
541-
542- while ( *q != ' #' ) {
543- if ( *q >= ' 0' && *q <= ' 9' ) {
544- const unsigned int digit = *q - ' 0' ;
545- TIXMLASSERT ( digit < 10 );
546- TIXMLASSERT ( digit == 0 || mult <= UINT_MAX / digit );
547- const unsigned int digitScaled = mult * digit;
548- TIXMLASSERT ( ucs <= ULONG_MAX - digitScaled );
549- ucs += digitScaled;
550- }
551- else {
552- return 0 ;
553- }
554- TIXMLASSERT ( mult <= UINT_MAX / 10 );
555- mult *= 10 ;
556- --q;
529+ TIXMLASSERT (digit < radix);
530+
531+ const unsigned int digitScaled = mult * digit;
532+ ucs += digitScaled;
533+ mult *= radix;
534+
535+ // Security check: could a value exist that is out of range?
536+ // Easily; limit to the MAX_CODE_POINT, which also allows for a
537+ // bunch of leading zeroes.
538+ if (mult > MAX_CODE_POINT) {
539+ mult = MAX_CODE_POINT;
557540 }
541+ --q;
542+ }
543+ // Out of range:
544+ if (ucs > MAX_CODE_POINT) {
545+ return 0 ;
558546 }
559547 // convert the UCS to UTF-8
560- ConvertUTF32ToUTF8 ( ucs, value, length );
548+ ConvertUTF32ToUTF8 (ucs, value, length);
549+ if (length == 0 ) {
550+ // If length is 0, there was an error. (Security? Bad input?)
551+ // Fail safely.
552+ return 0 ;
553+ }
561554 return p + delta + 1 ;
562555 }
563- return p+ 1 ;
556+ return p + 1 ;
564557}
565558
566-
567559void XMLUtil::ToStr ( int v, char * buffer, int bufferSize )
568560{
569561 TIXML_SNPRINTF ( buffer, bufferSize, " %d" , v );
@@ -701,7 +693,7 @@ bool XMLUtil::ToInt64(const char* str, int64_t* value)
701693bool XMLUtil::ToUnsigned64 (const char * str, uint64_t * value) {
702694 unsigned long long v = 0 ; // horrible syntax trick to make the compiler happy about %llu
703695 if (TIXML_SSCANF (str, IsPrefixHex (str) ? " %llx" : " %llu" , &v) == 1 ) {
704- *value = ( uint64_t )v ;
696+ *value = static_cast < uint64_t >(v) ;
705697 return true ;
706698 }
707699 return false ;
@@ -1978,7 +1970,7 @@ char* XMLElement::ParseAttributes( char* p, int* curLineNumPtr )
19781970 }
19791971
19801972 // attribute.
1981- if (XMLUtil::IsNameStartChar ( ( unsigned char ) *p ) ) {
1973+ if (XMLUtil::IsNameStartChar ( static_cast < unsigned char >(*p) ) ) {
19821974 XMLAttribute* attrib = CreateAttribute ();
19831975 TIXMLASSERT ( attrib );
19841976 attrib->_parseLineNum = _document->_parseCurLineNum ;
0 commit comments