Coverage Report

Created: 2026-07-15 07:31

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
31.3k
  (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
1.56k
  (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3)                         \
91
1.56k
                + ((((byte)[0]) & 3) << 1) + ((((byte)[1]) >> 5) & 1)]         \
92
1.56k
   & (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
1.98k
  (namingBitmap                                                                \
101
1.98k
       [((pages)[((((byte)[0]) & 0xF) << 4) + ((((byte)[1]) >> 2) & 0xF)]      \
102
1.98k
         << 3)                                                                 \
103
1.98k
        + ((((byte)[1]) & 3) << 1) + ((((byte)[2]) >> 5) & 1)]                 \
104
1.98k
   & (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
4.70k
  ((*p) < 0xC2 || ((p)[1] & 0x80) == 0 || ((p)[1] & 0xC0) == 0xC0)
118
119
#define UTF8_INVALID3(p)                                                       \
120
8.62k
  (((p)[2] & 0x80) == 0                                                        \
121
8.62k
   || ((*p) == 0xEF && (p)[1] == 0xBF ? (p)[2] > 0xBD                          \
122
8.34k
                                      : ((p)[2] & 0xC0) == 0xC0)               \
123
8.62k
   || ((*p) == 0xE0                                                            \
124
8.09k
           ? (p)[1] < 0xA0 || ((p)[1] & 0xC0) == 0xC0                          \
125
8.09k
           : ((p)[1] & 0x80) == 0                                              \
126
5.99k
                 || ((*p) == 0xED ? (p)[1] > 0x9F : ((p)[1] & 0xC0) == 0xC0)))
127
128
#define UTF8_INVALID4(p)                                                       \
129
3.24k
  (((p)[3] & 0x80) == 0 || ((p)[3] & 0xC0) == 0xC0 || ((p)[2] & 0x80) == 0     \
130
3.24k
   || ((p)[2] & 0xC0) == 0xC0                                                  \
131
3.24k
   || ((*p) == 0xF0                                                            \
132
2.80k
           ? (p)[1] < 0x90 || ((p)[1] & 0xC0) == 0xC0                          \
133
2.80k
           : ((p)[1] & 0x80) == 0                                              \
134
2.77k
                 || ((*p) == 0xF4 ? (p)[1] > 0x8F : ((p)[1] & 0xC0) == 0xC0)))
135
136
static int PTRFASTCALL
137
267
isNever(const ENCODING *enc, const char *p) {
138
267
  UNUSED_P(enc);
139
267
  UNUSED_P(p);
140
267
  return 0;
141
267
}
142
143
static int PTRFASTCALL
144
1.16k
utf8_isName2(const ENCODING *enc, const char *p) {
145
1.16k
  UNUSED_P(enc);
146
1.16k
  return UTF8_GET_NAMING2(namePages, (const unsigned char *)p);
147
1.16k
}
148
149
static int PTRFASTCALL
150
1.75k
utf8_isName3(const ENCODING *enc, const char *p) {
151
1.75k
  UNUSED_P(enc);
152
1.75k
  return UTF8_GET_NAMING3(namePages, (const unsigned char *)p);
153
1.75k
}
154
155
#define utf8_isName4 isNever
156
157
static int PTRFASTCALL
158
405
utf8_isNmstrt2(const ENCODING *enc, const char *p) {
159
405
  UNUSED_P(enc);
160
405
  return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p);
161
405
}
162
163
static int PTRFASTCALL
164
233
utf8_isNmstrt3(const ENCODING *enc, const char *p) {
165
233
  UNUSED_P(enc);
166
233
  return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p);
167
233
}
168
169
#define utf8_isNmstrt4 isNever
170
171
static int PTRFASTCALL
172
4.70k
utf8_isInvalid2(const ENCODING *enc, const char *p) {
173
4.70k
  UNUSED_P(enc);
174
4.70k
  return UTF8_INVALID2((const unsigned char *)p);
175
4.70k
}
176
177
static int PTRFASTCALL
178
8.62k
utf8_isInvalid3(const ENCODING *enc, const char *p) {
179
8.62k
  UNUSED_P(enc);
180
8.62k
  return UTF8_INVALID3((const unsigned char *)p);
181
8.62k
}
182
183
static int PTRFASTCALL
184
3.24k
utf8_isInvalid4(const ENCODING *enc, const char *p) {
185
3.24k
  UNUSED_P(enc);
186
3.24k
  return UTF8_INVALID4((const unsigned char *)p);
187
3.24k
}
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
20.3k
#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
68.6M
#  define MINBPC(enc) 1
247
#endif
248
249
#define SB_BYTE_TYPE(enc, p)                                                   \
250
46.8M
  (((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
46.7M
#  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
170k
#  define BYTE_TO_ASCII(enc, p) (*(p))
271
#endif
272
273
3.05k
#define IS_NAME_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isName##n(enc, p))
274
759
#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
21.2k
    (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
34.3k
#  define CHAR_MATCHES(enc, p, c) (*(p) == (c))
305
#endif
306
307
370k
#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
608k
                                           const char **fromLimRef) {
332
608k
  const char *fromLim = *fromLimRef;
333
608k
  size_t walked = 0;
334
608k
  for (; fromLim > from; fromLim--, walked++) {
335
606k
    const unsigned char prev = (unsigned char)fromLim[-1];
336
606k
    if ((prev & 0xf8u)
337
606k
        == 0xf0u) { /* 4-byte character, lead by 0b11110xxx byte */
338
71
      if (walked + 1 >= 4) {
339
71
        fromLim += 4 - 1;
340
71
        break;
341
71
      } else {
342
0
        walked = 0;
343
0
      }
344
606k
    } else if ((prev & 0xf0u)
345
606k
               == 0xe0u) { /* 3-byte character, lead by 0b1110xxxx byte */
346
29
      if (walked + 1 >= 3) {
347
21
        fromLim += 3 - 1;
348
21
        break;
349
21
      } else {
350
8
        walked = 0;
351
8
      }
352
606k
    } else if ((prev & 0xe0u)
353
606k
               == 0xc0u) { /* 2-byte character, lead by 0b110xxxxx byte */
354
28
      if (walked + 1 >= 2) {
355
22
        fromLim += 2 - 1;
356
22
        break;
357
22
      } else {
358
6
        walked = 0;
359
6
      }
360
606k
    } else if ((prev & 0x80u)
361
606k
               == 0x00u) { /* 1-byte character, matching 0b0xxxxxxx */
362
606k
      break;
363
606k
    }
364
606k
  }
365
608k
  *fromLimRef = fromLim;
366
608k
}
367
368
static enum XML_Convert_Result PTRCALL
369
utf8_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
370
608k
            char **toP, const char *toLim) {
371
608k
  bool input_incomplete = false;
372
608k
  bool output_exhausted = false;
373
374
  /* Avoid copying partial characters (due to limited space). */
375
608k
  const ptrdiff_t bytesAvailable = fromLim - *fromP;
376
608k
  const ptrdiff_t bytesStorable = toLim - *toP;
377
608k
  UNUSED_P(enc);
378
608k
  if (bytesAvailable > bytesStorable) {
379
3.28k
    fromLim = *fromP + bytesStorable;
380
3.28k
    output_exhausted = true;
381
3.28k
  }
382
383
  /* Avoid copying partial characters (from incomplete input). */
384
608k
  {
385
608k
    const char *const fromLimBefore = fromLim;
386
608k
    _INTERNAL_trim_to_complete_utf8_characters(*fromP, &fromLim);
387
608k
    if (fromLim < fromLimBefore) {
388
14
      input_incomplete = true;
389
14
    }
390
608k
  }
391
392
608k
  {
393
608k
    const ptrdiff_t bytesToCopy = fromLim - *fromP;
394
608k
    memcpy(*toP, *fromP, bytesToCopy);
395
608k
    *fromP += bytesToCopy;
396
608k
    *toP += bytesToCopy;
397
608k
  }
398
399
608k
  if (output_exhausted) /* needs to go first */
400
3.28k
    return XML_CONVERT_OUTPUT_EXHAUSTED;
401
605k
  else if (input_incomplete)
402
0
    return XML_CONVERT_INPUT_INCOMPLETE;
403
605k
  else
404
605k
    return XML_CONVERT_COMPLETED;
405
608k
}
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
160k
unicode_byte_type(char hi, char lo) {
600
160k
  switch ((unsigned char)hi) {
601
  /* 0xD800-0xDBFF first 16-bit code unit or high surrogate (W1) */
602
2.45k
  case 0xD8:
603
3.85k
  case 0xD9:
604
5.06k
  case 0xDA:
605
6.64k
  case 0xDB:
606
6.64k
    return BT_LEAD4;
607
  /* 0xDC00-0xDFFF second 16-bit code unit or low surrogate (W2) */
608
398
  case 0xDC:
609
782
  case 0xDD:
610
1.14k
  case 0xDE:
611
1.54k
  case 0xDF:
612
1.54k
    return BT_TRAIL;
613
4.24k
  case 0xFF:
614
4.24k
    switch ((unsigned char)lo) {
615
749
    case 0xFF: /* noncharacter-FFFF */
616
773
    case 0xFE: /* noncharacter-FFFE */
617
773
      return BT_NONXML;
618
4.24k
    }
619
3.47k
    break;
620
160k
  }
621
151k
  return BT_NONASCII;
622
160k
}
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
2.02k
      char **toP, const char *toLim) {                                         \
628
2.02k
    const char *from = *fromP;                                                 \
629
2.02k
    UNUSED_P(enc);                                                             \
630
2.02k
    fromLim = from + (((fromLim - from) >> 1) << 1); /* shrink to even */      \
631
14.6k
    for (; from < fromLim; from += 2) {                                        \
632
12.8k
      int plane;                                                               \
633
12.8k
      unsigned char lo2;                                                       \
634
12.8k
      unsigned char lo = GET_LO(from);                                         \
635
12.8k
      unsigned char hi = GET_HI(from);                                         \
636
12.8k
      switch (hi) {                                                            \
637
1.36k
      case 0:                                                                  \
638
1.36k
        if (lo < 0x80) {                                                       \
639
1.16k
          if (*toP == toLim) {                                                 \
640
17
            *fromP = from;                                                     \
641
17
            return XML_CONVERT_OUTPUT_EXHAUSTED;                               \
642
17
          }                                                                    \
643
1.16k
          *(*toP)++ = lo;                                                      \
644
1.14k
          break;                                                               \
645
1.16k
        }                                                                      \
646
1.36k
        EXPAT_FALLTHROUGH;                                                     \
647
918
      case 0x1:                                                                \
648
966
      case 0x2:                                                                \
649
1.33k
      case 0x3:                                                                \
650
1.38k
      case 0x4:                                                                \
651
1.41k
      case 0x5:                                                                \
652
1.42k
      case 0x6:                                                                \
653
1.42k
      case 0x7:                                                                \
654
1.42k
        if (toLim - *toP < 2) {                                                \
655
41
          *fromP = from;                                                       \
656
41
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
657
41
        }                                                                      \
658
1.42k
        *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2);                      \
659
1.38k
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
660
1.38k
        break;                                                                 \
661
10.2k
      default:                                                                 \
662
10.2k
        if (toLim - *toP < 3) {                                                \
663
106
          *fromP = from;                                                       \
664
106
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
665
106
        }                                                                      \
666
10.2k
        /* 16 bits divided 4, 6, 6 amongst 3 bytes */                          \
667
10.2k
        *(*toP)++ = ((hi >> 4) | UTF8_cval3);                                  \
668
10.1k
        *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80);                    \
669
10.1k
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
670
10.1k
        break;                                                                 \
671
10.2k
      case 0xD8:                                                               \
672
0
      case 0xD9:                                                               \
673
0
      case 0xDA:                                                               \
674
0
      case 0xDB:                                                               \
675
0
        if (toLim - *toP < 4) {                                                \
676
0
          *fromP = from;                                                       \
677
0
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
678
0
        }                                                                      \
679
0
        if (fromLim - from < 4) {                                              \
680
0
          *fromP = from;                                                       \
681
0
          return XML_CONVERT_INPUT_INCOMPLETE;                                 \
682
0
        }                                                                      \
683
0
        plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1;                   \
684
0
        *(*toP)++ = (char)((plane >> 2) | UTF8_cval4);                         \
685
0
        *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80);         \
686
0
        from += 2;                                                             \
687
0
        lo2 = GET_LO(from);                                                    \
688
0
        *(*toP)++ = (((lo & 0x3) << 4) | ((GET_HI(from) & 0x3) << 2)           \
689
0
                     | (lo2 >> 6) | 0x80);                                     \
690
0
        *(*toP)++ = ((lo2 & 0x3f) | 0x80);                                     \
691
0
        break;                                                                 \
692
12.8k
      }                                                                        \
693
12.8k
    }                                                                          \
