Coverage Report

Created: 2026-08-17 07:50

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
50.9k
  (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
2.82k
  (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3)                         \
94
2.82k
                + ((((byte)[0]) & 3) << 1) + ((((byte)[1]) >> 5) & 1)]         \
95
2.82k
   & (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
2.94k
  (namingBitmap                                                                \
104
2.94k
       [((pages)[((((byte)[0]) & 0xF) << 4) + ((((byte)[1]) >> 2) & 0xF)]      \
105
2.94k
         << 3)                                                                 \
106
2.94k
        + ((((byte)[1]) & 3) << 1) + ((((byte)[2]) >> 5) & 1)]                 \
107
2.94k
   & (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.05k
  ((*p) < 0xC2 || ((p)[1] & 0x80) == 0 || ((p)[1] & 0xC0) == 0xC0)
121
122
#define UTF8_INVALID3(p)                                                       \
123
14.1k
  (((p)[2] & 0x80) == 0                                                        \
124
14.1k
   || ((*p) == 0xEF && (p)[1] == 0xBF ? (p)[2] > 0xBD                          \
125
13.5k
                                      : ((p)[2] & 0xC0) == 0xC0)               \
126
14.1k
   || ((*p) == 0xE0                                                            \
127
13.1k
           ? (p)[1] < 0xA0 || ((p)[1] & 0xC0) == 0xC0                          \
128
13.1k
           : ((p)[1] & 0x80) == 0                                              \
129
10.2k
                 || ((*p) == 0xED ? (p)[1] > 0x9F : ((p)[1] & 0xC0) == 0xC0)))
130
131
#define UTF8_INVALID4(p)                                                       \
132
7.14k
  (((p)[3] & 0x80) == 0 || ((p)[3] & 0xC0) == 0xC0 || ((p)[2] & 0x80) == 0     \
133
7.14k
   || ((p)[2] & 0xC0) == 0xC0                                                  \
134
7.14k
   || ((*p) == 0xF0                                                            \
135
6.28k
           ? (p)[1] < 0x90 || ((p)[1] & 0xC0) == 0xC0                          \
136
6.28k
           : ((p)[1] & 0x80) == 0                                              \
137
6.21k
                 || ((*p) == 0xF4 ? (p)[1] > 0x8F : ((p)[1] & 0xC0) == 0xC0)))
138
139
static int PTRFASTCALL
140
550
isNever(const ENCODING *enc, const char *p) {
141
550
  UNUSED_P(enc);
142
550
  UNUSED_P(p);
143
550
  return 0;
144
550
}
145
146
static int PTRFASTCALL
147
2.15k
utf8_isName2(const ENCODING *enc, const char *p) {
148
2.15k
  UNUSED_P(enc);
149
2.15k
  return UTF8_GET_NAMING2(namePages, (const unsigned char *)p);
150
2.15k
}
151
152
static int PTRFASTCALL
153
2.44k
utf8_isName3(const ENCODING *enc, const char *p) {
154
2.44k
  UNUSED_P(enc);
155
2.44k
  return UTF8_GET_NAMING3(namePages, (const unsigned char *)p);
156
2.44k
}
157
158
#define utf8_isName4 isNever
159
160
static int PTRFASTCALL
161
671
utf8_isNmstrt2(const ENCODING *enc, const char *p) {
162
671
  UNUSED_P(enc);
163
671
  return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p);
164
671
}
165
166
static int PTRFASTCALL
167
503
utf8_isNmstrt3(const ENCODING *enc, const char *p) {
168
503
  UNUSED_P(enc);
169
503
  return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p);
170
503
}
171
172
#define utf8_isNmstrt4 isNever
173
174
static int PTRFASTCALL
175
9.05k
utf8_isInvalid2(const ENCODING *enc, const char *p) {
176
9.05k
  UNUSED_P(enc);
177
9.05k
  return UTF8_INVALID2((const unsigned char *)p);
178
9.05k
}
179
180
static int PTRFASTCALL
181
14.1k
utf8_isInvalid3(const ENCODING *enc, const char *p) {
182
14.1k
  UNUSED_P(enc);
183
14.1k
  return UTF8_INVALID3((const unsigned char *)p);
184
14.1k
}
185
186
static int PTRFASTCALL
187
7.14k
utf8_isInvalid4(const ENCODING *enc, const char *p) {
188
7.14k
  UNUSED_P(enc);
189
7.14k
  return UTF8_INVALID4((const unsigned char *)p);
190
7.14k
}
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
36.6k
#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
90.2M
#  define MINBPC(enc) 1
250
#endif
251
252
#define SB_BYTE_TYPE(enc, p)                                                   \
253
58.6M
  (((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
58.5M
#  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
185k
#  define BYTE_TO_ASCII(enc, p) (*(p))
274
#endif
275
276
4.88k
#define IS_NAME_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isName##n(enc, p))
277
1.44k
#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
38.0k
    (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
48.1k
#  define CHAR_MATCHES(enc, p, c) (*(p) == (c))
308
#endif
309
310
463k
#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
675k
                                           const char **fromLimRef) {
335
675k
  const char *fromLim = *fromLimRef;
336
675k
  size_t walked = 0;
337
675k
  for (; fromLim > from; fromLim--, walked++) {
338
672k
    const unsigned char prev = (unsigned char)fromLim[-1];
339
672k
    if ((prev & 0xf8u)
340
672k
        == 0xf0u) { /* 4-byte character, lead by 0b11110xxx byte */
341
102
      if (walked + 1 >= 4) {
342
102
        fromLim += 4 - 1;
343
102
        break;
344
102
      } else {
345
0
        walked = 0;
346
0
      }
347
672k
    } else if ((prev & 0xf0u)
348
672k
               == 0xe0u) { /* 3-byte character, lead by 0b1110xxxx byte */
349
26
      if (walked + 1 >= 3) {
350
18
        fromLim += 3 - 1;
351
18
        break;
352
18
      } else {
353
8
        walked = 0;
354
8
      }
355
672k
    } else if ((prev & 0xe0u)
356
672k
               == 0xc0u) { /* 2-byte character, lead by 0b110xxxxx byte */
357
121
      if (walked + 1 >= 2) {
358
23
        fromLim += 2 - 1;
359
23
        break;
360
98
      } else {
361
98
        walked = 0;
362
98
      }
363
672k
    } else if ((prev & 0x80u)
364
672k
               == 0x00u) { /* 1-byte character, matching 0b0xxxxxxx */
365
672k
      break;
366
672k
    }
367
672k
  }
368
675k
  *fromLimRef = fromLim;
369
675k
}
370
371
static enum XML_Convert_Result PTRCALL
372
utf8_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
373
675k
            char **toP, const char *toLim) {
374
675k
  bool input_incomplete = false;
375
675k
  bool output_exhausted = false;
376
377
  /* Avoid copying partial characters (due to limited space). */
378
675k
  const ptrdiff_t bytesAvailable = fromLim - *fromP;
379
675k
  const ptrdiff_t bytesStorable = toLim - *toP;
380
675k
  UNUSED_P(enc);
381
675k
  if (bytesAvailable > bytesStorable) {
382
6.87k
    fromLim = *fromP + bytesStorable;
383
6.87k
    output_exhausted = true;
384
6.87k
  }
385
386
  /* Avoid copying partial characters (from incomplete input). */
387
675k
  {
388
675k
    const char *const fromLimBefore = fromLim;
389
675k
    _INTERNAL_trim_to_complete_utf8_characters(*fromP, &fromLim);
390
675k
    if (fromLim < fromLimBefore) {
391
106
      input_incomplete = true;
392
106
    }
393
675k
  }
394
395
675k
  {
396
675k
    const ptrdiff_t bytesToCopy = fromLim - *fromP;
397
675k
    memcpy(*toP, *fromP, bytesToCopy);
398
675k
    *fromP += bytesToCopy;
399
675k
    *toP += bytesToCopy;
400
675k
  }
401
402
675k
  if (output_exhausted) /* needs to go first */
403
6.87k
    return XML_CONVERT_OUTPUT_EXHAUSTED;
404
668k
  else if (input_incomplete)
405
0
    return XML_CONVERT_INPUT_INCOMPLETE;
406
668k
  else
407
668k
    return XML_CONVERT_COMPLETED;
408
675k
}
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
323k
unicode_byte_type(char hi, char lo) {
603
323k
  switch ((unsigned char)hi) {
604
  /* 0xD800-0xDBFF first 16-bit code unit or high surrogate (W1) */
605
2.97k
  case 0xD8:
606
5.07k
  case 0xD9:
607
7.62k
  case 0xDA:
608
9.83k
  case 0xDB:
609
9.83k
    return BT_LEAD4;
610
  /* 0xDC00-0xDFFF second 16-bit code unit or low surrogate (W2) */
611
726
  case 0xDC:
612
1.33k
  case 0xDD:
613
2.04k
  case 0xDE:
614
2.79k
  case 0xDF:
615
2.79k
    return BT_TRAIL;
616
6.35k
  case 0xFF:
617
6.35k
    switch ((unsigned char)lo) {
618
1.25k
    case 0xFF: /* noncharacter-FFFF */
619
1.34k
    case 0xFE: /* noncharacter-FFFE */
620
1.34k
      return BT_NONXML;
621
6.35k
    }
622
5.00k
    break;
623
323k
  }
624
309k
  return BT_NONASCII;
625
323k
}
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
3.19k
      char **toP, const char *toLim) {                                         \
631
3.19k
    const char *from = *fromP;                                                 \
632
3.19k
    UNUSED_P(enc);                                                             \
633
3.19k
    fromLim = from + (((fromLim - from) >> 1) << 1); /* shrink to even */      \
634
22.9k
    for (; from < fromLim; from += 2) {                                        \
635
20.0k
      int plane;                                                               \
636
20.0k
      unsigned char lo2;                                                       \
637
20.0k
      unsigned char lo = GET_LO(from);                                         \
638
20.0k
      unsigned char hi = GET_HI(from);                                         \
639
20.0k
      switch (hi) {                                                            \
640
1.73k
      case 0:                                                                  \
641
1.73k
        if (lo < 0x80) {                                                       \
642
1.45k
          if (*toP == toLim) {                                                 \
643
17
            *fromP = from;                                                     \
644
17
            return XML_CONVERT_OUTPUT_EXHAUSTED;                               \
645
17
          }                                                                    \
646
1.45k
          *(*toP)++ = lo;                                                      \
647
1.43k
          break;                                                               \
648
1.45k
        }                                                                      \
649
1.73k
        EXPAT_FALLTHROUGH;                                                     \
650
1.18k
      case 0x1:                                                                \
651
1.31k
      case 0x2:                                                                \
652
1.83k
      case 0x3:                                                                \
653
1.91k
      case 0x4:                                                                \
654
1.94k
      case 0x5:                                                                \
655
1.96k
      case 0x6:                                                                \
656
1.96k
      case 0x7:                                                                \
657
1.96k
        if (toLim - *toP < 2) {                                                \
658
52
          *fromP = from;                                                       \
659
52
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
660
52
        }                                                                      \
661
1.96k
        *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2);                      \
662
1.91k
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
663
1.91k
        break;                                                                 \
664
16.6k
      default:                                                                 \
665
16.6k
        if (toLim - *toP < 3) {                                                \
666
201
          *fromP = from;                                                       \
667
201
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
668
201
        }                                                                      \
669
16.6k
        /* 16 bits divided 4, 6, 6 amongst 3 bytes */                          \
670
16.6k
        *(*toP)++ = ((hi >> 4) | UTF8_cval3);                                  \
671
16.4k
        *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80);                    \
672
16.4k
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
673
16.4k
        break;                                                                 \
674
16.6k
      case 0xD8:                                                               \
675
0
      case 0xD9:                                                               \
676
0
      case 0xDA:                                                               \
677
0
      case 0xDB:                                                               \
678
0
        if (toLim - *toP < 4) {                                                \
679
0
          *fromP = from;                                                       \
680
0
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
681
0
        }                                                                      \
682
0
        if (fromLim - from < 4) {                                              \
683
0
          *fromP = from;                                                       \
684
0
          return XML_CONVERT_INPUT_INCOMPLETE;                                 \
685
0
        }                                                                      \
686
0
        plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1;                   \
687
0
        *(*toP)++ = (char)((plane >> 2) | UTF8_cval4);                         \
688
0
        *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80);         \
689
0
        from += 2;                                                             \
690
0
        lo2 = GET_LO(from);                                                    \
691
0
        *(*toP)++ = (((lo & 0x3) << 4) | ((GET_HI(from) & 0x3) << 2)           \
692
0
                     | (lo2 >> 6) | 0x80);                                     \
693
0
        *(*toP)++ = ((lo2 & 0x3f) | 0x80);                                     \
694
0
        break;                                                                 \
695
20.0k
      }                                                                        \
696
20.0k
    }                                                                          \
