Coverage Report

Created: 2026-10-28 07:09

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
118k
  (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
4.86k
  (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3)                         \
95
4.86k
                + ((((byte)[0]) & 3) << 1) + ((((byte)[1]) >> 5) & 1)]         \
96
4.86k
   & (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.66k
  (namingBitmap                                                                \
105
7.66k
       [((pages)[((((byte)[0]) & 0xF) << 4) + ((((byte)[1]) >> 2) & 0xF)]      \
106
7.66k
         << 3)                                                                 \
107
7.66k
        + ((((byte)[1]) & 3) << 1) + ((((byte)[2]) >> 5) & 1)]                 \
108
7.66k
   & (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
22.0k
  ((*p) < 0xC2 || ((p)[1] & 0x80) == 0 || ((p)[1] & 0xC0) == 0xC0)
122
123
#define UTF8_INVALID3(p)                                                       \
124
28.0k
  (((p)[2] & 0x80) == 0                                                        \
125
28.0k
   || ((*p) == 0xEF && (p)[1] == 0xBF ? (p)[2] > 0xBD                          \
126
26.7k
                                      : ((p)[2] & 0xC0) == 0xC0)               \
127
28.0k
   || ((*p) == 0xE0                                                            \
128
26.1k
           ? (p)[1] < 0xA0 || ((p)[1] & 0xC0) == 0xC0                          \
129
26.1k
           : ((p)[1] & 0x80) == 0                                              \
130
19.1k
                 || ((*p) == 0xED ? (p)[1] > 0x9F : ((p)[1] & 0xC0) == 0xC0)))
131
132
#define UTF8_INVALID4(p)                                                       \
133
17.2k
  (((p)[3] & 0x80) == 0 || ((p)[3] & 0xC0) == 0xC0 || ((p)[2] & 0x80) == 0     \
134
17.2k
   || ((p)[2] & 0xC0) == 0xC0                                                  \
135
17.2k
   || ((*p) == 0xF0                                                            \
136
15.7k
           ? (p)[1] < 0x90 || ((p)[1] & 0xC0) == 0xC0                          \
137
15.7k
           : ((p)[1] & 0x80) == 0                                              \
138
15.4k
                 || ((*p) == 0xF4 ? (p)[1] > 0x8F : ((p)[1] & 0xC0) == 0xC0)))
139
140
static int
141
951
isNever(const ENCODING *enc, const char *p) {
142
951
  UNUSED_P(enc);
143
951
  UNUSED_P(p);
144
951
  return 0;
145
951
}
146
147
static int
148
3.39k
utf8_isName2(const ENCODING *enc, const char *p) {
149
3.39k
  UNUSED_P(enc);
150
3.39k
  return UTF8_GET_NAMING2(namePages, (const unsigned char *)p);
151
3.39k
}
152
153
static int
154
6.57k
utf8_isName3(const ENCODING *enc, const char *p) {
155
6.57k
  UNUSED_P(enc);
156
6.57k
  return UTF8_GET_NAMING3(namePages, (const unsigned char *)p);
157
6.57k
}
158
159
#define utf8_isName4 isNever
160
161
static int
162
1.47k
utf8_isNmstrt2(const ENCODING *enc, const char *p) {
163
1.47k
  UNUSED_P(enc);
164
1.47k
  return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p);
165
1.47k
}
166
167
static int
168
1.09k
utf8_isNmstrt3(const ENCODING *enc, const char *p) {
169
1.09k
  UNUSED_P(enc);
170
1.09k
  return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p);
171
1.09k
}
172
173
#define utf8_isNmstrt4 isNever
174
175
static int
176
22.0k
utf8_isInvalid2(const ENCODING *enc, const char *p) {
177
22.0k
  UNUSED_P(enc);
178
22.0k
  return UTF8_INVALID2((const unsigned char *)p);
179
22.0k
}
180
181
static int
182
28.0k
utf8_isInvalid3(const ENCODING *enc, const char *p) {
183
28.0k
  UNUSED_P(enc);
184
28.0k
  return UTF8_INVALID3((const unsigned char *)p);
185
28.0k
}
186
187
static int
188
17.2k
utf8_isInvalid4(const ENCODING *enc, const char *p) {
189
17.2k
  UNUSED_P(enc);
190
17.2k
  return UTF8_INVALID4((const unsigned char *)p);
191
17.2k
}
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
80.7k
#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
186M
#define MINBPC(enc) 1
229
230
#define SB_BYTE_TYPE(enc, p)                                                   \
231
111M
  (((const struct normal_encoding *)(enc))->type[(unsigned char)*(p)])
232
233
111M
#define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p)
234
235
265k
#define BYTE_TO_ASCII(enc, p) (*(p))
236
237
10.4k
#define IS_NAME_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isName##n(enc, p))
238
2.98k
#define IS_NMSTRT_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isNmstrt##n(enc, p))
239
#define IS_INVALID_CHAR(enc, p, n)                                             \
240
83.9k
  (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
108k
#define CHAR_MATCHES(enc, p, c) (*(p) == (c))
247
248
759k
#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
941k
                                           const char **fromLimRef) {
273
941k
  const char *fromLim = *fromLimRef;
274
941k
  size_t walked = 0;
275
943k
  for (; fromLim > from; fromLim--, walked++) {
276
939k
    const unsigned char prev = (unsigned char)fromLim[-1];
277
939k
    if ((prev & 0xf8u)
278
939k
        == 0xf0u) { /* 4-byte character, lead by 0b11110xxx byte */
279
339
      if (walked + 1 >= 4) {
280
273
        fromLim += 4 - 1;
281
273
        break;
282
273
      } else {
283
66
        walked = 0;
284
66
      }
285
938k
    } else if ((prev & 0xf0u)
286
938k
               == 0xe0u) { /* 3-byte character, lead by 0b1110xxxx byte */
287
173
      if (walked + 1 >= 3) {
288
82
        fromLim += 3 - 1;
289
82
        break;
290
91
      } else {
291
91
        walked = 0;
292
91
      }
293
938k
    } else if ((prev & 0xe0u)
294
938k
               == 0xc0u) { /* 2-byte character, lead by 0b110xxxxx byte */
295
251
      if (walked + 1 >= 2) {
296
72
        fromLim += 2 - 1;
297
72
        break;
298
179
      } else {
299
179
        walked = 0;
300
179
      }
301
938k
    } else if ((prev & 0x80u)
302
938k
               == 0x00u) { /* 1-byte character, matching 0b0xxxxxxx */
303
937k
      break;
304
937k
    }
305
939k
  }
306
941k
  *fromLimRef = fromLim;
307
941k
}
308
309
static enum XML_Convert_Result
310
utf8_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
311
941k
            char **toP, const char *toLim) {
312
941k
  bool input_incomplete = false;
313
941k
  bool output_exhausted = false;
314
315
  /* Avoid copying partial characters (due to limited space). */
316
941k
  const ptrdiff_t bytesAvailable = fromLim - *fromP;
317
941k
  const ptrdiff_t bytesStorable = toLim - *toP;
318
941k
  UNUSED_P(enc);
319
941k
  if (bytesAvailable > bytesStorable) {
320
18.0k
    fromLim = *fromP + bytesStorable;
321
18.0k
    output_exhausted = true;
322
18.0k
  }
323
324
  /* Avoid copying partial characters (from incomplete input). */
325
941k
  {
326
941k
    const char *const fromLimBefore = fromLim;
327
941k
    _INTERNAL_trim_to_complete_utf8_characters(*fromP, &fromLim);
328
941k
    if (fromLim < fromLimBefore) {
329
336
      input_incomplete = true;
330
336
    }
331
941k
  }
332
333
941k
  {
334
941k
    const ptrdiff_t bytesToCopy = fromLim - *fromP;
335
941k
    memcpy(*toP, *fromP, bytesToCopy);
336
941k
    *fromP += bytesToCopy;
337
941k
    *toP += bytesToCopy;
338
941k
  }
339
340
941k
  if (output_exhausted) /* needs to go first */
341
18.0k
    return XML_CONVERT_OUTPUT_EXHAUSTED;
342
923k
  else if (input_incomplete)
343
0
    return XML_CONVERT_INPUT_INCOMPLETE;
344
923k
  else
345
923k
    return XML_CONVERT_COMPLETED;
346
941k
}
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
732k
unicode_byte_type(char hi, char lo) {
541
732k
  switch ((unsigned char)hi) {
542
  /* 0xD800-0xDBFF first 16-bit code unit or high surrogate (W1) */
543
2.56k
  case 0xD8:
544
4.31k
  case 0xD9:
545
6.41k
  case 0xDA:
546
8.38k
  case 0xDB:
547
8.38k
    return BT_LEAD4;
548
  /* 0xDC00-0xDFFF second 16-bit code unit or low surrogate (W2) */
549
1.58k
  case 0xDC:
550
2.97k
  case 0xDD:
551
4.52k
  case 0xDE:
552
6.09k
  case 0xDF:
553
6.09k
    return BT_TRAIL;
554
9.78k
  case 0xFF:
555
9.78k
    switch ((unsigned char)lo) {
556
2.26k
    case 0xFF: /* noncharacter-FFFF */
557
2.37k
    case 0xFE: /* noncharacter-FFFE */
558
2.37k
      return BT_NONXML;
559
9.78k
    }
560
7.40k
    break;
561
732k
  }
562
715k
  return BT_NONASCII;
563
732k
}
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
7.36k
      char **toP, const char *toLim) {                                         \
569
7.36k
    const char *from = *fromP;                                                 \
570
7.36k
    UNUSED_P(enc);                                                             \
571
7.36k
    fromLim = from + (((fromLim - from) >> 1) << 1); /* shrink to even */      \
572
55.8k
    for (; from < fromLim; from += 2) {                                        \
573
49.0k
      int plane;                                                               \
574
49.0k
      unsigned char lo2;                                                       \
575
49.0k
      unsigned char lo = GET_LO(from);                                         \
576
49.0k
      unsigned char hi = GET_HI(from);                                         \
577
49.0k
      switch (hi) {                                                            \
578
3.15k
      case 0:                                                                  \
579
3.15k
        if (lo < 0x80) {                                                       \
580
2.79k
          if (*toP == toLim) {                                                 \
581
28
            *fromP = from;                                                     \
582
28
            return XML_CONVERT_OUTPUT_EXHAUSTED;                               \
583
28
          }                                                                    \
584
2.79k
          *(*toP)++ = lo;                                                      \
585
2.76k
          break;                                                               \
586
2.79k
        }                                                                      \
587
3.15k
        EXPAT_FALLTHROUGH;                                                     \
588
5.91k
      case 0x1:                                                                \
589
6.38k
      case 0x2:                                                                \
590
7.09k
      case 0x3:                                                                \
591
7.25k
      case 0x4:                                                                \
592
7.31k
      case 0x5:                                                                \
593
7.36k
      case 0x6:                                                                \
594
7.36k
      case 0x7:                                                                \
595
7.36k
        if (toLim - *toP < 2) {                                                \
596
195
          *fromP = from;                                                       \
597
195
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
598
195
        }                                                                      \
599
7.36k
        *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2);                      \
600
7.17k
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
601
7.17k
        break;                                                                 \
602
38.9k
      default:                                                                 \
603
38.9k
        if (toLim - *toP < 3) {                                                \
604
369
          *fromP = from;                                                       \
605
369
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
606
369
        }                                                                      \
607
38.9k
        /* 16 bits divided 4, 6, 6 amongst 3 bytes */                          \
608
38.9k
        *(*toP)++ = ((hi >> 4) | UTF8_cval3);                                  \
609
38.5k
        *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80);                    \
610
38.5k
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
611
38.5k
        break;                                                                 \
612
38.9k
      case 0xD8:                                                               \
613
0
      case 0xD9:                                                               \
614
0
      case 0xDA:                                                               \
615
0
      case 0xDB:                                                               \
616
0
        if (toLim - *toP < 4) {                                                \
617
0
          *fromP = from;                                                       \
618
0
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
619
0
        }                                                                      \
620
0
        if (fromLim - from < 4) {                                              \
621
0
          *fromP = from;                                                       \
622
0
          return XML_CONVERT_INPUT_INCOMPLETE;                                 \
623
0
        }                                                                      \
624
0
        plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1;                   \
625
0
        *(*toP)++ = (char)((plane >> 2) | UTF8_cval4);                         \
626
0
        *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80);         \
