1 /*
2 __ __ _
3 ___\ \/ /_ __ __ _| |_
4 / _ \\ /| '_ \ / _` | __|
5 | __// \| |_) | (_| | |_
6 \___/_/\_\ .__/ \__,_|\__|
7 |_| XML parser
8
9 Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
10 Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
11 Copyright (c) 2001-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
12 Copyright (c) 2002 Greg Stein <gstein@users.sourceforge.net>
13 Copyright (c) 2002-2016 Karl Waclawek <karl@waclawek.net>
14 Copyright (c) 2005-2009 Steven Solie <steven@solie.ca>
15 Copyright (c) 2016-2026 Sebastian Pipping <sebastian@pipping.org>
16 Copyright (c) 2016 Pascal Cuoq <cuoq@trust-in-soft.com>
17 Copyright (c) 2016 Don Lewis <truckman@apache.org>
18 Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
19 Copyright (c) 2017 Alexander Bluhm <alexander.bluhm@gmx.net>
20 Copyright (c) 2017 Benbuck Nason <bnason@netflix.com>
21 Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
22 Copyright (c) 2019 David Loffredo <loffredo@steptools.com>
23 Copyright (c) 2021 Donghee Na <donghee.na@python.org>
24 Copyright (c) 2022 Martin Ettl <ettl.martin78@googlemail.com>
25 Copyright (c) 2022 Sean McBride <sean@rogue-research.com>
26 Copyright (c) 2023 Hanno Böck <hanno@gentoo.org>
27 Copyright (c) 2025 Alfonso Gregory <gfunni234@gmail.com>
28 Copyright (c) 2026 Nick Begg <nick@stunttruck.net>
29 Copyright (c) 2026 Kartik Kenchi <netliomax25@gmail.com>
30 Licensed under the MIT license:
31
32 Permission is hereby granted, free of charge, to any person obtaining
33 a copy of this software and associated documentation files (the
34 "Software"), to deal in the Software without restriction, including
35 without limitation the rights to use, copy, modify, merge, publish,
36 distribute, sublicense, and/or sell copies of the Software, and to permit
37 persons to whom the Software is furnished to do so, subject to the
38 following conditions:
39
40 The above copyright notice and this permission notice shall be included
41 in all copies or substantial portions of the Software.
42
43 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
44 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
45 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
46 NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
47 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
48 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
49 USE OR OTHER DEALINGS IN THE SOFTWARE.
50
51 SPDX-License-Identifier: MIT
52 */
53
54 #include "expat_config.h"
55
56 #include <stddef.h>
57 #include <string.h> /* memcpy */
58 #include <stdbool.h>
59
60 #ifdef _WIN32
61 # include "winconfig.h"
62 #endif
63
64 #include "internal.h"
65 #include "fallthrough.h"
66 #include "xmltok.h"
67 #include "nametab.h"
68
69 #ifdef XML_DTD
70 # define IGNORE_SECTION_TOK_VTABLE , PREFIX(ignoreSectionTok)
71 #else
72 # define IGNORE_SECTION_TOK_VTABLE /* as nothing */
73 #endif
74
75 #define VTABLE1 \
76 {PREFIX(prologTok), PREFIX(contentTok), \
77 PREFIX(cdataSectionTok) IGNORE_SECTION_TOK_VTABLE}, \
78 {PREFIX(attributeValueTok), PREFIX(entityValueTok)}, \
79 PREFIX(nameMatchesAscii), PREFIX(nameLength), PREFIX(skipS), \
80 PREFIX(getAtts), PREFIX(charRefNumber), PREFIX(predefinedEntityName), \
81 PREFIX(updatePosition), PREFIX(isPublicId)
82
83 #define VTABLE VTABLE1, PREFIX(toUtf8), PREFIX(toUtf16)
84
85 #define UCS2_GET_NAMING(pages, hi, lo) \
86 (namingBitmap[(pages[hi] << 3) + ((lo) >> 5)] & (1u << ((lo) & 0x1F)))
87
88 /* A 2 byte UTF-8 representation splits the characters 11 bits between
89 the bottom 5 and 6 bits of the bytes. We need 8 bits to index into
90 pages, 3 bits to add to that index and 5 bits to generate the mask.
91 */
92 #define UTF8_GET_NAMING2(pages, byte) \
93 (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3) \
94 + ((((byte)[0]) & 3) << 1) + ((((byte)[1]) >> 5) & 1)] \
95 & (1u << (((byte)[1]) & 0x1F)))
96
97 /* A 3 byte UTF-8 representation splits the characters 16 bits between
98 the bottom 4, 6 and 6 bits of the bytes. We need 8 bits to index
99 into pages, 3 bits to add to that index and 5 bits to generate the
100 mask.
101 */
102 #define UTF8_GET_NAMING3(pages, byte) \
103 (namingBitmap \
104 [((pages)[((((byte)[0]) & 0xF) << 4) + ((((byte)[1]) >> 2) & 0xF)] \
105 << 3) \
106 + ((((byte)[1]) & 3) << 1) + ((((byte)[2]) >> 5) & 1)] \
107 & (1u << (((byte)[2]) & 0x1F)))
108
109 /* Detection of invalid UTF-8 sequences is based on Table 3.1B
110 of Unicode 3.2: https://www.unicode.org/unicode/reports/tr28/
111 with the additional restriction of not allowing the Unicode
112 code points 0xFFFF and 0xFFFE (sequences EF,BF,BF and EF,BF,BE).
113 Implementation details:
114 (A & 0x80) == 0 means A < 0x80
115 and
116 (A & 0xC0) == 0xC0 means A > 0xBF
117 */
118
119 #define UTF8_INVALID2(p) \
120 ((*p) < 0xC2 || ((p)[1] & 0x80) == 0 || ((p)[1] & 0xC0) == 0xC0)
121
122 #define UTF8_INVALID3(p) \
123 (((p)[2] & 0x80) == 0 \
124 || ((*p) == 0xEF && (p)[1] == 0xBF ? (p)[2] > 0xBD \
125 : ((p)[2] & 0xC0) == 0xC0) \
126 || ((*p) == 0xE0 \
127 ? (p)[1] < 0xA0 || ((p)[1] & 0xC0) == 0xC0 \
128 : ((p)[1] & 0x80) == 0 \
129 || ((*p) == 0xED ? (p)[1] > 0x9F : ((p)[1] & 0xC0) == 0xC0)))
130
131 #define UTF8_INVALID4(p) \
132 (((p)[3] & 0x80) == 0 || ((p)[3] & 0xC0) == 0xC0 || ((p)[2] & 0x80) == 0 \
133 || ((p)[2] & 0xC0) == 0xC0 \
134 || ((*p) == 0xF0 \
135 ? (p)[1] < 0x90 || ((p)[1] & 0xC0) == 0xC0 \
136 : ((p)[1] & 0x80) == 0 \
137 || ((*p) == 0xF4 ? (p)[1] > 0x8F : ((p)[1] & 0xC0) == 0xC0)))
138
139 static int PTRFASTCALL
isNever(const ENCODING * enc,const char * p)140 isNever(const ENCODING *enc, const char *p) {
141 UNUSED_P(enc);
142 UNUSED_P(p);
143 return 0;
144 }
145
146 static int PTRFASTCALL
utf8_isName2(const ENCODING * enc,const char * p)147 utf8_isName2(const ENCODING *enc, const char *p) {
148 UNUSED_P(enc);
149 return UTF8_GET_NAMING2(namePages, (const unsigned char *)p);
150 }
151
152 static int PTRFASTCALL
utf8_isName3(const ENCODING * enc,const char * p)153 utf8_isName3(const ENCODING *enc, const char *p) {
154 UNUSED_P(enc);
155 return UTF8_GET_NAMING3(namePages, (const unsigned char *)p);
156 }
157
158 #define utf8_isName4 isNever
159
160 static int PTRFASTCALL
utf8_isNmstrt2(const ENCODING * enc,const char * p)161 utf8_isNmstrt2(const ENCODING *enc, const char *p) {
162 UNUSED_P(enc);
163 return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p);
164 }
165
166 static int PTRFASTCALL
utf8_isNmstrt3(const ENCODING * enc,const char * p)167 utf8_isNmstrt3(const ENCODING *enc, const char *p) {
168 UNUSED_P(enc);
169 return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p);
170 }
171
172 #define utf8_isNmstrt4 isNever
173
174 static int PTRFASTCALL
utf8_isInvalid2(const ENCODING * enc,const char * p)175 utf8_isInvalid2(const ENCODING *enc, const char *p) {
176 UNUSED_P(enc);
177 return UTF8_INVALID2((const unsigned char *)p);
178 }
179
180 static int PTRFASTCALL
utf8_isInvalid3(const ENCODING * enc,const char * p)181 utf8_isInvalid3(const ENCODING *enc, const char *p) {
182 UNUSED_P(enc);
183 return UTF8_INVALID3((const unsigned char *)p);
184 }
185
186 static int PTRFASTCALL
utf8_isInvalid4(const ENCODING * enc,const char * p)187 utf8_isInvalid4(const ENCODING *enc, const char *p) {
188 UNUSED_P(enc);
189 return UTF8_INVALID4((const unsigned char *)p);
190 }
191
192 struct normal_encoding {
193 ENCODING enc;
194 unsigned char type[256];
195 #ifdef XML_MIN_SIZE
196 int(PTRFASTCALL *byteType)(const ENCODING *, const char *);
197 int(PTRFASTCALL *isNameMin)(const ENCODING *, const char *);
198 int(PTRFASTCALL *isNmstrtMin)(const ENCODING *, const char *);
199 int(PTRFASTCALL *byteToAscii)(const ENCODING *, const char *);
200 int(PTRCALL *charMatches)(const ENCODING *, const char *, int);
201 #endif /* XML_MIN_SIZE */
202 int(PTRFASTCALL *isName2)(const ENCODING *, const char *);
203 int(PTRFASTCALL *isName3)(const ENCODING *, const char *);
204 int(PTRFASTCALL *isName4)(const ENCODING *, const char *);
205 int(PTRFASTCALL *isNmstrt2)(const ENCODING *, const char *);
206 int(PTRFASTCALL *isNmstrt3)(const ENCODING *, const char *);
207 int(PTRFASTCALL *isNmstrt4)(const ENCODING *, const char *);
208 int(PTRFASTCALL *isInvalid2)(const ENCODING *, const char *);
209 int(PTRFASTCALL *isInvalid3)(const ENCODING *, const char *);
210 int(PTRFASTCALL *isInvalid4)(const ENCODING *, const char *);
211 };
212
213 #define AS_NORMAL_ENCODING(enc) ((const struct normal_encoding *)(enc))
214
215 #ifdef XML_MIN_SIZE
216
217 # define STANDARD_VTABLE(E) \
218 E##byteType, E##isNameMin, E##isNmstrtMin, E##byteToAscii, E##charMatches,
219
220 #else
221
222 # define STANDARD_VTABLE(E) /* as nothing */
223
224 #endif
225
226 #define NORMAL_VTABLE(E) \
227 E##isName2, E##isName3, E##isName4, E##isNmstrt2, E##isNmstrt3, \
228 E##isNmstrt4, E##isInvalid2, E##isInvalid3, E##isInvalid4
229
230 #define NULL_VTABLE \
231 /* isName2 */ NULL, /* isName3 */ NULL, /* isName4 */ NULL, \
232 /* isNmstrt2 */ NULL, /* isNmstrt3 */ NULL, /* isNmstrt4 */ NULL, \
233 /* isInvalid2 */ NULL, /* isInvalid3 */ NULL, /* isInvalid4 */ NULL
234
235 static int FASTCALL checkCharRefNumber(int result);
236
237 #include "xmltok_impl.h"
238 #include "ascii.h"
239
240 #ifdef XML_MIN_SIZE
241 # define sb_isNameMin isNever
242 # define sb_isNmstrtMin isNever
243 #endif
244
245 #ifdef XML_MIN_SIZE
246 # define MINBPC(enc) ((enc)->minBytesPerChar)
247 #else
248 /* minimum bytes per character */
249 # define MINBPC(enc) 1
250 #endif
251
252 #define SB_BYTE_TYPE(enc, p) \
253 (((const struct normal_encoding *)(enc))->type[(unsigned char)*(p)])
254
255 #ifdef XML_MIN_SIZE
256 static int PTRFASTCALL
sb_byteType(const ENCODING * enc,const char * p)257 sb_byteType(const ENCODING *enc, const char *p) {
258 return SB_BYTE_TYPE(enc, p);
259 }
260 # define BYTE_TYPE(enc, p) (AS_NORMAL_ENCODING(enc)->byteType(enc, p))
261 #else
262 # define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p)
263 #endif
264
265 #ifdef XML_MIN_SIZE
266 # define BYTE_TO_ASCII(enc, p) (AS_NORMAL_ENCODING(enc)->byteToAscii(enc, p))
267 static int PTRFASTCALL
sb_byteToAscii(const ENCODING * enc,const char * p)268 sb_byteToAscii(const ENCODING *enc, const char *p) {
269 UNUSED_P(enc);
270 return *p;
271 }
272 #else
273 # define BYTE_TO_ASCII(enc, p) (*(p))
274 #endif
275
276 #define IS_NAME_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isName##n(enc, p))
277 #define IS_NMSTRT_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isNmstrt##n(enc, p))
278 #ifdef XML_MIN_SIZE
279 # define IS_INVALID_CHAR(enc, p, n) \
280 (AS_NORMAL_ENCODING(enc)->isInvalid##n \
281 && AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p))
282 #else
283 # define IS_INVALID_CHAR(enc, p, n) \
284 (AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p))
285 #endif
286
287 #ifdef XML_MIN_SIZE
288 # define IS_NAME_CHAR_MINBPC(enc, p) \
289 (AS_NORMAL_ENCODING(enc)->isNameMin(enc, p))
290 # define IS_NMSTRT_CHAR_MINBPC(enc, p) \
291 (AS_NORMAL_ENCODING(enc)->isNmstrtMin(enc, p))
292 #else
293 # define IS_NAME_CHAR_MINBPC(enc, p) (0)
294 # define IS_NMSTRT_CHAR_MINBPC(enc, p) (0)
295 #endif
296
297 #ifdef XML_MIN_SIZE
298 # define CHAR_MATCHES(enc, p, c) \
299 (AS_NORMAL_ENCODING(enc)->charMatches(enc, p, c))
300 static int PTRCALL
sb_charMatches(const ENCODING * enc,const char * p,int c)301 sb_charMatches(const ENCODING *enc, const char *p, int c) {
302 UNUSED_P(enc);
303 return *p == c;
304 }
305 #else
306 /* c is an ASCII character */
307 # define CHAR_MATCHES(enc, p, c) (*(p) == (c))
308 #endif
309
310 #define PREFIX(ident) normal_##ident
311 #define XML_TOK_IMPL_C
312 #include "xmltok_impl.c"
313 #undef XML_TOK_IMPL_C
314
315 #undef MINBPC
316 #undef BYTE_TYPE
317 #undef BYTE_TO_ASCII
318 #undef CHAR_MATCHES
319 #undef IS_NAME_CHAR
320 #undef IS_NAME_CHAR_MINBPC
321 #undef IS_NMSTRT_CHAR
322 #undef IS_NMSTRT_CHAR_MINBPC
323 #undef IS_INVALID_CHAR
324
325 enum { /* UTF8_cvalN is value of masked first byte of N byte sequence */
326 UTF8_cval1 = 0x00,
327 UTF8_cval2 = 0xc0,
328 UTF8_cval3 = 0xe0,
329 UTF8_cval4 = 0xf0
330 };
331
332 void
_INTERNAL_trim_to_complete_utf8_characters(const char * from,const char ** fromLimRef)333 _INTERNAL_trim_to_complete_utf8_characters(const char *from,
334 const char **fromLimRef) {
335 const char *fromLim = *fromLimRef;
336 size_t walked = 0;
337 for (; fromLim > from; fromLim--, walked++) {
338 const unsigned char prev = (unsigned char)fromLim[-1];
339 if ((prev & 0xf8u)
340 == 0xf0u) { /* 4-byte character, lead by 0b11110xxx byte */
341 if (walked + 1 >= 4) {
342 fromLim += 4 - 1;
343 break;
344 } else {
345 walked = 0;
346 }
347 } else if ((prev & 0xf0u)
348 == 0xe0u) { /* 3-byte character, lead by 0b1110xxxx byte */
349 if (walked + 1 >= 3) {
350 fromLim += 3 - 1;
351 break;
352 } else {
353 walked = 0;
354 }
355 } else if ((prev & 0xe0u)
356 == 0xc0u) { /* 2-byte character, lead by 0b110xxxxx byte */
357 if (walked + 1 >= 2) {
358 fromLim += 2 - 1;
359 break;
360 } else {
361 walked = 0;
362 }
363 } else if ((prev & 0x80u)
364 == 0x00u) { /* 1-byte character, matching 0b0xxxxxxx */
365 break;
366 }
367 }
368 *fromLimRef = fromLim;
369 }
370
371 static enum XML_Convert_Result PTRCALL
utf8_toUtf8(const ENCODING * enc,const char ** fromP,const char * fromLim,char ** toP,const char * toLim)372 utf8_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
373 char **toP, const char *toLim) {
374 bool input_incomplete = false;
375 bool output_exhausted = false;
376
377 /* Avoid copying partial characters (due to limited space). */
378 const ptrdiff_t bytesAvailable = fromLim - *fromP;
379 const ptrdiff_t bytesStorable = toLim - *toP;
380 UNUSED_P(enc);
381 if (bytesAvailable > bytesStorable) {
382 fromLim = *fromP + bytesStorable;
383 output_exhausted = true;
384 }
385
386 /* Avoid copying partial characters (from incomplete input). */
387 {
388 const char *const fromLimBefore = fromLim;
389 _INTERNAL_trim_to_complete_utf8_characters(*fromP, &fromLim);
390 if (fromLim < fromLimBefore) {
391 input_incomplete = true;
392 }
393 }
394
395 {
396 const ptrdiff_t bytesToCopy = fromLim - *fromP;
397 memcpy(*toP, *fromP, bytesToCopy);
398 *fromP += bytesToCopy;
399 *toP += bytesToCopy;
400 }
401
402 if (output_exhausted) /* needs to go first */
403 return XML_CONVERT_OUTPUT_EXHAUSTED;
404 else if (input_incomplete)
405 return XML_CONVERT_INPUT_INCOMPLETE;
406 else
407 return XML_CONVERT_COMPLETED;
408 }
409
410 static enum XML_Convert_Result PTRCALL
utf8_toUtf16(const ENCODING * enc,const char ** fromP,const char * fromLim,unsigned short ** toP,const unsigned short * toLim)411 utf8_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim,
412 unsigned short **toP, const unsigned short *toLim) {
413 enum XML_Convert_Result res = XML_CONVERT_COMPLETED;
414 unsigned short *to = *toP;
415 const char *from = *fromP;
416 while (from < fromLim && to < toLim) {
417 switch (SB_BYTE_TYPE(enc, from)) {
418 case BT_LEAD2:
419 if (fromLim - from < 2) {
420 res = XML_CONVERT_INPUT_INCOMPLETE;
421 goto after;
422 }
423 *to++ = (unsigned short)(((from[0] & 0x1f) << 6) | (from[1] & 0x3f));
424 from += 2;
425 break;
426 case BT_LEAD3:
427 if (fromLim - from < 3) {
428 res = XML_CONVERT_INPUT_INCOMPLETE;
429 goto after;
430 }
431 *to++ = (unsigned short)(((from[0] & 0xf) << 12) | ((from[1] & 0x3f) << 6)
432 | (from[2] & 0x3f));
433 from += 3;
434 break;
435 case BT_LEAD4: {
436 unsigned long n;
437 if (toLim - to < 2) {
438 res = XML_CONVERT_OUTPUT_EXHAUSTED;
439 goto after;
440 }
441 if (fromLim - from < 4) {
442 res = XML_CONVERT_INPUT_INCOMPLETE;
443 goto after;
444 }
445 n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12)
446 | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f);
447 n -= 0x10000;
448 to[0] = (unsigned short)((n >> 10) | 0xD800);
449 to[1] = (unsigned short)((n & 0x3FF) | 0xDC00);
450 to += 2;
451 from += 4;
452 } break;
453 default:
454 *to++ = *from++;
455 break;
456 }
457 }
458 if (from < fromLim)
459 res = XML_CONVERT_OUTPUT_EXHAUSTED;
460 after:
461 *fromP = from;
462 *toP = to;
463 return res;
464 }
465
466 #ifdef XML_NS
467 static const struct normal_encoding utf8_encoding_ns
468 = {{VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0},
469 {
470 # include "asciitab.h"
471 # include "utf8tab.h"
472 },
473 STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)};
474 #endif
475
476 static const struct normal_encoding utf8_encoding
477 = {{VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0},
478 {
479 #define BT_COLON BT_NMSTRT
480 #include "asciitab.h"
481 #undef BT_COLON
482 #include "utf8tab.h"
483 },
484 STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)};
485
486 #ifdef XML_NS
487
488 static const struct normal_encoding internal_utf8_encoding_ns
489 = {{VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0},
490 {
491 # include "iasciitab.h"
492 # include "utf8tab.h"
493 },
494 STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)};
495
496 #endif
497
498 static const struct normal_encoding internal_utf8_encoding
499 = {{VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0},
500 {
501 #define BT_COLON BT_NMSTRT
502 #include "iasciitab.h"
503 #undef BT_COLON
504 #include "utf8tab.h"
505 },
506 STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)};
507
508 static enum XML_Convert_Result PTRCALL
latin1_toUtf8(const ENCODING * enc,const char ** fromP,const char * fromLim,char ** toP,const char * toLim)509 latin1_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
510 char **toP, const char *toLim) {
511 UNUSED_P(enc);
512 for (;;) {
513 unsigned char c;
514 if (*fromP == fromLim)
515 return XML_CONVERT_COMPLETED;
516 c = (unsigned char)**fromP;
517 if (c & 0x80) {
518 if (toLim - *toP < 2)
519 return XML_CONVERT_OUTPUT_EXHAUSTED;
520 *(*toP)++ = (char)((c >> 6) | UTF8_cval2);
521 *(*toP)++ = (char)((c & 0x3f) | 0x80);
522 (*fromP)++;
523 } else {
524 if (*toP == toLim)
525 return XML_CONVERT_OUTPUT_EXHAUSTED;
526 *(*toP)++ = *(*fromP)++;
527 }
528 }
529 }
530
531 static enum XML_Convert_Result PTRCALL
latin1_toUtf16(const ENCODING * enc,const char ** fromP,const char * fromLim,unsigned short ** toP,const unsigned short * toLim)532 latin1_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim,
533 unsigned short **toP, const unsigned short *toLim) {
534 UNUSED_P(enc);
535 while (*fromP < fromLim && *toP < toLim)
536 *(*toP)++ = (unsigned char)*(*fromP)++;
537
538 if ((*toP == toLim) && (*fromP < fromLim))
539 return XML_CONVERT_OUTPUT_EXHAUSTED;
540 else
541 return XML_CONVERT_COMPLETED;
542 }
543
544 #ifdef XML_NS
545
546 static const struct normal_encoding latin1_encoding_ns
547 = {{VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0},
548 {
549 # include "asciitab.h"
550 # include "latin1tab.h"
551 },
552 STANDARD_VTABLE(sb_) NULL_VTABLE};
553
554 #endif
555
556 static const struct normal_encoding latin1_encoding
557 = {{VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0},
558 {
559 #define BT_COLON BT_NMSTRT
560 #include "asciitab.h"
561 #undef BT_COLON
562 #include "latin1tab.h"
563 },
564 STANDARD_VTABLE(sb_) NULL_VTABLE};
565
566 static enum XML_Convert_Result PTRCALL
ascii_toUtf8(const ENCODING * enc,const char ** fromP,const char * fromLim,char ** toP,const char * toLim)567 ascii_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
568 char **toP, const char *toLim) {
569 UNUSED_P(enc);
570 while (*fromP < fromLim && *toP < toLim)
571 *(*toP)++ = *(*fromP)++;
572
573 if ((*toP == toLim) && (*fromP < fromLim))
574 return XML_CONVERT_OUTPUT_EXHAUSTED;
575 else
576 return XML_CONVERT_COMPLETED;
577 }
578
579 #ifdef XML_NS
580
581 static const struct normal_encoding ascii_encoding_ns
582 = {{VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0},
583 {
584 # include "asciitab.h"
585 /* BT_NONXML == 0 */
586 },
587 STANDARD_VTABLE(sb_) NULL_VTABLE};
588
589 #endif
590
591 static const struct normal_encoding ascii_encoding
592 = {{VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0},
593 {
594 #define BT_COLON BT_NMSTRT
595 #include "asciitab.h"
596 #undef BT_COLON
597 /* BT_NONXML == 0 */
598 },
599 STANDARD_VTABLE(sb_) NULL_VTABLE};
600
601 static int PTRFASTCALL
unicode_byte_type(char hi,char lo)602 unicode_byte_type(char hi, char lo) {
603 switch ((unsigned char)hi) {
604 /* 0xD800-0xDBFF first 16-bit code unit or high surrogate (W1) */
605 case 0xD8:
606 case 0xD9:
607 case 0xDA:
608 case 0xDB:
609 return BT_LEAD4;
610 /* 0xDC00-0xDFFF second 16-bit code unit or low surrogate (W2) */
611 case 0xDC:
612 case 0xDD:
613 case 0xDE:
614 case 0xDF:
615 return BT_TRAIL;
616 case 0xFF:
617 switch ((unsigned char)lo) {
618 case 0xFF: /* noncharacter-FFFF */
619 case 0xFE: /* noncharacter-FFFE */
620 return BT_NONXML;
621 }
622 break;
623 }
624 return BT_NONASCII;
625 }
626
627 #define DEFINE_UTF16_TO_UTF8(E) \
628 static enum XML_Convert_Result PTRCALL E##toUtf8( \
629 const ENCODING *enc, const char **fromP, const char *fromLim, \
630 char **toP, const char *toLim) { \
631 const char *from = *fromP; \
632 UNUSED_P(enc); \
633 fromLim = from + (((fromLim - from) >> 1) << 1); /* shrink to even */ \
634 for (; from < fromLim; from += 2) { \
635 int plane; \
636 unsigned char lo2; \
637 unsigned char lo = GET_LO(from); \
638 unsigned char hi = GET_HI(from); \
639 switch (hi) { \
640 case 0: \
641 if (lo < 0x80) { \
642 if (*toP == toLim) { \
643 *fromP = from; \
644 return XML_CONVERT_OUTPUT_EXHAUSTED; \
645 } \
646 *(*toP)++ = lo; \
647 break; \
648 } \
649 EXPAT_FALLTHROUGH; \
650 case 0x1: \
651 case 0x2: \
652 case 0x3: \
653 case 0x4: \
654 case 0x5: \
655 case 0x6: \
656 case 0x7: \
657 if (toLim - *toP < 2) { \
658 *fromP = from; \
659 return XML_CONVERT_OUTPUT_EXHAUSTED; \
660 } \
661 *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2); \
662 *(*toP)++ = ((lo & 0x3f) | 0x80); \
663 break; \
664 default: \
665 if (toLim - *toP < 3) { \
666 *fromP = from; \
667 return XML_CONVERT_OUTPUT_EXHAUSTED; \
668 } \
669 /* 16 bits divided 4, 6, 6 amongst 3 bytes */ \
670 *(*toP)++ = ((hi >> 4) | UTF8_cval3); \
671 *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80); \
672 *(*toP)++ = ((lo & 0x3f) | 0x80); \
673 break; \
674 case 0xD8: \
675 case 0xD9: \
676 case 0xDA: \
677 case 0xDB: \
678 if (toLim - *toP < 4) { \
679 *fromP = from; \
680 return XML_CONVERT_OUTPUT_EXHAUSTED; \
681 } \
682 if (fromLim - from < 4) { \
683 *fromP = from; \
684 return XML_CONVERT_INPUT_INCOMPLETE; \
685 } \
686 plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1; \
687 *(*toP)++ = (char)((plane >> 2) | UTF8_cval4); \
688 *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80); \
689 from += 2; \
690 lo2 = GET_LO(from); \
691 *(*toP)++ = (((lo & 0x3) << 4) | ((GET_HI(from) & 0x3) << 2) \
692 | (lo2 >> 6) | 0x80); \
693 *(*toP)++ = ((lo2 & 0x3f) | 0x80); \
694 break; \
695 } \
696 } \
697 *fromP = from; \
698 if (from < fromLim) \
699 return XML_CONVERT_INPUT_INCOMPLETE; \
700 else \
701 return XML_CONVERT_COMPLETED; \
702 }
703
704 #define DEFINE_UTF16_TO_UTF16(E) \
705 static enum XML_Convert_Result PTRCALL E##toUtf16( \
706 const ENCODING *enc, const char **fromP, const char *fromLim, \
707 unsigned short **toP, const unsigned short *toLim) { \
708 enum XML_Convert_Result res = XML_CONVERT_COMPLETED; \
709 UNUSED_P(enc); \
710 fromLim = *fromP + (((fromLim - *fromP) >> 1) << 1); /* shrink to even */ \
711 /* Avoid copying the first half (2 bytes) of surrogate pairs (4 bytes) */ \
712 if (fromLim - *fromP > ((toLim - *toP) << 1) \
713 && /* are the last two bytes a high surrogate (0xD800-0xDBFF)? */ \
714 (GET_HI(fromLim - 2) & 0xFC) == 0xD8) { \
715 fromLim -= 2; \
716 res = XML_CONVERT_INPUT_INCOMPLETE; \
717 } \
718 for (; *fromP < fromLim && *toP < toLim; *fromP += 2) \
719 *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \
720 if ((*toP == toLim) && (*fromP < fromLim)) \
721 return XML_CONVERT_OUTPUT_EXHAUSTED; \
722 else \
723 return res; \
724 }
725
726 #define GET_LO(ptr) ((unsigned char)(ptr)[0])
727 #define GET_HI(ptr) ((unsigned char)(ptr)[1])
728
729 DEFINE_UTF16_TO_UTF8(little2_)
DEFINE_UTF16_TO_UTF16(little2_)730 DEFINE_UTF16_TO_UTF16(little2_)
731
732 #undef GET_LO
733 #undef GET_HI
734
735 #define GET_LO(ptr) ((unsigned char)(ptr)[1])
736 #define GET_HI(ptr) ((unsigned char)(ptr)[0])
737
738 DEFINE_UTF16_TO_UTF8(big2_)
739 DEFINE_UTF16_TO_UTF16(big2_)
740
741 #undef GET_LO
742 #undef GET_HI
743
744 #define LITTLE2_BYTE_TYPE(enc, p) \
745 ((p)[1] == 0 ? SB_BYTE_TYPE(enc, p) : unicode_byte_type((p)[1], (p)[0]))
746 #define LITTLE2_BYTE_TO_ASCII(p) ((p)[1] == 0 ? (p)[0] : -1)
747 #define LITTLE2_CHAR_MATCHES(p, c) ((p)[1] == 0 && (p)[0] == (c))
748 #define LITTLE2_IS_NAME_CHAR_MINBPC(p) \
749 UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0])
750 #define LITTLE2_IS_NMSTRT_CHAR_MINBPC(p) \
751 UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0])
752
753 #ifdef XML_MIN_SIZE
754
755 static int PTRFASTCALL
756 little2_byteType(const ENCODING *enc, const char *p) {
757 return LITTLE2_BYTE_TYPE(enc, p);
758 }
759
760 static int PTRFASTCALL
little2_byteToAscii(const ENCODING * enc,const char * p)761 little2_byteToAscii(const ENCODING *enc, const char *p) {
762 UNUSED_P(enc);
763 return LITTLE2_BYTE_TO_ASCII(p);
764 }
765
766 static int PTRCALL
little2_charMatches(const ENCODING * enc,const char * p,int c)767 little2_charMatches(const ENCODING *enc, const char *p, int c) {
768 UNUSED_P(enc);
769 return LITTLE2_CHAR_MATCHES(p, c);
770 }
771
772 static int PTRFASTCALL
little2_isNameMin(const ENCODING * enc,const char * p)773 little2_isNameMin(const ENCODING *enc, const char *p) {
774 UNUSED_P(enc);
775 return LITTLE2_IS_NAME_CHAR_MINBPC(p);
776 }
777
778 static int PTRFASTCALL
little2_isNmstrtMin(const ENCODING * enc,const char * p)779 little2_isNmstrtMin(const ENCODING *enc, const char *p) {
780 UNUSED_P(enc);
781 return LITTLE2_IS_NMSTRT_CHAR_MINBPC(p);
782 }
783
784 # undef VTABLE
785 # define VTABLE VTABLE1, little2_toUtf8, little2_toUtf16
786
787 #else /* not XML_MIN_SIZE */
788
789 # undef PREFIX
790 # define PREFIX(ident) little2_##ident
791 # define MINBPC(enc) 2
792 /* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
793 # define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p)
794 # define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(p)
795 # define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(p, c)
796 # define IS_NAME_CHAR(enc, p, n) 0
797 # define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(p)
798 # define IS_NMSTRT_CHAR(enc, p, n) (0)
799 # define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(p)
800
801 # define XML_TOK_IMPL_C
802 # include "xmltok_impl.c"
803 # undef XML_TOK_IMPL_C
804
805 # undef MINBPC
806 # undef BYTE_TYPE
807 # undef BYTE_TO_ASCII
808 # undef CHAR_MATCHES
809 # undef IS_NAME_CHAR
810 # undef IS_NAME_CHAR_MINBPC
811 # undef IS_NMSTRT_CHAR
812 # undef IS_NMSTRT_CHAR_MINBPC
813 # undef IS_INVALID_CHAR
814
815 #endif /* not XML_MIN_SIZE */
816
817 #ifdef XML_NS
818
819 static const struct normal_encoding little2_encoding_ns
820 = {{VTABLE, 2, 0,
821 # if BYTEORDER == 1234
822 1
823 # else
824 0
825 # endif
826 },
827 {
828 # include "asciitab.h"
829 # include "latin1tab.h"
830 },
831 STANDARD_VTABLE(little2_) NULL_VTABLE};
832
833 #endif
834
835 static const struct normal_encoding little2_encoding
836 = {{VTABLE, 2, 0,
837 #if BYTEORDER == 1234
838 1
839 #else
840 0
841 #endif
842 },
843 {
844 #define BT_COLON BT_NMSTRT
845 #include "asciitab.h"
846 #undef BT_COLON
847 #include "latin1tab.h"
848 },
849 STANDARD_VTABLE(little2_) NULL_VTABLE};
850
851 #if BYTEORDER != 4321
852
853 # ifdef XML_NS
854
855 static const struct normal_encoding internal_little2_encoding_ns
856 = {{VTABLE, 2, 0, 1},
857 {
858 # include "iasciitab.h"
859 # include "latin1tab.h"
860 },
861 STANDARD_VTABLE(little2_) NULL_VTABLE};
862
863 # endif
864
865 static const struct normal_encoding internal_little2_encoding
866 = {{VTABLE, 2, 0, 1},
867 {
868 # define BT_COLON BT_NMSTRT
869 # include "iasciitab.h"
870 # undef BT_COLON
871 # include "latin1tab.h"
872 },
873 STANDARD_VTABLE(little2_) NULL_VTABLE};
874
875 #endif
876
877 #define BIG2_BYTE_TYPE(enc, p) \
878 ((p)[0] == 0 ? SB_BYTE_TYPE(enc, p + 1) : unicode_byte_type((p)[0], (p)[1]))
879 #define BIG2_BYTE_TO_ASCII(p) ((p)[0] == 0 ? (p)[1] : -1)
880 #define BIG2_CHAR_MATCHES(p, c) ((p)[0] == 0 && (p)[1] == (c))
881 #define BIG2_IS_NAME_CHAR_MINBPC(p) \
882 UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1])
883 #define BIG2_IS_NMSTRT_CHAR_MINBPC(p) \
884 UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1])
885
886 #ifdef XML_MIN_SIZE
887
888 static int PTRFASTCALL
big2_byteType(const ENCODING * enc,const char * p)889 big2_byteType(const ENCODING *enc, const char *p) {
890 return BIG2_BYTE_TYPE(enc, p);
891 }
892
893 static int PTRFASTCALL
big2_byteToAscii(const ENCODING * enc,const char * p)894 big2_byteToAscii(const ENCODING *enc, const char *p) {
895 UNUSED_P(enc);
896 return BIG2_BYTE_TO_ASCII(p);
897 }
898
899 static int PTRCALL
big2_charMatches(const ENCODING * enc,const char * p,int c)900 big2_charMatches(const ENCODING *enc, const char *p, int c) {
901 UNUSED_P(enc);
902 return BIG2_CHAR_MATCHES(p, c);
903 }
904
905 static int PTRFASTCALL
big2_isNameMin(const ENCODING * enc,const char * p)906 big2_isNameMin(const ENCODING *enc, const char *p) {
907 UNUSED_P(enc);
908 return BIG2_IS_NAME_CHAR_MINBPC(p);
909 }
910
911 static int PTRFASTCALL
big2_isNmstrtMin(const ENCODING * enc,const char * p)912 big2_isNmstrtMin(const ENCODING *enc, const char *p) {
913 UNUSED_P(enc);
914 return BIG2_IS_NMSTRT_CHAR_MINBPC(p);
915 }
916
917 # undef VTABLE
918 # define VTABLE VTABLE1, big2_toUtf8, big2_toUtf16
919
920 #else /* not XML_MIN_SIZE */
921
922 # undef PREFIX
923 # define PREFIX(ident) big2_##ident
924 # define MINBPC(enc) 2
925 /* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
926 # define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p)
927 # define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(p)
928 # define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(p, c)
929 # define IS_NAME_CHAR(enc, p, n) 0
930 # define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(p)
931 # define IS_NMSTRT_CHAR(enc, p, n) (0)
932 # define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(p)
933
934 # define XML_TOK_IMPL_C
935 # include "xmltok_impl.c"
936 # undef XML_TOK_IMPL_C
937
938 # undef MINBPC
939 # undef BYTE_TYPE
940 # undef BYTE_TO_ASCII
941 # undef CHAR_MATCHES
942 # undef IS_NAME_CHAR
943 # undef IS_NAME_CHAR_MINBPC
944 # undef IS_NMSTRT_CHAR
945 # undef IS_NMSTRT_CHAR_MINBPC
946 # undef IS_INVALID_CHAR
947
948 #endif /* not XML_MIN_SIZE */
949
950 #ifdef XML_NS
951
952 static const struct normal_encoding big2_encoding_ns
953 = {{VTABLE, 2, 0,
954 # if BYTEORDER == 4321
955 1
956 # else
957 0
958 # endif
959 },
960 {
961 # include "asciitab.h"
962 # include "latin1tab.h"
963 },
964 STANDARD_VTABLE(big2_) NULL_VTABLE};
965
966 #endif
967
968 static const struct normal_encoding big2_encoding
969 = {{VTABLE, 2, 0,
970 #if BYTEORDER == 4321
971 1
972 #else
973 0
974 #endif
975 },
976 {
977 #define BT_COLON BT_NMSTRT
978 #include "asciitab.h"
979 #undef BT_COLON
980 #include "latin1tab.h"
981 },
982 STANDARD_VTABLE(big2_) NULL_VTABLE};
983
984 #if BYTEORDER != 1234
985
986 # ifdef XML_NS
987
988 static const struct normal_encoding internal_big2_encoding_ns
989 = {{VTABLE, 2, 0, 1},
990 {
991 # include "iasciitab.h"
992 # include "latin1tab.h"
993 },
994 STANDARD_VTABLE(big2_) NULL_VTABLE};
995
996 # endif
997
998 static const struct normal_encoding internal_big2_encoding
999 = {{VTABLE, 2, 0, 1},
1000 {
1001 # define BT_COLON BT_NMSTRT
1002 # include "iasciitab.h"
1003 # undef BT_COLON
1004 # include "latin1tab.h"
1005 },
1006 STANDARD_VTABLE(big2_) NULL_VTABLE};
1007
1008 #endif
1009
1010 #undef PREFIX
1011
1012 static int FASTCALL
streqci(const char * s1,const char * s2)1013 streqci(const char *s1, const char *s2) {
1014 for (;;) {
1015 char c1 = *s1++;
1016 char c2 = *s2++;
1017 if (ASCII_a <= c1 && c1 <= ASCII_z)
1018 c1 += ASCII_A - ASCII_a;
1019 if (ASCII_a <= c2 && c2 <= ASCII_z)
1020 /* The following line will never get executed. streqci() is
1021 * only called from two places, both of which guarantee to put
1022 * upper-case strings into s2.
1023 */
1024 c2 += ASCII_A - ASCII_a; /* LCOV_EXCL_LINE */
1025 if (c1 != c2)
1026 return 0;
1027 if (! c1)
1028 break;
1029 }
1030 return 1;
1031 }
1032
1033 static void PTRCALL
initUpdatePosition(const ENCODING * enc,const char * ptr,const char * end,POSITION * pos)1034 initUpdatePosition(const ENCODING *enc, const char *ptr, const char *end,
1035 POSITION *pos) {
1036 UNUSED_P(enc);
1037 normal_updatePosition(&utf8_encoding.enc, ptr, end, pos);
1038 }
1039
1040 static int
toAscii(const ENCODING * enc,const char * ptr,const char * end)1041 toAscii(const ENCODING *enc, const char *ptr, const char *end) {
1042 char buf[1];
1043 char *p = buf;
1044 XmlUtf8Convert(enc, &ptr, end, &p, p + 1);
1045 if (p == buf)
1046 return -1;
1047 else
1048 return buf[0];
1049 }
1050
1051 static int FASTCALL
isSpace(int c)1052 isSpace(int c) {
1053 switch (c) {
1054 case 0x20:
1055 case 0xD:
1056 case 0xA:
1057 case 0x9:
1058 return 1;
1059 }
1060 return 0;
1061 }
1062
1063 /* Return 1 if there's just optional white space or there's an S
1064 followed by name=val.
1065 */
1066 static int
parsePseudoAttribute(const ENCODING * enc,const char * ptr,const char * end,const char ** namePtr,const char ** nameEndPtr,const char ** valPtr,const char ** nextTokPtr)1067 parsePseudoAttribute(const ENCODING *enc, const char *ptr, const char *end,
1068 const char **namePtr, const char **nameEndPtr,
1069 const char **valPtr, const char **nextTokPtr) {
1070 int c;
1071 char open;
1072 if (ptr == end) {
1073 *namePtr = NULL;
1074 return 1;
1075 }
1076 if (! isSpace(toAscii(enc, ptr, end))) {
1077 *nextTokPtr = ptr;
1078 return 0;
1079 }
1080 do {
1081 ptr += enc->minBytesPerChar;
1082 } while (isSpace(toAscii(enc, ptr, end)));
1083 if (ptr == end) {
1084 *namePtr = NULL;
1085 return 1;
1086 }
1087 *namePtr = ptr;
1088 for (;;) {
1089 c = toAscii(enc, ptr, end);
1090 if (c == -1) {
1091 *nextTokPtr = ptr;
1092 return 0;
1093 }
1094 if (c == ASCII_EQUALS) {
1095 *nameEndPtr = ptr;
1096 break;
1097 }
1098 if (isSpace(c)) {
1099 *nameEndPtr = ptr;
1100 do {
1101 ptr += enc->minBytesPerChar;
1102 } while (isSpace(c = toAscii(enc, ptr, end)));
1103 if (c != ASCII_EQUALS) {
1104 *nextTokPtr = ptr;
1105 return 0;
1106 }
1107 break;
1108 }
1109 ptr += enc->minBytesPerChar;
1110 }
1111 if (ptr == *namePtr) {
1112 *nextTokPtr = ptr;
1113 return 0;
1114 }
1115 ptr += enc->minBytesPerChar;
1116 c = toAscii(enc, ptr, end);
1117 while (isSpace(c)) {
1118 ptr += enc->minBytesPerChar;
1119 c = toAscii(enc, ptr, end);
1120 }
1121 if (c != ASCII_QUOT && c != ASCII_APOS) {
1122 *nextTokPtr = ptr;
1123 return 0;
1124 }
1125 open = (char)c;
1126 ptr += enc->minBytesPerChar;
1127 *valPtr = ptr;
1128 for (;; ptr += enc->minBytesPerChar) {
1129 c = toAscii(enc, ptr, end);
1130 if (c == open)
1131 break;
1132 if (! (ASCII_a <= c && c <= ASCII_z) && ! (ASCII_A <= c && c <= ASCII_Z)
1133 && ! (ASCII_0 <= c && c <= ASCII_9) && c != ASCII_PERIOD
1134 && c != ASCII_MINUS && c != ASCII_UNDERSCORE) {
1135 *nextTokPtr = ptr;
1136 return 0;
1137 }
1138 }
1139 *nextTokPtr = ptr + enc->minBytesPerChar;
1140 return 1;
1141 }
1142
1143 static const char KW_version[]
1144 = {ASCII_v, ASCII_e, ASCII_r, ASCII_s, ASCII_i, ASCII_o, ASCII_n, '\0'};
1145
1146 static const char KW_encoding[] = {ASCII_e, ASCII_n, ASCII_c, ASCII_o, ASCII_d,
1147 ASCII_i, ASCII_n, ASCII_g, '\0'};
1148
1149 static const char KW_standalone[]
1150 = {ASCII_s, ASCII_t, ASCII_a, ASCII_n, ASCII_d, ASCII_a,
1151 ASCII_l, ASCII_o, ASCII_n, ASCII_e, '\0'};
1152
1153 static const char KW_yes[] = {ASCII_y, ASCII_e, ASCII_s, '\0'};
1154
1155 static const char KW_no[] = {ASCII_n, ASCII_o, '\0'};
1156
1157 static int
doParseXmlDecl(const ENCODING * (* encodingFinder)(const ENCODING *,const char *,const char *),int isGeneralTextEntity,const ENCODING * enc,const char * ptr,const char * end,const char ** badPtr,const char ** versionPtr,const char ** versionEndPtr,const char ** encodingName,const ENCODING ** encoding,int * standalone)1158 doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *, const char *,
1159 const char *),
1160 int isGeneralTextEntity, const ENCODING *enc, const char *ptr,
1161 const char *end, const char **badPtr, const char **versionPtr,
1162 const char **versionEndPtr, const char **encodingName,
1163 const ENCODING **encoding, int *standalone) {
1164 const char *val = NULL;
1165 const char *name = NULL;
1166 const char *nameEnd = NULL;
1167 ptr += 5 * enc->minBytesPerChar;
1168 end -= 2 * enc->minBytesPerChar;
1169 if (! parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)
1170 || ! name) {
1171 *badPtr = ptr;
1172 return 0;
1173 }
1174 if (! XmlNameMatchesAscii(enc, name, nameEnd, KW_version)) {
1175 if (! isGeneralTextEntity) {
1176 *badPtr = name;
1177 return 0;
1178 }
1179 } else {
1180 if (versionPtr)
1181 *versionPtr = val;
1182 if (versionEndPtr)
1183 *versionEndPtr = ptr;
1184 /* The version number must not be empty; VersionNum requires at least
1185 one character. The encoding and standalone pseudo-attributes below
1186 already reject an empty value, so keep version consistent. */
1187 if (val == ptr - enc->minBytesPerChar) {
1188 *badPtr = val;
1189 return 0;
1190 }
1191 if (! parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
1192 *badPtr = ptr;
1193 return 0;
1194 }
1195 if (! name) {
1196 if (isGeneralTextEntity) {
1197 /* a TextDecl must have an EncodingDecl */
1198 *badPtr = ptr;
1199 return 0;
1200 }
1201 return 1;
1202 }
1203 }
1204 if (XmlNameMatchesAscii(enc, name, nameEnd, KW_encoding)) {
1205 int c = toAscii(enc, val, end);
1206 if (! (ASCII_a <= c && c <= ASCII_z) && ! (ASCII_A <= c && c <= ASCII_Z)) {
1207 *badPtr = val;
1208 return 0;
1209 }
1210 if (encodingName)
1211 *encodingName = val;
1212 if (encoding)
1213 *encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar);
1214 if (! parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
1215 *badPtr = ptr;
1216 return 0;
1217 }
1218 if (! name)
1219 return 1;
1220 }
1221 if (! XmlNameMatchesAscii(enc, name, nameEnd, KW_standalone)
1222 || isGeneralTextEntity) {
1223 *badPtr = name;
1224 return 0;
1225 }
1226 if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_yes)) {
1227 if (standalone)
1228 *standalone = 1;
1229 } else if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_no)) {
1230 if (standalone)
1231 *standalone = 0;
1232 } else {
1233 *badPtr = val;
1234 return 0;
1235 }
1236 while (isSpace(toAscii(enc, ptr, end)))
1237 ptr += enc->minBytesPerChar;
1238 if (ptr != end) {
1239 *badPtr = ptr;
1240 return 0;
1241 }
1242 return 1;
1243 }
1244
1245 static int FASTCALL
checkCharRefNumber(int result)1246 checkCharRefNumber(int result) {
1247 switch (result >> 8) {
1248 case 0xD8:
1249 case 0xD9:
1250 case 0xDA:
1251 case 0xDB:
1252 case 0xDC:
1253 case 0xDD:
1254 case 0xDE:
1255 case 0xDF:
1256 return -1;
1257 case 0:
1258 if (latin1_encoding.type[result] == BT_NONXML)
1259 return -1;
1260 break;
1261 case 0xFF:
1262 if (result == 0xFFFE || result == 0xFFFF)
1263 return -1;
1264 break;
1265 }
1266 return result;
1267 }
1268
1269 int FASTCALL
XmlUtf8Encode(int c,char * buf)1270 XmlUtf8Encode(int c, char *buf) {
1271 enum {
1272 /* minN is minimum legal resulting value for N byte sequence */
1273 min2 = 0x80,
1274 min3 = 0x800,
1275 min4 = 0x10000
1276 };
1277
1278 if (c < 0)
1279 return 0; /* LCOV_EXCL_LINE: this case is always eliminated beforehand */
1280 if (c < min2) {
1281 buf[0] = (char)(c | UTF8_cval1);
1282 return 1;
1283 }
1284 if (c < min3) {
1285 buf[0] = (char)((c >> 6) | UTF8_cval2);
1286 buf[1] = (char)((c & 0x3f) | 0x80);
1287 return 2;
1288 }
1289 if (c < min4) {
1290 buf[0] = (char)((c >> 12) | UTF8_cval3);
1291 buf[1] = (char)(((c >> 6) & 0x3f) | 0x80);
1292 buf[2] = (char)((c & 0x3f) | 0x80);
1293 return 3;
1294 }
1295 if (c < 0x110000) {
1296 buf[0] = (char)((c >> 18) | UTF8_cval4);
1297 buf[1] = (char)(((c >> 12) & 0x3f) | 0x80);
1298 buf[2] = (char)(((c >> 6) & 0x3f) | 0x80);
1299 buf[3] = (char)((c & 0x3f) | 0x80);
1300 return 4;
1301 }
1302 return 0; /* LCOV_EXCL_LINE: this case too is eliminated before calling */
1303 }
1304
1305 int FASTCALL
XmlUtf16Encode(int charNum,unsigned short * buf)1306 XmlUtf16Encode(int charNum, unsigned short *buf) {
1307 if (charNum < 0)
1308 return 0;
1309 if (charNum < 0x10000) {
1310 buf[0] = (unsigned short)charNum;
1311 return 1;
1312 }
1313 if (charNum < 0x110000) {
1314 charNum -= 0x10000;
1315 buf[0] = (unsigned short)((charNum >> 10) + 0xD800);
1316 buf[1] = (unsigned short)((charNum & 0x3FF) + 0xDC00);
1317 return 2;
1318 }
1319 return 0;
1320 }
1321
1322 struct unknown_encoding {
1323 struct normal_encoding normal;
1324 CONVERTER convert;
1325 void *userData;
1326 unsigned short utf16[256];
1327 char utf8[256][4];
1328 };
1329
1330 #define AS_UNKNOWN_ENCODING(enc) ((const struct unknown_encoding *)(enc))
1331
1332 int
XmlSizeOfUnknownEncoding(void)1333 XmlSizeOfUnknownEncoding(void) {
1334 return sizeof(struct unknown_encoding);
1335 }
1336
1337 static int PTRFASTCALL
unknown_isName(const ENCODING * enc,const char * p)1338 unknown_isName(const ENCODING *enc, const char *p) {
1339 const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
1340 int c = uenc->convert(uenc->userData, p);
1341 if (c & ~0xFFFF)
1342 return 0;
1343 return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF);
1344 }
1345
1346 static int PTRFASTCALL
unknown_isNmstrt(const ENCODING * enc,const char * p)1347 unknown_isNmstrt(const ENCODING *enc, const char *p) {
1348 const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
1349 int c = uenc->convert(uenc->userData, p);
1350 if (c & ~0xFFFF)
1351 return 0;
1352 return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF);
1353 }
1354
1355 static int PTRFASTCALL
unknown_isInvalid(const ENCODING * enc,const char * p)1356 unknown_isInvalid(const ENCODING *enc, const char *p) {
1357 const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
1358 int c = uenc->convert(uenc->userData, p);
1359 return (c & ~0xFFFF) || checkCharRefNumber(c) < 0;
1360 }
1361
1362 static enum XML_Convert_Result PTRCALL
unknown_toUtf8(const ENCODING * enc,const char ** fromP,const char * fromLim,char ** toP,const char * toLim)1363 unknown_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
1364 char **toP, const char *toLim) {
1365 const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
1366 char buf[XML_UTF8_ENCODE_MAX];
1367 for (;;) {
1368 const char *utf8;
1369 int n;
1370 if (*fromP == fromLim)
1371 return XML_CONVERT_COMPLETED;
1372 utf8 = uenc->utf8[(unsigned char)**fromP];
1373 n = *utf8++;
1374 if (n == 0) {
1375 int c = uenc->convert(uenc->userData, *fromP);
1376 n = XmlUtf8Encode(c, buf);
1377 if (n > toLim - *toP)
1378 return XML_CONVERT_OUTPUT_EXHAUSTED;
1379 utf8 = buf;
1380 *fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP]
1381 - (BT_LEAD2 - 2));
1382 } else {
1383 if (n > toLim - *toP)
1384 return XML_CONVERT_OUTPUT_EXHAUSTED;
1385 (*fromP)++;
1386 }
1387 memcpy(*toP, utf8, n);
1388 *toP += n;
1389 }
1390 }
1391
1392 static enum XML_Convert_Result PTRCALL
unknown_toUtf16(const ENCODING * enc,const char ** fromP,const char * fromLim,unsigned short ** toP,const unsigned short * toLim)1393 unknown_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim,
1394 unsigned short **toP, const unsigned short *toLim) {
1395 const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
1396 while (*fromP < fromLim && *toP < toLim) {
1397 unsigned short c = uenc->utf16[(unsigned char)**fromP];
1398 if (c == 0) {
1399 c = (unsigned short)uenc->convert(uenc->userData, *fromP);
1400 *fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP]
1401 - (BT_LEAD2 - 2));
1402 } else
1403 (*fromP)++;
1404 *(*toP)++ = c;
1405 }
1406
1407 if ((*toP == toLim) && (*fromP < fromLim))
1408 return XML_CONVERT_OUTPUT_EXHAUSTED;
1409 else
1410 return XML_CONVERT_COMPLETED;
1411 }
1412
1413 ENCODING *
XmlInitUnknownEncoding(void * mem,const int * table,CONVERTER convert,void * userData)1414 XmlInitUnknownEncoding(void *mem, const int *table, CONVERTER convert,
1415 void *userData) {
1416 int i;
1417 struct unknown_encoding *e = (struct unknown_encoding *)mem;
1418 memcpy(mem, &latin1_encoding, sizeof(struct normal_encoding));
1419 for (i = 0; i < 128; i++)
1420 if (latin1_encoding.type[i] != BT_OTHER
1421 && latin1_encoding.type[i] != BT_NONXML && table[i] != i)
1422 return 0;
1423 for (i = 0; i < 256; i++) {
1424 int c = table[i];
1425 if (c == -1) {
1426 e->normal.type[i] = BT_MALFORM;
1427 /* This shouldn't really get used. */
1428 e->utf16[i] = 0xFFFF;
1429 e->utf8[i][0] = 1;
1430 e->utf8[i][1] = 0;
1431 } else if (c < 0) {
1432 if (c < -4)
1433 return 0;
1434 /* Multi-byte sequences need a converter function */
1435 if (! convert)
1436 return 0;
1437 e->normal.type[i] = (unsigned char)(BT_LEAD2 - (c + 2));
1438 e->utf8[i][0] = 0;
1439 e->utf16[i] = 0;
1440 } else if (c < 0x80) {
1441 if (latin1_encoding.type[c] != BT_OTHER
1442 && latin1_encoding.type[c] != BT_NONXML && c != i)
1443 return 0;
1444 e->normal.type[i] = latin1_encoding.type[c];
1445 e->utf8[i][0] = 1;
1446 e->utf8[i][1] = (char)c;
1447 e->utf16[i] = (unsigned short)(c == 0 ? 0xFFFF : c);
1448 } else if (checkCharRefNumber(c) < 0) {
1449 e->normal.type[i] = BT_NONXML;
1450 /* This shouldn't really get used. */
1451 e->utf16[i] = 0xFFFF;
1452 e->utf8[i][0] = 1;
1453 e->utf8[i][1] = 0;
1454 } else {
1455 if (c > 0xFFFF)
1456 return 0;
1457 if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff))
1458 e->normal.type[i] = BT_NMSTRT;
1459 else if (UCS2_GET_NAMING(namePages, c >> 8, c & 0xff))
1460 e->normal.type[i] = BT_NAME;
1461 else
1462 e->normal.type[i] = BT_OTHER;
1463 e->utf8[i][0] = (char)XmlUtf8Encode(c, e->utf8[i] + 1);
1464 e->utf16[i] = (unsigned short)c;
1465 }
1466 }
1467 e->userData = userData;
1468 e->convert = convert;
1469 if (convert) {
1470 e->normal.isName2 = unknown_isName;
1471 e->normal.isName3 = unknown_isName;
1472 e->normal.isName4 = unknown_isName;
1473 e->normal.isNmstrt2 = unknown_isNmstrt;
1474 e->normal.isNmstrt3 = unknown_isNmstrt;
1475 e->normal.isNmstrt4 = unknown_isNmstrt;
1476 e->normal.isInvalid2 = unknown_isInvalid;
1477 e->normal.isInvalid3 = unknown_isInvalid;
1478 e->normal.isInvalid4 = unknown_isInvalid;
1479 }
1480 e->normal.enc.utf8Convert = unknown_toUtf8;
1481 e->normal.enc.utf16Convert = unknown_toUtf16;
1482 return &(e->normal.enc);
1483 }
1484
1485 /* If this enumeration is changed, getEncodingIndex and encodings
1486 must also be changed. */
1487 enum {
1488 UNKNOWN_ENC = -1,
1489 ISO_8859_1_ENC = 0,
1490 US_ASCII_ENC,
1491 UTF_8_ENC,
1492 UTF_16_ENC,
1493 UTF_16BE_ENC,
1494 UTF_16LE_ENC,
1495 /* must match encodingNames up to here */
1496 NO_ENC
1497 };
1498
1499 static const char KW_ISO_8859_1[]
1500 = {ASCII_I, ASCII_S, ASCII_O, ASCII_MINUS, ASCII_8, ASCII_8,
1501 ASCII_5, ASCII_9, ASCII_MINUS, ASCII_1, '\0'};
1502 static const char KW_US_ASCII[]
1503 = {ASCII_U, ASCII_S, ASCII_MINUS, ASCII_A, ASCII_S,
1504 ASCII_C, ASCII_I, ASCII_I, '\0'};
1505 static const char KW_UTF_8[]
1506 = {ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_8, '\0'};
1507 static const char KW_UTF_16[]
1508 = {ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, '\0'};
1509 static const char KW_UTF_16BE[]
1510 = {ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1,
1511 ASCII_6, ASCII_B, ASCII_E, '\0'};
1512 static const char KW_UTF_16LE[]
1513 = {ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1,
1514 ASCII_6, ASCII_L, ASCII_E, '\0'};
1515
1516 static int FASTCALL
getEncodingIndex(const char * name)1517 getEncodingIndex(const char *name) {
1518 static const char *const encodingNames[] = {
1519 KW_ISO_8859_1, KW_US_ASCII, KW_UTF_8, KW_UTF_16, KW_UTF_16BE, KW_UTF_16LE,
1520 };
1521 int i;
1522 if (name == NULL)
1523 return NO_ENC;
1524 for (i = 0; i < (int)(sizeof(encodingNames) / sizeof(encodingNames[0])); i++)
1525 if (streqci(name, encodingNames[i]))
1526 return i;
1527 return UNKNOWN_ENC;
1528 }
1529
1530 /* For binary compatibility, we store the index of the encoding
1531 specified at initialization in the isUtf16 member.
1532 */
1533
1534 #define INIT_ENC_INDEX(enc) ((int)(enc)->initEnc.isUtf16)
1535 #define SET_INIT_ENC_INDEX(enc, i) ((enc)->initEnc.isUtf16 = (char)i)
1536
1537 /* This is what detects the encoding. encodingTable maps from
1538 encoding indices to encodings; INIT_ENC_INDEX(enc) is the index of
1539 the external (protocol) specified encoding; state is
1540 XML_CONTENT_STATE if we're parsing an external text entity, and
1541 XML_PROLOG_STATE otherwise.
1542 */
1543
1544 static int
initScan(const ENCODING * const * encodingTable,const INIT_ENCODING * enc,int state,const char * ptr,const char * end,const char ** nextTokPtr)1545 initScan(const ENCODING *const *encodingTable, const INIT_ENCODING *enc,
1546 int state, const char *ptr, const char *end, const char **nextTokPtr) {
1547 const ENCODING **encPtr;
1548
1549 if (ptr >= end)
1550 return XML_TOK_NONE;
1551 encPtr = enc->encPtr;
1552 if (ptr + 1 == end) {
1553 /* only a single byte available for auto-detection */
1554 #ifndef XML_DTD /* FIXME */
1555 /* a well-formed document entity must have more than one byte */
1556 if (state != XML_CONTENT_STATE)
1557 return XML_TOK_PARTIAL;
1558 #endif
1559 /* so we're parsing an external text entity... */
1560 /* if UTF-16 was externally specified, then we need at least 2 bytes */
1561 switch (INIT_ENC_INDEX(enc)) {
1562 case UTF_16_ENC:
1563 case UTF_16LE_ENC:
1564 case UTF_16BE_ENC:
1565 return XML_TOK_PARTIAL;
1566 }
1567 switch ((unsigned char)*ptr) {
1568 case 0xFE:
1569 case 0xFF:
1570 case 0xEF: /* possibly first byte of UTF-8 BOM */
1571 if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
1572 break;
1573 EXPAT_FALLTHROUGH;
1574 case 0x00:
1575 case 0x3C:
1576 return XML_TOK_PARTIAL;
1577 }
1578 } else {
1579 switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) {
1580 case 0xFEFF:
1581 if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
1582 break;
1583 *nextTokPtr = ptr + 2;
1584 *encPtr = encodingTable[UTF_16BE_ENC];
1585 return XML_TOK_BOM;
1586 /* 00 3C is handled in the default case */
1587 case 0x3C00:
1588 if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC
1589 || INIT_ENC_INDEX(enc) == UTF_16_ENC)
1590 && state == XML_CONTENT_STATE)
1591 break;
1592 *encPtr = encodingTable[UTF_16LE_ENC];
1593 return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1594 case 0xFFFE:
1595 if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
1596 break;
1597 *nextTokPtr = ptr + 2;
1598 *encPtr = encodingTable[UTF_16LE_ENC];
1599 return XML_TOK_BOM;
1600 case 0xEFBB:
1601 /* Maybe a UTF-8 BOM (EF BB BF) */
1602 /* If there's an explicitly specified (external) encoding
1603 of ISO-8859-1 or some flavour of UTF-16
1604 and this is an external text entity,
1605 don't look for the BOM,
1606 because it might be a legal data.
1607 */
1608 if (state == XML_CONTENT_STATE) {
1609 int e = INIT_ENC_INDEX(enc);
1610 if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC || e == UTF_16LE_ENC
1611 || e == UTF_16_ENC)
1612 break;
1613 }
1614 if (ptr + 2 == end)
1615 return XML_TOK_PARTIAL;
1616 if ((unsigned char)ptr[2] == 0xBF) {
1617 *nextTokPtr = ptr + 3;
1618 *encPtr = encodingTable[UTF_8_ENC];
1619 return XML_TOK_BOM;
1620 }
1621 break;
1622 default:
1623 if (ptr[0] == '\0') {
1624 /* 0 isn't a legal data character. Furthermore a document
1625 entity can only start with ASCII characters. So the only
1626 way this can fail to be big-endian UTF-16 if it it's an
1627 external parsed general entity that's labelled as
1628 UTF-16LE.
1629 */
1630 if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC)
1631 break;
1632 *encPtr = encodingTable[UTF_16BE_ENC];
1633 return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1634 } else if (ptr[1] == '\0') {
1635 /* We could recover here in the case:
1636 - parsing an external entity
1637 - second byte is 0
1638 - no externally specified encoding
1639 - no encoding declaration
1640 by assuming UTF-16LE. But we don't, because this would mean when
1641 presented just with a single byte, we couldn't reliably determine
1642 whether we needed further bytes.
1643 */
1644 if (state == XML_CONTENT_STATE)
1645 break;
1646 *encPtr = encodingTable[UTF_16LE_ENC];
1647 return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1648 }
1649 break;
1650 }
1651 }
1652 *encPtr = encodingTable[INIT_ENC_INDEX(enc)];
1653 return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1654 }
1655
1656 #define NS(x) x
1657 #define ns(x) x
1658 #define XML_TOK_NS_C
1659 #include "xmltok_ns.c"
1660 #undef XML_TOK_NS_C
1661 #undef NS
1662 #undef ns
1663
1664 #ifdef XML_NS
1665
1666 # define NS(x) x##NS
1667 # define ns(x) x##_ns
1668
1669 # define XML_TOK_NS_C
1670 # include "xmltok_ns.c"
1671 # undef XML_TOK_NS_C
1672
1673 # undef NS
1674 # undef ns
1675
1676 ENCODING *
XmlInitUnknownEncodingNS(void * mem,const int * table,CONVERTER convert,void * userData)1677 XmlInitUnknownEncodingNS(void *mem, const int *table, CONVERTER convert,
1678 void *userData) {
1679 ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData);
1680 if (enc)
1681 ((struct normal_encoding *)enc)->type[ASCII_COLON] = BT_COLON;
1682 return enc;
1683 }
1684
1685 #endif /* XML_NS */
1686