697
3.19k
    *fromP = from;                                                             \
698
2.92k
    if (from < fromLim)                                                        \
699
2.92k
      return XML_CONVERT_INPUT_INCOMPLETE;                                     \
700
2.92k
    else                                                                       \
701
2.92k
      return XML_CONVERT_COMPLETED;                                            \
702
2.92k
  }
xmltok.c:little2_toUtf8
Line
Count
Source
630
1.93k
      char **toP, const char *toLim) {                                         \
631
1.93k
    const char *from = *fromP;                                                 \
632
1.93k
    UNUSED_P(enc);                                                             \
633
1.93k
    fromLim = from + (((fromLim - from) >> 1) << 1); /* shrink to even */      \
634
15.5k
    for (; from < fromLim; from += 2) {                                        \
635
13.7k
      int plane;                                                               \
636
13.7k
      unsigned char lo2;                                                       \
637
13.7k
      unsigned char lo = GET_LO(from);                                         \
638
13.7k
      unsigned char hi = GET_HI(from);                                         \
639
13.7k
      switch (hi) {                                                            \
640
898
      case 0:                                                                  \
641
898
        if (lo < 0x80) {                                                       \
642
709
          if (*toP == toLim) {                                                 \
643
10
            *fromP = from;                                                     \
644
10
            return XML_CONVERT_OUTPUT_EXHAUSTED;                               \
645
10
          }                                                                    \
646
709
          *(*toP)++ = lo;                                                      \
647
699
          break;                                                               \
648
709
        }                                                                      \
649
898
        EXPAT_FALLTHROUGH;                                                     \
650
1.03k
      case 0x1:                                                                \
651
1.08k
      case 0x2:                                                                \
652
1.58k
      case 0x3:                                                                \
653
1.60k
      case 0x4:                                                                \
654
1.62k
      case 0x5:                                                                \
655
1.64k
      case 0x6:                                                                \
656
1.64k
      case 0x7:                                                                \
657
1.64k
        if (toLim - *toP < 2) {                                                \
658
34
          *fromP = from;                                                       \
659
34
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
660
34
        }                                                                      \
661
1.64k
        *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2);                      \
662
1.60k
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
663
1.60k
        break;                                                                 \
664
11.3k
      default:                                                                 \
665
11.3k
        if (toLim - *toP < 3) {                                                \
666
123
          *fromP = from;                                                       \
667
123
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
668
123
        }                                                                      \
669
11.3k
        /* 16 bits divided 4, 6, 6 amongst 3 bytes */                          \
670
11.3k
        *(*toP)++ = ((hi >> 4) | UTF8_cval3);                                  \
671
11.2k
        *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80);                    \
672
11.2k
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
673
11.2k
        break;                                                                 \
674
11.3k
      case 0xD8:                                                               \
675
0
      case 0xD9:                                                               \
676
0
      case 0xDA:                                                               \
677
0
      case 0xDB:                                                               \
678
0
        if (toLim - *toP < 4) {                                                \
679
0
          *fromP = from;                                                       \
680
0
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
681
0
        }                                                                      \
682
0
        if (fromLim - from < 4) {                                              \
683
0
          *fromP = from;                                                       \
684
0
          return XML_CONVERT_INPUT_INCOMPLETE;                                 \
685
0
        }                                                                      \
686
0
        plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1;                   \
687
0
        *(*toP)++ = (char)((plane >> 2) | UTF8_cval4);                         \
688
0
        *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80);         \