694
2.02k
    *fromP = from;                                                             \
695
1.85k
    if (from < fromLim)                                                        \
696
1.85k
      return XML_CONVERT_INPUT_INCOMPLETE;                                     \
697
1.85k
    else                                                                       \
698
1.85k
      return XML_CONVERT_COMPLETED;                                            \
699
1.85k
  }
xmltok.c:little2_toUtf8
Line
Count
Source
627
1.02k
      char **toP, const char *toLim) {                                         \
628
1.02k
    const char *from = *fromP;                                                 \
629
1.02k
    UNUSED_P(enc);                                                             \
630
1.02k
    fromLim = from + (((fromLim - from) >> 1) << 1); /* shrink to even */      \
631
8.67k
    for (; from < fromLim; from += 2) {                                        \
632
7.73k
      int plane;                                                               \
633
7.73k
      unsigned char lo2;                                                       \
634
7.73k
      unsigned char lo = GET_LO(from);                                         \
635
7.73k
      unsigned char hi = GET_HI(from);                                         \
636
7.73k
      switch (hi) {                                                            \
637
708
      case 0:                                                                  \
638
708
        if (lo < 0x80) {                                                       \
639
561
          if (*toP == toLim) {                                                 \
640
11
            *fromP = from;                                                     \
641
11
            return XML_CONVERT_OUTPUT_EXHAUSTED;                               \
642
11
          }                                                                    \
643
561
          *(*toP)++ = lo;                                                      \
644
550
          break;                                                               \
645
561
        }                                                                      \
646
708
        EXPAT_FALLTHROUGH;                                                     \
647
805
      case 0x1:                                                                \
648
818
      case 0x2:                                                                \
649
1.16k
      case 0x3:                                                                \
650
1.17k
      case 0x4:                                                                \
651
1.18k
      case 0x5:                                                                \
652
1.19k
      case 0x6:                                                                \
653
1.19k
      case 0x7:                                                                \
654
1.19k
        if (toLim - *toP < 2) {                                                \
655
27
          *fromP = from;                                                       \
656
27
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
657
27
        }                                                                      \
658
1.19k
        *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2);                      \
659
1.16k
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
660
1.16k
        break;                                                                 \
661
5.97k
      default:                                                                 \
662
5.97k
        if (toLim - *toP < 3) {                                                \
663
40
          *fromP = from;                                                       \
664
40
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
665
40
        }                                                                      \
666
5.97k
        /* 16 bits divided 4, 6, 6 amongst 3 bytes */                          \
667
5.97k
        *(*toP)++ = ((hi >> 4) | UTF8_cval3);                                  \
668
5.93k
        *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80);                    \
669
5.93k
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
670
5.93k
        break;                                                                 \
671
5.97k
      case 0xD8:                                                               \
672
0
      case 0xD9:                                                               \
673
0
      case 0xDA:                                                               \
674
0
      case 0xDB:                                                               \
675
0
        if (toLim - *toP < 4) {                                                \
676
0
          *fromP = from;                                                       \
677
0
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
678
0
        }                                                                      \
679
0
        if (fromLim - from < 4) {                                              \
680
0
          *fromP = from;                                                       \
681
0
          return XML_CONVERT_INPUT_INCOMPLETE;                                 \
682
0
        }                                                                      \
683
0
        plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1;                   \
684
0
        *(*toP)++ = (char)((plane >> 2) | UTF8_cval4);                         \
685
0
        *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80);         \