627
0
        from += 2;                                                             \
628
0
        lo2 = GET_LO(from);                                                    \
629
0
        *(*toP)++ = (((lo & 0x3) << 4) | ((GET_HI(from) & 0x3) << 2)           \
630
0
                     | (lo2 >> 6) | 0x80);                                     \
631
0
        *(*toP)++ = ((lo2 & 0x3f) | 0x80);                                     \
632
0
        break;                                                                 \
633
49.0k
      }                                                                        \
634
49.0k
    }                                                                          \
635
7.36k
    *fromP = from;                                                             \
636
6.76k
    if (from < fromLim)                                                        \
637
6.76k
      return XML_CONVERT_INPUT_INCOMPLETE;                                     \
638
6.76k
    else                                                                       \
639
6.76k
      return XML_CONVERT_COMPLETED;                                            \
640
6.76k
  }
xmltok.c:little2_toUtf8
Line
Count
Source
568
5.60k
      char **toP, const char *toLim) {                                         \
569
5.60k
    const char *from = *fromP;                                                 \
570
5.60k
    UNUSED_P(enc);                                                             \
571
5.60k
    fromLim = from + (((fromLim - from) >> 1) << 1); /* shrink to even */      \
572
46.0k
    for (; from < fromLim; from += 2) {                                        \
573
40.8k
      int plane;                                                               \
574
40.8k
      unsigned char lo2;                                                       \
575
40.8k
      unsigned char lo = GET_LO(from);                                         \
576
40.8k
      unsigned char hi = GET_HI(from);                                         \
577
40.8k
      switch (hi) {                                                            \
578
2.08k
      case 0:                                                                  \
579
2.08k
        if (lo < 0x80) {                                                       \
580
1.81k
          if (*toP == toLim) {                                                 \
581
18
            *fromP = from;                                                     \
582
18
            return XML_CONVERT_OUTPUT_EXHAUSTED;                               \
583
18
          }                                                                    \
584
1.81k
          *(*toP)++ = lo;                                                      \
585
1.79k
          break;                                                               \
586
1.81k
        }                                                                      \
587
2.08k
        EXPAT_FALLTHROUGH;                                                     \
588
5.71k
      case 0x1:                                                                \
589
5.76k
      case 0x2:                                                                \
590
6.40k
      case 0x3:                                                                \
591
6.47k
      case 0x4:                                                                \
592
6.52k
      case 0x5:                                                                \
593
6.55k
      case 0x6:                                                                \
594
6.55k
      case 0x7:                                                                \
595
6.55k
        if (toLim - *toP < 2) {                                                \
596
154
          *fromP = from;                                                       \
597
154
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
598
154
        }                                                                      \
599
6.55k
        *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2);                      \
600
6.40k
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
601
6.40k
        break;                                                                 \
602
32.4k
      default:                                                                 \
603
32.4k
        if (toLim - *toP < 3) {                                                \
604
276
          *fromP = from;                                                       \
605
276
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
606
276
        }                                                                      \
607
32.4k
        /* 16 bits divided 4, 6, 6 amongst 3 bytes */                          \
608
32.4k
        *(*toP)++ = ((hi >> 4) | UTF8_cval3);                                  \
609
32.2k
        *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80);                    \
610
32.2k
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
611
32.2k
        break;                                                                 \
612
32.4k
      case 0xD8:                                                               \
613
0
      case 0xD9:                                                               \
614
0
      case 0xDA:                                                               \
615
0
      case 0xDB:                                                               \
616
0
        if (toLim - *toP < 4) {                                                \
617
0
          *fromP = from;                                                       \
618
0
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
619
0
        }                                                                      \
620
0
        if (fromLim - from < 4) {                                              \
621
0
          *fromP = from;                                                       \
622
0
          return XML_CONVERT_INPUT_INCOMPLETE;                                 \
623
0
        }                                                                      \
624
0
        plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1;                   \
625
0
        *(*toP)++ = (char)((plane >> 2) | UTF8_cval4);                         \
626
0
        *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80);         \