689
0
        from += 2;                                                             \
690
0
        lo2 = GET_LO(from);                                                    \
691
0
        *(*toP)++ = (((lo & 0x3) << 4) | ((GET_HI(from) & 0x3) << 2)           \
692
0
                     | (lo2 >> 6) | 0x80);                                     \
693
0
        *(*toP)++ = ((lo2 & 0x3f) | 0x80);                                     \
694
0
        break;                                                                 \
695
13.7k
      }                                                                        \
696
13.7k
    }                                                                          \
697
1.93k
    *fromP = from;                                                             \
698
1.76k
    if (from < fromLim)                                                        \
699
1.76k
      return XML_CONVERT_INPUT_INCOMPLETE;                                     \
700
1.76k
    else                                                                       \
701
1.76k
      return XML_CONVERT_COMPLETED;                                            \
702
1.76k
  }
xmltok.c:big2_toUtf8
Line
Count
Source
630
1.26k
      char **toP, const char *toLim) {                                         \
631
1.26k
    const char *from = *fromP;                                                 \
632
1.26k
    UNUSED_P(enc);                                                             \
633
1.26k
    fromLim = from + (((fromLim - from) >> 1) << 1); /* shrink to even */      \
634
7.47k
    for (; from < fromLim; from += 2) {                                        \
635
6.31k
      int plane;                                                               \
636
6.31k
      unsigned char lo2;                                                       \
637
6.31k
      unsigned char lo = GET_LO(from);                                         \
638
6.31k
      unsigned char hi = GET_HI(from);                                         \
639
6.31k
      switch (hi) {                                                            \
640
837
      case 0:                                                                  \
641
837
        if (lo < 0x80) {                                                       \
642
747
          if (*toP == toLim) {                                                 \
643
7
            *fromP = from;                                                     \
644
7
            return XML_CONVERT_OUTPUT_EXHAUSTED;                               \
645
7
          }                                                                    \
646
747
          *(*toP)++ = lo;                                                      \
647
740
          break;                                                               \
648
747
        }                                                                      \
649
837
        EXPAT_FALLTHROUGH;                                                     \
650
155
      case 0x1:                                                                \
651
228
      case 0x2:                                                                \
652
252
      case 0x3:                                                                \
653
305
      case 0x4:                                                                \
654
313
      case 0x5:                                                                \
655
319
      case 0x6:                                                                \
656
319
      case 0x7:                                                                \
657
319
        if (toLim - *toP < 2) {                                                \
658
18
          *fromP = from;                                                       \
659
18
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
660
18
        }                                                                      \
661
319
        *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2);                      \
662
301
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
663
301
        break;                                                                 \
664
5.25k
      default:                                                                 \
665
5.25k
        if (toLim - *toP < 3) {                                                \
666
78
          *fromP = from;                                                       \
667
78
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
668
78
        }                                                                      \
669
5.25k
        /* 16 bits divided 4, 6, 6 amongst 3 bytes */                          \
670
5.25k
        *(*toP)++ = ((hi >> 4) | UTF8_cval3);                                  \
671
5.17k
        *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80);                    \
672
5.17k
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
673
5.17k
        break;                                                                 \
674
5.25k
      case 0xD8:                                                               \
675
0
      case 0xD9:                                                               \
676
0
      case 0xDA:                                                               \
677
0
      case 0xDB:                                                               \
678
0
        if (toLim - *toP < 4) {                                                \
679
0
          *fromP = from;                                                       \
680
0
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
681
0
        }                                                                      \
682
0
        if (fromLim - from < 4) {                                              \
683
0
          *fromP = from;                                                       \
684
0
          return XML_CONVERT_INPUT_INCOMPLETE;                                 \
685
0
        }                                                                      \
686
0
        plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1;                   \
687
0
        *(*toP)++ = (char)((plane >> 2) | UTF8_cval4);                         \
688
0
        *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80);         \
