Coverage Report

Created: 2026-11-06 11:29

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
2.94k
  (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3)                         \
95
2.94k
                + ((((byte)[0]) & 3) << 1) + ((((byte)[1]) >> 5) & 1)]         \
96
2.94k
   & (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
79
  (namingBitmap                                                                \
105
79
       [((pages)[((((byte)[0]) & 0xF) << 4) + ((((byte)[1]) >> 2) & 0xF)]      \
106
79
         << 3)                                                                 \
107
79
        + ((((byte)[1]) & 3) << 1) + ((((byte)[2]) >> 5) & 1)]                 \
108
79
   & (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
23.5k
  ((*p) < 0xC2 || ((p)[1] & 0x80) == 0 || ((p)[1] & 0xC0) == 0xC0)
122
123
#define UTF8_INVALID3(p)                                                       \
124
841
  (((p)[2] & 0x80) == 0                                                        \
125
841
   || ((*p) == 0xEF && (p)[1] == 0xBF ? (p)[2] > 0xBD                          \
126
838
                                      : ((p)[2] & 0xC0) == 0xC0)               \
127
841
   || ((*p) == 0xE0                                                            \
128
836
           ? (p)[1] < 0xA0 || ((p)[1] & 0xC0) == 0xC0                          \
129
836
           : ((p)[1] & 0x80) == 0                                              \
130
741
                 || ((*p) == 0xED ? (p)[1] > 0x9F : ((p)[1] & 0xC0) == 0xC0)))
131
132
#define UTF8_INVALID4(p)                                                       \
133
1.80k
  (((p)[3] & 0x80) == 0 || ((p)[3] & 0xC0) == 0xC0 || ((p)[2] & 0x80) == 0     \
134
1.80k
   || ((p)[2] & 0xC0) == 0xC0                                                  \
135
1.80k
   || ((*p) == 0xF0                                                            \
136
1.79k
           ? (p)[1] < 0x90 || ((p)[1] & 0xC0) == 0xC0                          \
137
1.79k
           : ((p)[1] & 0x80) == 0                                              \
138
67
                 || ((*p) == 0xF4 ? (p)[1] > 0x8F : ((p)[1] & 0xC0) == 0xC0)))
139
140
static int
141
25
isNever(const ENCODING *enc, const char *p) {
142
25
  UNUSED_P(enc);
143
25
  UNUSED_P(p);
144
25
  return 0;
145
25
}
146
147
static int
148
1.81k
utf8_isName2(const ENCODING *enc, const char *p) {
149
1.81k
  UNUSED_P(enc);
150
1.81k
  return UTF8_GET_NAMING2(namePages, (const unsigned char *)p);
151
1.81k
}
152
153
static int
154
65
utf8_isName3(const ENCODING *enc, const char *p) {
155
65
  UNUSED_P(enc);
156
65
  return UTF8_GET_NAMING3(namePages, (const unsigned char *)p);
157
65
}
158
159
#define utf8_isName4 isNever
160
161
static int
162
1.12k
utf8_isNmstrt2(const ENCODING *enc, const char *p) {
163
1.12k
  UNUSED_P(enc);
164
1.12k
  return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p);
165
1.12k
}
166
167
static int
168
14
utf8_isNmstrt3(const ENCODING *enc, const char *p) {
169
14
  UNUSED_P(enc);
170
14
  return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p);
171
14
}
172
173
#define utf8_isNmstrt4 isNever
174
175
static int
176
23.5k
utf8_isInvalid2(const ENCODING *enc, const char *p) {
177
23.5k
  UNUSED_P(enc);
178
23.5k
  return UTF8_INVALID2((const unsigned char *)p);
179
23.5k
}
180
181
static int
182
841
utf8_isInvalid3(const ENCODING *enc, const char *p) {
183
841
  UNUSED_P(enc);
184
841
  return UTF8_INVALID3((const unsigned char *)p);
185
841
}
186
187
static int
188
1.80k
utf8_isInvalid4(const ENCODING *enc, const char *p) {
189
1.80k
  UNUSED_P(enc);
190
1.80k
  return UTF8_INVALID4((const unsigned char *)p);
191
1.80k
}
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
29.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
194M
#define MINBPC(enc) 1
229
230
#define SB_BYTE_TYPE(enc, p)                                                   \
231
118M
  (((const struct normal_encoding *)(enc))->type[(unsigned char)*(p)])
232
233
118M
#define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p)
234
235
86.2k
#define BYTE_TO_ASCII(enc, p) (*(p))
236
237
1.89k
#define IS_NAME_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isName##n(enc, p))
238
1.15k
#define IS_NMSTRT_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isNmstrt##n(enc, p))
239
#define IS_INVALID_CHAR(enc, p, n)                                             \
240
29.2k
  (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
958k
#define CHAR_MATCHES(enc, p, c) (*(p) == (c))
247
248
725k
#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.80M
                                           const char **fromLimRef) {
273
2.80M
  const char *fromLim = *fromLimRef;
274
2.80M
  size_t walked = 0;
275
2.80M
  for (; fromLim > from; fromLim--, walked++) {
276
2.78M
    const unsigned char prev = (unsigned char)fromLim[-1];
277
2.78M
    if ((prev & 0xf8u)
278
2.78M
        == 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.78M
    } else if ((prev & 0xf0u)
286
2.78M
               == 0xe0u) { /* 3-byte character, lead by 0b1110xxxx byte */
287
0
      if (walked + 1 >= 3) {
288
0
        fromLim += 3 - 1;
289
0
        break;
290
0
      } else {
291
0
        walked = 0;
292
0
      }
293
2.78M
    } else if ((prev & 0xe0u)
294
2.78M
               == 0xc0u) { /* 2-byte character, lead by 0b110xxxxx byte */
295
737
      if (walked + 1 >= 2) {
296
714
        fromLim += 2 - 1;
297
714
        break;
298
714
      } else {
299
23
        walked = 0;
300
23
      }
301
2.78M
    } else if ((prev & 0x80u)
302
2.78M
               == 0x00u) { /* 1-byte character, matching 0b0xxxxxxx */
303
2.78M
      break;
304
2.78M
    }
305
2.78M
  }
306
2.80M
  *fromLimRef = fromLim;
307
2.80M
}
308
309
static enum XML_Convert_Result
310
utf8_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
311
2.80M
            char **toP, const char *toLim) {
312
2.80M
  bool input_incomplete = false;
313
2.80M
  bool output_exhausted = false;
314
315
  /* Avoid copying partial characters (due to limited space). */
316
2.80M
  const ptrdiff_t bytesAvailable = fromLim - *fromP;
317
2.80M
  const ptrdiff_t bytesStorable = toLim - *toP;
318
2.80M
  UNUSED_P(enc);
319
2.80M
  if (bytesAvailable > bytesStorable) {
320
1.19M
    fromLim = *fromP + bytesStorable;
321
1.19M
    output_exhausted = true;
322
1.19M
  }
323
324
  /* Avoid copying partial characters (from incomplete input). */
325
2.80M
  {
326
2.80M
    const char *const fromLimBefore = fromLim;
327
2.80M
    _INTERNAL_trim_to_complete_utf8_characters(*fromP, &fromLim);
328
2.80M
    if (fromLim < fromLimBefore) {
329
23
      input_incomplete = true;
330
23
    }
331
2.80M
  }
332
333
2.80M
  {
334
2.80M
    const ptrdiff_t bytesToCopy = fromLim - *fromP;
335
2.80M
    memcpy(*toP, *fromP, bytesToCopy);
336
2.80M
    *fromP += bytesToCopy;
337
2.80M
    *toP += bytesToCopy;
338
2.80M
  }
339
340
2.80M
  if (output_exhausted) /* needs to go first */
341
1.19M
    return XML_CONVERT_OUTPUT_EXHAUSTED;
342
1.60M
  else if (input_incomplete)
343
0
    return XML_CONVERT_INPUT_INCOMPLETE;
344
1.60M
  else
345
1.60M
    return XML_CONVERT_COMPLETED;
346
2.80M
}
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
17
unicode_byte_type(char hi, char lo) {
541
17
  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
17
  }
