Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch expat-update Excluding Merge-Ins

This is equivalent to a diff from 6fcae124ae to f540486a07

2022-01-27
13:37
Fixed memory leak in case of dom parsing w/ a -validateCmd which is in use. check-in: 436f9b8957 user: rolf tags: trunk
2022-01-15
16:39
Start integrate new BillionLaughsAttackProtection featurs. Closed-Leaf check-in: f540486a07 user: rolf tags: expat-update
16:29
Expat 2.4.2 check-in: 3c331ee575 user: rolf tags: expat-update
2022-01-10
01:35
Fixed argument check of a few schema commands. check-in: 6fcae124ae user: rolf tags: trunk
01:07
Fixed possible bufffer overrun because of too small buffer for a sprintf. check-in: c18371f74a user: rolf tags: trunk

Changes to expat/VERSION.

     1         -expat-2.3.0
            1  +expat-2.4.2

Changes to expat/ascii.h.

     2      2                               __  __            _
     3      3                            ___\ \/ /_ __   __ _| |_
     4      4                           / _ \\  /| '_ \ / _` | __|
     5      5                          |  __//  \| |_) | (_| | |_
     6      6                           \___/_/\_\ .__/ \__,_|\__|
     7      7                                    |_| XML parser
     8      8   
     9         -   Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
    10         -   Copyright (c) 2000-2017 Expat development team
            9  +   Copyright (c) 1999-2000 Thai Open Source Software Center Ltd
           10  +   Copyright (c) 2000      Clark Cooper <coopercc@users.sourceforge.net>
           11  +   Copyright (c) 2002      Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
           12  +   Copyright (c) 2007      Karl Waclawek <karl@waclawek.net>
           13  +   Copyright (c) 2017      Sebastian Pipping <sebastian@pipping.org>
    11     14      Licensed under the MIT license:
    12     15   
    13     16      Permission is  hereby granted,  free of charge,  to any  person obtaining
    14     17      a  copy  of  this  software   and  associated  documentation  files  (the
    15     18      "Software"),  to  deal in  the  Software  without restriction,  including
    16     19      without  limitation the  rights  to use,  copy,  modify, merge,  publish,
    17     20      distribute, sublicense, and/or sell copies of the Software, and to permit

Changes to expat/asciitab.h.

     3      3                            ___\ \/ /_ __   __ _| |_
     4      4                           / _ \\  /| '_ \ / _` | __|
     5      5                          |  __//  \| |_) | (_| | |_
     6      6                           \___/_/\_\ .__/ \__,_|\__|
     7      7                                    |_| XML parser
     8      8   
     9      9      Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
    10         -   Copyright (c) 2000-2017 Expat development team
           10  +   Copyright (c) 2000      Clark Cooper <coopercc@users.sourceforge.net>
           11  +   Copyright (c) 2002      Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
           12  +   Copyright (c) 2017      Sebastian Pipping <sebastian@pipping.org>
    11     13      Licensed under the MIT license:
    12     14   
    13     15      Permission is  hereby granted,  free of charge,  to any  person obtaining
    14     16      a  copy  of  this  software   and  associated  documentation  files  (the
    15     17      "Software"),  to  deal in  the  Software  without restriction,  including
    16     18      without  limitation the  rights  to use,  copy,  modify, merge,  publish,
    17     19      distribute, sublicense, and/or sell copies of the Software, and to permit

Changes to expat/expat.h.

     3      3                            ___\ \/ /_ __   __ _| |_
     4      4                           / _ \\  /| '_ \ / _` | __|
     5      5                          |  __//  \| |_) | (_| | |_
     6      6                           \___/_/\_\ .__/ \__,_|\__|
     7      7                                    |_| XML parser
     8      8   
     9      9      Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
    10         -   Copyright (c) 2000-2017 Expat development team
           10  +   Copyright (c) 2000      Clark Cooper <coopercc@users.sourceforge.net>
           11  +   Copyright (c) 2000-2005 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
           12  +   Copyright (c) 2001-2002 Greg Stein <gstein@users.sourceforge.net>
           13  +   Copyright (c) 2002-2016 Karl Waclawek <karl@waclawek.net>
           14  +   Copyright (c) 2016-2021 Sebastian Pipping <sebastian@pipping.org>
           15  +   Copyright (c) 2016      Cristian Rodríguez <crrodriguez@opensuse.org>
           16  +   Copyright (c) 2016      Thomas Beutlich <tc@tbeu.de>
           17  +   Copyright (c) 2017      Rhodri James <rhodri@wildebeest.org.uk>
    11     18      Licensed under the MIT license:
    12     19   
    13     20      Permission is  hereby granted,  free of charge,  to any  person obtaining
    14     21      a  copy  of  this  software   and  associated  documentation  files  (the
    15     22      "Software"),  to  deal in  the  Software  without restriction,  including
    16     23      without  limitation the  rights  to use,  copy,  modify, merge,  publish,
    17     24      distribute, sublicense, and/or sell copies of the Software, and to permit
................................................................................
   113    120     /* Added in 2.0. */
   114    121     XML_ERROR_RESERVED_PREFIX_XML,
   115    122     XML_ERROR_RESERVED_PREFIX_XMLNS,
   116    123     XML_ERROR_RESERVED_NAMESPACE_URI,
   117    124     /* Added in 2.2.1. */
   118    125     XML_ERROR_INVALID_ARGUMENT,
   119    126     /* Added in 2.3.0. */
   120         -  XML_ERROR_NO_BUFFER
          127  +  XML_ERROR_NO_BUFFER,
          128  +  /* Added in 2.4.0. */
          129  +  XML_ERROR_AMPLIFICATION_LIMIT_BREACH
   121    130   };
   122    131   
   123    132   enum XML_Content_Type {
   124    133     XML_CTYPE_EMPTY = 1,
   125    134     XML_CTYPE_ANY,
   126    135     XML_CTYPE_MIXED,
   127    136     XML_CTYPE_NAME,
................................................................................
   995   1004     XML_FEATURE_DTD,
   996   1005     XML_FEATURE_CONTEXT_BYTES,
   997   1006     XML_FEATURE_MIN_SIZE,
   998   1007     XML_FEATURE_SIZEOF_XML_CHAR,
   999   1008     XML_FEATURE_SIZEOF_XML_LCHAR,
  1000   1009     XML_FEATURE_NS,
  1001   1010     XML_FEATURE_LARGE_SIZE,
  1002         -  XML_FEATURE_ATTR_INFO
         1011  +  XML_FEATURE_ATTR_INFO,
         1012  +  /* Added in Expat 2.4.0. */
         1013  +  XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT,
         1014  +  XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT
  1003   1015     /* Additional features must be added to the end of this enum. */
  1004   1016   };
  1005   1017   
  1006   1018   typedef struct {
  1007   1019     enum XML_FeatureEnum feature;
  1008   1020     const XML_LChar *name;
  1009   1021     long int value;
  1010   1022   } XML_Feature;
  1011   1023   
  1012   1024   XMLPARSEAPI(const XML_Feature *)
  1013   1025   XML_GetFeatureList(void);
         1026  +
         1027  +#ifdef XML_DTD
         1028  +/* Added in Expat 2.4.0. */
         1029  +XMLPARSEAPI(XML_Bool)
         1030  +XML_SetBillionLaughsAttackProtectionMaximumAmplification(
         1031  +    XML_Parser parser, float maximumAmplificationFactor);
         1032  +
         1033  +/* Added in Expat 2.4.0. */
         1034  +XMLPARSEAPI(XML_Bool)
         1035  +XML_SetBillionLaughsAttackProtectionActivationThreshold(
         1036  +    XML_Parser parser, unsigned long long activationThresholdBytes);
         1037  +#endif
  1014   1038   
  1015   1039   /* Expat follows the semantic versioning convention.
  1016   1040      See http://semver.org.
  1017   1041   */
  1018   1042   #define XML_MAJOR_VERSION 2
  1019         -#define XML_MINOR_VERSION 3
  1020         -#define XML_MICRO_VERSION 0
         1043  +#define XML_MINOR_VERSION 4
         1044  +#define XML_MICRO_VERSION 2
  1021   1045   
  1022   1046   #ifdef __cplusplus
  1023   1047   }
  1024   1048   #endif
  1025   1049   
  1026   1050   #endif /* not Expat_INCLUDED */

Changes to expat/expat_external.h.

     3      3                            ___\ \/ /_ __   __ _| |_
     4      4                           / _ \\  /| '_ \ / _` | __|
     5      5                          |  __//  \| |_) | (_| | |_
     6      6                           \___/_/\_\ .__/ \__,_|\__|
     7      7                                    |_| XML parser
     8      8   
     9      9      Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
    10         -   Copyright (c) 2000-2017 Expat development team
           10  +   Copyright (c) 2000      Clark Cooper <coopercc@users.sourceforge.net>
           11  +   Copyright (c) 2000-2004 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
           12  +   Copyright (c) 2001-2002 Greg Stein <gstein@users.sourceforge.net>
           13  +   Copyright (c) 2002-2006 Karl Waclawek <karl@waclawek.net>
           14  +   Copyright (c) 2016      Cristian Rodríguez <crrodriguez@opensuse.org>
           15  +   Copyright (c) 2016-2019 Sebastian Pipping <sebastian@pipping.org>
           16  +   Copyright (c) 2017      Rhodri James <rhodri@wildebeest.org.uk>
           17  +   Copyright (c) 2018      Yury Gribov <tetra2005@gmail.com>
    11     18      Licensed under the MIT license:
    12     19   
    13     20      Permission is  hereby granted,  free of charge,  to any  person obtaining
    14     21      a  copy  of  this  software   and  associated  documentation  files  (the
    15     22      "Software"),  to  deal in  the  Software  without restriction,  including
    16     23      without  limitation the  rights  to use,  copy,  modify, merge,  publish,
    17     24      distribute, sublicense, and/or sell copies of the Software, and to permit

Changes to expat/iasciitab.h.

     3      3                            ___\ \/ /_ __   __ _| |_
     4      4                           / _ \\  /| '_ \ / _` | __|
     5      5                          |  __//  \| |_) | (_| | |_
     6      6                           \___/_/\_\ .__/ \__,_|\__|
     7      7                                    |_| XML parser
     8      8   
     9      9      Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
    10         -   Copyright (c) 2000-2017 Expat development team
           10  +   Copyright (c) 2000      Clark Cooper <coopercc@users.sourceforge.net>
           11  +   Copyright (c) 2002      Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
           12  +   Copyright (c) 2017      Sebastian Pipping <sebastian@pipping.org>
    11     13      Licensed under the MIT license:
    12     14   
    13     15      Permission is  hereby granted,  free of charge,  to any  person obtaining
    14     16      a  copy  of  this  software   and  associated  documentation  files  (the
    15     17      "Software"),  to  deal in  the  Software  without restriction,  including
    16     18      without  limitation the  rights  to use,  copy,  modify, merge,  publish,
    17     19      distribute, sublicense, and/or sell copies of the Software, and to permit

Changes to expat/internal.h.

    21     21                               __  __            _
    22     22                            ___\ \/ /_ __   __ _| |_
    23     23                           / _ \\  /| '_ \ / _` | __|
    24     24                          |  __//  \| |_) | (_| | |_
    25     25                           \___/_/\_\ .__/ \__,_|\__|
    26     26                                    |_| XML parser
    27     27   
    28         -   Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
    29         -   Copyright (c) 2000-2017 Expat development team
           28  +   Copyright (c) 2002-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
           29  +   Copyright (c) 2002-2006 Karl Waclawek <karl@waclawek.net>
           30  +   Copyright (c) 2003      Greg Stein <gstein@users.sourceforge.net>
           31  +   Copyright (c) 2016-2021 Sebastian Pipping <sebastian@pipping.org>
           32  +   Copyright (c) 2018      Yury Gribov <tetra2005@gmail.com>
           33  +   Copyright (c) 2019      David Loffredo <loffredo@steptools.com>
    30     34      Licensed under the MIT license:
    31     35   
    32     36      Permission is  hereby granted,  free of charge,  to any  person obtaining
    33     37      a  copy  of  this  software   and  associated  documentation  files  (the
    34     38      "Software"),  to  deal in  the  Software  without restriction,  including
    35     39      without  limitation the  rights  to use,  copy,  modify, merge,  publish,
    36     40      distribute, sublicense, and/or sell copies of the Software, and to permit
................................................................................
    96    100   #ifdef __cplusplus
    97    101   #  define inline inline
    98    102   #else
    99    103   #  ifndef inline
   100    104   #    define inline
   101    105   #  endif
   102    106   #endif
          107  +
          108  +#include <limits.h> // ULONG_MAX
          109  +
          110  +#if defined(_WIN32) && ! defined(__USE_MINGW_ANSI_STDIO)
          111  +#  define EXPAT_FMT_ULL(midpart) "%" midpart "I64u"
          112  +#  if defined(_WIN64) // Note: modifiers "td" and "zu" do not work for MinGW
          113  +#    define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "I64d"
          114  +#    define EXPAT_FMT_SIZE_T(midpart) "%" midpart "I64u"
          115  +#  else
          116  +#    define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "d"
          117  +#    define EXPAT_FMT_SIZE_T(midpart) "%" midpart "u"
          118  +#  endif
          119  +#else
          120  +#  define EXPAT_FMT_ULL(midpart) "%" midpart "llu"
          121  +#  if ! defined(ULONG_MAX)
          122  +#    error Compiler did not define ULONG_MAX for us
          123  +#  elif ULONG_MAX == 18446744073709551615u // 2^64-1
          124  +#    define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "ld"
          125  +#    define EXPAT_FMT_SIZE_T(midpart) "%" midpart "lu"
          126  +#  else
          127  +#    define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "d"
          128  +#    define EXPAT_FMT_SIZE_T(midpart) "%" midpart "u"
          129  +#  endif
          130  +#endif
   103    131   
   104    132   #ifndef UNUSED_P
   105    133   #  define UNUSED_P(p) (void)p
   106    134   #endif
          135  +
          136  +/* NOTE BEGIN If you ever patch these defaults to greater values
          137  +              for non-attack XML payload in your environment,
          138  +              please file a bug report with libexpat.  Thank you!
          139  +*/
          140  +#define EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT   \
          141  +  100.0f
          142  +#define EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT    \
          143  +  8388608 // 8 MiB, 2^23
          144  +/* NOTE END */
          145  +
          146  +#include "expat.h" // so we can use type XML_Parser below
   107    147   
   108    148   #ifdef __cplusplus
   109    149   extern "C" {
   110    150   #endif
   111    151   
   112         -#ifdef XML_ENABLE_VISIBILITY
   113         -#  if XML_ENABLE_VISIBILITY
   114         -__attribute__((visibility("default")))
   115         -#  endif
          152  +void _INTERNAL_trim_to_complete_utf8_characters(const char *from,
          153  +                                                const char **fromLimRef);
          154  +
          155  +#if defined(XML_DTD)
          156  +unsigned long long testingAccountingGetCountBytesDirect(XML_Parser parser);
          157  +unsigned long long testingAccountingGetCountBytesIndirect(XML_Parser parser);
          158  +const char *unsignedCharToPrintable(unsigned char c);
   116    159   #endif
   117         -void
   118         -_INTERNAL_trim_to_complete_utf8_characters(const char *from,
   119         -                                           const char **fromLimRef);
   120    160   
   121    161   #ifdef __cplusplus
   122    162   }
   123    163   #endif

Changes to expat/latin1tab.h.

     3      3                            ___\ \/ /_ __   __ _| |_
     4      4                           / _ \\  /| '_ \ / _` | __|
     5      5                          |  __//  \| |_) | (_| | |_
     6      6                           \___/_/\_\ .__/ \__,_|\__|
     7      7                                    |_| XML parser
     8      8   
     9      9      Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
    10         -   Copyright (c) 2000-2017 Expat development team
           10  +   Copyright (c) 2000      Clark Cooper <coopercc@users.sourceforge.net>
           11  +   Copyright (c) 2002      Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
           12  +   Copyright (c) 2017      Sebastian Pipping <sebastian@pipping.org>
    11     13      Licensed under the MIT license:
    12     14   
    13     15      Permission is  hereby granted,  free of charge,  to any  person obtaining
    14     16      a  copy  of  this  software   and  associated  documentation  files  (the
    15     17      "Software"),  to  deal in  the  Software  without restriction,  including
    16     18      without  limitation the  rights  to use,  copy,  modify, merge,  publish,
    17     19      distribute, sublicense, and/or sell copies of the Software, and to permit