689
0
        from += 2;                                                             \
690
0
        lo2 = GET_LO(from);                                                    \
691
0
        *(*toP)++ = (((lo & 0x3) << 4) | ((GET_HI(from) & 0x3) << 2)           \
692
0
                     | (lo2 >> 6) | 0x80);                                     \
693
0
        *(*toP)++ = ((lo2 & 0x3f) | 0x80);                                     \
694
0
        break;                                                                 \
695
6.31k
      }                                                                        \
696
6.31k
    }                                                                          \
697
1.26k
    *fromP = from;                                                             \
698
1.15k
    if (from < fromLim)                                                        \
699
1.15k
      return XML_CONVERT_INPUT_INCOMPLETE;                                     \
700
1.15k
    else                                                                       \
701
1.15k
      return XML_CONVERT_COMPLETED;                                            \
702
1.15k
  }
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
13.7k
#define GET_LO(ptr) ((unsigned char)(ptr)[0])
727
13.7k
#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
6.31k
#define GET_LO(ptr) ((unsigned char)(ptr)[1])
736
6.31k
#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
319k
  ((p)[1] == 0 ? SB_BYTE_TYPE(enc, p) : unicode_byte_type((p)[1], (p)[0]))
746
36
#define LITTLE2_BYTE_TO_ASCII(p) ((p)[1] == 0 ? (p)[0] : -1)
747
4.20k
#define LITTLE2_CHAR_MATCHES(p, c) ((p)[1] == 0 && (p)[0] == (c))
748
#define LITTLE2_IS_NAME_CHAR_MINBPC(p)                                         \
749
27.8k
  UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0])
