Coverage Report

Created: 2026-10-14 09:33

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.22k
  (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3)                         \
95
3.22k
                + ((((byte)[0]) & 3) << 1) + ((((byte)[1]) >> 5) & 1)]         \
96
3.22k
   & (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
97
  (namingBitmap                                                                \
105
97
       [((pages)[((((byte)[0]) & 0xF) << 4) + ((((byte)[1]) >> 2) & 0xF)]      \
106
97
         << 3)                                                                 \
107
97
        + ((((byte)[1]) & 3) << 1) + ((((byte)[2]) >> 5) & 1)]                 \
108
97
   & (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
24.3k
  ((*p) < 0xC2 || ((p)[1] & 0x80) == 0 || ((p)[1] & 0xC0) == 0xC0)
122
123
#define UTF8_INVALID3(p)                                                       \
124
1.02k
  (((p)[2] & 0x80) == 0                                                        \
125
1.02k
   || ((*p) == 0xEF && (p)[1] == 0xBF ? (p)[2] > 0xBD                          \
126
1.01k
                                      : ((p)[2] & 0xC0) == 0xC0)               \
127
1.02k
   || ((*p) == 0xE0                                                            \
128
1.01k
           ? (p)[1] < 0xA0 || ((p)[1] & 0xC0) == 0xC0                          \
129
1.01k
           : ((p)[1] & 0x80) == 0                                              \
130
915
                 || ((*p) == 0xED ? (p)[1] > 0x9F : ((p)[1] & 0xC0) == 0xC0)))
131
132
#define UTF8_INVALID4(p)                                                       \
133
1.52k
  (((p)[3] & 0x80) == 0 || ((p)[3] & 0xC0) == 0xC0 || ((p)[2] & 0x80) == 0     \
134
1.52k
   || ((p)[2] & 0xC0) == 0xC0                                                  \
135
1.52k
   || ((*p) == 0xF0                                                            \
136
1.51k
           ? (p)[1] < 0x90 || ((p)[1] & 0xC0) == 0xC0                          \
137
1.51k
           : ((p)[1] & 0x80) == 0                                              \
138
63
                 || ((*p) == 0xF4 ? (p)[1] > 0x8F : ((p)[1] & 0xC0) == 0xC0)))
139
140
static int
141
21
isNever(const ENCODING *enc, const char *p) {
142
21
  UNUSED_P(enc);
143
21
  UNUSED_P(p);
144
21
  return 0;
145
21
}
146
147
static int
148
1.98k
utf8_isName2(const ENCODING *enc, const char *p) {
149
1.98k
  UNUSED_P(enc);
150
1.98k
  return UTF8_GET_NAMING2(namePages, (const unsigned char *)p);
151
1.98k
}
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.23k
utf8_isNmstrt2(const ENCODING *enc, const char *p) {
163
1.23k
  UNUSED_P(enc);
164
1.23k
  return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p);
165
1.23k
}
166
167
static int
168
17
utf8_isNmstrt3(const ENCODING *enc, const char *p) {
169
17
  UNUSED_P(enc);
170
17
  return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p);
171
17
}
172
173
#define utf8_isNmstrt4 isNever
174
175
static int
176
24.3k
utf8_isInvalid2(const ENCODING *enc, const char *p) {
177
24.3k
  UNUSED_P(enc);
178
24.3k
  return UTF8_INVALID2((const unsigned char *)p);
179
24.3k
}
180
181
static int
182
1.02k
utf8_isInvalid3(const ENCODING *enc, const char *p) {
183
1.02k
  UNUSED_P(enc);
184
1.02k
  return UTF8_INVALID3((const unsigned char *)p);
185
1.02k
}
186
187
static int
188
1.52k
utf8_isInvalid4(const ENCODING *enc, const char *p) {
189
1.52k
  UNUSED_P(enc);
190
1.52k
  return UTF8_INVALID4((const unsigned char *)p);
191
1.52k
}
192
193
struct normal_encoding {
194
  ENCODING enc;
195
  unsigned char type[256];
196
  int (*isName2)(const ENCODING *, const char *);
197
  int (*isName3)(const ENCODING *, const char *);
198
  int (*isName4)(const ENCODING *, const char *);
199
  int (*isNmstrt2)(const ENCODING *, const char *);
200
  int (*isNmstrt3)(const ENCODING *, const char *);
201
  int (*isNmstrt4)(const ENCODING *, const char *);
202
  int (*isInvalid2)(const ENCODING *, const char *);
203
  int (*isInvalid3)(const ENCODING *, const char *);
204
  int (*isInvalid4)(const ENCODING *, const char *);
205
};
206
207
30.2k
#define AS_NORMAL_ENCODING(enc) ((const struct normal_encoding *)(enc))
208
209
#define STANDARD_VTABLE(E) /* as nothing */
210
211
#define NORMAL_VTABLE(E)                                                       \
212
  E##isName2, E##isName3, E##isName4, E##isNmstrt2, E##isNmstrt3,              \
213
      E##isNmstrt4, E##isInvalid2, E##isInvalid3, E##isInvalid4
214
215
#define NULL_VTABLE                                                            \
216
  /* isName2 */ NULL, /* isName3 */ NULL, /* isName4 */ NULL,                  \
217
      /* isNmstrt2 */ NULL, /* isNmstrt3 */ NULL, /* isNmstrt4 */ NULL,        \
218
      /* isInvalid2 */ NULL, /* isInvalid3 */ NULL, /* isInvalid4 */ NULL
219
220
#define UTF16_NULL_VTABLE(E) NULL_VTABLE
221
222
static int checkCharRefNumber(int result);
223
224
#include "xmltok_impl.h"
225
#include "ascii.h"
226
227
/* minimum bytes per character */
228
199M
#define MINBPC(enc) 1
229
230
#define SB_BYTE_TYPE(enc, p)                                                   \
231
120M
  (((const struct normal_encoding *)(enc))->type[(unsigned char)*(p)])
232
233
120M
#define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p)
234
235
86.3k
#define BYTE_TO_ASCII(enc, p) (*(p))
236
237
2.07k
#define IS_NAME_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isName##n(enc, p))
238
1.26k
#define IS_NMSTRT_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isNmstrt##n(enc, p))
239
#define IS_INVALID_CHAR(enc, p, n)                                             \
240
30.1k
  (AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p))