Changes to expat/nametab.h.

     2      2                               __  __            _
     3      3                            ___\ \/ /_ __   __ _| |_
     4      4                           / _ \\  /| '_ \ / _` | __|
     5      5                          |  __//  \| |_) | (_| | |_
     6      6                           \___/_/\_\ .__/ \__,_|\__|
     7      7                                    |_| XML parser
     8      8   
     9         -   Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
    10         -   Copyright (c) 2000-2017 Expat development team
            9  +   Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
           10  +   Copyright (c) 2017 Sebastian Pipping <sebastian@pipping.org>
    11     11      Licensed under the MIT license:
    12     12   
    13     13      Permission is  hereby granted,  free of charge,  to any  person obtaining
    14     14      a  copy  of  this  software   and  associated  documentation  files  (the
    15     15      "Software"),  to  deal in  the  Software  without restriction,  including
    16     16      without  limitation the  rights  to use,  copy,  modify, merge,  publish,
    17     17      distribute, sublicense, and/or sell copies of the Software, and to permit

Changes to expat/utf8tab.h.

     3      3                            ___\ \/ /_ __   __ _| |_
     4      4                           / _ \\  /| '_ \ / _` | __|
     5      5                          |  __//  \| |_) | (_| | |_
     6      6                           \___/_/\_\ .__/ \__,_|\__|
     7      7                                    |_| XML parser
     8      8   
     9      9      Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
    10         -   Copyright (c) 2000-2017 Expat development team
           10  +   Copyright (c) 2000      Clark Cooper <coopercc@users.sourceforge.net>
           11  +   Copyright (c) 2002      Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
           12  +   Copyright (c) 2017      Sebastian Pipping <sebastian@pipping.org>
    11     13      Licensed under the MIT license:
    12     14   
    13     15      Permission is  hereby granted,  free of charge,  to any  person obtaining
    14     16      a  copy  of  this  software   and  associated  documentation  files  (the
    15     17      "Software"),  to  deal in  the  Software  without restriction,  including
    16     18      without  limitation the  rights  to use,  copy,  modify, merge,  publish,
    17     19      distribute, sublicense, and/or sell copies of the Software, and to permit

Changes to expat/winconfig.h.

     2      2                               __  __            _
     3      3                            ___\ \/ /_ __   __ _| |_
     4      4                           / _ \\  /| '_ \ / _` | __|
     5      5                          |  __//  \| |_) | (_| | |_
     6      6                           \___/_/\_\ .__/ \__,_|\__|
     7      7                                    |_| XML parser
     8      8   
     9         -   Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
    10         -   Copyright (c) 2000-2017 Expat development team
            9  +   Copyright (c) 2000      Clark Cooper <coopercc@users.sourceforge.net>
           10  +   Copyright (c) 2002      Greg Stein <gstein@users.sourceforge.net>
           11  +   Copyright (c) 2005      Karl Waclawek <karl@waclawek.net>
           12  +   Copyright (c) 2017-2021 Sebastian Pipping <sebastian@pipping.org>
    11     13      Licensed under the MIT license:
    12     14   
    13     15      Permission is  hereby granted,  free of charge,  to any  person obtaining
    14     16      a  copy  of  this  software   and  associated  documentation  files  (the
    15     17      "Software"),  to  deal in  the  Software  without restriction,  including
    16     18      without  limitation the  rights  to use,  copy,  modify, merge,  publish,
    17     19      distribute, sublicense, and/or sell copies of the Software, and to permit
................................................................................
    36     38   #define WIN32_LEAN_AND_MEAN
    37     39   #include <windows.h>
    38     40   #undef WIN32_LEAN_AND_MEAN
    39     41   
    40     42   #include <memory.h>
    41     43   #include <string.h>
    42     44   
    43         -#if defined(HAVE_EXPAT_CONFIG_H) /* e.g. MinGW */
    44         -#  include <expat_config.h>
    45         -#else /* !defined(HAVE_EXPAT_CONFIG_H) */
    46         -
    47         -#  define XML_NS 1
    48         -#  define XML_DTD 1
    49         -#  define XML_CONTEXT_BYTES 1024
    50         -
    51         -/* we will assume all Windows platforms are little endian */
    52         -#  define BYTEORDER 1234
    53         -
    54         -#endif /* !defined(HAVE_EXPAT_CONFIG_H) */
    55         -
    56     45   #endif /* ndef WINCONFIG_H */

Changes to expat/xmlparse.c.

     1         -/* d667b5f8e56e24fdfaf5e38596d419d924a9fadceb987d81d5613ecb7ca51b0e (2.3.0+)
            1  +/* 0550bc9a27b099d462d8d1007271cfeaa39852f20cd0d5d2caeadaeb39516fbe (2.4.2+)
     2      2                               __  __            _
     3      3                            ___\ \/ /_ __   __ _| |_
     4      4                           / _ \\  /| '_ \ / _` | __|
     5      5                          |  __//  \| |_) | (_| | |_
     6      6                           \___/_/\_\ .__/ \__,_|\__|
     7      7                                    |_| XML parser
     8      8   
     9      9      Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
    10         -   Copyright (c) 2000-2017 Expat development team
           10  +   Copyright (c) 2000      Clark Cooper <coopercc@users.sourceforge.net>
           11  +   Copyright (c) 2000-2006 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
           12  +   Copyright (c) 2001-2002 Greg Stein <gstein@users.sourceforge.net>
           13  +   Copyright (c) 2002-2016 Karl Waclawek <karl@waclawek.net>
           14  +   Copyright (c) 2005-2009 Steven Solie <ssolie@users.sourceforge.net>
           15  +   Copyright (c) 2016      Eric Rahm <erahm@mozilla.com>
           16  +   Copyright (c) 2016-2021 Sebastian Pipping <sebastian@pipping.org>
           17  +   Copyright (c) 2016      Gaurav <g.gupta@samsung.com>
           18  +   Copyright (c) 2016      Thomas Beutlich <tc@tbeu.de>
           19  +   Copyright (c) 2016      Gustavo Grieco <gustavo.grieco@imag.fr>
           20  +   Copyright (c) 2016      Pascal Cuoq <cuoq@trust-in-soft.com>
           21  +   Copyright (c) 2016      Ed Schouten <ed@nuxi.nl>
           22  +   Copyright (c) 2017-2018 Rhodri James <rhodri@wildebeest.org.uk>
           23  +   Copyright (c) 2017      Václav Slavík <vaclav@slavik.io>
           24  +   Copyright (c) 2017      Viktor Szakats <commit@vsz.me>
           25  +   Copyright (c) 2017      Chanho Park <chanho61.park@samsung.com>
           26  +   Copyright (c) 2017      Rolf Eike Beer <eike@sf-mail.de>
           27  +   Copyright (c) 2017      Hans Wennborg <hans@chromium.org>
           28  +   Copyright (c) 2018      Anton Maklakov <antmak.pub@gmail.com>
           29  +   Copyright (c) 2018      Benjamin Peterson <benjamin@python.org>
           30  +   Copyright (c) 2018      Marco Maggi <marco.maggi-ipsu@poste.it>
           31  +   Copyright (c) 2018      Mariusz Zaborski <oshogbo@vexillium.org>
           32  +   Copyright (c) 2019      David Loffredo <loffredo@steptools.com>
           33  +   Copyright (c) 2019-2020 Ben Wagner <bungeman@chromium.org>
           34  +   Copyright (c) 2019      Vadim Zeitlin <vadim@zeitlins.org>
           35  +   Copyright (c) 2021      Dong-hee Na <donghee.na@python.org>
    11     36      Licensed under the MIT license:
    12     37   
    13     38      Permission is  hereby granted,  free of charge,  to any  person obtaining
    14     39      a  copy  of  this  software   and  associated  documentation  files  (the
    15     40      "Software"),  to  deal in  the  Software  without restriction,  including
    16     41      without  limitation the  rights  to use,  copy,  modify, merge,  publish,
    17     42      distribute, sublicense, and/or sell copies of the Software, and to permit
................................................................................
    25     50      EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
    26     51      MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
    27     52      NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
    28     53      DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
    29     54      OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
    30     55      USE OR OTHER DEALINGS IN THE SOFTWARE.
    31     56   */
           57  +
           58  +#define XML_BUILDING_EXPAT 1
           59  +
           60  +#include <expat_config.h>
    32     61   
    33     62   #if ! defined(_GNU_SOURCE)
    34     63   #  define _GNU_SOURCE 1 /* syscall prototype */
    35     64   #endif
    36     65   
    37     66   #ifdef _WIN32
    38     67   /* force stdlib to define rand_s() */
................................................................................
    44     73   #include <stddef.h>
    45     74   #include <string.h> /* memset(), memcpy() */
    46     75   #include <assert.h>
    47     76   #include <limits.h> /* UINT_MAX */
    48     77   #include <stdio.h>  /* fprintf */
    49     78   #include <stdlib.h> /* getenv, rand_s */
    50     79   #include <stdint.h> /* uintptr_t */
           80  +#include <math.h>   /* isnan */
    51     81   
    52     82   #ifdef _WIN32
    53     83   #  define getpid GetCurrentProcessId
    54     84   #else
    55     85   #  include <sys/time.h>  /* gettimeofday() */
    56     86   #  include <sys/types.h> /* getpid() */
    57     87   #  include <unistd.h>    /* getpid() */
    58     88   #  include <fcntl.h>     /* O_RDONLY */
    59     89   #  include <errno.h>
    60     90   #endif
    61     91   
    62         -#define XML_BUILDING_EXPAT 1
    63         -
    64     92   #ifdef _WIN32
    65     93   #  include "winconfig.h"
    66         -#elif defined(HAVE_EXPAT_CONFIG_H)
    67         -#  include <expat_config.h>
    68         -#endif /* ndef _WIN32 */
           94  +#endif
    69     95   
    70     96   #include "ascii.h"
    71     97   #include "expat.h"
    72     98   #include "siphash.h"
    73     99   
    74    100   #if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
    75    101   #  if defined(HAVE_GETRANDOM)
................................................................................
   368    394     const char *internalEventEndPtr;
   369    395     struct open_internal_entity *next;
   370    396     ENTITY *entity;
   371    397     int startTagLevel;
   372    398     XML_Bool betweenDecl; /* WFC: PE Between Declarations */
   373    399   } OPEN_INTERNAL_ENTITY;
   374    400   
          401  +enum XML_Account {
          402  +  XML_ACCOUNT_DIRECT,           /* bytes directly passed to the Expat parser */
          403  +  XML_ACCOUNT_ENTITY_EXPANSION, /* intermediate bytes produced during entity
          404  +                                   expansion */
          405  +  XML_ACCOUNT_NONE              /* i.e. do not account, was accounted already */
          406  +};
          407  +
          408  +#ifdef XML_DTD
          409  +typedef unsigned long long XmlBigCount;
          410  +typedef struct accounting {
          411  +  XmlBigCount countBytesDirect;
          412  +  XmlBigCount countBytesIndirect;
          413  +  int debugLevel;
          414  +  float maximumAmplificationFactor; // >=1.0
          415  +  unsigned long long activationThresholdBytes;
          416  +} ACCOUNTING;
          417  +
          418  +typedef struct entity_stats {
          419  +  unsigned int countEverOpened;
          420  +  unsigned int currentDepth;
          421  +  unsigned int maximumDepthSeen;
          422  +  int debugLevel;
          423  +} ENTITY_STATS;
          424  +#endif /* XML_DTD */
          425  +
   375    426   typedef enum XML_Error PTRCALL Processor(XML_Parser parser, const char *start,
   376    427                                            const char *end, const char **endPtr);
   377    428   
   378    429   static Processor prologProcessor;
   379    430   static Processor prologInitProcessor;
   380    431   static Processor contentProcessor;
   381    432   static Processor cdataSectionProcessor;
................................................................................
   398    449                                               const XML_Char *encodingName);
   399    450   static enum XML_Error processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
   400    451                                        const char *s, const char *next);
   401    452   static enum XML_Error initializeEncoding(XML_Parser parser);
   402    453   static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc,
   403    454                                  const char *s, const char *end, int tok,
   404    455                                  const char *next, const char **nextPtr,
   405         -                               XML_Bool haveMore, XML_Bool allowClosingDoctype);
          456  +                               XML_Bool haveMore, XML_Bool allowClosingDoctype,
          457  +                               enum XML_Account account);
   406    458   static enum XML_Error processInternalEntity(XML_Parser parser, ENTITY *entity,
   407    459                                               XML_Bool betweenDecl);
   408    460   static enum XML_Error doContent(XML_Parser parser, int startTagLevel,
   409    461                                   const ENCODING *enc, const char *start,
   410    462                                   const char *end, const char **endPtr,
   411         -                                XML_Bool haveMore);
          463  +                                XML_Bool haveMore, enum XML_Account account);
   412    464   static enum XML_Error doCdataSection(XML_Parser parser, const ENCODING *,
   413    465                                        const char **startPtr, const char *end,
   414         -                                     const char **nextPtr, XML_Bool haveMore);
          466  +                                     const char **nextPtr, XML_Bool haveMore,
          467  +                                     enum XML_Account account);
   415    468   #ifdef XML_DTD
   416    469   static enum XML_Error doIgnoreSection(XML_Parser parser, const ENCODING *,
   417    470                                         const char **startPtr, const char *end,
   418    471                                         const char **nextPtr, XML_Bool haveMore);
   419    472   #endif /* XML_DTD */
   420    473   
   421    474   static void freeBindings(XML_Parser parser, BINDING *bindings);
   422    475   static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *,
   423    476                                   const char *s, TAG_NAME *tagNamePtr,
   424         -                                BINDING **bindingsPtr);
          477  +                                BINDING **bindingsPtr,
          478  +                                enum XML_Account account);
   425    479   static enum XML_Error addBinding(XML_Parser parser, PREFIX *prefix,
   426    480                                    const ATTRIBUTE_ID *attId, const XML_Char *uri,
   427    481                                    BINDING **bindingsPtr);
   428    482   static int defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,
   429    483                              XML_Bool isId, const XML_Char *dfltValue,
   430    484                              XML_Parser parser);
   431    485   static enum XML_Error storeAttributeValue(XML_Parser parser, const ENCODING *,
   432    486                                             XML_Bool isCdata, const char *,
   433         -                                          const char *, STRING_POOL *);
          487  +                                          const char *, STRING_POOL *,
          488  +                                          enum XML_Account account);
   434    489   static enum XML_Error appendAttributeValue(XML_Parser parser, const ENCODING *,
   435    490                                              XML_Bool isCdata, const char *,
   436         -                                           const char *, STRING_POOL *);
          491  +                                           const char *, STRING_POOL *,
          492  +                                           enum XML_Account account);
   437    493   static ATTRIBUTE_ID *getAttributeId(XML_Parser parser, const ENCODING *enc,
   438    494                                       const char *start, const char *end);
   439    495   static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
   440    496   static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc,
   441         -                                       const char *start, const char *end);
          497  +                                       const char *start, const char *end,
          498  +                                       enum XML_Account account);
   442    499   static int reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
   443    500                                          const char *start, const char *end);
   444    501   static int reportComment(XML_Parser parser, const ENCODING *enc,
   445    502                            const char *start, const char *end);
   446    503   static void reportDefault(XML_Parser parser, const ENCODING *enc,
   447    504                             const char *start, const char *end);
   448    505   