562
17
  return BT_NONASCII;
563
17
}
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.29k
      char **toP, const char *toLim) {                                         \
569
1.29k
    const char *from = *fromP;                                                 \
570
1.29k
    UNUSED_P(enc);                                                             \
571
1.29k
    fromLim = from + (((fromLim - from) >> 1) << 1); /* shrink to even */      \
572
9.38k
    for (; from < fromLim; from += 2) {                                        \
573
8.97k
      int plane;                                                               \
574
8.97k
      unsigned char lo2;                                                       \
575
8.97k
      unsigned char lo = GET_LO(from);                                         \
576
8.97k
      unsigned char hi = GET_HI(from);                                         \
577
8.97k
      switch (hi) {                                                            \
578
8.97k
      case 0:                                                                  \
579
8.97k
        if (lo < 0x80) {                                                       \
580
8.97k
          if (*toP == toLim) {                                                 \
581
884
            *fromP = from;                                                     \
582
884
            return XML_CONVERT_OUTPUT_EXHAUSTED;                               \
583
884
          }                                                                    \
584
8.97k
          *(*toP)++ = lo;                                                      \
585
8.09k
          break;                                                               \
586
8.97k
        }                                                                      \
587
8.97k
        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
8.97k
      }                                                                        \
634
8.97k
    }                                                                          \
635
1.29k
    *fromP = from;                                                             \
636
406
    if (from < fromLim)                                                        \
637
406
      return XML_CONVERT_INPUT_INCOMPLETE;                                     \
638
406
    else                                                                       \
639
406
      return XML_CONVERT_COMPLETED;                                            \
640
406
  }