750
#define LITTLE2_IS_NMSTRT_CHAR_MINBPC(p)                                       \
751
6.01k
  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
12.7k
#  define PREFIX(ident) little2_##ident
791
651k
#  define MINBPC(enc) 2
792
/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
793
319k
#  define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p)
794
36
#  define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(p)
795
4.20k
#  define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(p, c)
796
87
#  define IS_NAME_CHAR(enc, p, n) 0
797
27.8k
#  define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(p)
798
87
#  define IS_NMSTRT_CHAR(enc, p, n) (0)
799
6.01k
#  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
133k
  ((p)[0] == 0 ? SB_BYTE_TYPE(enc, p + 1) : unicode_byte_type((p)[0], (p)[1]))
879
51
#define BIG2_BYTE_TO_ASCII(p) ((p)[0] == 0 ? (p)[1] : -1)
880
824
#define BIG2_CHAR_MATCHES(p, c) ((p)[0] == 0 && (p)[1] == (c))
881
#define BIG2_IS_NAME_CHAR_MINBPC(p)                                            \
882
13.8k
  UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1])
883
#define BIG2_IS_NMSTRT_CHAR_MINBPC(p)                                          \
884
3.21k
  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
6.64k
#  define PREFIX(ident) big2_##ident
924
277k
#  define MINBPC(enc) 2
925
/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
926
133k
#  define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p)
927
51
#  define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(p)
928
824
#  define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(p, c)
929
29
#  define IS_NAME_CHAR(enc, p, n) 0
930
13.8k
#  define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(p)
931
29
#  define IS_NMSTRT_CHAR(enc, p, n) (0)
932
3.21k
#  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
476
                   POSITION *pos) {
1036
476
  UNUSED_P(enc);
1037
476
  normal_updatePosition(&utf8_encoding.enc, ptr, end, pos);
1038
476
}
1039
1040
static int
1041
3.41k
toAscii(const ENCODING *enc, const char *ptr, const char *end) {
1042
3.41k
  char buf[1];
1043
3.41k
  char *p = buf;
1044
3.41k
  XmlUtf8Convert(enc, &ptr, end, &p, p + 1);
1045
3.41k
  if (p == buf)
1046
102
    return -1;
1047
3.31k
  else
1048
3.31k
    return buf[0];
1049
3.41k
}
1050
1051
static int FASTCALL
1052
2.89k
isSpace(int c) {
1053
2.89k
  switch (c) {
1054
1.54k
  case 0x20:
1055
1.55k
  case 0xD:
1056
1.63k
  case 0xA:
1057
1.64k
  case 0x9:
1058
1.64k
    return 1;
1059
2.89k
  }
1060
1.25k
  return 0;
1061
2.89k
}
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
162
                     const char **valPtr, const char **nextTokPtr) {
1070
162
  int c;
1071
162
  char open;
1072
162
  if (ptr == end) {
1073
2
    *namePtr = NULL;
1074
2
    return 1;
1075
2
  }
1076
160
  if (! isSpace(toAscii(enc, ptr, end))) {
1077
0
    *nextTokPtr = ptr;
1078
0
    return 0;
1079
0
  }
1080
1.04k
  do {
1081
1.04k
    ptr += enc->minBytesPerChar;
1082
1.04k
  } while (isSpace(toAscii(enc, ptr, end)));
1083
160
  if (ptr == end) {
1084
0
    *namePtr = NULL;
1085
0
    return 1;
1086
0
  }
1087
160
  *namePtr = ptr;
1088
1.13k
  for (;;) {
1089
1.13k
    c = toAscii(enc, ptr, end);
1090
1.13k
    if (c == -1) {
1091
50
      *nextTokPtr = ptr;
1092
50
      return 0;
1093
50
    }
1094
1.08k
    if (c == ASCII_EQUALS) {
1095
43
      *nameEndPtr = ptr;
1096
43
      break;
1097
43
    }
1098
1.04k
    if (isSpace(c)) {
1099
67
      *nameEndPtr = ptr;
1100
581
      do {
1101
581
        ptr += enc->minBytesPerChar;
1102
581
      } while (isSpace(c = toAscii(enc, ptr, end)));
1103
67
      if (c != ASCII_EQUALS) {
1104
52
        *nextTokPtr = ptr;
1105
52
        return 0;
1106
52
      }
1107
15
      break;
1108
67
    }
1109
978
    ptr += enc->minBytesPerChar;
1110
978
  }
1111
58
  if (ptr == *namePtr) {
1112
5
    *nextTokPtr = ptr;
1113
5
    return 0;
1114
5
  }
1115
53
  ptr += enc->minBytesPerChar;
1116
53
  c = toAscii(enc, ptr, end);
1117
64
  while (isSpace(c)) {
1118
11
    ptr += enc->minBytesPerChar;
1119
11
    c = toAscii(enc, ptr, end);
1120
11
  }
1121
53
  if (c != ASCII_QUOT && c != ASCII_APOS) {
1122
7
    *nextTokPtr = ptr;
1123
7
    return 0;
1124
7
  }
1125
46
  open = (char)c;
1126
46
  ptr += enc->minBytesPerChar;
1127
46
  *valPtr = ptr;
1128
425
  for (;; ptr += enc->minBytesPerChar) {
1129
425
    c = toAscii(enc, ptr, end);
1130
425
    if (c == open)
1131
4
      break;
1132
421
    if (! (ASCII_a <= c && c <= ASCII_z) && ! (ASCII_A <= c && c <= ASCII_Z)
1133
143
        && ! (ASCII_0 <= c && c <= ASCII_9) && c != ASCII_PERIOD
1134
56
        && c != ASCII_MINUS && c != ASCII_UNDERSCORE) {
1135
42
      *nextTokPtr = ptr;
1136
42
      return 0;
1137
42
    }
1138
421
  }
1139
4
  *nextTokPtr = ptr + enc->minBytesPerChar;
1140
4
  return 1;
1141
46
}
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
162
               const ENCODING **encoding, int *standalone) {
1164
162
  const char *val = NULL;
1165
162
  const char *name = NULL;
1166
162
  const char *nameEnd = NULL;
1167
162
  ptr += 5 * enc->minBytesPerChar;
1168
162
  end -= 2 * enc->minBytesPerChar;
1169
162
  if (! parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)
1170
158
      || ! name) {
1171
158
    *badPtr = ptr;
1172
158
    return 0;
1173
158
  }
