Coverage Report

Created: 2026-09-28 10:59

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