................................................................................
   498    555   
   499    556   static XML_Parser parserCreate(const XML_Char *encodingName,
   500    557                                  const XML_Memory_Handling_Suite *memsuite,
   501    558                                  const XML_Char *nameSep, DTD *dtd);
   502    559   
   503    560   static void parserInit(XML_Parser parser, const XML_Char *encodingName);
   504    561   
          562  +#ifdef XML_DTD
          563  +static float accountingGetCurrentAmplification(XML_Parser rootParser);
          564  +static void accountingReportStats(XML_Parser originParser, const char *epilog);
          565  +static void accountingOnAbort(XML_Parser originParser);
          566  +static void accountingReportDiff(XML_Parser rootParser,
          567  +                                 unsigned int levelsAwayFromRootParser,
          568  +                                 const char *before, const char *after,
          569  +                                 ptrdiff_t bytesMore, int source_line,
          570  +                                 enum XML_Account account);
          571  +static XML_Bool accountingDiffTolerated(XML_Parser originParser, int tok,
          572  +                                        const char *before, const char *after,
          573  +                                        int source_line,
          574  +                                        enum XML_Account account);
          575  +
          576  +static void entityTrackingReportStats(XML_Parser parser, ENTITY *entity,
          577  +                                      const char *action, int sourceLine);
          578  +static void entityTrackingOnOpen(XML_Parser parser, ENTITY *entity,
          579  +                                 int sourceLine);
          580  +static void entityTrackingOnClose(XML_Parser parser, ENTITY *entity,
          581  +                                  int sourceLine);
          582  +
          583  +static XML_Parser getRootParserOf(XML_Parser parser,
          584  +                                  unsigned int *outLevelDiff);
          585  +#endif /* XML_DTD */
          586  +
          587  +static unsigned long getDebugLevel(const char *variableName,
          588  +                                   unsigned long defaultDebugLevel);
          589  +
   505    590   #define poolStart(pool) ((pool)->start)
   506    591   #define poolEnd(pool) ((pool)->ptr)
   507    592   #define poolLength(pool) ((pool)->ptr - (pool)->start)
   508    593   #define poolChop(pool) ((void)--(pool->ptr))
   509    594   #define poolLastChar(pool) (((pool)->ptr)[-1])
   510    595   #define poolDiscard(pool) ((pool)->ptr = (pool)->start)
   511    596   #define poolFinish(pool) ((pool)->start = (pool)->ptr)
................................................................................
   611    696     XML_ParsingStatus m_parsingStatus;
   612    697   #ifdef XML_DTD
   613    698     XML_Bool m_isParamEntity;
   614    699     XML_Bool m_useForeignDTD;
   615    700     enum XML_ParamEntityParsing m_paramEntityParsing;
   616    701   #endif
   617    702     unsigned long m_hash_secret_salt;
          703  +#ifdef XML_DTD
          704  +  ACCOUNTING m_accounting;
          705  +  ENTITY_STATS m_entity_stats;
          706  +#endif
   618    707   };
   619    708   
   620    709   #define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s)))
   621    710   #define REALLOC(parser, p, s) (parser->m_mem.realloc_fcn((p), (s)))
   622    711   #define FREE(parser, p) (parser->m_mem.free_fcn((p)))
   623    712   
   624    713   XML_Parser XMLCALL