241
242
0
#define IS_NAME_CHAR_MINBPC(enc, p) (0)
243
0
#define IS_NMSTRT_CHAR_MINBPC(enc, p) (0)
244
245
/* c is an ASCII character */
246
960k
#define CHAR_MATCHES(enc, p, c) (*(p) == (c))
247
248
742k
#define PREFIX(ident) normal_##ident
249
#define XML_TOK_IMPL_C
250
#include "xmltok_impl.c"
251
#undef XML_TOK_IMPL_C
252
253
#undef MINBPC
254
#undef BYTE_TYPE
255
#undef BYTE_TO_ASCII
256
#undef CHAR_MATCHES
257
#undef IS_NAME_CHAR
258
#undef IS_NAME_CHAR_MINBPC
259
#undef IS_NMSTRT_CHAR
260
#undef IS_NMSTRT_CHAR_MINBPC
261
#undef IS_INVALID_CHAR
262
263
enum { /* UTF8_cvalN is value of masked first byte of N byte sequence */
264
       UTF8_cval1 = 0x00,
265
       UTF8_cval2 = 0xc0,
266
       UTF8_cval3 = 0xe0,
267
       UTF8_cval4 = 0xf0
268
};
269
270
void
271
_INTERNAL_trim_to_complete_utf8_characters(const char *from,
272
2.82M
                                           const char **fromLimRef) {
273
2.82M
  const char *fromLim = *fromLimRef;
274
2.82M
  size_t walked = 0;
275
2.82M
  for (; fromLim > from; fromLim--, walked++) {
276
2.81M
    const unsigned char prev = (unsigned char)fromLim[-1];
277
2.81M
    if ((prev & 0xf8u)
278
2.81M
        == 0xf0u) { /* 4-byte character, lead by 0b11110xxx byte */
279
0
      if (walked + 1 >= 4) {
280
0
        fromLim += 4 - 1;
281
0
        break;
282
0
      } else {
283
0
        walked = 0;
284
0
      }
285
2.81M
    } else if ((prev & 0xf0u)
286
2.81M
               == 0xe0u) { /* 3-byte character, lead by 0b1110xxxx byte */
287
1
      if (walked + 1 >= 3) {
288
1
        fromLim += 3 - 1;
289
1
        break;
290
1
      } else {
291
0
        walked = 0;
292
0
      }
293
2.81M
    } else if ((prev & 0xe0u)
294
2.81M
               == 0xc0u) { /* 2-byte character, lead by 0b110xxxxx byte */
295
869
      if (walked + 1 >= 2) {
296
844
        fromLim += 2 - 1;
297
844
        break;
298
844
      } else {
299
25
        walked = 0;
300
25
      }
301
2.81M
    } else if ((prev & 0x80u)
302
2.81M
               == 0x00u) { /* 1-byte character, matching 0b0xxxxxxx */
303
2.80M
      break;
304
2.80M
    }
305
2.81M
  }
306
2.82M
  *fromLimRef = fromLim;
307
2.82M
}
308
309
static enum XML_Convert_Result
310
utf8_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
311
2.82M
            char **toP, const char *toLim) {
312
2.82M
  bool input_incomplete = false;
313
2.82M
  bool output_exhausted = false;
314
315
  /* Avoid copying partial characters (due to limited space). */
316
2.82M
  const ptrdiff_t bytesAvailable = fromLim - *fromP;
317
2.82M
  const ptrdiff_t bytesStorable = toLim - *toP;
318
2.82M
  UNUSED_P(enc);
319
2.82M
  if (bytesAvailable > bytesStorable) {
320
1.18M
    fromLim = *fromP + bytesStorable;
321
1.18M
    output_exhausted = true;
322
1.18M
  }
323
324
  /* Avoid copying partial characters (from incomplete input). */
325
2.82M
  {
326
2.82M
    const char *const fromLimBefore = fromLim;
327
2.82M
    _INTERNAL_trim_to_complete_utf8_characters(*fromP, &fromLim);
328
2.82M
    if (fromLim < fromLimBefore) {
329
25
      input_incomplete = true;
330
25
    }
331
2.82M
  }
332
333
2.82M
  {
334
2.82M
    const ptrdiff_t bytesToCopy = fromLim - *fromP;
335
2.82M
    memcpy(*toP, *fromP, bytesToCopy);
336
2.82M
    *fromP += bytesToCopy;
337
2.82M
    *toP += bytesToCopy;
338
2.82M
  }
339
340
2.82M
  if (output_exhausted) /* needs to go first */
341
1.18M
    return XML_CONVERT_OUTPUT_EXHAUSTED;
342
1.63M
  else if (input_incomplete)
343
0
    return XML_CONVERT_INPUT_INCOMPLETE;
344
1.63M
  else
345
1.63M
    return XML_CONVERT_COMPLETED;
346
2.82M
}
347
348
static enum XML_Convert_Result
349
utf8_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim,
350
0
             unsigned short **toP, const unsigned short *toLim) {
351
0
  enum XML_Convert_Result res = XML_CONVERT_COMPLETED;
352
0
  unsigned short *to = *toP;
353
0
  const char *from = *fromP;
354
0
  while (from < fromLim && to < toLim) {
355
0
    switch (SB_BYTE_TYPE(enc, from)) {
356
0
    case BT_LEAD2:
357
0
      if (fromLim - from < 2) {
358
0
        res = XML_CONVERT_INPUT_INCOMPLETE;
359
0
        goto after;
360
0
      }
361
0
      *to++ = (unsigned short)(((from[0] & 0x1f) << 6) | (from[1] & 0x3f));
362
0
      from += 2;
363
0
      break;
364
0
    case BT_LEAD3:
365
0
      if (fromLim - from < 3) {
366
0
        res = XML_CONVERT_INPUT_INCOMPLETE;
367
0
        goto after;
368
0
      }
369
0
      *to++ = (unsigned short)(((from[0] & 0xf) << 12) | ((from[1] & 0x3f) << 6)
370
0
                               | (from[2] & 0x3f));
371
0
      from += 3;
372
0
      break;
373
0
    case BT_LEAD4: {
374
0
      unsigned long n;
375
0
      if (toLim - to < 2) {
376
0
        res = XML_CONVERT_OUTPUT_EXHAUSTED;
377
0
        goto after;
378
0
      }
379
0
      if (fromLim - from < 4) {
380
0
        res = XML_CONVERT_INPUT_INCOMPLETE;
381
0
        goto after;
382
0
      }
383
0
      n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12)
384
0
          | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f);
385
0
      n -= 0x10000;
386
0
      to[0] = (unsigned short)((n >> 10) | 0xD800);
387
0
      to[1] = (unsigned short)((n & 0x3FF) | 0xDC00);
388
0
      to += 2;
389
0
      from += 4;
390
0
    } break;
391
0
    default:
392
0
      *to++ = *from++;
393
0
      break;
394
0
    }
395
0
  }
396
0
  if (from < fromLim)
397
0
    res = XML_CONVERT_OUTPUT_EXHAUSTED;
398
0
after:
399
0
  *fromP = from;
400
0
  *toP = to;
401
0
  return res;
402
0
}
403
404
#ifdef XML_NS
405
static const struct normal_encoding utf8_encoding_ns
406
    = {{VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0},
407
       {
408
#  include "asciitab.h"
409
#  include "utf8tab.h"
410
       },
411
       STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)};
412
#endif
413
414
static const struct normal_encoding utf8_encoding
415
    = {{VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0},
416
       {
417
#define BT_COLON BT_NMSTRT
418
#include "asciitab.h"
419
#undef BT_COLON
420
#include "utf8tab.h"
421
       },
422
       STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)};
423
424
#ifdef XML_NS
425
426
static const struct normal_encoding internal_utf8_encoding_ns
427
    = {{VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0},
428
       {
429
#  include "iasciitab.h"
430
#  include "utf8tab.h"
431
       },
432
       STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)};
433
434
#endif
435
436
static const struct normal_encoding internal_utf8_encoding
437
    = {{VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0},
438
       {
439
#define BT_COLON BT_NMSTRT
440
#include "iasciitab.h"
441
#undef BT_COLON
442
#include "utf8tab.h"
443
       },
444
       STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)};
445
446
static enum XML_Convert_Result
447
latin1_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
448
0
              char **toP, const char *toLim) {
449
0
  UNUSED_P(enc);
450
0
  for (;;) {
451
0
    unsigned char c;
452
0
    if (*fromP == fromLim)
453
0
      return XML_CONVERT_COMPLETED;
454
0
    c = (unsigned char)**fromP;
455
0
    if (c & 0x80) {
456
0
      if (toLim - *toP < 2)
457
0
        return XML_CONVERT_OUTPUT_EXHAUSTED;
458
0
      *(*toP)++ = (char)((c >> 6) | UTF8_cval2);
459
0
      *(*toP)++ = (char)((c & 0x3f) | 0x80);
460
0
      (*fromP)++;
461
0
    } else {
462
0
      if (*toP == toLim)
463
0
        return XML_CONVERT_OUTPUT_EXHAUSTED;
464
0
      *(*toP)++ = *(*fromP)++;
465
0
    }
466
0
  }
467
0
}
468
469
static enum XML_Convert_Result
470
latin1_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim,
471
0
               unsigned short **toP, const unsigned short *toLim) {
472
0
  UNUSED_P(enc);
473
0
  while (*fromP < fromLim && *toP < toLim)
474
0
    *(*toP)++ = (unsigned char)*(*fromP)++;
475
476
0
  if ((*toP == toLim) && (*fromP < fromLim))
477
0
    return XML_CONVERT_OUTPUT_EXHAUSTED;
478
0
  else
479
0
    return XML_CONVERT_COMPLETED;
480
0
}
481
482
#ifdef XML_NS
483
484
static const struct normal_encoding latin1_encoding_ns
485
    = {{VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0},
486
       {
487
#  include "asciitab.h"
488
#  include "latin1tab.h"
489
       },
490
       STANDARD_VTABLE(sb_) NULL_VTABLE};
491
492
#endif
493
494
static const struct normal_encoding latin1_encoding
495
    = {{VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0},
496
       {
497
#define BT_COLON BT_NMSTRT
498
#include "asciitab.h"
499
#undef BT_COLON
500
#include "latin1tab.h"
501
       },
502
       STANDARD_VTABLE(sb_) NULL_VTABLE};
503
504
static enum XML_Convert_Result
505
ascii_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
506
0
             char **toP, const char *toLim) {
507
0
  UNUSED_P(enc);
508
0
  while (*fromP < fromLim && *toP < toLim)
509
0
    *(*toP)++ = *(*fromP)++;
510
511
0
  if ((*toP == toLim) && (*fromP < fromLim))
512
0
    return XML_CONVERT_OUTPUT_EXHAUSTED;
513
0
  else
514
0
    return XML_CONVERT_COMPLETED;
515
0
}
516
517
#ifdef XML_NS
518
519
static const struct normal_encoding ascii_encoding_ns
520
    = {{VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0},
521
       {
522
#  include "asciitab.h"
523
           /* BT_NONXML == 0 */
524
       },
525
       STANDARD_VTABLE(sb_) NULL_VTABLE};