1174
4
  if (! XmlNameMatchesAscii(enc, name, nameEnd, KW_version)) {
1175
4
    if (! isGeneralTextEntity) {
1176
4
      *badPtr = name;
1177
4
      return 0;
1178
4
    }
1179
4
  } 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
516
checkCharRefNumber(int result) {
1247
516
  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
466
  case 0:
1258
466
    if (latin1_encoding.type[result] == BT_NONXML)
1259
57
      return -1;
1260
409
    break;
1261
409
  case 0xFF:
1262
0
    if (result == 0xFFFE || result == 0xFFFF)
1263
0
      return -1;
1264
0
    break;
1265
516
  }
1266
459
  return result;
1267
516
}
1268
1269
int FASTCALL
1270
420
XmlUtf8Encode(int c, char *buf) {
1271
420
  enum {
1272
    /* minN is minimum legal resulting value for N byte sequence */
1273
420
    min2 = 0x80,
1274
420
    min3 = 0x800,
1275
420
    min4 = 0x10000
1276
420
  };
1277
1278
420
  if (c < 0)
1279
0
    return 0; /* LCOV_EXCL_LINE: this case is always eliminated beforehand */
1280
420
  if (c < min2) {
1281
339
    buf[0] = (char)(c | UTF8_cval1);
1282
339
    return 1;
1283
339
  }
1284
81
  if (c < min3) {
1285
37
    buf[0] = (char)((c >> 6) | UTF8_cval2);
1286
37
    buf[1] = (char)((c & 0x3f) | 0x80);
1287
37
    return 2;
1288
37
  }
1289
44
  if (c < min4) {
1290
27
    buf[0] = (char)((c >> 12) | UTF8_cval3);
1291
27
    buf[1] = (char)(((c >> 6) & 0x3f) | 0x80);
1292
27
    buf[2] = (char)((c & 0x3f) | 0x80);
1293
27
    return 3;
1294
27
  }
1295
17
  if (c < 0x110000) {
1296
17
    buf[0] = (char)((c >> 18) | UTF8_cval4);
1297
17
    buf[1] = (char)(((c >> 12) & 0x3f) | 0x80);
1298
17
    buf[2] = (char)(((c >> 6) & 0x3f) | 0x80);
1299
17
    buf[3] = (char)((c & 0x3f) | 0x80);
1300
17
    return 4;
1301
17
  }
1302
0
  return 0; /* LCOV_EXCL_LINE: this case too is eliminated before calling */
1303
17
}
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
76.7k
getEncodingIndex(const char *name) {
1518
76.7k
  static const char *const encodingNames[] = {
1519
76.7k
      KW_ISO_8859_1, KW_US_ASCII, KW_UTF_8, KW_UTF_16, KW_UTF_16BE, KW_UTF_16LE,
1520
76.7k
  };
1521
76.7k
  int i;
1522
76.7k
  if (name == NULL)
1523
76.7k
    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
36.1k
#define INIT_ENC_INDEX(enc) ((int)(enc)->initEnc.isUtf16)
1535
76.7k
#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
38.3k
         int state, const char *ptr, const char *end, const char **nextTokPtr) {
1547
38.3k
  const ENCODING **encPtr;
1548
1549
38.3k
  if (ptr >= end)
1550
106
    return XML_TOK_NONE;
1551
38.2k
  encPtr = enc->encPtr;
1552
38.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
1.18k
    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
1.18k
    }