627
0
        from += 2;                                                             \
628
0
        lo2 = GET_LO(from);                                                    \
629
0
        *(*toP)++ = (((lo & 0x3) << 4) | ((GET_HI(from) & 0x3) << 2)           \
630
0
                     | (lo2 >> 6) | 0x80);                                     \
631
0
        *(*toP)++ = ((lo2 & 0x3f) | 0x80);                                     \
632
0
        break;                                                                 \
633
40.8k
      }                                                                        \
634
40.8k
    }                                                                          \
635
5.60k
    *fromP = from;                                                             \
636
5.15k
    if (from < fromLim)                                                        \
637
5.15k
      return XML_CONVERT_INPUT_INCOMPLETE;                                     \
638
5.15k
    else                                                                       \
639
5.15k
      return XML_CONVERT_COMPLETED;                                            \
640
5.15k
  }
xmltok.c:big2_toUtf8
Line
Count
Source
568
1.75k
      char **toP, const char *toLim) {                                         \
569
1.75k
    const char *from = *fromP;                                                 \
570
1.75k
    UNUSED_P(enc);                                                             \
571
1.75k
    fromLim = from + (((fromLim - from) >> 1) << 1); /* shrink to even */      \
572
9.84k
    for (; from < fromLim; from += 2) {                                        \
573
8.23k
      int plane;                                                               \
574
8.23k
      unsigned char lo2;                                                       \
575
8.23k
      unsigned char lo = GET_LO(from);                                         \
576
8.23k
      unsigned char hi = GET_HI(from);                                         \
577
8.23k
      switch (hi) {                                                            \
578
1.07k
      case 0:                                                                  \
579
1.07k
        if (lo < 0x80) {                                                       \
580
978
          if (*toP == toLim) {                                                 \
581
10
            *fromP = from;                                                     \
582
10
            return XML_CONVERT_OUTPUT_EXHAUSTED;                               \
583
10
          }                                                                    \
584
978
          *(*toP)++ = lo;                                                      \
585
968
          break;                                                               \
586
978
        }                                                                      \
587
1.07k
        EXPAT_FALLTHROUGH;                                                     \
588
206
      case 0x1:                                                                \
589
617
      case 0x2:                                                                \
590
690
      case 0x3:                                                                \
591
773
      case 0x4:                                                                \
592
792
      case 0x5:                                                                \
593
810
      case 0x6:                                                                \
594
810
      case 0x7:                                                                \
595
810
        if (toLim - *toP < 2) {                                                \
596
41
          *fromP = from;                                                       \
597
41
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
598
41
        }                                                                      \
599
810
        *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2);                      \
600
769
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
601
769
        break;                                                                 \
602
6.44k
      default:                                                                 \
603
6.44k
        if (toLim - *toP < 3) {                                                \
604
93
          *fromP = from;                                                       \
605
93
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
606
93
        }                                                                      \
607
6.44k
        /* 16 bits divided 4, 6, 6 amongst 3 bytes */                          \
608
6.44k
        *(*toP)++ = ((hi >> 4) | UTF8_cval3);                                  \
609
6.35k
        *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80);                    \
610
6.35k
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
611
6.35k
        break;                                                                 \
612
6.44k
      case 0xD8:                                                               \
613
0
      case 0xD9:                                                               \
614
0
      case 0xDA:                                                               \
615
0
      case 0xDB:                                                               \
616
0
        if (toLim - *toP < 4) {                                                \
617
0
          *fromP = from;                                                       \
618
0
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
619
0
        }                                                                      \
620
0
        if (fromLim - from < 4) {                                              \
621
0
          *fromP = from;                                                       \
622
0
          return XML_CONVERT_INPUT_INCOMPLETE;                                 \
623
0
        }                                                                      \
624
0
        plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1;                   \
625
0
        *(*toP)++ = (char)((plane >> 2) | UTF8_cval4);                         \
626
0
        *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80);         \