526
527
#endif
528
529
static const struct normal_encoding ascii_encoding
530
    = {{VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0},
531
       {
532
#define BT_COLON BT_NMSTRT
533
#include "asciitab.h"
534
#undef BT_COLON
535
           /* BT_NONXML == 0 */
536
       },
537
       STANDARD_VTABLE(sb_) NULL_VTABLE};
538
539
static int
540
18
unicode_byte_type(char hi, char lo) {
541
18
  switch ((unsigned char)hi) {
542
  /* 0xD800-0xDBFF first 16-bit code unit or high surrogate (W1) */
543
0
  case 0xD8:
544
0
  case 0xD9:
545
0
  case 0xDA:
546
0
  case 0xDB:
547
0
    return BT_LEAD4;
548
  /* 0xDC00-0xDFFF second 16-bit code unit or low surrogate (W2) */
549
0
  case 0xDC:
550
0
  case 0xDD:
551
0
  case 0xDE:
552
0
  case 0xDF:
553
0
    return BT_TRAIL;
554
0
  case 0xFF:
555
0
    switch ((unsigned char)lo) {
556
0
    case 0xFF: /* noncharacter-FFFF */
557
0
    case 0xFE: /* noncharacter-FFFE */
558
0
      return BT_NONXML;
559
0
    }
560
0
    break;
561
18
  }
562
18
  return BT_NONASCII;
563
18
}
564
565
#define DEFINE_UTF16_TO_UTF8(E)                                                \
566
  static enum XML_Convert_Result E##toUtf8(                                    \
567
      const ENCODING *enc, const char **fromP, const char *fromLim,            \
568
1.35k
      char **toP, const char *toLim) {                                         \
569
1.35k
    const char *from = *fromP;                                                 \
570
1.35k
    UNUSED_P(enc);                                                             \
571
1.35k
    fromLim = from + (((fromLim - from) >> 1) << 1); /* shrink to even */      \
572
9.71k
    for (; from < fromLim; from += 2) {                                        \
573
9.29k
      int plane;                                                               \
574
9.29k
      unsigned char lo2;                                                       \
575
9.29k
      unsigned char lo = GET_LO(from);                                         \
576
9.29k
      unsigned char hi = GET_HI(from);                                         \
577
9.29k
      switch (hi) {                                                            \
578
9.29k
      case 0:                                                                  \
579
9.29k
        if (lo < 0x80) {                                                       \
580
9.29k
          if (*toP == toLim) {                                                 \
581
936
            *fromP = from;                                                     \
582
936
            return XML_CONVERT_OUTPUT_EXHAUSTED;                               \
583
936
          }                                                                    \
584
9.29k
          *(*toP)++ = lo;                                                      \
585
8.35k
          break;                                                               \
586
9.29k
        }                                                                      \
587
9.29k
        EXPAT_FALLTHROUGH;                                                     \
588
0
      case 0x1:                                                                \
589
0
      case 0x2:                                                                \
590
0
      case 0x3:                                                                \
591
0
      case 0x4:                                                                \
592
0
      case 0x5:                                                                \
593
0
      case 0x6:                                                                \
594
0
      case 0x7:                                                                \
595
0
        if (toLim - *toP < 2) {                                                \
596
0
          *fromP = from;                                                       \
597
0
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
598
0
        }                                                                      \
599
0
        *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2);                      \
600
0
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
601
0
        break;                                                                 \
602
0
      default:                                                                 \
603
0
        if (toLim - *toP < 3) {                                                \
604
0
          *fromP = from;                                                       \
605
0
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
606
0
        }                                                                      \
607
0
        /* 16 bits divided 4, 6, 6 amongst 3 bytes */                          \
608
0
        *(*toP)++ = ((hi >> 4) | UTF8_cval3);                                  \
609
0
        *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80);                    \
610
0
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
611
0
        break;                                                                 \
612
0
      case 0xD8:                                                               \
613
0
      case 0xD9:                                                               \
614
0
      case 0xDA:                                                               \
615
0
      case 0xDB:                                                               \
616
0
        if (toLim - *toP < 4) {                                                \
617
0
          *fromP = from;                                                       \
618
0
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
619
0
        }                                                                      \
620
0
        if (fromLim - from < 4) {                                              \
621
0
          *fromP = from;                                                       \
622
0
          return XML_CONVERT_INPUT_INCOMPLETE;                                 \
623
0
        }                                                                      \
624
0
        plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1;                   \
625
0
        *(*toP)++ = (char)((plane >> 2) | UTF8_cval4);                         \
626
0
        *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80);         \
627
0
        from += 2;                                                             \
628
0
        lo2 = GET_LO(from);                                                    \
629
0
        *(*toP)++ = (((lo & 0x3) << 4) | ((GET_HI(from) & 0x3) << 2)           \
630
0
                     | (lo2 >> 6) | 0x80);                                     \
631
0
        *(*toP)++ = ((lo2 & 0x3f) | 0x80);                                     \
632
0
        break;                                                                 \
633
9.29k
      }                                                                        \
634
9.29k
    }                                                                          \
635
1.35k
    *fromP = from;                                                             \
636
420
    if (from < fromLim)                                                        \
637
420
      return XML_CONVERT_INPUT_INCOMPLETE;                                     \
638
420
    else                                                                       \
639
420
      return XML_CONVERT_COMPLETED;                                            \
640
420
  }
xmltok.c:little2_toUtf8
Line
Count
Source
568
1.35k
      char **toP, const char *toLim) {                                         \
569
1.35k
    const char *from = *fromP;                                                 \
570
1.35k
    UNUSED_P(enc);                                                             \
571
1.35k
    fromLim = from + (((fromLim - from) >> 1) << 1); /* shrink to even */      \
572
9.71k
    for (; from < fromLim; from += 2) {                                        \
573
9.29k
      int plane;                                                               \
574
9.29k
      unsigned char lo2;                                                       \
575
9.29k
      unsigned char lo = GET_LO(from);                                         \
576
9.29k
      unsigned char hi = GET_HI(from);                                         \
577
9.29k
      switch (hi) {                                                            \
578
9.29k
      case 0:                                                                  \
579
9.29k
        if (lo < 0x80) {                                                       \
580
9.29k
          if (*toP == toLim) {                                                 \
581
936
            *fromP = from;                                                     \
582
936
            return XML_CONVERT_OUTPUT_EXHAUSTED;                               \
583
936
          }                                                                    \
584
9.29k
          *(*toP)++ = lo;                                                      \
585
8.35k
          break;                                                               \
586
9.29k
        }                                                                      \
587
9.29k
        EXPAT_FALLTHROUGH;                                                     \
588
0
      case 0x1:                                                                \
589
0
      case 0x2:                                                                \
590
0
      case 0x3:                                                                \
591
0
      case 0x4:                                                                \
592
0
      case 0x5:                                                                \
593
0
      case 0x6:                                                                \
594
0
      case 0x7:                                                                \
595
0
        if (toLim - *toP < 2) {                                                \
596
0
          *fromP = from;                                                       \
597
0
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
598
0
        }                                                                      \
599
0
        *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2);                      \
600
0
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
601
0
        break;                                                                 \
602
0
      default:                                                                 \
603
0
        if (toLim - *toP < 3) {                                                \
604
0
          *fromP = from;                                                       \
605
0
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
606
0
        }                                                                      \
607
0
        /* 16 bits divided 4, 6, 6 amongst 3 bytes */                          \
608
0
        *(*toP)++ = ((hi >> 4) | UTF8_cval3);                                  \
609
0
        *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80);                    \
610
0
        *(*toP)++ = ((lo & 0x3f) | 0x80);                                      \
611
0
        break;                                                                 \
612
0
      case 0xD8:                                                               \
613
0
      case 0xD9:                                                               \
614
0
      case 0xDA:                                                               \
615
0
      case 0xDB:                                                               \
616
0
        if (toLim - *toP < 4) {                                                \
617
0
          *fromP = from;                                                       \
618
0
          return XML_CONVERT_OUTPUT_EXHAUSTED;                                 \
619
0
        }                                                                      \
620
0
        if (fromLim - from < 4) {                                              \
621
0
          *fromP = from;                                                       \
622
0
          return XML_CONVERT_INPUT_INCOMPLETE;                                 \
623
0
        }                                                                      \
624
0
        plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1;                   \
625
0
        *(*toP)++ = (char)((plane >> 2) | UTF8_cval4);                         \
626
0
        *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80);         \
627
0
        from += 2;                                                             \
628
0
        lo2 = GET_LO(from);                                                    \
