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