|
| 1 | +From 5be6d48c41d636826984605448dc8d4516f2b8ac Mon Sep 17 00:00:00 2001 |
| 2 | +From: archana25-ms <v-shettigara@microsoft.com> |
| 3 | +Date: Wed, 16 Apr 2025 07:10:31 +0000 |
| 4 | +Subject: [PATCH] Address CVE-2024-50615 |
| 5 | +Upstream Patch Reference : |
| 6 | +1. https://github.com/leethomason/tinyxml2/commit/494735de30c946bc7d684c65ff8ece05beeb232d |
| 7 | +2. https://github.com/leethomason/tinyxml2/commit/4cbb25155cde261ccf868efb8ae29ad0eebea4d1 |
| 8 | + |
| 9 | +--- |
| 10 | + tinyxml2.cpp | 129 +++++++++++++++++++++++---------------------------- |
| 11 | + xmltest.cpp | 31 ++++++++++++- |
| 12 | + 2 files changed, 89 insertions(+), 71 deletions(-) |
| 13 | + |
| 14 | +diff --git a/tinyxml2.cpp b/tinyxml2.cpp |
| 15 | +index 9173467..b12112e 100755 |
| 16 | +--- a/tinyxml2.cpp |
| 17 | ++++ b/tinyxml2.cpp |
| 18 | +@@ -467,102 +467,91 @@ void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length |
| 19 | + } |
| 20 | + |
| 21 | + |
| 22 | +-const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length ) |
| 23 | ++const char* XMLUtil::GetCharacterRef(const char* p, char* value, int* length) |
| 24 | + { |
| 25 | +- // Presume an entity, and pull it out. |
| 26 | ++ // Assume an entity, and pull it out. |
| 27 | + *length = 0; |
| 28 | + |
| 29 | ++ static const uint32_t MAX_CODE_POINT = 0x10FFFF; |
| 30 | ++ |
| 31 | + if ( *(p+1) == '#' && *(p+2) ) { |
| 32 | +- unsigned long ucs = 0; |
| 33 | +- TIXMLASSERT( sizeof( ucs ) >= 4 ); |
| 34 | ++ uint32_t ucs = 0; |
| 35 | + ptrdiff_t delta = 0; |
| 36 | +- unsigned mult = 1; |
| 37 | ++ uint32_t mult = 1; |
| 38 | + static const char SEMICOLON = ';'; |
| 39 | + |
| 40 | +- if ( *(p+2) == 'x' ) { |
| 41 | ++ bool hex = false; |
| 42 | ++ uint32_t radix = 10; |
| 43 | ++ const char* q = 0; |
| 44 | ++ char terminator = '#'; |
| 45 | ++ |
| 46 | ++ if (*(p + 2) == 'x') { |
| 47 | + // Hexadecimal. |
| 48 | +- const char* q = p+3; |
| 49 | +- if ( !(*q) ) { |
| 50 | +- return 0; |
| 51 | +- } |
| 52 | ++ hex = true; |
| 53 | ++ radix = 16; |
| 54 | ++ terminator = 'x'; |
| 55 | + |
| 56 | +- q = strchr( q, SEMICOLON ); |
| 57 | ++ q = p + 3; |
| 58 | ++ q = p + 3; |
| 59 | ++ } |
| 60 | ++ else { |
| 61 | ++ // Decimal. |
| 62 | ++ q = p + 2; |
| 63 | ++ } |
| 64 | ++ if (!(*q)) { |
| 65 | ++ return 0; |
| 66 | ++ } |
| 67 | + |
| 68 | +- if ( !q ) { |
| 69 | +- return 0; |
| 70 | +- } |
| 71 | +- TIXMLASSERT( *q == SEMICOLON ); |
| 72 | + |
| 73 | +- delta = q-p; |
| 74 | +- --q; |
| 75 | ++ q = strchr(q, SEMICOLON); |
| 76 | ++ if (!q) { |
| 77 | ++ return 0; |
| 78 | ++ } |
| 79 | ++ TIXMLASSERT(*q == SEMICOLON); |
| 80 | ++ delta = q - p; |
| 81 | ++ --q; |
| 82 | + |
| 83 | +- while ( *q != 'x' ) { |
| 84 | +- unsigned int digit = 0; |
| 85 | ++ while (*q != terminator) { |
| 86 | ++ uint32_t digit = 0; |
| 87 | + |
| 88 | +- if ( *q >= '0' && *q <= '9' ) { |
| 89 | +- digit = *q - '0'; |
| 90 | +- } |
| 91 | +- else if ( *q >= 'a' && *q <= 'f' ) { |
| 92 | +- digit = *q - 'a' + 10; |
| 93 | +- } |
| 94 | +- else if ( *q >= 'A' && *q <= 'F' ) { |
| 95 | +- digit = *q - 'A' + 10; |
| 96 | +- } |
| 97 | +- else { |
| 98 | +- return 0; |
| 99 | +- } |
| 100 | +- TIXMLASSERT( digit < 16 ); |
| 101 | +- TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit ); |
| 102 | +- const unsigned int digitScaled = mult * digit; |
| 103 | +- TIXMLASSERT( ucs <= ULONG_MAX - digitScaled ); |
| 104 | +- ucs += digitScaled; |
| 105 | +- TIXMLASSERT( mult <= UINT_MAX / 16 ); |
| 106 | +- mult *= 16; |
| 107 | +- --q; |
| 108 | ++ if (*q >= '0' && *q <= '9') { |
| 109 | ++ digit = *q - '0'; |
| 110 | + } |
| 111 | +- } |
| 112 | +- else { |
| 113 | +- // Decimal. |
| 114 | +- const char* q = p+2; |
| 115 | +- if ( !(*q) ) { |
| 116 | +- return 0; |
| 117 | ++ else if (hex && (*q >= 'a' && *q <= 'f')) { |
| 118 | ++ digit = *q - 'a' + 10; |
| 119 | + } |
| 120 | +- |
| 121 | +- q = strchr( q, SEMICOLON ); |
| 122 | +- |
| 123 | +- if ( !q ) { |
| 124 | ++ else if (hex && (*q >= 'A' && *q <= 'F')) { |
| 125 | ++ digit = *q - 'A' + 10; |
| 126 | ++ } |
| 127 | ++ else { |
| 128 | + return 0; |
| 129 | + } |
| 130 | +- TIXMLASSERT( *q == SEMICOLON ); |
| 131 | ++ TIXMLASSERT(digit < radix); |
| 132 | + |
| 133 | +- delta = q-p; |
| 134 | +- --q; |
| 135 | ++ const unsigned int digitScaled = mult * digit; |
| 136 | ++ ucs += digitScaled; |
| 137 | ++ mult *= radix; |
| 138 | + |
| 139 | +- while ( *q != '#' ) { |
| 140 | +- if ( *q >= '0' && *q <= '9' ) { |
| 141 | +- const unsigned int digit = *q - '0'; |
| 142 | +- TIXMLASSERT( digit < 10 ); |
| 143 | +- TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit ); |
| 144 | +- const unsigned int digitScaled = mult * digit; |
| 145 | +- TIXMLASSERT( ucs <= ULONG_MAX - digitScaled ); |
| 146 | +- ucs += digitScaled; |
| 147 | +- } |
| 148 | +- else { |
| 149 | +- return 0; |
| 150 | +- } |
| 151 | +- TIXMLASSERT( mult <= UINT_MAX / 10 ); |
| 152 | +- mult *= 10; |
| 153 | +- --q; |
| 154 | ++ // Security check: could a value exist that is out of range? |
| 155 | ++ // Easily; limit to the MAX_CODE_POINT, which also allows for a |
| 156 | ++ // bunch of leading zeroes. |
| 157 | ++ if (mult > MAX_CODE_POINT) { |
| 158 | ++ mult = MAX_CODE_POINT; |
| 159 | + } |
| 160 | ++ --q; |
| 161 | ++ } |
| 162 | ++ // Out of range: |
| 163 | ++ if (ucs > MAX_CODE_POINT) { |
| 164 | ++ return 0; |
| 165 | + } |
| 166 | + // convert the UCS to UTF-8 |
| 167 | +- ConvertUTF32ToUTF8( ucs, value, length ); |
| 168 | ++ TIXMLASSERT(ucs <= MAX_CODE_POINT); |
| 169 | ++ ConvertUTF32ToUTF8(ucs, value, length); |
| 170 | + return p + delta + 1; |
| 171 | + } |
| 172 | +- return p+1; |
| 173 | ++ return p + 1; |
| 174 | + } |
| 175 | + |
| 176 | +- |
| 177 | + void XMLUtil::ToStr( int v, char* buffer, int bufferSize ) |
| 178 | + { |
| 179 | + TIXML_SNPRINTF( buffer, bufferSize, "%d", v ); |
| 180 | +diff --git a/xmltest.cpp b/xmltest.cpp |
| 181 | +index d5a1ce3..50afcbd 100755 |
| 182 | +--- a/xmltest.cpp |
| 183 | ++++ b/xmltest.cpp |
| 184 | +@@ -1642,7 +1642,7 @@ int main( int argc, const char ** argv ) |
| 185 | + |
| 186 | + static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; |
| 187 | + XMLTest( "BOM and default declaration", result, printer.CStr(), false ); |
| 188 | +- XMLTest( "CStrSize", 42, printer.CStrSize(), false ); |
| 189 | ++ XMLTest( "CStrSize", true, printer.CStrSize() == 42, false ); |
| 190 | + } |
| 191 | + { |
| 192 | + const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>"; |
| 193 | +@@ -2488,6 +2488,35 @@ int main( int argc, const char ** argv ) |
| 194 | + doc.PrintError(); |
| 195 | + } |
| 196 | + |
| 197 | ++ // ---------- CVE-2024-50615 ----------- |
| 198 | ++ { |
| 199 | ++ const char* xml = "<Hello value='12A34' value2='56B78'>Text</Hello>"; |
| 200 | ++ XMLDocument doc; |
| 201 | ++ doc.Parse(xml); |
| 202 | ++ const char* value = doc.FirstChildElement()->Attribute("value"); |
| 203 | ++ const char* value2 = doc.FirstChildElement()->Attribute("value2"); |
| 204 | ++ XMLTest("Test attribute encode", false, doc.Error()); |
| 205 | ++ XMLTest("Test decimal value", value, "12A34"); |
| 206 | ++ XMLTest("Test hex encode", value2, "56B78"); |
| 207 | ++ } |
| 208 | ++ |
| 209 | ++ { |
| 210 | ++ const char* xml = "<Hello value='&#ABC9000000065;' value2='�' value3='�' value4='E' value5='!'>Text</Hello>"; |
| 211 | ++ XMLDocument doc; |
| 212 | ++ doc.Parse(xml); |
| 213 | ++ const char* value = doc.FirstChildElement()->Attribute("value"); |
| 214 | ++ const char* value2 = doc.FirstChildElement()->Attribute("value2"); |
| 215 | ++ const char* value3 = doc.FirstChildElement()->Attribute("value3"); |
| 216 | ++ const char* value4 = doc.FirstChildElement()->Attribute("value4"); |
| 217 | ++ const char* value5 = doc.FirstChildElement()->Attribute("value5"); |
| 218 | ++ XMLTest("Test attribute encode", false, doc.Error()); |
| 219 | ++ XMLTest("Test attribute encode too long value", value, "&#ABC9000000065;"); // test long value |
| 220 | ++ XMLTest("Test attribute encode out of unicode range", value2, "�"); // out of unicode range |
| 221 | ++ XMLTest("Test attribute encode out of int max value", value3, "�"); // out of int max value |
| 222 | ++ XMLTest("Test attribute encode with a Hex value", value4, "E"); // hex value in unicode value |
| 223 | ++ XMLTest("Test attribute encode with a Hex value", value5, "!"); // hex value in unicode value |
| 224 | ++ } |
| 225 | ++ |
| 226 | + // ----------- Performance tracking -------------- |
| 227 | + { |
| 228 | + #if defined( _MSC_VER ) |
| 229 | +-- |
| 230 | +2.45.3 |
| 231 | + |
0 commit comments