629
0
        *(*toP)++ = (((lo & 0x3) << 4) | ((GET_HI(from) & 0x3) << 2)           \
630
0
                     | (lo2 >> 6) | 0x80);                                     \
631
0
        *(*toP)++ = ((lo2 & 0x3f) | 0x80);                                     \
632
0
        break;                                                                 \
633
9.29k
      }                                                                        \
634
9.29k
    }                                                                          \
635
1.35k
    *fromP = from;                                                             \
636
420
    if (from < fromLim)                                                        \
637
420
      return XML_CONVERT_INPUT_INCOMPLETE;                                     \
638
420
    else                                                                       \
639
420
      return XML_CONVERT_COMPLETED;                                            \
640
420
  }
Unexecuted instantiation: xmltok.c:big2_toUtf8
641
642
#define DEFINE_UTF16_TO_UTF16(E)                                               \
643
  static enum XML_Convert_Result E##toUtf16(                                   \
644
      const ENCODING *enc, const char **fromP, const char *fromLim,            \
645
0
      unsigned short **toP, const unsigned short *toLim) {                     \
646
0
    enum XML_Convert_Result res = XML_CONVERT_COMPLETED;                       \
647
0
    UNUSED_P(enc);                                                             \
648
0
    fromLim = *fromP + (((fromLim - *fromP) >> 1) << 1); /* shrink to even */  \
649
0
    /* Avoid copying the first half (2 bytes) of surrogate pairs (4 bytes) */  \
650
0
    if (fromLim - *fromP > ((toLim - *toP) << 1)                               \
651
0
        && /* are the last two bytes a high surrogate (0xD800-0xDBFF)? */      \
652
0
        (GET_HI(fromLim - 2) & 0xFC) == 0xD8) {                                \
653
0
      fromLim -= 2;                                                            \
654
0
      res = XML_CONVERT_INPUT_INCOMPLETE;                                      \
655
0
    }                                                                          \
656
0
    for (; *fromP < fromLim && *toP < toLim; *fromP += 2)                      \
657
0
      *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP);                      \
658
0
    if ((*toP == toLim) && (*fromP < fromLim))                                 \
659
0
      return XML_CONVERT_OUTPUT_EXHAUSTED;                                     \
660
0
    else                                                                       \
661
0
      return res;                                                              \
662
0
  }
Unexecuted instantiation: xmltok.c:little2_toUtf16
Unexecuted instantiation: xmltok.c:big2_toUtf16
663
664
9.29k
#define GET_LO(ptr) ((unsigned char)(ptr)[0])
665
9.29k
#define GET_HI(ptr) ((unsigned char)(ptr)[1])
666
667
DEFINE_UTF16_TO_UTF8(little2_)
668
DEFINE_UTF16_TO_UTF16(little2_)
669
670
#undef GET_LO
671
#undef GET_HI
672
673
0
#define GET_LO(ptr) ((unsigned char)(ptr)[1])
674
0
#define GET_HI(ptr) ((unsigned char)(ptr)[0])
675
676
DEFINE_UTF16_TO_UTF8(big2_)
677
DEFINE_UTF16_TO_UTF16(big2_)
678
679
#undef GET_LO
680
#undef GET_HI
681
682
#define LITTLE2_BYTE_TYPE(enc, p)                                              \
683
28.7k
  ((p)[1] == 0 ? SB_BYTE_TYPE(enc, p) : unicode_byte_type((p)[1], (p)[0]))
684
54
#define LITTLE2_BYTE_TO_ASCII(p) ((p)[1] == 0 ? (p)[0] : -1)
685
612
#define LITTLE2_CHAR_MATCHES(p, c) ((p)[1] == 0 && (p)[0] == (c))
686
#define LITTLE2_IS_NAME_CHAR_MINBPC(p)                                         \
687
0
  UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0])
688
#define LITTLE2_IS_NMSTRT_CHAR_MINBPC(p)                                       \
689
0
  UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0])
690
/* A 4-byte UTF-16 character is a surrogate pair; byteType only reports BT_LEAD4
691
   for a high surrogate, so the pair is invalid unless the second unit is a low
692
   surrogate (U+DC00..U+DFFF, i.e. high byte 0xDC..0xDF). */
693
#define LITTLE2_IS_INVALID_CHAR(p, n)                                          \
694
0
  ((n) == 4 && ((unsigned char)(p)[3] & 0xFC) != 0xDC)
695
696
#undef PREFIX
697
216
#define PREFIX(ident) little2_##ident
698
48.6k
#define MINBPC(enc) 2
699
/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
700
28.7k
#define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p)
701
54
#define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(p)
702
612
#define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(p, c)
703
0
#define IS_NAME_CHAR(enc, p, n) 0
704
0
#define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(p)
705
0
#define IS_NMSTRT_CHAR(enc, p, n) (0)
706
0
#define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(p)
707
0
#define IS_INVALID_CHAR(enc, p, n) LITTLE2_IS_INVALID_CHAR(p, n)
708
709
#define XML_TOK_IMPL_C
710
#include "xmltok_impl.c"
711
#undef XML_TOK_IMPL_C
712
713
#undef MINBPC
714
#undef BYTE_TYPE
715
#undef BYTE_TO_ASCII
716
#undef CHAR_MATCHES
717
#undef IS_NAME_CHAR
718
#undef IS_NAME_CHAR_MINBPC
719
#undef IS_NMSTRT_CHAR
720
#undef IS_NMSTRT_CHAR_MINBPC
721
#undef IS_INVALID_CHAR
722
723
#ifdef XML_NS
724
725
static const struct normal_encoding little2_encoding_ns
726
    = {{VTABLE, 2, 0,
727
#  if BYTEORDER == 1234
728
        1
729
#  else
730
        0
731
#  endif
732
       },
733
       {
734
#  include "asciitab.h"
735
#  include "latin1tab.h"
736
       },
737
       STANDARD_VTABLE(little2_) UTF16_NULL_VTABLE(little2_)};
738
739
#endif
740
741
static const struct normal_encoding little2_encoding
742
    = {{VTABLE, 2, 0,
743
#if BYTEORDER == 1234
744
        1
745
#else
746
        0
747
#endif
748
       },
749
       {
750
#define BT_COLON BT_NMSTRT
751
#include "asciitab.h"
752
#undef BT_COLON
753
#include "latin1tab.h"
754
       },
755
       STANDARD_VTABLE(little2_) UTF16_NULL_VTABLE(little2_)};
756
757
#if BYTEORDER != 4321
758
759
#  ifdef XML_NS
760
761
static const struct normal_encoding internal_little2_encoding_ns
762
    = {{VTABLE, 2, 0, 1},
763
       {
764
#    include "iasciitab.h"
765
#    include "latin1tab.h"
766
       },
767
       STANDARD_VTABLE(little2_) UTF16_NULL_VTABLE(little2_)};
768
769
#  endif
770
771
static const struct normal_encoding internal_little2_encoding
772
    = {{VTABLE, 2, 0, 1},
773
       {
774
#  define BT_COLON BT_NMSTRT
775
#  include "iasciitab.h"
776
#  undef BT_COLON
777
#  include "latin1tab.h"
778
       },
779
       STANDARD_VTABLE(little2_) UTF16_NULL_VTABLE(little2_)};
780
781
#endif
782
783
#define BIG2_BYTE_TYPE(enc, p)                                                 \
784
2
  ((p)[0] == 0 ? SB_BYTE_TYPE(enc, p + 1) : unicode_byte_type((p)[0], (p)[1]))
785
0
#define BIG2_BYTE_TO_ASCII(p) ((p)[0] == 0 ? (p)[1] : -1)
786
0
#define BIG2_CHAR_MATCHES(p, c) ((p)[0] == 0 && (p)[1] == (c))
787
#define BIG2_IS_NAME_CHAR_MINBPC(p)                                            \
788
0
  UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1])
789
#define BIG2_IS_NMSTRT_CHAR_MINBPC(p)                                          \
790
0
  UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1])
791
/* A 4-byte UTF-16 character is a surrogate pair; byteType only reports BT_LEAD4
792
   for a high surrogate, so the pair is invalid unless the second unit is a low
793
   surrogate (U+DC00..U+DFFF, i.e. high byte 0xDC..0xDF). */
794
#define BIG2_IS_INVALID_CHAR(p, n)                                             \
795
0
  ((n) == 4 && ((unsigned char)(p)[2] & 0xFC) != 0xDC)