................................................................................
   795    884   #  endif
   796    885   }
   797    886   
   798    887   #endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
   799    888   
   800    889   static unsigned long
   801    890   ENTROPY_DEBUG(const char *label, unsigned long entropy) {
   802         -  const char *const EXPAT_ENTROPY_DEBUG = getenv("EXPAT_ENTROPY_DEBUG");
   803         -  if (EXPAT_ENTROPY_DEBUG && ! strcmp(EXPAT_ENTROPY_DEBUG, "1")) {
   804         -    fprintf(stderr, "Entropy: %s --> 0x%0*lx (%lu bytes)\n", label,
          891  +  if (getDebugLevel("EXPAT_ENTROPY_DEBUG", 0) >= 1u) {
          892  +    fprintf(stderr, "expat: Entropy: %s --> 0x%0*lx (%lu bytes)\n", label,
   805    893               (int)sizeof(entropy) * 2, entropy, (unsigned long)sizeof(entropy));
   806    894     }
   807    895     return entropy;
   808    896   }
   809    897   
   810    898   static unsigned long
   811    899   generate_hash_secret_salt(XML_Parser parser) {
................................................................................
  1059   1147     parser->m_parsingStatus.parsing = XML_INITIALIZED;
  1060   1148   #ifdef XML_DTD
  1061   1149     parser->m_isParamEntity = XML_FALSE;
  1062   1150     parser->m_useForeignDTD = XML_FALSE;
  1063   1151     parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
  1064   1152   #endif
  1065   1153     parser->m_hash_secret_salt = 0;
         1154  +
         1155  +#ifdef XML_DTD
         1156  +  memset(&parser->m_accounting, 0, sizeof(ACCOUNTING));
         1157  +  parser->m_accounting.debugLevel = getDebugLevel("EXPAT_ACCOUNTING_DEBUG", 0u);
         1158  +  parser->m_accounting.maximumAmplificationFactor
         1159  +      = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT;
         1160  +  parser->m_accounting.activationThresholdBytes
         1161  +      = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT;
         1162  +
         1163  +  memset(&parser->m_entity_stats, 0, sizeof(ENTITY_STATS));
         1164  +  parser->m_entity_stats.debugLevel = getDebugLevel("EXPAT_ENTITY_DEBUG", 0u);
         1165  +#endif
  1066   1166   }
  1067   1167   
  1068   1168   /* moves list of bindings to m_freeBindingList */
  1069   1169   static void FASTCALL
  1070   1170   moveToFreeBindingList(XML_Parser parser, BINDING *bindings) {
  1071   1171     while (bindings) {
  1072   1172       BINDING *b = bindings;
................................................................................
  2333   2433     /* Added in 2.2.5. */
  2334   2434     case XML_ERROR_INVALID_ARGUMENT: /* Constant added in 2.2.1, already */
  2335   2435       return XML_L("invalid argument");
  2336   2436       /* Added in 2.3.0. */
  2337   2437     case XML_ERROR_NO_BUFFER:
  2338   2438       return XML_L(
  2339   2439           "a successful prior call to function XML_GetBuffer is required");
         2440  +  /* Added in 2.4.0. */
         2441  +  case XML_ERROR_AMPLIFICATION_LIMIT_BREACH:
         2442  +    return XML_L(
         2443  +        "limit on input amplification factor (from DTD and entities) breached");
  2340   2444     }
  2341   2445     return NULL;
  2342   2446   }
  2343   2447   
  2344   2448   const XML_LChar *XMLCALL
  2345   2449   XML_ExpatVersion(void) {
  2346   2450     /* V1 is used to string-ize the version number. However, it would
................................................................................
  2369   2473     version.micro = XML_MICRO_VERSION;
  2370   2474   
  2371   2475     return version;
  2372   2476   }
  2373   2477   
  2374   2478   const XML_Feature *XMLCALL
  2375   2479   XML_GetFeatureList(void) {
  2376         -  static const XML_Feature features[]
  2377         -      = {{XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
  2378         -          sizeof(XML_Char)},
  2379         -         {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
  2380         -          sizeof(XML_LChar)},
         2480  +  static const XML_Feature features[] = {
         2481  +      {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
         2482  +       sizeof(XML_Char)},
         2483  +      {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
         2484  +       sizeof(XML_LChar)},
  2381   2485   #ifdef XML_UNICODE
  2382         -         {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
         2486  +      {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
  2383   2487   #endif
  2384   2488   #ifdef XML_UNICODE_WCHAR_T
  2385         -         {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
         2489  +      {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
  2386   2490   #endif
  2387   2491   #ifdef XML_DTD
  2388         -         {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
         2492  +      {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
  2389   2493   #endif
  2390   2494   #ifdef XML_CONTEXT_BYTES
  2391         -         {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
  2392         -          XML_CONTEXT_BYTES},
         2495  +      {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
         2496  +       XML_CONTEXT_BYTES},
  2393   2497   #endif
  2394   2498   #ifdef XML_MIN_SIZE
  2395         -         {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
         2499  +      {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
  2396   2500   #endif
  2397   2501   #ifdef XML_NS
  2398         -         {XML_FEATURE_NS, XML_L("XML_NS"), 0},
         2502  +      {XML_FEATURE_NS, XML_L("XML_NS"), 0},
  2399   2503   #endif
  2400   2504   #ifdef XML_LARGE_SIZE
  2401         -         {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
         2505  +      {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
  2402   2506   #endif
  2403   2507   #ifdef XML_ATTR_INFO
  2404         -         {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
         2508  +      {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
  2405   2509   #endif
  2406         -         {XML_FEATURE_END, NULL, 0}};
         2510  +#ifdef XML_DTD
         2511  +      /* Added in Expat 2.4.0. */
         2512  +      {XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT,
         2513  +       XML_L("XML_BLAP_MAX_AMP"),
         2514  +       (long int)
         2515  +           EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT},
         2516  +      {XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT,
         2517  +       XML_L("XML_BLAP_ACT_THRES"),
         2518  +       EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT},
         2519  +#endif
         2520  +      {XML_FEATURE_END, NULL, 0}};
  2407   2521   
  2408   2522     return features;
  2409   2523   }
  2410   2524   
         2525  +#ifdef XML_DTD
         2526  +XML_Bool XMLCALL
         2527  +XML_SetBillionLaughsAttackProtectionMaximumAmplification(
         2528  +    XML_Parser parser, float maximumAmplificationFactor) {
         2529  +  if ((parser == NULL) || (parser->m_parentParser != NULL)
         2530  +      || isnan(maximumAmplificationFactor)
         2531  +      || (maximumAmplificationFactor < 1.0f)) {
         2532  +    return XML_FALSE;
         2533  +  }
         2534  +  parser->m_accounting.maximumAmplificationFactor = maximumAmplificationFactor;
         2535  +  return XML_TRUE;
         2536  +}
         2537  +
         2538  +XML_Bool XMLCALL
         2539  +XML_SetBillionLaughsAttackProtectionActivationThreshold(
         2540  +    XML_Parser parser, unsigned long long activationThresholdBytes) {
         2541  +  if ((parser == NULL) || (parser->m_parentParser != NULL)) {
         2542  +    return XML_FALSE;
         2543  +  }
         2544  +  parser->m_accounting.activationThresholdBytes = activationThresholdBytes;
         2545  +  return XML_TRUE;
         2546  +}
         2547  +#endif /* XML_DTD */
         2548  +
  2411   2549   /* Initially tag->rawName always points into the parse buffer;
  2412   2550      for those TAG instances opened while the current parse buffer was
  2413   2551      processed, and not yet closed, we need to store tag->rawName in a more
  2414   2552      permanent location, since the parse buffer is about to be discarded.
  2415   2553   */
  2416   2554   static XML_Bool
  2417   2555   storeRawNames(XML_Parser parser) {
................................................................................
  2456   2594     }
  2457   2595     return XML_TRUE;
  2458   2596   }
  2459   2597   
  2460   2598   static enum XML_Error PTRCALL
  2461   2599   contentProcessor(XML_Parser parser, const char *start, const char *end,
  2462   2600                    const char **endPtr) {
  2463         -  enum XML_Error result
  2464         -      = doContent(parser, 0, parser->m_encoding, start, end, endPtr,
  2465         -                  (XML_Bool)! parser->m_parsingStatus.finalBuffer);
         2601  +  enum XML_Error result = doContent(
         2602  +      parser, 0, parser->m_encoding, start, end, endPtr,
         2603  +      (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_ACCOUNT_DIRECT);
  2466   2604     if (result == XML_ERROR_NONE) {
  2467   2605       if (! storeRawNames(parser))
  2468   2606         return XML_ERROR_NO_MEMORY;
  2469   2607     }
  2470   2608     return result;
  2471   2609   }
  2472   2610   
................................................................................
  2483   2621   static enum XML_Error PTRCALL
  2484   2622   externalEntityInitProcessor2(XML_Parser parser, const char *start,
  2485   2623                                const char *end, const char **endPtr) {
  2486   2624     const char *next = start; /* XmlContentTok doesn't always set the last arg */
  2487   2625     int tok = XmlContentTok(parser->m_encoding, start, end, &next);
  2488   2626     switch (tok) {
  2489   2627     case XML_TOK_BOM:
         2628  +#ifdef XML_DTD
         2629  +    if (! accountingDiffTolerated(parser, tok, start, next, __LINE__,
         2630  +                                  XML_ACCOUNT_DIRECT)) {
         2631  +      accountingOnAbort(parser);
         2632  +      return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
         2633  +    }
         2634  +#endif /* XML_DTD */
         2635  +
  2490   2636       /* If we are at the end of the buffer, this would cause the next stage,
  2491   2637          i.e. externalEntityInitProcessor3, to pass control directly to
  2492   2638          doContent (by detecting XML_TOK_NONE) without processing any xml text
  2493   2639          declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.
  2494   2640       */
  2495   2641       if (next == end && ! parser->m_parsingStatus.finalBuffer) {
  2496   2642         *endPtr = next;
................................................................................
  2520   2666   static enum XML_Error PTRCALL
  2521   2667   externalEntityInitProcessor3(XML_Parser parser, const char *start,
  2522   2668                                const char *end, const char **endPtr) {
  2523   2669     int tok;
  2524   2670     const char *next = start; /* XmlContentTok doesn't always set the last arg */
  2525   2671     parser->m_eventPtr = start;
  2526   2672     tok = XmlContentTok(parser->m_encoding, start, end, &next);
         2673  +  /* Note: These bytes are accounted later in:
         2674  +           - processXmlDecl
         2675  +           - externalEntityContentProcessor
         2676  +  */
  2527   2677     parser->m_eventEndPtr = next;
  2528   2678   
  2529   2679     switch (tok) {
  2530   2680     case XML_TOK_XML_DECL: {
  2531   2681       enum XML_Error result;
  2532   2682       result = processXmlDecl(parser, 1, start, next);
  2533   2683       if (result != XML_ERROR_NONE)
................................................................................
  2561   2711   }
  2562   2712   
  2563   2713   static enum XML_Error PTRCALL
  2564   2714   externalEntityContentProcessor(XML_Parser parser, const char *start,
  2565   2715                                  const char *end, const char **endPtr) {
  2566   2716     enum XML_Error result
  2567   2717         = doContent(parser, 1, parser->m_encoding, start, end, endPtr,
  2568         -                  (XML_Bool)! parser->m_parsingStatus.finalBuffer);
         2718  +                  (XML_Bool)! parser->m_parsingStatus.finalBuffer,
         2719  +                  XML_ACCOUNT_ENTITY_EXPANSION);
  2569   2720     if (result == XML_ERROR_NONE) {
  2570   2721       if (! storeRawNames(parser))
  2571   2722         return XML_ERROR_NO_MEMORY;
  2572   2723     }
  2573   2724     return result;
  2574   2725   }
  2575   2726   
  2576   2727   static enum XML_Error
  2577   2728   doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
  2578   2729             const char *s, const char *end, const char **nextPtr,
  2579         -          XML_Bool haveMore) {
         2730  +          XML_Bool haveMore, enum XML_Account account) {
  2580   2731     /* save one level of indirection */
  2581   2732     DTD *const dtd = parser->m_dtd;
  2582   2733   
  2583   2734     const char **eventPP;
  2584   2735     const char **eventEndPP;
  2585   2736     if (enc == parser->m_encoding) {
  2586   2737       eventPP = &parser->m_eventPtr;
................................................................................
  2590   2741       eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
  2591   2742     }
  2592   2743     *eventPP = s;
  2593   2744   
  2594   2745     for (;;) {
  2595   2746       const char *next = s; /* XmlContentTok doesn't always set the last arg */
  2596   2747       int tok = XmlContentTok(enc, s, end, &next);
         2748  +#ifdef XML_DTD
         2749  +    const char *accountAfter
         2750  +        = ((tok == XML_TOK_TRAILING_RSQB) || (tok == XML_TOK_TRAILING_CR))
         2751  +              ? (haveMore ? s /* i.e. 0 bytes */ : end)
         2752  +              : next;
         2753  +    if (! accountingDiffTolerated(parser, tok, s, accountAfter, __LINE__,
         2754  +                                  account)) {
         2755  +      accountingOnAbort(parser);
         2756  +      return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
         2757  +    }
         2758  +#endif
  2597   2759       *eventEndPP = next;
  2598   2760       switch (tok) {
  2599   2761       case XML_TOK_TRAILING_CR:
  2600   2762         if (haveMore) {
  2601   2763           *nextPtr = s;
  2602   2764           return XML_ERROR_NONE;
  2603   2765         }
................................................................................
  2645   2807         return XML_ERROR_PARTIAL_CHAR;
  2646   2808       case XML_TOK_ENTITY_REF: {
  2647   2809         const XML_Char *name;
  2648   2810         ENTITY *entity;
  2649   2811         XML_Char ch = (XML_Char)XmlPredefinedEntityName(
  2650   2812             enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar);
  2651   2813         if (ch) {
         2814  +#ifdef XML_DTD
         2815  +        /* NOTE: We are replacing 4-6 characters original input for 1 character
         2816  +         *       so there is no amplification and hence recording without
         2817  +         *       protection. */
         2818  +        accountingDiffTolerated(parser, tok, (char *)&ch,
         2819  +                                ((char *)&ch) + sizeof(XML_Char), __LINE__,
         2820  +                                XML_ACCOUNT_ENTITY_EXPANSION);
         2821  +#endif /* XML_DTD */
  2652   2822           if (parser->m_characterDataHandler)
  2653   2823             parser->m_characterDataHandler(parser->m_handlerArg, &ch, 1);
  2654   2824           else if (parser->m_defaultHandler)
  2655   2825             reportDefault(parser, enc, s, next);
  2656   2826           break;
  2657   2827         }
  2658   2828         name = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
................................................................................
  2763   2933               tag->bufEnd = temp + bufSize;
  2764   2934               toPtr = (XML_Char *)temp + convLen;
  2765   2935             }
  2766   2936           }
  2767   2937         }
  2768   2938         tag->name.str = (XML_Char *)tag->buf;
  2769   2939         *toPtr = XML_T('\0');
  2770         -      result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
         2940  +      result
         2941  +          = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings), account);
  2771   2942         if (result)
  2772   2943           return result;
  2773   2944         if (parser->m_startElementHandler)
  2774   2945           parser->m_startElementHandler(parser->m_handlerArg, tag->name.str,
  2775   2946                                         (const XML_Char **)parser->m_atts);
  2776   2947         else if (parser->m_defaultHandler)
  2777   2948           reportDefault(parser, enc, s, next);
................................................................................
  2787   2958         XML_Bool noElmHandlers = XML_TRUE;
  2788   2959         TAG_NAME name;
  2789   2960         name.str = poolStoreString(&parser->m_tempPool, enc, rawName,
  2790   2961                                    rawName + XmlNameLength(enc, rawName));
  2791   2962         if (! name.str)
  2792   2963           return XML_ERROR_NO_MEMORY;
  2793   2964         poolFinish(&parser->m_tempPool);
  2794         -      result = storeAtts(parser, enc, s, &name, &bindings);
         2965  +      result = storeAtts(parser, enc, s, &name, &bindings,
         2966  +                         XML_ACCOUNT_NONE /* token spans whole start tag */);
  2795   2967         if (result != XML_ERROR_NONE) {
  2796   2968           freeBindings(parser, bindings);
  2797   2969           return result;
  2798   2970         }
  2799   2971         poolFinish(&parser->m_tempPool);
  2800   2972         if (parser->m_startElementHandler) {
  2801   2973           parser->m_startElementHandler(parser->m_handlerArg, name.str,
................................................................................
  2922   3094         */
  2923   3095         else if (0 && parser->m_characterDataHandler)
  2924   3096           parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf,
  2925   3097                                          0);
  2926   3098         /* END disabled code */
  2927   3099         else if (parser->m_defaultHandler)
  2928   3100           reportDefault(parser, enc, s, next);
  2929         -      result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore);
         3101  +      result
         3102  +          = doCdataSection(parser, enc, &next, end, nextPtr, haveMore, account);
  2930   3103         if (result != XML_ERROR_NONE)
  2931   3104           return result;
  2932   3105         else if (! next) {
  2933   3106           parser->m_processor = cdataSectionProcessor;
  2934   3107           return result;
  2935   3108         }
  2936   3109       } break;
................................................................................
  3051   3224      - build list of attributes for startElementHandler
  3052   3225      - default attributes
  3053   3226      - process namespace declarations (check and report them)
  3054   3227      - generate namespace aware element name (URI, prefix)
  3055   3228   */
  3056   3229   static enum XML_Error
  3057   3230   storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
  3058         -          TAG_NAME *tagNamePtr, BINDING **bindingsPtr) {
         3231  +          TAG_NAME *tagNamePtr, BINDING **bindingsPtr,
         3232  +          enum XML_Account account) {
  3059   3233     DTD *const dtd = parser->m_dtd; /* save one level of indirection */
  3060   3234     ELEMENT_TYPE *elementType;
  3061   3235     int nDefaultAtts;
  3062   3236     const XML_Char **appAtts; /* the attribute list for the application */
  3063   3237     int attIndex = 0;
  3064   3238     int prefixLen;
  3065   3239     int i;
................................................................................
  3161   3335             }
  3162   3336           }
  3163   3337         }
  3164   3338   
  3165   3339         /* normalize the attribute value */
  3166   3340         result = storeAttributeValue(
  3167   3341             parser, enc, isCdata, parser->m_atts[i].valuePtr,
  3168         -          parser->m_atts[i].valueEnd, &parser->m_tempPool);
         3342  +          parser->m_atts[i].valueEnd, &parser->m_tempPool, account);
  3169   3343         if (result)
  3170   3344           return result;
  3171   3345         appAtts[attIndex] = poolStart(&parser->m_tempPool);
  3172   3346         poolFinish(&parser->m_tempPool);
  3173   3347       } else {
  3174   3348         /* the value did not need normalizing */
  3175   3349         appAtts[attIndex] = poolStoreString(&parser->m_tempPool, enc,
................................................................................
  3550   3724   
  3551   3725   /* The idea here is to avoid using stack for each CDATA section when
  3552   3726      the whole file is parsed with one call.
  3553   3727   */
  3554   3728   static enum XML_Error PTRCALL
  3555   3729   cdataSectionProcessor(XML_Parser parser, const char *start, const char *end,
  3556   3730                         const char **endPtr) {
  3557         -  enum XML_Error result
  3558         -      = doCdataSection(parser, parser->m_encoding, &start, end, endPtr,
  3559         -                       (XML_Bool)! parser->m_parsingStatus.finalBuffer);
         3731  +  enum XML_Error result = doCdataSection(
         3732  +      parser, parser->m_encoding, &start, end, endPtr,
         3733  +      (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_ACCOUNT_DIRECT);
  3560   3734     if (result != XML_ERROR_NONE)
  3561   3735       return result;
  3562   3736     if (start) {
  3563   3737       if (parser->m_parentParser) { /* we are parsing an external entity */
  3564   3738         parser->m_processor = externalEntityContentProcessor;
  3565   3739         return externalEntityContentProcessor(parser, start, end, endPtr);
  3566   3740       } else {
................................................................................
  3572   3746   }
  3573   3747   
  3574   3748   /* startPtr gets set to non-null if the section is closed, and to null if
  3575   3749      the section is not yet closed.
  3576   3750   */
  3577   3751   static enum XML_Error
  3578   3752   doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
  3579         -               const char *end, const char **nextPtr, XML_Bool haveMore) {
         3753  +               const char *end, const char **nextPtr, XML_Bool haveMore,
         3754  +               enum XML_Account account) {
  3580   3755     const char *s = *startPtr;
  3581   3756     const char **eventPP;
  3582   3757     const char **eventEndPP;
  3583   3758     if (enc == parser->m_encoding) {
  3584   3759       eventPP = &parser->m_eventPtr;
  3585   3760       *eventPP = s;
  3586   3761       eventEndPP = &parser->m_eventEndPtr;
................................................................................
  3590   3765     }
  3591   3766     *eventPP = s;
  3592   3767     *startPtr = NULL;
  3593   3768   
  3594   3769     for (;;) {
  3595   3770       const char *next = s; /* in case of XML_TOK_NONE or XML_TOK_PARTIAL */
  3596   3771       int tok = XmlCdataSectionTok(enc, s, end, &next);
         3772  +#ifdef XML_DTD
         3773  +    if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, account)) {
         3774  +      accountingOnAbort(parser);
         3775  +      return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
         3776  +    }
         3777  +#else
         3778  +    UNUSED_P(account);
         3779  +#endif
  3597   3780       *eventEndPP = next;
  3598   3781       switch (tok) {
  3599   3782       case XML_TOK_CDATA_SECT_CLOSE:
  3600   3783         if (parser->m_endCdataSectionHandler)
  3601   3784           parser->m_endCdataSectionHandler(parser->m_handlerArg);
  3602   3785         /* BEGIN disabled code */
  3603   3786         /* see comment under XML_TOK_CDATA_SECT_OPEN */
................................................................................
  3734   3917       eventPP = &(parser->m_openInternalEntities->internalEventPtr);
  3735   3918       eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
  3736   3919       /* LCOV_EXCL_STOP */
  3737   3920     }
  3738   3921     *eventPP = s;
  3739   3922     *startPtr = NULL;
  3740   3923     tok = XmlIgnoreSectionTok(enc, s, end, &next);
         3924  +#  ifdef XML_DTD
         3925  +  if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
         3926  +                                XML_ACCOUNT_DIRECT)) {
         3927  +    accountingOnAbort(parser);
         3928  +    return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
         3929  +  }
         3930  +#  endif
  3741   3931     *eventEndPP = next;
  3742   3932     switch (tok) {
  3743   3933     case XML_TOK_IGNORE_SECT:
  3744   3934       if (parser->m_defaultHandler)
  3745   3935         reportDefault(parser, enc, s, next);
  3746   3936       *startPtr = next;
  3747   3937       *nextPtr = next;
................................................................................
  3818   4008     const char *encodingName = NULL;
  3819   4009     const XML_Char *storedEncName = NULL;
  3820   4010     const ENCODING *newEncoding = NULL;
  3821   4011     const char *version = NULL;
  3822   4012     const char *versionend;
  3823   4013     const XML_Char *storedversion = NULL;
  3824   4014     int standalone = -1;
         4015  +
         4016  +#ifdef XML_DTD
         4017  +  if (! accountingDiffTolerated(parser, XML_TOK_XML_DECL, s, next, __LINE__,
         4018  +                                XML_ACCOUNT_DIRECT)) {
         4019  +    accountingOnAbort(parser);
         4020  +    return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
         4021  +  }
         4022  +#endif
         4023  +
  3825   4024     if (! (parser->m_ns ? XmlParseXmlDeclNS : XmlParseXmlDecl)(
  3826   4025             isGeneralTextEntity, parser->m_encoding, s, next, &parser->m_eventPtr,
  3827   4026             &version, &versionend, &encodingName, &newEncoding, &standalone)) {
  3828   4027       if (isGeneralTextEntity)
  3829   4028         return XML_ERROR_TEXT_DECL;
  3830   4029       else
  3831   4030         return XML_ERROR_XML_DECL;
................................................................................
  3967   4166     int tok;
  3968   4167     const char *start = s;
  3969   4168     const char *next = start;
  3970   4169     parser->m_eventPtr = start;
  3971   4170   
  3972   4171     for (;;) {
  3973   4172       tok = XmlPrologTok(parser->m_encoding, start, end, &next);
         4173  +    /* Note: Except for XML_TOK_BOM below, these bytes are accounted later in:
         4174  +             - storeEntityValue
         4175  +             - processXmlDecl
         4176  +    */
  3974   4177       parser->m_eventEndPtr = next;
  3975   4178       if (tok <= 0) {
  3976   4179         if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
  3977   4180           *nextPtr = s;
  3978   4181           return XML_ERROR_NONE;
  3979   4182         }
  3980   4183         switch (tok) {
................................................................................
  3985   4188         case XML_TOK_PARTIAL_CHAR:
  3986   4189           return XML_ERROR_PARTIAL_CHAR;
  3987   4190         case XML_TOK_NONE: /* start == end */
  3988   4191         default:
  3989   4192           break;
  3990   4193         }
  3991   4194         /* found end of entity value - can store it now */
  3992         -      return storeEntityValue(parser, parser->m_encoding, s, end);
         4195  +      return storeEntityValue(parser, parser->m_encoding, s, end,
         4196  +                              XML_ACCOUNT_DIRECT);
  3993   4197       } else if (tok == XML_TOK_XML_DECL) {
  3994   4198         enum XML_Error result;
  3995   4199         result = processXmlDecl(parser, 0, start, next);
  3996   4200         if (result != XML_ERROR_NONE)
  3997   4201           return result;
  3998   4202         /* At this point, m_parsingStatus.parsing cannot be XML_SUSPENDED.  For
  3999   4203          * that to happen, a parameter entity parsing handler must have attempted
................................................................................
  4012   4216          function to exit with *nextPtr set to s - that is what we want for other
  4013   4217          tokens, but not for the BOM - we would rather like to skip it;
  4014   4218          then, when this routine is entered the next time, XmlPrologTok will
  4015   4219          return XML_TOK_INVALID, since the BOM is still in the buffer
  4016   4220       */
  4017   4221       else if (tok == XML_TOK_BOM && next == end
  4018   4222                && ! parser->m_parsingStatus.finalBuffer) {
         4223  +#  ifdef XML_DTD
         4224  +      if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
         4225  +                                    XML_ACCOUNT_DIRECT)) {
         4226  +        accountingOnAbort(parser);
         4227  +        return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
         4228  +      }
         4229  +#  endif
         4230  +
  4019   4231         *nextPtr = next;
  4020   4232         return XML_ERROR_NONE;
  4021   4233       }
  4022   4234       /* If we get this token, we have the start of what might be a
  4023   4235          normal tag, but not a declaration (i.e. it doesn't begin with
  4024   4236          "<!").  In a DTD context, that isn't legal.
  4025   4237       */
................................................................................
  4054   4266       case XML_TOK_NONE: /* start == end */
  4055   4267       default:
  4056   4268         break;
  4057   4269       }
  4058   4270     }
  4059   4271     /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
  4060   4272        However, when parsing an external subset, doProlog will not accept a BOM
  4061         -     as valid, and report a syntax error, so we have to skip the BOM
         4273  +     as valid, and report a syntax error, so we have to skip the BOM, and
         4274  +     account for the BOM bytes.
  4062   4275     */
  4063   4276     else if (tok == XML_TOK_BOM) {
         4277  +    if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
         4278  +                                  XML_ACCOUNT_DIRECT)) {
         4279  +      accountingOnAbort(parser);
         4280  +      return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
         4281  +    }
         4282  +
  4064   4283       s = next;
  4065   4284       tok = XmlPrologTok(parser->m_encoding, s, end, &next);
  4066   4285     }
  4067   4286   
  4068   4287     parser->m_processor = prologProcessor;
  4069   4288     return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
  4070         -                  (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE);
         4289  +                  (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE,
         4290  +                  XML_ACCOUNT_DIRECT);
  4071   4291   }
  4072   4292   
  4073   4293   static enum XML_Error PTRCALL
  4074   4294   entityValueProcessor(XML_Parser parser, const char *s, const char *end,
  4075   4295                        const char **nextPtr) {
  4076   4296     const char *start = s;
  4077   4297     const char *next = s;
  4078   4298     const ENCODING *enc = parser->m_encoding;
  4079   4299     int tok;
  4080   4300   
  4081   4301     for (;;) {
  4082   4302       tok = XmlPrologTok(enc, start, end, &next);
         4303  +    /* Note: These bytes are accounted later in:
         4304  +             - storeEntityValue
         4305  +    */
  4083   4306       if (tok <= 0) {
  4084   4307         if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
  4085   4308           *nextPtr = s;
  4086   4309           return XML_ERROR_NONE;
  4087   4310         }
  4088   4311         switch (tok) {
  4089   4312         case XML_TOK_INVALID:
................................................................................
  4093   4316         case XML_TOK_PARTIAL_CHAR:
  4094   4317           return XML_ERROR_PARTIAL_CHAR;
  4095   4318         case XML_TOK_NONE: /* start == end */
  4096   4319         default:
  4097   4320           break;
  4098   4321         }
  4099   4322         /* found end of entity value - can store it now */
  4100         -      return storeEntityValue(parser, enc, s, end);
         4323  +      return storeEntityValue(parser, enc, s, end, XML_ACCOUNT_DIRECT);
  4101   4324       }
  4102   4325       start = next;
  4103   4326     }
  4104   4327   }
  4105   4328   
  4106   4329   #endif /* XML_DTD */
  4107   4330   
  4108   4331   static enum XML_Error PTRCALL
  4109   4332   prologProcessor(XML_Parser parser, const char *s, const char *end,
  4110   4333                   const char **nextPtr) {
  4111   4334     const char *next = s;
  4112   4335     int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
  4113   4336     return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
  4114         -                  (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE);
         4337  +                  (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE,
         4338  +                  XML_ACCOUNT_DIRECT);
  4115   4339   }
  4116   4340   
  4117   4341   static enum XML_Error
  4118   4342   doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
  4119   4343            int tok, const char *next, const char **nextPtr, XML_Bool haveMore,
  4120         -         XML_Bool allowClosingDoctype) {
         4344  +         XML_Bool allowClosingDoctype, enum XML_Account account) {
  4121   4345   #ifdef XML_DTD
  4122   4346     static const XML_Char externalSubsetName[] = {ASCII_HASH, '\0'};
  4123   4347   #endif /* XML_DTD */
  4124   4348     static const XML_Char atypeCDATA[]
  4125   4349         = {ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0'};
  4126   4350     static const XML_Char atypeID[] = {ASCII_I, ASCII_D, '\0'};
  4127   4351     static const XML_Char atypeIDREF[]
................................................................................
  4139   4363         = {ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K,
  4140   4364            ASCII_E, ASCII_N, ASCII_S, '\0'};
  4141   4365     static const XML_Char notationPrefix[]
  4142   4366         = {ASCII_N, ASCII_O, ASCII_T, ASCII_A,      ASCII_T,
  4143   4367            ASCII_I, ASCII_O, ASCII_N, ASCII_LPAREN, '\0'};
  4144   4368     static const XML_Char enumValueSep[] = {ASCII_PIPE, '\0'};
  4145   4369     static const XML_Char enumValueStart[] = {ASCII_LPAREN, '\0'};
         4370  +
         4371  +#ifndef XML_DTD
         4372  +  UNUSED_P(account);
         4373  +#endif
  4146   4374   
  4147   4375     /* save one level of indirection */
  4148   4376     DTD *const dtd = parser->m_dtd;
  4149   4377   
  4150   4378     const char **eventPP;
  4151   4379     const char **eventEndPP;
  4152   4380     enum XML_Content_Quant quant;
................................................................................
  4204   4432         default:
  4205   4433           tok = -tok;
  4206   4434           next = end;
  4207   4435           break;
  4208   4436         }
  4209   4437       }
  4210   4438       role = XmlTokenRole(&parser->m_prologState, tok, s, next, enc);
         4439  +#ifdef XML_DTD
         4440  +    switch (role) {
         4441  +    case XML_ROLE_INSTANCE_START: // bytes accounted in contentProcessor
         4442  +    case XML_ROLE_XML_DECL:       // bytes accounted in processXmlDecl
         4443  +    case XML_ROLE_TEXT_DECL:      // bytes accounted in processXmlDecl
         4444  +      break;
         4445  +    default:
         4446  +      if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, account)) {
         4447  +        accountingOnAbort(parser);
         4448  +        return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
         4449  +      }
         4450  +    }
         4451  +#endif
  4211   4452       switch (role) {
  4212   4453       case XML_ROLE_XML_DECL: {
  4213   4454         enum XML_Error result = processXmlDecl(parser, 0, s, next);
  4214   4455         if (result != XML_ERROR_NONE)
  4215   4456           return result;
  4216   4457         enc = parser->m_encoding;
  4217   4458         handleDefault = XML_FALSE;
................................................................................
  4479   4720         break;
  4480   4721       case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
  4481   4722       case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
  4482   4723         if (dtd->keepProcessing) {
  4483   4724           const XML_Char *attVal;
  4484   4725           enum XML_Error result = storeAttributeValue(
  4485   4726               parser, enc, parser->m_declAttributeIsCdata,
  4486         -            s + enc->minBytesPerChar, next - enc->minBytesPerChar, &dtd->pool);
         4727  +            s + enc->minBytesPerChar, next - enc->minBytesPerChar, &dtd->pool,
         4728  +            XML_ACCOUNT_NONE);
  4487   4729           if (result)
  4488   4730             return result;
  4489   4731           attVal = poolStart(&dtd->pool);
  4490   4732           poolFinish(&dtd->pool);
  4491   4733           /* ID attributes aren't allowed to have a default */
  4492   4734           if (! defineAttribute(
  4493   4735                   parser->m_declElementType, parser->m_declAttributeId,
................................................................................
  4512   4754             poolClear(&parser->m_tempPool);
  4513   4755             handleDefault = XML_FALSE;
  4514   4756           }
  4515   4757         }
  4516   4758         break;
  4517   4759       case XML_ROLE_ENTITY_VALUE:
  4518   4760         if (dtd->keepProcessing) {
  4519         -        enum XML_Error result = storeEntityValue(
  4520         -            parser, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar);
         4761  +        enum XML_Error result
         4762  +            = storeEntityValue(parser, enc, s + enc->minBytesPerChar,
         4763  +                               next - enc->minBytesPerChar, XML_ACCOUNT_NONE);
  4521   4764           if (parser->m_declEntity) {
  4522   4765             parser->m_declEntity->textPtr = poolStart(&dtd->entityValuePool);
  4523   4766             parser->m_declEntity->textLen
  4524   4767                 = (int)(poolLength(&dtd->entityValuePool));
  4525   4768             poolFinish(&dtd->entityValuePool);
  4526   4769             if (parser->m_entityDeclHandler) {
  4527   4770               *eventEndPP = s;
................................................................................
  4903   5146               return result;
  4904   5147             handleDefault = XML_FALSE;
  4905   5148             break;
  4906   5149           }
  4907   5150           if (parser->m_externalEntityRefHandler) {
  4908   5151             dtd->paramEntityRead = XML_FALSE;
  4909   5152             entity->open = XML_TRUE;
         5153  +          entityTrackingOnOpen(parser, entity, __LINE__);
  4910   5154             if (! parser->m_externalEntityRefHandler(
  4911   5155                     parser->m_externalEntityRefHandlerArg, 0, entity->base,
  4912   5156                     entity->systemId, entity->publicId)) {
         5157  +            entityTrackingOnClose(parser, entity, __LINE__);
  4913   5158               entity->open = XML_FALSE;
  4914   5159               return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
  4915   5160             }
         5161  +          entityTrackingOnClose(parser, entity, __LINE__);
  4916   5162             entity->open = XML_FALSE;
  4917   5163             handleDefault = XML_FALSE;
  4918   5164             if (! dtd->paramEntityRead) {
  4919   5165               dtd->keepProcessing = dtd->standalone;
  4920   5166               break;
  4921   5167             }
  4922   5168           } else {
................................................................................
  5106   5352   epilogProcessor(XML_Parser parser, const char *s, const char *end,
  5107   5353                   const char **nextPtr) {
  5108   5354     parser->m_processor = epilogProcessor;
  5109   5355     parser->m_eventPtr = s;
  5110   5356     for (;;) {
  5111   5357       const char *next = NULL;
  5112   5358       int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
         5359  +#ifdef XML_DTD
         5360  +    if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
         5361  +                                  XML_ACCOUNT_DIRECT)) {
         5362  +      accountingOnAbort(parser);
         5363  +      return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
         5364  +    }
         5365  +#endif
  5113   5366       parser->m_eventEndPtr = next;
  5114   5367       switch (tok) {
  5115   5368       /* report partial linebreak - it might be the last token */
  5116   5369       case -XML_TOK_PROLOG_S:
  5117   5370         if (parser->m_defaultHandler) {
  5118   5371           reportDefault(parser, parser->m_encoding, s, next);
  5119   5372           if (parser->m_parsingStatus.parsing == XML_FINISHED)
................................................................................
  5179   5432     } else {
  5180   5433       openEntity
  5181   5434           = (OPEN_INTERNAL_ENTITY *)MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY));
  5182   5435       if (! openEntity)
  5183   5436         return XML_ERROR_NO_MEMORY;
  5184   5437     }
  5185   5438     entity->open = XML_TRUE;
         5439  +#ifdef XML_DTD
         5440  +  entityTrackingOnOpen(parser, entity, __LINE__);
         5441  +#endif
  5186   5442     entity->processed = 0;
  5187   5443     openEntity->next = parser->m_openInternalEntities;
  5188   5444     parser->m_openInternalEntities = openEntity;
  5189   5445     openEntity->entity = entity;
  5190   5446     openEntity->startTagLevel = parser->m_tagLevel;
  5191   5447     openEntity->betweenDecl = betweenDecl;
  5192   5448     openEntity->internalEventPtr = NULL;
................................................................................
  5197   5453     next = textStart;
  5198   5454   
  5199   5455   #ifdef XML_DTD
  5200   5456     if (entity->is_param) {
  5201   5457       int tok
  5202   5458           = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
  5203   5459       result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
  5204         -                      tok, next, &next, XML_FALSE, XML_FALSE);
         5460  +                      tok, next, &next, XML_FALSE, XML_FALSE,
         5461  +                      XML_ACCOUNT_ENTITY_EXPANSION);
  5205   5462     } else
  5206   5463   #endif /* XML_DTD */
  5207   5464       result = doContent(parser, parser->m_tagLevel, parser->m_internalEncoding,
  5208         -                       textStart, textEnd, &next, XML_FALSE);
         5465  +                       textStart, textEnd, &next, XML_FALSE,
         5466  +                       XML_ACCOUNT_ENTITY_EXPANSION);
  5209   5467   
  5210   5468     if (result == XML_ERROR_NONE) {
  5211   5469       if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
  5212   5470         entity->processed = (int)(next - textStart);
  5213   5471         parser->m_processor = internalEntityProcessor;
  5214   5472       } else {
         5473  +#ifdef XML_DTD
         5474  +      entityTrackingOnClose(parser, entity, __LINE__);
         5475  +#endif /* XML_DTD */
  5215   5476         entity->open = XML_FALSE;
  5216   5477         parser->m_openInternalEntities = openEntity->next;
  5217   5478         /* put openEntity back in list of free instances */
  5218   5479         openEntity->next = parser->m_freeInternalEntities;
  5219   5480         parser->m_freeInternalEntities = openEntity;
  5220   5481       }
  5221   5482     }