627
0
        from += 2;                                                             \
628
0
        lo2 = GET_LO(from);                                                    \
629
0
        *(*toP)++ = (((lo & 0x3) << 4) | ((GET_HI(from) & 0x3) << 2)           \
630
0
                     | (lo2 >> 6) | 0x80);                                     \
631
0
        *(*toP)++ = ((lo2 & 0x3f) | 0x80);                                     \
632
0
        break;                                                                 \
633
8.23k
      }                                                                        \
634
8.23k
    }                                                                          \
635
1.75k
    *fromP = from;                                                             \
636
1.61k
    if (from < fromLim)                                                        \
637
1.61k
      return XML_CONVERT_INPUT_INCOMPLETE;                                     \
638
1.61k
    else                                                                       \
639
1.61k
      return XML_CONVERT_COMPLETED;                                            \
640
1.61k
  }
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
40.8k
#define GET_LO(ptr) ((unsigned char)(ptr)[0])
665
40.8k
#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
8.23k
#define GET_LO(ptr) ((unsigned char)(ptr)[1])
674
8.23k
#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
847k
  ((p)[1] == 0 ? SB_BYTE_TYPE(enc, p) : unicode_byte_type((p)[1], (p)[0]))
684
157
#define LITTLE2_BYTE_TO_ASCII(p) ((p)[1] == 0 ? (p)[0] : -1)
685
11.6k
#define LITTLE2_CHAR_MATCHES(p, c) ((p)[1] == 0 && (p)[0] == (c))
686
#define LITTLE2_IS_NAME_CHAR_MINBPC(p)                                         \
687
80.0k
  UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0])
