diff --git a/.github/workflows/data/expat_config_h_cmake__expected.txt b/.github/workflows/data/expat_config_h_cmake__expected.txt index ea291955a..9e8910b0b 100644 --- a/.github/workflows/data/expat_config_h_cmake__expected.txt +++ b/.github/workflows/data/expat_config_h_cmake__expected.txt @@ -34,4 +34,5 @@ XML_ATTR_INFO XML_CONTEXT_BYTES XML_DEV_URANDOM XML_DTD +XML_GE XML_NS diff --git a/.github/workflows/data/expat_config_h_in__expected.txt b/.github/workflows/data/expat_config_h_in__expected.txt index 796d447d2..f89b54f51 100644 --- a/.github/workflows/data/expat_config_h_in__expected.txt +++ b/.github/workflows/data/expat_config_h_in__expected.txt @@ -39,4 +39,5 @@ XML_ATTR_INFO XML_CONTEXT_BYTES XML_DEV_URANDOM XML_DTD +XML_GE XML_NS diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 784f7d3f1..3cc2b02b3 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -58,7 +58,9 @@ jobs: - MODE: qa-sh FLAT_ENV: CC=clang CXX=clang++ LD=clang++ QA_SANITIZER=address CMAKE_ARGS=-DEXPAT_CONTEXT_BYTES=0 - MODE: qa-sh - FLAT_ENV: CC=clang CXX=clang++ LD=clang++ QA_SANITIZER=address CMAKE_ARGS=-DEXPAT_DTD=OFF + FLAT_ENV: CC=clang CXX=clang++ LD=clang++ QA_SANITIZER=address CMAKE_ARGS="-DEXPAT_DTD=OFF -DEXPAT_GE=ON" + - MODE: qa-sh + FLAT_ENV: CC=clang CXX=clang++ LD=clang++ QA_SANITIZER=address CMAKE_ARGS="-DEXPAT_DTD=OFF -DEXPAT_GE=OFF" - MODE: qa-sh FLAT_ENV: CC=clang CXX=clang++ LD=clang++ QA_SANITIZER=address CMAKE_ARGS=-DEXPAT_LARGE_SIZE=ON - MODE: qa-sh diff --git a/expat/CMakeLists.txt b/expat/CMakeLists.txt index 325a4a729..5f59da717 100644 --- a/expat/CMakeLists.txt +++ b/expat/CMakeLists.txt @@ -143,6 +143,8 @@ expat_shy_set(EXPAT_CONTEXT_BYTES 1024 CACHE STRING "Define to specify how much mark_as_advanced(EXPAT_CONTEXT_BYTES) expat_shy_set(EXPAT_DTD ON CACHE BOOL "Define to make parameter entity parsing functionality available") mark_as_advanced(EXPAT_DTD) +expat_shy_set(EXPAT_GE ON CACHE BOOL "Define to make general entity parsing functionality available") +mark_as_advanced(EXPAT_GE) expat_shy_set(EXPAT_NS ON CACHE BOOL "Define to make XML Namespaces functionality available") mark_as_advanced(EXPAT_NS) expat_shy_set(EXPAT_WARNINGS_AS_ERRORS OFF CACHE BOOL "Treat all compiler warnings as errors") @@ -179,6 +181,11 @@ endif() # # Environment checks # +if(EXPAT_DTD AND NOT EXPAT_GE) + message(SEND_ERROR "Option EXPAT_DTD requires that EXPAT_GE is also enabled.") + message(SEND_ERROR "Please either enable option EXPAT_GE (recommended) or disable EXPAT_DTD also.") +endif() + if(EXPAT_WITH_LIBBSD) find_library(LIB_BSD NAMES bsd) if(NOT LIB_BSD) @@ -281,6 +288,7 @@ endif() _expat_copy_bool_int(EXPAT_ATTR_INFO XML_ATTR_INFO) _expat_copy_bool_int(EXPAT_DTD XML_DTD) +_expat_copy_bool_int(EXPAT_GE XML_GE) _expat_copy_bool_int(EXPAT_LARGE_SIZE XML_LARGE_SIZE) _expat_copy_bool_int(EXPAT_MIN_SIZE XML_MIN_SIZE) _expat_copy_bool_int(EXPAT_NS XML_NS) @@ -395,7 +403,13 @@ if(EXPAT_SHARED_LIBS) endif() endmacro() - _expat_def_file_toggle(EXPAT_DTD _EXPAT_COMMENT_DTD) + if(EXPAT_DTD OR EXPAT_GE) + set(_EXPAT_DTD_OR_GE TRUE) + else() + set(_EXPAT_DTD_OR_GE FALSE) + endif() + + _expat_def_file_toggle(_EXPAT_DTD_OR_GE _EXPAT_COMMENT_DTD_OR_GE) _expat_def_file_toggle(EXPAT_ATTR_INFO _EXPAT_COMMENT_ATTR_INFO) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/lib/libexpat.def.cmake" "${CMAKE_CURRENT_BINARY_DIR}/lib/libexpat.def") @@ -932,6 +946,7 @@ message(STATUS " // Advanced options, changes not advised") message(STATUS " Attributes info .......... ${EXPAT_ATTR_INFO}") message(STATUS " Context bytes ............ ${EXPAT_CONTEXT_BYTES}") message(STATUS " DTD support .............. ${EXPAT_DTD}") +message(STATUS " General entities ......... ${EXPAT_GE}") message(STATUS " Large size ............... ${EXPAT_LARGE_SIZE}") message(STATUS " Minimum size ............. ${EXPAT_MIN_SIZE}") message(STATUS " Namespace support ........ ${EXPAT_NS}") diff --git a/expat/configure.ac b/expat/configure.ac index c9f95bca7..fec4ecd0b 100644 --- a/expat/configure.ac +++ b/expat/configure.ac @@ -303,6 +303,8 @@ AC_SUBST(FILEMAP) dnl Some basic configuration: AC_DEFINE([XML_NS], 1, [Define to make XML Namespaces functionality available.]) +AC_DEFINE([XML_GE], 1, + [Define as 1/0 to enable/disable support for general entities.]) AC_DEFINE([XML_DTD], 1, [Define to make parameter entity parsing functionality available.]) AC_DEFINE([XML_DEV_URANDOM], 1, diff --git a/expat/coverage.sh b/expat/coverage.sh index 9b64d126a..78282358d 100755 --- a/expat/coverage.sh +++ b/expat/coverage.sh @@ -68,7 +68,17 @@ _get_build_dir() { m32_part=__m32 fi - echo "build__${version}__xml_context_${xml_context}${libbsd_part}${mingw_part}${char_part}${xml_attr_part}${m32_part}" + local ge_part= + if ${with_ge}; then + ge_part=__ge + fi + + local dtd_part= + if ${with_dtd}; then + dtd_part=__dtd + fi + + echo "build__${version}__xml_context_${xml_context}${libbsd_part}${mingw_part}${char_part}${ge_part}${dtd_part}${xml_attr_part}${m32_part}" } @@ -95,6 +105,8 @@ _call_cmake() { ${with_libbsd} && cmake_args+=( -DEXPAT_WITH_LIBBSD=ON ) ${with_mingw} && cmake_args+=( -DCMAKE_TOOLCHAIN_FILE="${abs_source_dir}"/cmake/mingw-toolchain.cmake ) ${with_m32} && cmake_args+=( -D_EXPAT_M32=ON ) + ${with_ge} || cmake_args+=( -DEXPAT_GE=OFF ) + ${with_dtd} || cmake_args+=( -DEXPAT_DTD=OFF ) ( set -x @@ -184,7 +196,10 @@ _run() { fi set -x - make CTEST_OUTPUT_ON_FAILURE=1 test run-xmltest + make CTEST_OUTPUT_ON_FAILURE=1 test + if ${with_dtd}; then + make run-xmltest + fi lcov -c -d "${capture_dir}" -o "${coverage_info}-test" &>> run.log lcov \ @@ -291,6 +306,8 @@ _main() { with_unsigned_char=false with_libbsd=false with_m32=false + with_dtd=true + with_ge=true for with_mingw in true false ; do for unicode_enabled in true false ; do if ${unicode_enabled} && ! ${with_mingw} ; then @@ -309,6 +326,8 @@ _main() { with_libbsd=true _build_case with_unsigned_char=true _build_case with_m32=true _build_case + with_dtd=false with_ge=true _build_case + with_dtd=false with_ge=false _build_case echo echo 'Merging coverage files...' diff --git a/expat/doc/reference.html b/expat/doc/reference.html index 8007f2533..2c943a581 100644 --- a/expat/doc/reference.html +++ b/expat/doc/reference.html @@ -360,13 +360,40 @@
XML_UNICODE_WCHAR_T. The symbols are:
&e1; to reference and
+syntax <!ENTITY e1 'value1'> (an internal general entity) or
+<!ENTITY e2 SYSTEM 'file2'> (an external general entity) to declare).
+With XML_GE enabled, general entities will be replaced by their declared replacement text;
+for this to work for external general entities, in addition an
+XML_ExternalEntityRefHandler must be set using
+XML_SetExternalEntityRefHandler.
+Also, enabling XML_GE makes
+the functions
+XML_SetBillionLaughsAttackProtectionMaximumAmplification and
+
+XML_SetBillionLaughsAttackProtectionActivationThreshold available.
+XML_GE disabled, Expat has a smaller memory footprint and can be faster, but will
+not load external general entities and will replace all general entities
+(except the predefined five:
+amp, apos, gt, lt, quot)
+with a self-reference:
+for example, referencing an entity e1 via &e1; will be replaced
+by text &e1;.
+
XML_SetBillionLaughsAttackProtectionMaximumAmplification and
diff --git a/expat/expat_config.h.cmake b/expat/expat_config.h.cmake
index a290fafb6..ceb9b4ecb 100644
--- a/expat/expat_config.h.cmake
+++ b/expat/expat_config.h.cmake
@@ -105,6 +105,9 @@
/* Define to make parameter entity parsing functionality available. */
#cmakedefine XML_DTD
+/* Define as 1/0 to enable/disable support for general entities. */
+#define XML_GE @XML_GE@
+
/* Define to make XML Namespaces functionality available. */
#cmakedefine XML_NS
diff --git a/expat/lib/expat.h b/expat/lib/expat.h
index f5f2025e0..4ea924396 100644
--- a/expat/lib/expat.h
+++ b/expat/lib/expat.h
@@ -1025,7 +1025,9 @@ enum XML_FeatureEnum {
XML_FEATURE_ATTR_INFO,
/* Added in Expat 2.4.0. */
XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT,
- XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT
+ XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT,
+ /* Added in Expat 2.6.0. */
+ XML_FEATURE_GE
/* Additional features must be added to the end of this enum. */
};
@@ -1038,13 +1040,15 @@ typedef struct {
XMLPARSEAPI(const XML_Feature *)
XML_GetFeatureList(void);
-#ifdef XML_DTD
-/* Added in Expat 2.4.0. */
+#if XML_GE == 1
+/* Added in Expat 2.4.0 for XML_DTD defined and
+ * added in Expat 2.6.0 for XML_GE == 1. */
XMLPARSEAPI(XML_Bool)
XML_SetBillionLaughsAttackProtectionMaximumAmplification(
XML_Parser parser, float maximumAmplificationFactor);
-/* Added in Expat 2.4.0. */
+/* Added in Expat 2.4.0 for XML_DTD defined and
+ * added in Expat 2.6.0 for XML_GE == 1. */
XMLPARSEAPI(XML_Bool)
XML_SetBillionLaughsAttackProtectionActivationThreshold(
XML_Parser parser, unsigned long long activationThresholdBytes);
diff --git a/expat/lib/internal.h b/expat/lib/internal.h
index e09f533b2..03c8fdec0 100644
--- a/expat/lib/internal.h
+++ b/expat/lib/internal.h
@@ -154,7 +154,7 @@ extern "C" {
void _INTERNAL_trim_to_complete_utf8_characters(const char *from,
const char **fromLimRef);
-#if defined(XML_DTD)
+#if XML_GE == 1
unsigned long long testingAccountingGetCountBytesDirect(XML_Parser parser);
unsigned long long testingAccountingGetCountBytesIndirect(XML_Parser parser);
const char *unsignedCharToPrintable(unsigned char c);
diff --git a/expat/lib/libexpat.def.cmake b/expat/lib/libexpat.def.cmake
index cf434a229..61a4f0062 100644
--- a/expat/lib/libexpat.def.cmake
+++ b/expat/lib/libexpat.def.cmake
@@ -75,5 +75,5 @@ EXPORTS
XML_SetHashSalt @67
; internal @68 removed with version 2.3.1
; added with version 2.4.0
-@_EXPAT_COMMENT_DTD@ XML_SetBillionLaughsAttackProtectionActivationThreshold @69
-@_EXPAT_COMMENT_DTD@ XML_SetBillionLaughsAttackProtectionMaximumAmplification @70
+@_EXPAT_COMMENT_DTD_OR_GE@ XML_SetBillionLaughsAttackProtectionActivationThreshold @69
+@_EXPAT_COMMENT_DTD_OR_GE@ XML_SetBillionLaughsAttackProtectionMaximumAmplification @70
diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
index 3650b6d61..80b3a0912 100644
--- a/expat/lib/xmlparse.c
+++ b/expat/lib/xmlparse.c
@@ -63,6 +63,14 @@
#include "expat_config.h"
+#if ! defined(XML_GE) || (1 - XML_GE - 1 == 2) || (XML_GE < 0) || (XML_GE > 1)
+# error XML_GE (for general entities) must be defined, non-empty, either 1 or 0 (0 to disable, 1 to enable; 1 is a common default)
+#endif
+
+#if defined(XML_DTD) && XML_GE == 0
+# error Either undefine XML_DTD or define XML_GE to 1.
+#endif
+
#if ! defined(XML_CONTEXT_BYTES) || (1 - XML_CONTEXT_BYTES - 1 == 2) \
|| (XML_CONTEXT_BYTES + 0 < 0)
# error XML_CONTEXT_BYTES must be defined, non-empty and >=0 (0 to disable, >=1 to enable; 1024 is a common default)
@@ -416,7 +424,7 @@ enum XML_Account {
XML_ACCOUNT_NONE /* i.e. do not account, was accounted already */
};
-#ifdef XML_DTD
+#if XML_GE == 1
typedef unsigned long long XmlBigCount;
typedef struct accounting {
XmlBigCount countBytesDirect;
@@ -432,7 +440,7 @@ typedef struct entity_stats {
unsigned int maximumDepthSeen;
unsigned long debugLevel;
} ENTITY_STATS;
-#endif /* XML_DTD */
+#endif /* XML_GE == 1 */
typedef enum XML_Error PTRCALL Processor(XML_Parser parser, const char *start,
const char *end, const char **endPtr);
@@ -504,9 +512,13 @@ static enum XML_Error appendAttributeValue(XML_Parser parser, const ENCODING *,
static ATTRIBUTE_ID *getAttributeId(XML_Parser parser, const ENCODING *enc,
const char *start, const char *end);
static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
+#if XML_GE == 1
static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc,
const char *start, const char *end,
enum XML_Account account);
+#else
+static enum XML_Error storeSelfEntityValue(XML_Parser parser, ENTITY *entity);
+#endif
static int reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
const char *start, const char *end);
static int reportComment(XML_Parser parser, const ENCODING *enc,
@@ -570,7 +582,7 @@ static XML_Parser parserCreate(const XML_Char *encodingName,
static void parserInit(XML_Parser parser, const XML_Char *encodingName);
-#ifdef XML_DTD
+#if XML_GE == 1
static float accountingGetCurrentAmplification(XML_Parser rootParser);
static void accountingReportStats(XML_Parser originParser, const char *epilog);
static void accountingOnAbort(XML_Parser originParser);
@@ -593,7 +605,7 @@ static void entityTrackingOnClose(XML_Parser parser, ENTITY *entity,
static XML_Parser getRootParserOf(XML_Parser parser,
unsigned int *outLevelDiff);
-#endif /* XML_DTD */
+#endif /* XML_GE == 1 */
static unsigned long getDebugLevel(const char *variableName,
unsigned long defaultDebugLevel);
@@ -718,7 +730,7 @@ struct XML_ParserStruct {
enum XML_ParamEntityParsing m_paramEntityParsing;
#endif
unsigned long m_hash_secret_salt;
-#ifdef XML_DTD
+#if XML_GE == 1
ACCOUNTING m_accounting;
ENTITY_STATS m_entity_stats;
#endif
@@ -1178,7 +1190,7 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) {
#endif
parser->m_hash_secret_salt = 0;
-#ifdef XML_DTD
+#if XML_GE == 1
memset(&parser->m_accounting, 0, sizeof(ACCOUNTING));
parser->m_accounting.debugLevel = getDebugLevel("EXPAT_ACCOUNTING_DEBUG", 0u);
parser->m_accounting.maximumAmplificationFactor
@@ -2534,8 +2546,9 @@ XML_GetFeatureList(void) {
#ifdef XML_ATTR_INFO
{XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
#endif
-#ifdef XML_DTD
- /* Added in Expat 2.4.0. */
+#if XML_GE == 1
+ /* Added in Expat 2.4.0 for XML_DTD defined and
+ * added in Expat 2.6.0 for XML_GE == 1. */
{XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT,
XML_L("XML_BLAP_MAX_AMP"),
(long int)
@@ -2543,6 +2556,8 @@ XML_GetFeatureList(void) {
{XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT,
XML_L("XML_BLAP_ACT_THRES"),
EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT},
+ /* Added in Expat 2.6.0. */
+ {XML_FEATURE_GE, XML_L("XML_GE"), 0},
#endif
{XML_FEATURE_END, NULL, 0}
};
@@ -2550,7 +2565,7 @@ XML_GetFeatureList(void) {
return features;
}
-#ifdef XML_DTD
+#if XML_GE == 1
XML_Bool XMLCALL
XML_SetBillionLaughsAttackProtectionMaximumAmplification(
XML_Parser parser, float maximumAmplificationFactor) {
@@ -2572,7 +2587,7 @@ XML_SetBillionLaughsAttackProtectionActivationThreshold(
parser->m_accounting.activationThresholdBytes = activationThresholdBytes;
return XML_TRUE;
}
-#endif /* XML_DTD */
+#endif /* XML_GE == 1 */
/* Initially tag->rawName always points into the parse buffer;
for those TAG instances opened while the current parse buffer was
@@ -2658,13 +2673,13 @@ externalEntityInitProcessor2(XML_Parser parser, const char *start,
int tok = XmlContentTok(parser->m_encoding, start, end, &next);
switch (tok) {
case XML_TOK_BOM:
-#ifdef XML_DTD
+#if XML_GE == 1
if (! accountingDiffTolerated(parser, tok, start, next, __LINE__,
XML_ACCOUNT_DIRECT)) {
accountingOnAbort(parser);
return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
}
-#endif /* XML_DTD */
+#endif /* XML_GE == 1 */
/* If we are at the end of the buffer, this would cause the next stage,
i.e. externalEntityInitProcessor3, to pass control directly to
@@ -2778,7 +2793,7 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
for (;;) {
const char *next = s; /* XmlContentTok doesn't always set the last arg */
int tok = XmlContentTok(enc, s, end, &next);
-#ifdef XML_DTD
+#if XML_GE == 1
const char *accountAfter
= ((tok == XML_TOK_TRAILING_RSQB) || (tok == XML_TOK_TRAILING_CR))
? (haveMore ? s /* i.e. 0 bytes */ : end)
@@ -2844,14 +2859,14 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
XML_Char ch = (XML_Char)XmlPredefinedEntityName(
enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar);
if (ch) {
-#ifdef XML_DTD
+#if XML_GE == 1
/* NOTE: We are replacing 4-6 characters original input for 1 character
* so there is no amplification and hence recording without
* protection. */
accountingDiffTolerated(parser, tok, (char *)&ch,
((char *)&ch) + sizeof(XML_Char), __LINE__,
XML_ACCOUNT_ENTITY_EXPANSION);
-#endif /* XML_DTD */
+#endif /* XML_GE == 1 */
if (parser->m_characterDataHandler)
parser->m_characterDataHandler(parser->m_handlerArg, &ch, 1);
else if (parser->m_defaultHandler)
@@ -4053,7 +4068,7 @@ doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
for (;;) {
const char *next = s; /* in case of XML_TOK_NONE or XML_TOK_PARTIAL */
int tok = XmlCdataSectionTok(enc, s, end, &next);
-#ifdef XML_DTD
+#if XML_GE == 1
if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, account)) {
accountingOnAbort(parser);
return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
@@ -4205,7 +4220,7 @@ doIgnoreSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
*eventPP = s;
*startPtr = NULL;
tok = XmlIgnoreSectionTok(enc, s, end, &next);
-# ifdef XML_DTD
+# if XML_GE == 1
if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
XML_ACCOUNT_DIRECT)) {
accountingOnAbort(parser);
@@ -4297,7 +4312,7 @@ processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *s,
const XML_Char *storedversion = NULL;
int standalone = -1;
-#ifdef XML_DTD
+#if XML_GE == 1
if (! accountingDiffTolerated(parser, XML_TOK_XML_DECL, s, next, __LINE__,
XML_ACCOUNT_DIRECT)) {
accountingOnAbort(parser);
@@ -4504,7 +4519,7 @@ entityValueInitProcessor(XML_Parser parser, const char *s, const char *end,
is not valid to have multiple BOMs.
*/
else if (tok == XML_TOK_BOM) {
-# ifdef XML_DTD
+# if XML_GE == 1
if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
XML_ACCOUNT_DIRECT)) {
accountingOnAbort(parser);
@@ -4720,11 +4735,13 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
}
}
role = XmlTokenRole(&parser->m_prologState, tok, s, next, enc);
-#ifdef XML_DTD
+#if XML_GE == 1
switch (role) {
case XML_ROLE_INSTANCE_START: // bytes accounted in contentProcessor
case XML_ROLE_XML_DECL: // bytes accounted in processXmlDecl
- case XML_ROLE_TEXT_DECL: // bytes accounted in processXmlDecl
+# ifdef XML_DTD
+ case XML_ROLE_TEXT_DECL: // bytes accounted in processXmlDecl
+# endif
break;
default:
if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, account)) {
@@ -5042,6 +5059,9 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
break;
case XML_ROLE_ENTITY_VALUE:
if (dtd->keepProcessing) {
+#if XML_GE == 1
+ // This will store the given replacement text in
+ // parser->m_declEntity->textPtr.
enum XML_Error result
= storeEntityValue(parser, enc, s + enc->minBytesPerChar,
next - enc->minBytesPerChar, XML_ACCOUNT_NONE);
@@ -5062,6 +5082,25 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
poolDiscard(&dtd->entityValuePool);
if (result != XML_ERROR_NONE)
return result;
+#else
+ // This will store "&entity123;" in parser->m_declEntity->textPtr
+ // to end up as "&entity123;" in the handler.
+ if (parser->m_declEntity != NULL) {
+ const enum XML_Error result
+ = storeSelfEntityValue(parser, parser->m_declEntity);
+ if (result != XML_ERROR_NONE)
+ return result;
+
+ if (parser->m_entityDeclHandler) {
+ *eventEndPP = s;
+ parser->m_entityDeclHandler(
+ parser->m_handlerArg, parser->m_declEntity->name,
+ parser->m_declEntity->is_param, parser->m_declEntity->textPtr,
+ parser->m_declEntity->textLen, parser->m_curBase, 0, 0, 0);
+ handleDefault = XML_FALSE;
+ }
+ }
+#endif
}
break;
case XML_ROLE_DOCTYPE_SYSTEM_ID:
@@ -5120,6 +5159,16 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
}
break;
case XML_ROLE_ENTITY_COMPLETE:
+#if XML_GE == 0
+ // This will store "&entity123;" in entity->textPtr
+ // to end up as "&entity123;" in the handler.
+ if (parser->m_declEntity != NULL) {
+ const enum XML_Error result
+ = storeSelfEntityValue(parser, parser->m_declEntity);
+ if (result != XML_ERROR_NONE)
+ return result;
+ }
+#endif
if (dtd->keepProcessing && parser->m_declEntity
&& parser->m_entityDeclHandler) {
*eventEndPP = s;
@@ -5661,7 +5710,7 @@ epilogProcessor(XML_Parser parser, const char *s, const char *end,
for (;;) {
const char *next = NULL;
int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
-#ifdef XML_DTD
+#if XML_GE == 1
if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
XML_ACCOUNT_DIRECT)) {
accountingOnAbort(parser);
@@ -5741,7 +5790,7 @@ processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) {
return XML_ERROR_NO_MEMORY;
}
entity->open = XML_TRUE;
-#ifdef XML_DTD
+#if XML_GE == 1
entityTrackingOnOpen(parser, entity, __LINE__);
#endif
entity->processed = 0;
@@ -5775,9 +5824,9 @@ processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) {
entity->processed = (int)(next - textStart);
parser->m_processor = internalEntityProcessor;
} else {
-#ifdef XML_DTD
+#if XML_GE == 1
entityTrackingOnClose(parser, entity, __LINE__);
-#endif /* XML_DTD */
+#endif /* XML_GE == 1 */
entity->open = XML_FALSE;
parser->m_openInternalEntities = openEntity->next;
/* put openEntity back in list of free instances */
@@ -5826,7 +5875,7 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
return result;
}
-#ifdef XML_DTD
+#if XML_GE == 1
entityTrackingOnClose(parser, entity, __LINE__);
#endif
entity->open = XML_FALSE;
@@ -5905,7 +5954,7 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
const char *next
= ptr; /* XmlAttributeValueTok doesn't always set the last arg */
int tok = XmlAttributeValueTok(enc, ptr, end, &next);
-#ifdef XML_DTD
+#if XML_GE == 1
if (! accountingDiffTolerated(parser, tok, ptr, next, __LINE__, account)) {
accountingOnAbort(parser);
return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
@@ -5970,14 +6019,14 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
XML_Char ch = (XML_Char)XmlPredefinedEntityName(
enc, ptr + enc->minBytesPerChar, next - enc->minBytesPerChar);
if (ch) {
-#ifdef XML_DTD
+#if XML_GE == 1
/* NOTE: We are replacing 4-6 characters original input for 1 character
* so there is no amplification and hence recording without
* protection. */
accountingDiffTolerated(parser, tok, (char *)&ch,
((char *)&ch) + sizeof(XML_Char), __LINE__,
XML_ACCOUNT_ENTITY_EXPANSION);
-#endif /* XML_DTD */
+#endif /* XML_GE == 1 */
if (! poolAppendChar(pool, ch))
return XML_ERROR_NO_MEMORY;
break;
@@ -6055,14 +6104,14 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
enum XML_Error result;
const XML_Char *textEnd = entity->textPtr + entity->textLen;
entity->open = XML_TRUE;
-#ifdef XML_DTD
+#if XML_GE == 1
entityTrackingOnOpen(parser, entity, __LINE__);
#endif
result = appendAttributeValue(parser, parser->m_internalEncoding,
isCdata, (const char *)entity->textPtr,
(const char *)textEnd, pool,
XML_ACCOUNT_ENTITY_EXPANSION);
-#ifdef XML_DTD
+#if XML_GE == 1
entityTrackingOnClose(parser, entity, __LINE__);
#endif
entity->open = XML_FALSE;
@@ -6092,6 +6141,7 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
/* not reached */
}
+#if XML_GE == 1
static enum XML_Error
storeEntityValue(XML_Parser parser, const ENCODING *enc,
const char *entityTextPtr, const char *entityTextEnd,
@@ -6099,12 +6149,12 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc,
DTD *const dtd = parser->m_dtd; /* save one level of indirection */
STRING_POOL *pool = &(dtd->entityValuePool);
enum XML_Error result = XML_ERROR_NONE;
-#ifdef XML_DTD
+# ifdef XML_DTD
int oldInEntityValue = parser->m_prologState.inEntityValue;
parser->m_prologState.inEntityValue = 1;
-#else
+# else
UNUSED_P(account);
-#endif /* XML_DTD */
+# endif /* XML_DTD */
/* never return Null for the value argument in EntityDeclHandler,
since this would indicate an external entity; therefore we
have to make sure that entityValuePool.start is not null */
@@ -6118,18 +6168,16 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc,
= entityTextPtr; /* XmlEntityValueTok doesn't always set the last arg */
int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
-#ifdef XML_DTD
if (! accountingDiffTolerated(parser, tok, entityTextPtr, next, __LINE__,
account)) {
accountingOnAbort(parser);
result = XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
goto endEntityValue;
}
-#endif
switch (tok) {
case XML_TOK_PARAM_ENTITY_REF:
-#ifdef XML_DTD
+# ifdef XML_DTD
if (parser->m_isParamEntity || enc != parser->m_encoding) {
const XML_Char *name;
ENTITY *entity;
@@ -6191,7 +6239,7 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc,
}
break;
}
-#endif /* XML_DTD */
+# endif /* XML_DTD */
/* In the internal subset, PE references are not legal
within markup declarations, e.g entity values in this case. */
parser->m_eventPtr = entityTextPtr;
@@ -6272,12 +6320,38 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc,
entityTextPtr = next;
}
endEntityValue:
-#ifdef XML_DTD
+# ifdef XML_DTD
parser->m_prologState.inEntityValue = oldInEntityValue;
-#endif /* XML_DTD */
+# endif /* XML_DTD */
return result;
}
+#else /* XML_GE == 0 */
+
+static enum XML_Error
+storeSelfEntityValue(XML_Parser parser, ENTITY *entity) {
+ // This will store "&entity123;" in entity->textPtr
+ // to end up as "&entity123;" in the handler.
+ const char *const entity_start = "&";
+ const char *const entity_end = ";";
+
+ STRING_POOL *const pool = &(parser->m_dtd->entityValuePool);
+ if (! poolAppendString(pool, entity_start)
+ || ! poolAppendString(pool, entity->name)
+ || ! poolAppendString(pool, entity_end)) {
+ poolDiscard(pool);
+ return XML_ERROR_NO_MEMORY;
+ }
+
+ entity->textPtr = poolStart(pool);
+ entity->textLen = (int)(poolLength(pool));
+ poolFinish(pool);
+
+ return XML_ERROR_NONE;
+}
+
+#endif /* XML_GE == 0 */
+
static void FASTCALL
normalizeLines(XML_Char *s) {
XML_Char *p;
@@ -7669,7 +7743,7 @@ copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite) {
return result;
}
-#ifdef XML_DTD
+#if XML_GE == 1
static float
accountingGetCurrentAmplification(XML_Parser rootParser) {
@@ -8400,7 +8474,7 @@ unsignedCharToPrintable(unsigned char c) {
assert(0); /* never gets here */
}
-#endif /* XML_DTD */
+#endif /* XML_GE == 1 */
static unsigned long
getDebugLevel(const char *variableName, unsigned long defaultDebugLevel) {
diff --git a/expat/tests/acc_tests.c b/expat/tests/acc_tests.c
index f2dee34d4..92b715043 100644
--- a/expat/tests/acc_tests.c
+++ b/expat/tests/acc_tests.c
@@ -54,7 +54,7 @@
#include "handlers.h"
#include "acc_tests.h"
-#if defined(XML_DTD)
+#if XML_GE == 1
START_TEST(test_accounting_precision) {
struct AccountingTestCase cases[] = {
{" ", NULL, NULL, 0},
@@ -92,9 +92,12 @@ START_TEST(test_accounting_precision) {
/* Processing instructions */
{" ",
NULL, NULL, 0},
+ {" ", NULL, NULL, 0},
+# ifdef XML_DTD
{" ",
"%e1;", "",
0},
+# endif /* XML_DTD */
/* CDATA */
{" ", NULL, NULL, 0},
@@ -108,6 +111,7 @@ START_TEST(test_accounting_precision) {
"&e; \n",
NULL, NULL, sizeof(XML_Char) * strlen("111333")},
+# ifdef XML_DTD
/* Conditional sections */
{"\n"
@@ -119,6 +123,7 @@ START_TEST(test_accounting_precision) {
"]]>\n"
"]]>",
NULL, sizeof(XML_Char) * (strlen("INCLUDE") + strlen("IGNORE"))},
+# endif /* XML_DTD */
/* General entities */
{"&five;",
"\xEF\xBB\xBF" /* UTF-8 BOM */, NULL, 0},
+# ifdef XML_DTD
/* Parameter entities */
{"\">\n"
@@ -228,6 +234,7 @@ START_TEST(test_accounting_precision) {
"%e1;\n",
"\xEF\xBB\xBF" /* UTF-8 BOM */,
strlen("\xEF\xBB\xBF")},
+# endif /* XML_DTD */
};
const size_t countCases = sizeof(cases) / sizeof(cases[0]);
@@ -297,8 +304,8 @@ portableINFINITY(void) {
START_TEST(test_billion_laughs_attack_protection_api) {
XML_Parser parserWithoutParent = XML_ParserCreate(NULL);
- XML_Parser parserWithParent
- = XML_ExternalEntityParserCreate(parserWithoutParent, NULL, NULL);
+ XML_Parser parserWithParent = XML_ExternalEntityParserCreate(
+ parserWithoutParent, XCS("entity123"), NULL);
if (parserWithoutParent == NULL)
fail("parserWithoutParent is NULL");
if (parserWithParent == NULL)
@@ -380,11 +387,11 @@ START_TEST(test_helper_unsigned_char_to_printable) {
fail("unsignedCharToPrintable result mistaken");
}
END_TEST
-#endif // defined(XML_DTD)
+#endif // XML_GE == 1
void
make_accounting_test_case(Suite *s) {
-#if defined(XML_DTD)
+#if XML_GE == 1
TCase *tc_accounting = tcase_create("accounting tests");
suite_add_tcase(s, tc_accounting);
@@ -394,5 +401,5 @@ make_accounting_test_case(Suite *s) {
tcase_add_test(tc_accounting, test_helper_unsigned_char_to_printable);
#else
UNUSED_P(s);
-#endif /* defined(XML_DTD) */
+#endif /* XML_GE == 1 */
}
diff --git a/expat/tests/alloc_tests.c b/expat/tests/alloc_tests.c
index 534bec049..129f3e719 100644
--- a/expat/tests/alloc_tests.c
+++ b/expat/tests/alloc_tests.c
@@ -2083,7 +2083,7 @@ make_alloc_test_case(Suite *s) {
tcase_add_test(tc_alloc, test_alloc_explicit_encoding);
tcase_add_test(tc_alloc, test_alloc_set_base);
tcase_add_test(tc_alloc, test_alloc_realloc_buffer);
- tcase_add_test(tc_alloc, test_alloc_ext_entity_realloc_buffer);
+ tcase_add_test__if_xml_ge(tc_alloc, test_alloc_ext_entity_realloc_buffer);
tcase_add_test(tc_alloc, test_alloc_realloc_many_attributes);
tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_public_entity_value);
tcase_add_test__ifdef_xml_dtd(tc_alloc,
@@ -2096,7 +2096,7 @@ make_alloc_test_case(Suite *s) {
test_alloc_realloc_attribute_enum_value);
tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_implied_attribute);
tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_default_attribute);
- tcase_add_test(tc_alloc, test_alloc_notation);
+ tcase_add_test__if_xml_ge(tc_alloc, test_alloc_notation);
tcase_add_test(tc_alloc, test_alloc_public_notation);
tcase_add_test(tc_alloc, test_alloc_system_notation);
tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_groups);
@@ -2110,17 +2110,17 @@ make_alloc_test_case(Suite *s) {
tcase_add_test(tc_alloc, test_alloc_attribute_whitespace);
tcase_add_test(tc_alloc, test_alloc_attribute_predefined_entity);
tcase_add_test(tc_alloc, test_alloc_long_attr_default_with_char_ref);
- tcase_add_test(tc_alloc, test_alloc_long_attr_value);
+ tcase_add_test__if_xml_ge(tc_alloc, test_alloc_long_attr_value);
tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_entities);
tcase_add_test__ifdef_xml_dtd(tc_alloc,
test_alloc_realloc_param_entity_newline);
tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_ce_extends_pe);
tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_attributes);
tcase_add_test(tc_alloc, test_alloc_long_doc_name);
- tcase_add_test(tc_alloc, test_alloc_long_base);
- tcase_add_test(tc_alloc, test_alloc_long_public_id);
- tcase_add_test(tc_alloc, test_alloc_long_entity_value);
- tcase_add_test(tc_alloc, test_alloc_long_notation);
+ tcase_add_test__if_xml_ge(tc_alloc, test_alloc_long_base);
+ tcase_add_test__if_xml_ge(tc_alloc, test_alloc_long_public_id);
+ tcase_add_test__if_xml_ge(tc_alloc, test_alloc_long_entity_value);
+ tcase_add_test__if_xml_ge(tc_alloc, test_alloc_long_notation);
tcase_add_test__ifdef_xml_dtd(
tc_alloc, test_alloc_reset_after_external_entity_parser_create_fail);
diff --git a/expat/tests/basic_tests.c b/expat/tests/basic_tests.c
index 09c1cc227..797ef73df 100644
--- a/expat/tests/basic_tests.c
+++ b/expat/tests/basic_tests.c
@@ -5218,7 +5218,7 @@ make_basic_test_case(Suite *s) {
tcase_add_test(tc_basic, test_xmldecl_invalid);
tcase_add_test(tc_basic, test_xmldecl_missing_attr);
tcase_add_test(tc_basic, test_xmldecl_missing_value);
- tcase_add_test(tc_basic, test_unknown_encoding_internal_entity);
+ tcase_add_test__if_xml_ge(tc_basic, test_unknown_encoding_internal_entity);
tcase_add_test(tc_basic, test_unrecognised_encoding_internal_entity);
tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_encoding);
tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_no_handler);
@@ -5234,9 +5234,9 @@ make_basic_test_case(Suite *s) {
tcase_add_test(tc_basic, test_wfc_undeclared_entity_with_external_subset);
tcase_add_test(tc_basic, test_not_standalone_handler_reject);
tcase_add_test(tc_basic, test_not_standalone_handler_accept);
- tcase_add_test(tc_basic, test_wfc_no_recursive_entity_refs);
+ tcase_add_test__if_xml_ge(tc_basic, test_wfc_no_recursive_entity_refs);
tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_invalid_parse);
- tcase_add_test(tc_basic, test_dtd_default_handling);
+ tcase_add_test__if_xml_ge(tc_basic, test_dtd_default_handling);
tcase_add_test(tc_basic, test_dtd_attr_handling);
tcase_add_test(tc_basic, test_empty_ns_without_namespaces);
tcase_add_test(tc_basic, test_ns_in_attribute_default_without_namespaces);
@@ -5254,7 +5254,7 @@ make_basic_test_case(Suite *s) {
tcase_add_test(tc_basic, test_stop_parser_between_cdata_calls);
tcase_add_test(tc_basic, test_suspend_parser_between_cdata_calls);
tcase_add_test(tc_basic, test_memory_allocation);
- tcase_add_test(tc_basic, test_default_current);
+ tcase_add_test__if_xml_ge(tc_basic, test_default_current);
tcase_add_test(tc_basic, test_dtd_elements);
tcase_add_test(tc_basic, test_dtd_elements_nesting);
tcase_add_test__ifdef_xml_dtd(tc_basic, test_set_foreign_dtd);
@@ -5266,22 +5266,22 @@ make_basic_test_case(Suite *s) {
tcase_add_test__ifdef_xml_dtd(tc_basic, test_empty_foreign_dtd);
tcase_add_test(tc_basic, test_set_base);
tcase_add_test(tc_basic, test_attributes);
- tcase_add_test(tc_basic, test_reset_in_entity);
+ tcase_add_test__if_xml_ge(tc_basic, test_reset_in_entity);
tcase_add_test(tc_basic, test_resume_invalid_parse);
tcase_add_test(tc_basic, test_resume_resuspended);
tcase_add_test(tc_basic, test_cdata_default);
tcase_add_test(tc_basic, test_subordinate_reset);
tcase_add_test(tc_basic, test_subordinate_suspend);
- tcase_add_test(tc_basic, test_subordinate_xdecl_suspend);
- tcase_add_test(tc_basic, test_subordinate_xdecl_abort);
+ tcase_add_test__if_xml_ge(tc_basic, test_subordinate_xdecl_suspend);
+ tcase_add_test__if_xml_ge(tc_basic, test_subordinate_xdecl_abort);
tcase_add_test__ifdef_xml_dtd(tc_basic,
test_ext_entity_invalid_suspended_parse);
tcase_add_test(tc_basic, test_explicit_encoding);
tcase_add_test(tc_basic, test_trailing_cr);
- tcase_add_test(tc_basic, test_ext_entity_trailing_cr);
+ tcase_add_test__if_xml_ge(tc_basic, test_ext_entity_trailing_cr);
tcase_add_test(tc_basic, test_trailing_rsqb);
- tcase_add_test(tc_basic, test_ext_entity_trailing_rsqb);
- tcase_add_test(tc_basic, test_ext_entity_good_cdata);
+ tcase_add_test__if_xml_ge(tc_basic, test_ext_entity_trailing_rsqb);
+ tcase_add_test__if_xml_ge(tc_basic, test_ext_entity_good_cdata);
tcase_add_test__ifdef_xml_dtd(tc_basic, test_user_parameters);
tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_ref_parameter);
tcase_add_test(tc_basic, test_empty_parse);
@@ -5338,10 +5338,10 @@ make_basic_test_case(Suite *s) {
tcase_add_test(tc_basic, test_skipped_null_loaded_ext_entity);
tcase_add_test(tc_basic, test_skipped_unloaded_ext_entity);
tcase_add_test__ifdef_xml_dtd(tc_basic, test_param_entity_with_trailing_cr);
- tcase_add_test(tc_basic, test_invalid_character_entity);
- tcase_add_test(tc_basic, test_invalid_character_entity_2);
- tcase_add_test(tc_basic, test_invalid_character_entity_3);
- tcase_add_test(tc_basic, test_invalid_character_entity_4);
+ tcase_add_test__if_xml_ge(tc_basic, test_invalid_character_entity);
+ tcase_add_test__if_xml_ge(tc_basic, test_invalid_character_entity_2);
+ tcase_add_test__if_xml_ge(tc_basic, test_invalid_character_entity_3);
+ tcase_add_test__if_xml_ge(tc_basic, test_invalid_character_entity_4);
tcase_add_test(tc_basic, test_pi_handled_in_default);
tcase_add_test(tc_basic, test_comment_handled_in_default);
tcase_add_test(tc_basic, test_pi_yml);
@@ -5366,14 +5366,14 @@ make_basic_test_case(Suite *s) {
tcase_add_test(tc_basic, test_unknown_encoding_invalid_surrogate);
tcase_add_test(tc_basic, test_unknown_encoding_invalid_high);
tcase_add_test(tc_basic, test_unknown_encoding_invalid_attr_value);
- tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom);
- tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom);
- tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom2);
- tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom2);
- tcase_add_test(tc_basic, test_ext_entity_utf16_be);
- tcase_add_test(tc_basic, test_ext_entity_utf16_le);
- tcase_add_test(tc_basic, test_ext_entity_utf16_unknown);
- tcase_add_test(tc_basic, test_ext_entity_utf8_non_bom);
+ tcase_add_test__if_xml_ge(tc_basic, test_ext_entity_latin1_utf16le_bom);
+ tcase_add_test__if_xml_ge(tc_basic, test_ext_entity_latin1_utf16be_bom);
+ tcase_add_test__if_xml_ge(tc_basic, test_ext_entity_latin1_utf16le_bom2);
+ tcase_add_test__if_xml_ge(tc_basic, test_ext_entity_latin1_utf16be_bom2);
+ tcase_add_test__if_xml_ge(tc_basic, test_ext_entity_utf16_be);
+ tcase_add_test__if_xml_ge(tc_basic, test_ext_entity_utf16_le);
+ tcase_add_test__if_xml_ge(tc_basic, test_ext_entity_utf16_unknown);
+ tcase_add_test__if_xml_ge(tc_basic, test_ext_entity_utf8_non_bom);
tcase_add_test(tc_basic, test_utf8_in_cdata_section);
tcase_add_test(tc_basic, test_utf8_in_cdata_section_2);
tcase_add_test(tc_basic, test_utf8_in_start_tags);
@@ -5408,5 +5408,5 @@ make_basic_test_case(Suite *s) {
tcase_add_test(tc_basic, test_empty_element_abort);
tcase_add_test__ifdef_xml_dtd(tc_basic,
test_pool_integrity_with_unfinished_attr);
- tcase_add_test(tc_basic, test_nested_entity_suspend);
+ tcase_add_test__if_xml_ge(tc_basic, test_nested_entity_suspend);
}
diff --git a/expat/tests/common.c b/expat/tests/common.c
index 21d9dfea9..2832933a2 100644
--- a/expat/tests/common.c
+++ b/expat/tests/common.c
@@ -153,6 +153,16 @@ tcase_add_test__ifdef_xml_dtd(TCase *tc, tcase_test_function test) {
#endif
}
+void
+tcase_add_test__if_xml_ge(TCase *tc, tcase_test_function test) {
+#if XML_GE == 1
+ tcase_add_test(tc, test);
+#else
+ UNUSED_P(tc);
+ UNUSED_P(test);
+#endif
+}
+
void
basic_teardown(void) {
if (g_parser != NULL) {
diff --git a/expat/tests/common.h b/expat/tests/common.h
index 386f85fb4..412c84ec2 100644
--- a/expat/tests/common.h
+++ b/expat/tests/common.h
@@ -90,6 +90,7 @@ extern const char *long_cdata_text;
extern const char *get_buffer_test_text;
extern void tcase_add_test__ifdef_xml_dtd(TCase *tc, tcase_test_function test);
+extern void tcase_add_test__if_xml_ge(TCase *tc, tcase_test_function test);
extern void basic_teardown(void);
diff --git a/expat/tests/handlers.c b/expat/tests/handlers.c
index 11915cb5b..1fb65ed14 100644
--- a/expat/tests/handlers.c
+++ b/expat/tests/handlers.c
@@ -669,6 +669,24 @@ external_entity_suspending_faulter(XML_Parser parser, const XML_Char *context,
return XML_STATUS_ERROR;
}
+int XMLCALL
+external_entity_failer__if_not_xml_ge(XML_Parser parser,
+ const XML_Char *context,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId) {
+ UNUSED_P(parser);
+ UNUSED_P(context);
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+#if XML_GE == 0
+ fail(
+ "Function external_entity_suspending_failer was called despite XML_GE==0.");
+#endif
+ return XML_STATUS_OK;
+}
+
int XMLCALL
external_entity_cr_catcher(XML_Parser parser, const XML_Char *context,
const XML_Char *base, const XML_Char *systemId,
@@ -1476,7 +1494,7 @@ external_entity_parser_create_alloc_fail_handler(XML_Parser parser,
return XML_STATUS_ERROR;
}
-#if defined(XML_DTD)
+#if XML_GE == 1
int
accounting_external_entity_ref_handler(XML_Parser parser,
const XML_Char *context,
@@ -1508,7 +1526,7 @@ accounting_external_entity_ref_handler(XML_Parser parser,
XML_ParserFree(entParser);
return status;
}
-#endif /* XML_DTD */
+#endif /* XML_GE == 1 */
/* NotStandalone handlers */
@@ -1853,10 +1871,43 @@ accumulate_entity_decl(void *userData, const XML_Char *entityName,
UNUSED_P(notationName);
CharData_AppendXMLChars(storage, entityName, -1);
CharData_AppendXMLChars(storage, XCS("="), 1);
- CharData_AppendXMLChars(storage, value, value_length);
+ if (value == NULL)
+ CharData_AppendXMLChars(storage, XCS("(null)"), -1);
+ else
+ CharData_AppendXMLChars(storage, value, value_length);
CharData_AppendXMLChars(storage, XCS("\n"), 1);
}
+void XMLCALL
+accumulate_char_data(void *userData, const XML_Char *s, int len) {
+ CharData *const storage = (CharData *)userData;
+ CharData_AppendXMLChars(storage, s, len);
+}
+
+void XMLCALL
+accumulate_start_element(void *userData, const XML_Char *name,
+ const XML_Char **atts) {
+ CharData *const storage = (CharData *)userData;
+ CharData_AppendXMLChars(storage, XCS("("), 1);
+ CharData_AppendXMLChars(storage, name, -1);
+
+ if ((atts != NULL) && (atts[0] != NULL)) {
+ CharData_AppendXMLChars(storage, XCS("("), 1);
+ while (atts[0] != NULL) {
+ CharData_AppendXMLChars(storage, atts[0], -1);
+ CharData_AppendXMLChars(storage, XCS("="), 1);
+ CharData_AppendXMLChars(storage, atts[1], -1);
+ atts += 2;
+ if (atts[0] != NULL) {
+ CharData_AppendXMLChars(storage, XCS(","), 1);
+ }
+ }
+ CharData_AppendXMLChars(storage, XCS(")"), 1);
+ }
+
+ CharData_AppendXMLChars(storage, XCS(")\n"), 2);
+}
+
void XMLCALL
checking_default_handler(void *userData, const XML_Char *s, int len) {
DefaultCheck *data = (DefaultCheck *)userData;
diff --git a/expat/tests/handlers.h b/expat/tests/handlers.h
index 0301d9531..069982e71 100644
--- a/expat/tests/handlers.h
+++ b/expat/tests/handlers.h
@@ -185,6 +185,9 @@ extern int XMLCALL external_entity_faulter(XML_Parser parser,
const XML_Char *base,
const XML_Char *systemId,
const XML_Char *publicId);
+extern int XMLCALL external_entity_failer__if_not_xml_ge(
+ XML_Parser parser, const XML_Char *context, const XML_Char *base,
+ const XML_Char *systemId, const XML_Char *publicId);
extern int XMLCALL external_entity_null_loader(XML_Parser parser,
const XML_Char *context,
const XML_Char *base,
@@ -404,7 +407,6 @@ extern int XMLCALL external_entity_parser_create_alloc_fail_handler(
XML_Parser parser, const XML_Char *context, const XML_Char *base,
const XML_Char *systemId, const XML_Char *publicId);
-# if defined(XML_DTD)
struct AccountingTestCase {
const char *primaryText;
const char *firstExternalText; /* often NULL */
@@ -417,7 +419,6 @@ extern int accounting_external_entity_ref_handler(XML_Parser parser,
const XML_Char *base,
const XML_Char *systemId,
const XML_Char *publicId);
-# endif /* defined(XML_DTD) */
/* NotStandalone handlers */
@@ -563,6 +564,13 @@ extern void XMLCALL accumulate_entity_decl(
const XML_Char *systemId, const XML_Char *publicId,
const XML_Char *notationName);
+extern void XMLCALL accumulate_char_data(void *userData, const XML_Char *s,
+ int len);
+
+extern void XMLCALL accumulate_start_element(void *userData,
+ const XML_Char *name,
+ const XML_Char **atts);
+
typedef struct default_check {
const XML_Char *expected;
const int expectedLen;
diff --git a/expat/tests/misc_tests.c b/expat/tests/misc_tests.c
index db2b14b95..4167c4cc0 100644
--- a/expat/tests/misc_tests.c
+++ b/expat/tests/misc_tests.c
@@ -406,6 +406,50 @@ START_TEST(test_misc_create_external_entity_parser_with_null_context) {
}
END_TEST
+START_TEST(test_misc_general_entities_support) {
+ const char *const doc
+ = "\n"
+ "\n"
+ "]>\n"
+ "[&e1;][&e2;][&'><"] ";
+
+ CharData storage;
+ CharData_Init(&storage);
+
+ XML_Parser parser = XML_ParserCreate(NULL);
+ XML_SetUserData(parser, &storage);
+ XML_SetStartElementHandler(parser, accumulate_start_element);
+ XML_SetExternalEntityRefHandler(parser,
+ external_entity_failer__if_not_xml_ge);
+ XML_SetEntityDeclHandler(parser, accumulate_entity_decl);
+ XML_SetCharacterDataHandler(parser, accumulate_char_data);
+
+ if (_XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc), XML_TRUE)
+ != XML_STATUS_OK) {
+ xml_failure(parser);
+ }
+
+ XML_ParserFree(parser);
+
+ CharData_CheckXMLChars(&storage,
+ /* clang-format off */
+#if XML_GE == 1
+ XCS("e1=v1\n")
+ XCS("e2=(null)\n")
+ XCS("(r(a1=[v1]))\n")
+ XCS("[v1][][&'><\"]")
+#else
+ XCS("e1=&e1;\n")
+ XCS("e2=(null)\n")
+ XCS("(r(a1=[&e1;]))\n")
+ XCS("[&e1;][&e2;][&'><\"]")
+#endif
+ );
+ /* clang-format on */
+}
+END_TEST
+
void
make_miscellaneous_test_case(Suite *s) {
TCase *tc_misc = tcase_create("miscellaneous tests");
@@ -428,4 +472,5 @@ make_miscellaneous_test_case(Suite *s) {
tcase_add_test(tc_misc, test_misc_tag_mismatch_reset_leak);
tcase_add_test(tc_misc,
test_misc_create_external_entity_parser_with_null_context);
+ tcase_add_test(tc_misc, test_misc_general_entities_support);
}
diff --git a/expat/tests/ns_tests.c b/expat/tests/ns_tests.c
index 360d83891..34683def1 100644
--- a/expat/tests/ns_tests.c
+++ b/expat/tests/ns_tests.c
@@ -747,7 +747,7 @@ make_namespace_test_case(Suite *s) {
tcase_add_test(tc_namespace, test_ns_bad_element_leafname);
tcase_add_test(tc_namespace, test_ns_utf16_leafname);
tcase_add_test(tc_namespace, test_ns_utf16_element_leafname);
- tcase_add_test(tc_namespace, test_ns_utf16_doctype);
+ tcase_add_test__if_xml_ge(tc_namespace, test_ns_utf16_doctype);
tcase_add_test(tc_namespace, test_ns_invalid_doctype);
tcase_add_test(tc_namespace, test_ns_double_colon_doctype);
tcase_add_test(tc_namespace, test_ns_separator_in_uri);
diff --git a/expat/tests/nsalloc_tests.c b/expat/tests/nsalloc_tests.c
index 6fb621c78..dc17cba35 100644
--- a/expat/tests/nsalloc_tests.c
+++ b/expat/tests/nsalloc_tests.c
@@ -1521,16 +1521,17 @@ make_nsalloc_test_case(Suite *s) {
tcase_add_test(tc_nsalloc, test_nsalloc_long_namespace);
tcase_add_test(tc_nsalloc, test_nsalloc_less_long_namespace);
tcase_add_test(tc_nsalloc, test_nsalloc_long_context);
- tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context);
- tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_2);
- tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_3);
- tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_4);
- tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_5);
- tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_6);
- tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_7);
+ tcase_add_test__if_xml_ge(tc_nsalloc, test_nsalloc_realloc_long_context);
+ tcase_add_test__if_xml_ge(tc_nsalloc, test_nsalloc_realloc_long_context_2);
+ tcase_add_test__if_xml_ge(tc_nsalloc, test_nsalloc_realloc_long_context_3);
+ tcase_add_test__if_xml_ge(tc_nsalloc, test_nsalloc_realloc_long_context_4);
+ tcase_add_test__if_xml_ge(tc_nsalloc, test_nsalloc_realloc_long_context_5);
+ tcase_add_test__if_xml_ge(tc_nsalloc, test_nsalloc_realloc_long_context_6);
+ tcase_add_test__if_xml_ge(tc_nsalloc, test_nsalloc_realloc_long_context_7);
tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_ge_name);
- tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_in_dtd);
- tcase_add_test(tc_nsalloc, test_nsalloc_long_default_in_ext);
+ tcase_add_test__if_xml_ge(tc_nsalloc,
+ test_nsalloc_realloc_long_context_in_dtd);
+ tcase_add_test__if_xml_ge(tc_nsalloc, test_nsalloc_long_default_in_ext);
tcase_add_test(tc_nsalloc, test_nsalloc_long_systemid_in_ext);
tcase_add_test(tc_nsalloc, test_nsalloc_prefixed_element);
}
diff --git a/expat/tests/runtests.c b/expat/tests/runtests.c
index 2104b92ff..db983dce8 100644
--- a/expat/tests/runtests.c
+++ b/expat/tests/runtests.c
@@ -69,7 +69,7 @@ make_suite(void) {
make_miscellaneous_test_case(s);
make_alloc_test_case(s);
make_nsalloc_test_case(s);
-#if defined(XML_DTD)
+#if XML_GE == 1
make_accounting_test_case(s);
#endif
diff --git a/expat/xmlwf/xmlwf.c b/expat/xmlwf/xmlwf.c
index d5157ef50..2b1cf5ff6 100644
--- a/expat/xmlwf/xmlwf.c
+++ b/expat/xmlwf/xmlwf.c
@@ -1096,9 +1096,10 @@ tmain(int argc, XML_Char **argv) {
" (needs a floating point number greater or equal than 1.0)"));
exit(XMLWF_EXIT_USAGE_ERROR);
}
-#ifndef XML_DTD
- ftprintf(stderr, T("Warning: Given amplification limit ignored") T(
- ", xmlwf has been compiled without DTD support.\n"));
+#if XML_GE == 0
+ ftprintf(stderr,
+ T("Warning: Given amplification limit ignored")
+ T(", xmlwf has been compiled without DTD/GE support.\n"));
#endif
break;
}
@@ -1117,9 +1118,10 @@ tmain(int argc, XML_Char **argv) {
exit(XMLWF_EXIT_USAGE_ERROR);
}
attackThresholdGiven = XML_TRUE;
-#ifndef XML_DTD
- ftprintf(stderr, T("Warning: Given attack threshold ignored") T(
- ", xmlwf has been compiled without DTD support.\n"));
+#if XML_GE == 0
+ ftprintf(stderr,
+ T("Warning: Given attack threshold ignored")
+ T(", xmlwf has been compiled without DTD/GE support.\n"));
#endif
break;
}
@@ -1155,13 +1157,13 @@ tmain(int argc, XML_Char **argv) {
}
if (attackMaximumAmplification != -1.0f) {
-#ifdef XML_DTD
+#if XML_GE == 1
XML_SetBillionLaughsAttackProtectionMaximumAmplification(
parser, attackMaximumAmplification);
#endif
}
if (attackThresholdGiven) {
-#ifdef XML_DTD
+#if XML_GE == 1
XML_SetBillionLaughsAttackProtectionActivationThreshold(
parser, attackThresholdBytes);
#else