686
0
        from += 2;                                                             \
687
0
        lo2 = GET_LO(from);                                                    \
688
0
        *(*toP)++ = (((lo & 0x3) << 4) | ((GET_HI(from) & 0x3) << 2)           \
689
0
                     | (lo2 >> 6) | 0x80);                                     \
690
0
        *(*toP)++ = ((lo2 & 0x3f) | 0x80);                                     \
691
0
        break;                                                                 \
692
7.73k
      }                                                                        \
693
7.73k
    }                                                                          \
694
1.02k
    *fromP = from;                                                             \
695
945
    if (from < fromLim)                                                        \
696
945
      return XML_CONVERT_INPUT_INCOMPLETE;                                     \
697
945
    else                                                                       \
698
945
      return XML_CONVERT_COMPLETED;                                            \
699
945
  }
xmltok.c:big2_toUtf8
Line
Count
Source
627
1.00k
      char **toP, const char *toLim) {                                         \
628
1.00k
    const char *from = *fromP;                                                 \
629
1.00k
    UNUSED_P(enc);                                                             \
630
1.00k
    fromLim = from + (((fromLim - from) >> 1) << 1); /* shrink to even */      \
631
5.98k
    for (; from < fromLim; from += 2) {                                        \
632
5.06k
      int plane;                                                               \
633
5.06k
      unsigned char lo2;                                                       \
634
5.06k
      unsigned char lo = GET_LO(from);                                         \
635
5.06k
      unsigned char hi = GET_HI(from);                                         \
636
5.06k
      switch (hi) {                                                            \
637
658
      case 0:                                                                  \
638
658
        if (lo < 0x80) {                                                       \
639
605
          if (*toP == toLim) {                                                 \
640
6
            *fromP = from;                                                     \
641
6
            return XML_CONVERT_OUTPUT_EXHAUSTED;                               \
642
6
          }                                                                    \
643
605
          *(*toP)++ = lo;                                                      \
644
599
          break;                                                               \
645
605
        }                                                                      \
646
658
        EXPAT_FALLTHROUGH;                                                     \
647
113
      case 0x1:                                                                \
648
148
      case 0x2:                                                                \
649
171
      case 0x3:                                                                \
650
211
      case 0x4:                                                                \
651
225
      case 0x5:                                                                \
652
231
      case 0x6:                                                                \
653
231
      case 0x7:                                                                \
654
231
        if (toLim - *toP < 2) {                                                \
655
14
          *fromP = from;                                                       \
656
14
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
657
14
        }                                                                      \
658
231
        *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2);                      \
659
217
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
660
217
        break;                                                                 \
661
4.23k
      default:                                                                 \
662
4.23k
        if (toLim - *toP < 3) {                                                \
663
66
          *fromP = from;                                                       \
664
66
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
665
66
        }                                                                      \
666
4.23k
        /* 16 bits divided 4, 6, 6 amongst 3 bytes */                          \
667
4.23k
        *(*toP)++ = ((hi >> 4) | UTF8_cval3);                                  \
668
4.16k
        *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80);                    \
669
4.16k
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
670
4.16k
        break;                                                                 \
671
4.23k
      case 0xD8:                                                               \
672
0
      case 0xD9:                                                               \
673
0
      case 0xDA:                                                               \
674
0
      case 0xDB:                                                               \
675
0
        if (toLim - *toP < 4) {                                                \
676
0
          *fromP = from;                                                       \
677
0
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
678
0
        }                                                                      \
679
0
        if (fromLim - from < 4) {                                              \
680
0
          *fromP = from;                                                       \
681
0
          return XML_CONVERT_INPUT_INCOMPLETE;                                 \
682
0
        }                                                                      \
683
0
        plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1;                   \
684
0
        *(*toP)++ = (char)((plane >> 2) | UTF8_cval4);                         \
685
0
        *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80);         \
