Coverage Report

Created: 2026-10-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libexpat/expat/lib/xmltok.c
Line
Count
Source
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
411k
  (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
3.79k
  (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3)                         \
95
3.79k
                + ((((byte)[0]) & 3) << 1) + ((((byte)[1]) >> 5) & 1)]         \
96
3.79k
   & (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
7.13k
  (namingBitmap                                                                \
105
7.13k
       [((pages)[((((byte)[0]) & 0xF) << 4) + ((((byte)[1]) >> 2) & 0xF)]      \
106
7.13k
         << 3)                                                                 \
107
7.13k
        + ((((byte)[1]) & 3) << 1) + ((((byte)[2]) >> 5) & 1)]                 \
108
7.13k
   & (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
11.9k
  ((*p) < 0xC2 || ((p)[1] & 0x80) == 0 || ((p)[1] & 0xC0) == 0xC0)
122
123
#define UTF8_INVALID3(p)                                                       \
124
22.9k
  (((p)[2] & 0x80) == 0                                                        \
125
22.9k
   || ((*p) == 0xEF && (p)[1] == 0xBF ? (p)[2] > 0xBD                          \
126
21.0k
                                      : ((p)[2] & 0xC0) == 0xC0)               \
127
22.9k
   || ((*p) == 0xE0                                                            \
128
20.3k
           ? (p)[1] < 0xA0 || ((p)[1] & 0xC0) == 0xC0                          \
129
20.3k
           : ((p)[1] & 0x80) == 0                                              \
130
20.0k
                 || ((*p) == 0xED ? (p)[1] > 0x9F : ((p)[1] & 0xC0) == 0xC0)))
131
132
#define UTF8_INVALID4(p)                                                       \
133
6.28k
  (((p)[3] & 0x80) == 0 || ((p)[3] & 0xC0) == 0xC0 || ((p)[2] & 0x80) == 0     \
134
6.28k
   || ((p)[2] & 0xC0) == 0xC0                                                  \
135
6.28k
   || ((*p) == 0xF0                                                            \
136
3.86k
           ? (p)[1] < 0x90 || ((p)[1] & 0xC0) == 0xC0                          \
137
3.86k
           : ((p)[1] & 0x80) == 0                                              \
138
3.14k
                 || ((*p) == 0xF4 ? (p)[1] > 0x8F : ((p)[1] & 0xC0) == 0xC0)))
139
140
static int
141
1.14k
isNever(const ENCODING *enc, const char *p) {
142
1.14k
  UNUSED_P(enc);
143
1.14k
  UNUSED_P(p);
144
1.14k
  return 0;
145
1.14k
}
146
147
static int
148
2.08k
utf8_isName2(const ENCODING *enc, const char *p) {
149
2.08k
  UNUSED_P(enc);
150
2.08k
  return UTF8_GET_NAMING2(namePages, (const unsigned char *)p);
151
2.08k
}
152
153
static int
154
4.96k
utf8_isName3(const ENCODING *enc, const char *p) {
155
4.96k
  UNUSED_P(enc);
156
4.96k
  return UTF8_GET_NAMING3(namePages, (const unsigned char *)p);
157
4.96k
}
158
159
#define utf8_isName4 isNever
160
161
static int
162
1.71k
utf8_isNmstrt2(const ENCODING *enc, const char *p) {
163
1.71k
  UNUSED_P(enc);
164
1.71k
  return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p);
165
1.71k
}
166
167
static int
168
2.16k
utf8_isNmstrt3(const ENCODING *enc, const char *p) {
169
2.16k
  UNUSED_P(enc);
170
2.16k
  return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p);
171
2.16k
}
172
173
#define utf8_isNmstrt4 isNever
174
175
static int
176
11.9k
utf8_isInvalid2(const ENCODING *enc, const char *p) {
177
11.9k
  UNUSED_P(enc);
178
11.9k
  return UTF8_INVALID2((const unsigned char *)p);
179
11.9k
}
180
181
static int
182
22.9k
utf8_isInvalid3(const ENCODING *enc, const char *p) {
183
22.9k
  UNUSED_P(enc);
184
22.9k
  return UTF8_INVALID3((const unsigned char *)p);
185
22.9k
}
186
187
static int
188
6.28k
utf8_isInvalid4(const ENCODING *enc, const char *p) {
189
6.28k
  UNUSED_P(enc);
190
6.28k
  return UTF8_INVALID4((const unsigned char *)p);
191
6.28k
}
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
53.1k
#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
41.4M
#define MINBPC(enc) 1
229
230
#define SB_BYTE_TYPE(enc, p)                                                   \
231
26.8M
  (((const struct normal_encoding *)(enc))->type[(unsigned char)*(p)])
232
233
26.1M
#define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p)
234
235
85.7k
#define BYTE_TO_ASCII(enc, p) (*(p))
236
237
7.65k
#define IS_NAME_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isName##n(enc, p))
238
4.41k
#define IS_NMSTRT_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isNmstrt##n(enc, p))
239
#define IS_INVALID_CHAR(enc, p, n)                                             \
240
57.5k
  (AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p))