796
797
#undef PREFIX
798
0
#define PREFIX(ident) big2_##ident
799
10
#define MINBPC(enc) 2
800
/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
801
2
#define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p)
802
0
#define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(p)
803
0
#define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(p, c)
804
0
#define IS_NAME_CHAR(enc, p, n) 0
805
0
#define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(p)
806
0
#define IS_NMSTRT_CHAR(enc, p, n) (0)
807
0
#define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(p)
808
0
#define IS_INVALID_CHAR(enc, p, n) BIG2_IS_INVALID_CHAR(p, n)
809
810
#define XML_TOK_IMPL_C
811
#include "xmltok_impl.c"
812
#undef XML_TOK_IMPL_C
813
814
#undef MINBPC
815
#undef BYTE_TYPE
816
#undef BYTE_TO_ASCII
817
#undef CHAR_MATCHES
818
#undef IS_NAME_CHAR
819
#undef IS_NAME_CHAR_MINBPC
820
#undef IS_NMSTRT_CHAR
821
#undef IS_NMSTRT_CHAR_MINBPC
822
#undef IS_INVALID_CHAR
823
824
#ifdef XML_NS
825
826
static const struct normal_encoding big2_encoding_ns
827
    = {{VTABLE, 2, 0,
828
#  if BYTEORDER == 4321
829
        1
830
#  else
831
        0
832
#  endif
833
       },
834
       {
835
#  include "asciitab.h"
836
#  include "latin1tab.h"
837
       },
838
       STANDARD_VTABLE(big2_) UTF16_NULL_VTABLE(big2_)};
839
840
#endif
841
842
static const struct normal_encoding big2_encoding
843
    = {{VTABLE, 2, 0,
844
#if BYTEORDER == 4321
845
        1
846
#else
847
        0
848
#endif
849
       },
850
       {
851
#define BT_COLON BT_NMSTRT
852
#include "asciitab.h"
853
#undef BT_COLON
854
#include "latin1tab.h"
855
       },
856
       STANDARD_VTABLE(big2_) UTF16_NULL_VTABLE(big2_)};
857
858
#if BYTEORDER != 1234
859
860
#  ifdef XML_NS
861
862
static const struct normal_encoding internal_big2_encoding_ns
863
    = {{VTABLE, 2, 0, 1},
864
       {
865
#    include "iasciitab.h"
866
#    include "latin1tab.h"
867
       },
868
       STANDARD_VTABLE(big2_) UTF16_NULL_VTABLE(big2_)};
869
870
#  endif
871
872
static const struct normal_encoding internal_big2_encoding
873
    = {{VTABLE, 2, 0, 1},
874
       {
875
#  define BT_COLON BT_NMSTRT
876
#  include "iasciitab.h"
877
#  undef BT_COLON
878
#  include "latin1tab.h"
879
       },
880
       STANDARD_VTABLE(big2_) UTF16_NULL_VTABLE(big2_)};
881
882
#endif
883
884
#undef PREFIX
885
886
static int
887
113k
streqci(const char *s1, const char *s2) {
888
396k
  for (;;) {
889
396k
    char c1 = *s1++;
890
396k
    char c2 = *s2++;
891
396k
    if (ASCII_a <= c1 && c1 <= ASCII_z)
892
6.52k
      c1 += ASCII_A - ASCII_a;
893
396k
    if (ASCII_a <= c2 && c2 <= ASCII_z)
894
      /* The following line will never get executed.  streqci() is
895
       * only called from two places, both of which guarantee to put
896
       * upper-case strings into s2.
897
       */
898
0
      c2 += ASCII_A - ASCII_a; /* LCOV_EXCL_LINE */
899
396k
    if (c1 != c2)
900
84.9k
      return 0;
901
311k
    if (! c1)
902
28.3k
      break;
903
311k
  }
904
28.3k
  return 1;
905
113k
}
906
907
static void
908
initUpdatePosition(const ENCODING *enc, const char *ptr, const char *end,
909
84
                   POSITION *pos) {
910
84
  UNUSED_P(enc);
911
84
  normal_updatePosition(&utf8_encoding.enc, ptr, end, pos);
912
84
}
913
914
static int
915
1.26M
toAscii(const ENCODING *enc, const char *ptr, const char *end) {
916
1.26M
  char buf[1];
917
1.26M
  char *p = buf;
918
1.26M
  XmlUtf8Convert(enc, &ptr, end, &p, p + 1);
919
1.26M
  if (p == buf)
920
13.9k
    return -1;
921
1.24M
  else
922
1.24M
    return buf[0];
923
1.26M
}
924
925
static int
926
793k
isSpace(int c) {
927
793k
  switch (c) {
928
71.0k
  case 0x20:
929
71.0k
  case 0xD:
930
71.0k
  case 0xA:
931
71.0k
  case 0x9:
932
71.0k
    return 1;
933
793k
  }
934
721k
  return 0;
935
793k
}
936
937
/* Return 1 if there's just optional white space or there's an S
938
   followed by name=val.
939
*/
940
static int
941
parsePseudoAttribute(const ENCODING *enc, const char *ptr, const char *end,
942
                     const char **namePtr, const char **nameEndPtr,
943
85.5k
                     const char **valPtr, const char **nextTokPtr) {
944
85.5k
  int c;
945
85.5k
  char open;
946
85.5k
  if (ptr == end) {
947
14.6k
    *namePtr = NULL;
948
14.6k
    return 1;
949
14.6k
  }
950
70.8k
  if (! isSpace(toAscii(enc, ptr, end))) {
951
0
    *nextTokPtr = ptr;
952
0
    return 0;
953
0
  }
954
70.9k
  do {
955
70.9k
    ptr += enc->minBytesPerChar;
956
70.9k
  } while (isSpace(toAscii(enc, ptr, end)));
957
70.8k
  if (ptr == end) {
958
1
    *namePtr = NULL;
959
1
    return 1;
960
1
  }
961
70.8k
  *namePtr = ptr;
962
637k
  for (;;) {
963
637k
    c = toAscii(enc, ptr, end);
964
637k
    if (c == -1) {
965
3
      *nextTokPtr = ptr;
966
3
      return 0;
967
3
    }
968
637k
    if (c == ASCII_EQUALS) {
969
70.8k
      *nameEndPtr = ptr;
970
70.8k
      break;
971
70.8k
    }
972
566k
    if (isSpace(c)) {
973
12
      *nameEndPtr = ptr;
974
35
      do {
975
35
        ptr += enc->minBytesPerChar;
976
35
      } while (isSpace(c = toAscii(enc, ptr, end)));
977
12
      if (c != ASCII_EQUALS) {
978
12
        *nextTokPtr = ptr;
979
12
        return 0;
980
12
      }
981
0
      break;
982
12
    }
983
566k
    ptr += enc->minBytesPerChar;
984
566k
  }
985
70.8k
  if (ptr == *namePtr) {
986
0
    *nextTokPtr = ptr;
987
0
    return 0;
988
0
  }
989
70.8k
  ptr += enc->minBytesPerChar;
990
70.8k
  c = toAscii(enc, ptr, end);
991
70.8k
  while (isSpace(c)) {
992
1
    ptr += enc->minBytesPerChar;
993
1
    c = toAscii(enc, ptr, end);
994
1
  }
995
70.8k
  if (c != ASCII_QUOT && c != ASCII_APOS) {
996
2
    *nextTokPtr = ptr;
997
2
    return 0;
998
2
  }
999
70.8k
  open = (char)c;
1000
70.8k
  ptr += enc->minBytesPerChar;
1001
70.8k
  *valPtr = ptr;
1002
339k
  for (;; ptr += enc->minBytesPerChar) {
1003
339k
    c = toAscii(enc, ptr, end);
1004
339k
    if (c == open)
1005
70.8k
      break;
1006
269k
    if (! (ASCII_a <= c && c <= ASCII_z) && ! (ASCII_A <= c && c <= ASCII_Z)
1007
142k
        && ! (ASCII_0 <= c && c <= ASCII_9) && c != ASCII_PERIOD
1008
28.2k
        && c != ASCII_MINUS && c != ASCII_UNDERSCORE) {
1009
3
      *nextTokPtr = ptr;
1010
3
      return 0;
1011
3
    }
1012
269k
  }
1013
70.8k
  *nextTokPtr = ptr + enc->minBytesPerChar;
1014
70.8k
  return 1;
1015
70.8k
}
1016
1017
static const char KW_version[]
1018
    = {ASCII_v, ASCII_e, ASCII_r, ASCII_s, ASCII_i, ASCII_o, ASCII_n, '\0'};
1019
1020
static const char KW_encoding[] = {ASCII_e, ASCII_n, ASCII_c, ASCII_o, ASCII_d,
1021
                                   ASCII_i, ASCII_n, ASCII_g, '\0'};
1022
1023
static const char KW_standalone[]
1024
    = {ASCII_s, ASCII_t, ASCII_a, ASCII_n, ASCII_d, ASCII_a,
1025
       ASCII_l, ASCII_o, ASCII_n, ASCII_e, '\0'};