................................................................................
  5240   5501     next = textStart;
  5241   5502   
  5242   5503   #ifdef XML_DTD
  5243   5504     if (entity->is_param) {
  5244   5505       int tok
  5245   5506           = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
  5246   5507       result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
  5247         -                      tok, next, &next, XML_FALSE, XML_TRUE);
         5508  +                      tok, next, &next, XML_FALSE, XML_TRUE,
         5509  +                      XML_ACCOUNT_ENTITY_EXPANSION);
  5248   5510     } else
  5249   5511   #endif /* XML_DTD */
  5250   5512       result = doContent(parser, openEntity->startTagLevel,
  5251   5513                          parser->m_internalEncoding, textStart, textEnd, &next,
  5252         -                       XML_FALSE);
         5514  +                       XML_FALSE, XML_ACCOUNT_ENTITY_EXPANSION);
  5253   5515   
  5254   5516     if (result != XML_ERROR_NONE)
  5255   5517       return result;
  5256   5518     else if (textEnd != next
  5257   5519              && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
  5258   5520       entity->processed = (int)(next - (const char *)entity->textPtr);
  5259   5521       return result;
  5260   5522     } else {
         5523  +#ifdef XML_DTD
         5524  +    entityTrackingOnClose(parser, entity, __LINE__);
         5525  +#endif
  5261   5526       entity->open = XML_FALSE;
  5262   5527       parser->m_openInternalEntities = openEntity->next;
  5263   5528       /* put openEntity back in list of free instances */
  5264   5529       openEntity->next = parser->m_freeInternalEntities;
  5265   5530       parser->m_freeInternalEntities = openEntity;
  5266   5531     }
  5267   5532   
  5268   5533   #ifdef XML_DTD
  5269   5534     if (entity->is_param) {
  5270   5535       int tok;
  5271   5536       parser->m_processor = prologProcessor;
  5272   5537       tok = XmlPrologTok(parser->m_encoding, s, end, &next);
  5273   5538       return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
  5274         -                    (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE);
         5539  +                    (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE,
         5540  +                    XML_ACCOUNT_DIRECT);
  5275   5541     } else
  5276   5542   #endif /* XML_DTD */
  5277   5543     {
  5278   5544       parser->m_processor = contentProcessor;
  5279   5545       /* see externalEntityContentProcessor vs contentProcessor */
  5280   5546       return doContent(parser, parser->m_parentParser ? 1 : 0, parser->m_encoding,
  5281   5547                        s, end, nextPtr,
  5282         -                     (XML_Bool)! parser->m_parsingStatus.finalBuffer);
         5548  +                     (XML_Bool)! parser->m_parsingStatus.finalBuffer,
         5549  +                     XML_ACCOUNT_DIRECT);
  5283   5550     }
  5284   5551   }
  5285   5552   
  5286   5553   static enum XML_Error PTRCALL
  5287   5554   errorProcessor(XML_Parser parser, const char *s, const char *end,
  5288   5555                  const char **nextPtr) {
  5289   5556     UNUSED_P(s);
................................................................................
  5290   5557     UNUSED_P(end);
  5291   5558     UNUSED_P(nextPtr);
  5292   5559     return parser->m_errorCode;
  5293   5560   }
  5294   5561   
  5295   5562   static enum XML_Error
  5296   5563   storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
  5297         -                    const char *ptr, const char *end, STRING_POOL *pool) {
         5564  +                    const char *ptr, const char *end, STRING_POOL *pool,
         5565  +                    enum XML_Account account) {
  5298   5566     enum XML_Error result
  5299         -      = appendAttributeValue(parser, enc, isCdata, ptr, end, pool);
         5567  +      = appendAttributeValue(parser, enc, isCdata, ptr, end, pool, account);
  5300   5568     if (result)
  5301   5569       return result;
  5302   5570     if (! isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
  5303   5571       poolChop(pool);
  5304   5572     if (! poolAppendChar(pool, XML_T('\0')))
  5305   5573       return XML_ERROR_NO_MEMORY;
  5306   5574     return XML_ERROR_NONE;
  5307   5575   }
  5308   5576   
  5309   5577   static enum XML_Error
  5310   5578   appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
  5311         -                     const char *ptr, const char *end, STRING_POOL *pool) {
         5579  +                     const char *ptr, const char *end, STRING_POOL *pool,
         5580  +                     enum XML_Account account) {
  5312   5581     DTD *const dtd = parser->m_dtd; /* save one level of indirection */
         5582  +#ifndef XML_DTD
         5583  +  UNUSED_P(account);
         5584  +#endif
         5585  +
  5313   5586     for (;;) {
  5314         -    const char *next;
         5587  +    const char *next
         5588  +        = ptr; /* XmlAttributeValueTok doesn't always set the last arg */
  5315   5589       int tok = XmlAttributeValueTok(enc, ptr, end, &next);
         5590  +#ifdef XML_DTD
         5591  +    if (! accountingDiffTolerated(parser, tok, ptr, next, __LINE__, account)) {
         5592  +      accountingOnAbort(parser);
         5593  +      return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
         5594  +    }
         5595  +#endif
  5316   5596       switch (tok) {
  5317   5597       case XML_TOK_NONE:
  5318   5598         return XML_ERROR_NONE;
  5319   5599       case XML_TOK_INVALID:
  5320   5600         if (enc == parser->m_encoding)
  5321   5601           parser->m_eventPtr = next;
  5322   5602         return XML_ERROR_INVALID_TOKEN;
................................................................................
  5368   5648       case XML_TOK_ENTITY_REF: {
  5369   5649         const XML_Char *name;
  5370   5650         ENTITY *entity;
  5371   5651         char checkEntityDecl;
  5372   5652         XML_Char ch = (XML_Char)XmlPredefinedEntityName(
  5373   5653             enc, ptr + enc->minBytesPerChar, next - enc->minBytesPerChar);
  5374   5654         if (ch) {
         5655  +#ifdef XML_DTD
         5656  +        /* NOTE: We are replacing 4-6 characters original input for 1 character
         5657  +         *       so there is no amplification and hence recording without
         5658  +         *       protection. */
         5659  +        accountingDiffTolerated(parser, tok, (char *)&ch,
         5660  +                                ((char *)&ch) + sizeof(XML_Char), __LINE__,
         5661  +                                XML_ACCOUNT_ENTITY_EXPANSION);
         5662  +#endif /* XML_DTD */
  5375   5663           if (! poolAppendChar(pool, ch))
  5376   5664             return XML_ERROR_NO_MEMORY;
  5377   5665           break;
  5378   5666         }
  5379   5667         name = poolStoreString(&parser->m_temp2Pool, enc,
  5380   5668                                ptr + enc->minBytesPerChar,
  5381   5669                                next - enc->minBytesPerChar);
................................................................................
  5445   5733           if (enc == parser->m_encoding)
  5446   5734             parser->m_eventPtr = ptr;
  5447   5735           return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
  5448   5736         } else {
  5449   5737           enum XML_Error result;
  5450   5738           const XML_Char *textEnd = entity->textPtr + entity->textLen;
  5451   5739           entity->open = XML_TRUE;
         5740  +#ifdef XML_DTD
         5741  +        entityTrackingOnOpen(parser, entity, __LINE__);
         5742  +#endif
  5452   5743           result = appendAttributeValue(parser, parser->m_internalEncoding,
  5453   5744                                         isCdata, (const char *)entity->textPtr,
  5454         -                                      (const char *)textEnd, pool);
         5745  +                                      (const char *)textEnd, pool,
         5746  +                                      XML_ACCOUNT_ENTITY_EXPANSION);
         5747  +#ifdef XML_DTD
         5748  +        entityTrackingOnClose(parser, entity, __LINE__);
         5749  +#endif
  5455   5750           entity->open = XML_FALSE;
  5456   5751           if (result)
  5457   5752             return result;
  5458   5753         }
  5459   5754       } break;
  5460   5755       default:
  5461   5756         /* The only token returned by XmlAttributeValueTok() that does
................................................................................
  5477   5772       ptr = next;
  5478   5773     }
  5479   5774     /* not reached */
  5480   5775   }
  5481   5776   
  5482   5777   static enum XML_Error
  5483   5778   storeEntityValue(XML_Parser parser, const ENCODING *enc,
  5484         -                 const char *entityTextPtr, const char *entityTextEnd) {
         5779  +                 const char *entityTextPtr, const char *entityTextEnd,
         5780  +                 enum XML_Account account) {
  5485   5781     DTD *const dtd = parser->m_dtd; /* save one level of indirection */
  5486   5782     STRING_POOL *pool = &(dtd->entityValuePool);
  5487   5783     enum XML_Error result = XML_ERROR_NONE;
  5488   5784   #ifdef XML_DTD
  5489   5785     int oldInEntityValue = parser->m_prologState.inEntityValue;
  5490   5786     parser->m_prologState.inEntityValue = 1;
         5787  +#else
         5788  +  UNUSED_P(account);
  5491   5789   #endif /* XML_DTD */
  5492   5790     /* never return Null for the value argument in EntityDeclHandler,
  5493   5791        since this would indicate an external entity; therefore we
  5494   5792        have to make sure that entityValuePool.start is not null */
  5495   5793     if (! pool->blocks) {
  5496   5794       if (! poolGrow(pool))
  5497   5795         return XML_ERROR_NO_MEMORY;
  5498   5796     }
  5499   5797   
  5500   5798     for (;;) {
  5501         -    const char *next;
         5799  +    const char *next
         5800  +        = entityTextPtr; /* XmlEntityValueTok doesn't always set the last arg */
  5502   5801       int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
         5802  +
         5803  +#ifdef XML_DTD
         5804  +    if (! accountingDiffTolerated(parser, tok, entityTextPtr, next, __LINE__,
         5805  +                                  account)) {
         5806  +      accountingOnAbort(parser);
         5807  +      result = XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
         5808  +      goto endEntityValue;
         5809  +    }
         5810  +#endif
         5811  +
  5503   5812       switch (tok) {
  5504   5813       case XML_TOK_PARAM_ENTITY_REF:
  5505   5814   #ifdef XML_DTD
  5506   5815         if (parser->m_isParamEntity || enc != parser->m_encoding) {
  5507   5816           const XML_Char *name;
  5508   5817           ENTITY *entity;
  5509   5818           name = poolStoreString(&parser->m_tempPool, enc,
................................................................................
  5531   5840             result = XML_ERROR_RECURSIVE_ENTITY_REF;
  5532   5841             goto endEntityValue;
  5533   5842           }
  5534   5843           if (entity->systemId) {
  5535   5844             if (parser->m_externalEntityRefHandler) {
  5536   5845               dtd->paramEntityRead = XML_FALSE;
  5537   5846               entity->open = XML_TRUE;
         5847  +            entityTrackingOnOpen(parser, entity, __LINE__);
  5538   5848               if (! parser->m_externalEntityRefHandler(
  5539   5849                       parser->m_externalEntityRefHandlerArg, 0, entity->base,
  5540   5850                       entity->systemId, entity->publicId)) {
         5851  +              entityTrackingOnClose(parser, entity, __LINE__);
  5541   5852                 entity->open = XML_FALSE;
  5542   5853                 result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
  5543   5854                 goto endEntityValue;
  5544   5855               }
         5856  +            entityTrackingOnClose(parser, entity, __LINE__);
  5545   5857               entity->open = XML_FALSE;
  5546   5858               if (! dtd->paramEntityRead)
  5547   5859                 dtd->keepProcessing = dtd->standalone;
  5548   5860             } else
  5549   5861               dtd->keepProcessing = dtd->standalone;
  5550   5862           } else {
  5551   5863             entity->open = XML_TRUE;
         5864  +          entityTrackingOnOpen(parser, entity, __LINE__);
  5552   5865             result = storeEntityValue(
  5553   5866                 parser, parser->m_internalEncoding, (const char *)entity->textPtr,
  5554         -              (const char *)(entity->textPtr + entity->textLen));
         5867  +              (const char *)(entity->textPtr + entity->textLen),
         5868  +              XML_ACCOUNT_ENTITY_EXPANSION);
         5869  +          entityTrackingOnClose(parser, entity, __LINE__);
  5555   5870             entity->open = XML_FALSE;
  5556   5871             if (result)
  5557   5872               goto endEntityValue;
  5558   5873           }
  5559   5874           break;
  5560   5875         }
  5561   5876   #endif /* XML_DTD */
................................................................................
  6908   7223     result = memsuite->malloc_fcn(charsRequired * sizeof(XML_Char));
  6909   7224     if (result == NULL)
  6910   7225       return NULL;
  6911   7226     /* Copy the original into place */
  6912   7227     memcpy(result, s, charsRequired * sizeof(XML_Char));
  6913   7228     return result;
  6914   7229   }
         7230  +
         7231  +#ifdef XML_DTD
         7232  +
         7233  +static float
         7234  +accountingGetCurrentAmplification(XML_Parser rootParser) {
         7235  +  const XmlBigCount countBytesOutput
         7236  +      = rootParser->m_accounting.countBytesDirect
         7237  +        + rootParser->m_accounting.countBytesIndirect;
         7238  +  const float amplificationFactor
         7239  +      = rootParser->m_accounting.countBytesDirect
         7240  +            ? (countBytesOutput
         7241  +               / (float)(rootParser->m_accounting.countBytesDirect))
         7242  +            : 1.0f;
         7243  +  assert(! rootParser->m_parentParser);
         7244  +  return amplificationFactor;
         7245  +}
         7246  +
         7247  +static void
         7248  +accountingReportStats(XML_Parser originParser, const char *epilog) {
         7249  +  const XML_Parser rootParser = getRootParserOf(originParser, NULL);
         7250  +  assert(! rootParser->m_parentParser);
         7251  +
         7252  +  if (rootParser->m_accounting.debugLevel < 1) {
         7253  +    return;
         7254  +  }
         7255  +
         7256  +  const float amplificationFactor
         7257  +      = accountingGetCurrentAmplification(rootParser);
         7258  +  fprintf(stderr,
         7259  +          "expat: Accounting(%p): Direct " EXPAT_FMT_ULL(
         7260  +              "10") ", indirect " EXPAT_FMT_ULL("10") ", amplification %8.2f%s",
         7261  +          (void *)rootParser, rootParser->m_accounting.countBytesDirect,
         7262  +          rootParser->m_accounting.countBytesIndirect,
         7263  +          (double)amplificationFactor, epilog);
         7264  +}
         7265  +
         7266  +static void
         7267  +accountingOnAbort(XML_Parser originParser) {
         7268  +  accountingReportStats(originParser, " ABORTING\n");
         7269  +}
         7270  +
         7271  +static void
         7272  +accountingReportDiff(XML_Parser rootParser,
         7273  +                     unsigned int levelsAwayFromRootParser, const char *before,
         7274  +                     const char *after, ptrdiff_t bytesMore, int source_line,
         7275  +                     enum XML_Account account) {
         7276  +  assert(! rootParser->m_parentParser);
         7277  +
         7278  +  fprintf(stderr,
         7279  +          " (+" EXPAT_FMT_PTRDIFF_T("6") " bytes %s|%d, xmlparse.c:%d) %*s\"",
         7280  +          bytesMore, (account == XML_ACCOUNT_DIRECT) ? "DIR" : "EXP",
         7281  +          levelsAwayFromRootParser, source_line, 10, "");
         7282  +
         7283  +  const char ellipis[] = "[..]";
         7284  +  const size_t ellipsisLength = sizeof(ellipis) /* because compile-time */ - 1;
         7285  +  const unsigned int contextLength = 10;
         7286  +
         7287  +  /* Note: Performance is of no concern here */
         7288  +  const char *walker = before;
         7289  +  if ((rootParser->m_accounting.debugLevel >= 3)
         7290  +      || (after - before)
         7291  +             <= (ptrdiff_t)(contextLength + ellipsisLength + contextLength)) {
         7292  +    for (; walker < after; walker++) {
         7293  +      fprintf(stderr, "%s", unsignedCharToPrintable(walker[0]));
         7294  +    }
         7295  +  } else {
         7296  +    for (; walker < before + contextLength; walker++) {
         7297  +      fprintf(stderr, "%s", unsignedCharToPrintable(walker[0]));
         7298  +    }
         7299  +    fprintf(stderr, ellipis);
         7300  +    walker = after - contextLength;
         7301  +    for (; walker < after; walker++) {
         7302  +      fprintf(stderr, "%s", unsignedCharToPrintable(walker[0]));
         7303  +    }
         7304  +  }
         7305  +  fprintf(stderr, "\"\n");
         7306  +}
         7307  +
         7308  +static XML_Bool
         7309  +accountingDiffTolerated(XML_Parser originParser, int tok, const char *before,
         7310  +                        const char *after, int source_line,
         7311  +                        enum XML_Account account) {
         7312  +  /* Note: We need to check the token type *first* to be sure that
         7313  +   *       we can even access variable <after>, safely.
         7314  +   *       E.g. for XML_TOK_NONE <after> may hold an invalid pointer. */
         7315  +  switch (tok) {
         7316  +  case XML_TOK_INVALID:
         7317  +  case XML_TOK_PARTIAL:
         7318  +  case XML_TOK_PARTIAL_CHAR:
         7319  +  case XML_TOK_NONE:
         7320  +    return XML_TRUE;
         7321  +  }
         7322  +
         7323  +  if (account == XML_ACCOUNT_NONE)
         7324  +    return XML_TRUE; /* because these bytes have been accounted for, already */
         7325  +
         7326  +  unsigned int levelsAwayFromRootParser;
         7327  +  const XML_Parser rootParser
         7328  +      = getRootParserOf(originParser, &levelsAwayFromRootParser);
         7329  +  assert(! rootParser->m_parentParser);
         7330  +
         7331  +  const int isDirect
         7332  +      = (account == XML_ACCOUNT_DIRECT) && (originParser == rootParser);
         7333  +  const ptrdiff_t bytesMore = after - before;
         7334  +
         7335  +  XmlBigCount *const additionTarget
         7336  +      = isDirect ? &rootParser->m_accounting.countBytesDirect
         7337  +                 : &rootParser->m_accounting.countBytesIndirect;
         7338  +
         7339  +  /* Detect and avoid integer overflow */
         7340  +  if (*additionTarget > (XmlBigCount)(-1) - (XmlBigCount)bytesMore)
         7341  +    return XML_FALSE;
         7342  +  *additionTarget += bytesMore;
         7343  +
         7344  +  const XmlBigCount countBytesOutput
         7345  +      = rootParser->m_accounting.countBytesDirect
         7346  +        + rootParser->m_accounting.countBytesIndirect;
         7347  +  const float amplificationFactor
         7348  +      = accountingGetCurrentAmplification(rootParser);
         7349  +  const XML_Bool tolerated
         7350  +      = (countBytesOutput < rootParser->m_accounting.activationThresholdBytes)
         7351  +        || (amplificationFactor
         7352  +            <= rootParser->m_accounting.maximumAmplificationFactor);
         7353  +
         7354  +  if (rootParser->m_accounting.debugLevel >= 2) {
         7355  +    accountingReportStats(rootParser, "");
         7356  +    accountingReportDiff(rootParser, levelsAwayFromRootParser, before, after,
         7357  +                         bytesMore, source_line, account);
         7358  +  }
         7359  +
         7360  +  return tolerated;
         7361  +}
         7362  +
         7363  +unsigned long long
         7364  +testingAccountingGetCountBytesDirect(XML_Parser parser) {
         7365  +  if (! parser)
         7366  +    return 0;
         7367  +  return parser->m_accounting.countBytesDirect;
         7368  +}
         7369  +
         7370  +unsigned long long
         7371  +testingAccountingGetCountBytesIndirect(XML_Parser parser) {
         7372  +  if (! parser)
         7373  +    return 0;
         7374  +  return parser->m_accounting.countBytesIndirect;
         7375  +}
         7376  +
         7377  +static void
         7378  +entityTrackingReportStats(XML_Parser rootParser, ENTITY *entity,
         7379  +                          const char *action, int sourceLine) {
         7380  +  assert(! rootParser->m_parentParser);
         7381  +  if (rootParser->m_entity_stats.debugLevel < 1)
         7382  +    return;
         7383  +
         7384  +#  if defined(XML_UNICODE)
         7385  +  const char *const entityName = "[..]";
         7386  +#  else
         7387  +  const char *const entityName = entity->name;
         7388  +#  endif
         7389  +
         7390  +  fprintf(
         7391  +      stderr,
         7392  +      "expat: Entities(%p): Count %9d, depth %2d/%2d %*s%s%s; %s length %d (xmlparse.c:%d)\n",
         7393  +      (void *)rootParser, rootParser->m_entity_stats.countEverOpened,
         7394  +      rootParser->m_entity_stats.currentDepth,
         7395  +      rootParser->m_entity_stats.maximumDepthSeen,
         7396  +      (rootParser->m_entity_stats.currentDepth - 1) * 2, "",
         7397  +      entity->is_param ? "%" : "&", entityName, action, entity->textLen,
         7398  +      sourceLine);
         7399  +}
         7400  +
         7401  +static void
         7402  +entityTrackingOnOpen(XML_Parser originParser, ENTITY *entity, int sourceLine) {
         7403  +  const XML_Parser rootParser = getRootParserOf(originParser, NULL);
         7404  +  assert(! rootParser->m_parentParser);
         7405  +
         7406  +  rootParser->m_entity_stats.countEverOpened++;
         7407  +  rootParser->m_entity_stats.currentDepth++;
         7408  +  if (rootParser->m_entity_stats.currentDepth
         7409  +      > rootParser->m_entity_stats.maximumDepthSeen) {
         7410  +    rootParser->m_entity_stats.maximumDepthSeen++;
         7411  +  }
         7412  +
         7413  +  entityTrackingReportStats(rootParser, entity, "OPEN ", sourceLine);
         7414  +}
         7415  +
         7416  +static void
         7417  +entityTrackingOnClose(XML_Parser originParser, ENTITY *entity, int sourceLine) {
         7418  +  const XML_Parser rootParser = getRootParserOf(originParser, NULL);
         7419  +  assert(! rootParser->m_parentParser);
         7420  +
         7421  +  entityTrackingReportStats(rootParser, entity, "CLOSE", sourceLine);
         7422  +  rootParser->m_entity_stats.currentDepth--;
         7423  +}
         7424  +
         7425  +static XML_Parser
         7426  +getRootParserOf(XML_Parser parser, unsigned int *outLevelDiff) {
         7427  +  XML_Parser rootParser = parser;
         7428  +  unsigned int stepsTakenUpwards = 0;
         7429  +  while (rootParser->m_parentParser) {
         7430  +    rootParser = rootParser->m_parentParser;
         7431  +    stepsTakenUpwards++;
         7432  +  }
         7433  +  assert(! rootParser->m_parentParser);
         7434  +  if (outLevelDiff != NULL) {
         7435  +    *outLevelDiff = stepsTakenUpwards;
         7436  +  }
         7437  +  return rootParser;
         7438  +}
         7439  +
         7440  +const char *
         7441  +unsignedCharToPrintable(unsigned char c) {
         7442  +  switch (c) {
         7443  +  case 0:
         7444  +    return "\\0";
         7445  +  case 1:
         7446  +    return "\\x1";
         7447  +  case 2:
         7448  +    return "\\x2";
         7449  +  case 3:
         7450  +    return "\\x3";
         7451  +  case 4:
         7452  +    return "\\x4";
         7453  +  case 5:
         7454  +    return "\\x5";
         7455  +  case 6:
         7456  +    return "\\x6";
         7457  +  case 7:
         7458  +    return "\\x7";
         7459  +  case 8:
         7460  +    return "\\x8";
         7461  +  case 9:
         7462  +    return "\\t";
         7463  +  case 10:
         7464  +    return "\\n";
         7465  +  case 11:
         7466  +    return "\\xB";
         7467  +  case 12:
         7468  +    return "\\xC";
         7469  +  case 13:
         7470  +    return "\\r";
         7471  +  case 14:
         7472  +    return "\\xE";
         7473  +  case 15:
         7474  +    return "\\xF";
         7475  +  case 16:
         7476  +    return "\\x10";
         7477  +  case 17:
         7478  +    return "\\x11";
         7479  +  case 18:
         7480  +    return "\\x12";
         7481  +  case 19:
         7482  +    return "\\x13";
         7483  +  case 20:
         7484  +    return "\\x14";
         7485  +  case 21:
         7486  +    return "\\x15";
         7487  +  case 22:
         7488  +    return "\\x16";
         7489  +  case 23:
         7490  +    return "\\x17";
         7491  +  case 24:
         7492  +    return "\\x18";
         7493  +  case 25:
         7494  +    return "\\x19";
         7495  +  case 26:
         7496  +    return "\\x1A";
         7497  +  case 27:
         7498  +    return "\\x1B";
         7499  +  case 28:
         7500  +    return "\\x1C";
         7501  +  case 29:
         7502  +    return "\\x1D";
         7503  +  case 30:
         7504  +    return "\\x1E";
         7505  +  case 31:
         7506  +    return "\\x1F";
         7507  +  case 32:
         7508  +    return " ";
         7509  +  case 33:
         7510  +    return "!";
         7511  +  case 34:
         7512  +    return "\\\"";
         7513  +  case 35:
         7514  +    return "#";
         7515  +  case 36:
         7516  +    return "$";
         7517  +  case 37:
         7518  +    return "%";
         7519  +  case 38:
         7520  +    return "&";
         7521  +  case 39:
         7522  +    return "'";
         7523  +  case 40:
         7524  +    return "(";
         7525  +  case 41:
         7526  +    return ")";
         7527  +  case 42:
         7528  +    return "*";
         7529  +  case 43:
         7530  +    return "+";
         7531  +  case 44:
         7532  +    return ",";
         7533  +  case 45:
         7534  +    return "-";
         7535  +  case 46:
         7536  +    return ".";
         7537  +  case 47:
         7538  +    return "/";
         7539  +  case 48:
         7540  +    return "0";
         7541  +  case 49:
         7542  +    return "1";
         7543  +  case 50:
         7544  +    return "2";
         7545  +  case 51:
         7546  +    return "3";
         7547  +  case 52:
         7548  +    return "4";
         7549  +  case 53:
         7550  +    return "5";
         7551  +  case 54:
         7552  +    return "6";
         7553  +  case 55:
         7554  +    return "7";
         7555  +  case 56:
         7556  +    return "8";
         7557  +  case 57:
         7558  +    return "9";
         7559  +  case 58:
         7560  +    return ":";
         7561  +  case 59:
         7562  +    return ";";
         7563  +  case 60:
         7564  +    return "<";
         7565  +  case 61:
         7566  +    return "=";
         7567  +  case 62:
         7568  +    return ">";
         7569  +  case 63:
         7570  +    return "?";
         7571  +  case 64:
         7572  +    return "@";
         7573  +  case 65:
         7574  +    return "A";
         7575  +  case 66:
         7576  +    return "B";
         7577  +  case 67:
         7578  +    return "C";
         7579  +  case 68:
         7580  +    return "D";
         7581  +  case 69:
         7582  +    return "E";
         7583  +  case 70:
         7584  +    return "F";
         7585  +  case 71:
         7586  +    return "G";
         7587  +  case 72:
         7588  +    return "H";
         7589  +  case 73:
         7590  +    return "I";
         7591  +  case 74:
         7592  +    return "J";
         7593  +  case 75:
         7594  +    return "K";
         7595  +  case 76:
         7596  +    return "L";
         7597  +  case 77:
         7598  +    return "M";
         7599  +  case 78:
         7600  +    return "N";
         7601  +  case 79:
         7602  +    return "O";
         7603  +  case 80:
         7604  +    return "P";
         7605  +  case 81:
         7606  +    return "Q";
         7607  +  case 82:
         7608  +    return "R";
         7609  +  case 83:
         7610  +    return "S";
         7611  +  case 84:
         7612  +    return "T";
         7613  +  case 85:
         7614  +    return "U";
         7615  +  case 86:
         7616  +    return "V";
         7617  +  case 87:
         7618  +    return "W";
         7619  +  case 88:
         7620  +    return "X";
         7621  +  case 89:
         7622  +    return "Y";
         7623  +  case 90:
         7624  +    return "Z";
         7625  +  case 91:
         7626  +    return "[";
         7627  +  case 92:
         7628  +    return "\\\\";
         7629  +  case 93:
         7630  +    return "]";
         7631  +  case 94:
         7632  +    return "^";
         7633  +  case 95:
         7634  +    return "_";
         7635  +  case 96:
         7636  +    return "`";
         7637  +  case 97:
         7638  +    return "a";
         7639  +  case 98:
         7640  +    return "b";
         7641  +  case 99:
         7642  +    return "c";
         7643  +  case 100:
         7644  +    return "d";
         7645  +  case 101:
         7646  +    return "e";
         7647  +  case 102:
         7648  +    return "f";
         7649  +  case 103:
         7650  +    return "g";
         7651  +  case 104:
         7652  +    return "h";
         7653  +  case 105:
         7654  +    return "i";
         7655  +  case 106:
         7656  +    return "j";
         7657  +  case 107:
         7658  +    return "k";
         7659  +  case 108:
         7660  +    return "l";
         7661  +  case 109:
         7662  +    return "m";
         7663  +  case 110:
         7664  +    return "n";
         7665  +  case 111:
         7666  +    return "o";
         7667  +  case 112:
         7668  +    return "p";
         7669  +  case 113:
         7670  +    return "q";
         7671  +  case 114:
         7672  +    return "r";
         7673  +  case 115:
         7674  +    return "s";
         7675  +  case 116:
         7676  +    return "t";
         7677  +  case 117:
         7678  +    return "u";
         7679  +  case 118:
         7680  +    return "v";
         7681  +  case 119:
         7682  +    return "w";
         7683  +  case 120:
         7684  +    return "x";
         7685  +  case 121:
         7686  +    return "y";
         7687  +  case 122:
         7688  +    return "z";
         7689  +  case 123:
         7690  +    return "{";
         7691  +  case 124:
         7692  +    return "|";
         7693  +  case 125:
         7694  +    return "}";
         7695  +  case 126:
         7696  +    return "~";
         7697  +  case 127:
         7698  +    return "\\x7F";
         7699  +  case 128:
         7700  +    return "\\x80";
         7701  +  case 129:
         7702  +    return "\\x81";
         7703  +  case 130:
         7704  +    return "\\x82";
         7705  +  case 131:
         7706  +    return "\\x83";
         7707  +  case 132:
         7708  +    return "\\x84";
         7709  +  case 133:
         7710  +    return "\\x85";
         7711  +  case 134:
         7712  +    return "\\x86";
         7713  +  case 135:
         7714  +    return "\\x87";
         7715  +  case 136:
         7716  +    return "\\x88";
         7717  +  case 137:
         7718  +    return "\\x89";
         7719  +  case 138:
         7720  +    return "\\x8A";
         7721  +  case 139:
         7722  +    return "\\x8B";
         7723  +  case 140:
         7724  +    return "\\x8C";
         7725  +  case 141:
         7726  +    return "\\x8D";
         7727  +  case 142:
         7728  +    return "\\x8E";
         7729  +  case 143:
         7730  +    return "\\x8F";
         7731  +  case 144:
         7732  +    return "\\x90";
         7733  +  case 145:
         7734  +    return "\\x91";
         7735  +  case 146:
         7736  +    return "\\x92";
         7737  +  case 147:
         7738  +    return "\\x93";
         7739  +  case 148:
         7740  +    return "\\x94";
         7741  +  case 149:
         7742  +    return "\\x95";
         7743  +  case 150:
         7744  +    return "\\x96";
         7745  +  case 151:
         7746  +    return "\\x97";
         7747  +  case 152:
         7748  +    return "\\x98";
         7749  +  case 153:
         7750  +    return "\\x99";
         7751  +  case 154:
         7752  +    return "\\x9A";
         7753  +  case 155:
         7754  +    return "\\x9B";
         7755  +  case 156:
         7756  +    return "\\x9C";
         7757  +  case 157:
         7758  +    return "\\x9D";
         7759  +  case 158:
         7760  +    return "\\x9E";
         7761  +  case 159:
         7762  +    return "\\x9F";
         7763  +  case 160:
         7764  +    return "\\xA0";
         7765  +  case 161:
         7766  +    return "\\xA1";
         7767  +  case 162:
         7768  +    return "\\xA2";
         7769  +  case 163:
         7770  +    return "\\xA3";
         7771  +  case 164:
         7772  +    return "\\xA4";
         7773  +  case 165:
         7774  +    return "\\xA5";
         7775  +  case 166:
         7776  +    return "\\xA6";
         7777  +  case 167:
         7778  +    return "\\xA7";
         7779  +  case 168:
         7780  +    return "\\xA8";
         7781  +  case 169:
         7782  +    return "\\xA9";
         7783  +  case 170:
         7784  +    return "\\xAA";
         7785  +  case 171:
         7786  +    return "\\xAB";
         7787  +  case 172:
         7788  +    return "\\xAC";
         7789  +  case 173:
         7790  +    return "\\xAD";
         7791  +  case 174:
         7792  +    return "\\xAE";
         7793  +  case 175:
         7794  +    return "\\xAF";
         7795  +  case 176:
         7796  +    return "\\xB0";
         7797  +  case 177:
         7798  +    return "\\xB1";
         7799  +  case 178:
         7800  +    return "\\xB2";
         7801  +  case 179:
         7802  +    return "\\xB3";
         7803  +  case 180:
         7804  +    return "\\xB4";
         7805  +  case 181:
         7806  +    return "\\xB5";
         7807  +  case 182:
         7808  +    return "\\xB6";
         7809  +  case 183:
         7810  +    return "\\xB7";
         7811  +  case 184:
         7812  +    return "\\xB8";
         7813  +  case 185:
         7814  +    return "\\xB9";
         7815  +  case 186:
         7816  +    return "\\xBA";
         7817  +  case 187:
         7818  +    return "\\xBB";
         7819  +  case 188:
         7820  +    return "\\xBC";
         7821  +  case 189:
         7822  +    return "\\xBD";
         7823  +  case 190:
         7824  +    return "\\xBE";
         7825  +  case 191:
         7826  +    return "\\xBF";
         7827  +  case 192:
         7828  +    return "\\xC0";
         7829  +  case 193:
         7830  +    return "\\xC1";
         7831  +  case 194:
         7832  +    return "\\xC2";
         7833  +  case 195:
         7834  +    return "\\xC3";
         7835  +  case 196:
         7836  +    return "\\xC4";
         7837  +  case 197:
         7838  +    return "\\xC5";
         7839  +  case 198:
         7840  +    return "\\xC6";
         7841  +  case 199:
         7842  +    return "\\xC7";
         7843  +  case 200:
         7844  +    return "\\xC8";
         7845  +  case 201:
         7846  +    return "\\xC9";
         7847  +  case 202:
         7848  +    return "\\xCA";
         7849  +  case 203:
         7850  +    return "\\xCB";
         7851  +  case 204:
         7852  +    return "\\xCC";
         7853  +  case 205:
         7854  +    return "\\xCD";
         7855  +  case 206:
         7856  +    return "\\xCE";
         7857  +  case 207:
         7858  +    return "\\xCF";
         7859  +  case 208:
         7860  +    return "\\xD0";
         7861  +  case 209:
         7862  +    return "\\xD1";
         7863  +  case 210:
         7864  +    return "\\xD2";
         7865  +  case 211:
         7866  +    return "\\xD3";
         7867  +  case 212:
         7868  +    return "\\xD4";
         7869  +  case 213:
         7870  +    return "\\xD5";
         7871  +  case 214:
         7872  +    return "\\xD6";
         7873  +  case 215:
         7874  +    return "\\xD7";
         7875  +  case 216:
         7876  +    return "\\xD8";
         7877  +  case 217:
         7878  +    return "\\xD9";
         7879  +  case 218:
         7880  +    return "\\xDA";
         7881  +  case 219:
         7882  +    return "\\xDB";
         7883  +  case 220:
         7884  +    return "\\xDC";
         7885  +  case 221:
         7886  +    return "\\xDD";
         7887  +  case 222:
         7888  +    return "\\xDE";
         7889  +  case 223:
         7890  +    return "\\xDF";
         7891  +  case 224:
         7892  +    return "\\xE0";
         7893  +  case 225:
         7894  +    return "\\xE1";
         7895  +  case 226:
         7896  +    return "\\xE2";
         7897  +  case 227:
         7898  +    return "\\xE3";
         7899  +  case 228:
         7900  +    return "\\xE4";
         7901  +  case 229:
         7902  +    return "\\xE5";
         7903  +  case 230:
         7904  +    return "\\xE6";
         7905  +  case 231:
         7906  +    return "\\xE7";
         7907  +  case 232:
         7908  +    return "\\xE8";
         7909  +  case 233:
         7910  +    return "\\xE9";
         7911  +  case 234:
         7912  +    return "\\xEA";
         7913  +  case 235:
         7914  +    return "\\xEB";
         7915  +  case 236:
         7916  +    return "\\xEC";
         7917  +  case 237:
         7918  +    return "\\xED";
         7919  +  case 238:
         7920  +    return "\\xEE";
         7921  +  case 239:
         7922  +    return "\\xEF";
         7923  +  case 240:
         7924  +    return "\\xF0";
         7925  +  case 241:
         7926  +    return "\\xF1";
         7927  +  case 242:
         7928  +    return "\\xF2";
         7929  +  case 243:
         7930  +    return "\\xF3";
         7931  +  case 244:
         7932  +    return "\\xF4";
         7933  +  case 245:
         7934  +    return "\\xF5";
         7935  +  case 246:
         7936  +    return "\\xF6";
         7937  +  case 247:
         7938  +    return "\\xF7";
         7939  +  case 248:
         7940  +    return "\\xF8";
         7941  +  case 249:
         7942  +    return "\\xF9";
         7943  +  case 250:
         7944  +    return "\\xFA";
         7945  +  case 251:
         7946  +    return "\\xFB";
         7947  +  case 252:
         7948  +    return "\\xFC";
         7949  +  case 253:
         7950  +    return "\\xFD";
         7951  +  case 254:
         7952  +    return "\\xFE";
         7953  +  case 255:
         7954  +    return "\\xFF";
         7955  +  default:
         7956  +    assert(0); /* never gets here */
         7957  +    return "dead code";
         7958  +  }
         7959  +  assert(0); /* never gets here */
         7960  +}
         7961  +
         7962  +#endif /* XML_DTD */
         7963  +
         7964  +static unsigned long
         7965  +getDebugLevel(const char *variableName, unsigned long defaultDebugLevel) {
         7966  +  const char *const valueOrNull = getenv(variableName);
         7967  +  if (valueOrNull == NULL) {
         7968  +    return defaultDebugLevel;
         7969  +  }
         7970  +  const char *const value = valueOrNull;
         7971  +
         7972  +  errno = 0;
         7973  +  char *afterValue = (char *)value;
         7974  +  unsigned long debugLevel = strtoul(value, &afterValue, 10);
         7975  +  if ((errno != 0) || (afterValue[0] != '\0')) {
         7976  +    errno = 0;
         7977  +    return defaultDebugLevel;
         7978  +  }
         7979  +
         7980  +  return debugLevel;
         7981  +}

Changes to expat/xmlrole.c.

     3      3                            ___\ \/ /_ __   __ _| |_
     4      4                           / _ \\  /| '_ \ / _` | __|
     5      5                          |  __//  \| |_) | (_| | |_
     6      6                           \___/_/\_\ .__/ \__,_|\__|
     7      7                                    |_| XML parser
     8      8   
     9      9      Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
    10         -   Copyright (c) 2000-2017 Expat development team
           10  +   Copyright (c) 2000      Clark Cooper <coopercc@users.sourceforge.net>
           11  +   Copyright (c) 2002      Greg Stein <gstein@users.sourceforge.net>
           12  +   Copyright (c) 2002-2006 Karl Waclawek <karl@waclawek.net>
           13  +   Copyright (c) 2002-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
           14  +   Copyright (c) 2005-2009 Steven Solie <ssolie@users.sourceforge.net>
           15  +   Copyright (c) 2016-2021 Sebastian Pipping <sebastian@pipping.org>
           16  +   Copyright (c) 2017      Rhodri James <rhodri@wildebeest.org.uk>
           17  +   Copyright (c) 2019      David Loffredo <loffredo@steptools.com>
           18  +   Copyright (c) 2021      Dong-hee Na <donghee.na@python.org>
    11     19      Licensed under the MIT license:
    12     20   
    13     21      Permission is  hereby granted,  free of charge,  to any  person obtaining
    14     22      a  copy  of  this  software   and  associated  documentation  files  (the
    15     23      "Software"),  to  deal in  the  Software  without restriction,  including
    16     24      without  limitation the  rights  to use,  copy,  modify, merge,  publish,
    17     25      distribute, sublicense, and/or sell copies of the Software, and to permit
................................................................................
    26     34      MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
    27     35      NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
    28     36      DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
    29     37      OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
    30     38      USE OR OTHER DEALINGS IN THE SOFTWARE.
    31     39   */
    32     40   
           41  +#include <expat_config.h>
           42  +
    33     43   #include <stddef.h>
    34     44   
    35     45   #ifdef _WIN32
    36     46   #  include "winconfig.h"
    37         -#else
    38         -#  ifdef HAVE_EXPAT_CONFIG_H
    39         -#    include <expat_config.h>
    40         -#  endif
    41         -#endif /* ndef _WIN32 */
           47  +#endif
    42     48   
    43     49   #include "expat_external.h"
    44     50   #include "internal.h"
    45     51   #include "xmlrole.h"
    46     52   #include "ascii.h"
    47     53   
    48     54   /* Doesn't check:

Changes to expat/xmlrole.h.

     3      3                            ___\ \/ /_ __   __ _| |_
     4      4                           / _ \\  /| '_ \ / _` | __|
     5      5                          |  __//  \| |_) | (_| | |_
     6      6                           \___/_/\_\ .__/ \__,_|\__|
     7      7                                    |_| XML parser
     8      8   
     9      9      Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
    10         -   Copyright (c) 2000-2017 Expat development team
           10  +   Copyright (c) 2000      Clark Cooper <coopercc@users.sourceforge.net>
           11  +   Copyright (c) 2002      Karl Waclawek <karl@waclawek.net>
           12  +   Copyright (c) 2002      Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
           13  +   Copyright (c) 2017      Sebastian Pipping <sebastian@pipping.org>
    11     14      Licensed under the MIT license:
    12     15   
    13     16      Permission is  hereby granted,  free of charge,  to any  person obtaining
    14     17      a  copy  of  this  software   and  associated  documentation  files  (the
    15     18      "Software"),  to  deal in  the  Software  without restriction,  including
    16     19      without  limitation the  rights  to use,  copy,  modify, merge,  publish,
    17     20      distribute, sublicense, and/or sell copies of the Software, and to permit

Changes to expat/xmltok.c.

     3      3                            ___\ \/ /_ __   __ _| |_
     4      4                           / _ \\  /| '_ \ / _` | __|
     5      5                          |  __//  \| |_) | (_| | |_
     6      6                           \___/_/\_\ .__/ \__,_|\__|
     7      7                                    |_| XML parser
     8      8   
     9      9      Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
    10         -   Copyright (c) 2000-2017 Expat development team
           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 <ssolie@users.sourceforge.net>
           15  +   Copyright (c) 2016-2021 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      Dong-hee Na <donghee.na@python.org>
    11     24      Licensed under the MIT license:
    12     25   
    13     26      Permission is  hereby granted,  free of charge,  to any  person obtaining
    14     27      a  copy  of  this  software   and  associated  documentation  files  (the
    15     28      "Software"),  to  deal in  the  Software  without restriction,  including
    16     29      without  limitation the  rights  to use,  copy,  modify, merge,  publish,
    17     30      distribute, sublicense, and/or sell copies of the Software, and to permit
................................................................................
    26     39      MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
    27     40      NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
    28     41      DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
    29     42      OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
    30     43      USE OR OTHER DEALINGS IN THE SOFTWARE.
    31     44   */
    32     45   
           46  +#include <expat_config.h>
           47  +
    33     48   #include <stddef.h>
    34     49   #include <string.h> /* memcpy */
    35     50   #include <stdbool.h>
    36     51   
    37     52   #ifdef _WIN32
    38     53   #  include "winconfig.h"
    39         -#else
    40         -#  ifdef HAVE_EXPAT_CONFIG_H
    41         -#    include <expat_config.h>
    42         -#  endif
    43         -#endif /* ndef _WIN32 */
           54  +#endif
    44     55   
    45     56   #include "expat_external.h"
    46     57   #include "internal.h"
    47     58   #include "xmltok.h"
    48     59   #include "nametab.h"
    49     60   
    50     61   #ifdef XML_DTD
................................................................................
   257    268   }
   258    269   #else
   259    270   #  define BYTE_TO_ASCII(enc, p) (*(p))
   260    271   #endif
   261    272   
   262    273   #define IS_NAME_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isName##n(enc, p))
   263    274   #define IS_NMSTRT_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isNmstrt##n(enc, p))
   264         -#define IS_INVALID_CHAR(enc, p, n)                                             \
   265         -  (AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p))
          275  +#ifdef XML_MIN_SIZE
          276  +#  define IS_INVALID_CHAR(enc, p, n)                                           \
          277  +    (AS_NORMAL_ENCODING(enc)->isInvalid##n                                     \
          278  +     && AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p))
          279  +#else
          280  +#  define IS_INVALID_CHAR(enc, p, n)                                           \
          281  +    (AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p))
          282  +#endif
   266    283   
   267    284   #ifdef XML_MIN_SIZE
   268    285   #  define IS_NAME_CHAR_MINBPC(enc, p)                                          \
   269    286       (AS_NORMAL_ENCODING(enc)->isNameMin(enc, p))
   270    287   #  define IS_NMSTRT_CHAR_MINBPC(enc, p)                                        \
   271    288       (AS_NORMAL_ENCODING(enc)->isNmstrtMin(enc, p))
   272    289   #else

