diff options
52 files changed, 2942 insertions, 825 deletions
diff --git a/contrib/expat/Changes b/contrib/expat/Changes index bf94e9db5616..91513379bb49 100644 --- a/contrib/expat/Changes +++ b/contrib/expat/Changes @@ -5,21 +5,108 @@ \___/_/\_\ .__/ \__,_|\__| |_| XML parser -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! <blink>Expat has UNFIXED SECURITY ISSUES!</blink> !! -!! Please see https://github.com/libexpat/libexpat/issues/1160 for details. !! -!! !! -!! Starting 2026-08-01, for up to six months my work maintaining libexpat !! -!! will be funded by the City of Munich as part of their !! -!! Open Source Sabbatical (https://opensource.muenchen.de/sabbatical.html) !! -!! — thank you! !! -!! !! -!! If your business relies on Expat beyond January 2027, please consider !! -!! funding the maintenance of Expat to ensure its health and security for !! -!! you and others. Thank you! !! -!! !! -!! Sebastian Pipping -- Berlin, 2026-09-22 !! -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +/////////////////////////////////////////////////////////////////////////////// +// <blink>Expat has UNFIXED SECURITY ISSUES!</blink> // +// Please see https://github.com/libexpat/libexpat/issues/1160 for details. // +// // +// Starting 2026-08-01, for up to six months my work maintaining libexpat // +// will be funded by the City of Munich as part of their // +// Open Source Sabbatical (https://opensource.muenchen.de/sabbatical.html) // +// — thank you! // +// // +// If your business relies on Expat beyond January 2027, please consider // +// funding the maintenance of Expat to ensure its health and security for // +// you and others. Thank you! // +// // +// Sebastian Pipping -- Berlin, 2026-09-22 // +/////////////////////////////////////////////////////////////////////////////// + +Release 2.9.0 Mon October 5 2026 + Security fixes: + #1392 CVE-2026-102633 -- Integer overflow in function + expat_realloc on 32bit platforms + #1393 CVE-2026-77214 -- Validate parameter `len` against available + buffer capacity in XML_ParseBuffer + + Bug fixes: + #1387 lib: Handle OOM when copying encodingName in XML_ParserReset + + New features: + #1327 lib: Introduce new "Properties API" to get and set + scalar properties for a single parser instance. + There are six new functions: + - XML_GetPropertyBool + - XML_GetPropertyDouble + - XML_GetPropertyUInt64 + - XML_SetPropertyBool + - XML_SetPropertyDouble + - XML_SetPropertyUInt64 + And two new enums: + - XML_Prop_Error + - XML_Parser_Property + #1323 lib: Introduce five new 64bit location API functions: + - XML_GetCurrentByteCount64 + - XML_GetCurrentByteIndex64 + - XML_GetCurrentColumnNumber64 + - XML_GetCurrentLineNumber64 + - XML_GetInputContext64 + These five functions closely mirror their predecessors + but are not prone to 32bit integer wrap-around. + + Other changes: + #1391 docs: Document the scope of function XML_GetErrorCode + #1395 docs: Document length expectations for XML_ParseBuffer + #1394 lib: Call unknown encoding release before parser teardown + #1370 #1373 lib: Drop (disabled-by-default) attribute info feature + These things are now gone: + - Public function XML_GetAttributeInfo + - Public struct XML_AttrInfo + - Macro XML_ATTR_INFO + These things are now causing build errors: + - Configure option --enable-xml-attr-info + - CMake option -DEXPAT_ATTR_INFO=ON + #1379 #1382 lib: Drop (disabled-by-default) minimum size feature + These things are now gone: + - Macro XML_MIN_SIZE + These things are now causing build errors: + - Configuring with -DXML_MIN_SIZE for CPPFLAGS/CFLAGS + - CMake option -DEXPAT_MIN_SIZE=ON + #1323 #1411 lib: Deprecate macro XML_LARGE_SIZE (use the new 64bit + location API functions instead please) + #1323 lib: Deprecate five location API functions that are cursed + with integer wrap-around: + - XML_GetCurrentByteCount + - XML_GetCurrentByteIndex + - XML_GetCurrentColumnNumber + - XML_GetCurrentLineNumber + - XML_GetInputContext + #1399 lib: Guard against out-of-handler use of XML_DefaultCurrent + #1400 lib: Use size_t for bytesAllocated and peakBytesAllocated + #1401 #1402 .. + #1404 #1405 lib|xmlwf|tests: Unify use of xcslen, xcscmp and xcsncmp + #1406 xmlwf: Add missing `#include "expat.h"` + #1389 #1396 Version info bumped from 13:5:12 (libexpat*.so.1.12.5) + to 14:0:13 (libexpat*.so.1.13.0); see https://verbump.de/ + for what these numbers do + + Infrastructure: + #1386 CI: Bump MinGW Clang from 23.1.1 to 23.1.2 + #1410 CI: Bump Fil-C from 0.685 to 0.686 + #1388 CI: Adapt to breaking changes regarding windows-11-arm image + #1403 CI: Limit package cache download runtime + + Special thanks to: + Bénédikt Tran + Berkay Eren Ürün + Fabian Wahle (Hap Security) + Filippo Tedeschi + Junki Lee + Matthew Fernandez + Scott Moore + Wade Sparks III + and + City of Munich Open Source Sabbatical + VulnCheck Release 2.8.5 Tue September 22 2026 Security fixes: @@ -33,17 +120,6 @@ Release 2.8.5 Tue September 22 2026 Upstream CVSS 3.1 vector: AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H (CVSS score: 9.8) -/////////////////////////////////////////////////////////////////////////////// -// The next release will drop two (disabled-by-default) features: // -// // -// - ATTR_INFO (-DXML_ATTR_INFO, -DEXPAT_ATTR_INFO, --enable-xml-attr-info, // -// function XML_GetAttributeInfo, struct XML_AttrInfo) // -// - MIN_SIZE (-DXML_MIN_SIZE, -DEXPAT_MIN_SIZE) // -// // -// If you need them in 2026 and beyond, please share your scenario at // -// GitHub issues #1370 (for ATTR_INFO) and/or #1379 (for MIN_SIZE). Thanks! // -/////////////////////////////////////////////////////////////////////////////// - Bug fixes: #1346 lib: Fix OOM-related memory leak on a failed overflow check #1371 lib: Fix memory alignment for architectures with 128bit diff --git a/contrib/expat/Makefile.in b/contrib/expat/Makefile.in index c0a0eefc47ac..999ed2b231dc 100644 --- a/contrib/expat/Makefile.in +++ b/contrib/expat/Makefile.in @@ -345,12 +345,10 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ -EXPAT_ATTR_INFO = @EXPAT_ATTR_INFO@ EXPAT_CHAR_TYPE = @EXPAT_CHAR_TYPE@ EXPAT_CONTEXT_BYTES = @EXPAT_CONTEXT_BYTES@ EXPAT_DTD = @EXPAT_DTD@ EXPAT_LARGE_SIZE = @EXPAT_LARGE_SIZE@ -EXPAT_MIN_SIZE = @EXPAT_MIN_SIZE@ EXPAT_NS = @EXPAT_NS@ FGREP = @FGREP@ FILECMD = @FILECMD@ @@ -405,7 +403,6 @@ SO_PATCH = @SO_PATCH@ STRIP = @STRIP@ VERSION = @VERSION@ VSCRIPT_LDFLAGS = @VSCRIPT_LDFLAGS@ -_EXPAT_COMMENT_ATTR_INFO = @_EXPAT_COMMENT_ATTR_INFO@ _EXPAT_COMMENT_DTD_OR_GE = @_EXPAT_COMMENT_DTD_OR_GE@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ diff --git a/contrib/expat/README.md b/contrib/expat/README.md index 36e46a90fd23..1951645e8285 100644 --- a/contrib/expat/README.md +++ b/contrib/expat/README.md @@ -17,7 +17,7 @@ > Thank you! :heart: :pray: -# Expat, Release 2.8.5 +# Expat, Release 2.9.0 This is Expat, a C99 library for parsing [XML 1.0 Fourth Edition](https://www.w3.org/TR/2006/REC-xml-20060816/), started by diff --git a/contrib/expat/configure.ac b/contrib/expat/configure.ac index e8562dbc5fc1..6d80021cf0a9 100644 --- a/contrib/expat/configure.ac +++ b/contrib/expat/configure.ac @@ -103,9 +103,9 @@ dnl dnl If the API changes incompatibly set LIBAGE back to 0 dnl -LIBCURRENT=13 # sync -LIBREVISION=5 # with -LIBAGE=12 # CMakeLists.txt! +LIBCURRENT=14 # sync +LIBREVISION=0 # with +LIBAGE=13 # CMakeLists.txt! AC_CONFIG_HEADERS([expat_config.h]) AH_TOP([#ifndef EXPAT_CONFIG_H @@ -226,9 +226,11 @@ AM_CONDITIONAL([MINGW], [test x${EXPATCFG_ON_MINGW} = xyes]) dnl Note: Prefix "_INTERNAL_" here means exclusive use inside of file configure.ac AM_CONDITIONAL([UNICODE], [echo -- "${CPPFLAGS}${CFLAGS}" | ${FGREP} XML_UNICODE >/dev/null]) AM_CONDITIONAL([_INTERNAL_UNICODE_WCHAR_T], [echo -- "${CPPFLAGS}${CFLAGS}" | ${FGREP} XML_UNICODE_WCHAR_T >/dev/null]) -AM_CONDITIONAL([_INTERNAL_MIN_SIZE], [echo -- "${CPPFLAGS}${CFLAGS}" | ${FGREP} XML_MIN_SIZE >/dev/null]) AM_CONDITIONAL([_INTERNAL_LARGE_SIZE], [echo -- "${CPPFLAGS}${CFLAGS}" | ${FGREP} XML_LARGE_SIZE >/dev/null]) +AS_IF([echo -- "${CPPFLAGS}${CFLAGS}" | ${FGREP} XML_MIN_SIZE >/dev/null], + [AC_MSG_ERROR([Feature XML_MIN_SIZE has been removed. Please open a GitHub issue if you need it back.])]) + LT_LIB_M AC_ARG_WITH([arc4random], @@ -428,13 +430,11 @@ AS_IF([test "x${with_dev_urandom}" = "xyes"], AC_ARG_ENABLE([xml-attr-info], - [AS_HELP_STRING([--enable-xml-attr-info], - [Enable retrieving the byte offsets for attribute names and values @<:@default=no@:>@])], + [], [], [enable_xml_attr_info=no]) AS_IF([test "x${enable_xml_attr_info}" = "xyes"], - [AC_DEFINE([XML_ATTR_INFO], 1, - [Define to allow retrieving the byte offsets for attribute names and values.])]) + [AC_MSG_ERROR([Feature --enable-xml-attr-info has been removed. Please open a GitHub issue if you need it back.])]) AC_ARG_ENABLE([xml-context], AS_HELP_STRING([--enable-xml-context @<:@COUNT@:>@], @@ -495,21 +495,12 @@ dnl Configure CMake file templates dnl NOTE: The *_TRUE variables read here are Automake conditionals dnl that are either set to "" when enabled or to "#" when disabled dnl (because they are used to dynamically comment out certain things) -AS_IF([test "x${enable_xml_attr_info}" = xyes], - [EXPAT_ATTR_INFO=ON - _EXPAT_COMMENT_ATTR_INFO=" "], - [EXPAT_ATTR_INFO=OFF - _EXPAT_COMMENT_ATTR_INFO="#"]) -AC_SUBST([_EXPAT_COMMENT_ATTR_INFO]) EXPAT_DTD=ON _EXPAT_COMMENT_DTD_OR_GE=" " AC_SUBST([_EXPAT_COMMENT_DTD_OR_GE]) AS_IF([test "x${_INTERNAL_LARGE_SIZE_TRUE}" = x], [EXPAT_LARGE_SIZE=ON], [EXPAT_LARGE_SIZE=OFF]) -AS_IF([test "x${_INTERNAL_MIN_SIZE_TRUE}" = x], - [EXPAT_MIN_SIZE=ON], - [EXPAT_MIN_SIZE=OFF]) EXPAT_NS=ON AS_IF([test "x${enable_xml_context}" != xno], [EXPAT_CONTEXT_BYTES=${enable_xml_context}], @@ -525,10 +516,8 @@ LIBDIR_BASENAME="$(basename "${libdir}")" SO_MAJOR="$(expr "${LIBCURRENT}" - "${LIBAGE}")" SO_MINOR="${LIBAGE}" SO_PATCH="${LIBREVISION}" -AC_SUBST([EXPAT_ATTR_INFO]) AC_SUBST([EXPAT_DTD]) AC_SUBST([EXPAT_LARGE_SIZE]) -AC_SUBST([EXPAT_MIN_SIZE]) AC_SUBST([EXPAT_NS]) AC_SUBST([EXPAT_CONTEXT_BYTES]) AC_SUBST([EXPAT_CHAR_TYPE]) diff --git a/contrib/expat/doc/Makefile.in b/contrib/expat/doc/Makefile.in index 52a18ffb673f..afe0b8d5c814 100644 --- a/contrib/expat/doc/Makefile.in +++ b/contrib/expat/doc/Makefile.in @@ -234,12 +234,10 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ -EXPAT_ATTR_INFO = @EXPAT_ATTR_INFO@ EXPAT_CHAR_TYPE = @EXPAT_CHAR_TYPE@ EXPAT_CONTEXT_BYTES = @EXPAT_CONTEXT_BYTES@ EXPAT_DTD = @EXPAT_DTD@ EXPAT_LARGE_SIZE = @EXPAT_LARGE_SIZE@ -EXPAT_MIN_SIZE = @EXPAT_MIN_SIZE@ EXPAT_NS = @EXPAT_NS@ FGREP = @FGREP@ FILECMD = @FILECMD@ @@ -294,7 +292,6 @@ SO_PATCH = @SO_PATCH@ STRIP = @STRIP@ VERSION = @VERSION@ VSCRIPT_LDFLAGS = @VSCRIPT_LDFLAGS@ -_EXPAT_COMMENT_ATTR_INFO = @_EXPAT_COMMENT_ATTR_INFO@ _EXPAT_COMMENT_DTD_OR_GE = @_EXPAT_COMMENT_DTD_OR_GE@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ diff --git a/contrib/expat/doc/reference.html b/contrib/expat/doc/reference.html index 5bd9150ea78a..2f892fd20b82 100644 --- a/contrib/expat/doc/reference.html +++ b/contrib/expat/doc/reference.html @@ -53,7 +53,7 @@ <body> <div> <h1> - The Expat XML Parser <small>Release 2.8.5</small> + The Expat XML Parser <small>Release 2.9.0</small> </h1> </div> @@ -309,22 +309,76 @@ <li> <a href="#XML_GetCurrentByteIndex">XML_GetCurrentByteIndex</a> + (deprecated) + </li> + + <li> + <a href="#XML_GetCurrentByteIndex64">XML_GetCurrentByteIndex64</a> </li> <li> <a href="#XML_GetCurrentLineNumber">XML_GetCurrentLineNumber</a> + (deprecated) + </li> + + <li> + <a href="#XML_GetCurrentLineNumber64">XML_GetCurrentLineNumber64</a> </li> <li> <a href="#XML_GetCurrentColumnNumber">XML_GetCurrentColumnNumber</a> + (deprecated) + </li> + + <li> + <a href= + "#XML_GetCurrentColumnNumber64">XML_GetCurrentColumnNumber64</a> </li> <li> <a href="#XML_GetCurrentByteCount">XML_GetCurrentByteCount</a> + (deprecated) + </li> + + <li> + <a href="#XML_GetCurrentByteCount64">XML_GetCurrentByteCount64</a> </li> <li> - <a href="#XML_GetInputContext">XML_GetInputContext</a> + <a href="#XML_GetInputContext">XML_GetInputContext</a> (deprecated) + </li> + + <li> + <a href="#XML_GetInputContext64">XML_GetInputContext64</a> + </li> + </ul> + </li> + + <li> + <a href="#properties">Properties / Security Tuning</a> + <ul> + <li> + <a href="#XML_GetPropertyBool">XML_GetPropertyBool</a> + </li> + + <li> + <a href="#XML_GetPropertyDouble">XML_GetPropertyDouble</a> + </li> + + <li> + <a href="#XML_GetPropertyUInt64">XML_GetPropertyUInt64</a> + </li> + + <li> + <a href="#XML_SetPropertyBool">XML_SetPropertyBool</a> + </li> + + <li> + <a href="#XML_SetPropertyDouble">XML_SetPropertyDouble</a> + </li> + + <li> + <a href="#XML_SetPropertyUInt64">XML_SetPropertyUInt64</a> </li> </ul> </li> @@ -392,10 +446,6 @@ </li> <li> - <a href="#XML_GetAttributeInfo">XML_GetAttributeInfo</a> - </li> - - <li> <a href="#XML_SetEncoding">XML_SetEncoding</a> </li> @@ -751,19 +801,59 @@ make install </dd> <dt> - <a id="XML_LARGE_SIZE" name="XML_LARGE_SIZE">XML_LARGE_SIZE</a> + <a id="XML_LARGE_SIZE" name="XML_LARGE_SIZE">XML_LARGE_SIZE</a> (deprecated) </dt> <dd> - If defined, causes the <code>XML_Size</code> and <code>XML_Index</code> integer - types to be at least 64 bits in size. This is intended to support processing of - very large input streams, where the return values of <code><a href= - "#XML_GetCurrentByteIndex">XML_GetCurrentByteIndex</a></code>, <code><a href= - "#XML_GetCurrentLineNumber">XML_GetCurrentLineNumber</a></code> and - <code><a href= - "#XML_GetCurrentColumnNumber">XML_GetCurrentColumnNumber</a></code> could - overflow. It may not be supported by all compilers, and is turned off by - default. + <p> + If defined, causes the <code>XML_Size</code> and <code>XML_Index</code> + integer types to be at least 64 bits in size. This is intended to support + processing of very large input streams, where the return values of + <code><a href="#XML_GetCurrentByteIndex">XML_GetCurrentByteIndex</a></code>, + <code><a href="#XML_GetCurrentLineNumber">XML_GetCurrentLineNumber</a></code> + and <code><a href= + "#XML_GetCurrentColumnNumber">XML_GetCurrentColumnNumber</a></code> could + overflow. It may not be supported by all compilers, and is turned off by + default. + </p> + + <p> + Starting with Expat 2.9.0, there are 64bit versions of these functions, so + that relying on (non-default and uncommon) macro <code>XML_LARGE_SIZE</code> + is no longer needed. These functions are: + </p> + + <ul> + <li> + <code><a href= + "#XML_GetCurrentByteIndex64">XML_GetCurrentByteIndex64</a></code> + </li> + + <li> + <code><a href= + "#XML_GetCurrentColumnNumber64">XML_GetCurrentColumnNumber64</a></code> + </li> + + <li> + <code><a href= + "#XML_GetCurrentLineNumber64">XML_GetCurrentLineNumber64</a></code> + </li> + </ul> + + <p> + And there are two more that <code>XML_LARGE_SIZE</code> was not covering: + </p> + + <ul> + <li> + <code><a href= + "#XML_GetCurrentByteCount64">XML_GetCurrentByteCount64</a></code> + </li> + + <li> + <code><a href="#XML_GetInputContext64">XML_GetInputContext64</a></code> + </li> + </ul> </dd> <dt> @@ -790,16 +880,6 @@ make install the code that calls it; this is required to get all the right MSVC magic annotations correct. This is ignored on other platforms. </dd> - - <dt> - <a id="XML_ATTR_INFO" name="XML_ATTR_INFO">XML_ATTR_INFO</a> - </dt> - - <dd> - If defined, makes the additional function <code><a href= - "#XML_GetAttributeInfo">XML_GetAttributeInfo</a></code> available for reporting - attribute byte offsets. - </dd> </dl> <hr /> @@ -1708,6 +1788,17 @@ XML_ParseBuffer(XML_Parser p, </p> <p> + <strong>Note:</strong> It is the responsibility of the application code to pass + a value for <code>len</code> that does not exceed the length of the remaining + unparsed XML content that was previously copied into the buffer obtained from + <code><a href="#XML_GetBuffer">XML_GetBuffer</a></code>. The documentation of + <code><a href="#XML_GetBuffer">XML_GetBuffer</a></code> below has an <a href= + "#XML_GetBuffer">example of typical use</a> of functions <code><a href= + "#XML_GetBuffer">XML_GetBuffer</a></code> and <code><a href= + "#XML_ParseBuffer">XML_ParseBuffer</a></code> in tandem. + </p> + + <p> Negative values for <code>len</code> are rejected since Expat 2.6.3. </p> </div> @@ -2889,7 +2980,40 @@ enum XML_Error XMLCALL XML_GetErrorCode(XML_Parser p); </pre> <div class="fcndef"> - Return what type of error has occurred. + <p> + Return what type of error has occurred inside the main Expat parsing machinery. + </p> + + <p> + Only the following functions record the type of error for retrivial via + <code>XML_GetErrorCode</code>: + </p> + + <ul> + <li> + <code><a href="#XML_GetBuffer">XML_GetBuffer</a></code> + </li> + + <li> + <code><a href="#XML_Parse">XML_Parse</a></code> + </li> + + <li> + <code><a href="#XML_ParseBuffer">XML_ParseBuffer</a></code> + </li> + + <li> + <code><a href="#XML_ParserReset">XML_ParserReset</a></code> + </li> + + <li> + <code><a href="#XML_ResumeParser">XML_ResumeParser</a></code> + </li> + + <li> + <code><a href="#XML_StopParser">XML_StopParser</a></code> + </li> + </ul> </div> <h4 id="XML_ErrorString"> @@ -2907,13 +3031,18 @@ XML_ErrorString(enum XML_Error code); </div> <h4 id="XML_GetCurrentByteIndex"> - XML_GetCurrentByteIndex + XML_GetCurrentByteIndex (deprecated) </h4> <pre class="fcndec"> XML_Index XMLCALL XML_GetCurrentByteIndex(XML_Parser p); </pre> + <p> + <b>Note:</b> This function is deprecated, please use function <code><a href= + "#XML_GetCurrentByteIndex64">XML_GetCurrentByteIndex64</a></code>, instead. + </p> + <div class="fcndef"> Return the byte offset of the position. This always corresponds to the values returned by <code><a href= @@ -2928,14 +3057,36 @@ XML_GetCurrentByteIndex(XML_Parser p); "#XML_LARGE_SIZE">XML_LARGE_SIZE</a></code>. </p> + <h4 id="XML_GetCurrentByteIndex64"> + XML_GetCurrentByteIndex64 + </h4> + + <pre class="fcndec"> +/* Added in Expat 2.9.0. */ +int64_t XMLCALL +XML_GetCurrentByteIndex64(XML_Parser p); +</pre> + <div class="fcndef"> + Return the byte offset of the position. This always corresponds to the values + returned by <code><a href= + "#XML_GetCurrentLineNumber64">XML_GetCurrentLineNumber64</a></code> and + <code><a href= + "#XML_GetCurrentColumnNumber64">XML_GetCurrentColumnNumber64</a></code>. + </div> + <h4 id="XML_GetCurrentLineNumber"> - XML_GetCurrentLineNumber + XML_GetCurrentLineNumber (deprecated) </h4> <pre class="fcndec"> XML_Size XMLCALL XML_GetCurrentLineNumber(XML_Parser p); </pre> + <p> + <b>Note:</b> This function is deprecated, please use function <code><a href= + "#XML_GetCurrentLineNumber64">XML_GetCurrentLineNumber64</a></code>, instead. + </p> + <div class="fcndef"> Return the line number of the position. The first line is reported as <code>1</code>. @@ -2948,14 +3099,33 @@ XML_GetCurrentLineNumber(XML_Parser p); "#XML_LARGE_SIZE">XML_LARGE_SIZE</a></code>. </p> + <h4 id="XML_GetCurrentLineNumber64"> + XML_GetCurrentLineNumber64 + </h4> + + <pre class="fcndec"> +/* Added in Expat 2.9.0. */ +uint64_t XMLCALL +XML_GetCurrentLineNumber64(XML_Parser p); +</pre> + <div class="fcndef"> + Return the line number of the position. The first line is reported as + <code>1</code>. + </div> + <h4 id="XML_GetCurrentColumnNumber"> - XML_GetCurrentColumnNumber + XML_GetCurrentColumnNumber (deprecated) </h4> <pre class="fcndec"> XML_Size XMLCALL XML_GetCurrentColumnNumber(XML_Parser p); </pre> + <p> + <b>Note:</b> This function is deprecated, please use function <code><a href= + "#XML_GetCurrentColumnNumber64">XML_GetCurrentColumnNumber64</a></code>, instead. + </p> + <div class="fcndef"> Return the <em>offset</em>, from the beginning of the current line, of the position. The first column is reported as <code>0</code>. @@ -2968,14 +3138,54 @@ XML_GetCurrentColumnNumber(XML_Parser p); "#XML_LARGE_SIZE">XML_LARGE_SIZE</a></code>. </p> + <h4 id="XML_GetCurrentColumnNumber64"> + XML_GetCurrentColumnNumber64 + </h4> + + <pre class="fcndec"> +/* Added in Expat 2.9.0. */ +uint64_t XMLCALL +XML_GetCurrentColumnNumber64(XML_Parser p); +</pre> + <div class="fcndef"> + Return the <em>offset</em>, from the beginning of the current line, of the + position. The first column is reported as <code>0</code>. + </div> + <h4 id="XML_GetCurrentByteCount"> - XML_GetCurrentByteCount + XML_GetCurrentByteCount (deprecated) </h4> <pre class="fcndec"> int XMLCALL XML_GetCurrentByteCount(XML_Parser p); </pre> + <p> + <b>Note:</b> This function is deprecated, please use function <code><a href= + "#XML_GetCurrentByteCount64">XML_GetCurrentByteCount64</a></code>, instead. + </p> + + <div class="fcndef"> + Return the number of bytes in the current event. Returns <code>0</code> if the + event is inside a reference to an internal entity and for the end-tag event for + empty element tags (the later can be used to distinguish empty-element tags from + empty elements using separate start and end tags). + </div> + + <p> + <strong>Note:</strong> Type <code>int</code> is known to wrap around (on both + 32bit platforms and 64bit platforms). + </p> + + <h4 id="XML_GetCurrentByteCount64"> + XML_GetCurrentByteCount64 + </h4> + + <pre class="fcndec"> +/* Added in Expat 2.9.0. */ +uint64_t XMLCALL +XML_GetCurrentByteCount64(XML_Parser p); +</pre> <div class="fcndef"> Return the number of bytes in the current event. Returns <code>0</code> if the event is inside a reference to an internal entity and for the end-tag event for @@ -2984,7 +3194,7 @@ XML_GetCurrentByteCount(XML_Parser p); </div> <h4 id="XML_GetInputContext"> - XML_GetInputContext + XML_GetInputContext (deprecated) </h4> <pre class="fcndec"> @@ -2993,6 +3203,53 @@ XML_GetInputContext(XML_Parser p, int *offset, int *size); </pre> + <p> + <b>Note:</b> This function is deprecated, please use function <code><a href= + "#XML_GetInputContext64">XML_GetInputContext64</a></code>, instead. + </p> + + <div class="fcndef"> + <p> + Returns the parser's input buffer, sets the integer pointed at by + <code>offset</code> to the offset within this buffer of the current parse + position, and set the integer pointed at by <code>size</code> to the size of + the returned buffer. + </p> + + <p> + This should only be called from within a handler during an active parse and the + returned buffer should only be referred to from within the handler that made + the call. This input buffer contains the untranslated bytes of the input. + </p> + + <p> + Only a limited amount of context is kept, so if the event triggering a call + spans over a very large amount of input, the actual parse position may be + before the beginning of the buffer. + </p> + + <p> + If <code>XML_CONTEXT_BYTES</code> is zero, this will always return + <code>NULL</code>. + </p> + + <p> + <strong>Note:</strong> Type <code>int</code> is known to wrap around (on both + 32bit platforms and 64bit platforms). + </p> + </div> + + <h4 id="XML_GetInputContext64"> + XML_GetInputContext64 + </h4> + + <pre class="fcndec"> +/* Added in Expat 2.9.0. */ +const char * XMLCALL +XML_GetInputContext64(XML_Parser p, + int64_t *offset, + zint64_t *size); +</pre> <div class="fcndef"> <p> Returns the parser's input buffer, sets the integer pointed at by @@ -3020,10 +3277,389 @@ XML_GetInputContext(XML_Parser p, </div> <h3> + <a id="properties" name="properties">Properties / Security Tuning</a> + </h3> + + <p> + Expat 2.9.0 introduced a new Properties API. Think of properties as the control + knobs of a parser. The key motivations behind its introduction are: + </p> + + <ul> + <li>to allow Expat to add more properties — both security-related and non- + security ones — in the future (without need to also add new related getter and + setter functions for each of them as was the case in the past), + </li> + + <li>to allow users to read (not just to set) the current values, and + </li> + + <li>to allow users to distinuish the different sources of error beyond a mere + "did not work". + </li> + </ul> + + <p> + There is one setter function and one getter function — a pair — per supported + data type: + </p> + + <ul> + <li>For <code>XML_Bool</code>: + <ul> + <li> + <code><a href="#XML_GetPropertyBool">XML_GetPropertyBool</a></code> + </li> + + <li> + <code><a href="#XML_SetPropertyBool">XML_SetPropertyBool</a></code> + </li> + </ul> + </li> + + <li>For <code>double</code>: + <ul> + <li> + <code><a href="#XML_GetPropertyDouble">XML_GetPropertyDouble</a></code> + </li> + + <li> + <code><a href="#XML_SetPropertyDouble">XML_SetPropertyDouble</a></code> + </li> + </ul> + </li> + + <li>For <code>uint64_t</code>: + <ul> + <li> + <code><a href="#XML_GetPropertyUInt64">XML_GetPropertyUInt64</a></code> + </li> + + <li> + <code><a href="#XML_SetPropertyUInt64">XML_SetPropertyUInt64</a></code> + </li> + </ul> + </li> + </ul> + + <p> + They all share these two key enums: + </p> + + <h4 id="XML_Parser_Property"> + XML_Parser_Property + </h4> + + <pre> +/* Added in Expat 2.9.0. */ +enum XML_Parser_Property { +# if XML_GE == 1 + XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD = 1, // of type `uint64_t` + XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION = 2, // of type `double` + XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD = 3, // of type `uint64_t` + XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION = 4, // of type `double` +# endif + XML_PROP_REPARSE_DEFERRAL_ENABLED = 5, // of type `XML_Bool` + /* more properties upcoming here */ +};</pre> + <h4 id="XML_Prop_Error"> + XML_Prop_Error + </h4> + + <pre> +/* Added in 2.9.0. */ +enum XML_Prop_Error { + XML_PROP_ERROR_NONE = 0, // i.e. success + + XML_PROP_ERROR_INVALID_KEY = 1, // i.e. the property is not known at all + XML_PROP_ERROR_INVALID_TYPE = 2, // i.e. the property is known but expects a + // different type (so a different + // getter/setter would need to be called) + XML_PROP_ERROR_INVALID_VALUE = 3, // i.e. the value is invalid (with a setter + // function) or a NULL-pointer (with a + // getter function) + + XML_PROP_ERROR_PARSER_NULL = 4, // i.e. the parser argument is NULL + XML_PROP_ERROR_PARSER_NOT_ROOT = 5, // i.e. the parser is not a root parser + // but a subparser (and a root parser is + // needed) + + /* potentially more error codes upcoming here */ +};</pre> + <p> + Let us look at these functions in more detail: + </p> + + <h4 id="XML_GetPropertyBool"> + XML_GetPropertyBool + </h4> + + <pre class="fcndec"> +/* Added in Expat 2.9.0. */ +enum XML_Prop_Error +XML_GetPropertyBool(XML_Parser parser, enum XML_Parser_Property property, + XML_Bool *value); +</pre> + <div class="fcndef"> + <p> + Writes the current value of boolean property <code>property</code> of parser + <code>parser</code> to output variable <code>value</code>. Supported properties + are: + </p> + + <ul> + <li> + <code>XML_PROP_REPARSE_DEFERRAL_ENABLED</code> — whether <a href= + "#XML_SetReparseDeferralEnabled">reparse deferral</a> is active or not + </li> + </ul> + + <p> + Both parameters <code>parser</code> and <code>value</code> must be + non-<code>NULL</code>. On success <code>XML_PROP_ERROR_NONE</code> is returned; + on error one of the other variants of <a href= + "#XML_Prop_Error">XML_Prop_Error</a> is returned. + </p> + + <p> + <strong>Note:</strong> There may be more error codes introduced into <a href= + "#XML_Prop_Error">XML_Prop_Error</a> in the future, so user code must be robust + towards error codes from the future at runtime that were not known at compile + time. + </p> + </div> + + <h4 id="XML_GetPropertyDouble"> + XML_GetPropertyDouble + </h4> + + <pre class="fcndec"> +/* Added in Expat 2.9.0. */ +enum XML_Prop_Error +XML_GetPropertyDouble(XML_Parser parser, enum XML_Parser_Property property, + double *value); +</pre> + <div class="fcndef"> + <p> + Writes the current value of floating point property <code>property</code> of + parser <code>parser</code> to output variable <code>value</code>. Supported + properties are: + </p> + + <ul> + <li> + <code>XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION</code> — the maximum + tolerated amplification with the <a href= + "#XML_SetAllocTrackerMaximumAmplification">allocation tracker</a> + </li> + + <li> + <code>XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION</code> — the maximum + tolerated amplification with <a href= + "#XML_SetBillionLaughsAttackProtectionMaximumAmplification">billion laughs + attack protection</a> + </li> + </ul> + + <p> + Both parameters <code>parser</code> and <code>value</code> must be + non-<code>NULL</code>. On success <code>XML_PROP_ERROR_NONE</code> is returned; + on error one of the other variants of <a href= + "#XML_Prop_Error">XML_Prop_Error</a> is returned. + </p> + + <p> + <strong>Note:</strong> There may be more error codes introduced into <a href= + "#XML_Prop_Error">XML_Prop_Error</a> in the future, so user code must be robust + towards error codes from the future at runtime that were not known at compile + time. + </p> + </div> + + <h4 id="XML_GetPropertyUInt64"> + XML_GetPropertyUInt64 + </h4> + + <pre class="fcndec"> +/* Added in Expat 2.9.0. */ +enum XML_Prop_Error +XML_GetPropertyUInt64(XML_Parser parser, enum XML_Parser_Property property, + uint64_t *value); +</pre> + <div class="fcndef"> + <p> + Writes the current value of integral property <code>property</code> of parser + <code>parser</code> to output variable <code>value</code>. Supported properties + are: + </p> + + <ul> + <li> + <code>XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD</code> — the activation + threshold in bytes with the <a href= + "#XML_SetAllocTrackerActivationThreshold">allocation tracker</a> + </li> + + <li> + <code>XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD</code> — the activation + threshold in bytes with <a href= + "#XML_SetBillionLaughsAttackProtectionActivationThreshold">billion laughs + attack protection</a> + </li> + </ul> + + <p> + Both parameters <code>parser</code> and <code>value</code> must be + non-<code>NULL</code>. On success <code>XML_PROP_ERROR_NONE</code> is returned; + on error one of the other variants of <a href= + "#XML_Prop_Error">XML_Prop_Error</a> is returned. + </p> + + <p> + <strong>Note:</strong> There may be more error codes introduced into <a href= + "#XML_Prop_Error">XML_Prop_Error</a> in the future, so user code must be robust + towards error codes from the future at runtime that were not known at compile + time. + </p> + </div> + + <h3> <a id="attack-protection" name="attack-protection">Attack Protection</a><a id= "billion-laughs" name="billion-laughs"></a> </h3> + <h4 id="XML_SetPropertyBool"> + XML_SetPropertyBool + </h4> + + <pre class="fcndec"> +/* Added in Expat 2.9.0. */ +enum XML_Prop_Error +XML_SetPropertyBool(XML_Parser parser, enum XML_Parser_Property property, + XML_Bool value); +</pre> + <div class="fcndef"> + <p> + Applies the given value <code>value</code> to boolean property + <code>property</code> of parser <code>parser</code>. Supported properties are: + </p> + + <ul> + <li> + <code>XML_PROP_REPARSE_DEFERRAL_ENABLED</code> — whether <a href= + "#XML_SetReparseDeferralEnabled">reparse deferral</a> is active or not + </li> + </ul> + + <p> + Parameter <code>parser</code> must be non-<code>NULL</code>. On success + <code>XML_PROP_ERROR_NONE</code> is returned; on error one of the other + variants of <a href="#XML_Prop_Error">XML_Prop_Error</a> is returned. + </p> + + <p> + <strong>Note:</strong> There may be more error codes introduced into <a href= + "#XML_Prop_Error">XML_Prop_Error</a> in the future, so user code must be robust + towards error codes from the future at runtime that were not known at compile + time. + </p> + </div> + + <h4 id="XML_SetPropertyDouble"> + XML_SetPropertyDouble + </h4> + + <pre class="fcndec"> +/* Added in Expat 2.9.0. */ +enum XML_Prop_Error +XML_SetPropertyDouble(XML_Parser parser, enum XML_Parser_Property property, + double value); +</pre> + <div class="fcndef"> + <p> + Applies the given value <code>value</code> to floating point property + <code>property</code> of parser <code>parser</code>. Supported properties are: + </p> + + <ul> + <li> + <code>XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION</code> — the maximum + tolerated amplification with the <a href= + "#XML_SetAllocTrackerMaximumAmplification">allocation tracker</a> + </li> + + <li> + <code>XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION</code> — the maximum + tolerated amplification with <a href= + "#XML_SetBillionLaughsAttackProtectionMaximumAmplification">billion laughs + attack protection</a> + </li> + </ul> + + <p> + Value <code>value</code> may or may not be cast to <code>float</code> + internally. + </p> + + <p> + Parameter <code>parser</code> must be non-<code>NULL</code>. On success + <code>XML_PROP_ERROR_NONE</code> is returned; on error one of the other + variants of <a href="#XML_Prop_Error">XML_Prop_Error</a> is returned. + </p> + + <p> + <strong>Note:</strong> There may be more error codes introduced into <a href= + "#XML_Prop_Error">XML_Prop_Error</a> in the future, so user code must be robust + towards error codes from the future at runtime that were not known at compile + time. + </p> + </div> + + <h4 id="XML_SetPropertyUInt64"> + XML_SetPropertyUInt64 + </h4> + + <pre class="fcndec"> +/* Added in Expat 2.9.0. */ +enum XML_Prop_Error +XML_SetPropertyUInt64(XML_Parser parser, enum XML_Parser_Property property, + uint64_t value); +</pre> + <div class="fcndef"> + <p> + Applies the given value <code>value</code> to integral property + <code>property</code> of parser <code>parser</code>. Supported properties are: + </p> + + <ul> + <li> + <code>XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD</code> — the activation + threshold in bytes with the <a href= + "#XML_SetAllocTrackerActivationThreshold">allocation tracker</a> + </li> + + <li> + <code>XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD</code> — the activation + threshold in bytes with <a href= + "#XML_SetBillionLaughsAttackProtectionActivationThreshold">billion laughs + attack protection</a> + </li> + </ul> + + <p> + Parameter <code>parser</code> must be non-<code>NULL</code>. On success + <code>XML_PROP_ERROR_NONE</code> is returned; on error one of the other + variants of <a href="#XML_Prop_Error">XML_Prop_Error</a> is returned. + </p> + + <p> + <strong>Note:</strong> There may be more error codes introduced into <a href= + "#XML_Prop_Error">XML_Prop_Error</a> in the future, so user code must be robust + towards error codes from the future at runtime that were not known at compile + time. + </p> + </div> + <h4 id="XML_SetBillionLaughsAttackProtectionMaximumAmplification"> XML_SetBillionLaughsAttackProtectionMaximumAmplification </h4> @@ -3405,38 +4041,6 @@ XML_GetIdAttributeIndex(XML_Parser p); means the current call. </div> - <h4 id="XML_GetAttributeInfo"> - XML_GetAttributeInfo - </h4> - - <pre class="fcndec"> -const XML_AttrInfo * XMLCALL -XML_GetAttributeInfo(XML_Parser parser); -</pre> - - <pre class="signature"> -typedef struct { - XML_Index nameStart; /* Offset to beginning of the attribute name. */ - XML_Index nameEnd; /* Offset after the attribute name's last byte. */ - XML_Index valueStart; /* Offset to beginning of the attribute value. */ - XML_Index valueEnd; /* Offset after the attribute value's last byte. */ -} XML_AttrInfo; -</pre> - <div class="fcndef"> - Returns an array of <code>XML_AttrInfo</code> structures for the attribute/value - pairs passed in the last call to the <code>XML_StartElementHandler</code> that - were specified in the start-tag rather than defaulted. Each attribute/value pair - counts as 1; thus the number of entries in the array is - <code>XML_GetSpecifiedAttributeCount(parser) / 2</code>. - </div> - - <p> - <strong>Note:</strong> Type <code>XML_Index</code> is known to wrap around on - 32bit platforms and 64bit Windows unless Expat has been compiled with - (non-default and uncommon) macro <code><a href= - "#XML_LARGE_SIZE">XML_LARGE_SIZE</a></code>. - </p> - <h4 id="XML_SetEncoding"> XML_SetEncoding </h4> @@ -3495,6 +4099,11 @@ int XMLCALL XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt); </pre> + <p> + <b>Note:</b> This function is deprecated, please use function <code><a href= + "#XML_SetHashSalt16Bytes">XML_SetHashSalt16Bytes</a></code>, instead. + </p> + <div class="fcndef"> Sets the hash salt to use for internal hash calculations. Helps in preventing DoS attacks based on predicting hash function behavior. In order to have an effect @@ -3502,15 +4111,13 @@ XML_SetHashSalt(XML_Parser parser, called after <code>XML_Parse</code> or <code>XML_ParseBuffer</code> or when <code>parser</code> is <code>NULL</code>. <p> - <b>Note:</b> Function <code>XML_SetHashSalt</code> is - <strong>deprecated</strong>. Please use function <code><a href= - "#XML_SetHashSalt16Bytes">XML_SetHashSalt16Bytes</a></code> instead for better - security. <code>XML_SetHashSalt</code> only provides 4 to 8 bytes of entropy - (depending on the size of type <code>unsigned long</code>) while the SipHash - implementation used by Expat can leverage up to 16 bytes of entropy — at least - twice as much. Function <code><a href= + <b>Note:</b> Function <code>XML_SetHashSalt</code> only provides 4 to 8 bytes + of entropy (depending on the size of type <code>unsigned long</code>) while the + SipHash implementation used by Expat can leverage up to 16 bytes of entropy — + at least twice as much. Function <code><a href= "#XML_SetHashSalt16Bytes">XML_SetHashSalt16Bytes</a></code> of Expat >=2.8.0 - (and where backported) matches the amount of entropy supported by SipHash. + (and where backported) with better security matches the amount of entropy + supported by SipHash. </p> <p> @@ -3710,6 +4317,7 @@ enum XML_FeatureEnum { XML_FEATURE_UNICODE_WCHAR_T, XML_FEATURE_DTD, XML_FEATURE_CONTEXT_BYTES, + /* Added in Expat 1.95.5, removed in Expat 2.9.0. */ XML_FEATURE_MIN_SIZE, XML_FEATURE_SIZEOF_XML_CHAR, XML_FEATURE_SIZEOF_XML_LCHAR, @@ -3717,7 +4325,7 @@ enum XML_FeatureEnum { XML_FEATURE_NS, /* Added in Expat 2.0.1. */ XML_FEATURE_LARGE_SIZE, - /* Added in Expat 2.1.0. */ + /* Added in Expat 2.1.0, removed in Expat 2.9.0. */ XML_FEATURE_ATTR_INFO, /* Added in Expat 2.4.0. */ XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT, diff --git a/contrib/expat/doc/xmlwf.1 b/contrib/expat/doc/xmlwf.1 index e9b6a2fe4610..22ca1d387b5f 100644 --- a/contrib/expat/doc/xmlwf.1 +++ b/contrib/expat/doc/xmlwf.1 @@ -5,7 +5,7 @@ \\$2 \(la\\$1\(ra\\$3 .. .if \n(.g .mso www.tmac -.TH XMLWF 1 "September 22, 2026" "" "" +.TH XMLWF 1 "October 5, 2026" "" "" .SH NAME xmlwf \- Determines if an XML document is well-formed .SH SYNOPSIS diff --git a/contrib/expat/doc/xmlwf.xml b/contrib/expat/doc/xmlwf.xml index e7a2664b7e42..06880749583b 100644 --- a/contrib/expat/doc/xmlwf.xml +++ b/contrib/expat/doc/xmlwf.xml @@ -21,7 +21,7 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [ <!ENTITY dhfirstname "<firstname>Scott</firstname>"> <!ENTITY dhsurname "<surname>Bronson</surname>"> - <!ENTITY dhdate "<date>September 22, 2026</date>"> + <!ENTITY dhdate "<date>October 5, 2026</date>"> <!-- Please adjust this^^ date whenever cutting a new release. --> <!ENTITY dhsection "<manvolnum>1</manvolnum>"> <!ENTITY dhemail "<email>bronson@rinspin.com</email>"> diff --git a/contrib/expat/examples/Makefile.in b/contrib/expat/examples/Makefile.in index 4ef878f7867c..d1973eeab7b0 100644 --- a/contrib/expat/examples/Makefile.in +++ b/contrib/expat/examples/Makefile.in @@ -262,12 +262,10 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ -EXPAT_ATTR_INFO = @EXPAT_ATTR_INFO@ EXPAT_CHAR_TYPE = @EXPAT_CHAR_TYPE@ EXPAT_CONTEXT_BYTES = @EXPAT_CONTEXT_BYTES@ EXPAT_DTD = @EXPAT_DTD@ EXPAT_LARGE_SIZE = @EXPAT_LARGE_SIZE@ -EXPAT_MIN_SIZE = @EXPAT_MIN_SIZE@ EXPAT_NS = @EXPAT_NS@ FGREP = @FGREP@ FILECMD = @FILECMD@ @@ -322,7 +320,6 @@ SO_PATCH = @SO_PATCH@ STRIP = @STRIP@ VERSION = @VERSION@ VSCRIPT_LDFLAGS = @VSCRIPT_LDFLAGS@ -_EXPAT_COMMENT_ATTR_INFO = @_EXPAT_COMMENT_ATTR_INFO@ _EXPAT_COMMENT_DTD_OR_GE = @_EXPAT_COMMENT_DTD_OR_GE@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ diff --git a/contrib/expat/examples/element_declarations.c b/contrib/expat/examples/element_declarations.c index ea790f4932b4..3d010d341cdc 100644 --- a/contrib/expat/examples/element_declarations.c +++ b/contrib/expat/examples/element_declarations.c @@ -12,7 +12,7 @@ Copyright (c) 2001-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net> Copyright (c) 2004-2006 Karl Waclawek <karl@waclawek.net> Copyright (c) 2005-2007 Steven Solie <steven@solie.ca> - Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org> + Copyright (c) 2016-2026 Sebastian Pipping <sebastian@pipping.org> Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> Copyright (c) 2019 Zhongyuan Zhou <zhouzhongyuan@huawei.com> Copyright (c) 2024 Hanno Böck <hanno@gentoo.org> @@ -41,17 +41,12 @@ SPDX-License-Identifier: MIT */ +#include <inttypes.h> // PRIu64 #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <expat.h> -#ifdef XML_LARGE_SIZE -# define XML_FMT_INT_MOD "ll" -#else -# define XML_FMT_INT_MOD "l" -#endif - #ifdef XML_UNICODE_WCHAR_T # define XML_FMT_STR "ls" #else @@ -225,9 +220,8 @@ main(void) { if (errorCode == XML_ERROR_ABORTED) { errorCode = XML_ERROR_NO_MEMORY; } - fprintf(stderr, - "Parse error at line %" XML_FMT_INT_MOD "u:\n%" XML_FMT_STR "\n", - XML_GetCurrentLineNumber(parser), XML_ErrorString(errorCode)); + fprintf(stderr, "Parse error at line %" PRIu64 ":\n%" XML_FMT_STR "\n", + XML_GetCurrentLineNumber64(parser), XML_ErrorString(errorCode)); XML_ParserFree(parser); return 1; } diff --git a/contrib/expat/examples/elements.c b/contrib/expat/examples/elements.c index ef7baeae5646..7df0d1940a19 100644 --- a/contrib/expat/examples/elements.c +++ b/contrib/expat/examples/elements.c @@ -14,7 +14,7 @@ Copyright (c) 2001-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net> Copyright (c) 2004-2006 Karl Waclawek <karl@waclawek.net> Copyright (c) 2005-2007 Steven Solie <steven@solie.ca> - Copyright (c) 2016-2022 Sebastian Pipping <sebastian@pipping.org> + Copyright (c) 2016-2026 Sebastian Pipping <sebastian@pipping.org> Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> Copyright (c) 2019 Zhongyuan Zhou <zhouzhongyuan@huawei.com> Licensed under the MIT license: @@ -41,15 +41,10 @@ SPDX-License-Identifier: MIT */ +#include <inttypes.h> // PRIu64 #include <stdio.h> #include <expat.h> -#ifdef XML_LARGE_SIZE -# define XML_FMT_INT_MOD "ll" -#else -# define XML_FMT_INT_MOD "l" -#endif - #ifdef XML_UNICODE_WCHAR_T # define XML_FMT_STR "ls" #else @@ -109,9 +104,8 @@ main(void) { done = feof(stdin); if (XML_ParseBuffer(parser, (int)len, done) == XML_STATUS_ERROR) { - fprintf(stderr, - "Parse error at line %" XML_FMT_INT_MOD "u:\n%" XML_FMT_STR "\n", - XML_GetCurrentLineNumber(parser), + fprintf(stderr, "Parse error at line %" PRIu64 ":\n%" XML_FMT_STR "\n", + XML_GetCurrentLineNumber64(parser), XML_ErrorString(XML_GetErrorCode(parser))); XML_ParserFree(parser); return 1; diff --git a/contrib/expat/examples/outline.c b/contrib/expat/examples/outline.c index 3168fab612cc..ba9bea447599 100644 --- a/contrib/expat/examples/outline.c +++ b/contrib/expat/examples/outline.c @@ -12,7 +12,7 @@ Copyright (c) 2001-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net> Copyright (c) 2005-2007 Steven Solie <steven@solie.ca> Copyright (c) 2005-2006 Karl Waclawek <karl@waclawek.net> - Copyright (c) 2016-2022 Sebastian Pipping <sebastian@pipping.org> + Copyright (c) 2016-2026 Sebastian Pipping <sebastian@pipping.org> Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> Licensed under the MIT license: @@ -38,15 +38,10 @@ SPDX-License-Identifier: MIT */ +#include <inttypes.h> // PRIu64 #include <stdio.h> #include <expat.h> -#ifdef XML_LARGE_SIZE -# define XML_FMT_INT_MOD "ll" -#else -# define XML_FMT_INT_MOD "l" -#endif - #ifdef XML_UNICODE_WCHAR_T # define XML_FMT_STR "ls" #else @@ -112,9 +107,8 @@ main(void) { done = feof(stdin); if (XML_ParseBuffer(parser, (int)len, done) == XML_STATUS_ERROR) { - fprintf(stderr, - "Parse error at line %" XML_FMT_INT_MOD "u:\n%" XML_FMT_STR "\n", - XML_GetCurrentLineNumber(parser), + fprintf(stderr, "Parse error at line %" PRIu64 ":\n%" XML_FMT_STR "\n", + XML_GetCurrentLineNumber64(parser), XML_ErrorString(XML_GetErrorCode(parser))); XML_ParserFree(parser); return 1; diff --git a/contrib/expat/expat_config.h.in b/contrib/expat/expat_config.h.in index 4d7d732e8052..b786029da5e8 100644 --- a/contrib/expat/expat_config.h.in +++ b/contrib/expat/expat_config.h.in @@ -113,10 +113,6 @@ # endif #endif -/* Define to allow retrieving the byte offsets for attribute names and values. - */ -#undef XML_ATTR_INFO - /* Define to specify how much context to retain around the current parse point, 0 to disable. */ #undef XML_CONTEXT_BYTES diff --git a/contrib/expat/fuzz/xml_parse_fuzzer.c b/contrib/expat/fuzz/xml_parse_fuzzer.c index 1eb0ad299628..8e9dfd79513d 100644 --- a/contrib/expat/fuzz/xml_parse_fuzzer.c +++ b/contrib/expat/fuzz/xml_parse_fuzzer.c @@ -79,7 +79,7 @@ ParseOneInput(XML_Parser p, const uint8_t *data, size_t size) { if (XML_Parse(p, (const XML_Char *)data, (int)size, 1) == XML_STATUS_ERROR) { XML_ErrorString(XML_GetErrorCode(p)); } - XML_GetCurrentLineNumber(p); + XML_GetCurrentLineNumber64(p); if (size % 2) { XML_ParserReset(p, NULL); } diff --git a/contrib/expat/fuzz/xml_parsebuffer_fuzzer.c b/contrib/expat/fuzz/xml_parsebuffer_fuzzer.c index a854f6706396..eec39241e222 100644 --- a/contrib/expat/fuzz/xml_parsebuffer_fuzzer.c +++ b/contrib/expat/fuzz/xml_parsebuffer_fuzzer.c @@ -87,7 +87,7 @@ ParseOneInput(XML_Parser p, const uint8_t *data, size_t size) { if (XML_ParseBuffer(p, (int)size, 1) == XML_STATUS_ERROR) { XML_ErrorString(XML_GetErrorCode(p)); } - XML_GetCurrentLineNumber(p); + XML_GetCurrentLineNumber64(p); if (size % 2) { XML_ParserReset(p, NULL); } diff --git a/contrib/expat/lib/Makefile.am b/contrib/expat/lib/Makefile.am index 6b0d0af4e3c5..e4211b4dd3f9 100644 --- a/contrib/expat/lib/Makefile.am +++ b/contrib/expat/lib/Makefile.am @@ -53,6 +53,7 @@ libexpat_la_LDFLAGS += $(VSCRIPT_LDFLAGS),@builddir@/libexpat.map endif libexpat_la_SOURCES = \ + xcs.c \ xmlparse.c \ xmltok.c \ xmlrole.c @@ -125,7 +126,7 @@ EXTRA_DIST = \ siphash.h \ utf8tab.h \ winconfig.h \ - xcsinc.c \ + xcs.h \ xmlrole.h \ xmltok.h \ xmltok_impl.c \ diff --git a/contrib/expat/lib/Makefile.in b/contrib/expat/lib/Makefile.in index 58b19912b596..4e5bb0bfd966 100644 --- a/contrib/expat/lib/Makefile.in +++ b/contrib/expat/lib/Makefile.in @@ -206,7 +206,7 @@ am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(docdir)" \ "$(DESTDIR)$(includedir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) libexpat_la_LIBADD = -am__libexpat_la_SOURCES_DIST = xmlparse.c xmltok.c xmlrole.c \ +am__libexpat_la_SOURCES_DIST = xcs.c xmlparse.c xmltok.c xmlrole.c \ random_arc4random.c random_arc4random.h \ random_arc4random_buf.c random_arc4random_buf.h \ random_dev_urandom.c random_dev_urandom.h random_getentropy.c \ @@ -218,7 +218,7 @@ am__libexpat_la_SOURCES_DIST = xmlparse.c xmltok.c xmlrole.c \ @WITH_GETENTROPY_TRUE@am__objects_4 = random_getentropy.lo @WITH_EITHER_GETRANDOM_TRUE@am__objects_5 = random_getrandom.lo @MINGW_TRUE@am__objects_6 = random_rand_s.lo -am_libexpat_la_OBJECTS = xmlparse.lo xmltok.lo xmlrole.lo \ +am_libexpat_la_OBJECTS = xcs.lo xmlparse.lo xmltok.lo xmlrole.lo \ $(am__objects_1) $(am__objects_2) $(am__objects_3) \ $(am__objects_4) $(am__objects_5) $(am__objects_6) libexpat_la_OBJECTS = $(am_libexpat_la_OBJECTS) @@ -230,7 +230,7 @@ libexpat_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libexpat_la_LDFLAGS) $(LDFLAGS) -o $@ libtestpat_la_LIBADD = -am__libtestpat_la_SOURCES_DIST = xmlparse.c xmltok.c xmlrole.c \ +am__libtestpat_la_SOURCES_DIST = xcs.c xmlparse.c xmltok.c xmlrole.c \ random_arc4random.c random_arc4random.h \ random_arc4random_buf.c random_arc4random_buf.h \ random_dev_urandom.c random_dev_urandom.h random_getentropy.c \ @@ -245,10 +245,10 @@ am__libtestpat_la_SOURCES_DIST = xmlparse.c xmltok.c xmlrole.c \ @WITH_EITHER_GETRANDOM_TRUE@am__objects_11 = \ @WITH_EITHER_GETRANDOM_TRUE@ libtestpat_la-random_getrandom.lo @MINGW_TRUE@am__objects_12 = libtestpat_la-random_rand_s.lo -am__objects_13 = libtestpat_la-xmlparse.lo libtestpat_la-xmltok.lo \ - libtestpat_la-xmlrole.lo $(am__objects_7) $(am__objects_8) \ - $(am__objects_9) $(am__objects_10) $(am__objects_11) \ - $(am__objects_12) +am__objects_13 = libtestpat_la-xcs.lo libtestpat_la-xmlparse.lo \ + libtestpat_la-xmltok.lo libtestpat_la-xmlrole.lo \ + $(am__objects_7) $(am__objects_8) $(am__objects_9) \ + $(am__objects_10) $(am__objects_11) $(am__objects_12) @WITH_TESTS_TRUE@am_libtestpat_la_OBJECTS = $(am__objects_13) libtestpat_la_OBJECTS = $(am_libtestpat_la_OBJECTS) @WITH_TESTS_TRUE@am_libtestpat_la_rpath = @@ -273,6 +273,7 @@ am__depfiles_remade = ./$(DEPDIR)/libtestpat_la-random_arc4random.Plo \ ./$(DEPDIR)/libtestpat_la-random_getentropy.Plo \ ./$(DEPDIR)/libtestpat_la-random_getrandom.Plo \ ./$(DEPDIR)/libtestpat_la-random_rand_s.Plo \ + ./$(DEPDIR)/libtestpat_la-xcs.Plo \ ./$(DEPDIR)/libtestpat_la-xmlparse.Plo \ ./$(DEPDIR)/libtestpat_la-xmlrole.Plo \ ./$(DEPDIR)/libtestpat_la-xmltok.Plo \ @@ -281,8 +282,8 @@ am__depfiles_remade = ./$(DEPDIR)/libtestpat_la-random_arc4random.Plo \ ./$(DEPDIR)/random_dev_urandom.Plo \ ./$(DEPDIR)/random_getentropy.Plo \ ./$(DEPDIR)/random_getrandom.Plo ./$(DEPDIR)/random_rand_s.Plo \ - ./$(DEPDIR)/xmlparse.Plo ./$(DEPDIR)/xmlrole.Plo \ - ./$(DEPDIR)/xmltok.Plo + ./$(DEPDIR)/xcs.Plo ./$(DEPDIR)/xmlparse.Plo \ + ./$(DEPDIR)/xmlrole.Plo ./$(DEPDIR)/xmltok.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @@ -369,12 +370,10 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ -EXPAT_ATTR_INFO = @EXPAT_ATTR_INFO@ EXPAT_CHAR_TYPE = @EXPAT_CHAR_TYPE@ EXPAT_CONTEXT_BYTES = @EXPAT_CONTEXT_BYTES@ EXPAT_DTD = @EXPAT_DTD@ EXPAT_LARGE_SIZE = @EXPAT_LARGE_SIZE@ -EXPAT_MIN_SIZE = @EXPAT_MIN_SIZE@ EXPAT_NS = @EXPAT_NS@ FGREP = @FGREP@ FILECMD = @FILECMD@ @@ -429,7 +428,6 @@ SO_PATCH = @SO_PATCH@ STRIP = @STRIP@ VERSION = @VERSION@ VSCRIPT_LDFLAGS = @VSCRIPT_LDFLAGS@ -_EXPAT_COMMENT_ATTR_INFO = @_EXPAT_COMMENT_ATTR_INFO@ _EXPAT_COMMENT_DTD_OR_GE = @_EXPAT_COMMENT_DTD_OR_GE@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ @@ -497,9 +495,9 @@ lib_LTLIBRARIES = libexpat.la @WITH_TESTS_TRUE@noinst_LTLIBRARIES = libtestpat.la libexpat_la_LDFLAGS = @AM_LDFLAGS@ @LIBM@ -no-undefined -version-info \ @LIBCURRENT@:@LIBREVISION@:@LIBAGE@ $(am__append_1) -libexpat_la_SOURCES = xmlparse.c xmltok.c xmlrole.c $(am__append_2) \ - $(am__append_3) $(am__append_4) $(am__append_5) \ - $(am__append_6) $(am__append_7) +libexpat_la_SOURCES = xcs.c xmlparse.c xmltok.c xmlrole.c \ + $(am__append_2) $(am__append_3) $(am__append_4) \ + $(am__append_5) $(am__append_6) $(am__append_7) @WITH_TESTS_TRUE@libtestpat_la_CPPFLAGS = -DXML_TESTING @WITH_TESTS_TRUE@libtestpat_la_SOURCES = $(libexpat_la_SOURCES) doc_DATA = \ @@ -522,7 +520,7 @@ EXTRA_DIST = \ siphash.h \ utf8tab.h \ winconfig.h \ - xcsinc.c \ + xcs.h \ xmlrole.h \ xmltok.h \ xmltok_impl.c \ @@ -625,6 +623,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtestpat_la-random_getentropy.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtestpat_la-random_getrandom.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtestpat_la-random_rand_s.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtestpat_la-xcs.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtestpat_la-xmlparse.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtestpat_la-xmlrole.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtestpat_la-xmltok.Plo@am__quote@ # am--include-marker @@ -634,6 +633,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random_getentropy.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random_getrandom.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random_rand_s.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xcs.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlparse.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlrole.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmltok.Plo@am__quote@ # am--include-marker @@ -668,6 +668,13 @@ am--depfiles: $(am__depfiles_remade) @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< +libtestpat_la-xcs.lo: xcs.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestpat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libtestpat_la-xcs.lo -MD -MP -MF $(DEPDIR)/libtestpat_la-xcs.Tpo -c -o libtestpat_la-xcs.lo `test -f 'xcs.c' || echo '$(srcdir)/'`xcs.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libtestpat_la-xcs.Tpo $(DEPDIR)/libtestpat_la-xcs.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xcs.c' object='libtestpat_la-xcs.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestpat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libtestpat_la-xcs.lo `test -f 'xcs.c' || echo '$(srcdir)/'`xcs.c + libtestpat_la-xmlparse.lo: xmlparse.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestpat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libtestpat_la-xmlparse.lo -MD -MP -MF $(DEPDIR)/libtestpat_la-xmlparse.Tpo -c -o libtestpat_la-xmlparse.lo `test -f 'xmlparse.c' || echo '$(srcdir)/'`xmlparse.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libtestpat_la-xmlparse.Tpo $(DEPDIR)/libtestpat_la-xmlparse.Plo @@ -914,6 +921,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/libtestpat_la-random_getentropy.Plo -rm -f ./$(DEPDIR)/libtestpat_la-random_getrandom.Plo -rm -f ./$(DEPDIR)/libtestpat_la-random_rand_s.Plo + -rm -f ./$(DEPDIR)/libtestpat_la-xcs.Plo -rm -f ./$(DEPDIR)/libtestpat_la-xmlparse.Plo -rm -f ./$(DEPDIR)/libtestpat_la-xmlrole.Plo -rm -f ./$(DEPDIR)/libtestpat_la-xmltok.Plo @@ -923,6 +931,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/random_getentropy.Plo -rm -f ./$(DEPDIR)/random_getrandom.Plo -rm -f ./$(DEPDIR)/random_rand_s.Plo + -rm -f ./$(DEPDIR)/xcs.Plo -rm -f ./$(DEPDIR)/xmlparse.Plo -rm -f ./$(DEPDIR)/xmlrole.Plo -rm -f ./$(DEPDIR)/xmltok.Plo @@ -978,6 +987,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libtestpat_la-random_getentropy.Plo -rm -f ./$(DEPDIR)/libtestpat_la-random_getrandom.Plo -rm -f ./$(DEPDIR)/libtestpat_la-random_rand_s.Plo + -rm -f ./$(DEPDIR)/libtestpat_la-xcs.Plo -rm -f ./$(DEPDIR)/libtestpat_la-xmlparse.Plo -rm -f ./$(DEPDIR)/libtestpat_la-xmlrole.Plo -rm -f ./$(DEPDIR)/libtestpat_la-xmltok.Plo @@ -987,6 +997,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/random_getentropy.Plo -rm -f ./$(DEPDIR)/random_getrandom.Plo -rm -f ./$(DEPDIR)/random_rand_s.Plo + -rm -f ./$(DEPDIR)/xcs.Plo -rm -f ./$(DEPDIR)/xmlparse.Plo -rm -f ./$(DEPDIR)/xmlrole.Plo -rm -f ./$(DEPDIR)/xmltok.Plo diff --git a/contrib/expat/lib/expat.h b/contrib/expat/lib/expat.h index 4c3851d50a5f..1b2852dd76cb 100644 --- a/contrib/expat/lib/expat.h +++ b/contrib/expat/lib/expat.h @@ -48,7 +48,7 @@ #ifndef Expat_INCLUDED # define Expat_INCLUDED 1 -# include <stdint.h> // for uint8_t +# include <stdint.h> // for int64_t, uint8_t, uint64_t # include <stdlib.h> # include "expat_external.h" @@ -140,6 +140,26 @@ enum XML_Error { XML_ERROR_NOT_STARTED, }; +/* Added in 2.9.0. */ +enum XML_Prop_Error { + XML_PROP_ERROR_NONE = 0, // i.e. success + + XML_PROP_ERROR_INVALID_KEY = 1, // i.e. the property is not known at all + XML_PROP_ERROR_INVALID_TYPE = 2, // i.e. the property is known but expects a + // different type (so a different + // getter/setter would need to be called) + XML_PROP_ERROR_INVALID_VALUE = 3, // i.e. the value is invalid (with a setter + // function) or a NULL-pointer (with a + // getter function) + + XML_PROP_ERROR_PARSER_NULL = 4, // i.e. the parser argument is NULL + XML_PROP_ERROR_PARSER_NOT_ROOT = 5, // i.e. the parser is not a root parser + // but a subparser (and a root parser is + // needed) + + /* potentially more error codes upcoming here */ +}; + enum XML_Content_Type { XML_CTYPE_EMPTY = 1, XML_CTYPE_ANY, @@ -757,29 +777,6 @@ XML_GetSpecifiedAttributeCount(XML_Parser parser); XMLPARSEAPI(int) XML_GetIdAttributeIndex(XML_Parser parser); -# ifdef XML_ATTR_INFO -/* Source file byte offsets for the start and end of attribute names and values. - The value indices are exclusive of surrounding quotes; thus in a UTF-8 source - file an attribute value of "blah" will yield: - info->valueEnd - info->valueStart = 4 bytes. -*/ -typedef struct { - XML_Index nameStart; /* Offset to beginning of the attribute name. */ - XML_Index nameEnd; /* Offset after the attribute name's last byte. */ - XML_Index valueStart; /* Offset to beginning of the attribute value. */ - XML_Index valueEnd; /* Offset after the attribute value's last byte. */ -} XML_AttrInfo; - -/* Returns an array of XML_AttrInfo structures for the attribute/value pairs - passed in last call to the XML_StartElementHandler that were specified - in the start-tag rather than defaulted. Each attribute/value pair counts - as 1; thus the number of entries in the array is - XML_GetSpecifiedAttributeCount(parser) / 2. -*/ -XMLPARSEAPI(const XML_AttrInfo *) -XML_GetAttributeInfo(XML_Parser parser); -# endif - /* Parses some input. Returns XML_STATUS_ERROR if a fatal error is detected. The last call to XML_Parse must have isFinal true; len may be zero for this call (or any other). @@ -964,15 +961,24 @@ XML_GetErrorCode(XML_Parser parser); return 0 to indicate an error. Note: XML_GetCurrentByteIndex returns -1 to indicate an error. */ +XML_ATTR_DEPRECATED("please use XML_GetCurrentLineNumber64 instead") XMLPARSEAPI(XML_Size) XML_GetCurrentLineNumber(XML_Parser parser); +XMLPARSEAPI(uint64_t) XML_GetCurrentLineNumber64(XML_Parser parser); +XML_ATTR_DEPRECATED("please use XML_GetCurrentColumnNumber64 instead") XMLPARSEAPI(XML_Size) XML_GetCurrentColumnNumber(XML_Parser parser); +XMLPARSEAPI(uint64_t) XML_GetCurrentColumnNumber64(XML_Parser parser); +XML_ATTR_DEPRECATED("please use XML_GetCurrentByteIndex64 instead") XMLPARSEAPI(XML_Index) XML_GetCurrentByteIndex(XML_Parser parser); +XMLPARSEAPI(int64_t) XML_GetCurrentByteIndex64(XML_Parser parser); /* Return the number of bytes in the current event. Returns 0 if the event is in an internal entity. */ +XML_ATTR_DEPRECATED("please use XML_GetCurrentByteCount64 instead") XMLPARSEAPI(int) XML_GetCurrentByteCount(XML_Parser parser); +XMLPARSEAPI(uint64_t) +XML_GetCurrentByteCount64(XML_Parser parser); /* If XML_CONTEXT_BYTES is >=1, returns the input buffer, sets the integer pointed to by offset to the offset within this buffer @@ -984,8 +990,11 @@ XML_GetCurrentByteCount(XML_Parser parser); NOTE: The character pointer returned should not be used outside the handler that makes the call. */ +XML_ATTR_DEPRECATED("please use XML_GetInputContext64 instead") XMLPARSEAPI(const char *) XML_GetInputContext(XML_Parser parser, int *offset, int *size); +XMLPARSEAPI(const char *) +XML_GetInputContext64(XML_Parser parser, int64_t *offset, uint64_t *size); /* For backwards compatibility with previous versions. */ # define XML_GetErrorLineNumber XML_GetCurrentLineNumber @@ -1040,6 +1049,7 @@ enum XML_FeatureEnum { XML_FEATURE_UNICODE_WCHAR_T, XML_FEATURE_DTD, XML_FEATURE_CONTEXT_BYTES, + /* Added in Expat 1.95.5, removed in Expat 2.9.0. */ XML_FEATURE_MIN_SIZE, XML_FEATURE_SIZEOF_XML_CHAR, XML_FEATURE_SIZEOF_XML_LCHAR, @@ -1047,7 +1057,7 @@ enum XML_FeatureEnum { XML_FEATURE_NS, /* Added in Expat 2.0.1. */ XML_FEATURE_LARGE_SIZE, - /* Added in Expat 2.1.0. */ + /* Added in Expat 2.1.0, removed in Expat 2.9.0. */ XML_FEATURE_ATTR_INFO, /* Added in Expat 2.4.0. */ XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT, @@ -1069,6 +1079,41 @@ typedef struct { XMLPARSEAPI(const XML_Feature *) XML_GetFeatureList(void); +/* Added in Expat 2.9.0. */ +enum XML_Parser_Property { +# if defined(XML_TESTING) + XML_PROP_INVALID = 0, +# endif +# if XML_GE == 1 + XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD = 1, // of type `uint64_t` + XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION = 2, // of type `double` + XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD = 3, // of type `uint64_t` + XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION = 4, // of type `double` +# endif + XML_PROP_REPARSE_DEFERRAL_ENABLED = 5, // of type `XML_Bool` + /* more properties upcoming here */ +}; + +/* Added in Expat 2.9.0. */ +XMLPARSEAPI(enum XML_Prop_Error) +XML_GetPropertyBool(XML_Parser parser, enum XML_Parser_Property property, + XML_Bool *value); +XMLPARSEAPI(enum XML_Prop_Error) +XML_GetPropertyDouble(XML_Parser parser, enum XML_Parser_Property property, + double *value); +XMLPARSEAPI(enum XML_Prop_Error) +XML_GetPropertyUInt64(XML_Parser parser, enum XML_Parser_Property property, + uint64_t *value); +XMLPARSEAPI(enum XML_Prop_Error) +XML_SetPropertyBool(XML_Parser parser, enum XML_Parser_Property property, + XML_Bool value); +XMLPARSEAPI(enum XML_Prop_Error) +XML_SetPropertyDouble(XML_Parser parser, enum XML_Parser_Property property, + double value); +XMLPARSEAPI(enum XML_Prop_Error) +XML_SetPropertyUInt64(XML_Parser parser, enum XML_Parser_Property property, + uint64_t value); + # if defined(XML_DTD) || (defined(XML_GE) && XML_GE == 1) /* Added in Expat 2.4.0 for XML_DTD defined and * added in Expat 2.6.0 for XML_GE == 1. */ @@ -1101,8 +1146,8 @@ XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled); See https://semver.org */ # define XML_MAJOR_VERSION 2 -# define XML_MINOR_VERSION 8 -# define XML_MICRO_VERSION 5 +# define XML_MINOR_VERSION 9 +# define XML_MICRO_VERSION 0 # ifdef __cplusplus } diff --git a/contrib/expat/lib/expat_external.h b/contrib/expat/lib/expat_external.h index cf80f960d6e1..0620fe47ed3c 100644 --- a/contrib/expat/lib/expat_external.h +++ b/contrib/expat/lib/expat_external.h @@ -166,6 +166,9 @@ typedef char XML_LChar; # endif /* XML_UNICODE */ # ifdef XML_LARGE_SIZE /* Use large integers for file/stream positions. */ +# if defined(__clang__) || defined(__GNUC__) +# warning Macro XML_LARGE_SIZE is deprecated, please use the 64bit location API functions instead. +# endif typedef long long XML_Index; typedef unsigned long long XML_Size; # else diff --git a/contrib/expat/lib/internal.h b/contrib/expat/lib/internal.h index 86655371d290..de34cd7dfc55 100644 --- a/contrib/expat/lib/internal.h +++ b/contrib/expat/lib/internal.h @@ -56,13 +56,11 @@ #if ! defined(INTERNAL_H) # define INTERNAL_H 1 -# ifndef XML_MIN_SIZE -# if ! defined(inline) -# ifdef __GNUC__ -# define inline __inline -# endif /* __GNUC__ */ -# endif -# endif /* XML_MIN_SIZE */ +# if ! defined(inline) +# ifdef __GNUC__ +# define inline __inline +# endif /* __GNUC__ */ +# endif # ifndef inline # define inline diff --git a/contrib/expat/lib/libexpat.map.in b/contrib/expat/lib/libexpat.map.in index 71a6758fd746..4a683bba360a 100644 --- a/contrib/expat/lib/libexpat.map.in +++ b/contrib/expat/lib/libexpat.map.in @@ -97,7 +97,7 @@ LIBEXPAT_1.95.8 { LIBEXPAT_2.1.0 { global: -@_EXPAT_COMMENT_ATTR_INFO@ XML_GetAttributeInfo; +# XML_GetAttributeInfo; XML_SetHashSalt; } LIBEXPAT_1.95.8; @@ -122,3 +122,18 @@ LIBEXPAT_2.8.0 { global: XML_SetHashSalt16Bytes; } LIBEXPAT_2.7.2; + +LIBEXPAT_2.9.0 { + global: + XML_GetCurrentByteCount64; + XML_GetCurrentByteIndex64; + XML_GetCurrentColumnNumber64; + XML_GetCurrentLineNumber64; + XML_GetInputContext64; + XML_GetPropertyBool; + XML_GetPropertyDouble; + XML_GetPropertyUInt64; + XML_SetPropertyBool; + XML_SetPropertyDouble; + XML_SetPropertyUInt64; +} LIBEXPAT_2.8.0; diff --git a/contrib/expat/lib/xcs.c b/contrib/expat/lib/xcs.c new file mode 100644 index 000000000000..ae5e042d778f --- /dev/null +++ b/contrib/expat/lib/xcs.c @@ -0,0 +1,90 @@ +/* + __ __ _ + ___\ \/ /_ __ __ _| |_ + / _ \\ /| '_ \ / _` | __| + | __// \| |_) | (_| | |_ + \___/_/\_\ .__/ \__,_|\__| + |_| XML parser + + Copyright (c) 2022-2026 Sebastian Pipping <sebastian@pipping.org> + Licensed under the MIT license: + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the + following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. + + SPDX-License-Identifier: MIT +*/ + +#include "xcs.h" + +#if defined(XML_UNICODE) +# if defined(XML_UNICODE_WCHAR_T) +# include <wchar.h> // for wcscmp, wcslen, wcsncmp +# endif +#else +# include <string.h> // for strcmp, strlen, strncmp +#endif + +size_t +xcslen(const XML_Char *s) { +#ifdef XML_UNICODE +# ifdef XML_UNICODE_WCHAR_T + return wcslen(s); +# else + // XML_Char is unsigned short + size_t len = 0; + while (s[len]) { + len++; + } + return len; +# endif +#else + return strlen(s); +#endif +} + +int +xcscmp(const XML_Char *a, const XML_Char *b) { +#if defined(XML_UNICODE) +# if defined(XML_UNICODE_WCHAR_T) + return wcscmp(a, b); +# else + for (; a[0] && b[0] && a[0] == b[0]; a++, b++) + ; + return a[0] - b[0]; +# endif +#else + return strcmp(a, b); +#endif +} + +int +xcsncmp(const XML_Char *a, const XML_Char *b, size_t len) { +#if defined(XML_UNICODE) +# if defined(XML_UNICODE_WCHAR_T) + return wcsncmp(a, b, len); +# else + for (; len > 0 && a[0] && b[0] && a[0] == b[0]; len--, a++, b++) { + } + return (len == 0) ? 0 : (a[0] - b[0]); +# endif +#else + return strncmp(a, b, len); +#endif +} diff --git a/contrib/expat/lib/xcsinc.c b/contrib/expat/lib/xcs.h index 675b2844c708..1b942647d333 100644 --- a/contrib/expat/lib/xcsinc.c +++ b/contrib/expat/lib/xcs.h @@ -1,4 +1,4 @@ -/* This file is included from other .c files! +/* __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| @@ -6,7 +6,7 @@ \___/_/\_\ .__/ \__,_|\__| |_| XML parser - Copyright (c) 2022-2026 Sebastian Pipping <sebastian@pipping.org> + Copyright (c) 2026 Sebastian Pipping <sebastian@pipping.org> Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -31,24 +31,14 @@ SPDX-License-Identifier: MIT */ -#if defined(XML_UNICODE) && defined(XML_UNICODE_WCHAR_T) -# include <wchar.h> -#endif +#if ! defined(EXPAT_XCS_H) -static size_t -xcslen(const XML_Char *s) { -#ifdef XML_UNICODE -# ifdef XML_UNICODE_WCHAR_T - return wcslen(s); -# else - // XML_Char is unsigned short - size_t len = 0; - while (s[len]) { - len++; - } - return len; -# endif -#else - return strlen(s); -#endif -} +# include <stddef.h> // size_t +# include "expat_external.h" // for XML_Char + +extern size_t xcslen(const XML_Char *s); + +extern int xcscmp(const XML_Char *a, const XML_Char *b); +extern int xcsncmp(const XML_Char *a, const XML_Char *b, size_t len); + +#endif // ! defined(EXPAT_XCS_H) diff --git a/contrib/expat/lib/xmlparse.c b/contrib/expat/lib/xmlparse.c index c3642bd52ff9..41288b6ad418 100644 --- a/contrib/expat/lib/xmlparse.c +++ b/contrib/expat/lib/xmlparse.c @@ -1,4 +1,4 @@ -/* 0864fe2d216f47b742263b698bc051c865b342e8b820e42c234717098ea507e3 (2.8.5+) +/* e3ca845466942140c9af531ac57808c4650116df5d6dbeda3b6546d2548a586e (2.9.0+) __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| @@ -56,6 +56,8 @@ Copyright (c) 2026 Zeyou Liu <zeyouliu@tencent.com> Copyright (c) 2026 Stan Ulbrych <stan@python.org> Copyright (c) 2026 Braian Plaku <braianplaku@gmail.com> + Copyright (c) 2026 Filippo Tedeschi <filippotedeschi98@gmail.com> + Copyright (c) 2026 Junki Lee <junkilee80@gmail.com> Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -107,6 +109,7 @@ #include <stdint.h> /* SIZE_MAX, UINT64_MAX, uint64_t, uintptr_t */ #include <math.h> /* isnan */ #include <errno.h> +#include <wchar.h> /* wcsncmp */ #ifdef _WIN32 # define getpid GetCurrentProcessId @@ -125,7 +128,7 @@ #include "ascii.h" #include "expat.h" #include "siphash.h" -#include "xcsinc.c" +#include "xcs.h" #if defined(HAVE_ARC4RANDOM) # include "random_arc4random.h" @@ -462,8 +465,8 @@ typedef struct accounting { } ACCOUNTING; typedef struct MALLOC_TRACKER { - XmlBigCount bytesAllocated; - XmlBigCount peakBytesAllocated; // updated live only for debug level >=2 + size_t bytesAllocated; + size_t peakBytesAllocated; // updated live only for debug level >=2 unsigned long debugLevel; float maximumAmplificationFactor; // >=1.0 XmlBigCount activationThresholdBytes; @@ -646,6 +649,25 @@ static bool poolAppendChar(STRING_POOL *pool, XML_Char c); static bool poolAppendChars(STRING_POOL *pool, const XML_Char *s, size_t len); +#if XML_GE == 1 +static enum XML_Prop_Error setBillionLaughsAttackProtectionMaximumAmplification( + XML_Parser parser, float maximumAmplificationFactor); + +static enum XML_Prop_Error setBillionLaughsAttackProtectionActivationThreshold( + XML_Parser parser, unsigned long long activationThresholdBytes); + +static enum XML_Prop_Error +setAllocTrackerMaximumAmplification(XML_Parser parser, + float maximumAmplificationFactor); + +static enum XML_Prop_Error +setAllocTrackerActivationThreshold(XML_Parser parser, + unsigned long long activationThresholdBytes); +#endif /* XML_GE == 1 */ + +static enum XML_Prop_Error setReparseDeferralEnabled(XML_Parser parser, + XML_Bool enabled); + #define poolStart(pool) ((pool)->start) #define poolLength(pool) ((pool)->ptr - (pool)->start) #define poolChop(pool) ((void)--(pool->ptr)) @@ -785,9 +807,6 @@ struct XML_ParserStruct { NS_ATT *m_nsAtts; unsigned long m_nsAttsVersion; unsigned char m_nsAttsPower; -#ifdef XML_ATTR_INFO - XML_AttrInfo *m_attInfo; -#endif POSITION m_position; STRING_POOL m_tempPool; STRING_POOL m_temp2Pool; @@ -824,30 +843,30 @@ struct XML_ParserStruct { #if XML_GE == 1 static void -expat_heap_stat(XML_Parser rootParser, char operator, XmlBigCount absDiff, - XmlBigCount newTotal, XmlBigCount peakTotal, int sourceLine) { +expat_heap_stat(XML_Parser rootParser, char operator, size_t absDiff, + size_t newTotal, size_t peakTotal, int sourceLine) { // NOTE: This can be +infinity or -nan const float amplification = (float)newTotal / (float)rootParser->m_accounting.countBytesDirect; fprintf( stderr, - "expat: Allocations(%p): Direct " EXPAT_FMT_ULL("10") ", allocated %c" EXPAT_FMT_ULL( - "10") " to " EXPAT_FMT_ULL("10") " (" EXPAT_FMT_ULL("10") " peak), amplification %8.2f (xmlparse.c:%d)\n", + "expat: Allocations(%p): Direct " EXPAT_FMT_ULL("10") ", allocated %c" EXPAT_FMT_SIZE_T( + "10") " to " EXPAT_FMT_SIZE_T("10") " (" EXPAT_FMT_SIZE_T("10") " peak), amplification %8.2f (xmlparse.c:%d)\n", (void *)rootParser, rootParser->m_accounting.countBytesDirect, operator, absDiff, newTotal, peakTotal, (double)amplification, sourceLine); } static bool -expat_heap_increase_tolerable(XML_Parser rootParser, XmlBigCount increase, +expat_heap_increase_tolerable(XML_Parser rootParser, size_t increase, int sourceLine) { assert(rootParser != NULL); assert(increase > 0); - XmlBigCount newTotal = 0; + size_t newTotal = 0; bool tolerable = true; // Detect integer overflow - if ((XmlBigCount)-1 - rootParser->m_alloc_tracker.bytesAllocated < increase) { + if (SIZE_MAX - rootParser->m_alloc_tracker.bytesAllocated < increase) { tolerable = false; } else { newTotal = rootParser->m_alloc_tracker.bytesAllocated + increase; @@ -887,8 +906,7 @@ expat_malloc(XML_Parser parser, size_t size, int sourceLine) { const size_t bytesToAllocate = sizeof(size_t) + EXPAT_MALLOC_PADDING + size; - if ((XmlBigCount)-1 - rootParser->m_alloc_tracker.bytesAllocated - < bytesToAllocate) { + if (SIZE_MAX - rootParser->m_alloc_tracker.bytesAllocated < bytesToAllocate) { return NULL; // i.e. signal integer overflow as out-of-memory } @@ -998,9 +1016,10 @@ expat_realloc(XML_Parser parser, void *ptr, size_t size, int sourceLine) { } } - // NOTE: Integer overflow detection has already been done for us - // by expat_heap_increase_tolerable(..) above - assert(SIZE_MAX - sizeof(size_t) - EXPAT_MALLOC_PADDING >= size); + // Detect and prevent integer overflow + if (size > SIZE_MAX - sizeof(size_t) - EXPAT_MALLOC_PADDING) { + return NULL; + } // Actually allocate mallocedPtr = parser->m_mem.realloc_fcn( @@ -1012,8 +1031,7 @@ expat_realloc(XML_Parser parser, void *ptr, size_t size, int sourceLine) { // Update accounting if (isIncrease) { - assert((XmlBigCount)-1 - rootParser->m_alloc_tracker.bytesAllocated - >= absDiff); + assert(SIZE_MAX - rootParser->m_alloc_tracker.bytesAllocated >= absDiff); rootParser->m_alloc_tracker.bytesAllocated += absDiff; } else { // i.e. decrease assert(rootParser->m_alloc_tracker.bytesAllocated >= absDiff); @@ -1389,20 +1407,9 @@ parserCreate(const XML_Char *encodingName, FREE(parser, parser); return NULL; } -#ifdef XML_ATTR_INFO - parser->m_attInfo = MALLOC(parser, parser->m_attsSize * sizeof(XML_AttrInfo)); - if (parser->m_attInfo == NULL) { - FREE(parser, parser->m_atts); - FREE(parser, parser); - return NULL; - } -#endif parser->m_dataBuf = MALLOC(parser, INIT_DATA_BUF_SIZE * sizeof(XML_Char)); if (parser->m_dataBuf == NULL) { FREE(parser, parser->m_atts); -#ifdef XML_ATTR_INFO - FREE(parser, parser->m_attInfo); -#endif FREE(parser, parser); return NULL; } @@ -1415,9 +1422,6 @@ parserCreate(const XML_Char *encodingName, if (parser->m_dtd == NULL) { FREE(parser, parser->m_dataBuf); FREE(parser, parser->m_atts); -#ifdef XML_ATTR_INFO - FREE(parser, parser->m_attInfo); -#endif FREE(parser, parser); return NULL; } @@ -1596,6 +1600,10 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) { if (parser->m_parentParser) return XML_FALSE; + // The application-defined release callback may access the parser, so it + // must run before any parser state is freed. + if (parser->m_unknownEncodingRelease) + callUnknownEncodingRelease(parser); /* move m_tagStack to m_freeTagList */ tStk = parser->m_tagStack; while (tStk) { @@ -1616,14 +1624,16 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) { moveEntityList(&parser->m_freeEntities, &parser->m_openValueEntities); moveToFreeBindingList(parser, parser->m_inheritedBindings); FREE(parser, parser->m_unknownEncodingMem); - if (parser->m_unknownEncodingRelease) - callUnknownEncodingRelease(parser); poolClear(&parser->m_tempPool); poolClear(&parser->m_temp2Pool); FREE(parser, (void *)parser->m_protocolEncodingName); parser->m_protocolEncodingName = NULL; parserInit(parser, encodingName); dtdReset(parser->m_dtd, parser); + if (encodingName && ! parser->m_protocolEncodingName) { + parser->m_errorCode = XML_ERROR_NO_MEMORY; + return XML_FALSE; + } return XML_TRUE; } @@ -1856,6 +1866,10 @@ XML_ParserFree(XML_Parser parser) { TAG *tagList; if ((parser == NULL) || isCalledFromInsideHandler(parser)) return; + // The application-defined release callback may access the parser, so it + // must run before any parser state is freed. + if (parser->m_unknownEncodingRelease) + callUnknownEncodingRelease(parser); /* free m_tagStack and m_freeTagList */ tagList = parser->m_tagStack; for (;;) { @@ -1916,9 +1930,6 @@ XML_ParserFree(XML_Parser parser) { #endif /* XML_DTD */ dtdDestroy(parser->m_dtd, (XML_Bool)! parser->m_parentParser, parser); FREE(parser, parser->m_atts); -#ifdef XML_ATTR_INFO - FREE(parser, parser->m_attInfo); -#endif FREE(parser, parser->m_groupConnector); // NOTE: We are avoiding FREE(..) here because parser->m_buffer // is not being allocated with MALLOC(..) but with plain @@ -1927,8 +1938,6 @@ XML_ParserFree(XML_Parser parser) { FREE(parser, parser->m_dataBuf); FREE(parser, parser->m_nsAtts); FREE(parser, parser->m_unknownEncodingMem); - if (parser->m_unknownEncodingRelease) - callUnknownEncodingRelease(parser); FREE(parser, parser); } @@ -2009,15 +2018,6 @@ XML_GetIdAttributeIndex(XML_Parser parser) { return parser->m_idAttIndex; } -#ifdef XML_ATTR_INFO -const XML_AttrInfo *XMLCALL -XML_GetAttributeInfo(XML_Parser parser) { - if (parser == NULL) - return NULL; - return parser->m_attInfo; -} -#endif - void XMLCALL XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start, XML_EndElementHandler end) { @@ -2446,6 +2446,11 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal) { parser->m_parsingStatus.parsing = XML_PARSING; } + if (len > EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferEnd)) { + parser->m_errorCode = XML_ERROR_INVALID_ARGUMENT; + return XML_STATUS_ERROR; + } + // Detect and avoid integer overflow if ((uint64_t)len > UINT64_MAX - parser->m_parseEndByteIndex) { parser->m_errorCode = XML_ERROR_NO_MEMORY; @@ -2705,41 +2710,57 @@ XML_GetErrorCode(XML_Parser parser) { return parser->m_errorCode; } -XML_Index XMLCALL -XML_GetCurrentByteIndex(XML_Parser parser) { +int64_t XMLCALL +XML_GetCurrentByteIndex64(XML_Parser parser) { if (parser == NULL) return -1; if (parser->m_eventPtr) { - // NOTE: XML_Index is known to wrap around for >2 GiB content - // on 32bit machines and 64bit Windows, unless (non-default and - // uncommon) XML_LARGE_SIZE is defined. - // That's a bug and it only lives on because we cannot break - // ABI compatibility of public API. - return (XML_Index)(parser->m_parseEndByteIndex - - (parser->m_parseEndPtr - parser->m_eventPtr)); + return (int64_t)(parser->m_parseEndByteIndex + - (parser->m_parseEndPtr - parser->m_eventPtr)); } return -1; } -int XMLCALL -XML_GetCurrentByteCount(XML_Parser parser) { +// DEPRECATED since Expat 2.9.0. +XML_Index XMLCALL +XML_GetCurrentByteIndex(XML_Parser parser) { + // NOTE: XML_Index is known to wrap around for >2 GiB content + // on 32bit machines and 64bit Windows, unless (non-default and + // uncommon) XML_LARGE_SIZE is defined. + // That's a bug and it only lives on because we cannot break + // ABI compatibility of public API. + return (XML_Index)XML_GetCurrentByteIndex64(parser); +} + +uint64_t XMLCALL +XML_GetCurrentByteCount64(XML_Parser parser) { if (parser == NULL) return 0; - if (parser->m_eventEndPtr && parser->m_eventPtr) - return (int)(parser->m_eventEndPtr - parser->m_eventPtr); + if (parser->m_eventEndPtr && parser->m_eventPtr) { + return parser->m_eventEndPtr - parser->m_eventPtr; + } return 0; } +// DEPRECATED since Expat 2.9.0. +int XMLCALL +XML_GetCurrentByteCount(XML_Parser parser) { + // NOTE: int is known to wrap around for >2 GiB content. + // That's a bug and it only lives on because we cannot break + // ABI compatibility of public API. + return (int)XML_GetCurrentByteCount64(parser); +} + const char *XMLCALL -XML_GetInputContext(XML_Parser parser, int *offset, int *size) { +XML_GetInputContext64(XML_Parser parser, int64_t *offset, uint64_t *size) { #if XML_CONTEXT_BYTES > 0 if (parser == NULL) return NULL; if (parser->m_eventPtr && parser->m_buffer) { if (offset != NULL) - *offset = (int)(parser->m_eventPtr - parser->m_buffer); + *offset = parser->m_eventPtr - parser->m_buffer; if (size != NULL) - *size = (int)(parser->m_bufferEnd - parser->m_buffer); + *size = parser->m_bufferEnd - parser->m_buffer; return parser->m_buffer; } #else @@ -2750,8 +2771,41 @@ XML_GetInputContext(XML_Parser parser, int *offset, int *size) { return NULL; } -XML_Size XMLCALL -XML_GetCurrentLineNumber(XML_Parser parser) { +// DEPRECATED since Expat 2.9.0. +const char *XMLCALL +XML_GetInputContext(XML_Parser parser, int *offset, int *size) { +#if XML_CONTEXT_BYTES > 0 + if (parser == NULL) + return NULL; + + int64_t offset64; + uint64_t size64; + + const char *const buffer = XML_GetInputContext64(parser, &offset64, &size64); + + if (buffer == NULL) + return NULL; + + // NOTE: int is known to wrap around for >2 GiB content. + // That's a bug and it only lives on because we cannot break + // ABI compatibility of public API. + if (offset != NULL) + *offset = (int)offset64; + + if (size != NULL) + *size = (int)size64; + + return buffer; +#else + (void)parser; + (void)offset; + (void)size; +#endif /* XML_CONTEXT_BYTES > 0 */ + return NULL; +} + +uint64_t XMLCALL +XML_GetCurrentLineNumber64(XML_Parser parser) { if (parser == NULL) return 0; if (parser->m_eventPtr && parser->m_eventPtr >= parser->m_positionPtr) { @@ -2759,16 +2813,22 @@ XML_GetCurrentLineNumber(XML_Parser parser) { parser->m_eventPtr, &parser->m_position); parser->m_positionPtr = parser->m_eventPtr; } + return parser->m_position.lineNumber + 1; +} + +// DEPRECATED since Expat 2.9.0. +XML_Size XMLCALL +XML_GetCurrentLineNumber(XML_Parser parser) { // NOTE: XML_Size is known to wrap around for >4 GiB content // on 32bit machines and 64bit Windows, unless (non-default and // uncommon) XML_LARGE_SIZE is defined. // That's a bug and it only lives on because we cannot break // ABI compatibility of public API. - return (XML_Size)(parser->m_position.lineNumber + 1); + return (XML_Size)XML_GetCurrentLineNumber64(parser); } -XML_Size XMLCALL -XML_GetCurrentColumnNumber(XML_Parser parser) { +uint64_t XMLCALL +XML_GetCurrentColumnNumber64(XML_Parser parser) { if (parser == NULL) return 0; if (parser->m_eventPtr && parser->m_eventPtr >= parser->m_positionPtr) { @@ -2776,12 +2836,18 @@ XML_GetCurrentColumnNumber(XML_Parser parser) { parser->m_eventPtr, &parser->m_position); parser->m_positionPtr = parser->m_eventPtr; } + return parser->m_position.columnNumber; +} + +// DEPRECATED since Expat 2.9.0. +XML_Size XMLCALL +XML_GetCurrentColumnNumber(XML_Parser parser) { // NOTE: XML_Size is known to wrap around for >4 GiB content // on 32bit machines and 64bit Windows, unless (non-default and // uncommon) XML_LARGE_SIZE is defined. // That's a bug and it only lives on because we cannot break // ABI compatibility of public API. - return (XML_Size)parser->m_position.columnNumber; + return (XML_Size)XML_GetCurrentColumnNumber64(parser); } void XMLCALL @@ -2827,7 +2893,7 @@ XML_MemFree(XML_Parser parser, void *ptr) { void XMLCALL XML_DefaultCurrent(XML_Parser parser) { - if (parser == NULL) + if (parser == NULL || ! isCalledFromInsideHandler(parser)) return; if (parser->m_defaultHandler) { if (parser->m_openInternalEntities) @@ -2998,18 +3064,12 @@ XML_GetFeatureList(void) { {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"), XML_CONTEXT_BYTES}, #endif -#ifdef XML_MIN_SIZE - {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0}, -#endif #ifdef XML_NS {XML_FEATURE_NS, XML_L("XML_NS"), 0}, #endif #ifdef XML_LARGE_SIZE {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0}, #endif -#ifdef XML_ATTR_INFO - {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0}, -#endif #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. */ @@ -3036,59 +3096,294 @@ XML_GetFeatureList(void) { } #if XML_GE == 1 +static enum XML_Prop_Error +setBillionLaughsAttackProtectionMaximumAmplification( + XML_Parser parser, float maximumAmplificationFactor) { + if (parser == NULL) + return XML_PROP_ERROR_PARSER_NULL; + + if (parser->m_parentParser != NULL) + return XML_PROP_ERROR_PARSER_NOT_ROOT; + + if (isnan(maximumAmplificationFactor) || (maximumAmplificationFactor < 1.0f)) + return XML_PROP_ERROR_INVALID_VALUE; + + parser->m_accounting.maximumAmplificationFactor = maximumAmplificationFactor; + + return XML_PROP_ERROR_NONE; +} + XML_Bool XMLCALL XML_SetBillionLaughsAttackProtectionMaximumAmplification( XML_Parser parser, float maximumAmplificationFactor) { - if ((parser == NULL) || (parser->m_parentParser != NULL) - || isnan(maximumAmplificationFactor) - || (maximumAmplificationFactor < 1.0f)) { - return XML_FALSE; - } - parser->m_accounting.maximumAmplificationFactor = maximumAmplificationFactor; - return XML_TRUE; + return (setBillionLaughsAttackProtectionMaximumAmplification( + parser, maximumAmplificationFactor) + == XML_PROP_ERROR_NONE) + ? XML_TRUE + : XML_FALSE; +} + +static enum XML_Prop_Error +setBillionLaughsAttackProtectionActivationThreshold( + XML_Parser parser, unsigned long long activationThresholdBytes) { + if (parser == NULL) + return XML_PROP_ERROR_PARSER_NULL; + + if (parser->m_parentParser != NULL) + return XML_PROP_ERROR_PARSER_NOT_ROOT; + + parser->m_accounting.activationThresholdBytes = activationThresholdBytes; + + return XML_PROP_ERROR_NONE; } XML_Bool XMLCALL XML_SetBillionLaughsAttackProtectionActivationThreshold( XML_Parser parser, unsigned long long activationThresholdBytes) { - if ((parser == NULL) || (parser->m_parentParser != NULL)) { - return XML_FALSE; - } - parser->m_accounting.activationThresholdBytes = activationThresholdBytes; - return XML_TRUE; + return (setBillionLaughsAttackProtectionActivationThreshold( + parser, activationThresholdBytes) + == XML_PROP_ERROR_NONE) + ? XML_TRUE + : XML_FALSE; +} + +static enum XML_Prop_Error +setAllocTrackerMaximumAmplification(XML_Parser parser, + float maximumAmplificationFactor) { + if (parser == NULL) + return XML_PROP_ERROR_PARSER_NULL; + + if (parser->m_parentParser != NULL) + return XML_PROP_ERROR_PARSER_NOT_ROOT; + + if (isnan(maximumAmplificationFactor) || (maximumAmplificationFactor < 1.0f)) + return XML_PROP_ERROR_INVALID_VALUE; + + parser->m_alloc_tracker.maximumAmplificationFactor + = maximumAmplificationFactor; + + return XML_PROP_ERROR_NONE; } XML_Bool XMLCALL XML_SetAllocTrackerMaximumAmplification(XML_Parser parser, float maximumAmplificationFactor) { - if ((parser == NULL) || (parser->m_parentParser != NULL) - || isnan(maximumAmplificationFactor) - || (maximumAmplificationFactor < 1.0f)) { - return XML_FALSE; - } - parser->m_alloc_tracker.maximumAmplificationFactor - = maximumAmplificationFactor; - return XML_TRUE; + return (setAllocTrackerMaximumAmplification(parser, + maximumAmplificationFactor) + == XML_PROP_ERROR_NONE) + ? XML_TRUE + : XML_FALSE; +} + +static enum XML_Prop_Error +setAllocTrackerActivationThreshold( + XML_Parser parser, unsigned long long activationThresholdBytes) { + if (parser == NULL) + return XML_PROP_ERROR_PARSER_NULL; + + if (parser->m_parentParser != NULL) + return XML_PROP_ERROR_PARSER_NOT_ROOT; + + parser->m_alloc_tracker.activationThresholdBytes = activationThresholdBytes; + + return XML_PROP_ERROR_NONE; } XML_Bool XMLCALL XML_SetAllocTrackerActivationThreshold( XML_Parser parser, unsigned long long activationThresholdBytes) { - if ((parser == NULL) || (parser->m_parentParser != NULL)) { - return XML_FALSE; - } - parser->m_alloc_tracker.activationThresholdBytes = activationThresholdBytes; - return XML_TRUE; + return (setAllocTrackerActivationThreshold(parser, activationThresholdBytes) + == XML_PROP_ERROR_NONE) + ? XML_TRUE + : XML_FALSE; } #endif /* XML_GE == 1 */ +static enum XML_Prop_Error +setReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled) { + if (parser == NULL) + return XML_PROP_ERROR_PARSER_NULL; + + if (enabled != XML_TRUE && enabled != XML_FALSE) + return XML_PROP_ERROR_INVALID_VALUE; + + parser->m_reparseDeferralEnabled = enabled; + + return XML_PROP_ERROR_NONE; +} + XML_Bool XMLCALL XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled) { - if (parser != NULL && (enabled == XML_TRUE || enabled == XML_FALSE)) { - parser->m_reparseDeferralEnabled = enabled; - return XML_TRUE; + return (setReparseDeferralEnabled(parser, enabled) == XML_PROP_ERROR_NONE) + ? XML_TRUE + : XML_FALSE; +} + +enum XML_Prop_Error XMLCALL +XML_SetPropertyBool(XML_Parser parser, enum XML_Parser_Property property, + XML_Bool value) { + if (parser == NULL) + return XML_PROP_ERROR_PARSER_NULL; + + switch (property) { +#if XML_GE == 1 + case XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD: + case XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION: + case XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD: + case XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION: + return XML_PROP_ERROR_INVALID_TYPE; +#endif /* XML_GE == 1 */ + case XML_PROP_REPARSE_DEFERRAL_ENABLED: + return setReparseDeferralEnabled(parser, value); + default: + return XML_PROP_ERROR_INVALID_KEY; + } + + assert(0 && "considered unreachable"); +} + +enum XML_Prop_Error XMLCALL +XML_SetPropertyDouble(XML_Parser parser, enum XML_Parser_Property property, + double value) { + if (parser == NULL) + return XML_PROP_ERROR_PARSER_NULL; + +#if XML_GE == 0 + UNUSED_P(value); +#endif + + switch (property) { +#if XML_GE == 1 + case XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION: + return setAllocTrackerMaximumAmplification(parser, (float)value); + case XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION: + return setBillionLaughsAttackProtectionMaximumAmplification(parser, + (float)value); + case XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD: + case XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD: +#endif /* XML_GE == 1 */ + case XML_PROP_REPARSE_DEFERRAL_ENABLED: + return XML_PROP_ERROR_INVALID_TYPE; + default: + return XML_PROP_ERROR_INVALID_KEY; + } + + assert(0 && "considered unreachable"); +} + +enum XML_Prop_Error XMLCALL +XML_SetPropertyUInt64(XML_Parser parser, enum XML_Parser_Property property, + uint64_t value) { + if (parser == NULL) + return XML_PROP_ERROR_PARSER_NULL; + +#if XML_GE == 0 + UNUSED_P(value); +#endif + + switch (property) { +#if XML_GE == 1 + case XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD: + return setAllocTrackerActivationThreshold(parser, + (unsigned long long)value); + case XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD: + return setBillionLaughsAttackProtectionActivationThreshold( + parser, (unsigned long long)value); + case XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION: + case XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION: +#endif /* XML_GE == 1 */ + case XML_PROP_REPARSE_DEFERRAL_ENABLED: + return XML_PROP_ERROR_INVALID_TYPE; + default: + return XML_PROP_ERROR_INVALID_KEY; + } + + assert(0 && "considered unreachable"); +} + +enum XML_Prop_Error XMLCALL +XML_GetPropertyBool(XML_Parser parser, enum XML_Parser_Property property, + XML_Bool *value) { + if (parser == NULL) + return XML_PROP_ERROR_PARSER_NULL; + + if (value == NULL) + return XML_PROP_ERROR_INVALID_VALUE; + + switch (property) { +#if XML_GE == 1 + case XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD: + case XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION: + case XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD: + case XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION: + return XML_PROP_ERROR_INVALID_TYPE; +#endif /* XML_GE == 1 */ + case XML_PROP_REPARSE_DEFERRAL_ENABLED: + *value = parser->m_reparseDeferralEnabled; + break; + default: + return XML_PROP_ERROR_INVALID_KEY; + } + + return XML_PROP_ERROR_NONE; +} + +enum XML_Prop_Error XMLCALL +XML_GetPropertyDouble(XML_Parser parser, enum XML_Parser_Property property, + double *value) { + if (parser == NULL) + return XML_PROP_ERROR_PARSER_NULL; + + if (value == NULL) + return XML_PROP_ERROR_INVALID_VALUE; + + switch (property) { +#if XML_GE == 1 + case XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION: + *value = (double)parser->m_accounting.maximumAmplificationFactor; + break; + case XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION: + *value = (double)parser->m_alloc_tracker.maximumAmplificationFactor; + break; + case XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD: + case XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD: +#endif /* XML_GE == 1 */ + case XML_PROP_REPARSE_DEFERRAL_ENABLED: + return XML_PROP_ERROR_INVALID_TYPE; + default: + return XML_PROP_ERROR_INVALID_KEY; } - return XML_FALSE; + + return XML_PROP_ERROR_NONE; +} + +enum XML_Prop_Error XMLCALL +XML_GetPropertyUInt64(XML_Parser parser, enum XML_Parser_Property property, + uint64_t *value) { + if (parser == NULL) + return XML_PROP_ERROR_PARSER_NULL; + + if (value == NULL) + return XML_PROP_ERROR_INVALID_VALUE; + + switch (property) { +#if XML_GE == 1 + case XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD: + *value = parser->m_accounting.activationThresholdBytes; + break; + case XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD: + *value = parser->m_alloc_tracker.activationThresholdBytes; + break; + case XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION: + case XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION: +#endif /* XML_GE == 1 */ + case XML_PROP_REPARSE_DEFERRAL_ENABLED: + return XML_PROP_ERROR_INVALID_TYPE; + default: + return XML_PROP_ERROR_INVALID_KEY; + } + + return XML_PROP_ERROR_NONE; } /* Initially tag->rawName always points into the parse buffer; @@ -3901,21 +4196,6 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, return XML_ERROR_NO_MEMORY; } parser->m_atts = temp; -#ifdef XML_ATTR_INFO - /* Detect and prevent integer overflow. */ - if (parser->m_attsSize > SIZE_MAX / sizeof(XML_AttrInfo)) { - parser->m_attsSize = oldAttsSize; - return XML_ERROR_NO_MEMORY; - } - - XML_AttrInfo *const temp2 = REALLOC( - parser, parser->m_attInfo, parser->m_attsSize * sizeof(XML_AttrInfo)); - if (temp2 == NULL) { - parser->m_attsSize = oldAttsSize; - return XML_ERROR_NO_MEMORY; - } - parser->m_attInfo = temp2; -#endif if (n > oldAttsSize) { /* Detect and prevent integer overflow. */ if (n > (size_t)INT_MAX) @@ -3928,33 +4208,12 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, const XML_Char **const appAtts = (const XML_Char **)parser->m_atts; for (size_t i = 0; i < n; i++) { ATTRIBUTE *currAtt = &parser->m_atts[i]; -#ifdef XML_ATTR_INFO - XML_AttrInfo *currAttInfo = &parser->m_attInfo[i]; -#endif /* add the name and value to the attribute list */ ATTRIBUTE_ID *attId = getAttributeId(parser, enc, currAtt->name, currAtt->name + XmlNameLength(enc, currAtt->name)); if (! attId) return XML_ERROR_NO_MEMORY; -#ifdef XML_ATTR_INFO - // NOTE: XML_Index is known to wrap around for >2 GiB content - // on 32bit machines and 64bit Windows, unless (non-default and - // uncommon) XML_LARGE_SIZE is defined. - // That's a bug and it only lives on because we cannot break - // ABI compatibility of public API. - currAttInfo->nameStart - = (XML_Index)(parser->m_parseEndByteIndex - - (parser->m_parseEndPtr - currAtt->name)); - currAttInfo->nameEnd - = currAttInfo->nameStart + XmlNameLength(enc, currAtt->name); - currAttInfo->valueStart - = (XML_Index)(parser->m_parseEndByteIndex - - (parser->m_parseEndPtr - currAtt->valuePtr)); - currAttInfo->valueEnd - = (XML_Index)(parser->m_parseEndByteIndex - - (parser->m_parseEndPtr - currAtt->valueEnd)); -#endif /* Detect duplicate attributes by their QNames. This does not work when namespace processing is turned on and different prefixes for the same namespace are used. For this case we have a check further down. diff --git a/contrib/expat/lib/xmltok.c b/contrib/expat/lib/xmltok.c index a3bf5e0e95b0..2f837acc4cbf 100644 --- a/contrib/expat/lib/xmltok.c +++ b/contrib/expat/lib/xmltok.c @@ -193,13 +193,6 @@ utf8_isInvalid4(const ENCODING *enc, const char *p) { struct normal_encoding { ENCODING enc; unsigned char type[256]; -#ifdef XML_MIN_SIZE - int (*byteType)(const ENCODING *, const char *); - int (*isNameMin)(const ENCODING *, const char *); - int (*isNmstrtMin)(const ENCODING *, const char *); - int (*byteToAscii)(const ENCODING *, const char *); - int (*charMatches)(const ENCODING *, const char *, int); -#endif /* XML_MIN_SIZE */ int (*isName2)(const ENCODING *, const char *); int (*isName3)(const ENCODING *, const char *); int (*isName4)(const ENCODING *, const char *); @@ -213,16 +206,7 @@ struct normal_encoding { #define AS_NORMAL_ENCODING(enc) ((const struct normal_encoding *)(enc)) -#ifdef XML_MIN_SIZE - -# define STANDARD_VTABLE(E) \ - E##byteType, E##isNameMin, E##isNmstrtMin, E##byteToAscii, E##charMatches, - -#else - -# define STANDARD_VTABLE(E) /* as nothing */ - -#endif +#define STANDARD_VTABLE(E) /* as nothing */ #define NORMAL_VTABLE(E) \ E##isName2, E##isName3, E##isName4, E##isNmstrt2, E##isNmstrt3, \ @@ -233,93 +217,33 @@ struct normal_encoding { /* isNmstrt2 */ NULL, /* isNmstrt3 */ NULL, /* isNmstrt4 */ NULL, \ /* isInvalid2 */ NULL, /* isInvalid3 */ NULL, /* isInvalid4 */ NULL -/* Like NULL_VTABLE but with a real isInvalid4 so the UTF-16 encodings reject a - high surrogate that is not followed by a low surrogate. Only needed for the - XML_MIN_SIZE build, where the shared tokenizer dispatches through the vtable; - the regular build inlines the same check via IS_INVALID_CHAR. */ -#ifdef XML_MIN_SIZE -# define UTF16_NULL_VTABLE(E) \ - /* isName2 */ NULL, /* isName3 */ NULL, /* isName4 */ NULL, \ - /* isNmstrt2 */ NULL, /* isNmstrt3 */ NULL, /* isNmstrt4 */ NULL, \ - /* isInvalid2 */ NULL, /* isInvalid3 */ NULL, E##isInvalid4 -#else -# define UTF16_NULL_VTABLE(E) NULL_VTABLE -#endif +#define UTF16_NULL_VTABLE(E) NULL_VTABLE static int checkCharRefNumber(int result); #include "xmltok_impl.h" #include "ascii.h" -#ifdef XML_MIN_SIZE -# define sb_isNameMin isNever -# define sb_isNmstrtMin isNever -#endif - -#ifdef XML_MIN_SIZE -# define MINBPC(enc) ((enc)->minBytesPerChar) -#else /* minimum bytes per character */ -# define MINBPC(enc) 1 -#endif +#define MINBPC(enc) 1 #define SB_BYTE_TYPE(enc, p) \ (((const struct normal_encoding *)(enc))->type[(unsigned char)*(p)]) -#ifdef XML_MIN_SIZE -static int -sb_byteType(const ENCODING *enc, const char *p) { - return SB_BYTE_TYPE(enc, p); -} -# define BYTE_TYPE(enc, p) (AS_NORMAL_ENCODING(enc)->byteType(enc, p)) -#else -# define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p) -#endif +#define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p) -#ifdef XML_MIN_SIZE -# define BYTE_TO_ASCII(enc, p) (AS_NORMAL_ENCODING(enc)->byteToAscii(enc, p)) -static int -sb_byteToAscii(const ENCODING *enc, const char *p) { - UNUSED_P(enc); - return *p; -} -#else -# define BYTE_TO_ASCII(enc, p) (*(p)) -#endif +#define BYTE_TO_ASCII(enc, p) (*(p)) #define IS_NAME_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isName##n(enc, p)) #define IS_NMSTRT_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isNmstrt##n(enc, p)) -#ifdef XML_MIN_SIZE -# define IS_INVALID_CHAR(enc, p, n) \ - (AS_NORMAL_ENCODING(enc)->isInvalid##n \ - && AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p)) -#else -# define IS_INVALID_CHAR(enc, p, n) \ - (AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p)) -#endif +#define IS_INVALID_CHAR(enc, p, n) \ + (AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p)) -#ifdef XML_MIN_SIZE -# define IS_NAME_CHAR_MINBPC(enc, p) \ - (AS_NORMAL_ENCODING(enc)->isNameMin(enc, p)) -# define IS_NMSTRT_CHAR_MINBPC(enc, p) \ - (AS_NORMAL_ENCODING(enc)->isNmstrtMin(enc, p)) -#else -# define IS_NAME_CHAR_MINBPC(enc, p) (0) -# define IS_NMSTRT_CHAR_MINBPC(enc, p) (0) -#endif +#define IS_NAME_CHAR_MINBPC(enc, p) (0) +#define IS_NMSTRT_CHAR_MINBPC(enc, p) (0) -#ifdef XML_MIN_SIZE -# define CHAR_MATCHES(enc, p, c) \ - (AS_NORMAL_ENCODING(enc)->charMatches(enc, p, c)) -static int -sb_charMatches(const ENCODING *enc, const char *p, int c) { - UNUSED_P(enc); - return *p == c; -} -#else /* c is an ASCII character */ -# define CHAR_MATCHES(enc, p, c) (*(p) == (c)) -#endif +#define CHAR_MATCHES(enc, p, c) (*(p) == (c)) #define PREFIX(ident) normal_##ident #define XML_TOK_IMPL_C @@ -769,76 +693,32 @@ DEFINE_UTF16_TO_UTF16(big2_) #define LITTLE2_IS_INVALID_CHAR(p, n) \ ((n) == 4 && ((unsigned char)(p)[3] & 0xFC) != 0xDC) -#ifdef XML_MIN_SIZE - -static int -little2_byteType(const ENCODING *enc, const char *p) { - return LITTLE2_BYTE_TYPE(enc, p); -} - -static int -little2_byteToAscii(const ENCODING *enc, const char *p) { - UNUSED_P(enc); - return LITTLE2_BYTE_TO_ASCII(p); -} - -static int -little2_charMatches(const ENCODING *enc, const char *p, int c) { - UNUSED_P(enc); - return LITTLE2_CHAR_MATCHES(p, c); -} - -static int -little2_isNameMin(const ENCODING *enc, const char *p) { - UNUSED_P(enc); - return LITTLE2_IS_NAME_CHAR_MINBPC(p); -} - -static int -little2_isNmstrtMin(const ENCODING *enc, const char *p) { - UNUSED_P(enc); - return LITTLE2_IS_NMSTRT_CHAR_MINBPC(p); -} - -static int -little2_isInvalid4(const ENCODING *enc, const char *p) { - UNUSED_P(enc); - return LITTLE2_IS_INVALID_CHAR(p, 4); -} - -# undef VTABLE -# define VTABLE VTABLE1, little2_toUtf8, little2_toUtf16 - -#else /* not XML_MIN_SIZE */ - -# undef PREFIX -# define PREFIX(ident) little2_##ident -# define MINBPC(enc) 2 +#undef PREFIX +#define PREFIX(ident) little2_##ident +#define MINBPC(enc) 2 /* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */ -# define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p) -# define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(p) -# define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(p, c) -# define IS_NAME_CHAR(enc, p, n) 0 -# define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(p) -# define IS_NMSTRT_CHAR(enc, p, n) (0) -# define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(p) -# define IS_INVALID_CHAR(enc, p, n) LITTLE2_IS_INVALID_CHAR(p, n) +#define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p) +#define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(p) +#define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(p, c) +#define IS_NAME_CHAR(enc, p, n) 0 +#define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(p) +#define IS_NMSTRT_CHAR(enc, p, n) (0) +#define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(p) +#define IS_INVALID_CHAR(enc, p, n) LITTLE2_IS_INVALID_CHAR(p, n) -# define XML_TOK_IMPL_C -# include "xmltok_impl.c" -# undef XML_TOK_IMPL_C - -# undef MINBPC -# undef BYTE_TYPE -# undef BYTE_TO_ASCII -# undef CHAR_MATCHES -# undef IS_NAME_CHAR -# undef IS_NAME_CHAR_MINBPC -# undef IS_NMSTRT_CHAR -# undef IS_NMSTRT_CHAR_MINBPC -# undef IS_INVALID_CHAR +#define XML_TOK_IMPL_C +#include "xmltok_impl.c" +#undef XML_TOK_IMPL_C -#endif /* not XML_MIN_SIZE */ +#undef MINBPC +#undef BYTE_TYPE +#undef BYTE_TO_ASCII +#undef CHAR_MATCHES +#undef IS_NAME_CHAR +#undef IS_NAME_CHAR_MINBPC +#undef IS_NMSTRT_CHAR +#undef IS_NMSTRT_CHAR_MINBPC +#undef IS_INVALID_CHAR #ifdef XML_NS @@ -914,76 +794,32 @@ static const struct normal_encoding internal_little2_encoding #define BIG2_IS_INVALID_CHAR(p, n) \ ((n) == 4 && ((unsigned char)(p)[2] & 0xFC) != 0xDC) -#ifdef XML_MIN_SIZE - -static int -big2_byteType(const ENCODING *enc, const char *p) { - return BIG2_BYTE_TYPE(enc, p); -} - -static int -big2_byteToAscii(const ENCODING *enc, const char *p) { - UNUSED_P(enc); - return BIG2_BYTE_TO_ASCII(p); -} - -static int -big2_charMatches(const ENCODING *enc, const char *p, int c) { - UNUSED_P(enc); - return BIG2_CHAR_MATCHES(p, c); -} - -static int -big2_isNameMin(const ENCODING *enc, const char *p) { - UNUSED_P(enc); - return BIG2_IS_NAME_CHAR_MINBPC(p); -} - -static int -big2_isNmstrtMin(const ENCODING *enc, const char *p) { - UNUSED_P(enc); - return BIG2_IS_NMSTRT_CHAR_MINBPC(p); -} - -static int -big2_isInvalid4(const ENCODING *enc, const char *p) { - UNUSED_P(enc); - return BIG2_IS_INVALID_CHAR(p, 4); -} - -# undef VTABLE -# define VTABLE VTABLE1, big2_toUtf8, big2_toUtf16 - -#else /* not XML_MIN_SIZE */ - -# undef PREFIX -# define PREFIX(ident) big2_##ident -# define MINBPC(enc) 2 +#undef PREFIX +#define PREFIX(ident) big2_##ident +#define MINBPC(enc) 2 /* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */ -# define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p) -# define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(p) -# define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(p, c) -# define IS_NAME_CHAR(enc, p, n) 0 -# define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(p) -# define IS_NMSTRT_CHAR(enc, p, n) (0) -# define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(p) -# define IS_INVALID_CHAR(enc, p, n) BIG2_IS_INVALID_CHAR(p, n) +#define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p) +#define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(p) +#define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(p, c) +#define IS_NAME_CHAR(enc, p, n) 0 +#define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(p) +#define IS_NMSTRT_CHAR(enc, p, n) (0) +#define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(p) +#define IS_INVALID_CHAR(enc, p, n) BIG2_IS_INVALID_CHAR(p, n) -# define XML_TOK_IMPL_C -# include "xmltok_impl.c" -# undef XML_TOK_IMPL_C - -# undef MINBPC -# undef BYTE_TYPE -# undef BYTE_TO_ASCII -# undef CHAR_MATCHES -# undef IS_NAME_CHAR -# undef IS_NAME_CHAR_MINBPC -# undef IS_NMSTRT_CHAR -# undef IS_NMSTRT_CHAR_MINBPC -# undef IS_INVALID_CHAR +#define XML_TOK_IMPL_C +#include "xmltok_impl.c" +#undef XML_TOK_IMPL_C -#endif /* not XML_MIN_SIZE */ +#undef MINBPC +#undef BYTE_TYPE +#undef BYTE_TO_ASCII +#undef CHAR_MATCHES +#undef IS_NAME_CHAR +#undef IS_NAME_CHAR_MINBPC +#undef IS_NMSTRT_CHAR +#undef IS_NMSTRT_CHAR_MINBPC +#undef IS_INVALID_CHAR #ifdef XML_NS diff --git a/contrib/expat/lib/xmltok_impl.c b/contrib/expat/lib/xmltok_impl.c index a71a2fd88c70..7900e94701e2 100644 --- a/contrib/expat/lib/xmltok_impl.c +++ b/contrib/expat/lib/xmltok_impl.c @@ -1,4 +1,4 @@ -/* This file is included (from xmltok.c, 1-3 times depending on XML_MIN_SIZE)! +/* This file is included (from xmltok.c, 3 times)! __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| diff --git a/contrib/expat/tests/Makefile.am b/contrib/expat/tests/Makefile.am index 21d8df2c6676..a6cf0d083698 100644 --- a/contrib/expat/tests/Makefile.am +++ b/contrib/expat/tests/Makefile.am @@ -55,8 +55,10 @@ runtests_SOURCES = \ misc_tests.c \ ns_tests.c \ nsalloc_tests.c \ + props_tests.c \ runtests.c \ - structdata.c + structdata.c \ + xcs_tests.c runtests_LDADD = ../lib/libtestpat.la @@ -76,8 +78,10 @@ EXTRA_DIST = \ misc_tests.h \ ns_tests.h \ nsalloc_tests.h \ + props_tests.h \ README.md \ structdata.h \ udiffer.py \ + xcs_tests.h \ xmltest.log.expected \ xmltest.sh diff --git a/contrib/expat/tests/Makefile.in b/contrib/expat/tests/Makefile.in index f81e113c2216..ea8554bd50ba 100644 --- a/contrib/expat/tests/Makefile.in +++ b/contrib/expat/tests/Makefile.in @@ -151,8 +151,9 @@ am_runtests_OBJECTS = acc_tests.$(OBJEXT) alloc_tests.$(OBJEXT) \ basic_tests.$(OBJEXT) chardata.$(OBJEXT) common.$(OBJEXT) \ dummy.$(OBJEXT) handlers.$(OBJEXT) hash_tests.$(OBJEXT) \ memcheck.$(OBJEXT) minicheck.$(OBJEXT) misc_tests.$(OBJEXT) \ - ns_tests.$(OBJEXT) nsalloc_tests.$(OBJEXT) runtests.$(OBJEXT) \ - structdata.$(OBJEXT) + ns_tests.$(OBJEXT) nsalloc_tests.$(OBJEXT) \ + props_tests.$(OBJEXT) runtests.$(OBJEXT) structdata.$(OBJEXT) \ + xcs_tests.$(OBJEXT) runtests_OBJECTS = $(am_runtests_OBJECTS) runtests_DEPENDENCIES = ../lib/libtestpat.la AM_V_lt = $(am__v_lt_@AM_V@) @@ -184,7 +185,8 @@ am__depfiles_remade = ./$(DEPDIR)/acc_tests.Po \ ./$(DEPDIR)/hash_tests.Po ./$(DEPDIR)/memcheck.Po \ ./$(DEPDIR)/minicheck.Po ./$(DEPDIR)/misc_tests.Po \ ./$(DEPDIR)/ns_tests.Po ./$(DEPDIR)/nsalloc_tests.Po \ - ./$(DEPDIR)/runtests.Po ./$(DEPDIR)/structdata.Po + ./$(DEPDIR)/props_tests.Po ./$(DEPDIR)/runtests.Po \ + ./$(DEPDIR)/structdata.Po ./$(DEPDIR)/xcs_tests.Po am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @@ -519,12 +521,10 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ -EXPAT_ATTR_INFO = @EXPAT_ATTR_INFO@ EXPAT_CHAR_TYPE = @EXPAT_CHAR_TYPE@ EXPAT_CONTEXT_BYTES = @EXPAT_CONTEXT_BYTES@ EXPAT_DTD = @EXPAT_DTD@ EXPAT_LARGE_SIZE = @EXPAT_LARGE_SIZE@ -EXPAT_MIN_SIZE = @EXPAT_MIN_SIZE@ EXPAT_NS = @EXPAT_NS@ FGREP = @FGREP@ FILECMD = @FILECMD@ @@ -579,7 +579,6 @@ SO_PATCH = @SO_PATCH@ STRIP = @STRIP@ VERSION = @VERSION@ VSCRIPT_LDFLAGS = @VSCRIPT_LDFLAGS@ -_EXPAT_COMMENT_ATTR_INFO = @_EXPAT_COMMENT_ATTR_INFO@ _EXPAT_COMMENT_DTD_OR_GE = @_EXPAT_COMMENT_DTD_OR_GE@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ @@ -656,8 +655,10 @@ runtests_SOURCES = \ misc_tests.c \ ns_tests.c \ nsalloc_tests.c \ + props_tests.c \ runtests.c \ - structdata.c + structdata.c \ + xcs_tests.c runtests_LDADD = ../lib/libtestpat.la runtests_LDFLAGS = @AM_LDFLAGS@ @LIBM@ @@ -675,9 +676,11 @@ EXTRA_DIST = \ misc_tests.h \ ns_tests.h \ nsalloc_tests.h \ + props_tests.h \ README.md \ structdata.h \ udiffer.py \ + xcs_tests.h \ xmltest.log.expected \ xmltest.sh @@ -742,8 +745,10 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc_tests.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ns_tests.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nsalloc_tests.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/props_tests.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/runtests.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/structdata.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xcs_tests.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @@ -1186,8 +1191,10 @@ distclean: distclean-recursive -rm -f ./$(DEPDIR)/misc_tests.Po -rm -f ./$(DEPDIR)/ns_tests.Po -rm -f ./$(DEPDIR)/nsalloc_tests.Po + -rm -f ./$(DEPDIR)/props_tests.Po -rm -f ./$(DEPDIR)/runtests.Po -rm -f ./$(DEPDIR)/structdata.Po + -rm -f ./$(DEPDIR)/xcs_tests.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -1246,8 +1253,10 @@ maintainer-clean: maintainer-clean-recursive -rm -f ./$(DEPDIR)/misc_tests.Po -rm -f ./$(DEPDIR)/ns_tests.Po -rm -f ./$(DEPDIR)/nsalloc_tests.Po + -rm -f ./$(DEPDIR)/props_tests.Po -rm -f ./$(DEPDIR)/runtests.Po -rm -f ./$(DEPDIR)/structdata.Po + -rm -f ./$(DEPDIR)/xcs_tests.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff --git a/contrib/expat/tests/acc_tests.c b/contrib/expat/tests/acc_tests.c index 5e38dee0f5e2..5e2f0f07316e 100644 --- a/contrib/expat/tests/acc_tests.c +++ b/contrib/expat/tests/acc_tests.c @@ -359,6 +359,41 @@ START_TEST(test_billion_laughs_attack_protection_api) { } END_TEST +START_TEST(test_billions_laughs_attack_protection_api_float_round_trip) { + const float values[] = {1.0f, 1.1f, INFINITY}; + + for (size_t i = 0; i < sizeof(values) / sizeof(values[0]); i++) { + set_subtest("float %f", (double)i); + const float wanted = values[i]; + + XML_Parser parser = XML_ParserCreate(NULL); + assert_true(parser != NULL); + + // Self-Test: Original value not already at target value + double actual = 123.456; + assert_true((float)actual != wanted); +# if XML_GE == 1 + assert_true( + XML_GetPropertyDouble( + parser, XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION, &actual) + == XML_PROP_ERROR_NONE); + assert_true((float)actual != wanted); // Self-Test + + // Test: Target value applied successfully + assert_true( + XML_SetBillionLaughsAttackProtectionMaximumAmplification(parser, wanted) + == XML_TRUE); + assert_true( + XML_GetPropertyDouble( + parser, XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION, &actual) + == XML_PROP_ERROR_NONE); + assert_true((float)actual == wanted); +# endif // XML_GE == 1 + XML_ParserFree(parser); + } +} +END_TEST + START_TEST(test_helper_unsigned_char_to_printable) { // Smoke test unsigned char uc = 0; @@ -451,6 +486,8 @@ make_accounting_test_case(Suite *s) { tcase_add_test(tc_accounting, test_accounting_precision); tcase_add_test(tc_accounting, test_billion_laughs_attack_protection_api); + tcase_add_test(tc_accounting, + test_billions_laughs_attack_protection_api_float_round_trip); tcase_add_test(tc_accounting, test_helper_unsigned_char_to_printable); tcase_add_test__ifdef_xml_dtd(tc_accounting, test_amplification_isolated_external_parser); diff --git a/contrib/expat/tests/alloc_tests.c b/contrib/expat/tests/alloc_tests.c index c7939708e061..690039bc9ed7 100644 --- a/contrib/expat/tests/alloc_tests.c +++ b/contrib/expat/tests/alloc_tests.c @@ -21,6 +21,7 @@ Copyright (c) 2023 Sony Corporation / Snild Dolkow <snild@sony.com> Copyright (c) 2025 Berkay Eren Ürün <berkay.ueruen@siemens.com> Copyright (c) 2026 Matthew Fernandez <matthew.fernandez@gmail.com> + Copyright (c) 2026 Filippo Tedeschi <filippotedeschi98@gmail.com> Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -563,6 +564,24 @@ START_TEST(test_alloc_explicit_encoding) { } END_TEST +/* Test robustness of XML_ParserReset() with a failing allocator when setting + * encoding */ +START_TEST(test_alloc_reset_encoding) { + int i; + const int max_alloc_count = 5; + + for (i = 0; i < max_alloc_count; i++) { + g_allocation_count = i; + if (XML_ParserReset(g_parser, XCS("us-ascii")) == XML_TRUE) + break; + } + if (i == 0) + fail("Reset with encoding succeeded despite failing allocator"); + else if (i == max_alloc_count) + fail("Reset with encoding failed at max allocation count"); +} +END_TEST + /* Test robustness of XML_SetBase against a failing allocator */ START_TEST(test_alloc_set_base) { const XML_Char *new_base = XCS("/local/file/name.xml"); @@ -2118,6 +2137,10 @@ START_TEST(test_alloc_tracker_size_recorded) { assert_true(ptr != NULL); assert_true(sizeRecordedFor(ptr) == 10); + assert_true(expat_realloc(parser, ptr, SIZE_MAX, -1) == NULL); + + assert_true(sizeRecordedFor(ptr) == 10); // i.e. unchanged + assert_true(expat_realloc(parser, ptr, SIZE_MAX / 2, -1) == NULL); assert_true(sizeRecordedFor(ptr) == 10); // i.e. unchanged @@ -2273,6 +2296,40 @@ START_TEST(test_alloc_tracker_api) { } END_TEST +START_TEST(test_alloc_tracker_api_float_round_trip) { + const float values[] = {1.0f, 1.1f, INFINITY}; + + for (size_t i = 0; i < sizeof(values) / sizeof(values[0]); i++) { + set_subtest("float %f", (double)i); + const float wanted = values[i]; + + XML_Parser parser = XML_ParserCreate(NULL); + assert_true(parser != NULL); + + // Self-Test: Original value not already at target value + double actual = 123.456; + assert_true((float)actual != wanted); +#if XML_GE == 1 + assert_true( + XML_GetPropertyDouble( + parser, XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION, &actual) + == XML_PROP_ERROR_NONE); + assert_true((float)actual != wanted); // Self-Test + + // Test: Target value applied successfully + assert_true(XML_SetAllocTrackerMaximumAmplification(parser, wanted) + == XML_TRUE); + assert_true( + XML_GetPropertyDouble( + parser, XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION, &actual) + == XML_PROP_ERROR_NONE); + assert_true((float)actual == wanted); +#endif // XML_GE == 1 + XML_ParserFree(parser); + } +} +END_TEST + START_TEST(test_mem_api_cycle) { XML_Parser parser = XML_ParserCreate(NULL); @@ -2336,6 +2393,7 @@ make_alloc_test_case(Suite *s) { tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_parameter_entity); tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_default_handling); tcase_add_test(tc_alloc, test_alloc_explicit_encoding); + tcase_add_test(tc_alloc, test_alloc_reset_encoding); tcase_add_test(tc_alloc, test_alloc_set_base); tcase_add_test(tc_alloc, test_alloc_realloc_buffer); tcase_add_test__if_xml_ge(tc_alloc, test_alloc_ext_entity_realloc_buffer); @@ -2386,6 +2444,7 @@ make_alloc_test_case(Suite *s) { tcase_add_test__if_xml_ge(tc_alloc, test_alloc_tracker_threshold); tcase_add_test__if_xml_ge(tc_alloc, test_alloc_tracker_getbuffer_unlimited); tcase_add_test__if_xml_ge(tc_alloc, test_alloc_tracker_api); + tcase_add_test__if_xml_ge(tc_alloc, test_alloc_tracker_api_float_round_trip); tcase_add_test(tc_alloc, test_mem_api_cycle); tcase_add_test__if_xml_ge(tc_alloc, test_mem_api_unlimited); diff --git a/contrib/expat/tests/basic_tests.c b/contrib/expat/tests/basic_tests.c index 8f4f0902d5c7..c7fd3d19d28b 100644 --- a/contrib/expat/tests/basic_tests.c +++ b/contrib/expat/tests/basic_tests.c @@ -26,6 +26,7 @@ Copyright (c) 2026 Zeyou Liu <zeyouliu@tencent.com> Copyright (c) 2026 Afonso Januário <afonso-januario@hotmail.com> Copyright (c) 2026 Braian Plaku <braianplaku@gmail.com> + Copyright (c) 2026 Filippo Tedeschi <filippotedeschi98@gmail.com> Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -57,7 +58,8 @@ #include "expat_config.h" #include <assert.h> -#include <limits.h> // ULONG_MAX +#include <inttypes.h> // PRIu64 +#include <limits.h> // ULONG_MAX #include <stdbool.h> #include <stdio.h> #include <string.h> @@ -72,6 +74,7 @@ #include "handlers.h" #include "siphash.h" #include "basic_tests.h" +#include "../lib/xcs.h" #define EXPAT_TESTS_ASAN 1 @@ -646,16 +649,15 @@ START_TEST(test_line_number_after_parse) { const char *text = "<tag>\n" "\n" "\n</tag>"; - XML_Size lineno; + uint64_t lineno; if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) == XML_STATUS_ERROR) xml_failure(g_parser); - lineno = XML_GetCurrentLineNumber(g_parser); + lineno = XML_GetCurrentLineNumber64(g_parser); if (lineno != 4) { char buffer[100]; - snprintf(buffer, sizeof(buffer), - "expected 4 lines, saw %" XML_FMT_INT_MOD "u", lineno); + snprintf(buffer, sizeof(buffer), "expected 4 lines, saw %" PRIu64, lineno); fail(buffer); } } @@ -664,16 +666,16 @@ END_TEST /* Regression test #2 for SF bug #653180. */ START_TEST(test_column_number_after_parse) { const char *text = "<tag></tag>"; - XML_Size colno; + uint64_t colno; if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) == XML_STATUS_ERROR) xml_failure(g_parser); - colno = XML_GetCurrentColumnNumber(g_parser); + colno = XML_GetCurrentColumnNumber64(g_parser); if (colno != 11) { char buffer[100]; - snprintf(buffer, sizeof(buffer), - "expected 11 columns, saw %" XML_FMT_INT_MOD "u", colno); + snprintf(buffer, sizeof(buffer), "expected 11 columns, saw %" PRIu64, + colno); fail(buffer); } } @@ -716,16 +718,15 @@ START_TEST(test_line_number_after_error) { const char *text = "<a>\n" " <b>\n" " </a>"; /* missing </b> */ - XML_Size lineno; + uint64_t lineno; if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) fail("Expected a parse error"); - lineno = XML_GetCurrentLineNumber(g_parser); + lineno = XML_GetCurrentLineNumber64(g_parser); if (lineno != 3) { char buffer[100]; - snprintf(buffer, sizeof(buffer), - "expected 3 lines, saw %" XML_FMT_INT_MOD "u", lineno); + snprintf(buffer, sizeof(buffer), "expected 3 lines, saw %" PRIu64, lineno); fail(buffer); } } @@ -736,16 +737,15 @@ START_TEST(test_column_number_after_error) { const char *text = "<a>\n" " <b>\n" " </a>"; /* missing </b> */ - XML_Size colno; + uint64_t colno; if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) fail("Expected a parse error"); - colno = XML_GetCurrentColumnNumber(g_parser); + colno = XML_GetCurrentColumnNumber64(g_parser); if (colno != 4) { char buffer[100]; - snprintf(buffer, sizeof(buffer), - "expected 4 columns, saw %" XML_FMT_INT_MOD "u", colno); + snprintf(buffer, sizeof(buffer), "expected 4 columns, saw %" PRIu64, colno); fail(buffer); } } @@ -921,9 +921,8 @@ check_attr_contains_normalized_whitespace(void *userData, const XML_Char *name, for (i = 0; atts[i] != NULL; i += 2) { const XML_Char *attrname = atts[i]; const XML_Char *value = atts[i + 1]; - if (xcstrcmp(XCS("attr"), attrname) == 0 - || xcstrcmp(XCS("ents"), attrname) == 0 - || xcstrcmp(XCS("refs"), attrname) == 0) { + if (xcscmp(XCS("attr"), attrname) == 0 || xcscmp(XCS("ents"), attrname) == 0 + || xcscmp(XCS("refs"), attrname) == 0) { if (! is_whitespace_normalized(value, 0)) { char buffer[256]; snprintf(buffer, sizeof(buffer), @@ -2598,6 +2597,57 @@ START_TEST(test_default_current) { } END_TEST +/* Test XML_DefaultCurrent does not dereference NULL when outside an event */ +START_TEST(test_default_current_outside_event) { + struct handler_record_list handlerCalls; + handlerCalls.count = 0; + + set_subtest("NULL parser"); + XML_DefaultCurrent(NULL); + + set_subtest("before parse"); + { + XML_Parser parser = XML_ParserCreate(NULL); + XML_SetDefaultHandler(parser, record_default_handler); + XML_SetUserData(parser, &handlerCalls); + + XML_DefaultCurrent(parser); + assert_true(handlerCalls.count == 0); + + XML_ParserFree(parser); + } + + set_subtest("after parse"); + { + const char *text = "<r>hello</r>"; + XML_Parser parser = XML_ParserCreate(NULL); + if (XML_Parse(parser, text, (int)strlen(text), XML_TRUE) + == XML_STATUS_ERROR) + xml_failure(parser); + + XML_SetDefaultHandler(parser, record_default_handler); + XML_SetUserData(parser, &handlerCalls); + + XML_DefaultCurrent(parser); + assert_true(handlerCalls.count == 0); + + XML_ParserFree(parser); + } + + set_subtest("explicit encoding before parse"); + { + XML_Parser parser = XML_ParserCreate(XCS("ISO-8859-1")); + XML_SetDefaultHandler(parser, record_default_handler); + XML_SetUserData(parser, &handlerCalls); + + XML_DefaultCurrent(parser); + assert_true(handlerCalls.count == 0); + + XML_ParserFree(parser); + } +} +END_TEST + /* Test DTD element parsing code paths */ START_TEST(test_dtd_elements) { const char *text = "<!DOCTYPE doc [\n" @@ -2627,7 +2677,7 @@ element_decl_check_model(void *userData, const XML_Char *name, * [5] (type 4, quant 3, name "xyz") * [2] (type 4, quant 2, name "zebra") */ - errorFlags |= ((xcstrcmp(name, XCS("junk")) == 0) ? 0 : (1u << 0)); + errorFlags |= ((xcscmp(name, XCS("junk")) == 0) ? 0 : (1u << 0)); errorFlags |= ((model != NULL) ? 0 : (1u << 1)); if (model != NULL) { @@ -2647,26 +2697,25 @@ element_decl_check_model(void *userData, const XML_Char *name, errorFlags |= ((model[2].quant == XML_CQUANT_REP) ? 0 : (1u << 13)); errorFlags |= ((model[2].numchildren == 0) ? 0 : (1u << 14)); errorFlags |= ((model[2].children == NULL) ? 0 : (1u << 15)); - errorFlags - |= ((xcstrcmp(model[2].name, XCS("zebra")) == 0) ? 0 : (1u << 16)); + errorFlags |= ((xcscmp(model[2].name, XCS("zebra")) == 0) ? 0 : (1u << 16)); errorFlags |= ((model[3].type == XML_CTYPE_NAME) ? 0 : (1u << 17)); errorFlags |= ((model[3].quant == XML_CQUANT_NONE) ? 0 : (1u << 18)); errorFlags |= ((model[3].numchildren == 0) ? 0 : (1u << 19)); errorFlags |= ((model[3].children == NULL) ? 0 : (1u << 20)); - errorFlags |= ((xcstrcmp(model[3].name, XCS("bar")) == 0) ? 0 : (1u << 21)); + errorFlags |= ((xcscmp(model[3].name, XCS("bar")) == 0) ? 0 : (1u << 21)); errorFlags |= ((model[4].type == XML_CTYPE_NAME) ? 0 : (1u << 22)); errorFlags |= ((model[4].quant == XML_CQUANT_NONE) ? 0 : (1u << 23)); errorFlags |= ((model[4].numchildren == 0) ? 0 : (1u << 24)); errorFlags |= ((model[4].children == NULL) ? 0 : (1u << 25)); - errorFlags |= ((xcstrcmp(model[4].name, XCS("foo")) == 0) ? 0 : (1u << 26)); + errorFlags |= ((xcscmp(model[4].name, XCS("foo")) == 0) ? 0 : (1u << 26)); errorFlags |= ((model[5].type == XML_CTYPE_NAME) ? 0 : (1u << 27)); errorFlags |= ((model[5].quant == XML_CQUANT_PLUS) ? 0 : (1u << 28)); errorFlags |= ((model[5].numchildren == 0) ? 0 : (1u << 29)); errorFlags |= ((model[5].children == NULL) ? 0 : (1u << 30)); - errorFlags |= ((xcstrcmp(model[5].name, XCS("xyz")) == 0) ? 0 : (1u << 31)); + errorFlags |= ((xcscmp(model[5].name, XCS("xyz")) == 0) ? 0 : (1u << 31)); } XML_SetUserData(g_parser, (void *)(uintptr_t)errorFlags); @@ -2833,7 +2882,7 @@ START_TEST(test_set_base) { old_base = XML_GetBase(g_parser); if (XML_SetBase(g_parser, new_base) != XML_STATUS_OK) fail("Unable to set base"); - if (xcstrcmp(XML_GetBase(g_parser), new_base) != 0) + if (xcscmp(XML_GetBase(g_parser), new_base) != 0) fail("Base setting not correct"); if (XML_SetBase(g_parser, NULL) != XML_STATUS_OK) fail("Unable to NULL base"); @@ -3160,12 +3209,12 @@ check_second_attr_normalization(void *userData, const XML_Char *name, for (size_t i = 0; atts[i] != NULL; i += 2) { const XML_Char *const key = atts[i]; const XML_Char *const value = atts[i + 1]; - if (xcstrcmp(key, XCS("second")) != 0) + if (xcscmp(key, XCS("second")) != 0) continue; *seen_second = 1; /* Attribute "second" is not of type CDATA, so leading, trailing and * repeated whitespace is to be normalized away. */ - if (xcstrcmp(value, XCS("a b")) != 0) + if (xcscmp(value, XCS("a b")) != 0) fail("Attribute of non-CDATA type was not whitespace-normalized"); } } @@ -3725,6 +3774,46 @@ START_TEST(test_negative_len_parse_buffer) { } END_TEST +/* Test XML_ParseBuffer rejects calls where len exceeds available buffer */ +START_TEST(test_parse_buffer_exceeds_buffer) { + for (int isFinal = 0; isFinal < 2; isFinal++) { + set_subtest("isFinal=%d", isFinal); + + XML_Parser parser = XML_ParserCreate(NULL); + + /* Calling XML_ParseBuffer without any prior XML_GetBuffer call */ + if (XML_ParseBuffer(parser, 10, isFinal) != XML_STATUS_ERROR) + fail("XML_ParseBuffer without XML_GetBuffer was expected to fail."); + if (XML_GetErrorCode(parser) != XML_ERROR_NO_BUFFER) + fail("Expected XML_ERROR_NO_BUFFER."); + + /* Acquire a small buffer */ + void *const buffer = XML_GetBuffer(parser, 10); + if (buffer == NULL) + fail("XML_GetBuffer failed."); + + /* Calling XML_ParseBuffer with len exceeding available buffer capacity */ + if (XML_ParseBuffer(parser, 10000, isFinal) != XML_STATUS_ERROR) + fail("XML_ParseBuffer with len > capacity was expected to fail."); + if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_ARGUMENT) + fail("Expected XML_ERROR_INVALID_ARGUMENT."); + + /* Valid parse */ + memcpy(buffer, "<r></r>", 7); + if (XML_ParseBuffer(parser, 7, XML_FALSE) != XML_STATUS_OK) + xml_failure(parser); + + /* Subsequent XML_ParseBuffer where len exceeds remaining capacity */ + if (XML_ParseBuffer(parser, 10000, isFinal) != XML_STATUS_ERROR) + fail("XML_ParseBuffer on subsequent chunk was expected to fail."); + if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_ARGUMENT) + fail("Expected XML_ERROR_INVALID_ARGUMENT."); + + XML_ParserFree(parser); + } +} +END_TEST + /* Test odd corners of the XML_GetBuffer interface */ static enum XML_Status get_feature(enum XML_FeatureEnum feature_id, long *presult) { @@ -3907,16 +3996,16 @@ END_TEST START_TEST(test_byte_info_at_end) { const char *text = "<doc></doc>"; - if (XML_GetCurrentByteIndex(g_parser) != -1 - || XML_GetCurrentByteCount(g_parser) != 0) + if (XML_GetCurrentByteIndex64(g_parser) != -1 + || XML_GetCurrentByteCount64(g_parser) != 0) fail("Byte index/count incorrect at start of parse"); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) == XML_STATUS_ERROR) xml_failure(g_parser); /* At end, the count will be zero and the index the end of string */ - if (XML_GetCurrentByteCount(g_parser) != 0) + if (XML_GetCurrentByteCount64(g_parser) != 0) fail("Terminal byte count incorrect"); - if (XML_GetCurrentByteIndex(g_parser) != (XML_Index)strlen(text)) + if (XML_GetCurrentByteIndex64(g_parser) != (int64_t)strlen(text)) fail("Terminal byte index incorrect"); } END_TEST @@ -3930,9 +4019,9 @@ START_TEST(test_byte_info_at_error) { if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) == XML_STATUS_OK) fail("Syntax error not faulted"); - if (XML_GetCurrentByteCount(g_parser) != 0) + if (XML_GetCurrentByteCount64(g_parser) != 0) fail("Error byte count incorrect"); - if (XML_GetCurrentByteIndex(g_parser) != strlen(PRE_ERROR_STR)) + if (XML_GetCurrentByteIndex64(g_parser) != strlen(PRE_ERROR_STR)) fail("Error byte index incorrect"); } END_TEST @@ -3945,11 +4034,12 @@ END_TEST #define END_ELEMENT "</e>" START_TEST(test_byte_info_at_cdata) { const char *text = START_ELEMENT CDATA_TEXT END_ELEMENT; - int offset, size; + int64_t offset; + uint64_t size; ByteTestData data; /* Check initial context is empty */ - if (XML_GetInputContext(g_parser, &offset, &size) != NULL) + if (XML_GetInputContext64(g_parser, &offset, &size) != NULL) fail("Unexpected context at start of parse"); data.start_element_len = (int)strlen(START_ELEMENT); @@ -4150,7 +4240,7 @@ external_bom_checker(XML_Parser parser, const XML_Char *context, if (ext_parser == NULL) fail("Could not create external entity parser"); - if (! xcstrcmp(systemId, XCS("004-2.ent"))) { + if (! xcscmp(systemId, XCS("004-2.ent"))) { struct bom_testdata *const testdata = XML_GetUserData(parser); const char *const external = testdata->external; const int split = testdata->split; @@ -4161,7 +4251,7 @@ external_bom_checker(XML_Parser parser, const XML_Char *context, xml_failure(ext_parser); } text = external + split; // the parse below will continue where we left off. - } else if (! xcstrcmp(systemId, XCS("004-1.ent"))) { + } else if (! xcscmp(systemId, XCS("004-1.ent"))) { text = "<!ELEMENT doc EMPTY>\n" "<!ENTITY % e1 SYSTEM '004-2.ent'>\n" "<!ENTITY % e2 '%e1;'>\n"; @@ -7139,6 +7229,7 @@ make_basic_test_case(Suite *s) { tcase_add_test(tc_basic, test_suspend_parser_between_cdata_calls); tcase_add_test(tc_basic, test_memory_allocation); tcase_add_test__if_xml_ge(tc_basic, test_default_current); + tcase_add_test(tc_basic, test_default_current_outside_event); 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); @@ -7181,6 +7272,7 @@ make_basic_test_case(Suite *s) { tcase_add_test(tc_basic, test_empty_parse); tcase_add_test(tc_basic, test_negative_len_parse); tcase_add_test(tc_basic, test_negative_len_parse_buffer); + tcase_add_test(tc_basic, test_parse_buffer_exceeds_buffer); tcase_add_test(tc_basic, test_get_buffer_1); tcase_add_test(tc_basic, test_get_buffer_2); #if XML_CONTEXT_BYTES > 0 diff --git a/contrib/expat/tests/benchmark/Makefile.in b/contrib/expat/tests/benchmark/Makefile.in index 4156629984be..894e6bdbae4f 100644 --- a/contrib/expat/tests/benchmark/Makefile.in +++ b/contrib/expat/tests/benchmark/Makefile.in @@ -252,12 +252,10 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ -EXPAT_ATTR_INFO = @EXPAT_ATTR_INFO@ EXPAT_CHAR_TYPE = @EXPAT_CHAR_TYPE@ EXPAT_CONTEXT_BYTES = @EXPAT_CONTEXT_BYTES@ EXPAT_DTD = @EXPAT_DTD@ EXPAT_LARGE_SIZE = @EXPAT_LARGE_SIZE@ -EXPAT_MIN_SIZE = @EXPAT_MIN_SIZE@ EXPAT_NS = @EXPAT_NS@ FGREP = @FGREP@ FILECMD = @FILECMD@ @@ -312,7 +310,6 @@ SO_PATCH = @SO_PATCH@ STRIP = @STRIP@ VERSION = @VERSION@ VSCRIPT_LDFLAGS = @VSCRIPT_LDFLAGS@ -_EXPAT_COMMENT_ATTR_INFO = @_EXPAT_COMMENT_ATTR_INFO@ _EXPAT_COMMENT_DTD_OR_GE = @_EXPAT_COMMENT_DTD_OR_GE@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ diff --git a/contrib/expat/tests/benchmark/benchmark.c b/contrib/expat/tests/benchmark/benchmark.c index a02b84a0131d..48658e5a464e 100644 --- a/contrib/expat/tests/benchmark/benchmark.c +++ b/contrib/expat/tests/benchmark/benchmark.c @@ -8,7 +8,7 @@ Copyright (c) 2003-2006 Karl Waclawek <karl@waclawek.net> Copyright (c) 2005-2007 Steven Solie <steven@solie.ca> - Copyright (c) 2017-2025 Sebastian Pipping <sebastian@pipping.org> + Copyright (c) 2017-2026 Sebastian Pipping <sebastian@pipping.org> Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> Licensed under the MIT license: @@ -40,7 +40,8 @@ # include <unistd.h> // close #endif -#include <fcntl.h> // open +#include <inttypes.h> // PRIu64 +#include <fcntl.h> // open #include <sys/stat.h> #include <assert.h> #include <stddef.h> // ptrdiff_t @@ -48,12 +49,6 @@ #include <time.h> #include "expat.h" -#ifdef XML_LARGE_SIZE -# define XML_FMT_INT_MOD "ll" -#else -# define XML_FMT_INT_MOD "l" -#endif - #ifdef XML_UNICODE_WCHAR_T # define XML_FMT_STR "ls" #else @@ -148,11 +143,11 @@ main(int argc, char *argv[]) { assert(parseBufferSize <= (ptrdiff_t)bufferSize); if (! XML_Parse(parser, XMLBufPtr, (int)parseBufferSize, isFinal)) { fprintf(stderr, - "error '%" XML_FMT_STR "' at line %" XML_FMT_INT_MOD - "u character %" XML_FMT_INT_MOD "u\n", + "error '%" XML_FMT_STR "' at line %" PRIu64 + " character %" PRIu64 "\n", XML_ErrorString(XML_GetErrorCode(parser)), - XML_GetCurrentLineNumber(parser), - XML_GetCurrentColumnNumber(parser)); + XML_GetCurrentLineNumber64(parser), + XML_GetCurrentColumnNumber64(parser)); free(XMLBuf); XML_ParserFree(parser); return 4; diff --git a/contrib/expat/tests/chardata.c b/contrib/expat/tests/chardata.c index a36d58c24f36..a9d917f1d0fc 100644 --- a/contrib/expat/tests/chardata.c +++ b/contrib/expat/tests/chardata.c @@ -9,7 +9,7 @@ Copyright (c) 2002-2004 Fred L. Drake, Jr. <fdrake@users.sourceforge.net> Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net> Copyright (c) 2016 Gilles Espinasse <g.esp@free.fr> - Copyright (c) 2016-2023 Sebastian Pipping <sebastian@pipping.org> + Copyright (c) 2016-2026 Sebastian Pipping <sebastian@pipping.org> Copyright (c) 2017 Joe Orton <jorton@redhat.com> Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> Copyright (c) 2022 Sean McBride <sean@rogue-research.com> @@ -49,7 +49,7 @@ #include <string.h> #include "chardata.h" -#include "../lib/xcsinc.c" +#include "../lib/xcs.h" void CharData_Init(CharData *storage) { diff --git a/contrib/expat/tests/common.c b/contrib/expat/tests/common.c index e2980cbcadbd..51509a7f0a1b 100644 --- a/contrib/expat/tests/common.c +++ b/contrib/expat/tests/common.c @@ -48,7 +48,8 @@ #include <assert.h> #include <errno.h> -#include <stdint.h> // for SIZE_MAX +#include <inttypes.h> // for PRIu64 +#include <stdint.h> // for SIZE_MAX #include <stdio.h> #include <string.h> @@ -188,10 +189,10 @@ _xml_failure(XML_Parser parser, const char *file, int line) { char buffer[1024]; enum XML_Error err = XML_GetErrorCode(parser); snprintf(buffer, sizeof(buffer), - " %d: %" XML_FMT_STR " (line %" XML_FMT_INT_MOD - "u, offset %" XML_FMT_INT_MOD "u)\n reported from %s, line %d\n", - err, XML_ErrorString(err), XML_GetCurrentLineNumber(parser), - XML_GetCurrentColumnNumber(parser), file, line); + " %d: %" XML_FMT_STR " (line %" PRIu64 ", offset %" PRIu64 + ")\n reported from %s, line %d\n", + err, XML_ErrorString(err), XML_GetCurrentLineNumber64(parser), + XML_GetCurrentColumnNumber64(parser), file, line); _fail(file, line, buffer); } diff --git a/contrib/expat/tests/common.h b/contrib/expat/tests/common.h index f9bde995e7d2..a7a6bf51ea15 100644 --- a/contrib/expat/tests/common.h +++ b/contrib/expat/tests/common.h @@ -59,9 +59,6 @@ #ifdef XML_UNICODE_WCHAR_T # define XML_FMT_STR "ls" # include <wchar.h> -# define xcstrlen(s) wcslen(s) -# define xcstrcmp(s, t) wcscmp((s), (t)) -# define xcstrncmp(s, t, n) wcsncmp((s), (t), (n)) # define XCS(s) _XCS(s) # define _XCS(s) L##s #else @@ -69,9 +66,6 @@ # error "No support for UTF-16 character without wchar_t in tests" # else # define XML_FMT_STR "s" -# define xcstrlen(s) strlen(s) -# define xcstrcmp(s, t) strcmp((s), (t)) -# define xcstrncmp(s, t, n) strncmp((s), (t), (n)) # define XCS(s) s # endif /* XML_UNICODE */ #endif /* XML_UNICODE_WCHAR_T */ diff --git a/contrib/expat/tests/handlers.c b/contrib/expat/tests/handlers.c index 7fc4b7e50cd6..57ca4e51df77 100644 --- a/contrib/expat/tests/handlers.c +++ b/contrib/expat/tests/handlers.c @@ -63,6 +63,7 @@ #include "structdata.h" #include "common.h" #include "handlers.h" +#include "../lib/xcs.h" /* Global variables for user parameter settings tests */ /* Variable holding the expected handler userData */ @@ -95,15 +96,16 @@ start_element_event_handler2(void *userData, const XML_Char *name, const XML_Char **attr) { StructData *storage = (StructData *)userData; UNUSED_P(attr); - StructData_AddItem(storage, name, (int)XML_GetCurrentColumnNumber(g_parser), - (int)XML_GetCurrentLineNumber(g_parser), STRUCT_START_TAG); + StructData_AddItem(storage, name, (int)XML_GetCurrentColumnNumber64(g_parser), + (int)XML_GetCurrentLineNumber64(g_parser), + STRUCT_START_TAG); } void XMLCALL end_element_event_handler2(void *userData, const XML_Char *name) { StructData *storage = (StructData *)userData; - StructData_AddItem(storage, name, (int)XML_GetCurrentColumnNumber(g_parser), - (int)XML_GetCurrentLineNumber(g_parser), STRUCT_END_TAG); + StructData_AddItem(storage, name, (int)XML_GetCurrentColumnNumber64(g_parser), + (int)XML_GetCurrentLineNumber64(g_parser), STRUCT_END_TAG); } void XMLCALL @@ -116,7 +118,7 @@ counting_start_element_handler(void *userData, const XML_Char *name, int count, id, i; while (info->name != NULL) { - if (! xcstrcmp(name, info->name)) + if (! xcscmp(name, info->name)) break; info++; } @@ -138,14 +140,14 @@ counting_start_element_handler(void *userData, const XML_Char *name, fail("ID not present"); return; } - if (id != -1 && xcstrcmp(atts[id], info->id_name) != 0) { + if (id != -1 && xcscmp(atts[id], info->id_name) != 0) { fail("ID does not have the correct name"); return; } for (i = 0; i < info->attr_count + info->default_attr_count; i++) { attr = info->attributes; while (attr->name != NULL) { - if (! xcstrcmp(atts[0], attr->name)) + if (! xcscmp(atts[0], attr->name)) break; attr++; } @@ -153,7 +155,7 @@ counting_start_element_handler(void *userData, const XML_Char *name, fail("Attribute not recognised"); return; } - if (xcstrcmp(atts[1], attr->value) != 0) { + if (xcscmp(atts[1], attr->value) != 0) { fail("Attribute has wrong value"); return; } @@ -176,9 +178,9 @@ start_element_suspender(void *userData, const XML_Char *name, const XML_Char **atts) { UNUSED_P(userData); UNUSED_P(atts); - if (! xcstrcmp(name, XCS("suspend"))) + if (! xcscmp(name, XCS("suspend"))) XML_StopParser(g_parser, XML_TRUE); - if (! xcstrcmp(name, XCS("abort"))) + if (! xcscmp(name, XCS("abort"))) XML_StopParser(g_parser, XML_FALSE); } @@ -195,12 +197,12 @@ triplet_start_checker(void *userData, const XML_Char *name, const XML_Char **atts) { XML_Char **elemstr = (XML_Char **)userData; char buffer[1024]; - if (xcstrcmp(elemstr[0], name) != 0) { + if (xcscmp(elemstr[0], name) != 0) { snprintf(buffer, sizeof(buffer), "unexpected start string: '%" XML_FMT_STR "'", name); fail(buffer); } - if (xcstrcmp(elemstr[1], atts[0]) != 0) { + if (xcscmp(elemstr[1], atts[0]) != 0) { snprintf(buffer, sizeof(buffer), "unexpected attribute string: '%" XML_FMT_STR "'", atts[0]); fail(buffer); @@ -215,7 +217,7 @@ triplet_start_checker(void *userData, const XML_Char *name, void XMLCALL triplet_end_checker(void *userData, const XML_Char *name) { XML_Char **elemstr = (XML_Char **)userData; - if (xcstrcmp(elemstr[0], name) != 0) { + if (xcscmp(elemstr[0], name) != 0) { char buffer[1024]; snprintf(buffer, sizeof(buffer), "unexpected end string: '%" XML_FMT_STR "'", name); @@ -291,7 +293,7 @@ int XMLCALL UnknownEncodingHandler(void *data, const XML_Char *encoding, XML_Encoding *info) { UNUSED_P(data); - if (xcstrcmp(encoding, XCS("unsupported-encoding")) == 0) { + if (xcscmp(encoding, XCS("unsupported-encoding")) == 0) { int i; for (i = 0; i < 256; ++i) info->map[i] = i; @@ -323,7 +325,7 @@ int XMLCALL unknown_released_encoding_handler(void *data, const XML_Char *encoding, XML_Encoding *info) { UNUSED_P(data); - if (! xcstrcmp(encoding, XCS("unsupported-encoding"))) { + if (! xcscmp(encoding, XCS("unsupported-encoding"))) { int i; for (i = 0; i < 256; i++) @@ -359,12 +361,12 @@ MiscEncodingHandler(void *data, const XML_Char *encoding, XML_Encoding *info) { int i; int high_map = -2; /* Assume a 2-byte sequence */ - if (! xcstrcmp(encoding, XCS("invalid-9")) - || ! xcstrcmp(encoding, XCS("ascii-like")) - || ! xcstrcmp(encoding, XCS("invalid-len")) - || ! xcstrcmp(encoding, XCS("invalid-a")) - || ! xcstrcmp(encoding, XCS("invalid-surrogate")) - || ! xcstrcmp(encoding, XCS("invalid-high"))) + if (! xcscmp(encoding, XCS("invalid-9")) + || ! xcscmp(encoding, XCS("ascii-like")) + || ! xcscmp(encoding, XCS("invalid-len")) + || ! xcscmp(encoding, XCS("invalid-a")) + || ! xcscmp(encoding, XCS("invalid-surrogate")) + || ! xcscmp(encoding, XCS("invalid-high"))) high_map = -1; for (i = 0; i < 128; ++i) @@ -373,28 +375,28 @@ MiscEncodingHandler(void *data, const XML_Char *encoding, XML_Encoding *info) { info->map[i] = high_map; /* If required, put an invalid value in the ASCII entries */ - if (! xcstrcmp(encoding, XCS("invalid-9"))) + if (! xcscmp(encoding, XCS("invalid-9"))) info->map[9] = 5; /* If required, have a top-bit set character starts a 5-byte sequence */ - if (! xcstrcmp(encoding, XCS("invalid-len"))) + if (! xcscmp(encoding, XCS("invalid-len"))) info->map[0x81] = -5; /* If required, make a top-bit set character a valid ASCII character */ - if (! xcstrcmp(encoding, XCS("invalid-a"))) + if (! xcscmp(encoding, XCS("invalid-a"))) info->map[0x82] = 'a'; /* If required, give a top-bit set character a forbidden value, * what would otherwise be the first of a surrogate pair. */ - if (! xcstrcmp(encoding, XCS("invalid-surrogate"))) + if (! xcscmp(encoding, XCS("invalid-surrogate"))) info->map[0x83] = 0xd801; /* If required, give a top-bit set character too high a value */ - if (! xcstrcmp(encoding, XCS("invalid-high"))) + if (! xcscmp(encoding, XCS("invalid-high"))) info->map[0x84] = 0x010101; info->data = data; info->release = NULL; - if (! xcstrcmp(encoding, XCS("failing-conv"))) + if (! xcscmp(encoding, XCS("failing-conv"))) info->convert = failing_converter; - else if (! xcstrcmp(encoding, XCS("prefix-conv"))) + else if (! xcscmp(encoding, XCS("prefix-conv"))) info->convert = prefix_converter; else info->convert = NULL; @@ -437,7 +439,7 @@ external_entity_optioner(XML_Parser parser, const XML_Char *context, UNUSED_P(base); UNUSED_P(publicId); while (options->parse_text != NULL) { - if (! xcstrcmp(systemId, options->system_id)) { + if (! xcscmp(systemId, options->system_id)) { enum XML_Status rc; ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); if (ext_parser == NULL) @@ -874,13 +876,13 @@ external_entity_param(XML_Parser parser, const XML_Char *context, if (ext_parser == NULL) fail("Could not create external entity parser"); - if (! xcstrcmp(systemId, XCS("004-1.ent"))) { + if (! xcscmp(systemId, XCS("004-1.ent"))) { if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE) != XML_STATUS_ERROR) fail("Inner DTD with invalid tag not rejected"); if (XML_GetErrorCode(ext_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING) xml_failure(ext_parser); - } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) { + } else if (! xcscmp(systemId, XCS("004-2.ent"))) { if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE) != XML_STATUS_ERROR) fail("Invalid tag in external param not rejected"); @@ -984,11 +986,11 @@ external_entity_valuer(XML_Parser parser, const XML_Char *context, ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); if (ext_parser == NULL) fail("Could not create external entity parser"); - if (! xcstrcmp(systemId, XCS("004-1.ent"))) { + if (! xcscmp(systemId, XCS("004-1.ent"))) { if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE) == XML_STATUS_ERROR) xml_failure(ext_parser); - } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) { + } else if (! xcscmp(systemId, XCS("004-2.ent"))) { ExtFaults *fault = XML_GetUserData(parser); enum XML_Status status; enum XML_Error error; @@ -1030,7 +1032,7 @@ external_entity_not_standalone(XML_Parser parser, const XML_Char *context, ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); if (ext_parser == NULL) fail("Could not create external entity parser"); - if (! xcstrcmp(systemId, XCS("foo"))) { + if (! xcscmp(systemId, XCS("foo"))) { XML_SetNotStandaloneHandler(ext_parser, reject_not_standalone_handler); if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE) != XML_STATUS_ERROR) @@ -1040,7 +1042,7 @@ external_entity_not_standalone(XML_Parser parser, const XML_Char *context, XML_SetNotStandaloneHandler(ext_parser, NULL); XML_ParserFree(ext_parser); return XML_STATUS_ERROR; - } else if (! xcstrcmp(systemId, XCS("bar"))) { + } else if (! xcscmp(systemId, XCS("bar"))) { if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE) == XML_STATUS_ERROR) xml_failure(ext_parser); @@ -1068,12 +1070,12 @@ external_entity_value_aborter(XML_Parser parser, const XML_Char *context, ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); if (ext_parser == NULL) fail("Could not create external entity parser"); - if (! xcstrcmp(systemId, XCS("004-1.ent"))) { + if (! xcscmp(systemId, XCS("004-1.ent"))) { if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE) == XML_STATUS_ERROR) xml_failure(ext_parser); } - if (! xcstrcmp(systemId, XCS("004-2.ent"))) { + if (! xcscmp(systemId, XCS("004-2.ent"))) { XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler); XML_SetUserData(ext_parser, ext_parser); if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE) @@ -1101,9 +1103,9 @@ external_entity_public(XML_Parser parser, const XML_Char *context, ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); if (ext_parser == NULL) return XML_STATUS_ERROR; - if (systemId != NULL && ! xcstrcmp(systemId, XCS("http://example.org/"))) { + if (systemId != NULL && ! xcscmp(systemId, XCS("http://example.org/"))) { text = text1; - } else if (publicId != NULL && ! xcstrcmp(publicId, XCS("foo"))) { + } else if (publicId != NULL && ! xcscmp(publicId, XCS("foo"))) { text = text2; } else fail("Unexpected parameters to external entity parser"); @@ -1126,9 +1128,9 @@ external_entity_devaluer(XML_Parser parser, const XML_Char *context, UNUSED_P(base); UNUSED_P(publicId); - if (systemId == NULL || ! xcstrcmp(systemId, XCS("bar"))) + if (systemId == NULL || ! xcscmp(systemId, XCS("bar"))) return XML_STATUS_OK; - if (xcstrcmp(systemId, XCS("foo")) != 0) + if (xcscmp(systemId, XCS("foo")) != 0) fail("Unexpected system ID"); ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); if (ext_parser == NULL) @@ -1527,9 +1529,9 @@ accounting_external_entity_ref_handler(XML_Parser parser, const struct AccountingTestCase *const testCase = XML_GetUserData(parser); const char *externalText = NULL; - if (xcstrcmp(systemId, XCS("first.ent")) == 0) { + if (xcscmp(systemId, XCS("first.ent")) == 0) { externalText = testCase->firstExternalText; - } else if (xcstrcmp(systemId, XCS("second.ent")) == 0) { + } else if (xcscmp(systemId, XCS("second.ent")) == 0) { externalText = testCase->secondExternalText; } else { assert(! "systemId is neither \"first.ent\" nor \"second.ent\""); @@ -1569,16 +1571,16 @@ verify_attlist_decl_handler(void *userData, const XML_Char *element_name, const XML_Char *default_value, int is_required) { AttTest *at = (AttTest *)userData; - if (xcstrcmp(element_name, at->element_name) != 0) + if (xcscmp(element_name, at->element_name) != 0) fail("Unexpected element name in attribute declaration"); - if (xcstrcmp(attr_name, at->attr_name) != 0) + if (xcscmp(attr_name, at->attr_name) != 0) fail("Unexpected attribute name in attribute declaration"); - if (xcstrcmp(attr_type, at->attr_type) != 0) + if (xcscmp(attr_type, at->attr_type) != 0) fail("Unexpected attribute type in attribute declaration"); if ((default_value == NULL && at->default_value != NULL) || (default_value != NULL && at->default_value == NULL) || (default_value != NULL - && xcstrcmp(default_value, at->default_value) != 0)) + && xcscmp(default_value, at->default_value) != 0)) fail("Unexpected default value in attribute declaration"); if (is_required != at->is_required) fail("Requirement mismatch in attribute declaration"); @@ -1649,23 +1651,24 @@ rsqb_handler(void *userData, const XML_Char *s, int len) { void XMLCALL byte_character_handler(void *userData, const XML_Char *s, int len) { #if XML_CONTEXT_BYTES > 0 - int offset, size; + int64_t offset; + uint64_t size; const char *buffer; ByteTestData *data = (ByteTestData *)userData; UNUSED_P(s); - buffer = XML_GetInputContext(g_parser, &offset, &size); + buffer = XML_GetInputContext64(g_parser, &offset, &size); if (buffer == NULL) fail("Failed to get context buffer"); if (offset != data->start_element_len) fail("Context offset in unexpected position"); if (len != data->cdata_len) fail("CDATA length reported incorrectly"); - if (size != data->total_string_len) + if (size != (uint64_t)data->total_string_len) fail("Context size is not full buffer"); - if (XML_GetCurrentByteIndex(g_parser) != offset) + if (XML_GetCurrentByteIndex64(g_parser) != offset) fail("Character byte index incorrect"); - if (XML_GetCurrentByteCount(g_parser) != len) + if (XML_GetCurrentByteCount64(g_parser) != (uint64_t)len) fail("Character byte count incorrect"); #else UNUSED_P(s); @@ -1723,7 +1726,7 @@ void XMLCALL record_element_start_handler(void *userData, const XML_Char *name, const XML_Char **atts) { UNUSED_P(atts); - CharData_AppendXMLChars((CharData *)userData, name, (int)xcstrlen(name)); + CharData_AppendXMLChars((CharData *)userData, name, (int)xcslen(name)); } void XMLCALL @@ -1763,13 +1766,13 @@ param_entity_match_handler(void *userData, const XML_Char *entityName, || entity_value_to_match == NULL) { return; } - if (! xcstrcmp(entityName, entity_name_to_match)) { + if (! xcscmp(entityName, entity_name_to_match)) { /* The cast here is safe because we control the horizontal and * the vertical, and we therefore know our strings are never * going to overflow an int. */ - if (value_length != (int)xcstrlen(entity_value_to_match) - || xcstrncmp(value, entity_value_to_match, value_length) != 0) { + if (value_length != (int)xcslen(entity_value_to_match) + || xcsncmp(value, entity_value_to_match, value_length) != 0) { entity_match_flag = ENTITY_MATCH_FAIL; } else { entity_match_flag = ENTITY_MATCH_SUCCESS; diff --git a/contrib/expat/tests/misc_tests.c b/contrib/expat/tests/misc_tests.c index 717cc2dd31aa..f5d1e3473887 100644 --- a/contrib/expat/tests/misc_tests.c +++ b/contrib/expat/tests/misc_tests.c @@ -24,6 +24,7 @@ Copyright (c) 2026 Kartik Kenchi <netliomax25@gmail.com> Copyright (c) 2026 Evgeny Kotkov <kotkov@apache.org> Copyright (c) 2026 Darren Carreras <carrerasdarren@gmail.com> + Copyright (c) 2026 Junki Lee <junkilee80@gmail.com> Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -55,6 +56,8 @@ #include "expat_config.h" #include <assert.h> +#include <stdbool.h> +#include <stdint.h> #include <string.h> #include "expat.h" @@ -65,6 +68,7 @@ #include "ascii.h" /* for ASCII_xxx */ #include "handlers.h" #include "misc_tests.h" +#include "../lib/xcs.h" void XMLCALL accumulate_characters_ext_handler(void *userData, const XML_Char *s, int len); @@ -218,7 +222,7 @@ START_TEST(test_misc_version) { if (! versions_equal(&read_version, &parsed_version)) fail("Version mismatch"); - if (xcstrcmp(version_text, XCS("expat_2.8.5")) + if (xcscmp(version_text, XCS("expat_2.9.0")) != 0) /* needs bump on releases */ fail("XML_*_VERSION in expat.h out of sync?\n"); } @@ -394,8 +398,8 @@ START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) { XML_Parser parser; enum XML_Status parseResult; int setParamEntityResult; - XML_Size lineNumber; - XML_Size columnNumber; + uint64_t lineNumber; + uint64_t columnNumber; parser = XML_ParserCreate(NULL); setParamEntityResult @@ -444,13 +448,13 @@ START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) { if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN) fail("Error code does not match XML_ERROR_INVALID_TOKEN"); - lineNumber = XML_GetCurrentLineNumber(parser); + lineNumber = XML_GetCurrentLineNumber64(parser); if (lineNumber != 6) - fail("XML_GetCurrentLineNumber does not work as expected."); + fail("XML_GetCurrentLineNumber64 does not work as expected."); - columnNumber = XML_GetCurrentColumnNumber(parser); + columnNumber = XML_GetCurrentColumnNumber64(parser); if (columnNumber != 0) - fail("XML_GetCurrentColumnNumber does not work as expected."); + fail("XML_GetCurrentColumnNumber64 does not work as expected."); XML_ParserFree(parser); } @@ -629,22 +633,23 @@ END_TEST // Inspired by function XML_OriginalString of Perl's XML::Parser static char * dup_original_string(XML_Parser parser) { - const int byte_count = XML_GetCurrentByteCount(parser); + const uint64_t byte_count = XML_GetCurrentByteCount64(parser); - assert_true(byte_count >= 0); + int64_t offset64 = -1; + uint64_t size64 = UINT64_MAX; - int offset = -1; - int size = -1; - - const char *const context = XML_GetInputContext(parser, &offset, &size); + const char *const context64 + = XML_GetInputContext64(parser, &offset64, &size64); #if XML_CONTEXT_BYTES > 0 - assert_true(context != NULL); - assert_true(offset >= 0); - assert_true(size >= 0); - return portable_strndup(context + offset, byte_count); + assert_true(context64 != NULL); + assert_true(offset64 != -1); + assert_true(size64 != UINT64_MAX); + + return portable_strndup(context64 + offset64, byte_count); #else - assert_true(context == NULL); + UNUSED_P(byte_count); + assert_true(context64 == NULL); return NULL; #endif } @@ -709,8 +714,8 @@ START_TEST(test_misc_async_entity_rejected) { const char *doc; enum XML_Status expectedStatusNoGE; enum XML_Error expectedErrorNoGE; - XML_Size expectedErrorLine; - XML_Size expectedErrorColumn; + uint64_t expectedErrorLine; + uint16_t expectedErrorColumn; }; const struct test_case cases[] = { // Opened by one entity, closed by another @@ -769,8 +774,9 @@ START_TEST(test_misc_async_entity_rejected) { == expectedStatus); assert_true(XML_GetErrorCode(parser) == expectedError); #if XML_GE == 1 - assert_true(XML_GetCurrentLineNumber(parser) == testCase.expectedErrorLine); - assert_true(XML_GetCurrentColumnNumber(parser) + assert_true(XML_GetCurrentLineNumber64(parser) + == testCase.expectedErrorLine); + assert_true(XML_GetCurrentColumnNumber64(parser) == testCase.expectedErrorColumn); #endif XML_ParserFree(parser); @@ -894,6 +900,66 @@ START_TEST(test_misc_unknown_encoding_callbacks_protected) { } END_TEST +typedef struct { + XML_Parser parser; + int releaseCallCount; + uint64_t lineAtRelease; +} EncodingReleaseData; + +static void XMLCALL +position_reading_encoding_release(void *userData) { + EncodingReleaseData *const data = userData; + data->releaseCallCount++; + data->lineAtRelease = XML_GetCurrentLineNumber64(data->parser); +} + +static int XMLCALL +position_reading_encoding_handler(void *userData, const XML_Char *name, + XML_Encoding *info) { + UNUSED_P(name); + + for (int i = 0; i < 256; i++) + info->map[i] = i; + info->data = userData; + info->convert = NULL; + info->release = position_reading_encoding_release; + return XML_STATUS_OK; +} + +static void +run_unknown_encoding_release_getter_test(bool resetParser) { + const char *const doc = "<?xml version='1.0' encoding='release-order'?>\n" + "<root>\n" + " <unclosed>\n" + "</root>\n"; + XML_Parser parser = XML_ParserCreate(NULL); + EncodingReleaseData data = {parser, 0, 0}; + + assert_true(parser != NULL); + XML_SetUnknownEncodingHandler(parser, position_reading_encoding_handler, + &data); + assert_true(XML_Parse(parser, doc, (int)strlen(doc), /*isFinal=*/XML_TRUE) + == XML_STATUS_ERROR); + assert_true(XML_GetErrorCode(parser) == XML_ERROR_TAG_MISMATCH); + + if (resetParser) + assert_true(XML_ParserReset(parser, NULL) == XML_TRUE); + XML_ParserFree(parser); + + assert_true(data.releaseCallCount == 1); + assert_true(data.lineAtRelease == 4); +} + +START_TEST(test_misc_unknown_encoding_release_getter_parser_free) { + run_unknown_encoding_release_getter_test(false); +} +END_TEST + +START_TEST(test_misc_unknown_encoding_release_getter_parser_reset) { + run_unknown_encoding_release_getter_test(true); +} +END_TEST + // General attack payload idea by Jason Kratzer of Mozilla START_TEST(test_misc_low_surrogate_mozilla_bug_2053153) { const char doc_before[] = "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n\0" @@ -992,6 +1058,10 @@ make_miscellaneous_test_case(Suite *s) { tcase_add_test(tc_misc, test_misc_calls_forbidden_from_handlers); tcase_add_test(tc_misc, test_misc_resume_parser_forbidden_from_handler); tcase_add_test(tc_misc, test_misc_unknown_encoding_callbacks_protected); + tcase_add_test(tc_misc, + test_misc_unknown_encoding_release_getter_parser_free); + tcase_add_test(tc_misc, + test_misc_unknown_encoding_release_getter_parser_reset); tcase_add_test(tc_misc, test_misc_input_2gb); tcase_add_test(tc_misc, test_misc_low_surrogate_mozilla_bug_2053153); } diff --git a/contrib/expat/tests/props_tests.c b/contrib/expat/tests/props_tests.c new file mode 100644 index 000000000000..fe0eb0697b79 --- /dev/null +++ b/contrib/expat/tests/props_tests.c @@ -0,0 +1,790 @@ +/* Tests related to the public properties API of Expat +__ __ _ + ___\ \/ /_ __ __ _| |_ + / _ \\ /| '_ \ / _` | __| + | __// \| |_) | (_| | |_ + \___/_/\_\ .__/ \__,_|\__| + |_| XML parser + + Copyright (c) 2026 Sebastian Pipping <sebastian@pipping.org> + Licensed under the MIT license: + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the + following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. + + SPDX-License-Identifier: MIT +*/ + +#include "expat_config.h" + +#include "props_tests.h" + +#include "common.h" // for g_chunkSize +#include "expat.h" +#include "internal.h" // for e.g. EXPAT_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT + +#include <math.h> +#include <stdbool.h> + +enum ExpectedType { + TYPE_BOOL, + TYPE_DOUBLE, + TYPE_UINT64, +}; + +START_TEST(test_props_getter_defaults) { + // The test is not doing any parsing, so a single run + // (with `g_chunkSize == 0`) is enough + if (g_chunkSize != 0) + return; + + XML_Parser parser = XML_ParserCreate(NULL); + assert_true(parser != NULL); + +#if XML_GE == 1 + // Case XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD + { + uint64_t actionThresholdBytes1 = 123; + assert_true(XML_GetPropertyUInt64( + parser, XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD, + &actionThresholdBytes1) + == XML_PROP_ERROR_NONE); + assert_true(actionThresholdBytes1 + == EXPAT_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT); + } + + // Case XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION + { + double maximumAmplification1 = 123.456; + assert_true(XML_GetPropertyDouble( + parser, XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION, + &maximumAmplification1) + == XML_PROP_ERROR_NONE); + assert_true(maximumAmplification1 + == (double)EXPAT_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION_DEFAULT); + } + + // Case XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD + { + uint64_t actionThresholdBytes2 = 123; + assert_true(XML_GetPropertyUInt64( + parser, XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD, + &actionThresholdBytes2) + == XML_PROP_ERROR_NONE); + assert_true( + actionThresholdBytes2 + == EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT); + } + + // Case XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION + { + double maximumAmplification2 = 123.456; + assert_true(XML_GetPropertyDouble( + parser, XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION, + &maximumAmplification2) + == XML_PROP_ERROR_NONE); + assert_true( + maximumAmplification2 + == (double) + EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT); + } +#endif + + // Case XML_PROP_REPARSE_DEFERRAL_ENABLED + XML_Bool reparseDeferralEnabled = XML_FALSE; + assert_true(XML_GetPropertyBool(parser, XML_PROP_REPARSE_DEFERRAL_ENABLED, + &reparseDeferralEnabled) + == XML_PROP_ERROR_NONE); + assert_true(reparseDeferralEnabled == g_reparseDeferralEnabledDefault); + + // Case XML_PROP_INVALID + XML_Bool dummyBool = XML_FALSE; + double dummyDouble = 123.456; + uint64_t dummyUInt64 = 123; + assert_true(XML_GetPropertyBool(parser, XML_PROP_INVALID, &dummyBool) + == XML_PROP_ERROR_INVALID_KEY); + assert_true(XML_GetPropertyDouble(parser, XML_PROP_INVALID, &dummyDouble) + == XML_PROP_ERROR_INVALID_KEY); + assert_true(XML_GetPropertyUInt64(parser, XML_PROP_INVALID, &dummyUInt64) + == XML_PROP_ERROR_INVALID_KEY); + + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_props_getter_error_parser_null) { + // The test is not doing any parsing, so a single run + // (with `g_chunkSize == 0`) is enough + if (g_chunkSize != 0) + return; + + XML_Parser parserNonNull = XML_ParserCreate(NULL); + XML_Parser parsers[] = {parserNonNull, NULL}; + assert_true(parserNonNull != NULL); + + for (size_t i = 0; i < sizeof(parsers) / sizeof(parsers[0]); i++) { + XML_Parser parser = parsers[i]; + const enum XML_Prop_Error validKeyExpectedError + = (parser == NULL) ? XML_PROP_ERROR_PARSER_NULL : XML_PROP_ERROR_NONE; + // NOTE: Currently the parser is checked for being `NULL` before the key is + // being checked for being valid. + // That precedence among errors is not considered part of the API + // contract: either error would be fine to return. + const enum XML_Prop_Error invalidKeyExpectedError + = (parser == NULL) ? XML_PROP_ERROR_PARSER_NULL + : XML_PROP_ERROR_INVALID_KEY; + + XML_Bool dummyBool = XML_FALSE; + double dummyDouble = 123.456; + uint64_t dummyUInt64 = 123; + +#if XML_GE == 1 + assert_true( + XML_GetPropertyUInt64( + parser, XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD, &dummyUInt64) + == validKeyExpectedError); + assert_true( + XML_GetPropertyDouble( + parser, XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION, &dummyDouble) + == validKeyExpectedError); + assert_true( + XML_GetPropertyUInt64( + parser, XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD, &dummyUInt64) + == validKeyExpectedError); + assert_true( + XML_GetPropertyDouble( + parser, XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION, &dummyDouble) + == validKeyExpectedError); +#endif + assert_true(XML_GetPropertyBool(parser, XML_PROP_REPARSE_DEFERRAL_ENABLED, + &dummyBool) + == validKeyExpectedError); + + assert_true(XML_GetPropertyBool(parser, XML_PROP_INVALID, &dummyBool) + == invalidKeyExpectedError); + assert_true(XML_GetPropertyDouble(parser, XML_PROP_INVALID, &dummyDouble) + == invalidKeyExpectedError); + assert_true(XML_GetPropertyUInt64(parser, XML_PROP_INVALID, &dummyUInt64) + == invalidKeyExpectedError); + } + + XML_ParserFree(parserNonNull); +} +END_TEST + +START_TEST(test_props_getter_error_invalid_key) { + // The test is not doing any parsing, so a single run + // (with `g_chunkSize == 0`) is enough + if (g_chunkSize != 0) + return; + + XML_Bool dummyBool = XML_FALSE; + double dummyDouble = 123.456; + uint64_t dummyUInt64 = 123; + + XML_Parser parser = XML_ParserCreate(NULL); + assert_true(parser != NULL); + + assert_true(XML_GetPropertyBool(parser, XML_PROP_INVALID, &dummyBool) + == XML_PROP_ERROR_INVALID_KEY); + assert_true(XML_GetPropertyDouble(parser, XML_PROP_INVALID, &dummyDouble) + == XML_PROP_ERROR_INVALID_KEY); + assert_true(XML_GetPropertyUInt64(parser, XML_PROP_INVALID, &dummyUInt64) + == XML_PROP_ERROR_INVALID_KEY); + + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_props_getter_error_invalid_type) { + // The test is not doing any parsing, so a single run + // (with `g_chunkSize == 0`) is enough + if (g_chunkSize != 0) + return; + + struct TestCase { + enum XML_Parser_Property key; + enum ExpectedType expectedType; + }; + + struct TestCase cases[] = { +#if XML_GE == 1 + {XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD, TYPE_UINT64}, + {XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION, TYPE_DOUBLE}, + {XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD, TYPE_UINT64}, + {XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION, TYPE_DOUBLE}, +#endif + {XML_PROP_REPARSE_DEFERRAL_ENABLED, TYPE_BOOL}, + }; + + XML_Bool dummyBool = XML_FALSE; + double dummyDouble = 123.456; + uint64_t dummyUInt64 = 123; + + XML_Parser parser = XML_ParserCreate(NULL); + assert_true(parser != NULL); + + for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) { + struct TestCase *const testCase = cases + i; + set_subtest("property %d", (int)testCase->key); + + const enum XML_Prop_Error expectedBoolError + = (testCase->expectedType == TYPE_BOOL) ? XML_PROP_ERROR_NONE + : XML_PROP_ERROR_INVALID_TYPE; + const enum XML_Prop_Error expectedDoubleError + = (testCase->expectedType == TYPE_DOUBLE) ? XML_PROP_ERROR_NONE + : XML_PROP_ERROR_INVALID_TYPE; + const enum XML_Prop_Error expectedUInt64Error + = (testCase->expectedType == TYPE_UINT64) ? XML_PROP_ERROR_NONE + : XML_PROP_ERROR_INVALID_TYPE; + + assert_true(XML_GetPropertyBool(parser, testCase->key, &dummyBool) + == expectedBoolError); + assert_true(XML_GetPropertyDouble(parser, testCase->key, &dummyDouble) + == expectedDoubleError); + assert_true(XML_GetPropertyUInt64(parser, testCase->key, &dummyUInt64) + == expectedUInt64Error); + } + + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_props_getter_error_invalid_value) { + // The test is not doing any parsing, so a single run + // (with `g_chunkSize == 0`) is enough + if (g_chunkSize != 0) + return; + + enum XML_Parser_Property keys[] = { +#if XML_GE == 1 + XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD, + XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION, + XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD, + XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION, +#endif + XML_PROP_REPARSE_DEFERRAL_ENABLED, + }; + + XML_Parser parser = XML_ParserCreate(NULL); + assert_true(parser != NULL); + + for (size_t i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) { + const enum XML_Parser_Property key = keys[i]; + set_subtest("property %d", (int)key); + + // NOTE: Currently the value output pointer is checked for being `NULL` + // before the key is being checked for being valid. + // That precedence among errors is not considered part of the API + // contract: either error would be fine to return. + assert_true(XML_GetPropertyBool(parser, key, NULL) + == XML_PROP_ERROR_INVALID_VALUE); + assert_true(XML_GetPropertyDouble(parser, key, NULL) + == XML_PROP_ERROR_INVALID_VALUE); + assert_true(XML_GetPropertyUInt64(parser, key, NULL) + == XML_PROP_ERROR_INVALID_VALUE); + } + + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_props_setter_effective) { + // The test is not doing any parsing, so a single run + // (with `g_chunkSize == 0`) is enough + if (g_chunkSize != 0) + return; + + struct TestCase { + enum XML_Parser_Property key; + enum ExpectedType expectedType; + }; + + struct TestCase cases[] = { +#if XML_GE == 1 + {XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD, TYPE_UINT64}, + {XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION, TYPE_DOUBLE}, + {XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD, TYPE_UINT64}, + {XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION, TYPE_DOUBLE}, +#endif + {XML_PROP_REPARSE_DEFERRAL_ENABLED, TYPE_BOOL}, + }; + + XML_Parser parser = XML_ParserCreate(NULL); + assert_true(parser != NULL); + + for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) { + struct TestCase *const testCase = cases + i; + set_subtest("property %d", (int)testCase->key); + + switch (testCase->expectedType) { + case TYPE_BOOL: { + // Get original value + XML_Bool valueOne = ! g_reparseDeferralEnabledDefault; + assert_true(XML_GetPropertyBool(parser, testCase->key, &valueOne) + == XML_PROP_ERROR_NONE); + const XML_Bool valueTwo = ((valueOne == XML_TRUE) ? XML_FALSE : XML_TRUE); + assert_true(valueTwo != valueOne); // self-test + + // Test: Set with reported success + assert_true(XML_SetPropertyBool(parser, testCase->key, valueTwo) + == XML_PROP_ERROR_NONE); + XML_Bool valueThree = valueOne; + assert_true(valueThree != valueTwo); // self-test + + // Test: Whether the new value has become effective + assert_true(XML_GetPropertyBool(parser, testCase->key, &valueThree) + == XML_PROP_ERROR_NONE); + assert_true(valueThree == valueTwo); + break; + } + case TYPE_DOUBLE: { + // Get original value + double valueOne = 1.23; + assert_true(XML_GetPropertyDouble(parser, testCase->key, &valueOne) + == XML_PROP_ERROR_NONE); + const double valueTwo = 4.56; + assert_true(valueTwo != valueOne); // self-test + + // Test: Set with reported success + assert_true(XML_SetPropertyDouble(parser, testCase->key, valueTwo) + == XML_PROP_ERROR_NONE); + double valueThree = 7.89; + assert_true(valueThree != valueTwo); // self-test + + // Test: Whether the new value has become effective + assert_true(XML_GetPropertyDouble(parser, testCase->key, &valueThree) + == XML_PROP_ERROR_NONE); + assert_true((float)valueThree == (float)valueTwo); + break; + } + case TYPE_UINT64: { + // Get original value + uint64_t valueOne = 123; + assert_true(XML_GetPropertyUInt64(parser, testCase->key, &valueOne) + == XML_PROP_ERROR_NONE); + const uint64_t valueTwo = 456; + assert_true(valueTwo != valueOne); // self-test + + // Test: Set with reported success + assert_true(XML_SetPropertyUInt64(parser, testCase->key, valueTwo) + == XML_PROP_ERROR_NONE); + uint64_t valueThree = 789; + assert_true(valueThree != valueTwo); // self-test + + // Test: Whether the new value has become effective + assert_true(XML_GetPropertyUInt64(parser, testCase->key, &valueThree) + == XML_PROP_ERROR_NONE); + assert_true(valueThree == valueTwo); + break; + } + default: + fail("unsupported type"); + } + } + + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_props_setter_error_parser_null) { + // The test is not doing any parsing, so a single run + // (with `g_chunkSize == 0`) is enough + if (g_chunkSize != 0) + return; + + struct TestCase { + enum XML_Parser_Property key; + enum ExpectedType expectedType; + }; + + struct TestCase cases[] = { +#if XML_GE == 1 + {XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD, TYPE_UINT64}, + {XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION, TYPE_DOUBLE}, + {XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD, TYPE_UINT64}, + {XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION, TYPE_DOUBLE}, +#endif + {XML_PROP_REPARSE_DEFERRAL_ENABLED, TYPE_BOOL}, + }; + + XML_Parser parserNonNull = XML_ParserCreate(NULL); + XML_Parser parsers[] = {parserNonNull, NULL}; + assert_true(parserNonNull != NULL); + + for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) { + struct TestCase *const testCase = cases + i; + for (size_t j = 0; j < sizeof(parsers) / sizeof(parsers[0]); j++) { + XML_Parser parser = parsers[j]; + set_subtest("property %d, parser %s", (int)testCase->key, + (parser == NULL) ? "NULL" : "non-NULL"); + + const enum XML_Prop_Error expected + = ((parser == NULL) ? XML_PROP_ERROR_PARSER_NULL + : XML_PROP_ERROR_NONE); + + enum XML_Prop_Error actual + = XML_PROP_ERROR_INVALID_TYPE; // i.e. some value unequal to + // `expected` + // above + assert_true(actual != expected); // self-test + + switch (testCase->expectedType) { + case TYPE_BOOL: + actual = XML_SetPropertyBool(parser, testCase->key, + ! g_reparseDeferralEnabledDefault); + break; + case TYPE_DOUBLE: + actual = XML_SetPropertyDouble(parser, testCase->key, 456.789); + break; + case TYPE_UINT64: + actual = XML_SetPropertyUInt64(parser, testCase->key, 456); + break; + default: + fail("unsupported type"); + } + assert_true(actual == expected); + } + } + + XML_ParserFree(parserNonNull); +} +END_TEST + +START_TEST(test_props_setter_error_parser_not_root) { + // The test is not doing any parsing, so a single run + // (with `g_chunkSize == 0`) is enough + if (g_chunkSize != 0) + return; + + struct TestCase { + enum XML_Parser_Property key; + enum ExpectedType expectedType; + bool needsRootParser; + }; + + struct TestCase cases[] = { +#if XML_GE == 1 + {XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD, TYPE_UINT64, true}, + {XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION, TYPE_DOUBLE, true}, + {XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD, TYPE_UINT64, true}, + {XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION, TYPE_DOUBLE, true}, +#endif + {XML_PROP_REPARSE_DEFERRAL_ENABLED, TYPE_BOOL, false}, + }; + + XML_Parser parser = XML_ParserCreate(NULL); + assert_true(parser != NULL); + XML_Parser subParser = XML_ExternalEntityParserCreate(parser, NULL, NULL); +#if defined(XML_DTD) + assert_true(subParser != NULL); + + for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) { + struct TestCase *const testCase = cases + i; + set_subtest("property %d", (int)testCase->key); + + const enum XML_Prop_Error expected + = (testCase->needsRootParser ? XML_PROP_ERROR_PARSER_NOT_ROOT + : XML_PROP_ERROR_NONE); + + enum XML_Prop_Error actual + = XML_PROP_ERROR_INVALID_TYPE; // i.e. some value unequal to `expected` + // above + assert_true(actual != expected); // self-test + + switch (testCase->expectedType) { + case TYPE_BOOL: + actual = XML_SetPropertyBool(subParser, testCase->key, + ! g_reparseDeferralEnabledDefault); + break; + case TYPE_DOUBLE: + actual = XML_SetPropertyDouble(subParser, testCase->key, 456.789); + break; + case TYPE_UINT64: + actual = XML_SetPropertyUInt64(subParser, testCase->key, 456); + break; + default: + fail("unsupported type"); + } + + assert_true(actual == expected); + } + + XML_ParserFree(subParser); +#else // ! defined(XML_DTD) + assert_true(subParser == NULL); + UNUSED_P(cases); +#endif + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_props_setter_error_parser_started) { + // The test is not doing any (real) parsing, so a single run + // (with `g_chunkSize == 0`) is enough + if (g_chunkSize != 0) + return; + + struct TestCase { + enum XML_Parser_Property key; + enum ExpectedType expectedType; + }; + + struct TestCase cases[] = { +#if XML_GE == 1 + {XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD, TYPE_UINT64}, + {XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION, TYPE_DOUBLE}, + {XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD, TYPE_UINT64}, + {XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION, TYPE_DOUBLE}, +#endif + {XML_PROP_REPARSE_DEFERRAL_ENABLED, TYPE_BOOL}, + }; + + XML_Parser parser = XML_ParserCreate(NULL); + assert_true(parser != NULL); + + // Get the parser into state "parsing started" + XML_ParsingStatus parsingStatus; + XML_GetParsingStatus(parser, &parsingStatus); + assert_true(parsingStatus.parsing == XML_INITIALIZED); // Self-test + assert_true(_XML_Parse_SINGLE_BYTES(parser, "", 0, /*isFInal=*/XML_FALSE) + == XML_STATUS_OK); + XML_GetParsingStatus(parser, &parsingStatus); + assert_true(parsingStatus.parsing == XML_PARSING); + + for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) { + struct TestCase *const testCase = cases + i; + set_subtest("property %d", (int)testCase->key); + + switch (testCase->expectedType) { + case TYPE_BOOL: { + // Get original value + XML_Bool valueOne = ! g_reparseDeferralEnabledDefault; + assert_true(XML_GetPropertyBool(parser, testCase->key, &valueOne) + == XML_PROP_ERROR_NONE); + const XML_Bool valueTwo = ((valueOne == XML_TRUE) ? XML_FALSE : XML_TRUE); + assert_true(valueTwo != valueOne); // self-test + + // Test: Set with reported success + assert_true(XML_SetPropertyBool(parser, testCase->key, valueTwo) + == XML_PROP_ERROR_NONE); + XML_Bool valueThree = valueOne; + assert_true(valueThree != valueTwo); // self-test + + // Test: Whether the new value has become effective + assert_true(XML_GetPropertyBool(parser, testCase->key, &valueThree) + == XML_PROP_ERROR_NONE); + assert_true(valueThree == valueTwo); // i.e. new value applied + break; + } + case TYPE_DOUBLE: { + // Get original value + double valueOne = 1.23; + assert_true(XML_GetPropertyDouble(parser, testCase->key, &valueOne) + == XML_PROP_ERROR_NONE); + const double valueTwo = 4.56; + assert_true(valueTwo != valueOne); // self-test + + // Test: Set with reported success + assert_true(XML_SetPropertyDouble(parser, testCase->key, valueTwo) + == XML_PROP_ERROR_NONE); + double valueThree = 7.89; + assert_true(valueThree != valueTwo); // self-test + + // Test: Whether the new value has become effective + assert_true(XML_GetPropertyDouble(parser, testCase->key, &valueThree) + == XML_PROP_ERROR_NONE); + assert_true((float)valueThree + == (float)valueTwo); // i.e. new value applied + break; + } + case TYPE_UINT64: { + // Get original value + uint64_t valueOne = 123; + assert_true(XML_GetPropertyUInt64(parser, testCase->key, &valueOne) + == XML_PROP_ERROR_NONE); + const uint64_t valueTwo = 456; + assert_true(valueTwo != valueOne); // self-test + + // Test: Set with reported success + assert_true(XML_SetPropertyUInt64(parser, testCase->key, valueTwo) + == XML_PROP_ERROR_NONE); + uint64_t valueThree = 789; + assert_true(valueThree != valueTwo); // self-test + + // Test: Whether the new value has become effective + assert_true(XML_GetPropertyUInt64(parser, testCase->key, &valueThree) + == XML_PROP_ERROR_NONE); + assert_true(valueThree == valueTwo); // i.e. new value applied + break; + } + default: + fail("unsupported type"); + } + } + + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_props_setter_error_invalid_key) { + // The test is not doing any parsing, so a single run + // (with `g_chunkSize == 0`) is enough + if (g_chunkSize != 0) + return; + + XML_Parser parser = XML_ParserCreate(NULL); + assert_true(parser != NULL); + + assert_true(XML_SetPropertyBool(parser, XML_PROP_INVALID, + ! g_reparseDeferralEnabledDefault) + == XML_PROP_ERROR_INVALID_KEY); + assert_true(XML_SetPropertyDouble(parser, XML_PROP_INVALID, 123.456) + == XML_PROP_ERROR_INVALID_KEY); + assert_true(XML_SetPropertyUInt64(parser, XML_PROP_INVALID, 123) + == XML_PROP_ERROR_INVALID_KEY); + + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_props_setter_error_invalid_type) { + // The test is not doing any parsing, so a single run + // (with `g_chunkSize == 0`) is enough + if (g_chunkSize != 0) + return; + + struct TestCase { + enum XML_Parser_Property key; + enum ExpectedType expectedType; + }; + + struct TestCase cases[] = { +#if XML_GE == 1 + {XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD, TYPE_UINT64}, + {XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION, TYPE_DOUBLE}, + {XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD, TYPE_UINT64}, + {XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION, TYPE_DOUBLE}, +#endif + {XML_PROP_REPARSE_DEFERRAL_ENABLED, TYPE_BOOL}, + }; + + XML_Parser parser = XML_ParserCreate(NULL); + assert_true(parser != NULL); + + for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) { + struct TestCase *const testCase = cases + i; + set_subtest("property %d", (int)testCase->key); + + const enum XML_Prop_Error expectedErrorBool + = ((testCase->expectedType == TYPE_BOOL) ? XML_PROP_ERROR_NONE + : XML_PROP_ERROR_INVALID_TYPE); + const enum XML_Prop_Error expectedErrorDouble + = ((testCase->expectedType == TYPE_DOUBLE) + ? XML_PROP_ERROR_NONE + : XML_PROP_ERROR_INVALID_TYPE); + const enum XML_Prop_Error expectedErrorUInt64 + = ((testCase->expectedType == TYPE_UINT64) + ? XML_PROP_ERROR_NONE + : XML_PROP_ERROR_INVALID_TYPE); + + assert_true(XML_SetPropertyBool(parser, testCase->key, + ! g_reparseDeferralEnabledDefault) + == expectedErrorBool); + assert_true(XML_SetPropertyDouble(parser, testCase->key, 456.789) + == expectedErrorDouble); + assert_true(XML_SetPropertyUInt64(parser, testCase->key, 456) + == expectedErrorUInt64); + } + + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_props_setter_error_invalid_value) { + // The test is not doing any parsing, so a single run + // (with `g_chunkSize == 0`) is enough + if (g_chunkSize != 0) + return; + + XML_Parser parser = XML_ParserCreate(NULL); + assert_true(parser != NULL); + +#if XML_GE == 1 + struct TestCase { + enum XML_Parser_Property key; + // NOTE: Neither `uint64_t`- nor `XML_Bool`-based properties have any + // invalid in-dimension values, so we are only testing `double`-based + // property values here. + double value; + bool valueValid; + }; + + struct TestCase cases[] = { + // XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION + {XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION, -HUGE_VAL, false}, + {XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION, -1.0, false}, + {XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION, -0.9, false}, + {XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION, 0.0, false}, + {XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION, 0.9, false}, + {XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION, 1.0, true}, + {XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION, HUGE_VAL, true}, + // XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION + {XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION, -HUGE_VAL, false}, + {XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION, -1.0, false}, + {XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION, -0.9, false}, + {XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION, 0.0, false}, + {XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION, 0.9, false}, + {XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION, 1.0, true}, + {XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION, HUGE_VAL, true}, + }; + + for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) { + struct TestCase *const testCase = cases + i; + const enum XML_Prop_Error expected + = (testCase->valueValid ? XML_PROP_ERROR_NONE + : XML_PROP_ERROR_INVALID_VALUE); + assert_true(XML_SetPropertyDouble(parser, testCase->key, testCase->value) + == expected); + } +#endif + + XML_ParserFree(parser); +} +END_TEST + +void +make_props_test_case(Suite *s) { + TCase *const tc_props = tcase_create("properties tests"); + suite_add_tcase(s, tc_props); + + tcase_add_test(tc_props, test_props_getter_defaults); + tcase_add_test(tc_props, test_props_getter_error_parser_null); + tcase_add_test(tc_props, test_props_getter_error_invalid_key); + tcase_add_test(tc_props, test_props_getter_error_invalid_type); + tcase_add_test(tc_props, test_props_getter_error_invalid_value); + + tcase_add_test(tc_props, test_props_setter_effective); + tcase_add_test(tc_props, test_props_setter_error_parser_null); + tcase_add_test(tc_props, test_props_setter_error_parser_not_root); + tcase_add_test(tc_props, test_props_setter_error_parser_started); + tcase_add_test(tc_props, test_props_setter_error_invalid_key); + tcase_add_test(tc_props, test_props_setter_error_invalid_type); + tcase_add_test(tc_props, test_props_setter_error_invalid_value); +} diff --git a/contrib/expat/tests/props_tests.h b/contrib/expat/tests/props_tests.h new file mode 100644 index 000000000000..c429e4c06bf0 --- /dev/null +++ b/contrib/expat/tests/props_tests.h @@ -0,0 +1,41 @@ +/* Tests related to the public properties API of Expat + __ __ _ + ___\ \/ /_ __ __ _| |_ + / _ \\ /| '_ \ / _` | __| + | __// \| |_) | (_| | |_ + \___/_/\_\ .__/ \__,_|\__| + |_| XML parser + + Copyright (c) 2026 Sebastian Pipping <sebastian@pipping.org> + Licensed under the MIT license: + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the + following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. + + SPDX-License-Identifier: MIT +*/ + +#ifndef XML_PROPS_TESTS_H +#define XML_PROPS_TESTS_H + +#include "minicheck.h" + +extern void make_props_test_case(Suite *s); + +#endif /* XML_PROPS_TESTS_H */ diff --git a/contrib/expat/tests/runtests.c b/contrib/expat/tests/runtests.c index 12f8c36c12e3..4bfff4e976a9 100644 --- a/contrib/expat/tests/runtests.c +++ b/contrib/expat/tests/runtests.c @@ -54,13 +54,15 @@ #include "minicheck.h" #include "common.h" +#include "acc_tests.h" +#include "alloc_tests.h" #include "basic_tests.h" #include "hash_tests.h" -#include "ns_tests.h" #include "misc_tests.h" -#include "alloc_tests.h" +#include "ns_tests.h" #include "nsalloc_tests.h" -#include "acc_tests.h" +#include "props_tests.h" +#include "xcs_tests.h" XML_Parser g_parser = NULL; @@ -68,15 +70,17 @@ static Suite * make_suite(void) { Suite *s = suite_create("basic"); +#if XML_GE == 1 + make_accounting_test_case(s); +#endif + make_alloc_test_case(s); make_basic_test_case(s); make_hash_test_case(s); - make_namespace_test_case(s); make_miscellaneous_test_case(s); - make_alloc_test_case(s); + make_namespace_test_case(s); make_nsalloc_test_case(s); -#if XML_GE == 1 - make_accounting_test_case(s); -#endif + make_props_test_case(s); + make_xcs_test_case(s); return s; } diff --git a/contrib/expat/tests/structdata.c b/contrib/expat/tests/structdata.c index b39c6cfb779b..77268a99d95f 100644 --- a/contrib/expat/tests/structdata.c +++ b/contrib/expat/tests/structdata.c @@ -7,7 +7,7 @@ |_| XML parser Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> - Copyright (c) 2017-2023 Sebastian Pipping <sebastian@pipping.org> + Copyright (c) 2017-2026 Sebastian Pipping <sebastian@pipping.org> Copyright (c) 2022 Sean McBride <sean@rogue-research.com> Copyright (c) 2026 Matthew Fernandez <matthew.fernandez@gmail.com> Licensed under the MIT license: @@ -47,23 +47,20 @@ #include "structdata.h" #include "minicheck.h" +#include "../lib/xcs.h" #define STRUCT_EXTENSION_COUNT 8 #ifdef XML_UNICODE_WCHAR_T # include <wchar.h> # define XML_FMT_STR "ls" -# define xcstrlen(s) wcslen(s) -# define xcstrcmp(s, t) wcscmp((s), (t)) #else # define XML_FMT_STR "s" -# define xcstrlen(s) strlen(s) -# define xcstrcmp(s, t) strcmp((s), (t)) #endif static XML_Char * xmlstrdup(const XML_Char *s) { - size_t byte_count = (xcstrlen(s) + 1) * sizeof(XML_Char); + size_t byte_count = (xcslen(s) + 1) * sizeof(XML_Char); XML_Char *const dup = malloc(byte_count); assert(dup != NULL); @@ -128,7 +125,7 @@ StructData_CheckItems(StructData *storage, const StructDataEntry *expected, assert(got != NULL); assert(want != NULL); - if (xcstrcmp(got->str, want->str) != 0) { + if (xcscmp(got->str, want->str) != 0) { StructData_Dispose(storage); fail("structure got bad string"); } else { diff --git a/contrib/expat/tests/xcs_tests.c b/contrib/expat/tests/xcs_tests.c new file mode 100644 index 000000000000..3d756b043dde --- /dev/null +++ b/contrib/expat/tests/xcs_tests.c @@ -0,0 +1,86 @@ +/* Tests related to the XCS (XML character string) functionality +__ __ _ + ___\ \/ /_ __ __ _| |_ + / _ \\ /| '_ \ / _` | __| + | __// \| |_) | (_| | |_ + \___/_/\_\ .__/ \__,_|\__| + |_| XML parser + + Copyright (c) 2026 Sebastian Pipping <sebastian@pipping.org> + Licensed under the MIT license: + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the + following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. + + SPDX-License-Identifier: MIT +*/ + +#include "xcs_tests.h" + +#include "ascii.h" +#include "common.h" // for g_chunkSize +#include "xcs.h" // for xcslen, xcscmp, xcsncmp + +static const XML_Char empty[] = {'\0'}; +static const XML_Char test[] = {ASCII_T, ASCII_E, ASCII_S, ASCII_T, '\0'}; +static const XML_Char testing[] + = {ASCII_T, ASCII_E, ASCII_S, ASCII_T, ASCII_I, ASCII_N, ASCII_G, '\0'}; + +START_TEST(test_xcs_len) { + if (g_chunkSize != 0) + return; + + assert_true(xcslen(empty) == 0); + assert_true(xcslen(test) == 4); +} +END_TEST + +START_TEST(test_xcs_cmp) { + if (g_chunkSize != 0) + return; + + assert_true(xcscmp(test, test) == 0); + assert_true(xcscmp(test, testing) < 0); + assert_true(xcscmp(testing, test) > 0); +} +END_TEST + +START_TEST(test_xcs_ncmp) { + if (g_chunkSize != 0) + return; + + assert_true(xcsncmp(test, test, 0) == 0); + assert_true(xcsncmp(test, test, 4) == 0); + + assert_true(xcsncmp(test, testing, 4) == 0); + assert_true(xcsncmp(testing, test, 4) == 0); + + assert_true(xcsncmp(test, testing, 5) < 0); + assert_true(xcsncmp(testing, test, 5) > 0); +} +END_TEST + +void +make_xcs_test_case(Suite *s) { + TCase *const tc_xcs = tcase_create("xcs tests"); + suite_add_tcase(s, tc_xcs); + tcase_add_test(tc_xcs, test_xcs_len); + tcase_add_test(tc_xcs, test_xcs_cmp); + tcase_add_test(tc_xcs, test_xcs_ncmp); +} diff --git a/contrib/expat/tests/xcs_tests.h b/contrib/expat/tests/xcs_tests.h new file mode 100644 index 000000000000..52015f14a63e --- /dev/null +++ b/contrib/expat/tests/xcs_tests.h @@ -0,0 +1,41 @@ +/* Tests related to the XCS (XML character string) functionality +__ __ _ + ___\ \/ /_ __ __ _| |_ + / _ \\ /| '_ \ / _` | __| + | __// \| |_) | (_| | |_ + \___/_/\_\ .__/ \__,_|\__| + |_| XML parser + + Copyright (c) 2026 Sebastian Pipping <sebastian@pipping.org> + Licensed under the MIT license: + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the + following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. + + SPDX-License-Identifier: MIT +*/ + +#ifndef XML_XCS_TESTS_H +#define XML_XCS_TESTS_H + +#include "minicheck.h" + +extern void make_xcs_test_case(Suite *s); + +#endif /* XML_XCS_TESTS_H */ diff --git a/contrib/expat/xmlwf/Makefile.am b/contrib/expat/xmlwf/Makefile.am index c7eebd1eeec2..52d73a12e896 100644 --- a/contrib/expat/xmlwf/Makefile.am +++ b/contrib/expat/xmlwf/Makefile.am @@ -6,7 +6,7 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2017-2021 Sebastian Pipping <sebastian@pipping.org> +# Copyright (c) 2017-2026 Sebastian Pipping <sebastian@pipping.org> # Licensed under the MIT license: # # Permission is hereby granted, free of charge, to any person obtaining @@ -32,6 +32,7 @@ bin_PROGRAMS = xmlwf xmlwf_LDADD = ../lib/libexpat.la xmlwf_SOURCES = \ + ../lib/xcs.c \ xmlwf.c \ xmlfile.c \ codepage.c \ diff --git a/contrib/expat/xmlwf/Makefile.in b/contrib/expat/xmlwf/Makefile.in index 7c4ff12ef536..22968b148a65 100644 --- a/contrib/expat/xmlwf/Makefile.in +++ b/contrib/expat/xmlwf/Makefile.in @@ -22,7 +22,7 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2017-2021 Sebastian Pipping <sebastian@pipping.org> +# Copyright (c) 2017-2026 Sebastian Pipping <sebastian@pipping.org> # Licensed under the MIT license: # # Permission is hereby granted, free of charge, to any person obtaining @@ -148,8 +148,10 @@ CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) -am_xmlwf_OBJECTS = xmlwf-xmlwf.$(OBJEXT) xmlwf-xmlfile.$(OBJEXT) \ - xmlwf-codepage.$(OBJEXT) xmlwf-@FILEMAP@.$(OBJEXT) +am__dirstamp = $(am__leading_dot)dirstamp +am_xmlwf_OBJECTS = ../lib/xmlwf-xcs.$(OBJEXT) xmlwf-xmlwf.$(OBJEXT) \ + xmlwf-xmlfile.$(OBJEXT) xmlwf-codepage.$(OBJEXT) \ + xmlwf-@FILEMAP@.$(OBJEXT) xmlwf_OBJECTS = $(am_xmlwf_OBJECTS) xmlwf_DEPENDENCIES = ../lib/libexpat.la AM_V_lt = $(am__v_lt_@AM_V@) @@ -174,9 +176,9 @@ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/conftools/depcomp am__maybe_remake_depfiles = depfiles -am__depfiles_remade = ./$(DEPDIR)/xmlwf-@FILEMAP@.Po \ - ./$(DEPDIR)/xmlwf-codepage.Po ./$(DEPDIR)/xmlwf-xmlfile.Po \ - ./$(DEPDIR)/xmlwf-xmlwf.Po +am__depfiles_remade = ../lib/$(DEPDIR)/xmlwf-xcs.Po \ + ./$(DEPDIR)/xmlwf-@FILEMAP@.Po ./$(DEPDIR)/xmlwf-codepage.Po \ + ./$(DEPDIR)/xmlwf-xmlfile.Po ./$(DEPDIR)/xmlwf-xmlwf.Po am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @@ -260,12 +262,10 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ -EXPAT_ATTR_INFO = @EXPAT_ATTR_INFO@ EXPAT_CHAR_TYPE = @EXPAT_CHAR_TYPE@ EXPAT_CONTEXT_BYTES = @EXPAT_CONTEXT_BYTES@ EXPAT_DTD = @EXPAT_DTD@ EXPAT_LARGE_SIZE = @EXPAT_LARGE_SIZE@ -EXPAT_MIN_SIZE = @EXPAT_MIN_SIZE@ EXPAT_NS = @EXPAT_NS@ FGREP = @FGREP@ FILECMD = @FILECMD@ @@ -320,7 +320,6 @@ SO_PATCH = @SO_PATCH@ STRIP = @STRIP@ VERSION = @VERSION@ VSCRIPT_LDFLAGS = @VSCRIPT_LDFLAGS@ -_EXPAT_COMMENT_ATTR_INFO = @_EXPAT_COMMENT_ATTR_INFO@ _EXPAT_COMMENT_DTD_OR_GE = @_EXPAT_COMMENT_DTD_OR_GE@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ @@ -381,6 +380,7 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ xmlwf_LDADD = ../lib/libexpat.la xmlwf_SOURCES = \ + ../lib/xcs.c \ xmlwf.c \ xmlfile.c \ codepage.c \ @@ -477,6 +477,14 @@ uninstall-binPROGRAMS: clean-binPROGRAMS: $(am__rm_f) $(bin_PROGRAMS) test -z "$(EXEEXT)" || $(am__rm_f) $(bin_PROGRAMS:$(EXEEXT)=) +../lib/$(am__dirstamp): + @$(MKDIR_P) ../lib + @: >>../lib/$(am__dirstamp) +../lib/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) ../lib/$(DEPDIR) + @: >>../lib/$(DEPDIR)/$(am__dirstamp) +../lib/xmlwf-xcs.$(OBJEXT): ../lib/$(am__dirstamp) \ + ../lib/$(DEPDIR)/$(am__dirstamp) xmlwf$(EXEEXT): $(xmlwf_OBJECTS) $(xmlwf_DEPENDENCIES) $(EXTRA_xmlwf_DEPENDENCIES) @rm -f xmlwf$(EXEEXT) @@ -484,10 +492,12 @@ xmlwf$(EXEEXT): $(xmlwf_OBJECTS) $(xmlwf_DEPENDENCIES) $(EXTRA_xmlwf_DEPENDENCIE mostlyclean-compile: -rm -f *.$(OBJEXT) + -rm -f ../lib/*.$(OBJEXT) distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@../lib/$(DEPDIR)/xmlwf-xcs.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlwf-@FILEMAP@.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlwf-codepage.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlwf-xmlfile.Po@am__quote@ # am--include-marker @@ -523,6 +533,20 @@ am--depfiles: $(am__depfiles_remade) @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< +../lib/xmlwf-xcs.o: ../lib/xcs.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xmlwf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../lib/xmlwf-xcs.o -MD -MP -MF ../lib/$(DEPDIR)/xmlwf-xcs.Tpo -c -o ../lib/xmlwf-xcs.o `test -f '../lib/xcs.c' || echo '$(srcdir)/'`../lib/xcs.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ../lib/$(DEPDIR)/xmlwf-xcs.Tpo ../lib/$(DEPDIR)/xmlwf-xcs.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../lib/xcs.c' object='../lib/xmlwf-xcs.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xmlwf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../lib/xmlwf-xcs.o `test -f '../lib/xcs.c' || echo '$(srcdir)/'`../lib/xcs.c + +../lib/xmlwf-xcs.obj: ../lib/xcs.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xmlwf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../lib/xmlwf-xcs.obj -MD -MP -MF ../lib/$(DEPDIR)/xmlwf-xcs.Tpo -c -o ../lib/xmlwf-xcs.obj `if test -f '../lib/xcs.c'; then $(CYGPATH_W) '../lib/xcs.c'; else $(CYGPATH_W) '$(srcdir)/../lib/xcs.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ../lib/$(DEPDIR)/xmlwf-xcs.Tpo ../lib/$(DEPDIR)/xmlwf-xcs.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../lib/xcs.c' object='../lib/xmlwf-xcs.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xmlwf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../lib/xmlwf-xcs.obj `if test -f '../lib/xcs.c'; then $(CYGPATH_W) '../lib/xcs.c'; else $(CYGPATH_W) '$(srcdir)/../lib/xcs.c'; fi` + xmlwf-xmlwf.o: xmlwf.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xmlwf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xmlwf-xmlwf.o -MD -MP -MF $(DEPDIR)/xmlwf-xmlwf.Tpo -c -o xmlwf-xmlwf.o `test -f 'xmlwf.c' || echo '$(srcdir)/'`xmlwf.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xmlwf-xmlwf.Tpo $(DEPDIR)/xmlwf-xmlwf.Po @@ -704,6 +728,8 @@ clean-generic: distclean-generic: -$(am__rm_f) $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES) + -$(am__rm_f) ../lib/$(DEPDIR)/$(am__dirstamp) + -$(am__rm_f) ../lib/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -713,6 +739,7 @@ clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am + -rm -f ../lib/$(DEPDIR)/xmlwf-xcs.Po -rm -f ./$(DEPDIR)/xmlwf-@FILEMAP@.Po -rm -f ./$(DEPDIR)/xmlwf-codepage.Po -rm -f ./$(DEPDIR)/xmlwf-xmlfile.Po @@ -762,6 +789,7 @@ install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am + -rm -f ../lib/$(DEPDIR)/xmlwf-xcs.Po -rm -f ./$(DEPDIR)/xmlwf-@FILEMAP@.Po -rm -f ./$(DEPDIR)/xmlwf-codepage.Po -rm -f ./$(DEPDIR)/xmlwf-xmlfile.Po diff --git a/contrib/expat/xmlwf/xmlfile.c b/contrib/expat/xmlwf/xmlfile.c index 85e5dc582827..f3662dc570c9 100644 --- a/contrib/expat/xmlwf/xmlfile.c +++ b/contrib/expat/xmlwf/xmlfile.c @@ -45,6 +45,7 @@ #include "expat_config.h" +#include <inttypes.h> // PRIu64 #include <stdio.h> #include <stdlib.h> #include <stddef.h> @@ -98,11 +99,9 @@ reportError(XML_Parser parser, const XML_Char *filename) { enum XML_Error code = XML_GetErrorCode(parser); const XML_Char *message = XML_ErrorString(code); if (message) - ftprintf(stdout, - T("%s") T(":%") T(XML_FMT_INT_MOD) T("u") T(":%") - T(XML_FMT_INT_MOD) T("u") T(": %s\n"), - filename, XML_GetCurrentLineNumber(parser), - XML_GetCurrentColumnNumber(parser), message); + ftprintf(stdout, T("%s") T(":%") T(PRIu64) T(":%") T(PRIu64) T(": %s\n"), + filename, XML_GetCurrentLineNumber64(parser), + XML_GetCurrentColumnNumber64(parser), message); else ftprintf(stderr, T("%s: (unknown message %u)\n"), filename, (unsigned int)code); diff --git a/contrib/expat/xmlwf/xmlfile.h b/contrib/expat/xmlwf/xmlfile.h index 7eb4811103c2..0039badb70f8 100644 --- a/contrib/expat/xmlwf/xmlfile.h +++ b/contrib/expat/xmlwf/xmlfile.h @@ -37,15 +37,11 @@ #include <stdbool.h> +#include "expat.h" // for XML_Parser, XML_Char + #define XML_MAP_FILE 01 #define XML_EXTERNAL_ENTITIES 02 -#ifdef XML_LARGE_SIZE -# define XML_FMT_INT_MOD "ll" -#else -# define XML_FMT_INT_MOD "l" -#endif - extern int g_read_size_bytes; extern bool XML_ProcessFile(XML_Parser parser, const XML_Char *filename, diff --git a/contrib/expat/xmlwf/xmlwf.c b/contrib/expat/xmlwf/xmlwf.c index 892732cb0729..aec099e41758 100644 --- a/contrib/expat/xmlwf/xmlwf.c +++ b/contrib/expat/xmlwf/xmlwf.c @@ -50,6 +50,7 @@ #include "expat_config.h" #include <assert.h> +#include <inttypes.h> // for PRIu64 #include <stdio.h> #include <stdlib.h> #include <stddef.h> @@ -72,7 +73,7 @@ # include <wchar.h> #endif -#include "../lib/xcsinc.c" +#include "../lib/xcs.h" enum ExitCode { XMLWF_EXIT_SUCCESS = 0, @@ -360,23 +361,6 @@ cleanupUserData(XmlwfUserData *userData) { } static int -xcscmp(const XML_Char *xs, const XML_Char *xt) { - while (*xs != 0 && *xt != 0) { - if (*xs < *xt) - return -1; - if (*xs > *xt) - return 1; - xs++; - xt++; - } - if (*xs < *xt) - return -1; - if (*xs > *xt) - return 1; - return 0; -} - -static int notationCmp(const void *a, const void *b) { const NotationList *const n1 = *(const NotationList *const *)a; const NotationList *const n2 = *(const NotationList *const *)b; @@ -587,12 +571,11 @@ metaLocation(XML_Parser parser) { puttc(T('"'), fp); } ftprintf(fp, - T(" byte=\"%") T(XML_FMT_INT_MOD) T("d\"") T(" nbytes=\"%d\"") - T(" line=\"%") T(XML_FMT_INT_MOD) T("u\"") T(" col=\"%") - T(XML_FMT_INT_MOD) T("u\""), - XML_GetCurrentByteIndex(parser), XML_GetCurrentByteCount(parser), - XML_GetCurrentLineNumber(parser), - XML_GetCurrentColumnNumber(parser)); + T(" byte=\"%") T(PRId64) T("\"") T(" nbytes=\"%") T(PRIu64) T("\"") + T(" line=\"%") T(PRIu64) T("\"") T(" col=\"%") T(PRIu64) T("\""), + XML_GetCurrentByteIndex64(parser), XML_GetCurrentByteCount64(parser), + XML_GetCurrentLineNumber64(parser), + XML_GetCurrentColumnNumber64(parser)); } static void diff --git a/lib/libexpat/Makefile b/lib/libexpat/Makefile index 1c5be3659eba..ccc1adaf65c4 100644 --- a/lib/libexpat/Makefile +++ b/lib/libexpat/Makefile @@ -4,7 +4,7 @@ EXPAT= ${SRCTOP}/contrib/expat LIB= bsdxml SHLIBDIR?= /lib SHLIB_MAJOR= 4 -SRCS= random_arc4random_buf.c xmlparse.c xmlrole.c xmltok.c +SRCS= random_arc4random_buf.c xcs.c xmlparse.c xmlrole.c xmltok.c INCS= bsdxml.h bsdxml_external.h MAN= libbsdxml.3 diff --git a/lib/libexpat/expat_config.h b/lib/libexpat/expat_config.h index 1f84d179bcb7..91fb9fd550e5 100644 --- a/lib/libexpat/expat_config.h +++ b/lib/libexpat/expat_config.h @@ -89,7 +89,7 @@ #define PACKAGE_NAME "expat" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "expat 2.8.5" +#define PACKAGE_STRING "expat 2.9.0" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "expat" @@ -98,7 +98,7 @@ #define PACKAGE_URL "" /* Define to the version of this package. */ -#define PACKAGE_VERSION "2.8.5" +#define PACKAGE_VERSION "2.9.0" /* Define to 1 if all of the C89 standard headers exist (not just the ones required in a freestanding environment). This macro is provided for @@ -106,7 +106,7 @@ #define STDC_HEADERS 1 /* Version number of package */ -#define VERSION "2.8.5" +#define VERSION "2.9.0" /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ diff --git a/lib/libexpat/libbsdxml.3 b/lib/libexpat/libbsdxml.3 index ffacc9898bc2..bfdc4457093b 100644 --- a/lib/libexpat/libbsdxml.3 +++ b/lib/libexpat/libbsdxml.3 @@ -23,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\"/ -.Dd September 22, 2026 +.Dd October 5, 2026 .Dt LIBBSDXML 3 .Os .Sh NAME @@ -34,7 +34,7 @@ .Sh DESCRIPTION The .Nm -library is a verbatim copy of the eXpat XML library version 2.8.5. +library is a verbatim copy of the eXpat XML library version 2.9.0. .Pp The .Nm |