241
242
0
#define IS_NAME_CHAR_MINBPC(enc, p) (0)
243
0
#define IS_NMSTRT_CHAR_MINBPC(enc, p) (0)
244
245
/* c is an ASCII character */
246
98.7k
#define CHAR_MATCHES(enc, p, c) (*(p) == (c))
247
248
234k
#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
314k
                                           const char **fromLimRef) {
273
314k
  const char *fromLim = *fromLimRef;
274
314k
  size_t walked = 0;
275
316k
  for (; fromLim > from; fromLim--, walked++) {
276
311k
    const unsigned char prev = (unsigned char)fromLim[-1];
277
311k
    if ((prev & 0xf8u)
278
311k
        == 0xf0u) { /* 4-byte character, lead by 0b11110xxx byte */
279
481
      if (walked + 1 >= 4) {
280
412
        fromLim += 4 - 1;
281
412
        break;
282
412
      } else {
283
69
        walked = 0;
284
69
      }
285
311k
    } else if ((prev & 0xf0u)
286
311k
               == 0xe0u) { /* 3-byte character, lead by 0b1110xxxx byte */
287
328
      if (walked + 1 >= 3) {
288
206
        fromLim += 3 - 1;
289
206
        break;
290
206
      } else {
291
122
        walked = 0;
292
122
      }
293
310k
    } else if ((prev & 0xe0u)
294
310k
               == 0xc0u) { /* 2-byte character, lead by 0b110xxxxx byte */
295
589
      if (walked + 1 >= 2) {
296
387
        fromLim += 2 - 1;
297
387
        break;
298
387
      } else {
299
202
        walked = 0;
300
202
      }
301
310k
    } else if ((prev & 0x80u)
302
310k
               == 0x00u) { /* 1-byte character, matching 0b0xxxxxxx */
303
308k
      break;
304
308k
    }
305
311k
  }
306
314k
  *fromLimRef = fromLim;
307
314k
}
308
309
static enum XML_Convert_Result
310
utf8_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
311
314k
            char **toP, const char *toLim) {
312
314k
  bool input_incomplete = false;
313
314k
  bool output_exhausted = false;
314
315
  /* Avoid copying partial characters (due to limited space). */
316
314k
  const ptrdiff_t bytesAvailable = fromLim - *fromP;
317
314k
  const ptrdiff_t bytesStorable = toLim - *toP;
318
314k
  UNUSED_P(enc);
319
314k
  if (bytesAvailable > bytesStorable) {
320
34.4k
    fromLim = *fromP + bytesStorable;
321
34.4k
    output_exhausted = true;
322
34.4k
  }
323
324
  /* Avoid copying partial characters (from incomplete input). */
325
314k
  {
326
314k
    const char *const fromLimBefore = fromLim;
327
314k
    _INTERNAL_trim_to_complete_utf8_characters(*fromP, &fromLim);
328
314k
    if (fromLim < fromLimBefore) {
329
393
      input_incomplete = true;
330
393
    }
331
314k
  }
332
333
314k
  {
334
314k
    const ptrdiff_t bytesToCopy = fromLim - *fromP;
335
314k
    memcpy(*toP, *fromP, bytesToCopy);
336
314k
    *fromP += bytesToCopy;
337
314k
    *toP += bytesToCopy;
338
314k
  }
339
340
314k
  if (output_exhausted) /* needs to go first */
341
34.4k
    return XML_CONVERT_OUTPUT_EXHAUSTED;
342
279k
  else if (input_incomplete)
343
0
    return XML_CONVERT_INPUT_INCOMPLETE;
344
279k
  else
345
279k
    return XML_CONVERT_COMPLETED;
346
314k
}
347
348
static enum XML_Convert_Result
349
utf8_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim,
350
0
             unsigned short **toP, const unsigned short *toLim) {
351
0
  enum XML_Convert_Result res = XML_CONVERT_COMPLETED;
352
0
  unsigned short *to = *toP;
353
0
  const char *from = *fromP;
354
0
  while (from < fromLim && to < toLim) {
355
0
    switch (SB_BYTE_TYPE(enc, from)) {
356
0
    case BT_LEAD2:
357
0
      if (fromLim - from < 2) {
358
0
        res = XML_CONVERT_INPUT_INCOMPLETE;
359
0
        goto after;
360
0
      }
361
0
      *to++ = (unsigned short)(((from[0] & 0x1f) << 6) | (from[1] & 0x3f));
362
0
      from += 2;
363
0
      break;
364
0
    case BT_LEAD3:
365
0
      if (fromLim - from < 3) {
366
0
        res = XML_CONVERT_INPUT_INCOMPLETE;
367
0
        goto after;
368
0
      }
369
0
      *to++ = (unsigned short)(((from[0] & 0xf) << 12) | ((from[1] & 0x3f) << 6)
370
0
                               | (from[2] & 0x3f));
371
0
      from += 3;
372
0
      break;
373
0
    case BT_LEAD4: {
374
0
      unsigned long n;
375
0
      if (toLim - to < 2) {
376
0
        res = XML_CONVERT_OUTPUT_EXHAUSTED;
377
0
        goto after;
378
0
      }
379
0
      if (fromLim - from < 4) {
380
0
        res = XML_CONVERT_INPUT_INCOMPLETE;
381
0
        goto after;
382
0
      }
383
0
      n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12)
384
0
          | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f);
385
0
      n -= 0x10000;
386
0
      to[0] = (unsigned short)((n >> 10) | 0xD800);
387
0
      to[1] = (unsigned short)((n & 0x3FF) | 0xDC00);
388
0
      to += 2;
389
0
      from += 4;
390
0
    } break;
391
0
    default:
392
0
      *to++ = *from++;
393
0
      break;
394
0
    }
395
0
  }
396
0
  if (from < fromLim)
397
0
    res = XML_CONVERT_OUTPUT_EXHAUSTED;
398
0
after:
399
0
  *fromP = from;
400
0
  *toP = to;
401
0
  return res;