686
0
        from += 2;                                                             \
687
0
        lo2 = GET_LO(from);                                                    \
688
0
        *(*toP)++ = (((lo & 0x3) << 4) | ((GET_HI(from) & 0x3) << 2)           \
689
0
                     | (lo2 >> 6) | 0x80);                                     \
690
0
        *(*toP)++ = ((lo2 & 0x3f) | 0x80);                                     \
691
0
        break;                                                                 \
692
5.06k
      }                                                                        \
693
5.06k
    }                                                                          \
694
1.00k
    *fromP = from;                                                             \
695
914
    if (from < fromLim)                                                        \
696
914
      return XML_CONVERT_INPUT_INCOMPLETE;                                     \
697
914
    else                                                                       \
698
914
      return XML_CONVERT_COMPLETED;                                            \
699
914
  }
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
7.73k
#define GET_LO(ptr) ((unsigned char)(ptr)[0])
723
7.73k
#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
5.06k
#define GET_LO(ptr) ((unsigned char)(ptr)[1])
732
5.06k
#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
128k
  ((p)[1] == 0 ? SB_BYTE_TYPE(enc, p) : unicode_byte_type((p)[1], (p)[0]))
742
16
#define LITTLE2_BYTE_TO_ASCII(p) ((p)[1] == 0 ? (p)[0] : -1)
743
458
#define LITTLE2_CHAR_MATCHES(p, c) ((p)[1] == 0 && (p)[0] == (c))
744
#define LITTLE2_IS_NAME_CHAR_MINBPC(p)                                         \
745
15.2k
  UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0])