688
#define LITTLE2_IS_NMSTRT_CHAR_MINBPC(p)                                       \
689
16.5k
  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
6.49k
  ((n) == 4 && ((unsigned char)(p)[3] & 0xFC) != 0xDC)
695
696
#undef PREFIX
697
35.5k
#define PREFIX(ident) little2_##ident
698
1.72M
#define MINBPC(enc) 2
699
/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
700
847k
#define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p)
701
157
#define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(p)
702
11.6k
#define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(p, c)
703
10
#define IS_NAME_CHAR(enc, p, n) 0
704
80.0k
#define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(p)
705
10
#define IS_NMSTRT_CHAR(enc, p, n) (0)
706
16.5k
#define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(p)
707
3.91k
#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
182k
  ((p)[0] == 0 ? SB_BYTE_TYPE(enc, p + 1) : unicode_byte_type((p)[0], (p)[1]))
785
134
#define BIG2_BYTE_TO_ASCII(p) ((p)[0] == 0 ? (p)[1] : -1)
786
1.23k
#define BIG2_CHAR_MATCHES(p, c) ((p)[0] == 0 && (p)[1] == (c))
787
#define BIG2_IS_NAME_CHAR_MINBPC(p)                                            \
788
17.4k
  UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1])
789
#define BIG2_IS_NMSTRT_CHAR_MINBPC(p)                                          \
790
4.26k
  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