402
0
}
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
0
              char **toP, const char *toLim) {
449
0
  UNUSED_P(enc);
450
0
  for (;;) {
451
0
    unsigned char c;
452
0
    if (*fromP == fromLim)
453
0
      return XML_CONVERT_COMPLETED;
454
0
    c = (unsigned char)**fromP;
455
0
    if (c & 0x80) {
456
0
      if (toLim - *toP < 2)
457
0
        return XML_CONVERT_OUTPUT_EXHAUSTED;
458
0
      *(*toP)++ = (char)((c >> 6) | UTF8_cval2);
459
0
      *(*toP)++ = (char)((c & 0x3f) | 0x80);
460
0
      (*fromP)++;
461
0
    } else {
462
0
      if (*toP == toLim)
463
0
        return XML_CONVERT_OUTPUT_EXHAUSTED;
464
0
      *(*toP)++ = *(*fromP)++;
465
0
    }
466
0
  }
467
0
}
468
469
static enum XML_Convert_Result
470
latin1_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim,
471
0
               unsigned short **toP, const unsigned short *toLim) {
472
0
  UNUSED_P(enc);
473
0
  while (*fromP < fromLim && *toP < toLim)
474
0
    *(*toP)++ = (unsigned char)*(*fromP)++;
475
476
0
  if ((*toP == toLim) && (*fromP < fromLim))
477
0
    return XML_CONVERT_OUTPUT_EXHAUSTED;
478
0
  else
479
0
    return XML_CONVERT_COMPLETED;
480
0
}
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
0
             char **toP, const char *toLim) {
507
0
  UNUSED_P(enc);
508
0
  while (*fromP < fromLim && *toP < toLim)
509
0
    *(*toP)++ = *(*fromP)++;
510
511
0
  if ((*toP == toLim) && (*fromP < fromLim))
512
0
    return XML_CONVERT_OUTPUT_EXHAUSTED;
513
0
  else
514
0
    return XML_CONVERT_COMPLETED;
515
0
}
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
1.86M
unicode_byte_type(char hi, char lo) {
541
1.86M
  switch ((unsigned char)hi) {
542
  /* 0xD800-0xDBFF first 16-bit code unit or high surrogate (W1) */
543
6.96k
  case 0xD8:
544
11.3k
  case 0xD9:
545
14.6k
  case 0xDA:
546
17.9k
  case 0xDB:
547
17.9k
    return BT_LEAD4;
548
  /* 0xDC00-0xDFFF second 16-bit code unit or low surrogate (W2) */
549
3.04k
  case 0xDC:
550
6.03k
  case 0xDD:
551
9.29k
  case 0xDE:
552
12.6k
  case 0xDF:
553
12.6k
    return BT_TRAIL;
554
23.3k
  case 0xFF:
555
23.3k
    switch ((unsigned char)lo) {
556
4.09k
    case 0xFF: /* noncharacter-FFFF */
557
4.32k
    case 0xFE: /* noncharacter-FFFE */
558
4.32k
      return BT_NONXML;
559
23.3k
    }
560
18.9k
    break;
561
1.86M
  }
562
1.83M
  return BT_NONASCII;
563
1.86M
}
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
22.4k
      char **toP, const char *toLim) {                                         \
569
22.4k
    const char *from = *fromP;                                                 \
570
22.4k
    UNUSED_P(enc);                                                             \
571
22.4k
    fromLim = from + (((fromLim - from) >> 1) << 1); /* shrink to even */      \
572
139k
    for (; from < fromLim; from += 2) {                                        \
573
118k
      int plane;                                                               \
574
118k
      unsigned char lo2;                                                       \
575
118k
      unsigned char lo = GET_LO(from);                                         \
576
118k
      unsigned char hi = GET_HI(from);                                         \
577
118k
      switch (hi) {                                                            \
578
25.9k
      case 0:                                                                  \
579
25.9k
        if (lo < 0x80) {                                                       \
580
23.7k
          if (*toP == toLim) {                                                 \
581
120
            *fromP = from;                                                     \
582
120
            return XML_CONVERT_OUTPUT_EXHAUSTED;                               \
583
120
          }                                                                    \
584
23.7k
          *(*toP)++ = lo;                                                      \
585
23.6k
          break;                                                               \
586
23.7k
        }                                                                      \
587
25.9k
        EXPAT_FALLTHROUGH;                                                     \
588
3.15k
      case 0x1:                                                                \
589
6.08k
      case 0x2:                                                                \
590
6.87k
      case 0x3:                                                                \
591
10.2k
      case 0x4:                                                                \
592
10.4k
      case 0x5:                                                                \
593
10.8k
      case 0x6:                                                                \
594
11.3k
      case 0x7:                                                                \
595
11.3k
        if (toLim - *toP < 2) {                                                \
596
143
          *fromP = from;                                                       \
597
143
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
598
143
        }                                                                      \
599
11.3k
        *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2);                      \
600
11.1k
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
601
11.1k
        break;                                                                 \
602
82.7k
      default:                                                                 \
603
82.7k
        if (toLim - *toP < 3) {                                                \
604
972
          *fromP = from;                                                       \
605
972
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
606
972
        }                                                                      \
607
82.7k
        /* 16 bits divided 4, 6, 6 amongst 3 bytes */                          \
608
82.7k
        *(*toP)++ = ((hi >> 4) | UTF8_cval3);                                  \
609
81.7k
        *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80);                    \
610
81.7k
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
611
81.7k
        break;                                                                 \
612
82.7k
      case 0xD8:                                                               \
613
123
      case 0xD9:                                                               \
614
157
      case 0xDA:                                                               \
615
200
      case 0xDB:                                                               \
616
200
        if (toLim - *toP < 4) {                                                \
617
0
          *fromP = from;                                                       \
618
0
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
619
0
        }                                                                      \
620
200
        if (fromLim - from < 4) {                                              \
621
0
          *fromP = from;                                                       \
622
0
          return XML_CONVERT_INPUT_INCOMPLETE;                                 \
623
0
        }                                                                      \
624
200
        plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1;                   \
625
200
        *(*toP)++ = (char)((plane >> 2) | UTF8_cval4);                         \
626
200
        *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80);         \
627
200
        from += 2;                                                             \
628
200
        lo2 = GET_LO(from);                                                    \
629
200
        *(*toP)++ = (((lo & 0x3) << 4) | ((GET_HI(from) & 0x3) << 2)           \
630
200
                     | (lo2 >> 6) | 0x80);                                     \
631
200
        *(*toP)++ = ((lo2 & 0x3f) | 0x80);                                     \
632
200
        break;                                                                 \
633
118k
      }                                                                        \
634
118k
    }                                                                          \
635
22.4k
    *fromP = from;                                                             \
636
21.2k
    if (from < fromLim)                                                        \
637
21.2k
      return XML_CONVERT_INPUT_INCOMPLETE;                                     \
638
21.2k
    else                                                                       \
639
21.2k
      return XML_CONVERT_COMPLETED;                                            \
640
21.2k
  }
xmltok.c:little2_toUtf8
Line
Count
Source
568
17.0k
      char **toP, const char *toLim) {                                         \
569
17.0k
    const char *from = *fromP;                                                 \
570
17.0k
    UNUSED_P(enc);                                                             \
571
17.0k
    fromLim = from + (((fromLim - from) >> 1) << 1); /* shrink to even */      \
572
80.5k
    for (; from < fromLim; from += 2) {                                        \
573
63.7k
      int plane;                                                               \
574
63.7k
      unsigned char lo2;                                                       \
575
63.7k
      unsigned char lo = GET_LO(from);                                         \
576
63.7k
      unsigned char hi = GET_HI(from);                                         \
577
63.7k
      switch (hi) {                                                            \
578
16.6k
      case 0:                                                                  \
579
16.6k
        if (lo < 0x80) {                                                       \
580
16.1k
          if (*toP == toLim) {                                                 \
581
74
            *fromP = from;                                                     \
582
74
            return XML_CONVERT_OUTPUT_EXHAUSTED;                               \
583
74
          }                                                                    \
584
16.1k
          *(*toP)++ = lo;                                                      \
585
16.0k
          break;                                                               \
586
16.1k
        }                                                                      \
587
16.6k
        EXPAT_FALLTHROUGH;                                                     \
588
1.08k
      case 0x1:                                                                \
589
3.65k
      case 0x2:                                                                \
590
4.17k
      case 0x3:                                                                \
591
7.32k
      case 0x4:                                                                \
592
7.43k
      case 0x5:                                                                \
593
7.50k
      case 0x6:                                                                \
594
7.91k
      case 0x7:                                                                \
595
7.91k
        if (toLim - *toP < 2) {                                                \
596
80
          *fromP = from;                                                       \
597
80
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
598
80
        }                                                                      \
599
7.91k
        *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2);                      \
600
7.83k
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
601
7.83k
        break;                                                                 \
602
39.6k
      default:                                                                 \
603
39.6k
        if (toLim - *toP < 3) {                                                \
604
116
          *fromP = from;                                                       \
605
116
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
606
116
        }                                                                      \
607
39.6k
        /* 16 bits divided 4, 6, 6 amongst 3 bytes */                          \
608
39.6k
        *(*toP)++ = ((hi >> 4) | UTF8_cval3);                                  \
609
39.4k
        *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80);                    \
610
39.4k
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
611
39.4k
        break;                                                                 \
612
39.6k
      case 0xD8:                                                               \
613
81
      case 0xD9:                                                               \
614
108
      case 0xDA:                                                               \
615
144
      case 0xDB:                                                               \
616
144
        if (toLim - *toP < 4) {                                                \
617
0
          *fromP = from;                                                       \
618
0
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
619
0
        }                                                                      \
620
144
        if (fromLim - from < 4) {                                              \
621
0
          *fromP = from;                                                       \
622
0
          return XML_CONVERT_INPUT_INCOMPLETE;                                 \
623
0
        }                                                                      \
624
144
        plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1;                   \
625
144
        *(*toP)++ = (char)((plane >> 2) | UTF8_cval4);                         \
626
144
        *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80);         \