746
#define LITTLE2_IS_NMSTRT_CHAR_MINBPC(p)                                       \
747
3.35k
  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
4.69k
#  define PREFIX(ident) little2_##ident
787
256k
#  define MINBPC(enc) 2
788
/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
789
128k
#  define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p)
790
16
#  define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(p)
791
458
#  define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(p, c)
792
94
#  define IS_NAME_CHAR(enc, p, n) 0
793
15.2k
#  define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(p)
794
94
#  define IS_NMSTRT_CHAR(enc, p, n) (0)
795
3.35k
#  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
99.9k
  ((p)[0] == 0 ? SB_BYTE_TYPE(enc, p + 1) : unicode_byte_type((p)[0], (p)[1]))
875
47
#define BIG2_BYTE_TO_ASCII(p) ((p)[0] == 0 ? (p)[1] : -1)
876
619
#define BIG2_CHAR_MATCHES(p, c) ((p)[0] == 0 && (p)[1] == (c))
877
#define BIG2_IS_NAME_CHAR_MINBPC(p)                                            \
878
10.4k
  UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1])
879
#define BIG2_IS_NMSTRT_CHAR_MINBPC(p)                                          \
880
2.33k
  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
5.02k
#  define PREFIX(ident) big2_##ident
920
206k
#  define MINBPC(enc) 2
921
/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
922
99.9k
#  define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p)
923
47
#  define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(p)
924
619
#  define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(p, c)
925
19
#  define IS_NAME_CHAR(enc, p, n) 0
926
10.4k
#  define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(p)
927
19
#  define IS_NMSTRT_CHAR(enc, p, n) (0)
928
2.33k
#  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
334
                   POSITION *pos) {
1032
334
  UNUSED_P(enc);
1033
334
  normal_updatePosition(&utf8_encoding.enc, ptr, end, pos);
1034
334
}
1035
1036
static int
1037
1.02k
toAscii(const ENCODING *enc, const char *ptr, const char *end) {
1038
1.02k
  char buf[1];
1039
1.02k
  char *p = buf;
1040
1.02k
  XmlUtf8Convert(enc, &ptr, end, &p, p + 1);
1041
1.02k
  if (p == buf)
1042
2
    return -1;
1043
1.01k
  else
1044
1.01k
    return buf[0];
1045
1.02k
}
1046
1047
static int FASTCALL
1048
889
isSpace(int c) {
1049
889
  switch (c) {
1050
552
  case 0x20:
1051
556
  case 0xD:
1052
566
  case 0xA:
1053
566
  case 0x9:
1054
566
    return 1;
1055
889
  }
1056
323
  return 0;
1057
889
}
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
43
                     const char **valPtr, const char **nextTokPtr) {
1066
43
  int c;
1067
43
  char open;
1068
43
  if (ptr == end) {
1069
2
    *namePtr = NULL;
1070
2
    return 1;
1071
2
  }
1072
41
  if (! isSpace(toAscii(enc, ptr, end))) {
1073
0
    *nextTokPtr = ptr;
1074
0
    return 0;
1075
0
  }
1076
368
  do {
1077
368
    ptr += enc->minBytesPerChar;
1078
368
  } while (isSpace(toAscii(enc, ptr, end)));
1079
41
  if (ptr == end) {
1080
0
    *namePtr = NULL;
1081
0
    return 1;
1082
0
  }
1083
41
  *namePtr = ptr;
1084
286
  for (;;) {
1085
286
    c = toAscii(enc, ptr, end);
1086
286
    if (c == -1) {
1087
2
      *nextTokPtr = ptr;
1088
2
      return 0;
1089
2
    }
1090
284
    if (c == ASCII_EQUALS) {
1091
18
      *nameEndPtr = ptr;
1092
18
      break;
1093
18
    }
1094
266
    if (isSpace(c)) {
1095
21
      *nameEndPtr = ptr;
1096
196
      do {
1097
196
        ptr += enc->minBytesPerChar;
1098
196
      } while (isSpace(c = toAscii(enc, ptr, end)));
1099
21
      if (c != ASCII_EQUALS) {
1100
21
        *nextTokPtr = ptr;
1101
21
        return 0;
1102
21
      }
1103
0
      break;
1104
21
    }
1105
245
    ptr += enc->minBytesPerChar;
1106
245
  }
1107
18
  if (ptr == *namePtr) {
1108
2
    *nextTokPtr = ptr;
1109
2
    return 0;
1110
2
  }
1111
16
  ptr += enc->minBytesPerChar;
1112
16
  c = toAscii(enc, ptr, end);
1113
18
  while (isSpace(c)) {
1114
2
    ptr += enc->minBytesPerChar;
1115
2
    c = toAscii(enc, ptr, end);
1116
2
  }
1117
16
  if (c != ASCII_QUOT && c != ASCII_APOS) {
1118
5
    *nextTokPtr = ptr;
1119
5
    return 0;
1120
5
  }
1121
11
  open = (char)c;
1122
11
  ptr += enc->minBytesPerChar;
1123
11
  *valPtr = ptr;
1124
111
  for (;; ptr += enc->minBytesPerChar) {
1125
111
    c = toAscii(enc, ptr, end);
1126
111
    if (c == open)
1127
0
      break;
1128
111
    if (! (ASCII_a <= c && c <= ASCII_z) && ! (ASCII_A <= c && c <= ASCII_Z)
1129
22
        && ! (ASCII_0 <= c && c <= ASCII_9) && c != ASCII_PERIOD
1130
11
        && c != ASCII_MINUS && c != ASCII_UNDERSCORE) {
1131
11
      *nextTokPtr = ptr;
1132
11
      return 0;
1133
11
    }
1134
111
  }
1135
0
  *nextTokPtr = ptr + enc->minBytesPerChar;
1136
0
  return 1;
1137
11
}
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
43
               const ENCODING **encoding, int *standalone) {
1160
43
  const char *val = NULL;
1161
43
  const char *name = NULL;
1162
43
  const char *nameEnd = NULL;
1163
43
  ptr += 5 * enc->minBytesPerChar;
1164
43
  end -= 2 * enc->minBytesPerChar;
1165
43
  if (! parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)
1166
43
      || ! name) {
1167
43
    *badPtr = ptr;
1168
43
    return 0;
1169
43
  }
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
80
checkCharRefNumber(int result) {
1243
80
  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
79
  case 0:
1254
79
    if (latin1_encoding.type[result] == BT_NONXML)
1255
17
      return -1;
1256
62
    break;
1257
62
  case 0xFF:
1258
0
    if (result == 0xFFFE || result == 0xFFFF)
1259
0
      return -1;
1260
0
    break;
1261
80
  }
