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 @@

Configuring Expat Using the Pre-Processor

XML_UNICODE_WCHAR_T. The symbols are:

+
XML_GE
+
+Added in Expat 2.6.0. +Include support for +general entities +(syntax &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. +
+With 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_DTD
Include support for using and reporting DTD-based content. If this is defined, default attribute values from an external DTD subset are reported and attribute value normalization occurs based on the type of attributes defined in the external subset. Without this, Expat has a smaller memory footprint and can be faster, but will -not load external entities or process conditional sections. If defined, makes +not load external parameter entities or process conditional sections. If defined, makes the functions 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