1567
1.18k
    switch ((unsigned char)*ptr) {
1568
10
    case 0xFE:
1569
20
    case 0xFF:
1570
23
    case 0xEF: /* possibly first byte of UTF-8 BOM */
1571
23
      if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
1572
0
        break;
1573
23
      EXPAT_FALLTHROUGH;
1574
23
    case 0x00:
1575
128
    case 0x3C:
1576
128
      return XML_TOK_PARTIAL;
1577
1.18k
    }
1578
37.0k
  } else {
1579
37.0k
    switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) {
1580
91
    case 0xFEFF:
1581
91
      if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
1582
0
        break;
1583
91
      *nextTokPtr = ptr + 2;
1584
91
      *encPtr = encodingTable[UTF_16BE_ENC];
1585
91
      return XML_TOK_BOM;
1586
    /* 00 3C is handled in the default case */
1587
7.28k
    case 0x3C00:
1588
7.28k
      if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC
1589
7.28k
           || INIT_ENC_INDEX(enc) == UTF_16_ENC)
1590
0
          && state == XML_CONTENT_STATE)
1591
0
        break;
1592
7.28k
      *encPtr = encodingTable[UTF_16LE_ENC];
1593
7.28k
      return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1594
498
    case 0xFFFE:
1595
498
      if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