627
144
        from += 2;                                                             \
628
144
        lo2 = GET_LO(from);                                                    \
629
144
        *(*toP)++ = (((lo & 0x3) << 4) | ((GET_HI(from) & 0x3) << 2)           \
630
144
                     | (lo2 >> 6) | 0x80);                                     \
631
144
        *(*toP)++ = ((lo2 & 0x3f) | 0x80);                                     \
632
144
        break;                                                                 \
633
63.7k
      }                                                                        \
634
63.7k
    }                                                                          \
635
17.0k
    *fromP = from;                                                             \
636
16.7k
    if (from < fromLim)                                                        \
637
16.7k
      return XML_CONVERT_INPUT_INCOMPLETE;                                     \
638
16.7k
    else                                                                       \
639
16.7k
      return XML_CONVERT_COMPLETED;                                            \
640
16.7k
  }
xmltok.c:big2_toUtf8
Line
Count
Source
568
5.44k
      char **toP, const char *toLim) {                                         \
569
5.44k
    const char *from = *fromP;                                                 \
570
5.44k
    UNUSED_P(enc);                                                             \
571
5.44k
    fromLim = from + (((fromLim - from) >> 1) << 1); /* shrink to even */      \
572
58.7k
    for (; from < fromLim; from += 2) {                                        \
573
54.2k
      int plane;                                                               \
574
54.2k
      unsigned char lo2;                                                       \
575
54.2k
      unsigned char lo = GET_LO(from);                                         \
576
54.2k
      unsigned char hi = GET_HI(from);                                         \
577
54.2k
      switch (hi) {                                                            \
578
9.25k
      case 0:                                                                  \
579
9.25k
        if (lo < 0x80) {                                                       \
580
7.68k
          if (*toP == toLim) {                                                 \
581
46
            *fromP = from;                                                     \
582
46
            return XML_CONVERT_OUTPUT_EXHAUSTED;                               \
583
46
          }                                                                    \
584
7.68k
          *(*toP)++ = lo;                                                      \
585
7.64k
          break;                                                               \
586
7.68k
        }                                                                      \
587
9.25k
        EXPAT_FALLTHROUGH;                                                     \
588
2.06k
      case 0x1:                                                                \
589
2.43k
      case 0x2:                                                                \
590
2.70k
      case 0x3:                                                                \
591
2.93k
      case 0x4:                                                                \
592
2.97k
      case 0x5:                                                                \
593
3.34k
      case 0x6:                                                                \
594
3.39k
      case 0x7:                                                                \
595
3.39k
        if (toLim - *toP < 2) {                                                \
596
63
          *fromP = from;                                                       \
597
63
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
598
63
        }                                                                      \
599
3.39k
        *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2);                      \
600
3.33k
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
601
3.33k
        break;                                                                 \
602
43.1k
      default:                                                                 \
603
43.1k
        if (toLim - *toP < 3) {                                                \
604
856
          *fromP = from;                                                       \
605
856
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
606
856
        }                                                                      \
607
43.1k
        /* 16 bits divided 4, 6, 6 amongst 3 bytes */                          \
608
43.1k
        *(*toP)++ = ((hi >> 4) | UTF8_cval3);                                  \
609
42.2k
        *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80);                    \
610
42.2k
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
611
42.2k
        break;                                                                 \
612
43.1k
      case 0xD8:                                                               \
613
42
      case 0xD9:                                                               \
614
49
      case 0xDA:                                                               \
615
56
      case 0xDB:                                                               \
616
56
        if (toLim - *toP < 4) {                                                \
617
0
          *fromP = from;                                                       \
618
0
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
619
0
        }                                                                      \
620
56
        if (fromLim - from < 4) {                                              \
621
0
          *fromP = from;                                                       \
622
0
          return XML_CONVERT_INPUT_INCOMPLETE;                                 \
623
0
        }                                                                      \
624
56
        plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1;                   \
625
56
        *(*toP)++ = (char)((plane >> 2) | UTF8_cval4);                         \
626
56
        *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80);         \
627
56
        from += 2;                                                             \
628
56
        lo2 = GET_LO(from);                                                    \
629
56
        *(*toP)++ = (((lo & 0x3) << 4) | ((GET_HI(from) & 0x3) << 2)           \
630
56
                     | (lo2 >> 6) | 0x80);                                     \
631
56
        *(*toP)++ = ((lo2 & 0x3f) | 0x80);                                     \
632
56
        break;                                                                 \
633
54.2k
      }                                                                        \
634
54.2k
    }                                                                          \
635
5.44k
    *fromP = from;                                                             \
636
4.48k
    if (from < fromLim)                                                        \
637
4.48k
      return XML_CONVERT_INPUT_INCOMPLETE;                                     \
638
4.48k
    else                                                                       \
639
4.48k
      return XML_CONVERT_COMPLETED;                                            \
640
4.48k
  }
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
0
      unsigned short **toP, const unsigned short *toLim) {                     \
646
0
    enum XML_Convert_Result res = XML_CONVERT_COMPLETED;                       \
647
0
    UNUSED_P(enc);                                                             \
648
0
    fromLim = *fromP + (((fromLim - *fromP) >> 1) << 1); /* shrink to even */  \
649
0
    /* Avoid copying the first half (2 bytes) of surrogate pairs (4 bytes) */  \
650
0
    if (fromLim - *fromP > ((toLim - *toP) << 1)                               \
651
0
        && /* are the last two bytes a high surrogate (0xD800-0xDBFF)? */      \
652
0
        (GET_HI(fromLim - 2) & 0xFC) == 0xD8) {                                \
653
0
      fromLim -= 2;                                                            \
654
0
      res = XML_CONVERT_INPUT_INCOMPLETE;                                      \
655
0
    }                                                                          \
656
0
    for (; *fromP < fromLim && *toP < toLim; *fromP += 2)                      \
657
0
      *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP);                      \
658
0
    if ((*toP == toLim) && (*fromP < fromLim))                                 \
659
0
      return XML_CONVERT_OUTPUT_EXHAUSTED;                                     \
660
0
    else                                                                       \
661
0
      return res;                                                              \
662
0
  }
