@@ -129,18 +129,31 @@ namespace misc_utils
129129 case ' /' : // Slash character
130130 val.push_back (' /' );break ;
131131 case ' u' : // Unicode code point
132- if (buf_end - it < 5 )
133132 {
134- ASSERT_MES_AND_THROW (" Invalid Unicode escape sequence" );
135- }
136- else
137- {
138- uint32_t dst = 0 ;
139- for (int i = 0 ; i < 4 ; ++i)
133+ auto read_hex4 = [&]() -> uint32_t {
134+ CHECK_AND_ASSERT_THROW_MES (buf_end - it >= 5 , " Invalid Unicode escape sequence" );
135+ uint32_t v = 0 ;
136+ for (int i = 0 ; i < 4 ; ++i)
137+ {
138+ const unsigned char tmp = isx[(unsigned char )*++it];
139+ CHECK_AND_ASSERT_THROW_MES (tmp != 0xff , " Bad Unicode encoding" );
140+ v = v << 4 | tmp;
141+ }
142+ return v;
143+ };
144+ uint32_t dst = read_hex4 ();
145+ // combine a UTF-16 surrogate pair into a single code point; reject lone surrogates
146+ if (dst >= 0xd800 && dst <= 0xdbff )
140147 {
141- const unsigned char tmp = isx[(unsigned char )*++it];
142- CHECK_AND_ASSERT_THROW_MES (tmp != 0xff , " Bad Unicode encoding" );
143- dst = dst << 4 | tmp;
148+ CHECK_AND_ASSERT_THROW_MES (buf_end - it >= 3 && *(it + 1 ) == ' \\ ' && *(it + 2 ) == ' u' , " Invalid UTF-16 surrogate pair" );
149+ it += 2 ;
150+ const uint32_t low = read_hex4 ();
151+ CHECK_AND_ASSERT_THROW_MES (low >= 0xdc00 && low <= 0xdfff , " Invalid UTF-16 surrogate pair" );
152+ dst = 0x10000 + ((dst - 0xd800 ) << 10 ) + (low - 0xdc00 );
153+ }
154+ else
155+ {
156+ CHECK_AND_ASSERT_THROW_MES (dst < 0xdc00 || dst > 0xdfff , " Invalid UTF-16 surrogate pair" );
144157 }
145158 // encode as UTF-8
146159 if (dst <= 0x7f )
@@ -160,7 +173,10 @@ namespace misc_utils
160173 }
161174 else
162175 {
163- ASSERT_MES_AND_THROW (" Unicode code point is out or range" );
176+ val.push_back (0xf0 | (dst >> 18 ));
177+ val.push_back (0x80 | ((dst >> 12 ) & 0x3f ));
178+ val.push_back (0x80 | ((dst >> 6 ) & 0x3f ));
179+ val.push_back (0x80 | (dst & 0x3f ));
164180 }
165181 }
166182 break ;
0 commit comments