1262
63
  return result;
1263
80
}
1264
1265
int FASTCALL
1266
63
XmlUtf8Encode(int c, char *buf) {
1267
63
  enum {
1268
    /* minN is minimum legal resulting value for N byte sequence */
1269
63
    min2 = 0x80,
1270
63
    min3 = 0x800,
1271
63
    min4 = 0x10000
1272
63
  };
1273
1274
63
  if (c < 0)
1275
0
    return 0; /* LCOV_EXCL_LINE: this case is always eliminated beforehand */
1276
63
  if (c < min2) {
1277
62
    buf[0] = (char)(c | UTF8_cval1);
1278
62
    return 1;
1279
62
  }
1280
1
  if (c < min3) {
1281
1
    buf[0] = (char)((c >> 6) | UTF8_cval2);
1282
1
    buf[1] = (char)((c & 0x3f) | 0x80);
1283
1
    return 2;
1284
1
  }
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
41.5k
getEncodingIndex(const char *name) {
1514
41.5k
  static const char *const encodingNames[] = {
1515
41.5k
      KW_ISO_8859_1, KW_US_ASCII, KW_UTF_8, KW_UTF_16, KW_UTF_16BE, KW_UTF_16LE,
1516
41.5k
  };
1517
41.5k
  int i;
1518
41.5k
  if (name == NULL)
1519
41.5k
    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
17.7k
#define INIT_ENC_INDEX(enc) ((int)(enc)->initEnc.isUtf16)
1531
41.5k
#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
20.7k
         int state, const char *ptr, const char *end, const char **nextTokPtr) {
1543
20.7k
  const ENCODING **encPtr;
1544
1545
20.7k
  if (ptr >= end)
1546
73
    return XML_TOK_NONE;
1547
20.7k
  encPtr = enc->encPtr;
1548
20.7k
  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
833
    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
833
    }
1563
833
    switch ((unsigned char)*ptr) {
1564
9
    case 0xFE:
1565
17
    case 0xFF:
1566
20
    case 0xEF: /* possibly first byte of UTF-8 BOM */
1567
20
      if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
1568
0
        break;
1569
20
      EXPAT_FALLTHROUGH;
1570
20
    case 0x00:
1571
90
    case 0x3C:
1572
90
      return XML_TOK_PARTIAL;
1573
833
    }
1574
19.8k
  } else {
1575
19.8k
    switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) {
1576
46
    case 0xFEFF:
1577
46
      if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
1578
0
        break;
1579
46
      *nextTokPtr = ptr + 2;
1580
46
      *encPtr = encodingTable[UTF_16BE_ENC];
1581
46
      return XML_TOK_BOM;
1582
    /* 00 3C is handled in the default case */
1583
2.69k
    case 0x3C00:
1584
2.69k
      if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC
1585
2.69k
           || INIT_ENC_INDEX(enc) == UTF_16_ENC)