2.34k
  ((n) == 4 && ((unsigned char)(p)[2] & 0xFC) != 0xDC)
796
797
#undef PREFIX
798
9.58k
#define PREFIX(ident) big2_##ident
799
387k
#define MINBPC(enc) 2
800
/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
801
182k
#define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p)
802
134
#define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(p)
803
1.23k
#define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(p, c)
804
0
#define IS_NAME_CHAR(enc, p, n) 0
805
17.4k
#define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(p)
806
4
#define IS_NMSTRT_CHAR(enc, p, n) (0)
807
4.26k
#define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(p)
808
1.39k
#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
0
streqci(const char *s1, const char *s2) {
888
0
  for (;;) {
889
0
    char c1 = *s1++;
890
0
    char c2 = *s2++;
891
0
    if (ASCII_a <= c1 && c1 <= ASCII_z)
892
0
      c1 += ASCII_A - ASCII_a;
893
0
    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
0
    if (c1 != c2)
900
0
      return 0;
901
0
    if (! c1)
902
0
      break;
903
0
  }
904
0
  return 1;
905
0
}
906
907
static void
908
initUpdatePosition(const ENCODING *enc, const char *ptr, const char *end,
909
644
                   POSITION *pos) {
910
644
  UNUSED_P(enc);
911
644
  normal_updatePosition(&utf8_encoding.enc, ptr, end, pos);
912
644
}
913
914
static int
915
12.6k
toAscii(const ENCODING *enc, const char *ptr, const char *end) {
916
12.6k
  char buf[1];
917
12.6k
  char *p = buf;
918
12.6k
  XmlUtf8Convert(enc, &ptr, end, &p, p + 1);
919
12.6k
  if (p == buf)
920
340
    return -1;
921
12.3k
  else
922
12.3k
    return buf[0];
923
12.6k
}
924
925
static int
926
8.78k
isSpace(int c) {
927
8.78k
  switch (c) {
928
4.77k
  case 0x20:
929
4.82k
  case 0xD:
930
5.03k
  case 0xA:
931
5.06k
  case 0x9:
932
5.06k
    return 1;
933
8.78k
  }
934
3.72k
  return 0;
935
8.78k
}
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
711
                     const char **valPtr, const char **nextTokPtr) {
944
711
  int c;
945
711
  char open;
946
711
  if (ptr == end) {
947
18
    *namePtr = NULL;
948
18
    return 1;
949
18
  }
950
693
  if (! isSpace(toAscii(enc, ptr, end))) {
951
0
    *nextTokPtr = ptr;
952
0
    return 0;
953
0
  }
954
3.76k
  do {
955
3.76k
    ptr += enc->minBytesPerChar;
956
3.76k
  } while (isSpace(toAscii(enc, ptr, end)));
957
693
  if (ptr == end) {
958
18
    *namePtr = NULL;
959
18
    return 1;
960
18
  }
961
675
  *namePtr = ptr;
962
2.82k
  for (;;) {
963
2.82k
    c = toAscii(enc, ptr, end);
964
2.82k
    if (c == -1) {
965
50
      *nextTokPtr = ptr;
966
50
      return 0;
967
50
    }
968
2.77k
    if (c == ASCII_EQUALS) {
969
192
      *nameEndPtr = ptr;
970
192
      break;
971
192
    }
972
2.58k
    if (isSpace(c)) {
973
433
      *nameEndPtr = ptr;
974
961
      do {
975
961
        ptr += enc->minBytesPerChar;
976
961
      } while (isSpace(c = toAscii(enc, ptr, end)));
977
433
      if (c != ASCII_EQUALS) {
978
144
        *nextTokPtr = ptr;
979
144
        return 0;
980
144
      }
981
289
      break;
982
433
    }
983
2.15k
    ptr += enc->minBytesPerChar;
984
2.15k
  }
985
481
  if (ptr == *namePtr) {
986
34
    *nextTokPtr = ptr;
987
34
    return 0;
988
34
  }
989
447
  ptr += enc->minBytesPerChar;
990
447
  c = toAscii(enc, ptr, end);
991
788
  while (isSpace(c)) {
992
341
    ptr += enc->minBytesPerChar;
993
341
    c = toAscii(enc, ptr, end);
994
341
  }
995
447
  if (c != ASCII_QUOT && c != ASCII_APOS) {
996
137
    *nextTokPtr = ptr;
997
137
    return 0;
998
137
  }
999
310
  open = (char)c;
1000
310
  ptr += enc->minBytesPerChar;
1001
310
  *valPtr = ptr;
1002
3.62k
  for (;; ptr += enc->minBytesPerChar) {
1003
3.62k
    c = toAscii(enc, ptr, end);
1004
3.62k
    if (c == open)
1005
38
      break;
1006
3.58k
    if (! (ASCII_a <= c && c <= ASCII_z) && ! (ASCII_A <= c && c <= ASCII_Z)
1007
946
        && ! (ASCII_0 <= c && c <= ASCII_9) && c != ASCII_PERIOD
1008
422
        && c != ASCII_MINUS && c != ASCII_UNDERSCORE) {
1009
272
      *nextTokPtr = ptr;
1010
272
      return 0;
1011
272
    }
1012
3.58k
  }
1013
38
  *nextTokPtr = ptr + enc->minBytesPerChar;
1014
38
  return 1;
1015
310
}
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
711
               const ENCODING **encoding, int *standalone) {
1066
711
  const char *val = NULL;
1067
711
  const char *name = NULL;
1068
711
  const char *nameEnd = NULL;
1069
711
  ptr += 5 * enc->minBytesPerChar;
1070
711
  end -= 2 * enc->minBytesPerChar;
1071
711
  if (! parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)
1072
673
      || ! name) {
1073
673
    *badPtr = ptr;
1074
673
    return 0;
1075
673
  }
