Coverage Report

Created: 2026-07-30 07:17

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