xmltok.c:little2_toUtf8
Line
Count
Source
568
1.29k
      char **toP, const char *toLim) {                                         \
569
1.29k
    const char *from = *fromP;                                                 \
570
1.29k
    UNUSED_P(enc);                                                             \
571
1.29k
    fromLim = from + (((fromLim - from) >> 1) << 1); /* shrink to even */      \
572
9.38k
    for (; from < fromLim; from += 2) {                                        \
573
8.97k
      int plane;                                                               \
574
8.97k
      unsigned char lo2;                                                       \
575
8.97k
      unsigned char lo = GET_LO(from);                                         \
576
8.97k
      unsigned char hi = GET_HI(from);                                         \
577
8.97k
      switch (hi) {                                                            \
578
8.97k
      case 0:                                                                  \
579
8.97k
        if (lo < 0x80) {                                                       \
580
8.97k
          if (*toP == toLim) {                                                 \
581
884
            *fromP = from;                                                     \
582
884
            return XML_CONVERT_OUTPUT_EXHAUSTED;                               \
583
884
          }                                                                    \
584
8.97k
          *(*toP)++ = lo;                                                      \
585
8.09k
          break;                                                               \
586
8.97k
        }                                                                      \
587
8.97k
        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
8.97k
      }                                                                        \
634
8.97k
    }                                                                          \
635
1.29k
    *fromP = from;                                                             \
636
406
    if (from < fromLim)                                                        \
637
406
      return XML_CONVERT_INPUT_INCOMPLETE;                                     \
638
406
    else                                                                       \
639
406
      return XML_CONVERT_COMPLETED;                                            \
640
406
  }
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
8.97k
#define GET_LO(ptr) ((unsigned char)(ptr)[0])
665
8.97k
#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
27.8k
  ((p)[1] == 0 ? SB_BYTE_TYPE(enc, p) : unicode_byte_type((p)[1], (p)[0]))
684
51
#define LITTLE2_BYTE_TO_ASCII(p) ((p)[1] == 0 ? (p)[0] : -1)
685
580
#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
208
#define PREFIX(ident) little2_##ident
698
47.1k
#define MINBPC(enc) 2
699
/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
700
27.8k
#define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p)
701
51
#define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(p)
702
580
#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
1
  ((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
5
#define MINBPC(enc) 2
800
/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
801
1
#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.48k
      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
66
                   POSITION *pos) {
910
66
  UNUSED_P(enc);
911
66
  normal_updatePosition(&utf8_encoding.enc, ptr, end, pos);
912
66
}
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
14.3k
    return -1;
921
1.25M
  else
922
1.25M
    return buf[0];
923
1.26M
}
924
925
static int
926
797k
isSpace(int c) {
927
797k
  switch (c) {
928
71.3k
  case 0x20:
929
71.3k
  case 0xD:
930
71.3k
  case 0xA:
931
71.3k
  case 0x9:
932
71.3k
    return 1;
933
797k
  }
934
726k
  return 0;
935
797k
}
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.2k
    *namePtr = NULL;
948
14.2k
    return 1;
949
14.2k
  }
950
71.2k
  if (! isSpace(toAscii(enc, ptr, end))) {
951
0
    *nextTokPtr = ptr;
952
0
    return 0;
953
0
  }
954
71.2k
  do {
955
71.2k
    ptr += enc->minBytesPerChar;
956
71.2k
  } while (isSpace(toAscii(enc, ptr, end)));
957
71.2k
  if (ptr == end) {
958
1
    *namePtr = NULL;
959
1
    return 1;
960
1
  }
961
71.2k
  *namePtr = ptr;
962
640k
  for (;;) {
963
640k
    c = toAscii(enc, ptr, end);
964
640k
    if (c == -1) {
965
4
      *nextTokPtr = ptr;
966
4
      return 0;
967
4
    }
968
640k
    if (c == ASCII_EQUALS) {
969
71.1k
      *nameEndPtr = ptr;
970
71.1k
      break;
971
71.1k
    }
972
569k
    if (isSpace(c)) {
973
10
      *nameEndPtr = ptr;
974
29
      do {
975
29
        ptr += enc->minBytesPerChar;
976
29
      } while (isSpace(c = toAscii(enc, ptr, end)));
977
10
      if (c != ASCII_EQUALS) {
978
10
        *nextTokPtr = ptr;
979
10
        return 0;
980
10
      }
981
0
      break;
982
10
    }
983
569k
    ptr += enc->minBytesPerChar;
984
569k
  }