1076
38
  if (! XmlNameMatchesAscii(enc, name, nameEnd, KW_version)) {
1077
38
    if (! isGeneralTextEntity) {
1078
38
      *badPtr = name;
1079
38
      return 0;
1080
38
    }
1081
38
  } 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
1.71k
checkCharRefNumber(int result) {
1158
1.71k
  switch (result >> 8) {
1159
0
  case 0xD8:
1160
0
  case 0xD9:
1161
0
  case 0xDA:
1162
0
  case 0xDB:
1163
10
  case 0xDC:
1164
10
  case 0xDD:
1165
10
  case 0xDE:
1166
10
  case 0xDF:
1167
10
    return -1;
1168
1.39k
  case 0:
1169
1.39k
    if (latin1_encoding.type[result] == BT_NONXML)
1170
117
      return -1;
1171
1.27k
    break;
1172
1.27k
  case 0xFF:
1173
0
    if (result == 0xFFFE || result == 0xFFFF)
1174
0
      return -1;
1175
0
    break;
1176
1.71k
  }
1177
1.59k
  return result;
1178
1.71k
}
1179
1180
int
1181
1.46k
XmlUtf8Encode(int c, char *buf) {
1182
1.46k
  enum {
1183
    /* minN is minimum legal resulting value for N byte sequence */
1184
1.46k
    min2 = 0x80,
1185
1.46k
    min3 = 0x800,
1186
1.46k
    min4 = 0x10000
1187
1.46k
  };
1188
1189
1.46k
  if (c < 0)
1190
0
    return 0; /* LCOV_EXCL_LINE: this case is always eliminated beforehand */
1191
1.46k
  if (c < min2) {
1192
1.07k
    buf[0] = (char)(c | UTF8_cval1);
1193
1.07k
    return 1;
1194
1.07k
  }
1195
384
  if (c < min3) {
1196
140
    buf[0] = (char)((c >> 6) | UTF8_cval2);
1197
140
    buf[1] = (char)((c & 0x3f) | 0x80);
1198
140
    return 2;
1199
140
  }
1200
244
  if (c < min4) {
1201
131
    buf[0] = (char)((c >> 12) | UTF8_cval3);
1202
131
    buf[1] = (char)(((c >> 6) & 0x3f) | 0x80);
1203
131
    buf[2] = (char)((c & 0x3f) | 0x80);
1204
131
    return 3;
1205
131
  }
1206
113
  if (c < 0x110000) {
1207
113
    buf[0] = (char)((c >> 18) | UTF8_cval4);
1208
113
    buf[1] = (char)(((c >> 12) & 0x3f) | 0x80);
1209
113
    buf[2] = (char)(((c >> 6) & 0x3f) | 0x80);
1210
113
    buf[3] = (char)((c & 0x3f) | 0x80);
1211
113
    return 4;
1212
113
  }
1213
0
  return 0; /* LCOV_EXCL_LINE: this case too is eliminated before calling */
1214
113
}
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
146k
getEncodingIndex(const char *name) {
1429
146k
  static const char *const encodingNames[] = {
1430
146k
      KW_ISO_8859_1, KW_US_ASCII, KW_UTF_8, KW_UTF_16, KW_UTF_16BE, KW_UTF_16LE,
1431
146k
  };
1432
146k
  int i;
1433
146k
  if (name == NULL)
1434
146k
    return NO_ENC;
1435
0
  for (i = 0; i < (int)(sizeof(encodingNames) / sizeof(encodingNames[0])); i++)
1436
0
    if (streqci(name, encodingNames[i]))
1437
0
      return i;
1438
0
  return UNKNOWN_ENC;
1439
0
}
1440
1441
/* For binary compatibility, we store the index of the encoding
1442
   specified at initialization in the isUtf16 member.
1443
*/
1444
1445
77.5k
#define INIT_ENC_INDEX(enc) ((int)(enc)->initEnc.isUtf16)
1446
146k
#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
73.3k
         int state, const char *ptr, const char *end, const char **nextTokPtr) {
1458
73.3k
  const ENCODING **encPtr;
1459
1460
73.3k
  if (ptr >= end)
1461
155
    return XML_TOK_NONE;
1462
73.1k
  encPtr = enc->encPtr;
1463
73.1k
  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
1.36k
    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
1.36k
    }
