diff options
author | RĂ©mi Verschelde <remi@verschelde.fr> | 2021-02-24 13:03:46 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-24 13:03:46 +0100 |
commit | 5a10f52ee844425e39fbb539acf1e356d0eee825 (patch) | |
tree | 1be9b0edf5a5033387d724d4203f264127738d6e /core/string | |
parent | a527c6856bbc59698793ae67aa6f034b31231a8c (diff) | |
parent | c6a911f0379b429691aa0dca6615523892bbfb06 (diff) |
Merge pull request #45914 from HenryWConklin/45841-xml-entities
Add support for numeric XML entities to XMLParser
Diffstat (limited to 'core/string')
-rw-r--r-- | core/string/ustring.cpp | 62 |
1 files changed, 46 insertions, 16 deletions
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index 59fda65d43..a57c7b2504 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -3888,25 +3888,55 @@ static _FORCE_INLINE_ int _xml_unescape(const char32_t *p_src, int p_src_len, ch if (p_src_len >= 4 && p_src[1] == '#') { char32_t c = 0; - - for (int i = 2; i < p_src_len; i++) { - eat = i + 1; - char32_t ct = p_src[i]; - if (ct == ';') { - break; - } else if (ct >= '0' && ct <= '9') { - ct = ct - '0'; - } else if (ct >= 'a' && ct <= 'f') { - ct = (ct - 'a') + 10; - } else if (ct >= 'A' && ct <= 'F') { - ct = (ct - 'A') + 10; - } else { - continue; + bool overflow = false; + if (p_src[2] == 'x') { + // Hex entity &#x<num>; + for (int i = 3; i < p_src_len; i++) { + eat = i + 1; + char32_t ct = p_src[i]; + if (ct == ';') { + break; + } else if (ct >= '0' && ct <= '9') { + ct = ct - '0'; + } else if (ct >= 'a' && ct <= 'f') { + ct = (ct - 'a') + 10; + } else if (ct >= 'A' && ct <= 'F') { + ct = (ct - 'A') + 10; + } else { + break; + } + if (c > (UINT32_MAX >> 4)) { + overflow = true; + break; + } + c <<= 4; + c |= ct; + } + } else { + // Decimal entity &#<num>; + for (int i = 2; i < p_src_len; i++) { + eat = i + 1; + char32_t ct = p_src[i]; + if (ct == ';' || ct < '0' || ct > '9') { + break; + } + } + if (p_src[eat - 1] == ';') { + int64_t val = String::to_int(p_src + 2, eat - 3); + if (val > 0 && val <= UINT32_MAX) { + c = (char32_t)val; + } else { + overflow = true; + } } - c <<= 4; - c |= ct; } + // Value must be non-zero, in the range of char32_t, + // actually end with ';'. If invalid, leave the entity as-is + if (c == '\0' || overflow || p_src[eat - 1] != ';') { + eat = 1; + c = *p_src; + } if (p_dst) { *p_dst = c; } |