Unexecuted instantiation: xmltok.c:little2_toUtf16
Unexecuted instantiation: xmltok.c:big2_toUtf16
663
664
63.9k
#define GET_LO(ptr) ((unsigned char)(ptr)[0])
665
63.9k
#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
54.3k
#define GET_LO(ptr) ((unsigned char)(ptr)[1])
674
54.3k
#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
1.53M
  ((p)[1] == 0 ? SB_BYTE_TYPE(enc, p) : unicode_byte_type((p)[1], (p)[0]))
684
4.69k
#define LITTLE2_BYTE_TO_ASCII(p) ((p)[1] == 0 ? (p)[0] : -1)
685
16.8k
#define LITTLE2_CHAR_MATCHES(p, c) ((p)[1] == 0 && (p)[0] == (c))
686
#define LITTLE2_IS_NAME_CHAR_MINBPC(p)                                         \
687
192k
  UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0])
688
#define LITTLE2_IS_NMSTRT_CHAR_MINBPC(p)                                       \
689
20.2k
  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
11.8k
  ((n) == 4 && ((unsigned char)(p)[3] & 0xFC) != 0xDC)
695
696
#undef PREFIX
697
64.9k
#define PREFIX(ident) little2_##ident
698
3.10M
#define MINBPC(enc) 2
699
/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
700
1.53M
#define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p)
701
4.69k
#define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(p)
702
16.8k
#define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(p, c)
703
43
#define IS_NAME_CHAR(enc, p, n) 0
704
192k
#define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(p)
705
31
#define IS_NMSTRT_CHAR(enc, p, n) (0)
706
20.2k
#define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(p)
707
7.84k
#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
1.11M
  ((p)[0] == 0 ? SB_BYTE_TYPE(enc, p + 1) : unicode_byte_type((p)[0], (p)[1]))
785
999
#define BIG2_BYTE_TO_ASCII(p) ((p)[0] == 0 ? (p)[1] : -1)
786
3.45k
#define BIG2_CHAR_MATCHES(p, c) ((p)[0] == 0 && (p)[1] == (c))
787
#define BIG2_IS_NAME_CHAR_MINBPC(p)                                            \
788
194k
  UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1])
789
#define BIG2_IS_NMSTRT_CHAR_MINBPC(p)                                          \
790
3.77k
  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
4.67k
  ((n) == 4 && ((unsigned char)(p)[2] & 0xFC) != 0xDC)
796
797
#undef PREFIX
798
16.9k
#define PREFIX(ident) big2_##ident
799
2.17M
#define MINBPC(enc) 2
800
/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
801
1.11M
#define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p)
802
999
#define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(p)
803
3.45k
#define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(p, c)
804
29
#define IS_NAME_CHAR(enc, p, n) 0
805
194k
#define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(p)
806
19
#define IS_NMSTRT_CHAR(enc, p, n) (0)
807
3.77k
#define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(p)
808
3.04k
#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
3
streqci(const char *s1, const char *s2) {
888
9
  for (;;) {
889
9
    char c1 = *s1++;
890
9
    char c2 = *s2++;
891
9
    if (ASCII_a <= c1 && c1 <= ASCII_z)
892
0
      c1 += ASCII_A - ASCII_a;
893
9
    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
0
      c2 += ASCII_A - ASCII_a; /* LCOV_EXCL_LINE */
899
9
    if (c1 != c2)
900
2
      return 0;
901
7
    if (! c1)
902
1
      break;
903
7
  }
904
1
  return 1;
905
3
}
906
907
static void
908
initUpdatePosition(const ENCODING *enc, const char *ptr, const char *end,
909
812
                   POSITION *pos) {
910
812
  UNUSED_P(enc);
911
812
  normal_updatePosition(&utf8_encoding.enc, ptr, end, pos);
912
812
}
913
914
static int
915
32.7k
toAscii(const ENCODING *enc, const char *ptr, const char *end) {
916
32.7k
  char buf[1];
917
32.7k
  char *p = buf;
918
32.7k
  XmlUtf8Convert(enc, &ptr, end, &p, p + 1);
919
32.7k
  if (p == buf)
920
473
    return -1;
921
32.2k
  else
922
32.2k
    return buf[0];
923
32.7k
}
924
925
static int
926
25.4k
isSpace(int c) {
927
25.4k
  switch (c) {
928
7.10k
  case 0x20:
929
7.98k
  case 0xD:
930
8.79k
  case 0xA:
931
9.98k
  case 0x9:
932
9.98k
    return 1;
933
25.4k
  }
934
15.5k
  return 0;
935
25.4k
}
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
1.15k
                     const char **valPtr, const char **nextTokPtr) {
944
1.15k
  int c;
945
1.15k
  char open;
946
1.15k
  if (ptr == end) {
947
34
    *namePtr = NULL;
948
34
    return 1;
949
34
  }
950
1.12k
  if (! isSpace(toAscii(enc, ptr, end))) {
951
0
    *nextTokPtr = ptr;
952
0
    return 0;
953
0
  }
954
5.35k
  do {
955
5.35k
    ptr += enc->minBytesPerChar;
956
5.35k
  } while (isSpace(toAscii(enc, ptr, end)));
957
1.12k
  if (ptr == end) {
958
72
    *namePtr = NULL;
959
72
    return 1;
960
72
  }
961
1.04k
  *namePtr = ptr;
962
14.3k
  for (;;) {
963
14.3k
    c = toAscii(enc, ptr, end);
964
14.3k
    if (c == -1) {
965
79
      *nextTokPtr = ptr;
966
79
      return 0;
967
79
    }
968
14.2k
    if (c == ASCII_EQUALS) {
969
603
      *nameEndPtr = ptr;
970
603
      break;
971
603
    }
972
13.6k
    if (isSpace(c)) {
973
366
      *nameEndPtr = ptr;
974
2.85k
      do {
975
2.85k
        ptr += enc->minBytesPerChar;
976
2.85k
      } while (isSpace(c = toAscii(enc, ptr, end)));
977
366
      if (c != ASCII_EQUALS) {
978
173
        *nextTokPtr = ptr;
979
173
        return 0;
980
173
      }
981
193
      break;
982
366
    }
983
13.2k
    ptr += enc->minBytesPerChar;
984
13.2k
  }
985
796
  if (ptr == *namePtr) {
986
46
    *nextTokPtr = ptr;
987
46
    return 0;
988
46
  }
989
750
  ptr += enc->minBytesPerChar;
990
750
  c = toAscii(enc, ptr, end);
991
2.51k
  while (isSpace(c)) {
992
1.76k
    ptr += enc->minBytesPerChar;
993
1.76k
    c = toAscii(enc, ptr, end);
994
1.76k
  }
995
750
  if (c != ASCII_QUOT && c != ASCII_APOS) {
996
203
    *nextTokPtr = ptr;
997
203
    return 0;
998
203
  }
999
547
  open = (char)c;
1000
547
  ptr += enc->minBytesPerChar;
1001
547
  *valPtr = ptr;
1002
6.53k
  for (;; ptr += enc->minBytesPerChar) {
1003
6.53k
    c = toAscii(enc, ptr, end);
1004
6.53k
    if (c == open)
1005
70
      break;
1006
6.46k
    if (! (ASCII_a <= c && c <= ASCII_z) && ! (ASCII_A <= c && c <= ASCII_Z)
1007
2.30k
        && ! (ASCII_0 <= c && c <= ASCII_9) && c != ASCII_PERIOD
1008
1.17k
        && c != ASCII_MINUS && c != ASCII_UNDERSCORE) {
1009
477
      *nextTokPtr = ptr;
1010
477
      return 0;
1011
477
    }
1012
6.46k
  }
1013
70
  *nextTokPtr = ptr + enc->minBytesPerChar;
1014
70
  return 1;
1015
547
}
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
0
                       const char *valEnd) {
1044
0
  if (valEnd - val < 2 * enc->minBytesPerChar
1045
0
      || ! XmlNameMatchesAscii(enc, val, val + 2 * enc->minBytesPerChar,
1046
0
                               KW_1_dot))
1047
0
    return false;
1048
0
  val += 2 * enc->minBytesPerChar;
1049
0
  if (val == valEnd)
1050
0
    return false;
1051
0
  for (; val != valEnd; val += enc->minBytesPerChar) {
1052
0
    int c = toAscii(enc, val, valEnd);
1053
0
    if (c < ASCII_0 || c > ASCII_9)
1054
0
      return false;
1055
0
  }
1056
0
  return true;
1057
0
}
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
1.15k
               const ENCODING **encoding, int *standalone) {
1066
1.15k
  const char *val = NULL;
1067
1.15k
  const char *name = NULL;
1068
1.15k
  const char *nameEnd = NULL;
1069
1.15k
  ptr += 5 * enc->minBytesPerChar;
1070
1.15k
  end -= 2 * enc->minBytesPerChar;
1071
1.15k
  if (! parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)
1072
1.08k
      || ! name) {
1073
1.08k
    *badPtr = ptr;
1074
1.08k
    return 0;
1075
1.08k
  }