1586
0
          && state == XML_CONTENT_STATE)
1587
0
        break;
1588
2.69k
      *encPtr = encodingTable[UTF_16LE_ENC];
1589
2.69k
      return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1590
374
    case 0xFFFE:
1591
374
      if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
1592
0
        break;
1593
374
      *nextTokPtr = ptr + 2;
1594
374
      *encPtr = encodingTable[UTF_16LE_ENC];
1595
374
      return XML_TOK_BOM;
1596
36
    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
36
      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
36
      if (ptr + 2 == end)
1611
4
        return XML_TOK_PARTIAL;
1612
32
      if ((unsigned char)ptr[2] == 0xBF) {
1613
13
        *nextTokPtr = ptr + 3;
1614
13
        *encPtr = encodingTable[UTF_8_ENC];
1615
13
        return XML_TOK_BOM;
1616
13
      }
1617
19
      break;
1618
16.7k
    default:
1619
16.7k
      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
4.70k
        if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC)
1627
0
          break;
1628
4.70k
        *encPtr = encodingTable[UTF_16BE_ENC];
1629
4.70k
        return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1630
12.0k
      } 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
1.76k
        if (state == XML_CONTENT_STATE)
1641
0
          break;
1642
1.76k
        *encPtr = encodingTable[UTF_16LE_ENC];
1643
1.76k
        return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1644
1.76k
      }
1645
10.2k
      break;
1646
19.8k
    }
1647
19.8k
  }
1648
11.0k
  *encPtr = encodingTable[INIT_ENC_INDEX(enc)];
1649
11.0k
  return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1650
20.7k
}
1651
1652
41.5k
#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
62.4k
#  define NS(x) x##NS
1663
20.7k
#  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 */