1026
1027
static const char KW_yes[] = {ASCII_y, ASCII_e, ASCII_s, '\0'};
1028
1029
static const char KW_no[] = {ASCII_n, ASCII_o, '\0'};
1030
1031
static const char KW_1_dot[] = {ASCII_1, ASCII_PERIOD, '\0'};
1032
1033
/* Checks a version pseudo-attribute value against the VersionNum production.
1034
   XML 1.0 Fourth Edition only allows the literal "1.0", but the Fifth
1035
   Edition relaxed this to "1." followed by one or more digits, since Expat
1036
   only implements 1.0 itself but plans to track the Fifth Edition's laxer
1037
   grammar here so that "1.1" and similar aren't rejected only to have that
1038
   rejection reverted later. Returns true for a value matching "1.[0-9]+".
1039
   val/valEnd bound the value itself; valEnd is the upper bound used when
1040
   decoding the individual characters between them. */
1041
static bool
1042
checkXmlDeclVersionNum(const ENCODING *enc, const char *val,
1043
28.6k
                       const char *valEnd) {
1044
28.6k
  if (valEnd - val < 2 * enc->minBytesPerChar
1045
28.6k
      || ! XmlNameMatchesAscii(enc, val, val + 2 * enc->minBytesPerChar,
1046
28.6k
                               KW_1_dot))
1047
0
    return false;
1048
28.6k
  val += 2 * enc->minBytesPerChar;
1049
28.6k
  if (val == valEnd)
1050
0
    return false;
1051
57.2k
  for (; val != valEnd; val += enc->minBytesPerChar) {
1052
28.6k
    int c = toAscii(enc, val, valEnd);
1053
28.6k
    if (c < ASCII_0 || c > ASCII_9)
1054
0
      return false;
1055
28.6k
  }
1056
28.6k
  return true;
1057
28.6k
}
1058
1059
static int
1060
doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *, const char *,
1061
                                                 const char *),
1062
               int isGeneralTextEntity, const ENCODING *enc, const char *ptr,
1063
               const char *end, const char **badPtr, const char **versionPtr,
1064
               const char **versionEndPtr, const char **encodingName,
1065
28.6k
               const ENCODING **encoding, int *standalone) {
1066
28.6k
  const char *val = NULL;
1067
28.6k
  const char *name = NULL;
1068
28.6k
  const char *nameEnd = NULL;
1069
28.6k
  ptr += 5 * enc->minBytesPerChar;
1070
28.6k
  end -= 2 * enc->minBytesPerChar;
1071
28.6k
  if (! parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)
1072
28.6k
      || ! name) {
1073
18
    *badPtr = ptr;
1074
18
    return 0;
1075
18
  }
1076
28.6k
  if (! XmlNameMatchesAscii(enc, name, nameEnd, KW_version)) {
1077
1
    if (! isGeneralTextEntity) {
1078
1
      *badPtr = name;
1079
1
      return 0;
1080
1
    }
1081
28.6k
  } else {
1082
28.6k
    if (versionPtr)
1083
28.6k
      *versionPtr = val;
1084
28.6k
    if (versionEndPtr)
1085
28.6k
      *versionEndPtr = ptr;
1086
    /* The version number must not be empty; VersionNum requires at least
1087
       one character.  The encoding and standalone pseudo-attributes below
1088
       already reject an empty value, so keep version consistent. */
1089
28.6k
    if (val == ptr - enc->minBytesPerChar) {
1090
0
      *badPtr = val;
1091
0
      return 0;
1092
0
    }
1093
    /* Expat implements XML 1.0 only, so any version outside the "1.0"/"1.x"
1094
       family is rejected. Following the Fifth Edition's VersionNum
1095
       production (rather than the Fourth Edition's exact "1.0") avoids
1096
       rejecting "1.1" now only to have to revert that once Expat tracks
1097
       the newer edition. */
1098
28.6k
    if (! checkXmlDeclVersionNum(enc, val, ptr - enc->minBytesPerChar)) {
1099
0
      *badPtr = val;
1100
0
      return 0;
1101
0
    }
1102
28.6k
    if (! parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
1103
3
      *badPtr = ptr;
1104
3
      return 0;
1105
3
    }
1106
28.6k
    if (! name) {
1107
321
      if (isGeneralTextEntity) {
1108
        /* a TextDecl must have an EncodingDecl */
1109
0
        *badPtr = ptr;
1110
0
        return 0;
1111
0
      }
1112
321
      return 1;
1113
321
    }
1114
28.6k
  }
1115
28.2k
  if (XmlNameMatchesAscii(enc, name, nameEnd, KW_encoding)) {
1116
28.2k
    int c = toAscii(enc, val, end);
1117
28.2k
    if (! (ASCII_a <= c && c <= ASCII_z) && ! (ASCII_A <= c && c <= ASCII_Z)) {
1118
0
      *badPtr = val;
1119
0
      return 0;
1120
0
    }
1121
28.2k
    if (encodingName)
1122
28.2k
      *encodingName = val;
1123
28.2k
    if (encoding)
1124
28.2k
      *encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar);
1125
28.2k
    if (! parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
1126
0
      *badPtr = ptr;
1127
0
      return 0;
1128
0
    }
1129
28.2k
    if (! name)
1130
14.3k
      return 1;
1131
28.2k
  }
1132
13.9k
  if (! XmlNameMatchesAscii(enc, name, nameEnd, KW_standalone)
1133
13.9k
      || isGeneralTextEntity) {
1134
1
    *badPtr = name;
1135
1
    return 0;
1136
1
  }
1137
13.9k
  if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_yes)) {
1138
13.8k
    if (standalone)
1139
13.8k
      *standalone = 1;
1140
13.8k
  } else if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_no)) {
1141
81
    if (standalone)
1142
81
      *standalone = 0;
1143
81
  } else {
1144
0
    *badPtr = val;
1145
0
    return 0;
1146
0
  }
1147
14.0k
  while (isSpace(toAscii(enc, ptr, end)))
1148
81
    ptr += enc->minBytesPerChar;
1149
13.9k
  if (ptr != end) {
1150
0
    *badPtr = ptr;
1151
0
    return 0;
1152
0
  }
1153
13.9k
  return 1;
1154
13.9k
}
1155
1156
static int
1157
0
checkCharRefNumber(int result) {
1158
0
  switch (result >> 8) {
1159
0
  case 0xD8:
1160
0
  case 0xD9:
1161
0
  case 0xDA:
1162
0
  case 0xDB:
1163
0
  case 0xDC:
1164
0
  case 0xDD:
1165
0
  case 0xDE:
1166
0
  case 0xDF:
1167
0
    return -1;
1168
0
  case 0:
1169
0
    if (latin1_encoding.type[result] == BT_NONXML)
1170
0
      return -1;
1171
0
    break;
1172
0
  case 0xFF:
1173
0
    if (result == 0xFFFE || result == 0xFFFF)
1174
0
      return -1;
1175
0
    break;
1176
0
  }
1177
0
  return result;
1178
0
}
1179
1180
int
1181
0
XmlUtf8Encode(int c, char *buf) {
1182
0
  enum {
1183
    /* minN is minimum legal resulting value for N byte sequence */
1184
0
    min2 = 0x80,
1185
0
    min3 = 0x800,
1186
0
    min4 = 0x10000
1187
0
  };
1188
1189
0
  if (c < 0)
1190
0
    return 0; /* LCOV_EXCL_LINE: this case is always eliminated beforehand */
1191
0
  if (c < min2) {
1192
0
    buf[0] = (char)(c | UTF8_cval1);
1193
0
    return 1;
1194
0
  }
1195
0
  if (c < min3) {
1196
0
    buf[0] = (char)((c >> 6) | UTF8_cval2);
1197
0
    buf[1] = (char)((c & 0x3f) | 0x80);
1198
0
    return 2;
1199
0
  }
1200
0
  if (c < min4) {
1201
0
    buf[0] = (char)((c >> 12) | UTF8_cval3);
1202
0
    buf[1] = (char)(((c >> 6) & 0x3f) | 0x80);
1203
0
    buf[2] = (char)((c & 0x3f) | 0x80);
1204
0
    return 3;
1205
0
  }
1206
0
  if (c < 0x110000) {
1207
0
    buf[0] = (char)((c >> 18) | UTF8_cval4);
1208
0
    buf[1] = (char)(((c >> 12) & 0x3f) | 0x80);
1209
0
    buf[2] = (char)(((c >> 6) & 0x3f) | 0x80);
1210
0
    buf[3] = (char)((c & 0x3f) | 0x80);
1211
0
    return 4;
1212
0
  }
1213
0
  return 0; /* LCOV_EXCL_LINE: this case too is eliminated before calling */
1214
0
}
1215
1216
int
1217
0
XmlUtf16Encode(int charNum, unsigned short *buf) {
1218
0
  if (charNum < 0)
1219
0
    return 0;
1220
0
  if (charNum < 0x10000) {
1221
0
    buf[0] = (unsigned short)charNum;
1222
0
    return 1;
1223
0
  }
1224
0
  if (charNum < 0x110000) {
1225
0
    charNum -= 0x10000;
1226
0
    buf[0] = (unsigned short)((charNum >> 10) + 0xD800);
1227
0
    buf[1] = (unsigned short)((charNum & 0x3FF) + 0xDC00);
1228
0
    return 2;
1229
0
  }
1230
0
  return 0;
1231
0
}
1232
1233
struct unknown_encoding {
1234
  struct normal_encoding normal;
1235
  CONVERTER convert;
1236
  void *userData;
1237
  unsigned short utf16[256];
1238
  char utf8[256][4];
1239
};
1240
1241
0
#define AS_UNKNOWN_ENCODING(enc) ((const struct unknown_encoding *)(enc))
1242
1243
int
1244
0
XmlSizeOfUnknownEncoding(void) {
1245
0
  return sizeof(struct unknown_encoding);
1246
0
}
1247
1248
static int
1249
0
unknown_isName(const ENCODING *enc, const char *p) {
1250
0
  const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
1251
0
  int c = uenc->convert(uenc->userData, p);
1252
0
  if (c & ~0xFFFF)
1253
0
    return 0;
1254
0
  return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF);