1076
70
  if (! XmlNameMatchesAscii(enc, name, nameEnd, KW_version)) {
1077
70
    if (! isGeneralTextEntity) {
1078
70
      *badPtr = name;
1079
70
      return 0;
1080
70
    }
1081
70
  } else {
1082
0
    if (versionPtr)
1083
0
      *versionPtr = val;
1084
0
    if (versionEndPtr)
1085
0
      *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
0
    if (val == ptr - enc->minBytesPerChar) {
1090
0
      *badPtr = val;
1091
0
      return 0;
1092
0
    }
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
0
    if (! checkXmlDeclVersionNum(enc, val, ptr - enc->minBytesPerChar)) {
1099
0
      *badPtr = val;
1100
0
      return 0;
1101
0
    }
1102
0
    if (! parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
1103
0
      *badPtr = ptr;
1104
0
      return 0;
1105
0
    }
1106
0
    if (! name) {
1107
0
      if (isGeneralTextEntity) {
1108
        /* a TextDecl must have an EncodingDecl */
1109
0
        *badPtr = ptr;
1110
0
        return 0;
1111
0
      }
1112
0
      return 1;
1113
0
    }
1114
0
  }
1115
0
  if (XmlNameMatchesAscii(enc, name, nameEnd, KW_encoding)) {
1116
0
    int c = toAscii(enc, val, end);
1117
0
    if (! (ASCII_a <= c && c <= ASCII_z) && ! (ASCII_A <= c && c <= ASCII_Z)) {
1118
0
      *badPtr = val;
1119
0
      return 0;
1120
0
    }
1121
0
    if (encodingName)
1122
0
      *encodingName = val;
1123
0
    if (encoding)
1124
0
      *encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar);
1125
0
    if (! parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
1126
0
      *badPtr = ptr;
1127
0
      return 0;
1128
0
    }
1129
0
    if (! name)
1130
0
      return 1;
1131
0
  }
1132
0
  if (! XmlNameMatchesAscii(enc, name, nameEnd, KW_standalone)
1133
0
      || isGeneralTextEntity) {
1134
0
    *badPtr = name;
1135
0
    return 0;
1136
0
  }
1137
0
  if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_yes)) {
1138
0
    if (standalone)
1139
0
      *standalone = 1;
1140
0
  } else if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_no)) {
1141
0
    if (standalone)
1142
0
      *standalone = 0;
1143
0
  } else {
1144
0
    *badPtr = val;
1145
0
    return 0;
1146
0
  }
1147
0
  while (isSpace(toAscii(enc, ptr, end)))
1148
0
    ptr += enc->minBytesPerChar;
1149
0
  if (ptr != end) {
1150
0
    *badPtr = ptr;
1151
0
    return 0;
1152
0
  }
1153
0
  return 1;
