Coverage Report

Created: 2026-08-11 07:29

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