1255
0
}
1256
1257
static int
1258
0
unknown_isNmstrt(const ENCODING *enc, const char *p) {
1259
0
  const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
1260
0
  int c = uenc->convert(uenc->userData, p);
1261
0
  if (c & ~0xFFFF)
1262
0
    return 0;
1263
0
  return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF);
1264
0
}
1265
1266
static int
1267
0
unknown_isInvalid(const ENCODING *enc, const char *p) {
1268
0
  const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
1269
0
  int c = uenc->convert(uenc->userData, p);
1270
0
  return (c & ~0xFFFF) || checkCharRefNumber(c) < 0;
1271
0
}
1272
1273
static enum XML_Convert_Result
1274
unknown_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
1275
0
               char **toP, const char *toLim) {
1276
0
  const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
1277
0
  char buf[XML_UTF8_ENCODE_MAX];
1278
0
  for (;;) {
1279
0
    const char *utf8;
1280
0
    int n;
1281
0
    if (*fromP == fromLim)
1282
0
      return XML_CONVERT_COMPLETED;
1283
0
    utf8 = uenc->utf8[(unsigned char)**fromP];
1284
0
    n = *utf8++;
1285
0
    if (n == 0) {
1286
0
      int c = uenc->convert(uenc->userData, *fromP);
1287
0
      n = XmlUtf8Encode(c, buf);
1288
0
      if (n > toLim - *toP)
1289
0
        return XML_CONVERT_OUTPUT_EXHAUSTED;
1290
0
      utf8 = buf;
1291
0
      *fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP]
1292
0
                 - (BT_LEAD2 - 2));
1293
0
    } else {
1294
0
      if (n > toLim - *toP)
1295
0
        return XML_CONVERT_OUTPUT_EXHAUSTED;
1296
0
      (*fromP)++;
1297
0
    }
1298
0
    memcpy(*toP, utf8, n);
1299
0
    *toP += n;
1300
0
  }
1301
0
}
1302
1303
static enum XML_Convert_Result
1304
unknown_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim,
1305
0
                unsigned short **toP, const unsigned short *toLim) {
1306
0
  const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
1307
0
  while (*fromP < fromLim && *toP < toLim) {
1308
0
    unsigned short c = uenc->utf16[(unsigned char)**fromP];
1309
0
    if (c == 0) {
1310
0
      c = (unsigned short)uenc->convert(uenc->userData, *fromP);
1311
0
      *fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP]
1312
0
                 - (BT_LEAD2 - 2));
1313
0
    } else
1314
0
      (*fromP)++;
1315
0
    *(*toP)++ = c;
1316
0
  }
1317
1318
0
  if ((*toP == toLim) && (*fromP < fromLim))
1319
0
    return XML_CONVERT_OUTPUT_EXHAUSTED;
1320
0
  else
1321
0
    return XML_CONVERT_COMPLETED;
1322
0
}
1323
1324
ENCODING *
1325
XmlInitUnknownEncoding(void *mem, const int *table, CONVERTER convert,
1326
0
                       void *userData) {
1327
0
  int i;
1328
0
  struct unknown_encoding *e = (struct unknown_encoding *)mem;
1329
0
  memcpy(mem, &latin1_encoding, sizeof(struct normal_encoding));
1330
0
  for (i = 0; i < 128; i++)
1331
0
    if (latin1_encoding.type[i] != BT_OTHER
1332
0
        && latin1_encoding.type[i] != BT_NONXML && table[i] != i)
1333
0
      return 0;
1334
0
  for (i = 0; i < 256; i++) {
1335
0
    int c = table[i];
1336
0
    if (c == -1) {
1337
0
      e->normal.type[i] = BT_MALFORM;
1338
      /* This shouldn't really get used. */
1339
0
      e->utf16[i] = 0xFFFF;
1340
0
      e->utf8[i][0] = 1;
1341
0
      e->utf8[i][1] = 0;
1342
0
    } else if (c < 0) {
1343
0
      if (c < -4)
1344
0
        return 0;
1345
      /* Multi-byte sequences need a converter function */
1346
0
      if (! convert)
1347
0
        return 0;
1348
0
      e->normal.type[i] = (unsigned char)(BT_LEAD2 - (c + 2));
1349
0
      e->utf8[i][0] = 0;
1350
0
      e->utf16[i] = 0;
1351
0
    } else if (c < 0x80) {
1352
0
      if (latin1_encoding.type[c] != BT_OTHER
1353
0
          && latin1_encoding.type[c] != BT_NONXML && c != i)
1354
0
        return 0;
1355
0
      e->normal.type[i] = latin1_encoding.type[c];
1356
0
      e->utf8[i][0] = 1;
1357
0
      e->utf8[i][1] = (char)c;
1358
0
      e->utf16[i] = (unsigned short)(c == 0 ? 0xFFFF : c);
1359
0
    } else if (checkCharRefNumber(c) < 0) {
1360
0
      e->normal.type[i] = BT_NONXML;
1361
      /* This shouldn't really get used. */
1362
0
      e->utf16[i] = 0xFFFF;
1363
0
      e->utf8[i][0] = 1;
1364
0
      e->utf8[i][1] = 0;
1365
0
    } else {
1366
0
      if (c > 0xFFFF)
1367
0
        return 0;
1368
0
      if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff))
1369
0
        e->normal.type[i] = BT_NMSTRT;
1370
0
      else if (UCS2_GET_NAMING(namePages, c >> 8, c & 0xff))
1371
0
        e->normal.type[i] = BT_NAME;
1372
0
      else
1373
0
        e->normal.type[i] = BT_OTHER;
1374
0
      e->utf8[i][0] = (char)XmlUtf8Encode(c, e->utf8[i] + 1);
1375
0
      e->utf16[i] = (unsigned short)c;
1376
0
    }
1377
0
  }
1378
0
  e->userData = userData;
1379
0
  e->convert = convert;
1380
0
  if (convert) {
1381
0
    e->normal.isName2 = unknown_isName;
1382
0
    e->normal.isName3 = unknown_isName;
1383
0
    e->normal.isName4 = unknown_isName;
1384
0
    e->normal.isNmstrt2 = unknown_isNmstrt;
1385
0
    e->normal.isNmstrt3 = unknown_isNmstrt;
1386
0
    e->normal.isNmstrt4 = unknown_isNmstrt;
1387
0
    e->normal.isInvalid2 = unknown_isInvalid;
1388
0
    e->normal.isInvalid3 = unknown_isInvalid;
1389
0
    e->normal.isInvalid4 = unknown_isInvalid;
1390
0
  }
1391
0
  e->normal.enc.utf8Convert = unknown_toUtf8;
1392
0
  e->normal.enc.utf16Convert = unknown_toUtf16;
1393
0
  return &(e->normal.enc);