1154
0
}
1155
1156
static int
1157
2.87k
checkCharRefNumber(int result) {
1158
2.87k
  switch (result >> 8) {
1159
34
  case 0xD8:
1160
88
  case 0xD9:
1161
174
  case 0xDA:
1162
214
  case 0xDB:
1163
265
  case 0xDC:
1164
329
  case 0xDD:
1165
365
  case 0xDE:
1166
399
  case 0xDF:
1167
399
    return -1;
1168
1.87k
  case 0:
1169
1.87k
    if (latin1_encoding.type[result] == BT_NONXML)
1170
1.27k
      return -1;
1171
600
    break;
1172
600
  case 0xFF:
1173
119
    if (result == 0xFFFE || result == 0xFFFF)
1174
0
      return -1;
1175
119
    break;
1176
2.87k
  }
1177
1.20k
  return result;
1178
2.87k
}
1179
1180
int
1181
141
XmlUtf8Encode(int c, char *buf) {
1182
141
  enum {
1183
    /* minN is minimum legal resulting value for N byte sequence */
1184
141
    min2 = 0x80,
1185
141
    min3 = 0x800,
1186
141
    min4 = 0x10000
1187
141
  };
1188
1189
141
  if (c < 0)
1190
0
    return 0; /* LCOV_EXCL_LINE: this case is always eliminated beforehand */
1191
141
  if (c < min2) {
1192
19
    buf[0] = (char)(c | UTF8_cval1);
1193
19
    return 1;
1194
19
  }
1195
122
  if (c < min3) {
1196
30
    buf[0] = (char)((c >> 6) | UTF8_cval2);
1197
30
    buf[1] = (char)((c & 0x3f) | 0x80);
1198
30
    return 2;
1199
30
  }
1200
92
  if (c < min4) {
1201
85
    buf[0] = (char)((c >> 12) | UTF8_cval3);
1202
85
    buf[1] = (char)(((c >> 6) & 0x3f) | 0x80);
1203
85
    buf[2] = (char)((c & 0x3f) | 0x80);
1204
85
    return 3;
1205
85
  }
1206
7
  if (c < 0x110000) {
1207
7
    buf[0] = (char)((c >> 18) | UTF8_cval4);
1208
7
    buf[1] = (char)(((c >> 12) & 0x3f) | 0x80);
1209
7
    buf[2] = (char)(((c >> 6) & 0x3f) | 0x80);
1210
7
    buf[3] = (char)((c & 0x3f) | 0x80);
1211
7
    return 4;
1212
7
  }
1213
0
  return 0; /* LCOV_EXCL_LINE: this case too is eliminated before calling */
1214
7
}
1215
1216
int
1217
0
XmlUtf16Encode(int charNum, unsigned short *buf) {
1218
0
  if (charNum < 0)
1219
0
    return 0;
1220
0
  if (charNum < 0x10000) {
1221
0
    buf[0] = (unsigned short)charNum;
1222
0
    return 1;
1223
0
  }
1224
0
  if (charNum < 0x110000) {
1225
0
    charNum -= 0x10000;
1226
0
    buf[0] = (unsigned short)((charNum >> 10) + 0xD800);
1227
0
    buf[1] = (unsigned short)((charNum & 0x3FF) + 0xDC00);
1228
0
    return 2;
1229
0
  }
1230
0
  return 0;
1231
0
}
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
0
#define AS_UNKNOWN_ENCODING(enc) ((const struct unknown_encoding *)(enc))
1242
1243
int
1244
0
XmlSizeOfUnknownEncoding(void) {
1245
0
  return sizeof(struct unknown_encoding);
1246
0
}
1247
1248
static int
1249
0
unknown_isName(const ENCODING *enc, const char *p) {
1250
0
  const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
1251
0
  int c = uenc->convert(uenc->userData, p);
1252
0
  if (c & ~0xFFFF)
1253
0
    return 0;
1254
0
  return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF);
1255
0
}
1256
1257
static int
1258
0
unknown_isNmstrt(const ENCODING *enc, const char *p) {
1259
0
  const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
1260
0
  int c = uenc->convert(uenc->userData, p);
1261
0
  if (c & ~0xFFFF)
1262
0
    return 0;
1263
0
  return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF);
1264
0
}
1265
1266
static int
1267
0
unknown_isInvalid(const ENCODING *enc, const char *p) {
1268
0
  const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
1269
0
  int c = uenc->convert(uenc->userData, p);
1270
0
  return (c & ~0xFFFF) || checkCharRefNumber(c) < 0;
1271
0
}
1272
1273
static enum XML_Convert_Result
1274
unknown_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
1275
0
               char **toP, const char *toLim) {
1276
0
  const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
1277
0
  char buf[XML_UTF8_ENCODE_MAX];
1278
0
  for (;;) {
1279
0
    const char *utf8;
1280
0
    int n;
1281
0
    if (*fromP == fromLim)
1282
0
      return XML_CONVERT_COMPLETED;
1283
0
    utf8 = uenc->utf8[(unsigned char)**fromP];
1284
0
    n = *utf8++;
1285
0
    if (n == 0) {
1286
0
      int c = uenc->convert(uenc->userData, *fromP);
1287
0
      n = XmlUtf8Encode(c, buf);
1288
0
      if (n > toLim - *toP)
1289
0
        return XML_CONVERT_OUTPUT_EXHAUSTED;
1290
0
      utf8 = buf;
1291
0
      *fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP]
1292
0
                 - (BT_LEAD2 - 2));
1293
0
    } else {
1294
0
      if (n > toLim - *toP)
1295
0
        return XML_CONVERT_OUTPUT_EXHAUSTED;
1296
0
      (*fromP)++;
1297
0
    }
1298
0
    memcpy(*toP, utf8, n);
1299
0
    *toP += n;
1300
0
  }
1301
0
}
1302
1303
static enum XML_Convert_Result
1304
unknown_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim,
1305
0
                unsigned short **toP, const unsigned short *toLim) {
1306
0
  const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
1307
0
  while (*fromP < fromLim && *toP < toLim) {
1308
0
    unsigned short c = uenc->utf16[(unsigned char)**fromP];
1309
0
    if (c == 0) {
1310
0
      c = (unsigned short)uenc->convert(uenc->userData, *fromP);
1311
0
      *fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP]
1312
0
                 - (BT_LEAD2 - 2));
1313
0
    } else
1314
0
      (*fromP)++;
1315
0
    *(*toP)++ = c;
1316
0
  }
1317
1318
0
  if ((*toP == toLim) && (*fromP < fromLim))
1319
0
    return XML_CONVERT_OUTPUT_EXHAUSTED;
1320
0
  else
1321
0
    return XML_CONVERT_COMPLETED;
1322
0
}
1323
1324
ENCODING *
1325
XmlInitUnknownEncoding(void *mem, const int *table, CONVERTER convert,
1326
0
                       void *userData) {
1327
0
  int i;
1328
0
  struct unknown_encoding *e = (struct unknown_encoding *)mem;
1329
0
  memcpy(mem, &latin1_encoding, sizeof(struct normal_encoding));
1330
0
  for (i = 0; i < 128; i++)
1331
0
    if (latin1_encoding.type[i] != BT_OTHER
1332
0
        && latin1_encoding.type[i] != BT_NONXML && table[i] != i)
1333
0
      return 0;
1334
0
  for (i = 0; i < 256; i++) {
1335
0
    int c = table[i];
1336
0
    if (c == -1) {
1337
0
      e->normal.type[i] = BT_MALFORM;
1338
      /* This shouldn't really get used. */
1339
0
      e->utf16[i] = 0xFFFF;
1340
0
      e->utf8[i][0] = 1;
1341
0
      e->utf8[i][1] = 0;
1342
0
    } else if (c < 0) {
1343
0
      if (c < -4)
1344
0
        return 0;
1345
      /* Multi-byte sequences need a converter function */
1346
0
      if (! convert)
1347
0
        return 0;
1348
0
      e->normal.type[i] = (unsigned char)(BT_LEAD2 - (c + 2));
1349
0
      e->utf8[i][0] = 0;
1350
0
      e->utf16[i] = 0;
1351
0
    } else if (c < 0x80) {
1352
0
      if (latin1_encoding.type[c] != BT_OTHER
1353
0
          && latin1_encoding.type[c] != BT_NONXML && c != i)
1354
0
        return 0;
1355
0
      e->normal.type[i] = latin1_encoding.type[c];
1356
0
      e->utf8[i][0] = 1;
1357
0
      e->utf8[i][1] = (char)c;
1358
0
      e->utf16[i] = (unsigned short)(c == 0 ? 0xFFFF : c);
1359
0
    } else if (checkCharRefNumber(c) < 0) {
1360
0
      e->normal.type[i] = BT_NONXML;
1361
      /* This shouldn't really get used. */
1362
0
      e->utf16[i] = 0xFFFF;
1363
0
      e->utf8[i][0] = 1;
1364
0
      e->utf8[i][1] = 0;
1365
0
    } else {
1366
0
      if (c > 0xFFFF)
1367
0
        return 0;
1368
0
      if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff))
1369
0
        e->normal.type[i] = BT_NMSTRT;
1370
0
      else if (UCS2_GET_NAMING(namePages, c >> 8, c & 0xff))
1371
0
        e->normal.type[i] = BT_NAME;
1372
0
      else
1373
0
        e->normal.type[i] = BT_OTHER;
1374
0
      e->utf8[i][0] = (char)XmlUtf8Encode(c, e->utf8[i] + 1);
1375
0
      e->utf16[i] = (unsigned short)c;
1376
0
    }