985
71.1k
  if (ptr == *namePtr) {
986
0
    *nextTokPtr = ptr;
987
0
    return 0;
988
0
  }
989
71.1k
  ptr += enc->minBytesPerChar;
990
71.1k
  c = toAscii(enc, ptr, end);
991
71.2k
  while (isSpace(c)) {
992
1
    ptr += enc->minBytesPerChar;
993
1
    c = toAscii(enc, ptr, end);
994
1
  }
995
71.1k
  if (c != ASCII_QUOT && c != ASCII_APOS) {
996
2
    *nextTokPtr = ptr;
997
2
    return 0;
998
2
  }
999
71.1k
  open = (char)c;
1000
71.1k
  ptr += enc->minBytesPerChar;
1001
71.1k
  *valPtr = ptr;
1002
341k
  for (;; ptr += enc->minBytesPerChar) {
1003
341k
    c = toAscii(enc, ptr, end);
1004
341k
    if (c == open)
1005
71.1k
      break;
1006
270k
    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
270k
  }
1013
71.1k
  *nextTokPtr = ptr + enc->minBytesPerChar;
1014
71.1k
  return 1;
1015
71.1k
}
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
1
    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
17
    *badPtr = ptr;
1074
17
    return 0;
1075
17
  }
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
1
      *badPtr = val;
1100
1
      return 0;
1101
1
    }
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
338
      if (isGeneralTextEntity) {
1108
        /* a TextDecl must have an EncodingDecl */
1109
0
        *badPtr = ptr;
1110
0
        return 0;
1111
0
      }
1112
338
      return 1;
1113
338
    }
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
13.9k
      return 1;
1131
28.2k
  }
1132
14.3k
  if (! XmlNameMatchesAscii(enc, name, nameEnd, KW_standalone)
1133
14.3k
      || isGeneralTextEntity) {
1134
1
    *badPtr = name;
1135
1
    return 0;
1136
1
  }
1137
14.3k
  if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_yes)) {
1138
14.2k
    if (standalone)
1139
14.2k
      *standalone = 1;
1140
14.2k
  } else if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_no)) {
1141
71
    if (standalone)
1142
71
      *standalone = 0;
1143
71
  } else {
1144
0
    *badPtr = val;
1145
0
    return 0;
1146
0
  }
1147
14.3k
  while (isSpace(toAscii(enc, ptr, end)))
1148
73
    ptr += enc->minBytesPerChar;
1149
14.3k
  if (ptr != end) {
1150
0
    *badPtr = ptr;
1151
0
    return 0;
1152
0
  }
1153
14.3k
  return 1;
1154
14.3k
}
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
109k
getEncodingIndex(const char *name) {
1429
109k
  static const char *const encodingNames[] = {
1430
109k
      KW_ISO_8859_1, KW_US_ASCII, KW_UTF_8, KW_UTF_16, KW_UTF_16BE, KW_UTF_16LE,
1431
109k
  };
1432
109k
  int i;
1433
109k
  if (name == NULL)
1434
80.9k
    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
40.4k
#define INIT_ENC_INDEX(enc) ((int)(enc)->initEnc.isUtf16)
1446
81.0k
#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
40.5k
         int state, const char *ptr, const char *end, const char **nextTokPtr) {
1458
40.5k
  const ENCODING **encPtr;
1459
1460
40.5k
  if (ptr >= end)
1461
22
    return XML_TOK_NONE;
1462
40.4k
  encPtr = enc->encPtr;
1463
40.4k
  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
40.4k
  } else {
1490
40.4k
    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
17
    case 0xFFFE:
1506
17
      if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
1507
0
        break;
1508
17
      *nextTokPtr = ptr + 2;
1509
17
      *encPtr = encodingTable[UTF_16LE_ENC];
1510
17
      return XML_TOK_BOM;
1511
0
    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
0
      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
0
      if (ptr + 2 == end)
1526
0
        return XML_TOK_PARTIAL;
1527
0
      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
0
      break;
1533
40.4k
    default:
1534
40.4k
      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
1
        if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC)
1542
0
          break;
1543
1
        *encPtr = encodingTable[UTF_16BE_ENC];
1544
1
        return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1545
40.4k
      } 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
40.4k
      break;
1561
40.4k
    }
1562
40.4k
  }
1563
40.4k
  *encPtr = encodingTable[INIT_ENC_INDEX(enc)];
1564
40.4k
  return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
1565
40.4k
}
1566
1567
259k
#define NS(x) x
1568
40.5k
#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 */