1478
1.36k
    switch ((unsigned char)*ptr) {
1479
11
    case 0xFE:
1480
75
    case 0xFF:
1481
85
    case 0xEF: /* possibly first byte of UTF-8 BOM */
1482
85
      if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
1483
0
        break;
1484
85
      EXPAT_FALLTHROUGH;
1485
85
    case 0x00:
1486
157
    case 0x3C:
1487
157
      return XML_TOK_PARTIAL;
1488
1.36k
    }
1489
71.7k
  } else {
1490
71.7k
    switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) {
1491
141
    case 0xFEFF:
1492
141
      if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
1493
0
        break;
1494
141
      *nextTokPtr = ptr + 2;
1495
141
      *encPtr = encodingTable[UTF_16BE_ENC];
1496
141
      return XML_TOK_BOM;
1497
    /* 00 3C is handled in the default case */
1498
20.4k
    case 0x3C00:
1499
20.4k
      if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC
1500
20.4k
           || INIT_ENC_INDEX(enc) == UTF_16_ENC)
1501
0
          && state == XML_CONTENT_STATE)
1502
0
        break;
1503
20.4k
      *encPtr = encodingTable[UTF_16LE_ENC];
1504
20.4k
      return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1505
450
    case 0xFFFE:
1506
450
      if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
1507
0
        break;
1508
450
      *nextTokPtr = ptr + 2;
1509
450
      *encPtr = encodingTable[UTF_16LE_ENC];
1510
450
      return XML_TOK_BOM;
1511
154
    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
154
      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
154
      if (ptr + 2 == end)
1526
10
        return XML_TOK_PARTIAL;
1527
144
      if ((unsigned char)ptr[2] == 0xBF) {
1528
75
        *nextTokPtr = ptr + 3;
1529
75
        *encPtr = encodingTable[UTF_8_ENC];
1530
75
        return XML_TOK_BOM;
1531
75
      }
1532
69
      break;
1533
50.6k
    default:
1534
50.6k
      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
11.2k
        if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC)
1542
0
          break;
1543
11.2k
        *encPtr = encodingTable[UTF_16BE_ENC];
1544
11.2k
        return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1545
39.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
6.01k
        if (state == XML_CONTENT_STATE)
1556
0
          break;
1557
6.01k
        *encPtr = encodingTable[UTF_16LE_ENC];
1558
6.01k
        return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1559
6.01k
      }
1560
33.3k
      break;
1561
71.7k
    }
1562
71.7k
  }
1563
34.6k
  *encPtr = encodingTable[INIT_ENC_INDEX(enc)];
1564
34.6k
  return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1565
73.1k
}
1566
1567
146k
#define NS(x) x
1568
0
#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
220k
#  define NS(x) x##NS
1578
73.3k
#  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 */