Changes to expat/xmltok.h.

     3      3                            ___\ \/ /_ __   __ _| |_
     4      4                           / _ \\  /| '_ \ / _` | __|
     5      5                          |  __//  \| |_) | (_| | |_
     6      6                           \___/_/\_\ .__/ \__,_|\__|
     7      7                                    |_| XML parser
     8      8   
     9      9      Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
    10         -   Copyright (c) 2000-2017 Expat development team
           10  +   Copyright (c) 2000      Clark Cooper <coopercc@users.sourceforge.net>
           11  +   Copyright (c) 2002      Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
           12  +   Copyright (c) 2002-2005 Karl Waclawek <karl@waclawek.net>
           13  +   Copyright (c) 2016-2017 Sebastian Pipping <sebastian@pipping.org>
           14  +   Copyright (c) 2017      Rhodri James <rhodri@wildebeest.org.uk>
    11     15      Licensed under the MIT license:
    12     16   
    13     17      Permission is  hereby granted,  free of charge,  to any  person obtaining
    14     18      a  copy  of  this  software   and  associated  documentation  files  (the
    15     19      "Software"),  to  deal in  the  Software  without restriction,  including
    16     20      without  limitation the  rights  to use,  copy,  modify, merge,  publish,
    17     21      distribute, sublicense, and/or sell copies of the Software, and to permit