1596
0
        break;
1597
498
      *nextTokPtr = ptr + 2;
1598
498
      *encPtr = encodingTable[UTF_16LE_ENC];
1599
498
      return XML_TOK_BOM;
1600
111
    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
111
      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
111
      if (ptr + 2 == end)
1615
4
        return XML_TOK_PARTIAL;
1616
107
      if ((unsigned char)ptr[2] == 0xBF) {
1617
70
        *nextTokPtr = ptr + 3;
1618
70
        *encPtr = encodingTable[UTF_8_ENC];
1619
70
        return XML_TOK_BOM;
1620
70
      }
1621
37
      break;
1622
29.0k
    default:
1623
29.0k
      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
7.01k
        if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC)
1631
0
          break;
1632
7.01k
        *encPtr = encodingTable[UTF_16BE_ENC];
1633
7.01k
        return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1634
22.0k
      } 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
3.35k
        if (state == XML_CONTENT_STATE)
1645
0
          break;
1646
3.35k
        *encPtr = encodingTable[UTF_16LE_ENC];
1647
3.35k
        return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1648
3.35k
      }
1649
18.7k
      break;
1650
37.0k
    }
1651
37.0k
  }
1652
19.8k
  *encPtr = encodingTable[INIT_ENC_INDEX(enc)];
1653
19.8k
  return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1654
38.2k
}
1655
1656
76.7k
#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
115k
#  define NS(x) x##NS
1667
38.3k
#  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 */