aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Paeps <philip@FreeBSD.org>2026-09-22 13:37:02 +0000
committerPhilip Paeps <philip@FreeBSD.org>2026-09-22 13:37:02 +0000
commitad0a85f5d53d2280fc4eb9304d571cae7c2a2c4e (patch)
treebc1b58acee508b899a0c72f7582518d9d4187029
parent698f424711732909a9b349950543e220eb0dfa08 (diff)
Vendor import of expat 2.8.5vendor/expat/2.8.5vendor/expat
-rw-r--r--Changes87
-rw-r--r--Makefile.am7
-rw-r--r--Makefile.in153
-rw-r--r--README.md2
-rw-r--r--configure.ac18
-rw-r--r--doc/Makefile.in12
-rw-r--r--doc/reference.html32
-rw-r--r--doc/xmlwf.12
-rw-r--r--doc/xmlwf.xml2
-rw-r--r--examples/Makefile.in27
-rw-r--r--fuzz/xml_lpm_fuzzer.cpp5
-rw-r--r--fuzz/xml_parse_fuzzer.c14
-rw-r--r--fuzz/xml_parsebuffer_fuzzer.c13
-rw-r--r--lib/Makefile.am1
-rw-r--r--lib/Makefile.in28
-rw-r--r--lib/expat.h8
-rw-r--r--lib/expat_external.h12
-rw-r--r--lib/hash_table.h78
-rw-r--r--lib/internal.h163
-rw-r--r--lib/xmlparse.c223
-rw-r--r--lib/xmlrole.c113
-rw-r--r--lib/xmlrole.h14
-rw-r--r--lib/xmltok.c203
-rw-r--r--lib/xmltok.h58
-rw-r--r--lib/xmltok_impl.c63
-rw-r--r--lib/xmltok_ns.c6
-rw-r--r--tests/Makefile.am8
-rw-r--r--tests/Makefile.in52
-rw-r--r--tests/acc_tests.h12
-rw-r--r--tests/alloc_tests.h12
-rw-r--r--tests/basic_tests.c354
-rw-r--r--tests/basic_tests.h12
-rw-r--r--tests/benchmark/Makefile.in27
-rw-r--r--tests/chardata.h10
-rw-r--r--tests/common.h86
-rw-r--r--tests/dummy.h48
-rw-r--r--tests/handlers.h43
-rw-r--r--tests/hash_tests.c157
-rw-r--r--tests/hash_tests.h41
-rw-r--r--tests/memcheck.c3
-rw-r--r--tests/memcheck.h12
-rw-r--r--tests/minicheck.h76
-rw-r--r--tests/misc_tests.c2
-rw-r--r--tests/misc_tests.h12
-rw-r--r--tests/ns_tests.h12
-rw-r--r--tests/nsalloc_tests.c2
-rw-r--r--tests/nsalloc_tests.h12
-rw-r--r--tests/runtests.c4
-rw-r--r--tests/structdata.h9
-rwxr-xr-xtests/xmltest.sh2
-rw-r--r--xmlwf/Makefile.in27
-rw-r--r--xmlwf/unixfilemap.c4
-rw-r--r--xmlwf/xmlfile.c6
-rw-r--r--xmlwf/xmlfile.h8
-rw-r--r--xmlwf/xmlmime.h10
-rw-r--r--xmlwf/xmlwf.c25
-rwxr-xr-xxmlwf/xmlwf_helpgen.py7
-rwxr-xr-xxmlwf/xmlwf_helpgen.sh8
58 files changed, 1601 insertions, 846 deletions
diff --git a/Changes b/Changes
index af91a67dd5ce..bf94e9db5616 100644
--- a/Changes
+++ b/Changes
@@ -13,9 +13,94 @@
!! will be funded by the City of Munich as part of their !!
!! Open Source Sabbatical (https://opensource.muenchen.de/sabbatical.html) !!
!! — thank you! !!
-!! Sebastian Pipping -- Berlin, 2026-08-03 !!
+!! !!
+!! 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.8.5 Tue September 22 2026
+ Security fixes:
+ #1282 CVE-2026-93990 -- Reject high surrogates not followed by a
+ low surrogate during UTF-16 decoding; previously, malformed
+ UTF-16 could be smuggled into the application using Expat
+ and could cause arbitrary damage there, depending on how
+ malformed UTF-16 was handled inside the application;
+ validation was not their job but Expat's. This is similar
+ to past vulnerability CVE-2022-25235.
+ 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
+ pointers like CHERI-RISC-V
+ #1367 xmlwf: Handle errors when closing output files
+
+ Other changes:
+ #1354 lib: Reject an XML declaration version other than `1.[0-9]+`
+ (which is less strict than XML 1.0r4 (fourth edition)
+ and matches XML 1.0r5 (fifth edition))
+ #1362 lib: Make Clang, GCC and MSVC warn about use of function
+ XML_SetHashSalt that is deprecated since Expat 2.8.0
+ #1357 lib: Drop internal macros FASTCALL, PTRCALL, PTRFASTCALL
+ #1367 xmlwf: Document that with `-k` the last error determines the
+ xmlwf exit code in `--help` output
+ #1367 xmlwf: Make exit code 3 documentation match exit code 2 more
+ closely in `--help` output
+ #1352 #1353 CMake|Windows: Refrain from adding `/source-charset:utf-8`
+ for MSVC
+ #1366 #1374 Autotools: Be explicit about the minimum required version of
+ GNU Automake, currently version 1.13 of 2012-12-28
+ #1351 Autotools|macOS: Sync CMake templates with CMake 4.4.3
+ #1349 Replace some internal use of XML_Bool with standard bool
+ #1364 tests: Propagate xmltest.sh failures via exit status
+ #1360 tests|xmlwf: Add `#include "expat_config.h"` where missing
+ #1355 tests: Start covering hash table operation
+ #1350 #1369 tests: Drop __cplusplus leftovers
+ #1378 tests: Fix tail pointer when unlinking the last tracked
+ allocation
+ #1376 docs: Emphasize that XML_StopParser is not immediate
+ #1381 docs: Sync XML_FeatureEnum value list in doc/reference.html
+ #1356 #1361 Version info bumped from 13:4:12 (libexpat*.so.1.12.4)
+ to 13:5:12 (libexpat*.so.1.12.5); see https://verbump.de/
+ for what these numbers do
+
+ Infrastructure:
+ #1347 Add missing .gitignore entries
+ #1360 CI: Detect missing `#include "expat_config.h"`
+ #1368 CI: Bump MinGW Clang from 23.0.1 to 23.1.1
+ #1377 CI: Bump Fil-C from 0.684 to 0.685
+ #1380 CI: Bump Cppcheck from 2.21.0 to 2.22.0
+ #1372 CI: Extract helper script `apply-htmltidy.sh`
+ #1366 #1374 Autotools: Start to also produce .tar.bz3 release tarballs
+
+ Special thanks to:
+ Afonso Januário
+ Braian Plaku
+ Florian Schmaus
+ Huang Wenbin
+ Kamila Szewczyk
+ Kartik Kenchi
+ Leo Camus
+ Matthew Fernandez
+ Stan Ulbrych
+ and
+ City of Munich Open Source Sabbatical
+
Release 2.8.4 Mon August 31 2026
Security fixes:
#1321 #1331 CVE-2026-66046, CVE-2026-76641 -- Fix quadratic runtime from
diff --git a/Makefile.am b/Makefile.am
index 09b88f315165..fbc03d85f474 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -33,13 +33,6 @@
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
# USE OR OTHER DEALINGS IN THE SOFTWARE.
-AUTOMAKE_OPTIONS = \
- dist-bzip2 \
- dist-lzip \
- dist-xz \
- foreign \
- subdir-objects
-
ACLOCAL_AMFLAGS = -I m4
LIBTOOLFLAGS = --verbose
diff --git a/Makefile.in b/Makefile.in
index 0f9a441aa882..c0a0eefc47ac 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.18.1 from Makefile.am.
+# Makefile.in generated by automake 1.19 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2025 Free Software Foundation, Inc.
+# Copyright (C) 1994-2026 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -261,7 +261,13 @@ am__remove_distdir = \
; rm -rf "$(distdir)" \
|| { sleep 5 && rm -rf "$(distdir)"; }; \
else :; fi
-am__post_remove_distdir = $(am__remove_distdir)
+am__post_remove_distdir = \
+ $(am__is_gnu_make) || rm -f am__distdir.tar; \
+ $(am__remove_distdir)
+am__ensure_distdir_tar = \
+ test -f am__distdir.tar || $(MAKE) $(AM_MAKEFLAGS) am__distdir.tar
+am__dist_compress_failed = \
+ am__rc=$$?; rm -f $$am__archive am__distdir.tar; exit $$am__rc
am__relativize = \
dir0=`pwd`; \
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
@@ -287,10 +293,13 @@ am__relativize = \
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
done; \
reldir="$$dir2"
-DIST_ARCHIVES = $(distdir).tar.gz $(distdir).tar.bz2 $(distdir).tar.lz \
- $(distdir).tar.xz
+# Exists only to be overridden by the user if desired.
+AM_DIST_TAR_IGNORE_STDERR = $(am__tar_ignore_stderr)
+DIST_ARCHIVES = $(distdir).tar.gz $(distdir).tar.bz2 \
+ $(distdir).tar.bz3 $(distdir).tar.lz $(distdir).tar.xz
GZIP_ENV = -9
-DIST_TARGETS = dist-lzip dist-xz dist-bzip2 dist-gzip
+DIST_TARGETS = am--dist-lzip am--dist-xz am--dist-bzip2 am--dist-bzip3 \
+ am--dist-gzip
# Exists only to be overridden by the user if desired.
AM_DISTCHECK_DVI_TARGET = dvi
distuninstallcheck_listfiles = find . -type f -print
@@ -411,6 +420,7 @@ am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__rm_f_notfound = @am__rm_f_notfound@
am__tar = @am__tar@
+am__tar_ignore_stderr = @am__tar_ignore_stderr@
am__untar = @am__untar@
am__xargs_n = @am__xargs_n@
bindir = @bindir@
@@ -454,13 +464,6 @@ target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
-AUTOMAKE_OPTIONS = \
- dist-bzip2 \
- dist-lzip \
- dist-xz \
- foreign \
- subdir-objects
-
ACLOCAL_AMFLAGS = -I m4
LIBTOOLFLAGS = --verbose
SUBDIRS = lib $(am__append_1) $(am__append_2) $(am__append_3)
@@ -748,13 +751,14 @@ distdir-am: $(DISTFILES)
$(AM_V_at)$(MKDIR_P) "$(distdir)"
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ am__distdir="$(distdir)"; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sed "/\//!d;s|^|$$am__distdir/|;s,/[^/]*$$,," | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
@@ -807,55 +811,96 @@ distdir-am: $(DISTFILES)
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|| chmod -R a+r "$(distdir)"
-dist-gzip: distdir
- tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz
+
+am__distdir.tar: distdir
+ am__distdir="$(distdir)"; \
+ am__tar_msg=`tardir=$$am__distdir && $(am__tar) 2>&1 >am__distdir.tar`; \
+ am__tar_rc=$$?; \
+ test -z "$$am__tar_msg" || { printf '%s\n' "$$am__tar_msg" >&2; \
+ test x"$(AM_DIST_TAR_IGNORE_STDERR)" = xyes || am__tar_rc=1; }; \
+ test $$am__tar_rc -eq 0 || { rm -f am__distdir.tar; \
+ echo "$(distdir).tar: cannot create the distribution archive" >&2; exit 1; }
+
+.INTERMEDIATE: am__distdir.tar
+dist-gzip: am--dist-gzip
$(am__post_remove_distdir)
-dist-bzip2: distdir
- tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
+am--dist-gzip: am__distdir.tar
+ @$(am__ensure_distdir_tar)
+ am__archive=$(distdir).tar.gz; \
+ eval GZIP= gzip $(GZIP_ENV) -c <am__distdir.tar >$$am__archive \
+ || { $(am__dist_compress_failed); }
+dist-bzip2: am--dist-bzip2
$(am__post_remove_distdir)
-
-dist-bzip3: distdir
- tardir=$(distdir) && $(am__tar) | bzip3 -c >$(distdir).tar.bz3
+am--dist-bzip2: am__distdir.tar
+ @$(am__ensure_distdir_tar)
+ am__archive=$(distdir).tar.bz2; \
+ BZIP2=$${BZIP2--9} bzip2 -c <am__distdir.tar >$$am__archive \
+ || { $(am__dist_compress_failed); }
+dist-bzip3: am--dist-bzip3
$(am__post_remove_distdir)
-dist-lzip: distdir
- tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
+am--dist-bzip3: am__distdir.tar
+ @$(am__ensure_distdir_tar)
+ am__archive=$(distdir).tar.bz3; \
+ bzip3 -c <am__distdir.tar >$$am__archive \
+ || { $(am__dist_compress_failed); }
+dist-lzip: am--dist-lzip
$(am__post_remove_distdir)
-dist-xz: distdir
- tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
+am--dist-lzip: am__distdir.tar
+ @$(am__ensure_distdir_tar)
+ am__archive=$(distdir).tar.lz; \
+ lzip -c $${LZIP_OPT--9} <am__distdir.tar >$$am__archive \
+ || { $(am__dist_compress_failed); }
+dist-xz: am--dist-xz
$(am__post_remove_distdir)
+am--dist-xz: am__distdir.tar
+ @$(am__ensure_distdir_tar)
+ am__archive=$(distdir).tar.xz; \
+ XZ_OPT=$${XZ_OPT--e} xz -c <am__distdir.tar >$$am__archive \
+ || { $(am__dist_compress_failed); }
-dist-zstd: distdir
- tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst
+dist-zstd: am--dist-zstd
$(am__post_remove_distdir)
+am--dist-zstd: am__distdir.tar
+ @$(am__ensure_distdir_tar)
+ am__archive=$(distdir).tar.zst; \
+ zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} <am__distdir.tar >$$am__archive \
+ || { $(am__dist_compress_failed); }
-dist-tarZ: distdir
+dist-tarZ: am--dist-tarZ
+ $(am__post_remove_distdir)
+am--dist-tarZ: am__distdir.tar
+ @$(am__ensure_distdir_tar)
@echo WARNING: "Support for distribution archives compressed with" \
"legacy program 'compress' is deprecated." >&2
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
- tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
- $(am__post_remove_distdir)
+ am__archive=$(distdir).tar.Z; \
+ compress -c <am__distdir.tar >$$am__archive \
+ || { $(am__dist_compress_failed); }
-dist-shar: distdir
+dist-shar: am--dist-shar
+ $(am__post_remove_distdir)
+am--dist-shar: distdir
@echo WARNING: "Support for shar distribution archives is" \
"deprecated." >&2
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
- shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz
- $(am__post_remove_distdir)
+ shar $(distdir) >$(distdir).shar || { rm -f $(distdir).shar; exit 1; }
+ eval GZIP= gzip $(GZIP_ENV) -f $(distdir).shar
-dist-zip: distdir
+dist-zip: am--dist-zip
+ $(am__post_remove_distdir)
+am--dist-zip: distdir
-rm -f $(distdir).zip
zip -rq $(distdir).zip $(distdir)
- $(am__post_remove_distdir)
dist dist-all:
- $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:'
+ $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS)
$(am__post_remove_distdir)
# This target untars the dist file and tries a VPATH configuration. Then
# it guarantees that the distribution is self-contained by making another
# tarfile.
distcheck: dist
- case '$(DIST_ARCHIVES)' in \
+ case "$(DIST_ARCHIVES)" in \
*.tar.gz*) \
eval GZIP= gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
*.tar.bz2*) \
@@ -879,11 +924,13 @@ distcheck: dist
chmod u+w $(distdir)
mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst
chmod a-w $(distdir)
- test -d $(distdir)/_build || exit 0; \
- dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+ am__distdir="$(distdir)"; \
+ am__distarchives="$(DIST_ARCHIVES)"; \
+ test -d "$$am__distdir/_build" || exit 0; \
+ dc_install_base=`$(am__cd) "$$am__distdir/_inst" && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
&& am__cwd=`pwd` \
- && $(am__cd) $(distdir)/_build/sub \
+ && $(am__cd) "$$am__distdir/_build/sub" \
&& ../../configure \
$(AM_DISTCHECK_CONFIGURE_FLAGS) \
$(DISTCHECK_CONFIGURE_FLAGS) \
@@ -906,13 +953,13 @@ distcheck: dist
} || { rm -rf "$$dc_destdir"; exit 1; }) \
&& rm -rf "$$dc_destdir" \
&& $(MAKE) $(AM_MAKEFLAGS) dist \
- && rm -rf $(DIST_ARCHIVES) \
+ && rm -rf $$am__distarchives \
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
&& cd "$$am__cwd" \
|| exit 1
$(am__post_remove_distdir)
@(echo "$(distdir) archives ready for distribution: "; \
- list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+ list="$(DIST_ARCHIVES)"; for i in $$list; do echo $$i; done) | \
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
distuninstallcheck:
@test -n '$(distuninstallcheck_dir)' || { \
@@ -1051,16 +1098,18 @@ uninstall-am: uninstall-nodist_cmakeDATA uninstall-pkgconfigDATA
.MAKE: $(am__recursive_targets) all install-am install-strip
.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
- am--refresh check check-am clean clean-cscope clean-generic \
- clean-libtool cscope cscopelist-am ctags ctags-am dist \
- dist-all dist-bzip2 dist-bzip3 dist-gzip dist-lzip dist-shar \
- dist-tarZ dist-xz dist-zip dist-zstd distcheck distclean \
- distclean-generic distclean-hdr distclean-libtool \
- distclean-tags distcleancheck distdir distuninstallcheck dvi \
- dvi-am html html-am info info-am install install-am \
- install-data install-data-am install-dvi install-dvi-am \
- install-exec install-exec-am install-html install-html-am \
- install-info install-info-am install-man \
+ am--dist-bzip2 am--dist-bzip3 am--dist-gzip am--dist-lzip \
+ am--dist-shar am--dist-tarZ am--dist-xz am--dist-zip \
+ am--dist-zstd am--refresh check check-am clean clean-cscope \
+ clean-generic clean-libtool cscope cscopelist-am ctags \
+ ctags-am dist dist-all dist-bzip2 dist-bzip3 dist-gzip \
+ dist-lzip dist-shar dist-tarZ dist-xz dist-zip dist-zstd \
+ distcheck distclean distclean-generic distclean-hdr \
+ distclean-libtool distclean-tags distcleancheck distdir \
+ distuninstallcheck dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
install-nodist_cmakeDATA install-pdf install-pdf-am \
install-pkgconfigDATA install-ps install-ps-am install-strip \
installcheck installcheck-am installdirs installdirs-am \
diff --git a/README.md b/README.md
index ae43ed3cc663..36e46a90fd23 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@
> Thank you! :heart: :pray:
-# Expat, Release 2.8.4
+# Expat, Release 2.8.5
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/configure.ac b/configure.ac
index be6b8b289197..e8562dbc5fc1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -74,7 +74,21 @@ AC_CONFIG_SRCDIR([Makefile.in])
AC_CONFIG_AUX_DIR([conftools])
AC_CONFIG_MACRO_DIR([m4])
AC_CANONICAL_HOST
-AM_INIT_AUTOMAKE
+
+dnl NOTE: Macro `AM_OPTIONAL_AUTOMAKE` is available with Automake >=1.19
+dnl and serves as a proxy for robust Automake >=1.19 detection here.
+dnl `dist-bzip3` was introduced with Automake 1.18 already but there
+dnl is no robust way of checking precisely for Automake >=1.18.
+dnl Automake >=1.13 is needed for (1) our use of LOG_DRIVER and
+dnl (2) making it work without asking for parallel tests, explicitly.
+m4_ifdef([AM_OPTIONAL_AUTOMAKE], [
+ AM_INIT_AUTOMAKE([1.19 dist-bzip2 dist-bzip3 dist-lzip dist-xz foreign subdir-objects])
+
+ dnl NOTE: Without this dummy call in the file the `m4_ifdef` above never hits true.
+ AM_OPTIONAL_AUTOMAKE([])
+], [
+ AM_INIT_AUTOMAKE([1.13 dist-bzip2 dist-lzip dist-xz foreign subdir-objects])
+])
AM_MAINTAINER_MODE([enable]) # to allow argument --disable-maintainer-mode
@@ -90,7 +104,7 @@ dnl If the API changes incompatibly set LIBAGE back to 0
dnl
LIBCURRENT=13 # sync
-LIBREVISION=4 # with
+LIBREVISION=5 # with
LIBAGE=12 # CMakeLists.txt!
AC_CONFIG_HEADERS([expat_config.h])
diff --git a/doc/Makefile.in b/doc/Makefile.in
index 0bda758420f0..52a18ffb673f 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.18.1 from Makefile.am.
+# Makefile.in generated by automake 1.19 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2025 Free Software Foundation, Inc.
+# Copyright (C) 1994-2026 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -309,6 +309,7 @@ am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__rm_f_notfound = @am__rm_f_notfound@
am__tar = @am__tar@
+am__tar_ignore_stderr = @am__tar_ignore_stderr@
am__untar = @am__untar@
am__xargs_n = @am__xargs_n@
bindir = @bindir@
@@ -372,9 +373,9 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu doc/Makefile
+ $(AUTOMAKE) --foreign doc/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
@@ -455,13 +456,14 @@ distdir: $(BUILT_SOURCES)
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ am__distdir="$(distdir)"; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sed "/\//!d;s|^|$$am__distdir/|;s,/[^/]*$$,," | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
diff --git a/doc/reference.html b/doc/reference.html
index e54c7be2965a..5bd9150ea78a 100644
--- a/doc/reference.html
+++ b/doc/reference.html
@@ -53,7 +53,7 @@
<body>
<div>
<h1>
- The Expat XML Parser <small>Release 2.8.4</small>
+ The Expat XML Parser <small>Release 2.8.5</small>
</h1>
</div>
@@ -1763,12 +1763,16 @@ XML_StopParser(XML_Parser p,
</pre>
<div class="fcndef">
<p>
- Stops parsing, causing <code><a href="#XML_Parse">XML_Parse</a></code> or
- <code><a href="#XML_ParseBuffer">XML_ParseBuffer</a></code> to return. Must be
- called from within a call-back handler, except when aborting (when
- <code>resumable</code> is <code>XML_FALSE</code>) an already suspended parser.
- Some call-backs may still follow because they would otherwise get lost,
- including
+ Stops parsing as soon as possible, causing <code><a href=
+ "#XML_Parse">XML_Parse</a></code> or <code><a href=
+ "#XML_ParseBuffer">XML_ParseBuffer</a></code> to return. Must be called from
+ within a call-back handler, except when aborting (when <code>resumable</code>
+ is <code>XML_FALSE</code>) an already suspended parser.
+ </p>
+
+ <p>
+ <strong>Note:</strong> Some call-backs may still follow because they would
+ otherwise get lost, including
</p>
<ul>
@@ -3709,8 +3713,20 @@ enum XML_FeatureEnum {
XML_FEATURE_MIN_SIZE,
XML_FEATURE_SIZEOF_XML_CHAR,
XML_FEATURE_SIZEOF_XML_LCHAR,
+ /* Added in Expat 2.0.0. */
XML_FEATURE_NS,
- XML_FEATURE_LARGE_SIZE
+ /* Added in Expat 2.0.1. */
+ XML_FEATURE_LARGE_SIZE,
+ /* Added in Expat 2.1.0. */
+ XML_FEATURE_ATTR_INFO,
+ /* Added in Expat 2.4.0. */
+ XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT,
+ XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT,
+ /* Added in Expat 2.6.0. */
+ XML_FEATURE_GE,
+ /* Added in Expat 2.7.2. */
+ XML_FEATURE_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION_DEFAULT,
+ XML_FEATURE_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT,
};
typedef struct {
diff --git a/doc/xmlwf.1 b/doc/xmlwf.1
index 7177cbf19c49..e9b6a2fe4610 100644
--- a/doc/xmlwf.1
+++ b/doc/xmlwf.1
@@ -5,7 +5,7 @@
\\$2 \(la\\$1\(ra\\$3
..
.if \n(.g .mso www.tmac
-.TH XMLWF 1 "August 31, 2026" "" ""
+.TH XMLWF 1 "September 22, 2026" "" ""
.SH NAME
xmlwf \- Determines if an XML document is well-formed
.SH SYNOPSIS
diff --git a/doc/xmlwf.xml b/doc/xmlwf.xml
index 93a67c407563..e7a2664b7e42 100644
--- a/doc/xmlwf.xml
+++ b/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>August 31, 2026</date>">
+ <!ENTITY dhdate "<date>September 22, 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/examples/Makefile.in b/examples/Makefile.in
index 56a6f69c07b7..4ef878f7867c 100644
--- a/examples/Makefile.in
+++ b/examples/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.18.1 from Makefile.am.
+# Makefile.in generated by automake 1.19 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2025 Free Software Foundation, Inc.
+# Copyright (C) 1994-2026 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -337,6 +337,7 @@ am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__rm_f_notfound = @am__rm_f_notfound@
am__tar = @am__tar@
+am__tar_ignore_stderr = @am__tar_ignore_stderr@
am__untar = @am__untar@
am__xargs_n = @am__xargs_n@
bindir = @bindir@
@@ -399,9 +400,9 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu examples/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign examples/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu examples/Makefile
+ $(AUTOMAKE) --foreign examples/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
@@ -453,22 +454,25 @@ $(am__depfiles_remade):
am--depfiles: $(am__depfiles_remade)
.c.o:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
@@ -537,13 +541,14 @@ distdir: $(BUILT_SOURCES)
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ am__distdir="$(distdir)"; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sed "/\//!d;s|^|$$am__distdir/|;s,/[^/]*$$,," | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
diff --git a/fuzz/xml_lpm_fuzzer.cpp b/fuzz/xml_lpm_fuzzer.cpp
index 719629a6b547..190b34f74d98 100644
--- a/fuzz/xml_lpm_fuzzer.cpp
+++ b/fuzz/xml_lpm_fuzzer.cpp
@@ -8,6 +8,7 @@
Copyright (c) 2022 Mark Brand <markbrand@google.com>
Copyright (c) 2025 Sebastian Pipping <sebastian@pipping.org>
+ Copyright (c) 2026 Braian Plaku <braianplaku@gmail.com>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@@ -383,7 +384,9 @@ UnknownEncodingHandler(void *encodingHandlerData, const XML_Char *name,
void
InitializeParser(XML_Parser parser) {
XML_SetUserData(parser, (void *)parser);
- XML_SetHashSalt(parser, 0x41414141);
+ const uint8_t entropy[16] = {0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
+ 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41};
+ XML_SetHashSalt16Bytes(parser, entropy);
XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
XML_SetElementDeclHandler(parser, ElementDeclHandler);
diff --git a/fuzz/xml_parse_fuzzer.c b/fuzz/xml_parse_fuzzer.c
index 29ab33ff79d9..1eb0ad299628 100644
--- a/fuzz/xml_parse_fuzzer.c
+++ b/fuzz/xml_parse_fuzzer.c
@@ -17,6 +17,7 @@
#include <assert.h>
#include <limits.h> // for INT_MAX
#include <stdint.h>
+#include <string.h>
#include "expat.h"
#include "siphash.h"
@@ -34,7 +35,8 @@
#endif
// 16-byte deterministic hash key.
-static unsigned char hash_key[16] = "FUZZING IS FUN!";
+static unsigned char hash_key_1[16] = "FUZZING IS FUN?";
+static unsigned char hash_key_2[16] = "FUZZING IS FUN!";
static void XMLCALL
start(void *userData, const XML_Char *name, const XML_Char **atts) {
@@ -59,8 +61,14 @@ may_stop_character_handler(void *userData, const XML_Char *s, int len) {
static void
ParseOneInput(XML_Parser p, const uint8_t *data, size_t size) {
// Set the hash salt using siphash to generate a deterministic hash.
- struct sipkey *key = sip_keyof(hash_key);
- XML_SetHashSalt(p, (unsigned long)siphash24(data, size, key));
+ // The salt is 16 bytes and siphash24 produces 8, so the input is hashed
+ // under two keys.
+ const uint64_t first = siphash24(data, size, sip_keyof(hash_key_1));
+ const uint64_t second = siphash24(data, size, sip_keyof(hash_key_2));
+ uint8_t entropy[16];
+ memcpy(entropy, &first, sizeof(first));
+ memcpy(entropy + sizeof(first), &second, sizeof(second));
+ XML_SetHashSalt16Bytes(p, entropy);
(void)sip24_valid;
XML_SetUserData(p, p);
diff --git a/fuzz/xml_parsebuffer_fuzzer.c b/fuzz/xml_parsebuffer_fuzzer.c
index 38b9981b0b50..a854f6706396 100644
--- a/fuzz/xml_parsebuffer_fuzzer.c
+++ b/fuzz/xml_parsebuffer_fuzzer.c
@@ -35,7 +35,8 @@
#endif
// 16-byte deterministic hash key.
-static unsigned char hash_key[16] = "FUZZING IS FUN!";
+static unsigned char hash_key_1[16] = "FUZZING IS FUN?";
+static unsigned char hash_key_2[16] = "FUZZING IS FUN!";
static void XMLCALL
start(void *userData, const XML_Char *name, const XML_Char **atts) {
@@ -60,8 +61,14 @@ may_stop_character_handler(void *userData, const XML_Char *s, int len) {
static void
ParseOneInput(XML_Parser p, const uint8_t *data, size_t size) {
// Set the hash salt using siphash to generate a deterministic hash.
- struct sipkey *key = sip_keyof(hash_key);
- XML_SetHashSalt(p, (unsigned long)siphash24(data, size, key));
+ // The salt is 16 bytes and siphash24 produces 8, so the input is hashed
+ // under two keys.
+ const uint64_t first = siphash24(data, size, sip_keyof(hash_key_1));
+ const uint64_t second = siphash24(data, size, sip_keyof(hash_key_2));
+ uint8_t entropy[16];
+ memcpy(entropy, &first, sizeof(first));
+ memcpy(entropy + sizeof(first), &second, sizeof(second));
+ XML_SetHashSalt16Bytes(p, entropy);
(void)sip24_valid;
XML_SetUserData(p, p);
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 2b6aec2e6bdc..6b0d0af4e3c5 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -115,6 +115,7 @@ EXTRA_DIST = \
expat_external.h \
expat.h \
fallthrough.h \
+ hash_table.h \
iasciitab.h \
internal.h \
latin1tab.h \
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 73db0e584705..58b19912b596 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.18.1 from Makefile.am.
+# Makefile.in generated by automake 1.19 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2025 Free Software Foundation, Inc.
+# Copyright (C) 1994-2026 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -444,6 +444,7 @@ am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__rm_f_notfound = @am__rm_f_notfound@
am__tar = @am__tar@
+am__tar_ignore_stderr = @am__tar_ignore_stderr@
am__untar = @am__untar@
am__xargs_n = @am__xargs_n@
bindir = @bindir@
@@ -511,6 +512,7 @@ EXTRA_DIST = \
expat_external.h \
expat.h \
fallthrough.h \
+ hash_table.h \
iasciitab.h \
internal.h \
latin1tab.h \
@@ -540,9 +542,9 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu lib/Makefile
+ $(AUTOMAKE) --foreign lib/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
@@ -643,22 +645,25 @@ $(am__depfiles_remade):
am--depfiles: $(am__depfiles_remade)
.c.o:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
@@ -832,13 +837,14 @@ distdir: $(BUILT_SOURCES)
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ am__distdir="$(distdir)"; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sed "/\//!d;s|^|$$am__distdir/|;s,/[^/]*$$,," | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
diff --git a/lib/expat.h b/lib/expat.h
index b296be9dbad2..4c3851d50a5f 100644
--- a/lib/expat.h
+++ b/lib/expat.h
@@ -20,6 +20,7 @@
Copyright (c) 2023 Sony Corporation / Snild Dolkow <snild@sony.com>
Copyright (c) 2024 Taichi Haradaguchi <20001722@ymail.ne.jp>
Copyright (c) 2025 Matthew Fernandez <matthew.fernandez@gmail.com>
+ Copyright (c) 2026 Braian Plaku <braianplaku@gmail.com>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@@ -921,7 +922,9 @@ XML_SetParamEntityParsing(XML_Parser parser,
Returns 1 if successful, 0 when called after parsing has started.
Note: If parser == NULL, the function will do nothing and return 0.
DEPRECATED since Expat 2.8.0.
+ Please use XML_SetHashSalt16Bytes instead.
*/
+XML_ATTR_DEPRECATED("please use XML_SetHashSalt16Bytes instead")
XMLPARSEAPI(int)
XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt);
@@ -1040,8 +1043,11 @@ enum XML_FeatureEnum {
XML_FEATURE_MIN_SIZE,
XML_FEATURE_SIZEOF_XML_CHAR,
XML_FEATURE_SIZEOF_XML_LCHAR,
+ /* Added in Expat 2.0.0. */
XML_FEATURE_NS,
+ /* Added in Expat 2.0.1. */
XML_FEATURE_LARGE_SIZE,
+ /* Added in Expat 2.1.0. */
XML_FEATURE_ATTR_INFO,
/* Added in Expat 2.4.0. */
XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT,
@@ -1096,7 +1102,7 @@ XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled);
*/
# define XML_MAJOR_VERSION 2
# define XML_MINOR_VERSION 8
-# define XML_MICRO_VERSION 4
+# define XML_MICRO_VERSION 5
# ifdef __cplusplus
}
diff --git a/lib/expat_external.h b/lib/expat_external.h
index 4cd1f3a49c35..cf80f960d6e1 100644
--- a/lib/expat_external.h
+++ b/lib/expat_external.h
@@ -16,6 +16,7 @@
Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
Copyright (c) 2018 Yury Gribov <tetra2005@gmail.com>
Copyright (c) 2026 Matthew Fernandez <matthew.fernandez@gmail.com>
+ Copyright (c) 2026 Braian Plaku <braianplaku@gmail.com>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@@ -125,6 +126,17 @@
# define XML_ATTR_ALLOC_SIZE(x)
# endif
+/* Marks a function that Expat still provides but that callers should move off
+ of. */
+# if defined(__clang__) || defined(__GNUC__)
+# define XML_ATTR_DEPRECATED(message) \
+ __attribute__((__deprecated__(message)))
+# elif defined(_MSC_VER)
+# define XML_ATTR_DEPRECATED(message) __declspec(deprecated(message))
+# else
+# define XML_ATTR_DEPRECATED(message) // empty i.e. no deprecation
+# endif
+
# define XMLPARSEAPI(type) XMLIMPORT type XMLCALL
# ifdef __cplusplus
diff --git a/lib/hash_table.h b/lib/hash_table.h
new file mode 100644
index 000000000000..f290aad18693
--- /dev/null
+++ b/lib/hash_table.h
@@ -0,0 +1,78 @@
+/* Hash table related internal API
+ __ __ _
+ ___\ \/ /_ __ __ _| |_
+ / _ \\ /| '_ \ / _` | __|
+ | __// \| |_) | (_| | |_
+ \___/_/\_\ .__/ \__,_|\__|
+ |_| 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
+*/
+
+#if ! defined(HASH_TABLE_H)
+# define HASH_TABLE_H 1
+
+# include "expat.h" // for XML_Bool, XML_Parser
+# include "internal.h" // for XML_NONTESTING_STATIC
+
+# include <stddef.h> // for size_t
+
+typedef const XML_Char *KEY;
+
+typedef struct {
+ KEY name;
+} NAMED;
+
+typedef struct {
+ NAMED **v;
+ unsigned char power;
+ size_t size;
+ size_t used;
+ XML_Parser parser;
+} HASH_TABLE;
+
+typedef struct {
+ NAMED **p;
+ NAMED **end;
+} HASH_TABLE_ITER;
+
+XML_NONTESTING_STATIC NAMED *lookupWithLength(XML_Parser parser,
+ HASH_TABLE *table, KEY name,
+ size_t nameLen,
+ size_t createSize);
+XML_NONTESTING_STATIC NAMED *lookup(XML_Parser parser, HASH_TABLE *table,
+ KEY name, size_t createSize);
+
+XML_NONTESTING_STATIC void hashTableInit(HASH_TABLE *table, XML_Parser parser);
+XML_NONTESTING_STATIC void hashTableClear(HASH_TABLE *table);
+XML_NONTESTING_STATIC void hashTableDestroy(HASH_TABLE *table);
+XML_NONTESTING_STATIC void hashTableIterInit(HASH_TABLE_ITER *iter,
+ const HASH_TABLE *table);
+XML_NONTESTING_STATIC NAMED *hashTableIterNext(HASH_TABLE_ITER *iter);
+
+XML_NONTESTING_STATIC XML_Bool keyeq(KEY s1, size_t s1len, KEY s2);
+XML_NONTESTING_STATIC size_t keylen(KEY s);
+
+#endif // ! defined(HASH_TABLE_H)
diff --git a/lib/internal.h b/lib/internal.h
index 6311028e94b8..86655371d290 100644
--- a/lib/internal.h
+++ b/lib/internal.h
@@ -6,13 +6,6 @@
The following calling convention macros are defined for frequently
called functions:
- FASTCALL - Used for those internal functions that have a simple
- body and a low number of arguments and local variables.
-
- PTRCALL - Used for functions called though function pointers.
-
- PTRFASTCALL - Like PTRCALL, but for low number of arguments.
-
inline - Used for selected internal functions for which inlining
may improve performance on some platforms.
@@ -34,6 +27,8 @@
Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild@sony.com>
Copyright (c) 2024 Taichi Haradaguchi <20001722@ymail.ne.jp>
Copyright (c) 2026 Matthew Wozniczka <mattheww@simba.com>
+ Copyright (c) 2026 Braian Plaku <braianplaku@gmail.com>
+ Copyright (c) 2026 Florian Schmaus <florian.schmaus@codasip.com>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@@ -58,132 +53,104 @@
SPDX-License-Identifier: MIT
*/
-#if defined(__GNUC__) && defined(__i386__) && ! defined(__MINGW32__)
-/* We'll use this version by default only where we know it helps.
-
- regparm() generates warnings on Solaris boxes. See SF bug #692878.
-
- Instability reported with egcs on a RedHat Linux 7.3.
- Let's comment out:
- #define FASTCALL __attribute__((stdcall, regparm(3)))
- and let's try this:
-*/
-# define FASTCALL __attribute__((regparm(3)))
-# define PTRFASTCALL __attribute__((regparm(3)))
-#endif
-
-/* Using __fastcall seems to have an unexpected negative effect under
- MS VC++, especially for function pointers, so we won't use it for
- now on that platform. It may be reconsidered for a future release
- if it can be made more effective.
- Likely reason: __fastcall on Windows is like stdcall, therefore
- the compiler cannot perform stack optimizations for call clusters.
-*/
-
-/* Make sure all of these are defined if they aren't already. */
-
-#ifndef FASTCALL
-# define FASTCALL
-#endif
-
-#ifndef PTRCALL
-# define PTRCALL
-#endif
+#if ! defined(INTERNAL_H)
+# define INTERNAL_H 1
-#ifndef PTRFASTCALL
-# define PTRFASTCALL
-#endif
+# ifndef XML_MIN_SIZE
+# if ! defined(inline)
+# ifdef __GNUC__
+# define inline __inline
+# endif /* __GNUC__ */
+# endif
+# endif /* XML_MIN_SIZE */
-#ifndef XML_MIN_SIZE
-# if ! defined(__cplusplus) && ! defined(inline)
-# ifdef __GNUC__
-# define inline __inline
-# endif /* __GNUC__ */
-# endif
-#endif /* XML_MIN_SIZE */
-
-#ifdef __cplusplus
-# define inline inline
-#else
# ifndef inline
# define inline
# endif
-#endif
-#include <limits.h> // ULONG_MAX
-#include <stddef.h> // size_t
+# if ! defined(XML_NONTESTING_STATIC)
+# if defined(XML_TESTING)
+# define XML_NONTESTING_STATIC // empty i.e. not static
+# else
+# define XML_NONTESTING_STATIC static
+# endif
+# endif
+
+# include <limits.h> // ULONG_MAX
+# include <stddef.h> // size_t
-#if defined(_WIN32) \
- && (! defined(__USE_MINGW_ANSI_STDIO) \
- || (1 - __USE_MINGW_ANSI_STDIO - 1 == 0))
-# define EXPAT_FMT_LLX(midpart) "%" midpart "I64x"
-# define EXPAT_FMT_ULL(midpart) "%" midpart "I64u"
-# if defined(_WIN64) // Note: modifiers "td" and "zu" do not work for MinGW
-# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "I64d"
-# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "I64u"
+# if defined(_WIN32) \
+ && (! defined(__USE_MINGW_ANSI_STDIO) \
+ || (1 - __USE_MINGW_ANSI_STDIO - 1 == 0))
+# define EXPAT_FMT_LLX(midpart) "%" midpart "I64x"
+# define EXPAT_FMT_ULL(midpart) "%" midpart "I64u"
+# if defined(_WIN64) // Note: modifiers "td" and "zu" do not work for MinGW
+# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "I64d"
+# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "I64u"
+# else
+# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "d"
+# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "u"
+# endif
# else
-# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "d"
-# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "u"
+# include <inttypes.h> // PRIdPTR, PRIuPTR
+# define EXPAT_FMT_LLX(midpart) "%" midpart "llx"
+# define EXPAT_FMT_ULL(midpart) "%" midpart "llu"
+# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart PRIdPTR
+# define EXPAT_FMT_SIZE_T(midpart) "%" midpart PRIuPTR
# endif
-#else
-# include <inttypes.h> // PRIdPTR, PRIuPTR
-# define EXPAT_FMT_LLX(midpart) "%" midpart "llx"
-# define EXPAT_FMT_ULL(midpart) "%" midpart "llu"
-# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart PRIdPTR
-# define EXPAT_FMT_SIZE_T(midpart) "%" midpart PRIuPTR
-#endif
-#ifndef UNUSED_P
-# define UNUSED_P(p) (void)p
-#endif
+# ifndef UNUSED_P
+# define UNUSED_P(p) (void)p
+# endif
/* NOTE BEGIN If you ever patch these defaults to greater values
for non-attack XML payload in your environment,
please file a bug report with libexpat. Thank you!
*/
-#define EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT \
- 100.0f
-#define EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT \
- 8388608 // 8 MiB, 2^23
+# define EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT \
+ 100.0f
+# define EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT \
+ 8388608 // 8 MiB, 2^23
-#define EXPAT_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION_DEFAULT 100.0f
-#define EXPAT_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT \
- 67108864 // 64 MiB, 2^26
+# define EXPAT_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION_DEFAULT 100.0f
+# define EXPAT_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT \
+ 67108864 // 64 MiB, 2^26
// NOTE: If function expat_alloc was user facing, EXPAT_MALLOC_ALIGNMENT would
// have to take sizeof(long double) into account
-#define EXPAT_MALLOC_ALIGNMENT sizeof(long long) // largest parser (sub)member
-#define EXPAT_MALLOC_PADDING ((EXPAT_MALLOC_ALIGNMENT) - sizeof(size_t))
+union expat_align {
+ long long l;
+ void *p;
+};
+# define EXPAT_MALLOC_ALIGNMENT sizeof(union expat_align)
+# define EXPAT_MALLOC_PADDING ((EXPAT_MALLOC_ALIGNMENT) - sizeof(size_t))
/* NOTE END */
-#include "expat.h" // so we can use type XML_Parser below
-
-#ifdef __cplusplus
-extern "C" {
-#endif
+# include "expat.h" // so we can use type XML_Parser below
void _INTERNAL_trim_to_complete_utf8_characters(const char *from,
const char **fromLimRef);
-#if defined(XML_GE) && XML_GE == 1
+# if defined(XML_GE) && XML_GE == 1
unsigned long long testingAccountingGetCountBytesDirect(XML_Parser parser);
unsigned long long testingAccountingGetCountBytesIndirect(XML_Parser parser);
const char *unsignedCharToPrintable(unsigned char c);
-#endif
+# endif
extern
-#if ! defined(XML_TESTING)
+# if ! defined(XML_TESTING)
const
-#endif
+# endif
XML_Bool g_reparseDeferralEnabledDefault; // written ONLY in runtests.c
-#if defined(XML_TESTING)
+# if defined(XML_TESTING)
+
+int xmlSetHashSalt(XML_Parser parser, unsigned long hash_salt);
+
void *expat_malloc(XML_Parser parser, size_t size, int sourceLine);
void expat_free(XML_Parser parser, void *ptr, int sourceLine);
void *expat_realloc(XML_Parser parser, void *ptr, size_t size, int sourceLine);
extern unsigned int g_bytesScanned; // used for testing only
-#endif
+# endif
-#ifdef __cplusplus
-}
-#endif
+#endif // not defined INTERNAL_H
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index 2e1936fb84c4..c3642bd52ff9 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -1,4 +1,4 @@
-/* 13c4e8da8fccffb0e8e599684e0d447ad14c1bb0b48792cf5dd77d8712301871 (2.8.4+)
+/* 0864fe2d216f47b742263b698bc051c865b342e8b820e42c234717098ea507e3 (2.8.5+)
__ __ _
___\ \/ /_ __ __ _| |_
/ _ \\ /| '_ \ / _` | __|
@@ -54,6 +54,8 @@
Copyright (c) 2026 Darren Carreras <carrerasdarren@gmail.com>
Copyright (c) 2026 Alberto Maschietto <albertomaschietto9@gmail.com>
Copyright (c) 2026 Zeyou Liu <zeyouliu@tencent.com>
+ Copyright (c) 2026 Stan Ulbrych <stan@python.org>
+ Copyright (c) 2026 Braian Plaku <braianplaku@gmail.com>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@@ -226,25 +228,10 @@ typedef char ICHAR;
#define EXPAT_MIN(a, b) (((a) < (b)) ? (a) : (b))
#include "internal.h"
+#include "hash_table.h"
#include "xmltok.h"
#include "xmlrole.h"
-typedef const XML_Char *KEY;
-
-typedef struct {
- KEY name;
-} NAMED;
-
-typedef struct {
- NAMED **v;
- unsigned char power;
- size_t size;
- size_t used;
- XML_Parser parser;
-} HASH_TABLE;
-
-static size_t keylen(KEY s);
-
static void copy_salt_to_sipkey(XML_Parser parser, struct sipkey *key);
/* For probing (after a collision) we need a step size relative prime
@@ -260,11 +247,6 @@ static void copy_salt_to_sipkey(XML_Parser parser, struct sipkey *key);
#define PROBE_STEP(hash, mask, power) \
((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
-typedef struct {
- NAMED **p;
- NAMED **end;
-} HASH_TABLE_ITER;
-
#define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
#define INIT_DATA_BUF_SIZE 1024
#define INIT_ATTS_SIZE 16
@@ -334,12 +316,12 @@ typedef struct {
const XML_Char *publicId;
const XML_Char *notation;
bool open;
- XML_Bool hasMore; /* true if entity has not been completely processed */
- /* An entity can be open while being already completely processed (hasMore ==
- XML_FALSE). The reason is the delayed closing of entities until their inner
+ bool hasMore; /* true if entity has not been completely processed */
+ /* An entity can be open while being already completely processed (!hasMore).
+ The reason is the delayed closing of entities until their inner
entities are processed and closed */
- XML_Bool is_param;
- XML_Bool is_internal; /* true if declared in internal subset outside PE */
+ bool is_param;
+ bool is_internal; /* true if declared in internal subset outside PE */
} ENTITY;
typedef struct {
@@ -374,8 +356,8 @@ typedef struct {
typedef struct attribute_id {
XML_Char *name;
PREFIX *prefix;
- XML_Bool maybeTokenized;
- XML_Bool xmlns;
+ bool maybeTokenized;
+ bool xmlns;
} ATTRIBUTE_ID;
typedef struct {
@@ -431,12 +413,12 @@ typedef struct {
XML_Bool standalone;
#ifdef XML_DTD
/* indicates if external PE has been read */
- XML_Bool paramEntityRead;
+ bool paramEntityRead;
HASH_TABLE paramEntities;
#endif /* XML_DTD */
PREFIX defaultPrefix;
/* === scaffolding for building content model === */
- XML_Bool in_eldecl;
+ bool in_eldecl;
CONTENT_SCAFFOLD *scaffold;
unsigned contentStringLen;
unsigned scaffSize;
@@ -458,7 +440,7 @@ typedef struct open_internal_entity {
struct open_internal_entity *next;
ENTITY *entity;
int startTagLevel;
- XML_Bool betweenDecl; /* WFC: PE Between Declarations */
+ bool betweenDecl; /* WFC: PE Between Declarations */
enum EntityType type;
} OPEN_INTERNAL_ENTITY;
@@ -495,8 +477,8 @@ typedef struct entity_stats {
} ENTITY_STATS;
#endif /* XML_GE == 1 */
-typedef enum XML_Error PTRCALL Processor(XML_Parser parser, const char *start,
- const char *end, const char **endPtr);
+typedef enum XML_Error Processor(XML_Parser parser, const char *start,
+ const char *end, const char **endPtr);
static Processor prologProcessor;
static Processor prologInitProcessor;
@@ -528,7 +510,7 @@ static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc,
XML_Bool haveMore, XML_Bool allowClosingDoctype,
enum XML_Account account);
static enum XML_Error processEntity(XML_Parser parser, ENTITY *entity,
- XML_Bool betweenDecl, enum EntityType type);
+ bool betweenDecl, enum EntityType type);
static enum XML_Error doContent(XML_Parser parser, int startTagLevel,
const ENCODING *enc, const char *start,
const char *end, const char **endPtr,
@@ -588,7 +570,7 @@ static void reportDefault(XML_Parser parser, const ENCODING *enc,
static const XML_Char *getContext(XML_Parser parser);
static XML_Bool setContext(XML_Parser parser, const XML_Char *context);
-static void FASTCALL normalizePublicId(XML_Char *s);
+static void normalizePublicId(XML_Char *s);
static DTD *dtdCreate(XML_Parser parser);
/* do not call if m_parentParser != NULL */
@@ -598,36 +580,24 @@ static int dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
XML_Parser parser);
static int copyEntityTable(XML_Parser oldParser, HASH_TABLE *newTable,
STRING_POOL *newPool, const HASH_TABLE *oldTable);
-static NAMED *lookupWithLength(XML_Parser parser, HASH_TABLE *table, KEY name,
- size_t nameLen, size_t createSize);
-static NAMED *lookup(XML_Parser parser, HASH_TABLE *table, KEY name,
- size_t createSize);
-static void FASTCALL hashTableInit(HASH_TABLE *table, XML_Parser parser);
-static void FASTCALL hashTableClear(HASH_TABLE *table);
-static void FASTCALL hashTableDestroy(HASH_TABLE *table);
-static void FASTCALL hashTableIterInit(HASH_TABLE_ITER *iter,
- const HASH_TABLE *table);
-static NAMED *FASTCALL hashTableIterNext(HASH_TABLE_ITER *iter);
-static void FASTCALL poolInit(STRING_POOL *pool, XML_Parser parser);
-static void FASTCALL poolClear(STRING_POOL *pool);
-static void FASTCALL poolDestroy(STRING_POOL *pool);
+static void poolInit(STRING_POOL *pool, XML_Parser parser);
+static void poolClear(STRING_POOL *pool);
+static void poolDestroy(STRING_POOL *pool);
static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
const char *ptr, const char *end);
static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
const char *ptr, const char *end);
-static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
-static bool FASTCALL poolGrowUntil(STRING_POOL *pool, size_t needed);
-static const XML_Char *FASTCALL poolCopyString(STRING_POOL *pool,
- const XML_Char *s);
-static const XML_Char *FASTCALL poolCopyStringNoFinish(STRING_POOL *pool,
- const XML_Char *s);
+static XML_Bool poolGrow(STRING_POOL *pool);
+static bool poolGrowUntil(STRING_POOL *pool, size_t needed);
+static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s);
+static const XML_Char *poolCopyStringNoFinish(STRING_POOL *pool,
+ const XML_Char *s);
static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s,
int n);
-static const XML_Char *FASTCALL poolAppendString(STRING_POOL *pool,
- const XML_Char *s);
+static const XML_Char *poolAppendString(STRING_POOL *pool, const XML_Char *s);
-static int FASTCALL nextScaffoldPart(XML_Parser parser);
+static int nextScaffoldPart(XML_Parser parser);
static XML_Content *build_model(XML_Parser parser);
static ELEMENT_TYPE *getElementType(XML_Parser parser, const ENCODING *enc,
const char *ptr, const char *end);
@@ -1596,7 +1566,7 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) {
}
/* moves list of bindings to m_freeBindingList */
-static void FASTCALL
+static void
moveToFreeBindingList(XML_Parser parser, BINDING *bindings) {
while (bindings) {
BINDING *b = bindings;
@@ -1869,7 +1839,7 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
return parser;
}
-static void FASTCALL
+static void
destroyBindings(BINDING *bindings, XML_Parser parser) {
for (;;) {
BINDING *b = bindings;
@@ -2268,9 +2238,10 @@ XML_SetParamEntityParsing(XML_Parser parser,
#endif
}
-// DEPRECATED since Expat 2.8.0.
-int XMLCALL
-XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) {
+/* The body of XML_SetHashSalt, so that Expat's own tests can reach it
+ without tripping the deprecation of the public function. */
+XML_NONTESTING_STATIC int
+xmlSetHashSalt(XML_Parser parser, unsigned long hash_salt) {
if (parser == NULL)
return 0;
@@ -2296,6 +2267,12 @@ XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) {
return 1;
}
+// DEPRECATED since Expat 2.8.0.
+int XMLCALL
+XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) {
+ return xmlSetHashSalt(parser, hash_salt);
+}
+
XML_Bool XMLCALL
XML_SetHashSalt16Bytes(XML_Parser parser, const uint8_t entropy[16]) {
if (parser == NULL)
@@ -3168,7 +3145,7 @@ storeRawNames(XML_Parser parser) {
return XML_TRUE;
}
-static enum XML_Error PTRCALL
+static enum XML_Error
contentProcessor(XML_Parser parser, const char *start, const char *end,
const char **endPtr) {
enum XML_Error result = doContent(
@@ -3182,7 +3159,7 @@ contentProcessor(XML_Parser parser, const char *start, const char *end,
return result;
}
-static enum XML_Error PTRCALL
+static enum XML_Error
externalEntityInitProcessor(XML_Parser parser, const char *start,
const char *end, const char **endPtr) {
enum XML_Error result = initializeEncoding(parser);
@@ -3192,7 +3169,7 @@ externalEntityInitProcessor(XML_Parser parser, const char *start,
return externalEntityInitProcessor2(parser, start, end, endPtr);
}
-static enum XML_Error PTRCALL
+static enum XML_Error
externalEntityInitProcessor2(XML_Parser parser, const char *start,
const char *end, const char **endPtr) {
const char *next = start; /* XmlContentTok doesn't always set the last arg */
@@ -3237,7 +3214,7 @@ externalEntityInitProcessor2(XML_Parser parser, const char *start,
return externalEntityInitProcessor3(parser, start, end, endPtr);
}
-static enum XML_Error PTRCALL
+static enum XML_Error
externalEntityInitProcessor3(XML_Parser parser, const char *start,
const char *end, const char **endPtr) {
int tok;
@@ -3289,7 +3266,7 @@ externalEntityInitProcessor3(XML_Parser parser, const char *start,
return externalEntityContentProcessor(parser, start, end, endPtr);
}
-static enum XML_Error PTRCALL
+static enum XML_Error
externalEntityContentProcessor(XML_Parser parser, const char *start,
const char *end, const char **endPtr) {
enum XML_Error result
@@ -4551,6 +4528,7 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
/* Detect and prevent integer overflow */
if (len > SIZE_MAX - EXPAND_SPARE
|| len + EXPAND_SPARE > SIZE_MAX / sizeof(XML_Char)) {
+ FREE(parser, b);
return XML_ERROR_NO_MEMORY;
}
@@ -4588,7 +4566,7 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
/* The idea here is to avoid using stack for each CDATA section when
the whole file is parsed with one call.
*/
-static enum XML_Error PTRCALL
+static enum XML_Error
cdataSectionProcessor(XML_Parser parser, const char *start, const char *end,
const char **endPtr) {
enum XML_Error result = doCdataSection(
@@ -4754,7 +4732,7 @@ doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
/* The idea here is to avoid using stack for each IGNORE section when
the whole file is parsed with one call.
*/
-static enum XML_Error PTRCALL
+static enum XML_Error
ignoreSectionProcessor(XML_Parser parser, const char *start, const char *end,
const char **endPtr) {
enum XML_Error result
@@ -5024,7 +5002,7 @@ handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName) {
return XML_ERROR_UNKNOWN_ENCODING;
}
-static enum XML_Error PTRCALL
+static enum XML_Error
prologInitProcessor(XML_Parser parser, const char *s, const char *end,
const char **nextPtr) {
enum XML_Error result = initializeEncoding(parser);
@@ -5036,7 +5014,7 @@ prologInitProcessor(XML_Parser parser, const char *s, const char *end,
#ifdef XML_DTD
-static enum XML_Error PTRCALL
+static enum XML_Error
externalParEntInitProcessor(XML_Parser parser, const char *s, const char *end,
const char **nextPtr) {
enum XML_Error result = initializeEncoding(parser);
@@ -5045,7 +5023,7 @@ externalParEntInitProcessor(XML_Parser parser, const char *s, const char *end,
/* we know now that XML_Parse(Buffer) has been called,
so we consider the external parameter entity read */
- parser->m_dtd->paramEntityRead = XML_TRUE;
+ parser->m_dtd->paramEntityRead = true;
if (parser->m_prologState.inEntityValue) {
parser->m_processor = entityValueInitProcessor;
@@ -5056,7 +5034,7 @@ externalParEntInitProcessor(XML_Parser parser, const char *s, const char *end,
}
}
-static enum XML_Error PTRCALL
+static enum XML_Error
entityValueInitProcessor(XML_Parser parser, const char *s, const char *end,
const char **nextPtr) {
int tok;
@@ -5140,7 +5118,7 @@ entityValueInitProcessor(XML_Parser parser, const char *s, const char *end,
}
}
-static enum XML_Error PTRCALL
+static enum XML_Error
externalParEntProcessor(XML_Parser parser, const char *s, const char *end,
const char **nextPtr) {
const char *next = s;
@@ -5186,7 +5164,7 @@ externalParEntProcessor(XML_Parser parser, const char *s, const char *end,
XML_ACCOUNT_DIRECT);
}
-static enum XML_Error PTRCALL
+static enum XML_Error
entityValueProcessor(XML_Parser parser, const char *s, const char *end,
const char **nextPtr) {
const char *start = s;
@@ -5233,7 +5211,7 @@ entityValueProcessor(XML_Parser parser, const char *s, const char *end,
#endif /* XML_DTD */
-static enum XML_Error PTRCALL
+static enum XML_Error
prologProcessor(XML_Parser parser, const char *s, const char *end,
const char **nextPtr) {
const char *next = s;
@@ -5479,7 +5457,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
}
if (parser->m_useForeignDTD)
entity->base = parser->m_curBase;
- dtd->paramEntityRead = XML_FALSE;
+ dtd->paramEntityRead = false;
beforeHandler(parser);
const int status = parser->m_externalEntityRefHandler(
parser->m_externalEntityRefHandlerArg, 0, entity->base,
@@ -5529,7 +5507,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
if (! entity)
return XML_ERROR_NO_MEMORY;
entity->base = parser->m_curBase;
- dtd->paramEntityRead = XML_FALSE;
+ dtd->paramEntityRead = false;
beforeHandler(parser);
const int status = parser->m_externalEntityRefHandler(
parser->m_externalEntityRefHandlerArg, 0, entity->base,
@@ -5872,7 +5850,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
} else {
poolFinish(&dtd->pool);
parser->m_declEntity->publicId = NULL;
- parser->m_declEntity->is_param = XML_FALSE;
+ parser->m_declEntity->is_param = false;
/* if we have a parent parser or are reading an internal parameter
entity, then the entity declaration is not considered "internal"
*/
@@ -5902,7 +5880,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
} else {
poolFinish(&dtd->pool);
parser->m_declEntity->publicId = NULL;
- parser->m_declEntity->is_param = XML_TRUE;
+ parser->m_declEntity->is_param = true;
/* if we have a parent parser or are reading an internal parameter
entity, then the entity declaration is not considered "internal"
*/
@@ -6137,8 +6115,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
return XML_ERROR_RECURSIVE_ENTITY_REF;
if (entity->textPtr) {
enum XML_Error result;
- XML_Bool betweenDecl
- = (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
+ bool betweenDecl = (role == XML_ROLE_PARAM_ENTITY_REF);
result = processEntity(parser, entity, betweenDecl, ENTITY_INTERNAL);
if (result != XML_ERROR_NONE)
return result;
@@ -6146,7 +6123,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
break;
}
if (parser->m_externalEntityRefHandler) {
- dtd->paramEntityRead = XML_FALSE;
+ dtd->paramEntityRead = false;
entity->open = true;
entityTrackingOnOpen(parser, entity, __LINE__);
beforeHandler(parser);
@@ -6190,7 +6167,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
return XML_ERROR_NO_MEMORY;
dtd->scaffLevel = 0;
dtd->scaffCount = 0;
- dtd->in_eldecl = XML_TRUE;
+ dtd->in_eldecl = true;
handleDefault = XML_FALSE;
}
break;
@@ -6219,7 +6196,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
afterHandler(parser);
handleDefault = XML_FALSE;
}
- dtd->in_eldecl = XML_FALSE;
+ dtd->in_eldecl = false;
}
break;
@@ -6301,7 +6278,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
parser->m_handlerArg, parser->m_declElementType->name, model);
afterHandler(parser);
}
- dtd->in_eldecl = XML_FALSE;
+ dtd->in_eldecl = false;
dtd->contentStringLen = 0;
}
}
@@ -6370,7 +6347,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
/* not reached */
}
-static enum XML_Error PTRCALL
+static enum XML_Error
epilogProcessor(XML_Parser parser, const char *s, const char *end,
const char **nextPtr) {
parser->m_processor = epilogProcessor;
@@ -6449,7 +6426,7 @@ epilogProcessor(XML_Parser parser, const char *s, const char *end,
}
static enum XML_Error
-processEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl,
+processEntity(XML_Parser parser, ENTITY *entity, bool betweenDecl,
enum EntityType type) {
OPEN_INTERNAL_ENTITY *openEntity, **openEntityList;
OPEN_INTERNAL_ENTITY **const freeEntityList = &parser->m_freeEntities;
@@ -6485,7 +6462,7 @@ processEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl,
return XML_ERROR_NO_MEMORY;
}
entity->open = true;
- entity->hasMore = XML_TRUE;
+ entity->hasMore = true;
#if XML_GE == 1
entityTrackingOnOpen(parser, entity, __LINE__);
#endif
@@ -6507,7 +6484,7 @@ processEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl,
return XML_ERROR_NONE;
}
-static enum XML_Error PTRCALL
+static enum XML_Error
internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
const char **nextPtr) {
UNUSED_P(s);
@@ -6557,7 +6534,7 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
// Entity is complete. We cannot close it here since we need to first
// process its possible inner entities (which are added to the
// m_openInternalEntities during doProlog or doContent calls above)
- entity->hasMore = XML_FALSE;
+ entity->hasMore = false;
if (! entity->is_param
&& (openEntity->startTagLevel != parser->m_tagLevel)) {
return XML_ERROR_ASYNC_ENTITY;
@@ -6589,7 +6566,7 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
return XML_ERROR_NONE;
}
-static enum XML_Error PTRCALL
+static enum XML_Error
errorProcessor(XML_Parser parser, const char *s, const char *end,
const char **nextPtr) {
UNUSED_P(s);
@@ -6640,7 +6617,7 @@ storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
// Entity is complete. We cannot close it here since we need to first
// process its possible inner entities (which are added to the
// m_openAttributeEntities during appendAttributeValue)
- entity->hasMore = XML_FALSE;
+ entity->hasMore = false;
continue;
} // End of entity processing, "if" block skips the rest
@@ -6948,7 +6925,7 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc,
}
if (entity->systemId) {
if (parser->m_externalEntityRefHandler) {
- dtd->paramEntityRead = XML_FALSE;
+ dtd->paramEntityRead = false;
entity->open = true;
entityTrackingOnOpen(parser, entity, __LINE__);
beforeHandler(parser);
@@ -7100,7 +7077,7 @@ callStoreEntityValue(XML_Parser parser, const ENCODING *enc,
// Entity is complete. We cannot close it here since we need to first
// process its possible inner entities (which are added to the
// m_openValueEntities during storeEntityValue)
- entity->hasMore = XML_FALSE;
+ entity->hasMore = false;
continue;
} // End of entity processing, "if" block skips the rest
@@ -7162,7 +7139,7 @@ storeSelfEntityValue(XML_Parser parser, ENTITY *entity) {
#endif /* XML_GE == 0 */
-static void FASTCALL
+static void
normalizeLines(XML_Char *s) {
XML_Char *p;
for (;; s++) {
@@ -7328,7 +7305,7 @@ defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
att->value = value;
att->isCdata = isCdata;
if (! isCdata)
- attId->maybeTokenized = XML_TRUE;
+ attId->maybeTokenized = true;
NAME_AND_DEFAULT_ATTRIBUTE *const nameAndDefaultAttribute
= (NAME_AND_DEFAULT_ATTRIBUTE *)lookup(
@@ -7413,7 +7390,7 @@ getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
else
id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6,
sizeof(PREFIX));
- id->xmlns = XML_TRUE;
+ id->xmlns = true;
} else {
int i;
for (i = 0; name[i]; i++) {
@@ -7603,7 +7580,7 @@ setContext(XML_Parser parser, const XML_Char *context) {
return XML_TRUE;
}
-static void FASTCALL
+static void
normalizePublicId(XML_Char *publicId) {
XML_Char *p = publicId;
XML_Char *s;
@@ -7636,13 +7613,13 @@ dtdCreate(XML_Parser parser) {
hashTableInit(&(p->attributeIds), parser);
hashTableInit(&(p->prefixes), parser);
#ifdef XML_DTD
- p->paramEntityRead = XML_FALSE;
+ p->paramEntityRead = false;
hashTableInit(&(p->paramEntities), parser);
#endif /* XML_DTD */
p->defaultPrefix.name = NULL;
p->defaultPrefix.binding = NULL;
- p->in_eldecl = XML_FALSE;
+ p->in_eldecl = false;
p->scaffIndex = NULL;
p->scaffIndexSize = 0;
p->scaffold = NULL;
@@ -7670,7 +7647,7 @@ dtdReset(DTD *p, XML_Parser parser) {
}
hashTableClear(&(p->generalEntities));
#ifdef XML_DTD
- p->paramEntityRead = XML_FALSE;
+ p->paramEntityRead = false;
hashTableClear(&(p->paramEntities));
#endif /* XML_DTD */
hashTableClear(&(p->elementTypes));
@@ -7681,7 +7658,7 @@ dtdReset(DTD *p, XML_Parser parser) {
p->defaultPrefix.name = NULL;
p->defaultPrefix.binding = NULL;
- p->in_eldecl = XML_FALSE;
+ p->in_eldecl = false;
FREE(parser, p->scaffIndex);
p->scaffIndex = NULL;
@@ -7949,7 +7926,7 @@ copyEntityTable(XML_Parser oldParser, HASH_TABLE *newTable,
// Compares two strings `s1` and `s2` whereas:
// - `s2` is zero-terminated but
// - `s1` is made up of exactly (not just up to) `s1len` non-zero characters.
-static XML_Bool FASTCALL
+XML_NONTESTING_STATIC XML_Bool
keyeq(KEY s1, size_t s1len, KEY s2) {
#ifdef XML_UNICODE
# ifdef XML_UNICODE_WCHAR_T
@@ -7966,7 +7943,7 @@ keyeq(KEY s1, size_t s1len, KEY s2) {
#endif
}
-static size_t
+XML_NONTESTING_STATIC size_t
keylen(KEY s) {
return xcslen(s);
}
@@ -7979,7 +7956,7 @@ copy_salt_to_sipkey(XML_Parser parser, struct sipkey *key) {
*key = rootParser->m_hash_secret_salt_128;
}
-static unsigned long FASTCALL
+static unsigned long
hash(XML_Parser parser, KEY s, size_t keyLen) {
struct siphash state;
struct sipkey key;
@@ -8009,7 +7986,7 @@ hash(XML_Parser parser, KEY s, size_t keyLen) {
// read-write mode does, because keys can be re-hashed later and the
// hash table does not store key length information.
//
-static NAMED *
+XML_NONTESTING_STATIC NAMED *
lookupWithLength(XML_Parser parser, HASH_TABLE *table, KEY name, size_t nameLen,
size_t createSize) {
size_t i;
@@ -8116,12 +8093,12 @@ lookupWithLength(XML_Parser parser, HASH_TABLE *table, KEY name, size_t nameLen,
// be used to tell cases "existed and found" and "newly inserted" apart
// with the structure returned.
//
-static NAMED *
+XML_NONTESTING_STATIC NAMED *
lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) {
return lookupWithLength(parser, table, name, keylen(name), createSize);
}
-static void FASTCALL
+XML_NONTESTING_STATIC void
hashTableClear(HASH_TABLE *table) {
size_t i;
for (i = 0; i < table->size; i++) {
@@ -8131,7 +8108,7 @@ hashTableClear(HASH_TABLE *table) {
table->used = 0;
}
-static void FASTCALL
+XML_NONTESTING_STATIC void
hashTableDestroy(HASH_TABLE *table) {
size_t i;
for (i = 0; i < table->size; i++)
@@ -8139,7 +8116,7 @@ hashTableDestroy(HASH_TABLE *table) {
FREE(table->parser, table->v);
}
-static void FASTCALL
+XML_NONTESTING_STATIC void
hashTableInit(HASH_TABLE *p, XML_Parser parser) {
p->power = 0;
p->size = 0;
@@ -8148,13 +8125,13 @@ hashTableInit(HASH_TABLE *p, XML_Parser parser) {
p->parser = parser;
}
-static void FASTCALL
+XML_NONTESTING_STATIC void
hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table) {
iter->p = table->v;
iter->end = iter->p ? iter->p + table->size : NULL;
}
-static NAMED *FASTCALL
+XML_NONTESTING_STATIC NAMED *
hashTableIterNext(HASH_TABLE_ITER *iter) {
while (iter->p != iter->end) {
NAMED *tem = *(iter->p)++;
@@ -8164,7 +8141,7 @@ hashTableIterNext(HASH_TABLE_ITER *iter) {
return NULL;
}
-static void FASTCALL
+static void
poolInit(STRING_POOL *pool, XML_Parser parser) {
pool->blocks = NULL;
pool->freeBlocks = NULL;
@@ -8174,7 +8151,7 @@ poolInit(STRING_POOL *pool, XML_Parser parser) {
pool->parser = parser;
}
-static void FASTCALL
+static void
poolClear(STRING_POOL *pool) {
if (! pool->freeBlocks)
pool->freeBlocks = pool->blocks;
@@ -8193,7 +8170,7 @@ poolClear(STRING_POOL *pool) {
pool->end = NULL;
}
-static void FASTCALL
+static void
poolDestroy(STRING_POOL *pool) {
BLOCK *p = pool->blocks;
while (p) {
@@ -8226,7 +8203,7 @@ poolAppend(STRING_POOL *pool, const ENCODING *enc, const char *ptr,
return pool->start;
}
-static const XML_Char *FASTCALL
+static const XML_Char *
poolCopyString(STRING_POOL *pool, const XML_Char *s) {
if (! poolAppendChars(pool, s, xcslen(s) + /*null terminator*/ 1))
return NULL;
@@ -8237,7 +8214,7 @@ poolCopyString(STRING_POOL *pool, const XML_Char *s) {
// A version of `poolCopyString` that does not call `poolFinish`
// and reverts any partial advancement upon failure.
-static const XML_Char *FASTCALL
+static const XML_Char *
poolCopyStringNoFinish(STRING_POOL *pool, const XML_Char *s) {
const XML_Char *const original = s;
do {
@@ -8275,7 +8252,7 @@ poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n) {
return s;
}
-static const XML_Char *FASTCALL
+static const XML_Char *
poolAppendString(STRING_POOL *pool, const XML_Char *s) {
if (! poolAppendChars(pool, s, xcslen(s)))
return NULL;
@@ -8320,7 +8297,7 @@ poolBytesToAllocateFor(int blockSize) {
}
}
-static XML_Bool FASTCALL
+static XML_Bool
poolGrow(STRING_POOL *pool) {
if (pool->freeBlocks) {
if (pool->start == NULL) {
@@ -8425,7 +8402,7 @@ poolGrow(STRING_POOL *pool) {
return XML_TRUE;
}
-static bool FASTCALL
+static bool
poolGrowUntil(STRING_POOL *pool, size_t needed) {
for (;;) {
const size_t available = pool->end - pool->ptr;
@@ -8438,7 +8415,7 @@ poolGrowUntil(STRING_POOL *pool, size_t needed) {
}
}
-static int FASTCALL
+static int
nextScaffoldPart(XML_Parser parser) {
DTD *const dtd = parser->m_dtd; /* save one level of indirection */
CONTENT_SCAFFOLD *me;
diff --git a/lib/xmlrole.c b/lib/xmlrole.c
index 8f6bedda7165..dbf4a2d1b8f7 100644
--- a/lib/xmlrole.c
+++ b/lib/xmlrole.c
@@ -12,7 +12,7 @@
Copyright (c) 2002-2006 Karl Waclawek <karl@waclawek.net>
Copyright (c) 2002-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2005-2009 Steven Solie <steven@solie.ca>
- Copyright (c) 2016-2023 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 David Loffredo <loffredo@steptools.com>
Copyright (c) 2021 Donghee Na <donghee.na@python.org>
@@ -121,9 +121,8 @@ static const char KW_SYSTEM[]
# define setTopLevel(state) ((state)->handler = internalSubset)
#endif /* not XML_DTD */
-typedef int PTRCALL PROLOG_HANDLER(PROLOG_STATE *state, int tok,
- const char *ptr, const char *end,
- const ENCODING *enc);
+typedef int PROLOG_HANDLER(PROLOG_STATE *state, int tok, const char *ptr,
+ const char *end, const ENCODING *enc);
static PROLOG_HANDLER prolog0, prolog1, prolog2, doctype0, doctype1, doctype2,
doctype3, doctype4, doctype5, internalSubset, entity0, entity1, entity2,
@@ -137,9 +136,9 @@ static PROLOG_HANDLER prolog0, prolog1, prolog2, doctype0, doctype1, doctype2,
#endif /* XML_DTD */
declClose, error;
-static int FASTCALL common(PROLOG_STATE *state, int tok);
+static int common(PROLOG_STATE *state, int tok);
-static int PTRCALL
+static int
prolog0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -170,7 +169,7 @@ prolog0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
prolog1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -202,7 +201,7 @@ prolog1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
prolog2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -222,7 +221,7 @@ prolog2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
doctype0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -239,7 +238,7 @@ doctype0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
doctype1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -265,7 +264,7 @@ doctype1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
doctype2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -281,7 +280,7 @@ doctype2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
doctype3(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -297,7 +296,7 @@ doctype3(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
doctype4(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -316,7 +315,7 @@ doctype4(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
doctype5(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -332,7 +331,7 @@ doctype5(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
internalSubset(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -377,7 +376,7 @@ internalSubset(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
#ifdef XML_DTD
-static int PTRCALL
+static int
externalSubset0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
state->handler = externalSubset1;
@@ -386,7 +385,7 @@ externalSubset0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return externalSubset1(state, tok, ptr, end, enc);
}
-static int PTRCALL
+static int
externalSubset1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -414,7 +413,7 @@ externalSubset1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
#endif /* XML_DTD */
-static int PTRCALL
+static int
entity0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -433,7 +432,7 @@ entity0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
entity1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -449,7 +448,7 @@ entity1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
entity2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -473,7 +472,7 @@ entity2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
entity3(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -489,7 +488,7 @@ entity3(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
entity4(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -505,7 +504,7 @@ entity4(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
entity5(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -524,7 +523,7 @@ entity5(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
entity6(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -541,7 +540,7 @@ entity6(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
entity7(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -565,7 +564,7 @@ entity7(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
entity8(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -581,7 +580,7 @@ entity8(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
entity9(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -597,7 +596,7 @@ entity9(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
entity10(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -613,7 +612,7 @@ entity10(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
notation0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -629,7 +628,7 @@ notation0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
notation1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -649,7 +648,7 @@ notation1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
notation2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -665,7 +664,7 @@ notation2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
notation3(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -682,7 +681,7 @@ notation3(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
notation4(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -702,7 +701,7 @@ notation4(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
attlist0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -719,7 +718,7 @@ attlist0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
attlist1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -739,7 +738,7 @@ attlist1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
attlist2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -769,7 +768,7 @@ attlist2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
attlist3(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -787,7 +786,7 @@ attlist3(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
attlist4(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -806,7 +805,7 @@ attlist4(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
attlist5(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -822,7 +821,7 @@ attlist5(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
attlist6(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -838,7 +837,7 @@ attlist6(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
attlist7(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -858,7 +857,7 @@ attlist7(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
}
/* default value */
-static int PTRCALL
+static int
attlist8(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -888,7 +887,7 @@ attlist8(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
attlist9(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -904,7 +903,7 @@ attlist9(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
element0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -921,7 +920,7 @@ element0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
element1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -947,7 +946,7 @@ element1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
element2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -981,7 +980,7 @@ element2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
element3(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -1005,7 +1004,7 @@ element3(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
element4(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -1022,7 +1021,7 @@ element4(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
element5(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -1042,7 +1041,7 @@ element5(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
element6(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -1071,7 +1070,7 @@ element6(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
element7(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -1120,7 +1119,7 @@ element7(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
#ifdef XML_DTD
-static int PTRCALL
+static int
condSect0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -1140,7 +1139,7 @@ condSect0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
condSect1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -1157,7 +1156,7 @@ condSect1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
return common(state, tok);
}
-static int PTRCALL
+static int
condSect2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -1175,7 +1174,7 @@ condSect2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
#endif /* XML_DTD */
-static int PTRCALL
+static int
declClose(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -1211,7 +1210,7 @@ declClose(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
*
* LCOV_EXCL_START
*/
-static int PTRCALL
+static int
error(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(state);
@@ -1223,7 +1222,7 @@ error(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
}
/* LCOV_EXCL_STOP */
-static int FASTCALL
+static int
common(PROLOG_STATE *state, int tok) {
#ifdef XML_DTD
if (! state->documentEntity && tok == XML_TOK_PARAM_ENTITY_REF)
diff --git a/lib/xmlrole.h b/lib/xmlrole.h
index 903a6951f434..f4aba4079f5c 100644
--- a/lib/xmlrole.h
+++ b/lib/xmlrole.h
@@ -10,7 +10,7 @@
Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
Copyright (c) 2002 Karl Waclawek <karl@waclawek.net>
Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
- Copyright (c) 2017-2025 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
@@ -40,10 +40,6 @@
# include "xmltok.h"
-# ifdef __cplusplus
-extern "C" {
-# endif
-
enum {
XML_ROLE_ERROR = -1,
XML_ROLE_NONE = 0,
@@ -112,8 +108,8 @@ enum {
};
typedef struct prolog_state {
- int(PTRCALL *handler)(struct prolog_state *state, int tok, const char *ptr,
- const char *end, const ENCODING *enc);
+ int (*handler)(struct prolog_state *state, int tok, const char *ptr,
+ const char *end, const ENCODING *enc);
unsigned level;
int role_none;
# ifdef XML_DTD
@@ -131,8 +127,4 @@ void XmlPrologStateInitExternalEntity(PROLOG_STATE *state);
# define XmlTokenRole(state, tok, ptr, end, enc) \
(((state)->handler)(state, tok, ptr, end, enc))
-# ifdef __cplusplus
-}
-# endif
-
#endif /* not XmlRole_INCLUDED */
diff --git a/lib/xmltok.c b/lib/xmltok.c
index d66af6045f07..a3bf5e0e95b0 100644
--- a/lib/xmltok.c
+++ b/lib/xmltok.c
@@ -27,6 +27,7 @@
Copyright (c) 2025 Alfonso Gregory <gfunni234@gmail.com>
Copyright (c) 2026 Nick Begg <nick@stunttruck.net>
Copyright (c) 2026 Kartik Kenchi <netliomax25@gmail.com>
+ Copyright (c) 2026 Afonso Januário <afonso-januario@hotmail.com>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@@ -136,20 +137,20 @@
: ((p)[1] & 0x80) == 0 \
|| ((*p) == 0xF4 ? (p)[1] > 0x8F : ((p)[1] & 0xC0) == 0xC0)))
-static int PTRFASTCALL
+static int
isNever(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
UNUSED_P(p);
return 0;
}
-static int PTRFASTCALL
+static int
utf8_isName2(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return UTF8_GET_NAMING2(namePages, (const unsigned char *)p);
}
-static int PTRFASTCALL
+static int
utf8_isName3(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return UTF8_GET_NAMING3(namePages, (const unsigned char *)p);
@@ -157,13 +158,13 @@ utf8_isName3(const ENCODING *enc, const char *p) {
#define utf8_isName4 isNever
-static int PTRFASTCALL
+static int
utf8_isNmstrt2(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p);
}
-static int PTRFASTCALL
+static int
utf8_isNmstrt3(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p);
@@ -171,19 +172,19 @@ utf8_isNmstrt3(const ENCODING *enc, const char *p) {
#define utf8_isNmstrt4 isNever
-static int PTRFASTCALL
+static int
utf8_isInvalid2(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return UTF8_INVALID2((const unsigned char *)p);
}
-static int PTRFASTCALL
+static int
utf8_isInvalid3(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return UTF8_INVALID3((const unsigned char *)p);
}
-static int PTRFASTCALL
+static int
utf8_isInvalid4(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return UTF8_INVALID4((const unsigned char *)p);
@@ -193,21 +194,21 @@ struct normal_encoding {
ENCODING enc;
unsigned char type[256];
#ifdef XML_MIN_SIZE
- int(PTRFASTCALL *byteType)(const ENCODING *, const char *);
- int(PTRFASTCALL *isNameMin)(const ENCODING *, const char *);
- int(PTRFASTCALL *isNmstrtMin)(const ENCODING *, const char *);
- int(PTRFASTCALL *byteToAscii)(const ENCODING *, const char *);
- int(PTRCALL *charMatches)(const ENCODING *, const char *, int);
+ 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(PTRFASTCALL *isName2)(const ENCODING *, const char *);
- int(PTRFASTCALL *isName3)(const ENCODING *, const char *);
- int(PTRFASTCALL *isName4)(const ENCODING *, const char *);
- int(PTRFASTCALL *isNmstrt2)(const ENCODING *, const char *);
- int(PTRFASTCALL *isNmstrt3)(const ENCODING *, const char *);
- int(PTRFASTCALL *isNmstrt4)(const ENCODING *, const char *);
- int(PTRFASTCALL *isInvalid2)(const ENCODING *, const char *);
- int(PTRFASTCALL *isInvalid3)(const ENCODING *, const char *);
- int(PTRFASTCALL *isInvalid4)(const ENCODING *, const char *);
+ int (*isName2)(const ENCODING *, const char *);
+ int (*isName3)(const ENCODING *, const char *);
+ int (*isName4)(const ENCODING *, const char *);
+ int (*isNmstrt2)(const ENCODING *, const char *);
+ int (*isNmstrt3)(const ENCODING *, const char *);
+ int (*isNmstrt4)(const ENCODING *, const char *);
+ int (*isInvalid2)(const ENCODING *, const char *);
+ int (*isInvalid3)(const ENCODING *, const char *);
+ int (*isInvalid4)(const ENCODING *, const char *);
};
#define AS_NORMAL_ENCODING(enc) ((const struct normal_encoding *)(enc))
@@ -232,7 +233,20 @@ struct normal_encoding {
/* isNmstrt2 */ NULL, /* isNmstrt3 */ NULL, /* isNmstrt4 */ NULL, \
/* isInvalid2 */ NULL, /* isInvalid3 */ NULL, /* isInvalid4 */ NULL
-static int FASTCALL checkCharRefNumber(int result);
+/* 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
+
+static int checkCharRefNumber(int result);
#include "xmltok_impl.h"
#include "ascii.h"
@@ -253,7 +267,7 @@ static int FASTCALL checkCharRefNumber(int result);
(((const struct normal_encoding *)(enc))->type[(unsigned char)*(p)])
#ifdef XML_MIN_SIZE
-static int PTRFASTCALL
+static int
sb_byteType(const ENCODING *enc, const char *p) {
return SB_BYTE_TYPE(enc, p);
}
@@ -264,7 +278,7 @@ sb_byteType(const ENCODING *enc, const char *p) {
#ifdef XML_MIN_SIZE
# define BYTE_TO_ASCII(enc, p) (AS_NORMAL_ENCODING(enc)->byteToAscii(enc, p))
-static int PTRFASTCALL
+static int
sb_byteToAscii(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return *p;
@@ -297,7 +311,7 @@ sb_byteToAscii(const ENCODING *enc, const char *p) {
#ifdef XML_MIN_SIZE
# define CHAR_MATCHES(enc, p, c) \
(AS_NORMAL_ENCODING(enc)->charMatches(enc, p, c))
-static int PTRCALL
+static int
sb_charMatches(const ENCODING *enc, const char *p, int c) {
UNUSED_P(enc);
return *p == c;
@@ -368,7 +382,7 @@ _INTERNAL_trim_to_complete_utf8_characters(const char *from,
*fromLimRef = fromLim;
}
-static enum XML_Convert_Result PTRCALL
+static enum XML_Convert_Result
utf8_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
char **toP, const char *toLim) {
bool input_incomplete = false;
@@ -407,7 +421,7 @@ utf8_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
return XML_CONVERT_COMPLETED;
}
-static enum XML_Convert_Result PTRCALL
+static enum XML_Convert_Result
utf8_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim,
unsigned short **toP, const unsigned short *toLim) {
enum XML_Convert_Result res = XML_CONVERT_COMPLETED;
@@ -505,7 +519,7 @@ static const struct normal_encoding internal_utf8_encoding
},
STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)};
-static enum XML_Convert_Result PTRCALL
+static enum XML_Convert_Result
latin1_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
char **toP, const char *toLim) {
UNUSED_P(enc);
@@ -528,7 +542,7 @@ latin1_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
}
}
-static enum XML_Convert_Result PTRCALL
+static enum XML_Convert_Result
latin1_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim,
unsigned short **toP, const unsigned short *toLim) {
UNUSED_P(enc);
@@ -563,7 +577,7 @@ static const struct normal_encoding latin1_encoding
},
STANDARD_VTABLE(sb_) NULL_VTABLE};
-static enum XML_Convert_Result PTRCALL
+static enum XML_Convert_Result
ascii_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
char **toP, const char *toLim) {
UNUSED_P(enc);
@@ -598,7 +612,7 @@ static const struct normal_encoding ascii_encoding
},
STANDARD_VTABLE(sb_) NULL_VTABLE};
-static int PTRFASTCALL
+static int
unicode_byte_type(char hi, char lo) {
switch ((unsigned char)hi) {
/* 0xD800-0xDBFF first 16-bit code unit or high surrogate (W1) */
@@ -625,7 +639,7 @@ unicode_byte_type(char hi, char lo) {
}
#define DEFINE_UTF16_TO_UTF8(E) \
- static enum XML_Convert_Result PTRCALL E##toUtf8( \
+ static enum XML_Convert_Result E##toUtf8( \
const ENCODING *enc, const char **fromP, const char *fromLim, \
char **toP, const char *toLim) { \
const char *from = *fromP; \
@@ -702,7 +716,7 @@ unicode_byte_type(char hi, char lo) {
}
#define DEFINE_UTF16_TO_UTF16(E) \
- static enum XML_Convert_Result PTRCALL E##toUtf16( \
+ static enum XML_Convert_Result E##toUtf16( \
const ENCODING *enc, const char **fromP, const char *fromLim, \
unsigned short **toP, const unsigned short *toLim) { \
enum XML_Convert_Result res = XML_CONVERT_COMPLETED; \
@@ -749,38 +763,49 @@ DEFINE_UTF16_TO_UTF16(big2_)
UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0])
#define LITTLE2_IS_NMSTRT_CHAR_MINBPC(p) \
UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0])
+/* A 4-byte UTF-16 character is a surrogate pair; byteType only reports BT_LEAD4
+ for a high surrogate, so the pair is invalid unless the second unit is a low
+ surrogate (U+DC00..U+DFFF, i.e. high byte 0xDC..0xDF). */
+#define LITTLE2_IS_INVALID_CHAR(p, n) \
+ ((n) == 4 && ((unsigned char)(p)[3] & 0xFC) != 0xDC)
#ifdef XML_MIN_SIZE
-static int PTRFASTCALL
+static int
little2_byteType(const ENCODING *enc, const char *p) {
return LITTLE2_BYTE_TYPE(enc, p);
}
-static int PTRFASTCALL
+static int
little2_byteToAscii(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return LITTLE2_BYTE_TO_ASCII(p);
}
-static int PTRCALL
+static int
little2_charMatches(const ENCODING *enc, const char *p, int c) {
UNUSED_P(enc);
return LITTLE2_CHAR_MATCHES(p, c);
}
-static int PTRFASTCALL
+static int
little2_isNameMin(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return LITTLE2_IS_NAME_CHAR_MINBPC(p);
}
-static int PTRFASTCALL
+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
@@ -797,6 +822,7 @@ little2_isNmstrtMin(const ENCODING *enc, const char *p) {
# 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"
@@ -828,7 +854,7 @@ static const struct normal_encoding little2_encoding_ns
# include "asciitab.h"
# include "latin1tab.h"
},
- STANDARD_VTABLE(little2_) NULL_VTABLE};
+ STANDARD_VTABLE(little2_) UTF16_NULL_VTABLE(little2_)};
#endif
@@ -846,7 +872,7 @@ static const struct normal_encoding little2_encoding
#undef BT_COLON
#include "latin1tab.h"
},
- STANDARD_VTABLE(little2_) NULL_VTABLE};
+ STANDARD_VTABLE(little2_) UTF16_NULL_VTABLE(little2_)};
#if BYTEORDER != 4321
@@ -858,7 +884,7 @@ static const struct normal_encoding internal_little2_encoding_ns
# include "iasciitab.h"
# include "latin1tab.h"
},
- STANDARD_VTABLE(little2_) NULL_VTABLE};
+ STANDARD_VTABLE(little2_) UTF16_NULL_VTABLE(little2_)};
# endif
@@ -870,7 +896,7 @@ static const struct normal_encoding internal_little2_encoding
# undef BT_COLON
# include "latin1tab.h"
},
- STANDARD_VTABLE(little2_) NULL_VTABLE};
+ STANDARD_VTABLE(little2_) UTF16_NULL_VTABLE(little2_)};
#endif
@@ -882,38 +908,49 @@ static const struct normal_encoding internal_little2_encoding
UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1])
#define BIG2_IS_NMSTRT_CHAR_MINBPC(p) \
UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1])
+/* A 4-byte UTF-16 character is a surrogate pair; byteType only reports BT_LEAD4
+ for a high surrogate, so the pair is invalid unless the second unit is a low
+ surrogate (U+DC00..U+DFFF, i.e. high byte 0xDC..0xDF). */
+#define BIG2_IS_INVALID_CHAR(p, n) \
+ ((n) == 4 && ((unsigned char)(p)[2] & 0xFC) != 0xDC)
#ifdef XML_MIN_SIZE
-static int PTRFASTCALL
+static int
big2_byteType(const ENCODING *enc, const char *p) {
return BIG2_BYTE_TYPE(enc, p);
}
-static int PTRFASTCALL
+static int
big2_byteToAscii(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return BIG2_BYTE_TO_ASCII(p);
}
-static int PTRCALL
+static int
big2_charMatches(const ENCODING *enc, const char *p, int c) {
UNUSED_P(enc);
return BIG2_CHAR_MATCHES(p, c);
}
-static int PTRFASTCALL
+static int
big2_isNameMin(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return BIG2_IS_NAME_CHAR_MINBPC(p);
}
-static int PTRFASTCALL
+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
@@ -930,6 +967,7 @@ big2_isNmstrtMin(const ENCODING *enc, const char *p) {
# 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"
@@ -961,7 +999,7 @@ static const struct normal_encoding big2_encoding_ns
# include "asciitab.h"
# include "latin1tab.h"
},
- STANDARD_VTABLE(big2_) NULL_VTABLE};
+ STANDARD_VTABLE(big2_) UTF16_NULL_VTABLE(big2_)};
#endif
@@ -979,7 +1017,7 @@ static const struct normal_encoding big2_encoding
#undef BT_COLON
#include "latin1tab.h"
},
- STANDARD_VTABLE(big2_) NULL_VTABLE};
+ STANDARD_VTABLE(big2_) UTF16_NULL_VTABLE(big2_)};
#if BYTEORDER != 1234
@@ -991,7 +1029,7 @@ static const struct normal_encoding internal_big2_encoding_ns
# include "iasciitab.h"
# include "latin1tab.h"
},
- STANDARD_VTABLE(big2_) NULL_VTABLE};
+ STANDARD_VTABLE(big2_) UTF16_NULL_VTABLE(big2_)};
# endif
@@ -1003,13 +1041,13 @@ static const struct normal_encoding internal_big2_encoding
# undef BT_COLON
# include "latin1tab.h"
},
- STANDARD_VTABLE(big2_) NULL_VTABLE};
+ STANDARD_VTABLE(big2_) UTF16_NULL_VTABLE(big2_)};
#endif
#undef PREFIX
-static int FASTCALL
+static int
streqci(const char *s1, const char *s2) {
for (;;) {
char c1 = *s1++;
@@ -1030,7 +1068,7 @@ streqci(const char *s1, const char *s2) {
return 1;
}
-static void PTRCALL
+static void
initUpdatePosition(const ENCODING *enc, const char *ptr, const char *end,
POSITION *pos) {
UNUSED_P(enc);
@@ -1048,7 +1086,7 @@ toAscii(const ENCODING *enc, const char *ptr, const char *end) {
return buf[0];
}
-static int FASTCALL
+static int
isSpace(int c) {
switch (c) {
case 0x20:
@@ -1154,6 +1192,34 @@ static const char KW_yes[] = {ASCII_y, ASCII_e, ASCII_s, '\0'};
static const char KW_no[] = {ASCII_n, ASCII_o, '\0'};
+static const char KW_1_dot[] = {ASCII_1, ASCII_PERIOD, '\0'};
+
+/* Checks a version pseudo-attribute value against the VersionNum production.
+ XML 1.0 Fourth Edition only allows the literal "1.0", but the Fifth
+ Edition relaxed this to "1." followed by one or more digits, since Expat
+ only implements 1.0 itself but plans to track the Fifth Edition's laxer
+ grammar here so that "1.1" and similar aren't rejected only to have that
+ rejection reverted later. Returns true for a value matching "1.[0-9]+".
+ val/valEnd bound the value itself; valEnd is the upper bound used when
+ decoding the individual characters between them. */
+static bool
+checkXmlDeclVersionNum(const ENCODING *enc, const char *val,
+ const char *valEnd) {
+ if (valEnd - val < 2 * enc->minBytesPerChar
+ || ! XmlNameMatchesAscii(enc, val, val + 2 * enc->minBytesPerChar,
+ KW_1_dot))
+ return false;
+ val += 2 * enc->minBytesPerChar;
+ if (val == valEnd)
+ return false;
+ for (; val != valEnd; val += enc->minBytesPerChar) {
+ int c = toAscii(enc, val, valEnd);
+ if (c < ASCII_0 || c > ASCII_9)
+ return false;
+ }
+ return true;
+}
+
static int
doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *, const char *,
const char *),
@@ -1188,6 +1254,15 @@ doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *, const char *,
*badPtr = val;
return 0;
}
+ /* Expat implements XML 1.0 only, so any version outside the "1.0"/"1.x"
+ family is rejected. Following the Fifth Edition's VersionNum
+ production (rather than the Fourth Edition's exact "1.0") avoids
+ rejecting "1.1" now only to have to revert that once Expat tracks
+ the newer edition. */
+ if (! checkXmlDeclVersionNum(enc, val, ptr - enc->minBytesPerChar)) {
+ *badPtr = val;
+ return 0;
+ }
if (! parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
*badPtr = ptr;
return 0;
@@ -1242,7 +1317,7 @@ doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *, const char *,
return 1;
}
-static int FASTCALL
+static int
checkCharRefNumber(int result) {
switch (result >> 8) {
case 0xD8:
@@ -1266,7 +1341,7 @@ checkCharRefNumber(int result) {
return result;
}
-int FASTCALL
+int
XmlUtf8Encode(int c, char *buf) {
enum {
/* minN is minimum legal resulting value for N byte sequence */
@@ -1302,7 +1377,7 @@ XmlUtf8Encode(int c, char *buf) {
return 0; /* LCOV_EXCL_LINE: this case too is eliminated before calling */
}
-int FASTCALL
+int
XmlUtf16Encode(int charNum, unsigned short *buf) {
if (charNum < 0)
return 0;
@@ -1334,7 +1409,7 @@ XmlSizeOfUnknownEncoding(void) {
return sizeof(struct unknown_encoding);
}
-static int PTRFASTCALL
+static int
unknown_isName(const ENCODING *enc, const char *p) {
const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
int c = uenc->convert(uenc->userData, p);
@@ -1343,7 +1418,7 @@ unknown_isName(const ENCODING *enc, const char *p) {
return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF);
}
-static int PTRFASTCALL
+static int
unknown_isNmstrt(const ENCODING *enc, const char *p) {
const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
int c = uenc->convert(uenc->userData, p);
@@ -1352,14 +1427,14 @@ unknown_isNmstrt(const ENCODING *enc, const char *p) {
return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF);
}
-static int PTRFASTCALL
+static int
unknown_isInvalid(const ENCODING *enc, const char *p) {
const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
int c = uenc->convert(uenc->userData, p);
return (c & ~0xFFFF) || checkCharRefNumber(c) < 0;
}
-static enum XML_Convert_Result PTRCALL
+static enum XML_Convert_Result
unknown_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
char **toP, const char *toLim) {
const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
@@ -1389,7 +1464,7 @@ unknown_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
}
}
-static enum XML_Convert_Result PTRCALL
+static enum XML_Convert_Result
unknown_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim,
unsigned short **toP, const unsigned short *toLim) {
const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
@@ -1513,7 +1588,7 @@ static const char KW_UTF_16LE[]
= {ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1,
ASCII_6, ASCII_L, ASCII_E, '\0'};
-static int FASTCALL
+static int
getEncodingIndex(const char *name) {
static const char *const encodingNames[] = {
KW_ISO_8859_1, KW_US_ASCII, KW_UTF_8, KW_UTF_16, KW_UTF_16BE, KW_UTF_16LE,
diff --git a/lib/xmltok.h b/lib/xmltok.h
index 76be2c7c5ca1..bf641af6d4f7 100644
--- a/lib/xmltok.h
+++ b/lib/xmltok.h
@@ -41,10 +41,6 @@
# include <stdint.h> // uint64_t
-# ifdef __cplusplus
-extern "C" {
-# endif
-
/* The following token may be returned by XmlContentTok */
# define XML_TOK_TRAILING_RSQB \
-5 /* ] or ]] at the end of the scan; might be \
@@ -163,8 +159,8 @@ typedef struct {
struct encoding;
typedef struct encoding ENCODING;
-typedef int(PTRCALL *SCANNER)(const ENCODING *, const char *, const char *,
- const char **);
+typedef int (*SCANNER)(const ENCODING *, const char *, const char *,
+ const char **);
enum XML_Convert_Result {
XML_CONVERT_COMPLETED = 0,
@@ -176,28 +172,27 @@ enum XML_Convert_Result {
struct encoding {
SCANNER scanners[XML_N_STATES];
SCANNER literalScanners[XML_N_LITERAL_TYPES];
- int(PTRCALL *nameMatchesAscii)(const ENCODING *, const char *, const char *,
- const char *);
- int(PTRFASTCALL *nameLength)(const ENCODING *, const char *);
- const char *(PTRFASTCALL *skipS)(const ENCODING *, const char *);
- int(PTRCALL *getAtts)(const ENCODING *enc, const char *ptr, int attsMax,
- ATTRIBUTE *atts);
- int(PTRFASTCALL *charRefNumber)(const ENCODING *enc, const char *ptr);
- int(PTRCALL *predefinedEntityName)(const ENCODING *, const char *,
- const char *);
- void(PTRCALL *updatePosition)(const ENCODING *, const char *ptr,
- const char *end, POSITION *);
- int(PTRCALL *isPublicId)(const ENCODING *enc, const char *ptr,
- const char *end, const char **badPtr);
- enum XML_Convert_Result(PTRCALL *utf8Convert)(const ENCODING *enc,
- const char **fromP,
- const char *fromLim, char **toP,
- const char *toLim);
- enum XML_Convert_Result(PTRCALL *utf16Convert)(const ENCODING *enc,
- const char **fromP,
- const char *fromLim,
- unsigned short **toP,
- const unsigned short *toLim);
+ int (*nameMatchesAscii)(const ENCODING *, const char *, const char *,
+ const char *);
+ int (*nameLength)(const ENCODING *, const char *);
+ const char *(*skipS)(const ENCODING *, const char *);
+ int (*getAtts)(const ENCODING *enc, const char *ptr, int attsMax,
+ ATTRIBUTE *atts);
+ int (*charRefNumber)(const ENCODING *enc, const char *ptr);
+ int (*predefinedEntityName)(const ENCODING *, const char *, const char *);
+ void (*updatePosition)(const ENCODING *, const char *ptr, const char *end,
+ POSITION *);
+ int (*isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **badPtr);
+ enum XML_Convert_Result (*utf8Convert)(const ENCODING *enc,
+ const char **fromP,
+ const char *fromLim, char **toP,
+ const char *toLim);
+ enum XML_Convert_Result (*utf16Convert)(const ENCODING *enc,
+ const char **fromP,
+ const char *fromLim,
+ unsigned short **toP,
+ const unsigned short *toLim);
int minBytesPerChar;
char isUtf8;
char isUtf16;
@@ -297,8 +292,8 @@ int XmlInitEncoding(INIT_ENCODING *p, const ENCODING **encPtr,
const char *name);
const ENCODING *XmlGetUtf8InternalEncoding(void);
const ENCODING *XmlGetUtf16InternalEncoding(void);
-int FASTCALL XmlUtf8Encode(int charNumber, char *buf);
-int FASTCALL XmlUtf16Encode(int charNumber, unsigned short *buf);
+int XmlUtf8Encode(int charNumber, char *buf);
+int XmlUtf16Encode(int charNumber, unsigned short *buf);
int XmlSizeOfUnknownEncoding(void);
typedef int(XMLCALL *CONVERTER)(void *userData, const char *p);
@@ -318,8 +313,5 @@ const ENCODING *XmlGetUtf8InternalEncodingNS(void);
const ENCODING *XmlGetUtf16InternalEncodingNS(void);
ENCODING *XmlInitUnknownEncodingNS(void *mem, const int *table,
CONVERTER convert, void *userData);
-# ifdef __cplusplus
-}
-# endif
#endif /* not XmlTok_INCLUDED */
diff --git a/lib/xmltok_impl.c b/lib/xmltok_impl.c
index 1d8e457d9de5..a71a2fd88c70 100644
--- a/lib/xmltok_impl.c
+++ b/lib/xmltok_impl.c
@@ -10,7 +10,7 @@
Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2002-2016 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>
Copyright (c) 2018 Benjamin Peterson <benjamin@python.org>
Copyright (c) 2018 Anton Maklakov <antmak.pub@gmail.com>
@@ -18,6 +18,7 @@
Copyright (c) 2020 Boris Kolpackov <boris@codesynthesis.com>
Copyright (c) 2022 Martin Ettl <ettl.martin78@googlemail.com>
Copyright (c) 2026 Nick Begg <nick@stunttruck.net>
+ Copyright (c) 2026 Kartik Kenchi <netliomax25@gmail.com>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@@ -44,10 +45,6 @@
#ifdef XML_TOK_IMPL_C
-# ifndef IS_INVALID_CHAR // i.e. for UTF-16 and XML_MIN_SIZE not defined
-# define IS_INVALID_CHAR(enc, ptr, n) (0)
-# endif
-
# define INVALID_LEAD_CASE(n, ptr, nextTokPtr) \
case BT_LEAD##n: \
if (end - ptr < n) \
@@ -144,7 +141,7 @@
/* ptr points to character following "<!-" */
-static int PTRCALL
+static int
PREFIX(scanComment)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
if (HAS_CHAR(enc, ptr, end)) {
@@ -181,7 +178,7 @@ PREFIX(scanComment)(const ENCODING *enc, const char *ptr, const char *end,
/* ptr points to character following "<!" */
-static int PTRCALL
+static int
PREFIX(scanDecl)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
REQUIRE_CHAR(enc, ptr, end);
@@ -230,7 +227,7 @@ PREFIX(scanDecl)(const ENCODING *enc, const char *ptr, const char *end,
return XML_TOK_PARTIAL;
}
-static int PTRCALL
+static int
PREFIX(checkPiTarget)(const ENCODING *enc, const char *ptr, const char *end,
int *tokPtr) {
int upper = 0;
@@ -275,7 +272,7 @@ PREFIX(checkPiTarget)(const ENCODING *enc, const char *ptr, const char *end,
/* ptr points to character following "<?" */
-static int PTRCALL
+static int
PREFIX(scanPi)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
int tok;
@@ -335,7 +332,7 @@ PREFIX(scanPi)(const ENCODING *enc, const char *ptr, const char *end,
return XML_TOK_PARTIAL;
}
-static int PTRCALL
+static int
PREFIX(scanCdataSection)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
static const char CDATA_LSQB[]
@@ -354,7 +351,7 @@ PREFIX(scanCdataSection)(const ENCODING *enc, const char *ptr, const char *end,
return XML_TOK_CDATA_SECT_OPEN;
}
-static int PTRCALL
+static int
PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
if (ptr >= end)
@@ -430,7 +427,7 @@ PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr, const char *end,
/* ptr points to character following "</" */
-static int PTRCALL
+static int
PREFIX(scanEndTag)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
REQUIRE_CHAR(enc, ptr, end);
@@ -481,7 +478,7 @@ PREFIX(scanEndTag)(const ENCODING *enc, const char *ptr, const char *end,
/* ptr points to character following "&#X" */
-static int PTRCALL
+static int
PREFIX(scanHexCharRef)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
if (HAS_CHAR(enc, ptr, end)) {
@@ -512,7 +509,7 @@ PREFIX(scanHexCharRef)(const ENCODING *enc, const char *ptr, const char *end,
/* ptr points to character following "&#" */
-static int PTRCALL
+static int
PREFIX(scanCharRef)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
if (HAS_CHAR(enc, ptr, end)) {
@@ -543,7 +540,7 @@ PREFIX(scanCharRef)(const ENCODING *enc, const char *ptr, const char *end,
/* ptr points to character following "&" */
-static int PTRCALL
+static int
PREFIX(scanRef)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
REQUIRE_CHAR(enc, ptr, end);
@@ -571,7 +568,7 @@ PREFIX(scanRef)(const ENCODING *enc, const char *ptr, const char *end,
/* ptr points to character following first character of attribute name */
-static int PTRCALL
+static int
PREFIX(scanAtts)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
# ifdef XML_NS
@@ -724,7 +721,7 @@ PREFIX(scanAtts)(const ENCODING *enc, const char *ptr, const char *end,
/* ptr points to character following "<" */
-static int PTRCALL
+static int
PREFIX(scanLt)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
# ifdef XML_NS
@@ -822,7 +819,7 @@ PREFIX(scanLt)(const ENCODING *enc, const char *ptr, const char *end,
return XML_TOK_PARTIAL;
}
-static int PTRCALL
+static int
PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
if (ptr >= end)
@@ -922,7 +919,7 @@ PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end,
/* ptr points to character following "%" */
-static int PTRCALL
+static int
PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
REQUIRE_CHAR(enc, ptr, end);
@@ -952,7 +949,7 @@ PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end,
return XML_TOK_PARTIAL;
}
-static int PTRCALL
+static int
PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
REQUIRE_CHAR(enc, ptr, end);
@@ -982,7 +979,7 @@ PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end,
return -XML_TOK_POUND_NAME;
}
-static int PTRCALL
+static int
PREFIX(scanLit)(int open, const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
while (HAS_CHAR(enc, ptr, end)) {
@@ -1016,7 +1013,7 @@ PREFIX(scanLit)(int open, const ENCODING *enc, const char *ptr, const char *end,
return XML_TOK_PARTIAL;
}
-static int PTRCALL
+static int
PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
int tok;
@@ -1260,7 +1257,7 @@ PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end,
return -tok;
}
-static int PTRCALL
+static int
PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
const char *start;
@@ -1329,7 +1326,7 @@ PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *end,
return XML_TOK_DATA_CHARS;
}
-static int PTRCALL
+static int
PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
const char *start;
@@ -1396,7 +1393,7 @@ PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *end,
# ifdef XML_DTD
-static int PTRCALL
+static int
PREFIX(ignoreSectionTok)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
int level = 0;
@@ -1448,7 +1445,7 @@ PREFIX(ignoreSectionTok)(const ENCODING *enc, const char *ptr, const char *end,
# endif /* XML_DTD */
-static int PTRCALL
+static int
PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
const char **badPtr) {
ptr += MINBPC(enc);
@@ -1508,7 +1505,7 @@ PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
first attsMax attributes are stored in atts.
*/
-static int PTRCALL
+static int
PREFIX(getAtts)(const ENCODING *enc, const char *ptr, int attsMax,
ATTRIBUTE *atts) {
enum { other, inName, inValue } state = inName;
@@ -1601,7 +1598,7 @@ PREFIX(getAtts)(const ENCODING *enc, const char *ptr, int attsMax,
/* not reached */
}
-static int PTRFASTCALL
+static int
PREFIX(charRefNumber)(const ENCODING *enc, const char *ptr) {
int result = 0;
/* skip &# */
@@ -1659,7 +1656,7 @@ PREFIX(charRefNumber)(const ENCODING *enc, const char *ptr) {
return checkCharRefNumber(result);
}
-static int PTRCALL
+static int
PREFIX(predefinedEntityName)(const ENCODING *enc, const char *ptr,
const char *end) {
UNUSED_P(enc);
@@ -1713,7 +1710,7 @@ PREFIX(predefinedEntityName)(const ENCODING *enc, const char *ptr,
return 0;
}
-static int PTRCALL
+static int
PREFIX(nameMatchesAscii)(const ENCODING *enc, const char *ptr1,
const char *end1, const char *ptr2) {
UNUSED_P(enc);
@@ -1732,7 +1729,7 @@ PREFIX(nameMatchesAscii)(const ENCODING *enc, const char *ptr1,
return ptr1 == end1;
}
-static int PTRFASTCALL
+static int
PREFIX(nameLength)(const ENCODING *enc, const char *ptr) {
const char *start = ptr;
for (;;) {
@@ -1762,7 +1759,7 @@ PREFIX(nameLength)(const ENCODING *enc, const char *ptr) {
}
}
-static const char *PTRFASTCALL
+static const char *
PREFIX(skipS)(const ENCODING *enc, const char *ptr) {
for (;;) {
switch (BYTE_TYPE(enc, ptr)) {
@@ -1777,7 +1774,7 @@ PREFIX(skipS)(const ENCODING *enc, const char *ptr) {
}
}
-static void PTRCALL
+static void
PREFIX(updatePosition)(const ENCODING *enc, const char *ptr, const char *end,
POSITION *pos) {
while (HAS_CHAR(enc, ptr, end)) {
diff --git a/lib/xmltok_ns.c b/lib/xmltok_ns.c
index 40a02a0308b5..d9f69abb92ef 100644
--- a/lib/xmltok_ns.c
+++ b/lib/xmltok_ns.c
@@ -11,7 +11,7 @@
Copyright (c) 2002 Greg Stein <gstein@users.sourceforge.net>
Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2002-2006 Karl Waclawek <karl@waclawek.net>
- Copyright (c) 2017-2021 Sebastian Pipping <sebastian@pipping.org>
+ Copyright (c) 2017-2026 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2025 Alfonso Gregory <gfunni234@gmail.com>
Licensed under the MIT license:
@@ -64,14 +64,14 @@ static const ENCODING *const NS(encodings)[] = {
&ns(utf8_encoding).enc /* NO_ENC */
};
-static int PTRCALL
+static int
NS(initScanProlog)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_PROLOG_STATE,
ptr, end, nextTokPtr);
}
-static int PTRCALL
+static int
NS(initScanContent)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_CONTENT_STATE,
diff --git a/tests/Makefile.am b/tests/Makefile.am
index eefcfe023501..21d8df2c6676 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -49,6 +49,7 @@ runtests_SOURCES = \
common.c \
dummy.c \
handlers.c \
+ hash_tests.c \
memcheck.c \
minicheck.c \
misc_tests.c \
@@ -69,13 +70,14 @@ EXTRA_DIST = \
common.h \
dummy.h \
handlers.h \
+ hash_tests.h \
+ memcheck.h \
+ minicheck.h \
misc_tests.h \
ns_tests.h \
nsalloc_tests.h \
- structdata.h \
- minicheck.h \
- memcheck.h \
README.md \
+ structdata.h \
udiffer.py \
xmltest.log.expected \
xmltest.sh
diff --git a/tests/Makefile.in b/tests/Makefile.in
index 97b22713663f..f81e113c2216 100644
--- a/tests/Makefile.in
+++ b/tests/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.18.1 from Makefile.am.
+# Makefile.in generated by automake 1.19 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2025 Free Software Foundation, Inc.
+# Copyright (C) 1994-2026 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -149,9 +149,9 @@ CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am_runtests_OBJECTS = acc_tests.$(OBJEXT) alloc_tests.$(OBJEXT) \
basic_tests.$(OBJEXT) chardata.$(OBJEXT) common.$(OBJEXT) \
- dummy.$(OBJEXT) handlers.$(OBJEXT) memcheck.$(OBJEXT) \
- minicheck.$(OBJEXT) misc_tests.$(OBJEXT) ns_tests.$(OBJEXT) \
- nsalloc_tests.$(OBJEXT) runtests.$(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)
runtests_OBJECTS = $(am_runtests_OBJECTS)
runtests_DEPENDENCIES = ../lib/libtestpat.la
@@ -181,10 +181,10 @@ am__depfiles_remade = ./$(DEPDIR)/acc_tests.Po \
./$(DEPDIR)/alloc_tests.Po ./$(DEPDIR)/basic_tests.Po \
./$(DEPDIR)/chardata.Po ./$(DEPDIR)/common.Po \
./$(DEPDIR)/dummy.Po ./$(DEPDIR)/handlers.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)/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
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -594,6 +594,7 @@ am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__rm_f_notfound = @am__rm_f_notfound@
am__tar = @am__tar@
+am__tar_ignore_stderr = @am__tar_ignore_stderr@
am__untar = @am__untar@
am__xargs_n = @am__xargs_n@
bindir = @bindir@
@@ -649,6 +650,7 @@ runtests_SOURCES = \
common.c \
dummy.c \
handlers.c \
+ hash_tests.c \
memcheck.c \
minicheck.c \
misc_tests.c \
@@ -667,13 +669,14 @@ EXTRA_DIST = \
common.h \
dummy.h \
handlers.h \
+ hash_tests.h \
+ memcheck.h \
+ minicheck.h \
misc_tests.h \
ns_tests.h \
nsalloc_tests.h \
- structdata.h \
- minicheck.h \
- memcheck.h \
README.md \
+ structdata.h \
udiffer.py \
xmltest.log.expected \
xmltest.sh
@@ -691,9 +694,9 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu tests/Makefile
+ $(AUTOMAKE) --foreign tests/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
@@ -733,6 +736,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dummy.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/handlers.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash_tests.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memcheck.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minicheck.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc_tests.Po@am__quote@ # am--include-marker
@@ -748,22 +752,25 @@ $(am__depfiles_remade):
am--depfiles: $(am__depfiles_remade)
.c.o:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
@@ -1067,13 +1074,14 @@ distdir: $(BUILT_SOURCES)
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ am__distdir="$(distdir)"; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sed "/\//!d;s|^|$$am__distdir/|;s,/[^/]*$$,," | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
@@ -1172,6 +1180,7 @@ distclean: distclean-recursive
-rm -f ./$(DEPDIR)/common.Po
-rm -f ./$(DEPDIR)/dummy.Po
-rm -f ./$(DEPDIR)/handlers.Po
+ -rm -f ./$(DEPDIR)/hash_tests.Po
-rm -f ./$(DEPDIR)/memcheck.Po
-rm -f ./$(DEPDIR)/minicheck.Po
-rm -f ./$(DEPDIR)/misc_tests.Po
@@ -1231,6 +1240,7 @@ maintainer-clean: maintainer-clean-recursive
-rm -f ./$(DEPDIR)/common.Po
-rm -f ./$(DEPDIR)/dummy.Po
-rm -f ./$(DEPDIR)/handlers.Po
+ -rm -f ./$(DEPDIR)/hash_tests.Po
-rm -f ./$(DEPDIR)/memcheck.Po
-rm -f ./$(DEPDIR)/minicheck.Po
-rm -f ./$(DEPDIR)/misc_tests.Po
diff --git a/tests/acc_tests.h b/tests/acc_tests.h
index 6fc0dcac9d98..49a3cd944232 100644
--- a/tests/acc_tests.h
+++ b/tests/acc_tests.h
@@ -10,7 +10,7 @@
Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
Copyright (c) 2005-2012 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-2022 Rhodri James <rhodri@wildebeest.org.uk>
Copyright (c) 2017 Joe Orton <jorton@redhat.com>
Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
@@ -42,17 +42,9 @@
SPDX-License-Identifier: MIT
*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#ifndef XML_ACC_TESTS_H
-# define XML_ACC_TESTS_H
+#define XML_ACC_TESTS_H
extern void make_accounting_test_case(Suite *s);
#endif /* XML_ACC_TESTS_H */
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/tests/alloc_tests.h b/tests/alloc_tests.h
index 6dcc7b4cf513..97f3f91ee795 100644
--- a/tests/alloc_tests.h
+++ b/tests/alloc_tests.h
@@ -10,7 +10,7 @@
Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
Copyright (c) 2005-2012 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-2022 Rhodri James <rhodri@wildebeest.org.uk>
Copyright (c) 2017 Joe Orton <jorton@redhat.com>
Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
@@ -42,17 +42,9 @@
SPDX-License-Identifier: MIT
*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#ifndef XML_ALLOC_TESTS_H
-# define XML_ALLOC_TESTS_H
+#define XML_ALLOC_TESTS_H
extern void make_alloc_test_case(Suite *s);
#endif /* XML_ALLOC_TESTS_H */
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/tests/basic_tests.c b/tests/basic_tests.c
index e6829516ca79..8f4f0902d5c7 100644
--- a/tests/basic_tests.c
+++ b/tests/basic_tests.c
@@ -24,6 +24,8 @@
Copyright (c) 2026 Matthew Fernandez <matthew.fernandez@gmail.com>
Copyright (c) 2026 Kartik Kenchi <netliomax25@gmail.com>
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>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@@ -214,7 +216,7 @@ START_TEST(test_hash_collision) {
"<d8>This triggers the table growth and collides with b2</d8>\n"
"</doc>\n";
- XML_SetHashSalt(g_parser, COLLIDING_HASH_SALT);
+ xmlSetHashSalt(g_parser, COLLIDING_HASH_SALT);
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
== XML_STATUS_ERROR)
xml_failure(g_parser);
@@ -998,6 +1000,50 @@ START_TEST(test_xmldecl_empty_version) {
}
END_TEST
+/* Regression test for GH #967: Expat only implements XML 1.0 Fourth
+ Edition, so a declared version outside the "1.x" family must be
+ rejected rather than silently accepted. A version matching the Fifth
+ Edition's VersionNum production ("1." followed by one or more digits)
+ is accepted even though Expat itself only implements 1.0 Fourth
+ Edition, per GH #967's review thread: rejecting "1.1" now would just
+ have to be reverted once Expat tracks the Fifth Edition, so it's let
+ through rather than blocked twice. */
+START_TEST(test_xmldecl_wrong_version_number) {
+ const char *const badVersions[] = {"2.3", "0.9", "10", "1.", "1", " 1.0 "};
+
+ for (size_t i = 0; i < sizeof(badVersions) / sizeof(badVersions[0]); i++) {
+ char doc[64];
+ snprintf(doc, sizeof(doc), "<?xml version='%s'?>\n<doc/>", badVersions[i]);
+ set_subtest("version='%s'", badVersions[i]);
+
+ XML_Parser parser = XML_ParserCreate(NULL);
+ assert_true(_XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc), XML_TRUE)
+ == XML_STATUS_ERROR);
+ assert_true(XML_GetErrorCode(parser) == XML_ERROR_XML_DECL);
+ XML_ParserFree(parser);
+ }
+}
+END_TEST
+
+/* GH #967's review pointed out that XML 1.0 Fifth Edition relaxed
+ VersionNum to "1." followed by one or more digits, so versions like
+ "1.1" and "1.123" should parse rather than being rejected. */
+START_TEST(test_xmldecl_accepts_1_x_version) {
+ const char *const goodVersions[] = {"1.1", "1.123"};
+
+ for (size_t i = 0; i < sizeof(goodVersions) / sizeof(goodVersions[0]); i++) {
+ char doc[64];
+ snprintf(doc, sizeof(doc), "<?xml version='%s'?>\n<doc/>", goodVersions[i]);
+ set_subtest("version='%s'", goodVersions[i]);
+
+ XML_Parser parser = XML_ParserCreate(NULL);
+ assert_true(_XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc), XML_TRUE)
+ == XML_STATUS_OK);
+ XML_ParserFree(parser);
+ }
+}
+END_TEST
+
/* Regression test for SF bug #584832. */
START_TEST(test_unknown_encoding_internal_entity) {
const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
@@ -1846,6 +1892,301 @@ START_TEST(test_utf16_bad_surrogate_pair) {
}
END_TEST
+// Helper that creates a UTF-16LE copy of UTF-16BE literal input and vice versa
+static char *
+utf16_dup_flipped(const char *text, size_t lenBytes) {
+ assert_true(lenBytes < SIZE_MAX);
+ assert_true(lenBytes % 2 == 0);
+ char *const buffer = malloc(lenBytes + 1);
+ assert_true(buffer != NULL);
+
+ for (size_t i = 0; i < lenBytes; i++) {
+ // This maps 0 -> 1, 1 -> 0, 2 -> 3, 3 -> 2, 4 -> 5, ..
+ size_t j = i + ((i % 2 == 0) ? +1 : -1);
+ assert_true(j < lenBytes);
+ buffer[j] = text[i];
+ }
+
+ buffer[lenBytes] = '\0';
+
+ return buffer;
+}
+
+/* Tests that invalid combinations of surrogates are detected when decoding
+ UTF-16, both little-endian and big-endian.
+ Previously, a high surrogate not followed by a low surrogate slipped
+ through. Without validation the high would consume the next
+ code unit as a fake low, hiding e.g. a following '<' from the
+ tokenizer. */
+START_TEST(test_utf16_surrogate_pairs) {
+ struct TestCase {
+ const char *idea;
+ const char *content;
+ bool expectedSuccess;
+ };
+
+ struct TestCase testCases[] = {
+ // Group {smallest high - 1}{*}
+ {"{smallest high - 1}{smallest high - 1}",
+ "\0<\0a\0>"
+ "\xD7\xFF"
+ "\xD7\xFF"
+ "\0<\0/\0a\0>",
+ true},
+ {"{smallest high - 1}{smallest high}",
+ "\0<\0a\0>"
+ "\xD7\xFF"
+ "\xD8\x00"
+ "\0<\0/\0a\0>",
+ false},
+ {"{smallest high - 1}{largest high}",
+ "\0<\0a\0>"
+ "\xD7\xFF"
+ "\xDB\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{smallest high - 1}{smallest low}",
+ "\0<\0a\0>"
+ "\xD7\xFF"
+ "\xDC\x00"
+ "\0<\0/\0a\0>",
+ false},
+ {"{smallest high - 1}{largest low}",
+ "\0<\0a\0>"
+ "\xD7\xFF"
+ "\xDF\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{smallest high - 1}{largest low + 1}",
+ "\0<\0a\0>"
+ "\xD7\xFF"
+ "\xE0\x00"
+ "\0<\0/\0a\0>",
+ true},
+ // Group {smallest high}{*}
+ {"{smallest high}{smallest high - 1}",
+ "\0<\0a\0>"
+ "\xD8\x00"
+ "\xD7\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{smallest high}{smallest high}",
+ "\0<\0a\0>"
+ "\xD8\x00"
+ "\xD8\x00"
+ "\0<\0/\0a\0>",
+ false},
+ {"{smallest high}{largest high}",
+ "\0<\0a\0>"
+ "\xD8\x00"
+ "\xDB\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{smallest high}{smallest low}",
+ "\0<\0a\0>"
+ "\xD8\x00"
+ "\xDC\x00"
+ "\0<\0/\0a\0>",
+ true},
+ {"{smallest high}{largest low}",
+ "\0<\0a\0>"
+ "\xD8\x00"
+ "\xDF\xFF"
+ "\0<\0/\0a\0>",
+ true},
+ {"{smallest high}{largest low + 1}",
+ "\0<\0a\0>"
+ "\xD8\x00"
+ "\xE0\x00"
+ "\0<\0/\0a\0>",
+ false},
+ // Group {largest high}{*}
+ {"{largest high}{smallest high - 1}",
+ "\0<\0a\0>"
+ "\xDB\xFF"
+ "\xD7\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{largest high}{smallest high}",
+ "\0<\0a\0>"
+ "\xDB\xFF"
+ "\xD8\x00"
+ "\0<\0/\0a\0>",
+ false},
+ {"{largest high}{largest high}",
+ "\0<\0a\0>"
+ "\xDB\xFF"
+ "\xDB\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{largest high}{smallest low}",
+ "\0<\0a\0>"
+ "\xDB\xFF"
+ "\xDC\x00"
+ "\0<\0/\0a\0>",
+ true},
+ {"{largest high}{largest low}",
+ "\0<\0a\0>"
+ "\xDB\xFF"
+ "\xDF\xFF"
+ "\0<\0/\0a\0>",
+ true},
+ {"{largest high}{largest low + 1}",
+ "\0<\0a\0>"
+ "\xDB\xFF"
+ "\xE0\x00"
+ "\0<\0/\0a\0>",
+ false},
+ // Group {smallest low}{*}
+ {"{smallest low}{smallest high - 1}",
+ "\0<\0a\0>"
+ "\xDC\x00"
+ "\xD7\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{smallest low}{smallest high}",
+ "\0<\0a\0>"
+ "\xDC\x00"
+ "\xD8\x00"
+ "\0<\0/\0a\0>",
+ false},
+ {"{smallest low}{largest high}",
+ "\0<\0a\0>"
+ "\xDC\x00"
+ "\xDB\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{smallest low}{smallest low}",
+ "\0<\0a\0>"
+ "\xDC\x00"
+ "\xDC\x00"
+ "\0<\0/\0a\0>",
+ false},
+ {"{smallest low}{largest low}",
+ "\0<\0a\0>"
+ "\xDC\x00"
+ "\xDF\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{smallest low}{largest low + 1}",
+ "\0<\0a\0>"
+ "\xDC\x00"
+ "\xE0\x00"
+ "\0<\0/\0a\0>",
+ false},
+ // Group {largest low}{*}
+ {"{largest low}{smallest high - 1}",
+ "\0<\0a\0>"
+ "\xDF\xFF"
+ "\xD7\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{largest low}{smallest high}",
+ "\0<\0a\0>"
+ "\xDF\xFF"
+ "\xD8\x00"
+ "\0<\0/\0a\0>",
+ false},
+ {"{largest low}{largest high}",
+ "\0<\0a\0>"
+ "\xDF\xFF"
+ "\xDB\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{largest low}{smallest low}",
+ "\0<\0a\0>"
+ "\xDF\xFF"
+ "\xDC\x00"
+ "\0<\0/\0a\0>",
+ false},
+ {"{largest low}{largest low}",
+ "\0<\0a\0>"
+ "\xDF\xFF"
+ "\xDF\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{largest low}{largest low + 1}",
+ "\0<\0a\0>"
+ "\xDF\xFF"
+ "\xE0\x00"
+ "\0<\0/\0a\0>",
+ false},
+ // Group {largest low + 1}{*}
+ {"{largest low + 1}{smallest high - 1}",
+ "\0<\0a\0>"
+ "\xE0\x00"
+ "\xD7\xFF"
+ "\0<\0/\0a\0>",
+ true},
+ {"{largest low + 1}{smallest high}",
+ "\0<\0a\0>"
+ "\xE0\x00"
+ "\xD8\x00"
+ "\0<\0/\0a\0>",
+ false},
+ {"{largest low + 1}{largest high}",
+ "\0<\0a\0>"
+ "\xE0\x00"
+ "\xDB\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{largest low + 1}{smallest low}",
+ "\0<\0a\0>"
+ "\xE0\x00"
+ "\xDC\x00"
+ "\0<\0/\0a\0>",
+ false},
+ {"{largest low + 1}{largest low}",
+ "\0<\0a\0>"
+ "\xE0\x00"
+ "\xDF\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{largest low + 1}{largest low + 1}",
+ "\0<\0a\0>"
+ "\xE0\x00"
+ "\xE0\x00"
+ "\0<\0/\0a\0>",
+ true},
+ };
+
+ for (size_t i = 0; i < sizeof(testCases) / sizeof(testCases[0]); i++) {
+ set_subtest("%s", testCases[i].idea);
+
+ const int lenBytes = /*<a>*/ 6 + /*first*/ 2 + /*second*/ 2 + /*</a>*/ 8;
+ const bool expectedSuccess = testCases[i].expectedSuccess;
+ const enum XML_Status expectedStatus
+ = (expectedSuccess ? XML_STATUS_OK : XML_STATUS_ERROR);
+
+ const char *const bigEndian = testCases[i].content;
+ char *const littleEndian = utf16_dup_flipped(bigEndian, lenBytes);
+ assert_true(littleEndian != NULL);
+ const char *endianCases[] = {bigEndian, littleEndian};
+
+ for (size_t j = 0; j < sizeof(endianCases) / sizeof(endianCases[0]); j++) {
+ const char *text = endianCases[j];
+
+ assert_true(text[lenBytes] == '\0'); // self-test
+ assert_true((text[0] == '\0')
+ != (text[lenBytes - 1] == '\0')); // self-test
+
+ XML_Parser parser = XML_ParserCreate(NULL);
+ assert_true(parser != NULL);
+
+ assert_true(_XML_Parse_SINGLE_BYTES(parser, text, lenBytes, XML_TRUE)
+ == expectedStatus);
+ if (! expectedSuccess) {
+ assert_true(XML_GetErrorCode(parser) == XML_ERROR_INVALID_TOKEN);
+ }
+
+ XML_ParserFree(parser);
+ }
+
+ free(littleEndian);
+ }
+}
+END_TEST
+
START_TEST(test_bad_cdata) {
struct CaseData {
const char *text;
@@ -2358,7 +2699,7 @@ START_TEST(test_set_foreign_dtd) {
ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
/* Check hash salt is passed through too */
- XML_SetHashSalt(g_parser, 0x12345678);
+ xmlSetHashSalt(g_parser, 0x12345678);
XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
XML_SetUserData(g_parser, &test_data);
XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
@@ -2377,7 +2718,7 @@ START_TEST(test_set_foreign_dtd) {
!= XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
fail("Failed to reject late foreign DTD setting");
/* Ditto for the hash salt */
- if (XML_SetHashSalt(g_parser, 0x23456789))
+ if (xmlSetHashSalt(g_parser, 0x23456789))
fail("Failed to reject late hash salt change");
/* Now finish the parse */
@@ -2428,7 +2769,7 @@ START_TEST(test_foreign_dtd_with_doctype) {
ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
/* Check hash salt is passed through too */
- XML_SetHashSalt(g_parser, 0x12345678);
+ xmlSetHashSalt(g_parser, 0x12345678);
XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
XML_SetUserData(g_parser, &test_data);
XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
@@ -2447,7 +2788,7 @@ START_TEST(test_foreign_dtd_with_doctype) {
!= XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
fail("Failed to reject late foreign DTD setting");
/* Ditto for the hash salt */
- if (XML_SetHashSalt(g_parser, 0x23456789))
+ if (xmlSetHashSalt(g_parser, 0x23456789))
fail("Failed to reject late hash salt change");
/* Now finish the parse */
@@ -6756,6 +7097,8 @@ make_basic_test_case(Suite *s) {
tcase_add_test(tc_basic, test_xmldecl_missing_attr);
tcase_add_test(tc_basic, test_xmldecl_missing_value);
tcase_add_test(tc_basic, test_xmldecl_empty_version);
+ tcase_add_test(tc_basic, test_xmldecl_wrong_version_number);
+ tcase_add_test(tc_basic, test_xmldecl_accepts_1_x_version);
tcase_add_test__if_xml_ge(tc_basic, test_unknown_encoding_internal_entity);
tcase_add_test(tc_basic, test_unrecognised_encoding_internal_entity);
tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_encoding);
@@ -6789,6 +7132,7 @@ make_basic_test_case(Suite *s) {
tcase_add_test(tc_basic, test_long_cdata_utf16);
tcase_add_test(tc_basic, test_multichar_cdata_utf16);
tcase_add_test(tc_basic, test_utf16_bad_surrogate_pair);
+ tcase_add_test(tc_basic, test_utf16_surrogate_pairs);
tcase_add_test(tc_basic, test_bad_cdata);
tcase_add_test(tc_basic, test_bad_cdata_utf16);
tcase_add_test(tc_basic, test_stop_parser_between_cdata_calls);
diff --git a/tests/basic_tests.h b/tests/basic_tests.h
index e8a8488773ed..c4b9c6039849 100644
--- a/tests/basic_tests.h
+++ b/tests/basic_tests.h
@@ -10,7 +10,7 @@
Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
Copyright (c) 2005-2012 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-2022 Rhodri James <rhodri@wildebeest.org.uk>
Copyright (c) 2017 Joe Orton <jorton@redhat.com>
Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
@@ -42,17 +42,9 @@
SPDX-License-Identifier: MIT
*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#ifndef XML_BASIC_TESTS_H
-# define XML_BASIC_TESTS_H
+#define XML_BASIC_TESTS_H
extern void make_basic_test_case(Suite *s);
#endif /* XML_BASIC_TESTS_H */
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/tests/benchmark/Makefile.in b/tests/benchmark/Makefile.in
index 89a29cef053b..4156629984be 100644
--- a/tests/benchmark/Makefile.in
+++ b/tests/benchmark/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.18.1 from Makefile.am.
+# Makefile.in generated by automake 1.19 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2025 Free Software Foundation, Inc.
+# Copyright (C) 1994-2026 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -327,6 +327,7 @@ am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__rm_f_notfound = @am__rm_f_notfound@
am__tar = @am__tar@
+am__tar_ignore_stderr = @am__tar_ignore_stderr@
am__untar = @am__untar@
am__xargs_n = @am__xargs_n@
bindir = @bindir@
@@ -388,9 +389,9 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/benchmark/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/benchmark/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu tests/benchmark/Makefile
+ $(AUTOMAKE) --foreign tests/benchmark/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
@@ -432,22 +433,25 @@ $(am__depfiles_remade):
am--depfiles: $(am__depfiles_remade)
.c.o:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
@@ -516,13 +520,14 @@ distdir: $(BUILT_SOURCES)
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ am__distdir="$(distdir)"; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sed "/\//!d;s|^|$$am__distdir/|;s,/[^/]*$$,," | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
diff --git a/tests/chardata.h b/tests/chardata.h
index 51b18afe3ffe..ba6d8054e0cb 100644
--- a/tests/chardata.h
+++ b/tests/chardata.h
@@ -9,7 +9,7 @@
Copyright (c) 2002-2004 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
- Copyright (c) 2017 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
@@ -34,10 +34,6 @@
SPDX-License-Identifier: MIT
*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#ifndef XML_CHARDATA_H
# define XML_CHARDATA_H 1
@@ -57,7 +53,3 @@ void CharData_AppendXMLChars(CharData *storage, const XML_Char *s, int len);
int CharData_CheckXMLChars(CharData *storage, const XML_Char *s);
#endif /* XML_CHARDATA_H */
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/tests/common.h b/tests/common.h
index cf1635de0592..f9bde995e7d2 100644
--- a/tests/common.h
+++ b/tests/common.h
@@ -10,7 +10,7 @@
Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net>
- Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org>
+ Copyright (c) 2016-2026 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2017-2022 Rhodri James <rhodri@wildebeest.org.uk>
Copyright (c) 2017 Joe Orton <jorton@redhat.com>
Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
@@ -43,42 +43,38 @@
SPDX-License-Identifier: MIT
*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#ifndef XML_COMMON_H
-# define XML_COMMON_H
+#define XML_COMMON_H
-# include "expat_config.h"
-# include "minicheck.h"
-# include "chardata.h"
+#include "expat_config.h"
+#include "minicheck.h"
+#include "chardata.h"
-# ifdef XML_LARGE_SIZE
-# define XML_FMT_INT_MOD "ll"
-# else
-# define XML_FMT_INT_MOD "l"
-# endif
+#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"
-# 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
+#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
+# ifdef XML_UNICODE
+# error "No support for UTF-16 character without wchar_t in tests"
# else
-# ifdef XML_UNICODE
-# 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 */
+# 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 */
extern XML_Parser g_parser;
@@ -98,7 +94,7 @@ extern void basic_teardown(void);
extern void _xml_failure(XML_Parser parser, const char *file, int line);
-# define xml_failure(parser) _xml_failure((parser), __FILE__, __LINE__)
+#define xml_failure(parser) _xml_failure((parser), __FILE__, __LINE__)
extern enum XML_Status _XML_Parse_SINGLE_BYTES(XML_Parser parser, const char *s,
int len, int isFinal);
@@ -107,8 +103,8 @@ extern void _expect_failure(const char *text, enum XML_Error errorCode,
const char *errorMessage, const char *file,
int lineno);
-# define expect_failure(text, errorCode, errorMessage) \
- _expect_failure((text), (errorCode), (errorMessage), __FILE__, __LINE__)
+#define expect_failure(text, errorCode, errorMessage) \
+ _expect_failure((text), (errorCode), (errorMessage), __FILE__, __LINE__)
/* Support functions for handlers to collect up character and attribute data.
*/
@@ -116,14 +112,14 @@ extern void _expect_failure(const char *text, enum XML_Error errorCode,
extern void _run_character_check(const char *text, const XML_Char *expected,
const char *file, int line);
-# define run_character_check(text, expected) \
- _run_character_check(text, expected, __FILE__, __LINE__)
+#define run_character_check(text, expected) \
+ _run_character_check(text, expected, __FILE__, __LINE__)
extern void _run_attribute_check(const char *text, const XML_Char *expected,
const char *file, int line);
-# define run_attribute_check(text, expected) \
- _run_attribute_check(text, expected, __FILE__, __LINE__)
+#define run_attribute_check(text, expected) \
+ _run_attribute_check(text, expected, __FILE__, __LINE__)
typedef struct ExtTest {
const char *parse_text;
@@ -135,11 +131,11 @@ extern void _run_ext_character_check(const char *text, ExtTest *test_data,
const XML_Char *expected, const char *file,
int line);
-# define run_ext_character_check(text, test_data, expected) \
- _run_ext_character_check(text, test_data, expected, __FILE__, __LINE__)
+#define run_ext_character_check(text, test_data, expected) \
+ _run_ext_character_check(text, test_data, expected, __FILE__, __LINE__)
-# define ALLOC_ALWAYS_SUCCEED (-1)
-# define REALLOC_ALWAYS_SUCCEED (-1)
+#define ALLOC_ALWAYS_SUCCEED (-1)
+#define REALLOC_ALWAYS_SUCCEED (-1)
extern int g_allocation_count;
extern int g_reallocation_count;
@@ -151,7 +147,3 @@ extern void *duff_reallocator(void *ptr, size_t size);
extern char *portable_strndup(const char *s, size_t n);
#endif /* XML_COMMON_H */
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/tests/dummy.h b/tests/dummy.h
index 9a75b6fe9244..c1b4056f60c7 100644
--- a/tests/dummy.h
+++ b/tests/dummy.h
@@ -10,7 +10,7 @@
Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
Copyright (c) 2005-2012 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-2022 Rhodri James <rhodri@wildebeest.org.uk>
Copyright (c) 2017 Joe Orton <jorton@redhat.com>
Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
@@ -42,31 +42,27 @@
SPDX-License-Identifier: MIT
*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#ifndef XML_DUMMY_H
-# define XML_DUMMY_H
+#define XML_DUMMY_H
-# define DUMMY_START_DOCTYPE_HANDLER_FLAG (1UL << 0)
-# define DUMMY_END_DOCTYPE_HANDLER_FLAG (1UL << 1)
-# define DUMMY_ENTITY_DECL_HANDLER_FLAG (1UL << 2)
-# define DUMMY_NOTATION_DECL_HANDLER_FLAG (1UL << 3)
-# define DUMMY_ELEMENT_DECL_HANDLER_FLAG (1UL << 4)
-# define DUMMY_ATTLIST_DECL_HANDLER_FLAG (1UL << 5)
-# define DUMMY_COMMENT_HANDLER_FLAG (1UL << 6)
-# define DUMMY_PI_HANDLER_FLAG (1UL << 7)
-# define DUMMY_START_ELEMENT_HANDLER_FLAG (1UL << 8)
-# define DUMMY_START_CDATA_HANDLER_FLAG (1UL << 9)
-# define DUMMY_END_CDATA_HANDLER_FLAG (1UL << 10)
-# define DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG (1UL << 11)
-# define DUMMY_START_NS_DECL_HANDLER_FLAG (1UL << 12)
-# define DUMMY_END_NS_DECL_HANDLER_FLAG (1UL << 13)
-# define DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG (1UL << 14)
-# define DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG (1UL << 15)
-# define DUMMY_SKIP_HANDLER_FLAG (1UL << 16)
-# define DUMMY_DEFAULT_HANDLER_FLAG (1UL << 17)
+#define DUMMY_START_DOCTYPE_HANDLER_FLAG (1UL << 0)
+#define DUMMY_END_DOCTYPE_HANDLER_FLAG (1UL << 1)
+#define DUMMY_ENTITY_DECL_HANDLER_FLAG (1UL << 2)
+#define DUMMY_NOTATION_DECL_HANDLER_FLAG (1UL << 3)
+#define DUMMY_ELEMENT_DECL_HANDLER_FLAG (1UL << 4)
+#define DUMMY_ATTLIST_DECL_HANDLER_FLAG (1UL << 5)
+#define DUMMY_COMMENT_HANDLER_FLAG (1UL << 6)
+#define DUMMY_PI_HANDLER_FLAG (1UL << 7)
+#define DUMMY_START_ELEMENT_HANDLER_FLAG (1UL << 8)
+#define DUMMY_START_CDATA_HANDLER_FLAG (1UL << 9)
+#define DUMMY_END_CDATA_HANDLER_FLAG (1UL << 10)
+#define DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG (1UL << 11)
+#define DUMMY_START_NS_DECL_HANDLER_FLAG (1UL << 12)
+#define DUMMY_END_NS_DECL_HANDLER_FLAG (1UL << 13)
+#define DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG (1UL << 14)
+#define DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG (1UL << 15)
+#define DUMMY_SKIP_HANDLER_FLAG (1UL << 16)
+#define DUMMY_DEFAULT_HANDLER_FLAG (1UL << 17)
extern void init_dummy_handlers(void);
extern unsigned long get_dummy_handler_flags(void);
@@ -146,7 +142,3 @@ extern void XMLCALL dummy_skip_handler(void *userData,
int is_parameter_entity);
#endif /* XML_DUMMY_H */
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/tests/handlers.h b/tests/handlers.h
index 02c170d226d2..a0b413140a7c 100644
--- a/tests/handlers.h
+++ b/tests/handlers.h
@@ -45,16 +45,12 @@
SPDX-License-Identifier: MIT
*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#ifndef XML_HANDLERS_H
-# define XML_HANDLERS_H
+#define XML_HANDLERS_H
-# include "expat_config.h"
+#include "expat_config.h"
-# include "expat.h"
+#include "expat.h"
/* Variable holding the expected handler userData */
extern const void *g_handler_data;
@@ -74,8 +70,8 @@ extern void XMLCALL start_element_event_handler(void *userData,
extern void XMLCALL end_element_event_handler(void *userData,
const XML_Char *name);
-# define STRUCT_START_TAG 0
-# define STRUCT_END_TAG 1
+#define STRUCT_START_TAG 0
+#define STRUCT_END_TAG 1
extern void XMLCALL start_element_event_handler2(void *userData,
const XML_Char *name,
@@ -516,22 +512,21 @@ extern const struct handler_record_entry *
_handler_record_get(const struct handler_record_list *storage, int index,
const char *file, int line);
-# define handler_record_get(storage, index) \
- _handler_record_get((storage), (index), __FILE__, __LINE__)
+#define handler_record_get(storage, index) \
+ _handler_record_get((storage), (index), __FILE__, __LINE__)
-# define assert_record_handler_called(storage, index, expected_name, \
- expected_arg) \
- do { \
- const struct handler_record_entry *e \
- = handler_record_get(storage, index); \
- assert_true(strcmp(e->name, expected_name) == 0); \
- assert_true(e->arg == (expected_arg)); \
- } while (0)
+#define assert_record_handler_called(storage, index, expected_name, \
+ expected_arg) \
+ do { \
+ const struct handler_record_entry *e = handler_record_get(storage, index); \
+ assert_true(strcmp(e->name, expected_name) == 0); \
+ assert_true(e->arg == (expected_arg)); \
+ } while (0)
/* Entity Declaration Handlers */
-# define ENTITY_MATCH_FAIL (-1)
-# define ENTITY_MATCH_NOT_FOUND (0)
-# define ENTITY_MATCH_SUCCESS (1)
+#define ENTITY_MATCH_FAIL (-1)
+#define ENTITY_MATCH_NOT_FOUND (0)
+#define ENTITY_MATCH_SUCCESS (1)
extern void XMLCALL param_entity_match_handler(
void *userData, const XML_Char *entityName, int is_parameter_entity,
@@ -630,7 +625,3 @@ extern void XMLCALL suspend_then_resume_character_handler(void *userData,
int len);
#endif /* XML_HANDLERS_H */
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/tests/hash_tests.c b/tests/hash_tests.c
new file mode 100644
index 000000000000..5c5d7d4cf0f0
--- /dev/null
+++ b/tests/hash_tests.c
@@ -0,0 +1,157 @@
+/* Tests related to the hash tables used inside 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 "hash_tests.h"
+
+#include "common.h" // for XCS
+#include "expat.h"
+#include "hash_table.h"
+#include "minicheck.h"
+
+#include <stdbool.h>
+#include <string.h> // for memcmp
+
+START_TEST(test_hash_table) {
+ // The test is not doing any parsing, so a single run
+ // (with `g_chunkSize == 0`) is enough
+ if (g_chunkSize != 0)
+ return;
+
+ typedef struct {
+ const XML_Char *name;
+ bool initialized;
+ } NAME_AND_FLAG;
+
+ HASH_TABLE table;
+ XML_Parser parser = XML_ParserCreate(NULL);
+ hashTableInit(&table, parser);
+
+ const XML_Char *const key1 = XCS("key1");
+ const XML_Char *const key2 = XCS("key2");
+ const XML_Char *const key3 = XCS("key1overlap");
+
+ // Self-test: `key3` starts with `key1` but is different from it
+ assert_true(memcmp(key1, key3, keylen(key1)) == 0);
+ assert_true(keyeq(key1, keylen(key1), key3) == XML_FALSE);
+
+ // Test: Look up false for all keys because the table is empty
+ assert_true(lookup(parser, &table, key1, 0) == NULL);
+ assert_true(lookup(parser, &table, key2, 0) == NULL);
+ assert_true(lookup(parser, &table, key3, 0) == NULL);
+
+ // Test: Iteration yields 0 items initially
+ {
+ HASH_TABLE_ITER iter1;
+ hashTableIterInit(&iter1, &table);
+ assert_true(hashTableIterNext(&iter1) == NULL);
+ }
+
+ // Test: Insertion works (including initialization to zero)
+ NAME_AND_FLAG *const inserted1
+ = (NAME_AND_FLAG *)lookup(parser, &table, key1, sizeof(NAME_AND_FLAG));
+ assert_true(inserted1 != NULL);
+ assert_true(inserted1->name == key1);
+ assert_true(! inserted1->initialized);
+
+ // Make it possible to tell the struct apart from a freshly inserted version
+ inserted1->initialized = true;
+
+ // Test: Only present keys can be looked up
+ assert_true(lookup(parser, &table, key1, 0) != NULL);
+ assert_true(lookup(parser, &table, key2, 0) == NULL);
+ assert_true(lookup(parser, &table, key3, 0) == NULL);
+
+ // Test: Key length works without false positives
+ assert_true(lookupWithLength(parser, &table, key3, /*nameLen=*/3, 0) == NULL);
+ assert_true(lookupWithLength(parser, &table, key3, /*nameLen=*/4, 0) != NULL);
+ assert_true(lookupWithLength(parser, &table, key3, /*nameLen=*/5, 0) == NULL);
+
+ // TEST: Lookup does not reset existing entries to zeros
+ NAME_AND_FLAG *const found
+ = (NAME_AND_FLAG *)lookup(parser, &table, key1, sizeof(NAME_AND_FLAG));
+ assert_true(found != NULL);
+ assert_true(found->name == key1);
+ assert_true(found->initialized); // this is key
+
+ // Test: Insertion of a second item works
+ assert_true(lookup(parser, &table, key2, 0) == NULL);
+ assert_true(lookup(parser, &table, key2, sizeof(NAME_AND_FLAG)) != NULL);
+ assert_true(lookup(parser, &table, key2, 0) != NULL);
+
+ // Test: Iteration yields nothing but the two expected items
+ {
+ HASH_TABLE_ITER iter2;
+ hashTableIterInit(&iter2, &table);
+ size_t itemCount = 0;
+ while (true) {
+ const NAME_AND_FLAG *const item
+ = (const NAME_AND_FLAG *)hashTableIterNext(&iter2);
+ if (item == NULL)
+ break;
+
+ itemCount++;
+
+ if (keyeq(key1, keylen(key1), item->name) == XML_TRUE)
+ assert_true(item->initialized);
+ else if (keyeq(key2, keylen(key2), item->name) == XML_TRUE)
+ assert_true(! item->initialized);
+ else
+ fail("unexpected item .name");
+ }
+ assert_true(itemCount == 2);
+ }
+
+ // Test: After clearing all lookups fail
+ hashTableClear(&table);
+ assert_true(lookup(parser, &table, key1, 0) == NULL);
+ assert_true(lookup(parser, &table, key2, 0) == NULL);
+ assert_true(lookup(parser, &table, key3, 0) == NULL);
+
+ // Test: After clearing iteration yields 0 items again
+ {
+ HASH_TABLE_ITER iter3;
+ hashTableIterInit(&iter3, &table);
+ assert_true(hashTableIterNext(&iter3) == NULL);
+ }
+
+ hashTableDestroy(&table);
+ XML_ParserFree(parser);
+}
+END_TEST
+
+void
+make_hash_test_case(Suite *s) {
+ TCase *const tc_hash = tcase_create("hash tests");
+ suite_add_tcase(s, tc_hash);
+ tcase_add_test(tc_hash, test_hash_table);
+}
diff --git a/tests/hash_tests.h b/tests/hash_tests.h
new file mode 100644
index 000000000000..ed2c459ff82a
--- /dev/null
+++ b/tests/hash_tests.h
@@ -0,0 +1,41 @@
+/* Tests related to the hash tables used inside 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_HASH_TESTS_H
+#define XML_HASH_TESTS_H
+
+#include "minicheck.h"
+
+extern void make_hash_test_case(Suite *s);
+
+#endif /* XML_HASH_TESTS_H */
diff --git a/tests/memcheck.c b/tests/memcheck.c
index b670b322c012..8361f78fb356 100644
--- a/tests/memcheck.c
+++ b/tests/memcheck.c
@@ -10,6 +10,7 @@
Copyright (c) 2017-2023 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2022 Sean McBride <sean@rogue-research.com>
Copyright (c) 2026 Matthew Fernandez <matthew.fernandez@gmail.com>
+ Copyright (c) 2026 Leo Camus <leo.camus23@gmail.com>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@@ -117,7 +118,7 @@ tracking_free(void *ptr) {
if (entry->next != NULL)
entry->next->prev = entry->prev;
else
- alloc_tail = entry->next;
+ alloc_tail = entry->prev;
free(entry);
} else {
printf("Attempting to free unallocated memory at %p\n", ptr);
diff --git a/tests/memcheck.h b/tests/memcheck.h
index 7255aba14796..3febafe2fa05 100644
--- a/tests/memcheck.h
+++ b/tests/memcheck.h
@@ -7,8 +7,8 @@
\___/_/\_\ .__/ \__,_|\__|
|_| XML parser
- Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
- Copyright (c) 2017 Sebastian Pipping <sebastian@pipping.org>
+ Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
+ 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
@@ -33,10 +33,6 @@
SPDX-License-Identifier: MIT
*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#ifndef XML_MEMCHECK_H
# define XML_MEMCHECK_H 1
@@ -53,7 +49,3 @@ void *tracking_realloc(void *ptr, size_t size);
int tracking_report(void);
#endif /* XML_MEMCHECK_H */
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/tests/minicheck.h b/tests/minicheck.h
index d80c8603c637..0b21f5f581d5 100644
--- a/tests/minicheck.h
+++ b/tests/minicheck.h
@@ -14,7 +14,7 @@
Copyright (c) 2004-2006 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2006-2012 Karl Waclawek <karl@waclawek.net>
- Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org>
+ Copyright (c) 2016-2026 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2022 Rhodri James <rhodri@wildebeest.org.uk>
Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild@sony.com>
Licensed under the MIT license:
@@ -41,27 +41,15 @@
SPDX-License-Identifier: MIT
*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#ifndef XML_MINICHECK_H
-# define XML_MINICHECK_H
-
-# define CK_NOFORK 0
-# define CK_FORK 1
+#define XML_MINICHECK_H
-# define CK_SILENT 0
-# define CK_NORMAL 1
-# define CK_VERBOSE 2
+#define CK_NOFORK 0
+#define CK_FORK 1
-/* Workaround for Microsoft's compiler and Tru64 Unix systems where the
- C compiler has a working __func__, but the C++ compiler only has a
- working __FUNCTION__. This could be fixed in configure.in, but it's
- not worth it right now. */
-# if defined(_MSC_VER) || (defined(__osf__) && defined(__cplusplus))
-# define __func__ __FUNCTION__
-# endif
+#define CK_SILENT 0
+#define CK_NORMAL 1
+#define CK_VERBOSE 2
/* PRINTF_LIKE has two effects:
1. Make clang's -Wformat-nonliteral stop warning about non-literal format
@@ -69,30 +57,30 @@ extern "C" {
2. Make both clang and gcc's -Wformat-nonliteral warn about *callers* of
the annotated function that use a non-literal format string.
*/
-# if defined(__GNUC__)
-# define PRINTF_LIKE(fmtpos, argspos) \
- __attribute__((format(printf, fmtpos, argspos)))
-# else
-# define PRINTF_LIKE(fmtpos, argspos)
-# endif
+#if defined(__GNUC__)
+# define PRINTF_LIKE(fmtpos, argspos) \
+ __attribute__((format(printf, fmtpos, argspos)))
+#else
+# define PRINTF_LIKE(fmtpos, argspos)
+#endif
-# define START_TEST(testname) \
- static void testname(void) { \
- _check_set_test_info(__func__, __FILE__, __LINE__); \
- {
-# define END_TEST \
- } \
- }
+#define START_TEST(testname) \
+ static void testname(void) { \
+ _check_set_test_info(__func__, __FILE__, __LINE__); \
+ {
+#define END_TEST \
+ } \
+ }
void PRINTF_LIKE(1, 2) set_subtest(char const *fmt, ...);
-# define fail(msg) _fail(__FILE__, __LINE__, msg)
-# define assert_true(cond) \
- do { \
- if (! (cond)) { \
- _fail(__FILE__, __LINE__, "check failed: " #cond); \
- } \
- } while (0)
+#define fail(msg) _fail(__FILE__, __LINE__, msg)
+#define assert_true(cond) \
+ do { \
+ if (! (cond)) { \
+ _fail(__FILE__, __LINE__, "check failed: " #cond); \
+ } \
+ } while (0)
typedef void (*tcase_setup_function)(void);
typedef void (*tcase_teardown_function)(void);
@@ -131,11 +119,11 @@ void _check_set_test_info(char const *function, char const *filename,
* Prototypes for the actual implementation.
*/
-# if defined(__has_attribute)
-# if __has_attribute(noreturn)
+#if defined(__has_attribute)
+# if __has_attribute(noreturn)
__attribute__((noreturn))
-# endif
# endif
+#endif
void _fail(const char *file, int line, const char *msg);
Suite *suite_create(const char *name);
TCase *tcase_create(const char *name);
@@ -150,7 +138,3 @@ int srunner_ntests_failed(SRunner *runner);
void srunner_free(SRunner *runner);
#endif /* XML_MINICHECK_H */
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/tests/misc_tests.c b/tests/misc_tests.c
index 889620d42660..717cc2dd31aa 100644
--- a/tests/misc_tests.c
+++ b/tests/misc_tests.c
@@ -218,7 +218,7 @@ START_TEST(test_misc_version) {
if (! versions_equal(&read_version, &parsed_version))
fail("Version mismatch");
- if (xcstrcmp(version_text, XCS("expat_2.8.4"))
+ if (xcstrcmp(version_text, XCS("expat_2.8.5"))
!= 0) /* needs bump on releases */
fail("XML_*_VERSION in expat.h out of sync?\n");
}
diff --git a/tests/misc_tests.h b/tests/misc_tests.h
index 4cff492e4c90..8f8cda353ced 100644
--- a/tests/misc_tests.h
+++ b/tests/misc_tests.h
@@ -10,7 +10,7 @@
Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
Copyright (c) 2005-2012 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-2022 Rhodri James <rhodri@wildebeest.org.uk>
Copyright (c) 2017 Joe Orton <jorton@redhat.com>
Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
@@ -42,17 +42,9 @@
SPDX-License-Identifier: MIT
*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#ifndef XML_MISC_TESTS_H
-# define XML_MISC_TESTS_H
+#define XML_MISC_TESTS_H
extern void make_miscellaneous_test_case(Suite *s);
#endif /* XML_MISC_TESTS_H */
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/tests/ns_tests.h b/tests/ns_tests.h
index 72d13532e61e..9c3640b1c658 100644
--- a/tests/ns_tests.h
+++ b/tests/ns_tests.h
@@ -10,7 +10,7 @@
Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
Copyright (c) 2005-2012 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-2022 Rhodri James <rhodri@wildebeest.org.uk>
Copyright (c) 2017 Joe Orton <jorton@redhat.com>
Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
@@ -42,17 +42,9 @@
SPDX-License-Identifier: MIT
*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#ifndef XML_NS_TESTS_H
-# define XML_NS_TESTS_H
+#define XML_NS_TESTS_H
extern void make_namespace_test_case(Suite *s);
#endif /* XML_NS_TESTS_H */
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/tests/nsalloc_tests.c b/tests/nsalloc_tests.c
index b8c361ae25df..a0ee114efe3f 100644
--- a/tests/nsalloc_tests.c
+++ b/tests/nsalloc_tests.c
@@ -43,6 +43,8 @@
SPDX-License-Identifier: MIT
*/
+#include "expat_config.h"
+
#if defined(NDEBUG)
# undef NDEBUG /* because test suite relies on assert(...) at the moment */
#endif
diff --git a/tests/nsalloc_tests.h b/tests/nsalloc_tests.h
index 59ec6c559847..483926b1428d 100644
--- a/tests/nsalloc_tests.h
+++ b/tests/nsalloc_tests.h
@@ -10,7 +10,7 @@
Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
Copyright (c) 2005-2012 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-2022 Rhodri James <rhodri@wildebeest.org.uk>
Copyright (c) 2017 Joe Orton <jorton@redhat.com>
Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
@@ -42,17 +42,9 @@
SPDX-License-Identifier: MIT
*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#ifndef XML_NSALLOC_TESTS_H
-# define XML_NSALLOC_TESTS_H
+#define XML_NSALLOC_TESTS_H
extern void make_nsalloc_test_case(Suite *s);
#endif /* XML_NSALLOC_TESTS_H */
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/tests/runtests.c b/tests/runtests.c
index 51fd131e99f9..12f8c36c12e3 100644
--- a/tests/runtests.c
+++ b/tests/runtests.c
@@ -10,7 +10,7 @@
Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net>
- Copyright (c) 2016-2023 Sebastian Pipping <sebastian@pipping.org>
+ Copyright (c) 2016-2026 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2017-2022 Rhodri James <rhodri@wildebeest.org.uk>
Copyright (c) 2017 Joe Orton <jorton@redhat.com>
Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
@@ -55,6 +55,7 @@
#include "common.h"
#include "basic_tests.h"
+#include "hash_tests.h"
#include "ns_tests.h"
#include "misc_tests.h"
#include "alloc_tests.h"
@@ -68,6 +69,7 @@ make_suite(void) {
Suite *s = suite_create("basic");
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);
diff --git a/tests/structdata.h b/tests/structdata.h
index 2fb9fca714c1..a1f6dcbe7e61 100644
--- a/tests/structdata.h
+++ b/tests/structdata.h
@@ -8,6 +8,7 @@
|_| XML parser
Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
+ Copyright (c) 2026 Sebastian Pipping <sebastian@pipping.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@@ -32,10 +33,6 @@
SPDX-License-Identifier: MIT
*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#ifndef XML_STRUCTDATA_H
# define XML_STRUCTDATA_H 1
@@ -65,7 +62,3 @@ void StructData_CheckItems(StructData *storage, const StructDataEntry *expected,
void StructData_Dispose(StructData *storage);
#endif /* XML_STRUCTDATA_H */
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/tests/xmltest.sh b/tests/xmltest.sh
index 56e66c56f6ea..423b773a8860 100755
--- a/tests/xmltest.sh
+++ b/tests/xmltest.sh
@@ -31,6 +31,7 @@
# Copyright (c) 2008-2019 Sebastian Pipping <sebastian@pipping.org>
# Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
# Copyright (c) 2025 Hanno Böck <hanno@gentoo.org>
+# Copyright (c) 2026 Huang Wenbin <huangwenbin@kylinos.cn>
# Licensed under the MIT license:
#
# Permission is hereby granted, free of charge, to any person obtaining
@@ -172,3 +173,4 @@ done
echo "Passed: $SUCCESS"
echo "Failed: $ERROR"
+test "$ERROR" -eq 0
diff --git a/xmlwf/Makefile.in b/xmlwf/Makefile.in
index d6d4033b0090..7c4ff12ef536 100644
--- a/xmlwf/Makefile.in
+++ b/xmlwf/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.18.1 from Makefile.am.
+# Makefile.in generated by automake 1.19 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2025 Free Software Foundation, Inc.
+# Copyright (C) 1994-2026 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -335,6 +335,7 @@ am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__rm_f_notfound = @am__rm_f_notfound@
am__tar = @am__tar@
+am__tar_ignore_stderr = @am__tar_ignore_stderr@
am__untar = @am__untar@
am__xargs_n = @am__xargs_n@
bindir = @bindir@
@@ -412,9 +413,9 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu xmlwf/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign xmlwf/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu xmlwf/Makefile
+ $(AUTOMAKE) --foreign xmlwf/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
@@ -499,22 +500,25 @@ $(am__depfiles_remade):
am--depfiles: $(am__depfiles_remade)
.c.o:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
@@ -639,13 +643,14 @@ distdir: $(BUILT_SOURCES)
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ am__distdir="$(distdir)"; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sed "/\//!d;s|^|$$am__distdir/|;s,/[^/]*$$,," | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
diff --git a/xmlwf/unixfilemap.c b/xmlwf/unixfilemap.c
index 5ebffe35ba05..71fb744b7a53 100644
--- a/xmlwf/unixfilemap.c
+++ b/xmlwf/unixfilemap.c
@@ -10,7 +10,7 @@
Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
Copyright (c) 2001-2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2006 Karl Waclawek <karl@waclawek.net>
- Copyright (c) 2016-2025 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) 2026 Matthew Fernandez <matthew.fernandez@gmail.com>
Licensed under the MIT license:
@@ -37,6 +37,8 @@
SPDX-License-Identifier: MIT
*/
+#include "expat_config.h" // for off_t
+
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
diff --git a/xmlwf/xmlfile.c b/xmlwf/xmlfile.c
index 0b5f5d67298c..85e5dc582827 100644
--- a/xmlwf/xmlfile.c
+++ b/xmlwf/xmlfile.c
@@ -11,7 +11,7 @@
Copyright (c) 2002-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-2025 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 David Loffredo <loffredo@steptools.com>
Copyright (c) 2021 Donghee Na <donghee.na@python.org>
@@ -266,7 +266,7 @@ externalEntityRefStream(XML_Parser parser, const XML_Char *context,
return ret;
}
-int
+bool
XML_ProcessFile(XML_Parser parser, const XML_Char *filename, unsigned flags) {
int result;
@@ -299,5 +299,5 @@ XML_ProcessFile(XML_Parser parser, const XML_Char *filename, unsigned flags) {
}
} else
result = processStream(filename, parser);
- return result;
+ return (bool)result;
}
diff --git a/xmlwf/xmlfile.h b/xmlwf/xmlfile.h
index c4c8c82cd5cb..7eb4811103c2 100644
--- a/xmlwf/xmlfile.h
+++ b/xmlwf/xmlfile.h
@@ -10,7 +10,7 @@
Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2005 Karl Waclawek <karl@waclawek.net>
- Copyright (c) 2016-2023 Sebastian Pipping <sebastian@pipping.org>
+ Copyright (c) 2016-2026 Sebastian Pipping <sebastian@pipping.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@@ -35,6 +35,8 @@
SPDX-License-Identifier: MIT
*/
+#include <stdbool.h>
+
#define XML_MAP_FILE 01
#define XML_EXTERNAL_ENTITIES 02
@@ -46,5 +48,5 @@
extern int g_read_size_bytes;
-extern int XML_ProcessFile(XML_Parser parser, const XML_Char *filename,
- unsigned flags);
+extern bool XML_ProcessFile(XML_Parser parser, const XML_Char *filename,
+ unsigned flags);
diff --git a/xmlwf/xmlmime.h b/xmlwf/xmlmime.h
index 87665bf6cd9d..335a87e9cbc4 100644
--- a/xmlwf/xmlmime.h
+++ b/xmlwf/xmlmime.h
@@ -8,7 +8,7 @@
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
- Copyright (c) 2016-2017 Sebastian Pipping <sebastian@pipping.org>
+ Copyright (c) 2016-2026 Sebastian Pipping <sebastian@pipping.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@@ -33,10 +33,6 @@
SPDX-License-Identifier: MIT
*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/* Registered charset names are at most 40 characters long. */
#define CHARSET_MAX 41
@@ -48,7 +44,3 @@ extern "C" {
*/
void getXMLCharset(const char *buf, char *charset);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/xmlwf/xmlwf.c b/xmlwf/xmlwf.c
index 57beef1f75c6..892732cb0729 100644
--- a/xmlwf/xmlwf.c
+++ b/xmlwf/xmlwf.c
@@ -933,7 +933,7 @@ usage(const XML_Char *prog, int rc) {
T(" -w enable support for [W]indows code pages\n")
T(" -r disable memory-mapping and use [r]ead calls instead\n")
T(" -g BYTES buffer size to request per call pair to XML_[G]etBuffer and read (default: 8 KiB)\n")
- T(" -k when processing multiple files, [k]eep processing after first file with error\n")
+ T(" -k when processing multiple files, [k]eep processing after first file with error, and make the last error determine the exit code.\n")
T("\n")
T("output control arguments:\n")
T(" -d DIRECTORY output [d]estination directory\n")
@@ -969,7 +969,7 @@ usage(const XML_Char *prog, int rc) {
T(" 0 the input files are well-formed and the output (if requested) was written successfully\n")
T(" 1 could not allocate data structures, signals a serious problem with execution environment\n")
T(" 2 one or more input files were not well-formed\n")
- T(" 3 could not create an output file\n")
+ T(" 3 one or more output files could not be written\n")
T(" 4 command-line argument error\n")
T("\n")
T("xmlwf of libexpat is software libre, licensed under the MIT license.\n")
@@ -1194,7 +1194,6 @@ tmain(int argc, XML_Char **argv) {
}
for (; i < argc; i++) {
XML_Char *outName = 0;
- int result;
XML_Parser parser;
if (useNamespaces)
parser = XML_ParserCreateNS(encoding, NSSEP);
@@ -1350,19 +1349,29 @@ tmain(int argc, XML_Char **argv) {
}
if (windowsCodePages)
XML_SetUnknownEncodingHandler(parser, unknownEncoding, 0);
- result = XML_ProcessFile(parser, useStdin ? NULL : argv[i], processFlags);
+ const bool processingSuccess
+ = XML_ProcessFile(parser, useStdin ? NULL : argv[i], processFlags);
+ bool closingSuccess = true;
if (outputDir) {
if (outputType == 'm')
metaEndDocument(parser);
- fclose(userData.fp);
- if (! result) {
+ closingSuccess = (fclose(userData.fp) == 0);
+ if (! closingSuccess)
+ tperror(outName);
+ if (! processingSuccess || ! closingSuccess) {
tremove(outName);
}
free(outName);
}
XML_ParserFree(parser);
- if (! result) {
- exitCode = XMLWF_EXIT_NOT_WELLFORMED;
+ if (! processingSuccess || ! closingSuccess) {
+ // NOTE: If both failed, the last error should determine the exit code.
+ // Failure to close happened after failure to process.
+ if (! closingSuccess)
+ exitCode = XMLWF_EXIT_OUTPUT_ERROR;
+ else if (! processingSuccess)
+ exitCode = XMLWF_EXIT_NOT_WELLFORMED;
+
cleanupUserData(&userData);
if (! continueOnError) {
break;
diff --git a/xmlwf/xmlwf_helpgen.py b/xmlwf/xmlwf_helpgen.py
index d80020550273..98a01e4b282d 100755
--- a/xmlwf/xmlwf_helpgen.py
+++ b/xmlwf/xmlwf_helpgen.py
@@ -50,7 +50,7 @@ epilog = dedent(
0 the input files are well-formed and the output (if requested) was written successfully
1 could not allocate data structures, signals a serious problem with execution environment
2 one or more input files were not well-formed
- 3 could not create an output file
+ 3 one or more output files could not be written
4 command-line argument error
xmlwf of libexpat is software libre, licensed under the MIT license.
@@ -116,7 +116,10 @@ input_related.add_argument(
input_related.add_argument(
"-k",
action="store_true",
- help="when processing multiple files, [k]eep processing after first file with error",
+ help=(
+ "when processing multiple files, [k]eep processing after first file with error"
+ ", and make the last error determine the exit code."
+ ),
)
output_related = parser.add_argument_group("output control arguments")
diff --git a/xmlwf/xmlwf_helpgen.sh b/xmlwf/xmlwf_helpgen.sh
index ac3c33ea00b5..a4ebb6db4e8b 100755
--- a/xmlwf/xmlwf_helpgen.sh
+++ b/xmlwf/xmlwf_helpgen.sh
@@ -6,7 +6,7 @@
# \___/_/\_\ .__/ \__,_|\__|
# |_| XML parser
#
-# Copyright (c) 2019-2021 Sebastian Pipping <sebastian@pipping.org>
+# Copyright (c) 2019-2026 Sebastian Pipping <sebastian@pipping.org>
# Licensed under the MIT license:
#
# Permission is hereby granted, free of charge, to any person obtaining
@@ -30,7 +30,11 @@
#
# SPDX-License-Identifier: MIT
-./xmlwf/xmlwf_helpgen.py | sed \
+set -e
+
+cd "$(dirname "$(type -P "$0")")"
+
+./xmlwf_helpgen.py | sed \
-e 's,usage: ,usage:,' \
-e 's, xmlwf, %s,' \
-e 's, \[-h | -v\],,' \