Changes to expat/xmltok_impl.c.

     1         -/* This file is included!
            1  +/* This file is included (from xmltok.c, 1-3 times depending on XML_MIN_SIZE)!
     2      2                               __  __            _
     3      3                            ___\ \/ /_ __   __ _| |_
     4      4                           / _ \\  /| '_ \ / _` | __|
     5      5                          |  __//  \| |_) | (_| | |_
     6      6                           \___/_/\_\ .__/ \__,_|\__|
     7      7                                    |_| XML parser
     8      8   
     9      9      Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
    10         -   Copyright (c) 2000-2017 Expat development team
           10  +   Copyright (c) 2000      Clark Cooper <coopercc@users.sourceforge.net>
           11  +   Copyright (c) 2002      Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
           12  +   Copyright (c) 2002-2016 Karl Waclawek <karl@waclawek.net>
           13  +   Copyright (c) 2016-2021 Sebastian Pipping <sebastian@pipping.org>
           14  +   Copyright (c) 2017      Rhodri James <rhodri@wildebeest.org.uk>
           15  +   Copyright (c) 2018      Benjamin Peterson <benjamin@python.org>
           16  +   Copyright (c) 2018      Anton Maklakov <antmak.pub@gmail.com>
           17  +   Copyright (c) 2019      David Loffredo <loffredo@steptools.com>
           18  +   Copyright (c) 2020      Boris Kolpackov <boris@codesynthesis.com>
    11     19      Licensed under the MIT license:
    12     20   
    13     21      Permission is  hereby granted,  free of charge,  to any  person obtaining
    14     22      a  copy  of  this  software   and  associated  documentation  files  (the
    15     23      "Software"),  to  deal in  the  Software  without restriction,  including
    16     24      without  limitation the  rights  to use,  copy,  modify, merge,  publish,
    17     25      distribute, sublicense, and/or sell copies of the Software, and to permit
................................................................................
    28     36      DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
    29     37      OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
    30     38      USE OR OTHER DEALINGS IN THE SOFTWARE.
    31     39   */
    32     40   
    33     41   #ifdef XML_TOK_IMPL_C
    34     42   
    35         -#  ifndef IS_INVALID_CHAR
           43  +#  ifndef IS_INVALID_CHAR // i.e. for UTF-16 and XML_MIN_SIZE not defined
    36     44   #    define IS_INVALID_CHAR(enc, ptr, n) (0)
    37     45   #  endif
    38     46   
    39     47   #  define INVALID_LEAD_CASE(n, ptr, nextTokPtr)                                \
    40     48     case BT_LEAD##n:                                                             \
    41     49       if (end - ptr < n)                                                         \
    42     50         return XML_TOK_PARTIAL_CHAR;                                             \