1377
0
  }
1378
0
  e->userData = userData;
1379
0
  e->convert = convert;
1380
0
  if (convert) {
1381
0
    e->normal.isName2 = unknown_isName;
1382
0
    e->normal.isName3 = unknown_isName;
1383
0
    e->normal.isName4 = unknown_isName;
1384
0
    e->normal.isNmstrt2 = unknown_isNmstrt;
1385
0
    e->normal.isNmstrt3 = unknown_isNmstrt;
1386
0
    e->normal.isNmstrt4 = unknown_isNmstrt;
1387
0
    e->normal.isInvalid2 = unknown_isInvalid;
1388
0
    e->normal.isInvalid3 = unknown_isInvalid;
1389
0
    e->normal.isInvalid4 = unknown_isInvalid;
1390
0
  }
1391
0
  e->normal.enc.utf8Convert = unknown_toUtf8;
1392
0
  e->normal.enc.utf16Convert = unknown_toUtf16;
1393
0
  return &(e->normal.enc);
1394
0
}
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
214k
getEncodingIndex(const char *name) {
1429
214k
  static const char *const encodingNames[] = {
1430
214k
      KW_ISO_8859_1, KW_US_ASCII, KW_UTF_8, KW_UTF_16, KW_UTF_16BE, KW_UTF_16LE,
1431
214k
  };
1432
214k
  int i;
1433
214k
  if (name == NULL)
1434
214k
    return NO_ENC;
1435
3
  for (i = 0; i < (int)(sizeof(encodingNames) / sizeof(encodingNames[0])); i++)
1436
3
    if (streqci(name, encodingNames[i]))
1437
1
      return i;
1438
0
  return UNKNOWN_ENC;
1439
1
}
1440
1441
/* For binary compatibility, we store the index of the encoding
1442
   specified at initialization in the isUtf16 member.
1443
*/
1444
1445
113k
#define INIT_ENC_INDEX(enc) ((int)(enc)->initEnc.isUtf16)
1446
214k
#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
107k
         int state, const char *ptr, const char *end, const char **nextTokPtr) {
1458
107k
  const ENCODING **encPtr;
1459
1460
107k
  if (ptr >= end)
1461
97
    return XML_TOK_NONE;
1462
107k
  encPtr = enc->encPtr;
1463
107k
  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
461
    switch (INIT_ENC_INDEX(enc)) {
1473
0
    case UTF_16_ENC:
1474
0
    case UTF_16LE_ENC:
1475
0
    case UTF_16BE_ENC:
1476
0
      return XML_TOK_PARTIAL;
1477
461
    }
1478
461
    switch ((unsigned char)*ptr) {
1479
39
    case 0xFE:
1480
127
    case 0xFF:
1481
165
    case 0xEF: /* possibly first byte of UTF-8 BOM */
1482
165
      if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
1483
0
        break;
1484
165
      EXPAT_FALLTHROUGH;
1485
165
    case 0x00:
1486
303
    case 0x3C:
1487
303
      return XML_TOK_PARTIAL;
1488
461
    }
1489
106k
  } else {
1490
106k
    switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) {
1491
91
    case 0xFEFF:
1492
91
      if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
1493
0
        break;
1494
91
      *nextTokPtr = ptr + 2;
1495
91
      *encPtr = encodingTable[UTF_16BE_ENC];
1496
91
      return XML_TOK_BOM;
1497
    /* 00 3C is handled in the default case */
1498
32.0k
    case 0x3C00:
1499
32.0k
      if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC
1500
32.0k
           || INIT_ENC_INDEX(enc) == UTF_16_ENC)
1501
0
          && state == XML_CONTENT_STATE)
1502
0
        break;
1503
32.0k
      *encPtr = encodingTable[UTF_16LE_ENC];
1504
32.0k
      return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1505
88
    case 0xFFFE:
1506
88
      if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
1507
0
        break;
1508
88
      *nextTokPtr = ptr + 2;
1509
88
      *encPtr = encodingTable[UTF_16LE_ENC];
1510
88
      return XML_TOK_BOM;
1511
155
    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
155
      if (state == XML_CONTENT_STATE) {
1520
0
        int e = INIT_ENC_INDEX(enc);
1521
0
        if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC || e == UTF_16LE_ENC
1522
0
            || e == UTF_16_ENC)
1523
0
          break;
1524
0
      }
1525
155
      if (ptr + 2 == end)
1526
6
        return XML_TOK_PARTIAL;
1527
149
      if ((unsigned char)ptr[2] == 0xBF) {
1528
71
        *nextTokPtr = ptr + 3;
1529
71
        *encPtr = encodingTable[UTF_8_ENC];
1530
71
        return XML_TOK_BOM;
1531
71
      }
1532
78
      break;
1533
74.4k
    default:
1534
74.4k
      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
16.0k
        if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC)
1542
0
          break;
1543
16.0k
        *encPtr = encodingTable[UTF_16BE_ENC];
1544
16.0k
        return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1545
58.3k
      } 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
9.61k
        if (state == XML_CONTENT_STATE)
1556
0
          break;
1557
9.61k
        *encPtr = encodingTable[UTF_16LE_ENC];
1558
9.61k
        return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1559
9.61k
      }
1560
48.7k
      break;
1561
106k
    }
1562
106k
  }
1563
48.9k
  *encPtr = encodingTable[INIT_ENC_INDEX(enc)];
1564
48.9k
  return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1565
107k
}
1566
1567
214k
#define NS(x) x
1568
1
#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
323k
#  define NS(x) x##NS
1578
107k
#  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
0
                         void *userData) {
1590
0
  ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData);
1591
0
  if (enc)
1592
0
    ((struct normal_encoding *)enc)->type[ASCII_COLON] = BT_COLON;
1593
0
  return enc;
1594
0
}
1595
1596
#endif /* XML_NS */