1394
0
}
1395
1396
/* If this enumeration is changed, getEncodingIndex and encodings
1397
must also be changed. */
1398
enum {
1399
  UNKNOWN_ENC = -1,
1400
  ISO_8859_1_ENC = 0,
1401
  US_ASCII_ENC,
1402
  UTF_8_ENC,
1403
  UTF_16_ENC,
1404
  UTF_16BE_ENC,
1405
  UTF_16LE_ENC,
1406
  /* must match encodingNames up to here */
1407
  NO_ENC
1408
};
1409
1410
static const char KW_ISO_8859_1[]
1411
    = {ASCII_I, ASCII_S, ASCII_O,     ASCII_MINUS, ASCII_8, ASCII_8,
1412
       ASCII_5, ASCII_9, ASCII_MINUS, ASCII_1,     '\0'};
1413
static const char KW_US_ASCII[]
1414
    = {ASCII_U, ASCII_S, ASCII_MINUS, ASCII_A, ASCII_S,
1415
       ASCII_C, ASCII_I, ASCII_I,     '\0'};
1416
static const char KW_UTF_8[]
1417
    = {ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_8, '\0'};
1418
static const char KW_UTF_16[]
1419
    = {ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, '\0'};
1420
static const char KW_UTF_16BE[]
1421
    = {ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1,
1422
       ASCII_6, ASCII_B, ASCII_E, '\0'};
1423
static const char KW_UTF_16LE[]
1424
    = {ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1,
1425
       ASCII_6, ASCII_L, ASCII_E, '\0'};
1426
1427
static int
1428
112k
getEncodingIndex(const char *name) {
1429
112k
  static const char *const encodingNames[] = {
1430
112k
      KW_ISO_8859_1, KW_US_ASCII, KW_UTF_8, KW_UTF_16, KW_UTF_16BE, KW_UTF_16LE,
1431
112k
  };
1432
112k
  int i;
1433
112k
  if (name == NULL)
1434
84.2k
    return NO_ENC;
1435
85.0k
  for (i = 0; i < (int)(sizeof(encodingNames) / sizeof(encodingNames[0])); i++)
1436
85.0k
    if (streqci(name, encodingNames[i]))
1437
28.3k
      return i;
1438
1
  return UNKNOWN_ENC;
1439
28.3k
}
1440
1441
/* For binary compatibility, we store the index of the encoding
1442
   specified at initialization in the isUtf16 member.
1443
*/
1444
1445
42.1k
#define INIT_ENC_INDEX(enc) ((int)(enc)->initEnc.isUtf16)
1446
84.3k
#define SET_INIT_ENC_INDEX(enc, i) ((enc)->initEnc.isUtf16 = (char)i)
1447
1448
/* This is what detects the encoding.  encodingTable maps from
1449
   encoding indices to encodings; INIT_ENC_INDEX(enc) is the index of
1450
   the external (protocol) specified encoding; state is
1451
   XML_CONTENT_STATE if we're parsing an external text entity, and
1452
   XML_PROLOG_STATE otherwise.
1453
*/
1454
1455
static int
1456
initScan(const ENCODING *const *encodingTable, const INIT_ENCODING *enc,
1457
42.1k
         int state, const char *ptr, const char *end, const char **nextTokPtr) {
1458
42.1k
  const ENCODING **encPtr;
1459
1460
42.1k
  if (ptr >= end)
1461
28
    return XML_TOK_NONE;
1462
42.1k
  encPtr = enc->encPtr;
1463
42.1k
  if (ptr + 1 == end) {
1464
    /* only a single byte available for auto-detection */
1465
#ifndef XML_DTD /* FIXME */
1466
    /* a well-formed document entity must have more than one byte */
1467
    if (state != XML_CONTENT_STATE)
1468
      return XML_TOK_PARTIAL;
1469
#endif
1470
    /* so we're parsing an external text entity... */
1471
    /* if UTF-16 was externally specified, then we need at least 2 bytes */
1472
0
    switch (INIT_ENC_INDEX(enc)) {
1473
0
    case UTF_16_ENC:
1474
0
    case UTF_16LE_ENC:
1475
0
    case UTF_16BE_ENC:
1476
0
      return XML_TOK_PARTIAL;
1477
0
    }
1478
0
    switch ((unsigned char)*ptr) {
1479
0
    case 0xFE:
1480
0
    case 0xFF:
1481
0
    case 0xEF: /* possibly first byte of UTF-8 BOM */
1482
0
      if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
1483
0
        break;
1484
0
      EXPAT_FALLTHROUGH;
1485
0
    case 0x00:
1486
0
    case 0x3C:
1487
0
      return XML_TOK_PARTIAL;
1488
0
    }
1489
42.1k
  } else {
1490
42.1k
    switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) {
1491
0
    case 0xFEFF:
1492
0
      if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
1493
0
        break;
1494
0
      *nextTokPtr = ptr + 2;
1495
0
      *encPtr = encodingTable[UTF_16BE_ENC];
1496
0
      return XML_TOK_BOM;
1497
    /* 00 3C is handled in the default case */
1498
0
    case 0x3C00:
1499
0
      if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC
1500
0
           || INIT_ENC_INDEX(enc) == UTF_16_ENC)
1501
0
          && state == XML_CONTENT_STATE)
1502
0
        break;
1503
0
      *encPtr = encodingTable[UTF_16LE_ENC];
1504
0
      return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1505
18
    case 0xFFFE:
1506
18
      if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
1507
0
        break;
1508
18
      *nextTokPtr = ptr + 2;
1509
18
      *encPtr = encodingTable[UTF_16LE_ENC];
1510
18
      return XML_TOK_BOM;
1511
1
    case 0xEFBB:
1512
      /* Maybe a UTF-8 BOM (EF BB BF) */
1513
      /* If there's an explicitly specified (external) encoding
1514
         of ISO-8859-1 or some flavour of UTF-16
1515
         and this is an external text entity,
1516
         don't look for the BOM,
1517
         because it might be a legal data.
1518
      */
1519
1
      if (state == XML_CONTENT_STATE) {
1520
0
        int e = INIT_ENC_INDEX(enc);
1521
0
        if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC || e == UTF_16LE_ENC
1522
0
            || e == UTF_16_ENC)
1523
0
          break;
1524
0
      }
1525
1
      if (ptr + 2 == end)
1526
0
        return XML_TOK_PARTIAL;
1527
1
      if ((unsigned char)ptr[2] == 0xBF) {
1528
0
        *nextTokPtr = ptr + 3;
1529
0
        *encPtr = encodingTable[UTF_8_ENC];
1530
0
        return XML_TOK_BOM;
1531
0
      }
1532
1
      break;
1533
42.1k
    default:
1534
42.1k
      if (ptr[0] == '\0') {
1535
        /* 0 isn't a legal data character. Furthermore a document
1536
           entity can only start with ASCII characters.  So the only
1537
           way this can fail to be big-endian UTF-16 if it it's an
1538
           external parsed general entity that's labelled as
1539
           UTF-16LE.
1540
        */
1541
2
        if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC)
1542
0
          break;
1543
2
        *encPtr = encodingTable[UTF_16BE_ENC];
1544
2
        return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1545
42.1k
      } else if (ptr[1] == '\0') {
1546
        /* We could recover here in the case:
1547
            - parsing an external entity
1548
            - second byte is 0
1549
            - no externally specified encoding
1550
            - no encoding declaration
1551
           by assuming UTF-16LE.  But we don't, because this would mean when
1552
           presented just with a single byte, we couldn't reliably determine
1553
           whether we needed further bytes.
1554
        */
1555
1
        if (state == XML_CONTENT_STATE)
1556
0
          break;
1557
1
        *encPtr = encodingTable[UTF_16LE_ENC];
1558
1
        return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1559
1
      }
1560
42.1k
      break;
1561
42.1k
    }
1562
42.1k
  }
1563
42.1k
  *encPtr = encodingTable[INIT_ENC_INDEX(enc)];
1564
42.1k
  return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1565
42.1k
}
1566
1567
267k
#define NS(x) x
1568
42.1k
#define ns(x) x
1569
#define XML_TOK_NS_C
1570
#include "xmltok_ns.c"
1571
#undef XML_TOK_NS_C
1572
#undef NS
1573
#undef ns
1574
1575
#ifdef XML_NS
1576
1577
0
#  define NS(x) x##NS
1578
0
#  define ns(x) x##_ns
1579
1580
#  define XML_TOK_NS_C
1581
#  include "xmltok_ns.c"
1582
#  undef XML_TOK_NS_C
1583
1584
#  undef NS
1585
#  undef ns
1586
1587
ENCODING *
1588
XmlInitUnknownEncodingNS(void *mem, const int *table, CONVERTER convert,
1589
0
                         void *userData) {
1590
0
  ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData);
1591
0
  if (enc)
1592
0
    ((struct normal_encoding *)enc)->type[ASCII_COLON] = BT_COLON;
1593
0
  return enc;
1594
0
}
1595
1596
#endif /* XML_NS */