Changes to expat/xmltok_impl.h.

     3      3                            ___\ \/ /_ __   __ _| |_
     4      4                           / _ \\  /| '_ \ / _` | __|
     5      5                          |  __//  \| |_) | (_| | |_
     6      6                           \___/_/\_\ .__/ \__,_|\__|
     7      7                                    |_| XML parser
     8      8   
     9      9      Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
    10         -   Copyright (c) 2000-2017 Expat development team
           10  +   Copyright (c) 2000      Clark Cooper <coopercc@users.sourceforge.net>
           11  +   Copyright (c) 2017-2019 Sebastian Pipping <sebastian@pipping.org>
    11     12      Licensed under the MIT license:
    12     13   
    13     14      Permission is  hereby granted,  free of charge,  to any  person obtaining
    14     15      a  copy  of  this  software   and  associated  documentation  files  (the
    15     16      "Software"),  to  deal in  the  Software  without restriction,  including
    16     17      without  limitation the  rights  to use,  copy,  modify, merge,  publish,
    17     18      distribute, sublicense, and/or sell copies of the Software, and to permit

Changes to expat/xmltok_ns.c.

     3      3                            ___\ \/ /_ __   __ _| |_
     4      4                           / _ \\  /| '_ \ / _` | __|
     5      5                          |  __//  \| |_) | (_| | |_
     6      6                           \___/_/\_\ .__/ \__,_|\__|
     7      7                                    |_| XML parser
     8      8   
     9      9      Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
    10         -   Copyright (c) 2000-2017 Expat development team
           10  +   Copyright (c) 2000      Clark Cooper <coopercc@users.sourceforge.net>
           11  +   Copyright (c) 2002      Greg Stein <gstein@users.sourceforge.net>
           12  +   Copyright (c) 2002      Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
           13  +   Copyright (c) 2002-2006 Karl Waclawek <karl@waclawek.net>
           14  +   Copyright (c) 2017      Sebastian Pipping <sebastian@pipping.org>
    11     15      Licensed under the MIT license:
    12     16   
    13     17      Permission is  hereby granted,  free of charge,  to any  person obtaining
    14     18      a  copy  of  this  software   and  associated  documentation  files  (the
    15     19      "Software"),  to  deal in  the  Software  without restriction,  including
    16     20      without  limitation the  rights  to use,  copy,  modify, merge,  publish,
    17     21      distribute, sublicense, and/or sell copies of the Software, and to permit

Changes to generic/tcldom.c.

   166    166   #define SERIALIZE_INDENT_ATTR_WITH_TAB 512
   167    167   
   168    168   /*----------------------------------------------------------------------------
   169    169   |   Module Globals
   170    170   |
   171    171   \---------------------------------------------------------------------------*/
   172    172   #ifndef TCL_THREADS
   173         -    static int        storeLineColumn       = 0;
   174         -    static int        dontCreateObjCommands = 0;
   175         -    static int        dontCheckCharData     = 0;
   176         -    static int        dontCheckName         = 0;
   177         -    static int        domCreateCmdMode      = 0;
          173  +    static int         storeLineColumn       = 0;
          174  +    static int         dontCreateObjCommands = 0;
          175  +    static int         dontCheckCharData     = 0;
          176  +    static int         dontCheckName         = 0;
          177  +    static int         domCreateCmdMode      = 0; 
          178  +    /* BLAP stands for BillionLaughsAttackProtection */
          179  +    static float       BLAPMaximumAmplification;
          180  +    unsigned long long BLAPActivationThreshold;
   178    181   #   define TSD(x)     x
   179    182   #   define GetTcldomTSD()
   180    183   #else
   181    184       typedef struct ThreadSpecificData {
   182    185           int        storeLineColumn;
   183    186           int        dontCreateObjCommands;
   184    187           int        dontCheckCharData;
   185    188           int        dontCheckName;
   186    189           int        domCreateCmdMode;
          190  +        float      BLAPMaximumAmplification;
          191  +        unsigned long long BLAPActivationThreshold;
   187    192       } ThreadSpecificData;
   188    193       static Tcl_ThreadDataKey dataKey;
   189    194       static Tcl_HashTable     sharedDocs;
   190    195       static Tcl_Mutex         tableMutex;
   191    196       static int               tcldomInitialized;
   192    197   #   define TSD(x)            tsdPtr->x
   193    198   #   define GetTcldomTSD()  ThreadSpecificData *tsdPtr = \