expat: update to 2.7.0

arm-master
pedro 7 months ago
parent 4ea85f3676
commit f7d7c7a73a

@ -350,7 +350,7 @@ sub fixDyn
# avahi
fixDynDep("avahi-daemon", "libavahi-core.so.7.1.0");
fixDynDep("avahi-daemon", "libavahi-common.so.3.5.4");
fixDynDep("avahi-daemon", "libexpat.so.1.10.0");
fixDynDep("avahi-daemon", "libexpat.so.1.10.1");
fixDynDep("avahi-daemon", "libdaemon.so.0.5.0");
fixDynDep("xtables-legacy-multi", "libxtables.so");
@ -669,7 +669,7 @@ elsif ($openssldir eq "openssl-3.0") {
#genSO("${root}/usr/lib/libwolfssl.so.42.2.0", "${router}/wolfssl/src/.libs/libwolfssl.a", "${stripshared}");
if ($is_arm ne "y") { # MIPS only (ARM - bigger)
genSO("${root}/usr/lib/libexpat.so.1.10.0", "${router}/expat/lib/.libs/libexpat.a", "${stripshared}");
genSO("${root}/usr/lib/libexpat.so.1.10.1", "${router}/expat/lib/.libs/libexpat.a", "${stripshared}");
genSO("${root}/usr/lib/libid3tag.so.0.16.3", "${router}/libid3tag/static/libid3tag.a", "${stripshared}", "-L${router}/zlib");
genSO("${root}/usr/lib/libexif.so.12", "${router}/libexif/libexif/.libs/libexif.a", "${stripshared}");
genSO("${root}/usr/lib/libavcodec.so.54", "${router}/ffmpeg//libavcodec/libavcodec.a", "${stripshared}", "-L${router}/ffmpeg/libavutil -L${router}/zlib");

@ -3818,9 +3818,9 @@ expat: expat/stamp-h1
@$(MAKE) -C $@ DESTDIR=$(TOP)/expat/staged install
expat-install:
install -D expat/staged/usr/lib/libexpat.so.1.10.0 $(INSTALLDIR)/expat/usr/lib/libexpat.so.1.10.0
$(STRIP) $(INSTALLDIR)/expat/usr/lib/libexpat.so.1.10.0
cd $(INSTALLDIR)/expat/usr/lib && ln -sf libexpat.so.1.10.0 libexpat.so.1
install -D expat/staged/usr/lib/libexpat.so.1.10.1 $(INSTALLDIR)/expat/usr/lib/libexpat.so.1.10.1
$(STRIP) $(INSTALLDIR)/expat/usr/lib/libexpat.so.1.10.1
cd $(INSTALLDIR)/expat/usr/lib && ln -sf libexpat.so.1.10.1 libexpat.so.1
expat-clean:
-@$(MAKE) -C expat clean

@ -3,25 +3,25 @@
The cmake based buildsystem for expat works on Windows (cygwin, mingw, Visual
Studio) and should work on all other platform cmake supports.
Assuming ~/expat-2.6.4 is the source directory of expat, add a subdirectory
Assuming ~/expat-2.7.0 is the source directory of expat, add a subdirectory
build and change into that directory:
~/expat-2.6.4$ mkdir build && cd build
~/expat-2.6.4/build$
~/expat-2.7.0$ mkdir build && cd build
~/expat-2.7.0/build$
From that directory, call cmake first, then call make, make test and
make install in the usual way:
~/expat-2.6.4/build$ cmake ..
~/expat-2.7.0/build$ cmake ..
-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
....
-- Configuring done
-- Generating done
-- Build files have been written to: /home/patrick/expat-2.6.4/build
-- Build files have been written to: /home/patrick/expat-2.7.0/build
If you want to specify the install location for your files, append
-DCMAKE_INSTALL_PREFIX=/your/install/path to the cmake call.
~/expat-2.6.4/build$ make && make test && make install
~/expat-2.7.0/build$ make && make test && make install
Scanning dependencies of target expat
[ 5%] Building C object CMakeFiles/expat.dir/lib/xmlparse.c.o
[ 11%] Building C object CMakeFiles/expat.dir/lib/xmlrole.c.o

@ -7,7 +7,7 @@
#
# Copyright (c) 2010 Patrick Spendrin <ps_ml@gmx.de>
# Copyright (c) 2012 Karl Waclawek <karl@waclawek.net>
# Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org>
# Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org>
# Copyright (c) 2016 Sergei Nikulov <sergey.nikulov@gmail.com>
# Copyright (c) 2016 Björn Lindahl <bjorn.lindahl@foi.se>
# Copyright (c) 2016 Tobias Taschner <github@tc84.de>
@ -30,15 +30,16 @@
# Copyright (c) 2020 Thomas Beutlich <tc@tbeu.de>
# Copyright (c) 2021 Alex Richardson <Alexander.Richardson@cl.cam.ac.uk>
# Copyright (c) 2022 Johnny Jazeix <jazeix@gmail.com>
# Copyright (c) 2022 Mark Brand <markbrand@google.com>
# Copyright (c) 2022 David Faure <david.faure@kdab.com>
# Unlike most of Expat,
# this file is copyrighted under the BSD-license for buildsystem files of KDE.
cmake_minimum_required(VERSION 3.5.0)
cmake_minimum_required(VERSION 3.13.0)
project(expat
VERSION
2.6.4
2.7.0
LANGUAGES
C
)
@ -134,7 +135,7 @@ expat_shy_set(EXPAT_SHARED_LIBS ${_EXPAT_SHARED_LIBS_DEFAULT} CACHE BOOL "Build
expat_shy_set(EXPAT_BUILD_DOCS ${_EXPAT_BUILD_DOCS_DEFAULT} CACHE BOOL "Build man page for xmlwf")
expat_shy_set(EXPAT_BUILD_FUZZERS OFF CACHE BOOL "Build fuzzers for the expat library")
expat_shy_set(EXPAT_BUILD_PKGCONFIG ${_EXPAT_BUILD_PKGCONFIG_DEFAULT} CACHE BOOL "Build pkg-config file")
expat_shy_set(EXPAT_OSSFUZZ_BUILD OFF CACHE BOOL "Build fuzzers via ossfuzz for the expat library")
expat_shy_set(EXPAT_OSSFUZZ_BUILD OFF CACHE BOOL "Build fuzzers via OSS-Fuzz for the expat library")
if(UNIX OR _EXPAT_HELP)
expat_shy_set(EXPAT_WITH_LIBBSD OFF CACHE BOOL "Utilize libbsd (for arc4random_buf)")
endif()
@ -169,11 +170,15 @@ if(NOT _EXPAT_HELP)
mark_as_advanced(_EXPAT_M32)
endif()
if(EXPAT_BUILD_TESTS)
if(EXPAT_BUILD_TESTS OR EXPAT_BUILD_FUZZERS)
# We have to call enable_language() before modifying any CMAKE_CXX_* variables
enable_language(CXX)
if (EXPAT_BUILD_FUZZERS)
set(CMAKE_CXX_STANDARD 17) # for std::string_view for Abseil for libprotobuf-mutator
else()
set(CMAKE_CXX_STANDARD 11)
endif()
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) # i.e. -std=c++11 rather than default -std=gnu++11
endif()
@ -320,7 +325,7 @@ if(FLAG_VISIBILITY)
endif()
set(EXTRA_COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -fvisibility=hidden")
endif()
if(MINGW)
if(MINGW AND ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU"))
# Without __USE_MINGW_ANSI_STDIO the compiler produces a false positive
set(EXTRA_COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -Wno-pedantic-ms-format")
endif()
@ -467,7 +472,7 @@ foreach(build_type_upper
endforeach()
set(LIBCURRENT 11) # sync
set(LIBREVISION 0) # with
set(LIBREVISION 1) # with
set(LIBAGE 10) # configure.ac!
math(EXPR LIBCURRENT_MINUS_AGE "${LIBCURRENT} - ${LIBAGE}")
@ -587,7 +592,7 @@ if(EXPAT_BUILD_TOOLS)
if(MINGW AND _EXPAT_UNICODE_WCHAR_T)
# https://gcc.gnu.org/onlinedocs/gcc/x86-Windows-Options.html
set_target_properties(xmlwf PROPERTIES LINK_FLAGS -municode)
target_link_options(xmlwf PRIVATE -municode)
endif()
if(EXPAT_BUILD_DOCS)
@ -724,7 +729,7 @@ if(EXPAT_BUILD_FUZZERS)
message(SEND_ERROR
"OSS-Fuzz builds require the environment variable "
"LIB_FUZZING_ENGINE to be set. If you are seeing this "
"warning, it points to a deeper problem in the ossfuzz "
"warning, it points to a deeper problem in the OSS-Fuzz "
"build setup.")
endif()
@ -743,24 +748,78 @@ if(EXPAT_BUILD_FUZZERS)
target_link_libraries(${target_name} fuzzpat)
target_compile_definitions(${target_name}
PRIVATE ENCODING_FOR_FUZZING=${encoding_type})
if(NOT EXPAT_OSSFUZZ_BUILD)
target_compile_options(${target_name} PRIVATE -fsanitize=fuzzer-no-link)
endif()
# NOTE: Avoiding target_link_options here only because it needs CMake >=3.13
if(EXPAT_OSSFUZZ_BUILD)
set_target_properties(${target_name} PROPERTIES LINK_FLAGS $ENV{LIB_FUZZING_ENGINE})
target_link_options(${target_name} PRIVATE $ENV{LIB_FUZZING_ENGINE})
set_target_properties(${target_name} PROPERTIES LINKER_LANGUAGE "CXX")
else()
set_target_properties(${target_name} PROPERTIES LINK_FLAGS -fsanitize=fuzzer)
target_compile_options(${target_name} PRIVATE -fsanitize=fuzzer)
target_link_options(${target_name} PRIVATE -fsanitize=fuzzer)
endif()
set_property(
TARGET ${target_name} PROPERTY RUNTIME_OUTPUT_DIRECTORY fuzz)
endforeach()
endforeach()
find_package(Protobuf REQUIRED)
# Only include libprotobuf-mutator here so we don't build it in non-fuzz
# configurations.
include(ExternalProject)
set(ProtobufMutator_PREFIX libprotobuf-mutator)
set(ProtobufMutator_PATH ${CMAKE_CURRENT_BINARY_DIR}/${ProtobufMutator_PREFIX}/src/${ProtobufMutator_PREFIX})
set(ProtobufMutator_BUILD_PATH ${ProtobufMutator_PATH}-build)
set(ProtobufMutator_INCLUDE_DIR ${ProtobufMutator_PATH})
set(ProtobufMutator_LIBRARIES ${ProtobufMutator_BUILD_PATH}/src/libfuzzer/libprotobuf-mutator-libfuzzer.a ${ProtobufMutator_BUILD_PATH}/src/libprotobuf-mutator.a)
ExternalProject_Add(
${ProtobufMutator_PREFIX}
PREFIX ${ProtobufMutator_PREFIX}
GIT_REPOSITORY https://github.com/google/libprotobuf-mutator.git
GIT_TAG 57928f41ae52bb27666aa15b310130d086dac245 # v1.4-16-g57928f4
CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
CMAKE_CACHE_ARGS
-DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER}
-DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER}
-DLIB_PROTO_MUTATOR_EXAMPLES:BOOL=OFF
-DLIB_PROTO_MUTATOR_TESTING:BOOL=OFF
BUILD_BYPRODUCTS ${ProtobufMutator_LIBRARIES}
UPDATE_COMMAND true
INSTALL_COMMAND true)
# Check for availability of protobuf compiler to avoid hard-to-understand
# errors from make(1) down the line as seen with CMake 3.25.1 on Debian
if(NOT Protobuf_PROTOC_EXECUTABLE)
message(SEND_ERROR
"The protobuf compiler (protoc) could not be found. "
"Is it installed and working properly?")
endif()
protobuf_generate_cpp(XML_LPM_FUZZER_PROTO_SRCS
XML_LPM_FUZZER_PROTO_HDRS
fuzz/xml_lpm_fuzzer.proto)
add_executable(xml_lpm_fuzzer
fuzz/xml_lpm_fuzzer.cpp
${XML_LPM_FUZZER_PROTO_SRCS})
target_include_directories(xml_lpm_fuzzer PUBLIC ${ProtobufMutator_INCLUDE_DIR})
target_link_libraries(xml_lpm_fuzzer
fuzzpat
${ProtobufMutator_LIBRARIES}
${Protobuf_LIBRARIES})
add_dependencies(xml_lpm_fuzzer ${ProtobufMutator_PREFIX})
if(EXPAT_OSSFUZZ_BUILD)
target_link_options(xml_lpm_fuzzer PRIVATE $ENV{LIB_FUZZING_ENGINE})
else()
target_compile_options(xml_lpm_fuzzer PRIVATE -fsanitize=fuzzer)
target_link_options(xml_lpm_fuzzer PRIVATE -fsanitize=fuzzer)
endif()
set_property(TARGET xml_lpm_fuzzer PROPERTY RUNTIME_OUTPUT_DIRECTORY fuzz)
else()
if(EXPAT_OSSFUZZ_BUILD)
message(SEND_ERROR
"Attempting to perform an ossfuzz build without turning on the fuzzer build. "
"Attempting to perform an OSS-Fuzz build without turning on the fuzzer build. "
"This is likely in error - consider adding "
"-DEXPAT_BUILD_FUZZERS=ON to your cmake execution.")
endif()
@ -913,13 +972,7 @@ elseif(EXPAT_CHAR_TYPE STREQUAL "wchar_t")
else()
set(_EXPAT_CHAR_TYPE_SUMMARY "ERROR")
endif()
# NOTE: We're not accessing global property GENERATOR_IS_MULTI_CONFIG
# because that would require CMake >=3.9
if(CMAKE_CONFIGURATION_TYPES)
set(_EXPAT_GENERATOR_IS_MULTI_CONFIG TRUE)
else()
set(_EXPAT_GENERATOR_IS_MULTI_CONFIG FALSE)
endif()
get_property(_EXPAT_GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
message(STATUS "===========================================================================")
message(STATUS "")

@ -11,16 +11,23 @@
!! The following topics need *additional skilled C developers* to progress !!
!! in a timely manner or at all (loosely ordered by descending priority): !!
!! !!
!! - <blink>fixing a complex non-public security issue</blink>, !!
!! - teaming up on researching and fixing future security reports and !!
!! ClusterFuzz findings with few-days-max response times in communication !!
!! in order to (1) have a sound fix ready before the end of a 90 days !!
!! grace period and (2) in a sustainable manner, !!
!! - helping CPython Expat bindings with supporting Expat's billion laughs !!
!! attack protection API (https://github.com/python/cpython/issues/90949): !!
!! - XML_SetBillionLaughsAttackProtectionActivationThreshold !!
!! - XML_SetBillionLaughsAttackProtectionMaximumAmplification !!
!! - helping Perl's XML::Parser Expat bindings with supporting Expat's !!
!! security API (https://github.com/cpan-authors/XML-Parser/issues/102): !!
!! - XML_SetBillionLaughsAttackProtectionActivationThreshold !!
!! - XML_SetBillionLaughsAttackProtectionMaximumAmplification !!
!! - XML_SetReparseDeferralEnabled !!
!! - implementing and auto-testing XML 1.0r5 support !!
!! (needs discussion before pull requests), !!
!! - smart ideas on fixing the Autotools CMake files generation issue !!
!! without breaking CI (needs discussion before pull requests), !!
!! - the Windows binaries topic (needs requirements engineering first), !!
!! - pushing migration from `int` to `size_t` further !!
!! including edge-cases test coverage (needs discussion before anything). !!
!! !!
@ -30,6 +37,78 @@
!! THANK YOU! Sebastian Pipping -- Berlin, 2024-03-09 !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Release 2.7.0 Thu March 13 2025
Security fixes:
#893 #973 CVE-2024-8176 -- Fix crash from chaining a large number
of entities caused by stack overflow by resolving use of
recursion, for all three uses of entities:
- general entities in character data ("<e>&g1;</e>")
- general entities in attribute values ("<e k1='&g1;'/>")
- parameter entities ("%p1;")
Known impact is (reliable and easy) denial of service:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H/E:H/RL:O/RC:C
(Base Score: 7.5, Temporal Score: 7.2)
Please note that a layer of compression around XML can
significantly reduce the minimum attack payload size.
Other changes:
#935 #937 Autotools: Make generated CMake files look for
libexpat.@SO_MAJOR@.dylib on macOS
#925 Autotools: Sync CMake templates with CMake 3.29
#945 #962 #966 CMake: Drop support for CMake <3.13
#942 CMake: Small fuzzing related improvements
#921 docs: Add missing documentation of error code
XML_ERROR_NOT_STARTED that was introduced with 2.6.4
#941 docs: Document need for C++11 compiler for use from C++
#959 tests/benchmark: Fix a (harmless) TOCTTOU
#944 Windows: Fix installer target location of file xmlwf.xml
for CMake
#953 Windows: Address warning -Wunknown-warning-option
about -Wno-pedantic-ms-format from LLVM MinGW
#971 Address Cppcheck warnings
#969 #970 Mass-migrate links from http:// to https://
#947 #958 ..
#974 #975 Document changes since the previous release
#974 #975 Version info bumped from 11:0:10 (libexpat*.so.1.10.0)
to 11:1:10 (libexpat*.so.1.10.1); see https://verbump.de/
for what these numbers do
Infrastructure:
#926 tests: Increase robustness
#927 #932 ..
#930 #933 tests: Increase test coverage
#617 #950 ..
#951 #952 ..
#954 #955 .. Fuzzing: Add new fuzzer "xml_lpm_fuzzer" based on
#961 Google's libprotobuf-mutator ("LPM")
#957 Fuzzing|CI: Start producing fuzzing code coverage reports
#936 CI: Pass -q -q for LCOV >=2.1 in coverage.sh
#942 CI: Small fuzzing related improvements
#139 #203 ..
#791 #946 CI: Make GitHub Actions build using MSVC on Windows and
produce 32bit and 64bit Windows binaries
#956 CI: Get off of about-to-be-removed Ubuntu 20.04
#960 #964 CI: Start uploading to Coverity Scan for static analysis
#972 CI: Stop loading DTD from the internet to address flaky CI
#971 CI: Adapt to breaking changes in Cppcheck
Special thanks to:
Alexander Gieringer
Berkay Eren Ürün
Hanno Böck
Jann Horn
Mark Brand
Sebastian Andrzej Siewior
Snild Dolkow
Thomas Pröll
Tomas Korbar
valord577
and
Google Project Zero
Linutronix
Red Hat
Siemens
Release 2.6.4 Wed November 6 2024
Security fixes:
#915 CVE-2024-50602 -- Fix crash within function XML_ResumeParser
@ -46,6 +125,8 @@ Release 2.6.4 Wed November 6 2024
#904 tests: Resolve duplicate handler
#317 #918 tests: Improve tests on doctype closing (ex CVE-2019-15903)
#914 Fix signedness of format strings
#915 For use from C++, expat.h started requiring C++11 due to
use of C99 features
#919 #920 Version info bumped from 10:3:9 (libexpat*.so.1.9.3)
to 11:0:10 (libexpat*.so.1.10.0); see https://verbump.de/
for what these numbers do

@ -11,7 +11,7 @@
> at the top of the `Changes` file.
# Expat, Release 2.6.4
# Expat, Release 2.7.0
This is Expat, a C99 library for parsing
[XML 1.0 Fourth Edition](https://www.w3.org/TR/2006/REC-xml-20060816/), started by
@ -22,9 +22,9 @@ are called when the parser discovers the associated structures in the
document being parsed. A start tag is an example of the kind of
structures for which you may register handlers.
Expat supports the following compilers:
Expat supports the following C99 compilers:
- GNU GCC >=4.5
- GNU GCC >=4.5 (for use from C) or GNU GCC >=4.8.1 (for use from C++)
- LLVM Clang >=3.5
- Microsoft Visual Studio >=16.0/2019 (rolling `${today} minus 5 years`)
@ -52,7 +52,7 @@ This approach leverages CMake's own [module `FindEXPAT`](https://cmake.org/cmake
Notice the *uppercase* `EXPAT` in the following example:
```cmake
cmake_minimum_required(VERSION 3.0) # or 3.10, see below
cmake_minimum_required(VERSION 3.10)
project(hello VERSION 1.0.0)
@ -62,12 +62,7 @@ add_executable(hello
hello.c
)
# a) for CMake >=3.10 (see CMake's FindEXPAT docs)
target_link_libraries(hello PUBLIC EXPAT::EXPAT)
# b) for CMake >=3.0
target_include_directories(hello PRIVATE ${EXPAT_INCLUDE_DIRS})
target_link_libraries(hello PUBLIC ${EXPAT_LIBRARIES})
```
### b) `find_package` with Config Mode
@ -85,7 +80,7 @@ or
Notice the *lowercase* `expat` in the following example:
```cmake
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.10)
project(hello VERSION 1.0.0)
@ -295,7 +290,7 @@ EXPAT_ENABLE_INSTALL:BOOL=ON
// Use /MT flag (static CRT) when compiling in MSVC
EXPAT_MSVC_STATIC_CRT:BOOL=OFF
// Build fuzzers via ossfuzz for the expat library
// Build fuzzers via OSS-Fuzz for the expat library
EXPAT_OSSFUZZ_BUILD:BOOL=OFF
// Build a shared expat library

@ -8,12 +8,12 @@ set(CMAKE_IMPORT_FILE_VERSION 1)
# Import target "expat::expat" for configuration "NoConfig"
set_property(TARGET expat::expat APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG)
set_target_properties(expat::expat PROPERTIES
IMPORTED_LOCATION_NOCONFIG "${_IMPORT_PREFIX}/@LIBDIR_BASENAME@/libexpat.@SO_MAJOR@.@SO_MINOR@.@SO_PATCH@.dylib"
IMPORTED_LOCATION_NOCONFIG "${_IMPORT_PREFIX}/@LIBDIR_BASENAME@/libexpat.@SO_MAJOR@.dylib"
IMPORTED_SONAME_NOCONFIG "@rpath/libexpat.@SO_MAJOR@.dylib"
)
list(APPEND _cmake_import_check_targets expat::expat )
list(APPEND _cmake_import_check_files_for_expat::expat "${_IMPORT_PREFIX}/@LIBDIR_BASENAME@/libexpat.@SO_MAJOR@.@SO_MINOR@.@SO_PATCH@.dylib" )
list(APPEND _cmake_import_check_files_for_expat::expat "${_IMPORT_PREFIX}/@LIBDIR_BASENAME@/libexpat.@SO_MAJOR@.dylib" )
# Commands beyond this point should not need to know the version.
set(CMAKE_IMPORT_FILE_VERSION)

@ -1,13 +1,13 @@
# Generated by CMake
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8)
message(FATAL_ERROR "CMake >= 2.8.0 required")
message(FATAL_ERROR "CMake >= 2.8.12 required")
endif()
if(CMAKE_VERSION VERSION_LESS "2.8.12")
message(FATAL_ERROR "CMake >= 2.8.12 required")
endif()
cmake_policy(PUSH)
cmake_policy(VERSION 2.8.12...3.28)
cmake_policy(VERSION 2.8.12...3.29)
#----------------------------------------------------------------
# Generated CMake target import file.
#----------------------------------------------------------------

File diff suppressed because it is too large Load Diff

@ -11,7 +11,7 @@ dnl Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
dnl Copyright (c) 2000-2005 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
dnl Copyright (c) 2001-2003 Greg Stein <gstein@users.sourceforge.net>
dnl Copyright (c) 2006-2012 Karl Waclawek <karl@waclawek.net>
dnl Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org>
dnl Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org>
dnl Copyright (c) 2017 S. P. Zeidler <spz@netbsd.org>
dnl Copyright (c) 2017 Stephen Groat <stephen@groat.us>
dnl Copyright (c) 2017-2020 Joe Orton <jorton@redhat.com>
@ -85,7 +85,7 @@ dnl If the API changes incompatibly set LIBAGE back to 0
dnl
LIBCURRENT=11 # sync
LIBREVISION=0 # with
LIBREVISION=1 # with
LIBAGE=10 # CMakeLists.txt!
AC_CONFIG_HEADERS([expat_config.h])

@ -2,7 +2,7 @@
## DO NOT EDIT - This file generated from ./build-aux/ltmain.in
## by inline-source v2019-02-19.15
# libtool (GNU libtool) 2.5.3
# libtool (GNU libtool) 2.5.4
# Provide generalized library-building support services.
# Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
@ -31,8 +31,8 @@
PROGRAM=libtool
PACKAGE=libtool
VERSION=2.5.3
package_revision=2.5.3
VERSION=2.5.4
package_revision=2.5.4
## ------ ##
@ -589,7 +589,7 @@ func_require_term_colors ()
# _G_HAVE_PLUSEQ_OP
# Can be empty, in which case the shell is probed, "yes" if += is
# useable or anything else if it does not work.
# usable or anything else if it does not work.
test -z "$_G_HAVE_PLUSEQ_OP" \
&& (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \
&& _G_HAVE_PLUSEQ_OP=yes
@ -739,7 +739,7 @@ eval 'func_dirname ()
# to NONDIR_REPLACEMENT.
# value returned in "$func_dirname_result"
# basename: Compute filename of FILE.
# value retuned in "$func_basename_result"
# value returned in "$func_basename_result"
# For efficiency, we do not delegate to the functions above but instead
# duplicate the functionality here.
eval 'func_dirname_and_basename ()
@ -2215,7 +2215,30 @@ func_version ()
# End:
# Set a version string.
scriptversion='(GNU libtool) 2.5.3'
scriptversion='(GNU libtool) 2.5.4'
# func_version
# ------------
# Echo version message to standard output and exit.
func_version ()
{
$debug_cmd
year=`date +%Y`
cat <<EOF
$progname $scriptversion
Copyright (C) $year Free Software Foundation, Inc.
License GPLv2+: GNU GPL version 2 or later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Originally written by Gordon Matzigkeit, 1996
(See AUTHORS for complete contributor listing)
EOF
exit $?
}
# func_echo ARG...
@ -2238,18 +2261,6 @@ func_echo ()
}
# func_warning ARG...
# -------------------
# Libtool warnings are not categorized, so override funclib.sh
# func_warning with this simpler definition.
func_warning ()
{
$debug_cmd
$warning_func ${1+"$@"}
}
## ---------------- ##
## Options parsing. ##
## ---------------- ##
@ -2264,11 +2275,15 @@ usage_message="Options:
--config show all configuration variables
--debug enable verbose shell tracing
-n, --dry-run display commands without modifying any files
--features display basic configuration information and exit
--features display basic configuration information
--finish use operation '--mode=finish'
--mode=MODE use operation mode MODE
--no-finish don't update shared library cache
--no-quiet, --no-silent print default informational messages
--no-warnings equivalent to '-Wnone'
--preserve-dup-deps don't remove duplicate dependency libraries
--quiet, --silent don't print informational messages
--reorder-cache=DIRS reorder shared library cache for preferred DIRS
--tag=TAG use configuration variables from tag TAG
-v, --verbose print more informational messages than default
--version print version information
@ -2306,7 +2321,7 @@ include the following information:
compiler: $LTCC
compiler flags: $LTCFLAGS
linker: $LD (gnu? $with_gnu_ld)
version: $progname (GNU libtool) 2.5.3
version: $progname $scriptversion
automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q`
autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q`
@ -2502,8 +2517,11 @@ libtool_options_prep ()
opt_dry_run=false
opt_help=false
opt_mode=
opt_reorder_cache=false
opt_preserve_dup_deps=false
opt_quiet=false
opt_finishing=true
opt_warning=
nonopt=
preserve_args=
@ -2593,14 +2611,18 @@ libtool_parse_options ()
clean|compile|execute|finish|install|link|relink|uninstall) ;;
# Catch anything else as an error
*) func_error "invalid argument for $_G_opt"
*) func_error "invalid argument '$1' for $_G_opt"
exit_cmd=exit
break
;;
esac
shift
;;
--no-finish)
opt_finishing=false
func_append preserve_args " $_G_opt"
;;
--no-silent|--no-quiet)
opt_quiet=false
func_append preserve_args " $_G_opt"
@ -2616,6 +2638,24 @@ libtool_parse_options ()
func_append preserve_args " $_G_opt"
;;
--reorder-cache)
opt_reorder_cache=true
shared_lib_dirs=$1
if test -n "$shared_lib_dirs"; then
case $1 in
# Must begin with /:
/*) ;;
# Catch anything else as an error (relative paths)
*) func_error "invalid argument '$1' for $_G_opt"
func_error "absolute paths are required for $_G_opt"
exit_cmd=exit
;;
esac
fi
shift
;;
--silent|--quiet)
opt_quiet=:
opt_verbose=false
@ -2652,6 +2692,18 @@ libtool_parse_options ()
func_add_hook func_parse_options libtool_parse_options
# func_warning ARG...
# -------------------
# Libtool warnings are not categorized, so override funclib.sh
# func_warning with this simpler definition.
func_warning ()
{
if $opt_warning; then
$debug_cmd
$warning_func ${1+"$@"}
fi
}
# libtool_validate_options [ARG]...
# ---------------------------------
@ -3181,6 +3233,15 @@ func_convert_path_front_back_pathsep ()
# end func_convert_path_front_back_pathsep
# func_convert_delimited_path PATH ORIG_DELIMITER NEW_DELIMITER
# Replaces a delimiter for a given path.
func_convert_delimited_path ()
{
converted_path=`$ECHO "$1" | $SED "s#$2#$3#g"`
}
# end func_convert_delimited_path
##################################################
# $build to $host FILE NAME CONVERSION FUNCTIONS #
##################################################
@ -3515,6 +3576,65 @@ func_dll_def_p ()
}
# func_reorder_shared_lib_cache DIRS
# Reorder the shared library cache by unconfiguring previous shared library cache
# and configuring preferred search directories before previous search directories.
# Previous shared library cache: /usr/lib /usr/local/lib
# Preferred search directories: /tmp/testing
# Reordered shared library cache: /tmp/testing /usr/lib /usr/local/lib
func_reorder_shared_lib_cache ()
{
$debug_cmd
case $host_os in
openbsd*)
get_search_directories=`PATH="$PATH:/sbin" ldconfig -r | $GREP "search directories" | $SED "s#.*search directories:\ ##g"`
func_convert_delimited_path "$get_search_directories" ':' '\ '
save_search_directories=$converted_path
func_convert_delimited_path "$1" ':' '\ '
# Ensure directories exist
for dir in $converted_path; do
# Ensure each directory is an absolute path
case $dir in
/*) ;;
*) func_error "Directory '$dir' is not an absolute path"
exit $EXIT_FAILURE ;;
esac
# Ensure no trailing slashes
func_stripname '' '/' "$dir"
dir=$func_stripname_result
if test -d "$dir"; then
if test -n "$preferred_search_directories"; then
preferred_search_directories="$preferred_search_directories $dir"
else
preferred_search_directories=$dir
fi
else
func_error "Directory '$dir' does not exist"
exit $EXIT_FAILURE
fi
done
PATH="$PATH:/sbin" ldconfig -U $save_search_directories
PATH="$PATH:/sbin" ldconfig -m $preferred_search_directories $save_search_directories
get_search_directories=`PATH="$PATH:/sbin" ldconfig -r | $GREP "search directories" | $SED "s#.*search directories:\ ##g"`
func_convert_delimited_path "$get_search_directories" ':' '\ '
reordered_search_directories=$converted_path
$ECHO "Original: $save_search_directories"
$ECHO "Reordered: $reordered_search_directories"
exit $EXIT_SUCCESS
;;
*)
func_error "--reorder-cache is not supported for host_os=$host_os."
exit $EXIT_FAILURE
;;
esac
}
# end func_reorder_shared_lib_cache
# func_mode_compile arg...
func_mode_compile ()
{
@ -4087,6 +4207,12 @@ if $opt_help; then
fi
# If option '--reorder-cache', reorder the shared library cache and exit.
if $opt_reorder_cache; then
func_reorder_shared_lib_cache $shared_lib_dirs
fi
# func_mode_execute arg...
func_mode_execute ()
{
@ -4271,7 +4397,7 @@ func_mode_finish ()
fi
fi
if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
if test -n "$finish_cmds$finish_eval" && test -n "$libdirs" && $opt_finishing; then
for libdir in $libdirs; do
if test -n "$finish_cmds"; then
# Do each command in the finish commands.
@ -4296,6 +4422,12 @@ func_mode_finish ()
for libdir in $libdirs; do
$ECHO " $libdir"
done
if test "false" = "$opt_finishing"; then
echo
echo "NOTE: finish_cmds were not executed during testing, so you must"
echo "manually run ldconfig to add a given test directory, LIBDIR, to"
echo "the search path for generated executables."
fi
echo
echo "If you ever happen to want to link against installed libraries"
echo "in a given directory, LIBDIR, you must either use libtool, and"
@ -4532,8 +4664,15 @@ func_mode_install ()
func_append dir "$objdir"
if test -n "$relink_command"; then
# Strip any trailing slash from the destination.
func_stripname '' '/' "$libdir"
destlibdir=$func_stripname_result
func_stripname '' '/' "$destdir"
s_destdir=$func_stripname_result
# Determine the prefix the user has applied to our future dir.
inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"`
inst_prefix_dir=`$ECHO "X$s_destdir" | $Xsed -e "s%$destlibdir\$%%"`
# Don't allow the user to place us outside of our expected
# location b/c this prevents finding dependent libraries that
@ -6782,6 +6921,7 @@ func_mode_link ()
finalize_command=$nonopt
compile_rpath=
compile_rpath_tail=
finalize_rpath=
compile_shlibpath=
finalize_shlibpath=
@ -7337,7 +7477,8 @@ func_mode_link ()
# Tru64 UNIX uses -model [arg] to determine the layout of C++
# classes, name mangling, and exception handling.
# Darwin uses the -arch flag to determine output architecture.
-model|-arch|-isysroot|--sysroot)
# -q <option> for IBM XL C/C++ compiler.
-model|-arch|-isysroot|--sysroot|-q)
func_append compiler_flags " $arg"
func_append compile_command " $arg"
func_append finalize_command " $arg"
@ -8433,10 +8574,11 @@ func_mode_link ()
case " $sys_lib_dlsearch_path " in
*" $absdir "*) ;;
*)
case "$compile_rpath " in
case "$compile_rpath$compile_rpath_tail " in
*" $absdir "*) ;;
*) case $absdir in
"$progdir/"*) func_append compile_rpath " $absdir" ;;
*) func_append compile_rpath_tail " $absdir" ;;
esac
esac
;;
@ -8509,10 +8651,11 @@ func_mode_link ()
case " $sys_lib_dlsearch_path " in
*" $absdir "*) ;;
*)
case "$compile_rpath " in
case "$compile_rpath$compile_rpath_tail " in
*" $absdir "*) ;;
*) case $absdir in
"$progdir/"*) func_append compile_rpath " $absdir" ;;
*) func_append compile_rpath_tail " $absdir" ;;
esac
esac
;;
@ -8588,6 +8731,7 @@ func_mode_link ()
case $host in
*-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;;
*-*-sysv4*uw2*) add_dir=-L$dir ;;
*-*-emscripten*) add_dir=-L$dir ;;
*-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
*-*-unixware7*) add_dir=-L$dir ;;
*-*-darwin* )
@ -8876,6 +9020,8 @@ func_mode_link ()
done # for deplib in $libs
func_append temp_rpath "$temp_rpath_tail"
func_append compile_rpath "$compile_rpath_tail"
if test link = "$pass"; then
if test prog = "$linkmode"; then
compile_deplibs="$new_inherited_linker_flags $compile_deplibs"
@ -9163,6 +9309,9 @@ func_mode_link ()
revision=$number_minor
lt_irix_increment=no
;;
*)
func_fatal_configuration "$modename: unknown library version type '$version_type'"
;;
esac
;;
no)
@ -10059,20 +10208,7 @@ func_mode_link ()
last_robj=
k=1
if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then
output=$output_objdir/$output_la.lnkscript
func_verbose "creating GNU ld script: $output"
echo 'INPUT (' > $output
for obj in $save_libobjs
do
func_to_tool_file "$obj"
$ECHO "$func_to_tool_file_result" >> $output
done
echo ')' >> $output
func_append delfiles " $output"
func_to_tool_file "$output"
output=$func_to_tool_file_result
elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then
if test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then
output=$output_objdir/$output_la.lnk
func_verbose "creating linker input file list: $output"
: > $output
@ -10091,6 +10227,19 @@ func_mode_link ()
func_append delfiles " $output"
func_to_tool_file "$output"
output=$firstobj\"$file_list_spec$func_to_tool_file_result\"
elif test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then
output=$output_objdir/$output_la.lnkscript
func_verbose "creating GNU ld script: $output"
echo 'INPUT (' > $output
for obj in $save_libobjs
do
func_to_tool_file "$obj"
$ECHO "$func_to_tool_file_result" >> $output
done
echo ')' >> $output
func_append delfiles " $output"
func_to_tool_file "$output"
output=$func_to_tool_file_result
else
if test -n "$save_libobjs"; then
func_verbose "creating reloadable object files..."

@ -14,7 +14,7 @@
Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
Copyright (c) 2000-2004 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2002-2012 Karl Waclawek <karl@waclawek.net>
Copyright (c) 2017-2024 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2017-2025 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2017 Jakub Wilk <jwilk@jwilk.net>
Copyright (c) 2021 Tomas Korbar <tkorbar@redhat.com>
Copyright (c) 2021 Nicolas Cavallari <nicolas.cavallari@green-communications.fr>
@ -52,7 +52,7 @@
<div>
<h1>
The Expat XML Parser
<small>Release 2.6.4</small>
<small>Release 2.7.0</small>
</h1>
</div>
<div class="content">
@ -1267,6 +1267,11 @@ call-backs, except when parsing an external parameter entity and
<code>XML_STATUS_ERROR</code> otherwise. The possible error codes
are:</p>
<dl>
<dt><code>XML_ERROR_NOT_STARTED</code></dt>
<dd>
when stopping or suspending a parser before it has started,
added in Expat 2.6.4.
</dd>
<dt><code>XML_ERROR_SUSPENDED</code></dt>
<dd>when suspending an already suspended parser.</dd>
<dt><code>XML_ERROR_FINISHED</code></dt>

@ -5,7 +5,7 @@
\\$2 \(la\\$1\(ra\\$3
..
.if \n(.g .mso www.tmac
.TH XMLWF 1 "November 6, 2024" "" ""
.TH XMLWF 1 "March 13, 2025" "" ""
.SH NAME
xmlwf \- Determines if an XML document is well-formed
.SH SYNOPSIS

@ -9,7 +9,7 @@
Copyright (c) 2001 Scott Bronson <bronson@rinspin.com>
Copyright (c) 2002-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2009 Karl Waclawek <karl@waclawek.net>
Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2016 Ardo van Rangelrooij <ardo@debian.org>
Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
Copyright (c) 2020 Joe Orton <jorton@redhat.com>
@ -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>November 6, 2024</date>">
<!ENTITY dhdate "<date>March 13, 2025</date>">
<!-- Please adjust this^^ date whenever cutting a new release. -->
<!ENTITY dhsection "<manvolnum>1</manvolnum>">
<!ENTITY dhemail "<email>bronson@rinspin.com</email>">

@ -83,7 +83,7 @@
#define PACKAGE_NAME "expat"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "expat 2.6.4"
#define PACKAGE_STRING "expat 2.7.0"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "expat"
@ -92,7 +92,7 @@
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "2.6.4"
#define PACKAGE_VERSION "2.7.0"
/* Define to 1 if all of the C90 standard headers exist (not just the ones
required in a freestanding environment). This macro is provided for
@ -100,7 +100,7 @@
#define STDC_HEADERS 1
/* Version number of package */
#define VERSION "2.6.4"
#define VERSION "2.7.0"
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */

@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,

@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,

@ -11,7 +11,7 @@
Copyright (c) 2000-2005 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2001-2002 Greg Stein <gstein@users.sourceforge.net>
Copyright (c) 2002-2016 Karl Waclawek <karl@waclawek.net>
Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2016 Cristian Rodríguez <crrodriguez@opensuse.org>
Copyright (c) 2016 Thomas Beutlich <tc@tbeu.de>
Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
@ -1067,8 +1067,8 @@ XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled);
See https://semver.org
*/
#define XML_MAJOR_VERSION 2
#define XML_MINOR_VERSION 6
#define XML_MICRO_VERSION 4
#define XML_MINOR_VERSION 7
#define XML_MICRO_VERSION 0
#ifdef __cplusplus
}

@ -1,4 +1,4 @@
/* c5625880f4bf417c1463deee4eb92d86ff413f802048621c57e25fe483eb59e4 (2.6.4+)
/* 7d6840a33c250b74adb0ba295d6ec818dccebebaffc8c3ed27d0b29c28adbeb3 (2.7.0+)
__ __ _
___\ \/ /_ __ __ _| |_
/ _ \\ /| '_ \ / _` | __|
@ -13,7 +13,7 @@
Copyright (c) 2002-2016 Karl Waclawek <karl@waclawek.net>
Copyright (c) 2005-2009 Steven Solie <steven@solie.ca>
Copyright (c) 2016 Eric Rahm <erahm@mozilla.com>
Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2016 Gaurav <g.gupta@samsung.com>
Copyright (c) 2016 Thomas Beutlich <tc@tbeu.de>
Copyright (c) 2016 Gustavo Grieco <gustavo.grieco@imag.fr>
@ -39,7 +39,7 @@
Copyright (c) 2022 Sean McBride <sean@rogue-research.com>
Copyright (c) 2023 Owain Davies <owaind@bath.edu>
Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild@sony.com>
Copyright (c) 2024 Berkay Eren Ürün <berkay.ueruen@siemens.com>
Copyright (c) 2024-2025 Berkay Eren Ürün <berkay.ueruen@siemens.com>
Copyright (c) 2024 Hanno Böck <hanno@gentoo.org>
Licensed under the MIT license:
@ -325,6 +325,10 @@ typedef struct {
const XML_Char *publicId;
const XML_Char *notation;
XML_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
entities are processed and closed */
XML_Bool is_param;
XML_Bool is_internal; /* true if declared in internal subset outside PE */
} ENTITY;
@ -415,6 +419,12 @@ typedef struct {
int *scaffIndex;
} DTD;
enum EntityType {
ENTITY_INTERNAL,
ENTITY_ATTRIBUTE,
ENTITY_VALUE,
};
typedef struct open_internal_entity {
const char *internalEventPtr;
const char *internalEventEndPtr;
@ -422,6 +432,7 @@ typedef struct open_internal_entity {
ENTITY *entity;
int startTagLevel;
XML_Bool betweenDecl; /* WFC: PE Between Declarations */
enum EntityType type;
} OPEN_INTERNAL_ENTITY;
enum XML_Account {
@ -481,8 +492,8 @@ static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc,
const char *next, const char **nextPtr,
XML_Bool haveMore, XML_Bool allowClosingDoctype,
enum XML_Account account);
static enum XML_Error processInternalEntity(XML_Parser parser, ENTITY *entity,
XML_Bool betweenDecl);
static enum XML_Error processEntity(XML_Parser parser, ENTITY *entity,
XML_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,
@ -513,16 +524,20 @@ static enum XML_Error storeAttributeValue(XML_Parser parser,
const char *ptr, const char *end,
STRING_POOL *pool,
enum XML_Account account);
static enum XML_Error appendAttributeValue(XML_Parser parser,
const ENCODING *enc,
XML_Bool isCdata, const char *ptr,
const char *end, STRING_POOL *pool,
enum XML_Account account);
static enum XML_Error
appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
const char *ptr, const char *end, STRING_POOL *pool,
enum XML_Account account, const char **nextPtr);
static ATTRIBUTE_ID *getAttributeId(XML_Parser parser, const ENCODING *enc,
const char *start, const char *end);
static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType);
#if XML_GE == 1
static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc,
const char *start, const char *end,
enum XML_Account account,
const char **nextPtr);
static enum XML_Error callStoreEntityValue(XML_Parser parser,
const ENCODING *enc,
const char *start, const char *end,
enum XML_Account account);
#else
@ -709,6 +724,10 @@ struct XML_ParserStruct {
const char *m_positionPtr;
OPEN_INTERNAL_ENTITY *m_openInternalEntities;
OPEN_INTERNAL_ENTITY *m_freeInternalEntities;
OPEN_INTERNAL_ENTITY *m_openAttributeEntities;
OPEN_INTERNAL_ENTITY *m_freeAttributeEntities;
OPEN_INTERNAL_ENTITY *m_openValueEntities;
OPEN_INTERNAL_ENTITY *m_freeValueEntities;
XML_Bool m_defaultExpandInternalEntities;
int m_tagLevel;
ENTITY *m_declEntity;
@ -756,6 +775,7 @@ struct XML_ParserStruct {
ACCOUNTING m_accounting;
ENTITY_STATS m_entity_stats;
#endif
XML_Bool m_reenter;
};
#define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s)))
@ -1028,7 +1048,29 @@ callProcessor(XML_Parser parser, const char *start, const char *end,
#if defined(XML_TESTING)
g_bytesScanned += (unsigned)have_now;
#endif
const enum XML_Error ret = parser->m_processor(parser, start, end, endPtr);
// Run in a loop to eliminate dangerous recursion depths
enum XML_Error ret;
*endPtr = start;
while (1) {
// Use endPtr as the new start in each iteration, since it will
// be set to the next start point by m_processor.
ret = parser->m_processor(parser, *endPtr, end, endPtr);
// Make parsing status (and in particular XML_SUSPENDED) take
// precedence over re-enter flag when they disagree
if (parser->m_parsingStatus.parsing != XML_PARSING) {
parser->m_reenter = XML_FALSE;
}
if (! parser->m_reenter) {
break;
}
parser->m_reenter = XML_FALSE;
if (ret != XML_ERROR_NONE)
return ret;
}
if (ret == XML_ERROR_NONE) {
// if we consumed nothing, remember what we had on this parse attempt.
if (*endPtr == start) {
@ -1139,6 +1181,8 @@ parserCreate(const XML_Char *encodingName,
parser->m_freeBindingList = NULL;
parser->m_freeTagList = NULL;
parser->m_freeInternalEntities = NULL;
parser->m_freeAttributeEntities = NULL;
parser->m_freeValueEntities = NULL;
parser->m_groupSize = 0;
parser->m_groupConnector = NULL;
@ -1241,6 +1285,8 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) {
parser->m_eventEndPtr = NULL;
parser->m_positionPtr = NULL;
parser->m_openInternalEntities = NULL;
parser->m_openAttributeEntities = NULL;
parser->m_openValueEntities = NULL;
parser->m_defaultExpandInternalEntities = XML_TRUE;
parser->m_tagLevel = 0;
parser->m_tagStack = NULL;
@ -1251,6 +1297,8 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) {
parser->m_unknownEncodingData = NULL;
parser->m_parentParser = NULL;
parser->m_parsingStatus.parsing = XML_INITIALIZED;
// Reentry can only be triggered inside m_processor calls
parser->m_reenter = XML_FALSE;
#ifdef XML_DTD
parser->m_isParamEntity = XML_FALSE;
parser->m_useForeignDTD = XML_FALSE;
@ -1310,6 +1358,24 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) {
openEntity->next = parser->m_freeInternalEntities;
parser->m_freeInternalEntities = openEntity;
}
/* move m_openAttributeEntities to m_freeAttributeEntities (i.e. same task but
* for attributes) */
openEntityList = parser->m_openAttributeEntities;
while (openEntityList) {
OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
openEntityList = openEntity->next;
openEntity->next = parser->m_freeAttributeEntities;
parser->m_freeAttributeEntities = openEntity;
}
/* move m_openValueEntities to m_freeValueEntities (i.e. same task but
* for value entities) */
openEntityList = parser->m_openValueEntities;
while (openEntityList) {
OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
openEntityList = openEntity->next;
openEntity->next = parser->m_freeValueEntities;
parser->m_freeValueEntities = openEntity;
}
moveToFreeBindingList(parser, parser->m_inheritedBindings);
FREE(parser, parser->m_unknownEncodingMem);
if (parser->m_unknownEncodingRelease)
@ -1323,6 +1389,19 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) {
return XML_TRUE;
}
static XML_Bool
parserBusy(XML_Parser parser) {
switch (parser->m_parsingStatus.parsing) {
case XML_PARSING:
case XML_SUSPENDED:
return XML_TRUE;
case XML_INITIALIZED:
case XML_FINISHED:
default:
return XML_FALSE;
}
}
enum XML_Status XMLCALL
XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) {
if (parser == NULL)
@ -1331,8 +1410,7 @@ XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) {
XXX There's no way for the caller to determine which of the
XXX possible error cases caused the XML_STATUS_ERROR return.
*/
if (parser->m_parsingStatus.parsing == XML_PARSING
|| parser->m_parsingStatus.parsing == XML_SUSPENDED)
if (parserBusy(parser))
return XML_STATUS_ERROR;
/* Get rid of any previous encoding name */
@ -1569,7 +1647,34 @@ XML_ParserFree(XML_Parser parser) {
entityList = entityList->next;
FREE(parser, openEntity);
}
/* free m_openAttributeEntities and m_freeAttributeEntities */
entityList = parser->m_openAttributeEntities;
for (;;) {
OPEN_INTERNAL_ENTITY *openEntity;
if (entityList == NULL) {
if (parser->m_freeAttributeEntities == NULL)
break;
entityList = parser->m_freeAttributeEntities;
parser->m_freeAttributeEntities = NULL;
}
openEntity = entityList;
entityList = entityList->next;
FREE(parser, openEntity);
}
/* free m_openValueEntities and m_freeValueEntities */
entityList = parser->m_openValueEntities;
for (;;) {
OPEN_INTERNAL_ENTITY *openEntity;
if (entityList == NULL) {
if (parser->m_freeValueEntities == NULL)
break;
entityList = parser->m_freeValueEntities;
parser->m_freeValueEntities = NULL;
}
openEntity = entityList;
entityList = entityList->next;
FREE(parser, openEntity);
}
destroyBindings(parser->m_freeBindingList, parser);
destroyBindings(parser->m_inheritedBindings, parser);
poolDestroy(&parser->m_tempPool);
@ -1611,8 +1716,7 @@ XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD) {
return XML_ERROR_INVALID_ARGUMENT;
#ifdef XML_DTD
/* block after XML_Parse()/XML_ParseBuffer() has been called */
if (parser->m_parsingStatus.parsing == XML_PARSING
|| parser->m_parsingStatus.parsing == XML_SUSPENDED)
if (parserBusy(parser))
return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
parser->m_useForeignDTD = useDTD;
return XML_ERROR_NONE;
@ -1627,8 +1731,7 @@ XML_SetReturnNSTriplet(XML_Parser parser, int do_nst) {
if (parser == NULL)
return;
/* block after XML_Parse()/XML_ParseBuffer() has been called */
if (parser->m_parsingStatus.parsing == XML_PARSING
|| parser->m_parsingStatus.parsing == XML_SUSPENDED)
if (parserBusy(parser))
return;
parser->m_ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
}
@ -1897,8 +2000,7 @@ XML_SetParamEntityParsing(XML_Parser parser,
if (parser == NULL)
return 0;
/* block after XML_Parse()/XML_ParseBuffer() has been called */
if (parser->m_parsingStatus.parsing == XML_PARSING
|| parser->m_parsingStatus.parsing == XML_SUSPENDED)
if (parserBusy(parser))
return 0;
#ifdef XML_DTD
parser->m_paramEntityParsing = peParsing;
@ -1915,8 +2017,7 @@ XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) {
if (parser->m_parentParser)
return XML_SetHashSalt(parser->m_parentParser, hash_salt);
/* block after XML_Parse()/XML_ParseBuffer() has been called */
if (parser->m_parsingStatus.parsing == XML_PARSING
|| parser->m_parsingStatus.parsing == XML_SUSPENDED)
if (parserBusy(parser))
return 0;
parser->m_hash_secret_salt = hash_salt;
return 1;
@ -2230,6 +2331,11 @@ XML_GetBuffer(XML_Parser parser, int len) {
return parser->m_bufferEnd;
}
static void
triggerReenter(XML_Parser parser) {
parser->m_reenter = XML_TRUE;
}
enum XML_Status XMLCALL
XML_StopParser(XML_Parser parser, XML_Bool resumable) {
if (parser == NULL)
@ -2704,8 +2810,9 @@ static enum XML_Error PTRCALL
contentProcessor(XML_Parser parser, const char *start, const char *end,
const char **endPtr) {
enum XML_Error result = doContent(
parser, 0, parser->m_encoding, start, end, endPtr,
(XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_ACCOUNT_DIRECT);
parser, parser->m_parentParser ? 1 : 0, parser->m_encoding, start, end,
endPtr, (XML_Bool)! parser->m_parsingStatus.finalBuffer,
XML_ACCOUNT_DIRECT);
if (result == XML_ERROR_NONE) {
if (! storeRawNames(parser))
return XML_ERROR_NO_MEMORY;
@ -2793,6 +2900,11 @@ externalEntityInitProcessor3(XML_Parser parser, const char *start,
return XML_ERROR_NONE;
case XML_FINISHED:
return XML_ERROR_ABORTED;
case XML_PARSING:
if (parser->m_reenter) {
return XML_ERROR_UNEXPECTED_STATE; // LCOV_EXCL_LINE
}
/* Fall through */
default:
start = next;
}
@ -2966,7 +3078,7 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
reportDefault(parser, enc, s, next);
break;
}
result = processInternalEntity(parser, entity, XML_FALSE);
result = processEntity(parser, entity, XML_FALSE, ENTITY_INTERNAL);
if (result != XML_ERROR_NONE)
return result;
} else if (parser->m_externalEntityRefHandler) {
@ -3092,7 +3204,9 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
}
if ((parser->m_tagLevel == 0)
&& (parser->m_parsingStatus.parsing != XML_FINISHED)) {
if (parser->m_parsingStatus.parsing == XML_SUSPENDED)
if (parser->m_parsingStatus.parsing == XML_SUSPENDED
|| (parser->m_parsingStatus.parsing == XML_PARSING
&& parser->m_reenter))
parser->m_processor = epilogProcessor;
else
return epilogProcessor(parser, next, end, nextPtr);
@ -3153,7 +3267,9 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
}
if ((parser->m_tagLevel == 0)
&& (parser->m_parsingStatus.parsing != XML_FINISHED)) {
if (parser->m_parsingStatus.parsing == XML_SUSPENDED)
if (parser->m_parsingStatus.parsing == XML_SUSPENDED
|| (parser->m_parsingStatus.parsing == XML_PARSING
&& parser->m_reenter))
parser->m_processor = epilogProcessor;
else
return epilogProcessor(parser, next, end, nextPtr);
@ -3293,6 +3409,12 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
return XML_ERROR_NONE;
case XML_FINISHED:
return XML_ERROR_ABORTED;
case XML_PARSING:
if (parser->m_reenter) {
*nextPtr = next;
return XML_ERROR_NONE;
}
/* Fall through */
default:;
}
}
@ -4217,6 +4339,11 @@ doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
return XML_ERROR_NONE;
case XML_FINISHED:
return XML_ERROR_ABORTED;
case XML_PARSING:
if (parser->m_reenter) {
return XML_ERROR_UNEXPECTED_STATE; // LCOV_EXCL_LINE
}
/* Fall through */
default:;
}
}
@ -4549,7 +4676,7 @@ entityValueInitProcessor(XML_Parser parser, const char *s, const char *end,
}
/* found end of entity value - can store it now */
return storeEntityValue(parser, parser->m_encoding, s, end,
XML_ACCOUNT_DIRECT);
XML_ACCOUNT_DIRECT, NULL);
} else if (tok == XML_TOK_XML_DECL) {
enum XML_Error result;
result = processXmlDecl(parser, 0, start, next);
@ -4676,7 +4803,7 @@ entityValueProcessor(XML_Parser parser, const char *s, const char *end,
break;
}
/* found end of entity value - can store it now */
return storeEntityValue(parser, enc, s, end, XML_ACCOUNT_DIRECT);
return storeEntityValue(parser, enc, s, end, XML_ACCOUNT_DIRECT, NULL);
}
start = next;
}
@ -5119,9 +5246,9 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
#if XML_GE == 1
// This will store the given replacement text in
// parser->m_declEntity->textPtr.
enum XML_Error result
= storeEntityValue(parser, enc, s + enc->minBytesPerChar,
next - enc->minBytesPerChar, XML_ACCOUNT_NONE);
enum XML_Error result = callStoreEntityValue(
parser, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar,
XML_ACCOUNT_NONE);
if (parser->m_declEntity) {
parser->m_declEntity->textPtr = poolStart(&dtd->entityValuePool);
parser->m_declEntity->textLen
@ -5546,7 +5673,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
enum XML_Error result;
XML_Bool betweenDecl
= (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
result = processInternalEntity(parser, entity, betweenDecl);
result = processEntity(parser, entity, betweenDecl, ENTITY_INTERNAL);
if (result != XML_ERROR_NONE)
return result;
handleDefault = XML_FALSE;
@ -5751,6 +5878,12 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
return XML_ERROR_NONE;
case XML_FINISHED:
return XML_ERROR_ABORTED;
case XML_PARSING:
if (parser->m_reenter) {
*nextPtr = next;
return XML_ERROR_NONE;
}
/* Fall through */
default:
s = next;
tok = XmlPrologTok(enc, s, end, &next);
@ -5825,21 +5958,49 @@ epilogProcessor(XML_Parser parser, const char *s, const char *end,
return XML_ERROR_NONE;
case XML_FINISHED:
return XML_ERROR_ABORTED;
case XML_PARSING:
if (parser->m_reenter) {
return XML_ERROR_UNEXPECTED_STATE; // LCOV_EXCL_LINE
}
/* Fall through */
default:;
}
}
}
static enum XML_Error
processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) {
const char *textStart, *textEnd;
const char *next;
enum XML_Error result;
OPEN_INTERNAL_ENTITY *openEntity;
processEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl,
enum EntityType type) {
OPEN_INTERNAL_ENTITY *openEntity, **openEntityList, **freeEntityList;
switch (type) {
case ENTITY_INTERNAL:
parser->m_processor = internalEntityProcessor;
openEntityList = &parser->m_openInternalEntities;
freeEntityList = &parser->m_freeInternalEntities;
break;
case ENTITY_ATTRIBUTE:
openEntityList = &parser->m_openAttributeEntities;
freeEntityList = &parser->m_freeAttributeEntities;
break;
case ENTITY_VALUE:
openEntityList = &parser->m_openValueEntities;
freeEntityList = &parser->m_freeValueEntities;
break;
/* default case serves merely as a safety net in case of a
* wrong entityType. Therefore we exclude the following lines
* from the test coverage.
*
* LCOV_EXCL_START
*/
default:
// Should not reach here
assert(0);
/* LCOV_EXCL_STOP */
}
if (parser->m_freeInternalEntities) {
openEntity = parser->m_freeInternalEntities;
parser->m_freeInternalEntities = openEntity->next;
if (*freeEntityList) {
openEntity = *freeEntityList;
*freeEntityList = openEntity->next;
} else {
openEntity
= (OPEN_INTERNAL_ENTITY *)MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY));
@ -5847,55 +6008,34 @@ processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) {
return XML_ERROR_NO_MEMORY;
}
entity->open = XML_TRUE;
entity->hasMore = XML_TRUE;
#if XML_GE == 1
entityTrackingOnOpen(parser, entity, __LINE__);
#endif
entity->processed = 0;
openEntity->next = parser->m_openInternalEntities;
parser->m_openInternalEntities = openEntity;
openEntity->next = *openEntityList;
*openEntityList = openEntity;
openEntity->entity = entity;
openEntity->type = type;
openEntity->startTagLevel = parser->m_tagLevel;
openEntity->betweenDecl = betweenDecl;
openEntity->internalEventPtr = NULL;
openEntity->internalEventEndPtr = NULL;
textStart = (const char *)entity->textPtr;
textEnd = (const char *)(entity->textPtr + entity->textLen);
/* Set a safe default value in case 'next' does not get set */
next = textStart;
if (entity->is_param) {
int tok
= XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
tok, next, &next, XML_FALSE, XML_FALSE,
XML_ACCOUNT_ENTITY_EXPANSION);
} else {
result = doContent(parser, parser->m_tagLevel, parser->m_internalEncoding,
textStart, textEnd, &next, XML_FALSE,
XML_ACCOUNT_ENTITY_EXPANSION);
}
if (result == XML_ERROR_NONE) {
if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
entity->processed = (int)(next - textStart);
parser->m_processor = internalEntityProcessor;
} else if (parser->m_openInternalEntities->entity == entity) {
#if XML_GE == 1
entityTrackingOnClose(parser, entity, __LINE__);
#endif /* XML_GE == 1 */
entity->open = XML_FALSE;
parser->m_openInternalEntities = openEntity->next;
/* put openEntity back in list of free instances */
openEntity->next = parser->m_freeInternalEntities;
parser->m_freeInternalEntities = openEntity;
// Only internal entities make use of the reenter flag
// therefore no need to set it for other entity types
if (type == ENTITY_INTERNAL) {
triggerReenter(parser);
}
}
return result;
return XML_ERROR_NONE;
}
static enum XML_Error PTRCALL
internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
const char **nextPtr) {
UNUSED_P(s);
UNUSED_P(end);
UNUSED_P(nextPtr);
ENTITY *entity;
const char *textStart, *textEnd;
const char *next;
@ -5905,6 +6045,9 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
return XML_ERROR_UNEXPECTED_STATE;
entity = openEntity->entity;
// This will return early
if (entity->hasMore) {
textStart = ((const char *)entity->textPtr) + entity->processed;
textEnd = (const char *)(entity->textPtr + entity->textLen);
/* Set a safe default value in case 'next' does not get set */
@ -5914,7 +6057,7 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
int tok
= XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
tok, next, &next, XML_FALSE, XML_TRUE,
tok, next, &next, XML_FALSE, XML_FALSE,
XML_ACCOUNT_ENTITY_EXPANSION);
} else {
result = doContent(parser, openEntity->startTagLevel,
@ -5924,49 +6067,45 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
if (result != XML_ERROR_NONE)
return result;
if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
// Check if entity is complete, if not, mark down how much of it is
// processed
if (textEnd != next
&& (parser->m_parsingStatus.parsing == XML_SUSPENDED
|| (parser->m_parsingStatus.parsing == XML_PARSING
&& parser->m_reenter))) {
entity->processed = (int)(next - (const char *)entity->textPtr);
return result;
}
// 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;
triggerReenter(parser);
return result;
} // End of entity processing, "if" block will return here
// Remove fully processed openEntity from open entity list.
#if XML_GE == 1
entityTrackingOnClose(parser, entity, __LINE__);
#endif
// openEntity is m_openInternalEntities' head, as we set it at the start of
// this function and we skipped doProlog and doContent calls with hasMore set
// to false. This means we can directly remove the head of
// m_openInternalEntities
assert(parser->m_openInternalEntities == openEntity);
entity->open = XML_FALSE;
parser->m_openInternalEntities = openEntity->next;
parser->m_openInternalEntities = parser->m_openInternalEntities->next;
/* put openEntity back in list of free instances */
openEntity->next = parser->m_freeInternalEntities;
parser->m_freeInternalEntities = openEntity;
// If there are more open entities we want to stop right here and have the
// upcoming call to XML_ResumeParser continue with entity content, or it would
// be ignored altogether.
if (parser->m_openInternalEntities != NULL
&& parser->m_parsingStatus.parsing == XML_SUSPENDED) {
return XML_ERROR_NONE;
}
if (entity->is_param) {
int tok;
parser->m_processor = prologProcessor;
tok = XmlPrologTok(parser->m_encoding, s, end, &next);
return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
(XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE,
XML_ACCOUNT_DIRECT);
} else {
parser->m_processor = contentProcessor;
/* see externalEntityContentProcessor vs contentProcessor */
result = doContent(parser, parser->m_parentParser ? 1 : 0,
parser->m_encoding, s, end, nextPtr,
(XML_Bool)! parser->m_parsingStatus.finalBuffer,
XML_ACCOUNT_DIRECT);
if (result == XML_ERROR_NONE) {
if (! storeRawNames(parser))
return XML_ERROR_NO_MEMORY;
}
return result;
if (parser->m_openInternalEntities == NULL) {
parser->m_processor = entity->is_param ? prologProcessor : contentProcessor;
}
triggerReenter(parser);
return XML_ERROR_NONE;
}
static enum XML_Error PTRCALL
@ -5982,8 +6121,70 @@ static enum XML_Error
storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
const char *ptr, const char *end, STRING_POOL *pool,
enum XML_Account account) {
enum XML_Error result
= appendAttributeValue(parser, enc, isCdata, ptr, end, pool, account);
const char *next = ptr;
enum XML_Error result = XML_ERROR_NONE;
while (1) {
if (! parser->m_openAttributeEntities) {
result = appendAttributeValue(parser, enc, isCdata, next, end, pool,
account, &next);
} else {
OPEN_INTERNAL_ENTITY *const openEntity = parser->m_openAttributeEntities;
if (! openEntity)
return XML_ERROR_UNEXPECTED_STATE;
ENTITY *const entity = openEntity->entity;
const char *const textStart
= ((const char *)entity->textPtr) + entity->processed;
const char *const textEnd
= (const char *)(entity->textPtr + entity->textLen);
/* Set a safe default value in case 'next' does not get set */
const char *nextInEntity = textStart;
if (entity->hasMore) {
result = appendAttributeValue(
parser, parser->m_internalEncoding, isCdata, textStart, textEnd,
pool, XML_ACCOUNT_ENTITY_EXPANSION, &nextInEntity);
if (result != XML_ERROR_NONE)
break;
// Check if entity is complete, if not, mark down how much of it is
// processed. A XML_SUSPENDED check here is not required as
// appendAttributeValue will never suspend the parser.
if (textEnd != nextInEntity) {
entity->processed
= (int)(nextInEntity - (const char *)entity->textPtr);
continue;
}
// 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;
continue;
} // End of entity processing, "if" block skips the rest
// Remove fully processed openEntity from open entity list.
#if XML_GE == 1
entityTrackingOnClose(parser, entity, __LINE__);
#endif
// openEntity is m_openAttributeEntities' head, since we set it at the
// start of this function and because we skipped appendAttributeValue call
// with hasMore set to false. This means we can directly remove the head
// of m_openAttributeEntities
assert(parser->m_openAttributeEntities == openEntity);
entity->open = XML_FALSE;
parser->m_openAttributeEntities = parser->m_openAttributeEntities->next;
/* put openEntity back in list of free instances */
openEntity->next = parser->m_freeAttributeEntities;
parser->m_freeAttributeEntities = openEntity;
}
// Break if an error occurred or there is nothing left to process
if (result || (parser->m_openAttributeEntities == NULL && end == next)) {
break;
}
}
if (result)
return result;
if (! isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
@ -5996,7 +6197,7 @@ storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
static enum XML_Error
appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
const char *ptr, const char *end, STRING_POOL *pool,
enum XML_Account account) {
enum XML_Account account, const char **nextPtr) {
DTD *const dtd = parser->m_dtd; /* save one level of indirection */
#ifndef XML_DTD
UNUSED_P(account);
@ -6014,6 +6215,9 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
#endif
switch (tok) {
case XML_TOK_NONE:
if (nextPtr) {
*nextPtr = next;
}
return XML_ERROR_NONE;
case XML_TOK_INVALID:
if (enc == parser->m_encoding)
@ -6154,20 +6358,10 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
} else {
enum XML_Error result;
const XML_Char *textEnd = entity->textPtr + entity->textLen;
entity->open = XML_TRUE;
#if XML_GE == 1
entityTrackingOnOpen(parser, entity, __LINE__);
#endif
result = appendAttributeValue(parser, parser->m_internalEncoding,
isCdata, (const char *)entity->textPtr,
(const char *)textEnd, pool,
XML_ACCOUNT_ENTITY_EXPANSION);
#if XML_GE == 1
entityTrackingOnClose(parser, entity, __LINE__);
#endif
entity->open = XML_FALSE;
if (result)
result = processEntity(parser, entity, XML_FALSE, ENTITY_ATTRIBUTE);
if ((result == XML_ERROR_NONE) && (nextPtr != NULL)) {
*nextPtr = next;
}
return result;
}
} break;
@ -6197,7 +6391,7 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
static enum XML_Error
storeEntityValue(XML_Parser parser, const ENCODING *enc,
const char *entityTextPtr, const char *entityTextEnd,
enum XML_Account account) {
enum XML_Account account, const char **nextPtr) {
DTD *const dtd = parser->m_dtd; /* save one level of indirection */
STRING_POOL *pool = &(dtd->entityValuePool);
enum XML_Error result = XML_ERROR_NONE;
@ -6215,8 +6409,9 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc,
return XML_ERROR_NO_MEMORY;
}
const char *next;
for (;;) {
const char *next
next
= entityTextPtr; /* XmlEntityValueTok doesn't always set the last arg */
int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
@ -6278,15 +6473,7 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc,
} else
dtd->keepProcessing = dtd->standalone;
} else {
entity->open = XML_TRUE;
entityTrackingOnOpen(parser, entity, __LINE__);
result = storeEntityValue(
parser, parser->m_internalEncoding, (const char *)entity->textPtr,
(const char *)(entity->textPtr + entity->textLen),
XML_ACCOUNT_ENTITY_EXPANSION);
entityTrackingOnClose(parser, entity, __LINE__);
entity->open = XML_FALSE;
if (result)
result = processEntity(parser, entity, XML_FALSE, ENTITY_VALUE);
goto endEntityValue;
}
break;
@ -6375,6 +6562,81 @@ endEntityValue:
# ifdef XML_DTD
parser->m_prologState.inEntityValue = oldInEntityValue;
# endif /* XML_DTD */
// If 'nextPtr' is given, it should be updated during the processing
if (nextPtr != NULL) {
*nextPtr = next;
}
return result;
}
static enum XML_Error
callStoreEntityValue(XML_Parser parser, const ENCODING *enc,
const char *entityTextPtr, const char *entityTextEnd,
enum XML_Account account) {
const char *next = entityTextPtr;
enum XML_Error result = XML_ERROR_NONE;
while (1) {
if (! parser->m_openValueEntities) {
result
= storeEntityValue(parser, enc, next, entityTextEnd, account, &next);
} else {
OPEN_INTERNAL_ENTITY *const openEntity = parser->m_openValueEntities;
if (! openEntity)
return XML_ERROR_UNEXPECTED_STATE;
ENTITY *const entity = openEntity->entity;
const char *const textStart
= ((const char *)entity->textPtr) + entity->processed;
const char *const textEnd
= (const char *)(entity->textPtr + entity->textLen);
/* Set a safe default value in case 'next' does not get set */
const char *nextInEntity = textStart;
if (entity->hasMore) {
result = storeEntityValue(parser, parser->m_internalEncoding, textStart,
textEnd, XML_ACCOUNT_ENTITY_EXPANSION,
&nextInEntity);
if (result != XML_ERROR_NONE)
break;
// Check if entity is complete, if not, mark down how much of it is
// processed. A XML_SUSPENDED check here is not required as
// appendAttributeValue will never suspend the parser.
if (textEnd != nextInEntity) {
entity->processed
= (int)(nextInEntity - (const char *)entity->textPtr);
continue;
}
// 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;
continue;
} // End of entity processing, "if" block skips the rest
// Remove fully processed openEntity from open entity list.
# if XML_GE == 1
entityTrackingOnClose(parser, entity, __LINE__);
# endif
// openEntity is m_openValueEntities' head, since we set it at the
// start of this function and because we skipped storeEntityValue call
// with hasMore set to false. This means we can directly remove the head
// of m_openValueEntities
assert(parser->m_openValueEntities == openEntity);
entity->open = XML_FALSE;
parser->m_openValueEntities = parser->m_openValueEntities->next;
/* put openEntity back in list of free instances */
openEntity->next = parser->m_freeValueEntities;
parser->m_freeValueEntities = openEntity;
}
// Break if an error occurred or there is nothing left to process
if (result
|| (parser->m_openValueEntities == NULL && entityTextEnd == next)) {
break;
}
}
return result;
}
@ -8542,11 +8804,13 @@ unsignedCharToPrintable(unsigned char c) {
return "\\xFE";
case 255:
return "\\xFF";
// LCOV_EXCL_START
default:
assert(0); /* never gets here */
return "dead code";
}
assert(0); /* never gets here */
// LCOV_EXCL_STOP
}
#endif /* XML_GE == 1 */

@ -32,7 +32,7 @@ m4_define([_LT_COPYING], [dnl
# along with this program. If not, see <http://www.gnu.org/licenses/>.
])
# serial 62 LT_INIT
# serial 63 LT_INIT
# LT_PREREQ(VERSION)
@ -1100,6 +1100,21 @@ _LT_EOF
if test yes = "$lt_cv_apple_cc_single_mod"; then
_lt_dar_single_mod='$single_module'
fi
_lt_dar_needs_single_mod=no
case $host_os in
rhapsody* | darwin1.*)
_lt_dar_needs_single_mod=yes ;;
darwin*)
# When targeting Mac OS X 10.4 (darwin 8) or later,
# -single_module is the default and -multi_module is unsupported.
# The toolchain on macOS 10.14 (darwin 18) and later cannot
# target any OS version that needs -single_module.
case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
10.0,*-darwin[[567]].*|10.[[0-3]],*-darwin[[5-9]].*|10.[[0-3]],*-darwin1[[0-7]].*)
_lt_dar_needs_single_mod=yes ;;
esac
;;
esac
if test yes = "$lt_cv_ld_exported_symbols_list"; then
_lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym'
else
@ -1145,7 +1160,7 @@ m4_defun([_LT_DARWIN_LINKER_FEATURES],
_LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
_LT_TAGVAR(module_expsym_cmds, $1)="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
m4_if([$1], [CXX],
[ if test yes != "$lt_cv_apple_cc_single_mod"; then
[ if test yes = "$_lt_dar_needs_single_mod" -a yes != "$lt_cv_apple_cc_single_mod"; then
_LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil"
_LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil"
fi
@ -1710,9 +1725,9 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
lt_cv_sys_max_cmd_len=12288; # 12K is about right
;;
gnu*)
# Under GNU Hurd, this test is not required because there is
# no limit to the length of command line arguments.
gnu* | ironclad*)
# Under GNU Hurd and Ironclad, this test is not required because there
# is no limit to the length of command line arguments.
# Libtool will interpret -1 as no limit whatsoever
lt_cv_sys_max_cmd_len=-1;
;;
@ -2566,10 +2581,10 @@ cygwin* | mingw* | windows* | pw32* | cegcc*)
# gcc
library_names_spec='$libname.dll.a'
# DLL is installed to $(libdir)/../bin by postinstall_cmds
# If user builds GCC with mulitlibs enabled,
# If user builds GCC with multilib enabled,
# it should just install on $(libdir)
# not on $(libdir)/../bin or 32 bits dlls would override 64 bit ones.
if test yes = $multilib; then
if test xyes = x"$multilib"; then
postinstall_cmds='base_file=`basename \$file`~
dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
dldir=$destdir/`dirname \$dlpath`~
@ -2784,8 +2799,9 @@ haiku*)
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LIBRARY_PATH
shlibpath_overrides_runpath=no
sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
hardcode_into_libs=yes
sys_lib_search_path_spec='/boot/system/non-packaged/develop/lib /boot/system/develop/lib'
sys_lib_dlsearch_path_spec='/boot/home/config/non-packaged/lib /boot/home/config/lib /boot/system/non-packaged/lib /boot/system/lib'
hardcode_into_libs=no
;;
hpux9* | hpux10* | hpux11*)
@ -2963,6 +2979,18 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
dynamic_linker='GNU/Linux ld.so'
;;
netbsdelf*-gnu)
version_type=linux
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=no
hardcode_into_libs=yes
dynamic_linker='NetBSD ld.elf_so'
;;
netbsd*)
version_type=sunos
need_lib_prefix=no
@ -2981,6 +3009,18 @@ netbsd*)
hardcode_into_libs=yes
;;
*-mlibc)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
dynamic_linker='mlibc ld.so'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=no
hardcode_into_libs=yes
;;
newsos6)
version_type=linux # correct to gnu/linux during the next big refactor
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
@ -3060,6 +3100,17 @@ rdos*)
dynamic_linker=no
;;
serenity*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=no
dynamic_linker='SerenityOS LibELF'
;;
solaris*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
@ -3157,6 +3208,21 @@ uts4*)
shlibpath_var=LD_LIBRARY_PATH
;;
emscripten*)
version_type=none
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext'
soname_spec='$libname$release$shared_ext'
finish_cmds=
dynamic_linker="Emscripten linker"
_LT_COMPILER_PIC($1)='-fPIC'
_LT_TAGVAR(archive_cmds, $1)='$CC -sSIDE_MODULE=2 -shared $libobjs $deplibs $compiler_flags -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -sSIDE_MODULE=2 -shared $libobjs $deplibs $compiler_flags -o $lib -s EXPORTED_FUNCTIONS=@$output_objdir/$soname.expsym'
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(no_undefined_flag, $1)=
;;
*)
dynamic_linker=no
;;
@ -3621,7 +3687,11 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
lt_cv_deplibs_check_method=pass_all
;;
netbsd*)
*-mlibc)
lt_cv_deplibs_check_method=pass_all
;;
netbsd* | netbsdelf*-gnu)
if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
else
@ -3655,6 +3725,10 @@ rdos*)
lt_cv_deplibs_check_method=pass_all
;;
serenity*)
lt_cv_deplibs_check_method=pass_all
;;
solaris*)
lt_cv_deplibs_check_method=pass_all
;;
@ -4127,7 +4201,8 @@ _LT_EOF
if AC_TRY_EVAL(ac_compile); then
# Now try to grab the symbols.
nlist=conftest.nm
if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then
$ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&AS_MESSAGE_LOG_FD
if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&AS_MESSAGE_LOG_FD && test -s "$nlist"; then
# Try sorting and uniquifying the output.
if sort "$nlist" | uniq > "$nlist"T; then
mv -f "$nlist"T "$nlist"
@ -4499,7 +4574,9 @@ m4_if([$1], [CXX], [
;;
esac
;;
netbsd*)
netbsd* | netbsdelf*-gnu)
;;
*-mlibc)
;;
*qnx* | *nto*)
# QNX uses GNU C++, but need to define -shared option too, otherwise
@ -4529,6 +4606,8 @@ m4_if([$1], [CXX], [
;;
psos*)
;;
serenity*)
;;
solaris*)
case $cc_basename in
CC* | sunCC*)
@ -4767,7 +4846,7 @@ m4_if([$1], [CXX], [
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
;;
*flang* | ftn)
*flang* | ftn | f18* | f95*)
# Flang compiler.
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
@ -4855,6 +4934,12 @@ m4_if([$1], [CXX], [
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
*-mlibc)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
;;
*nto* | *qnx*)
# QNX uses GNU C++, but need to define -shared option too, otherwise
# it will coredump.
@ -4871,6 +4956,9 @@ m4_if([$1], [CXX], [
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
;;
serenity*)
;;
solaris*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
@ -5076,9 +5164,6 @@ dnl Note also adjust exclude_expsyms for C++ above.
# we just hope/assume this is gcc and not c89 (= MSVC++ or ICC)
with_gnu_ld=yes
;;
openbsd*)
with_gnu_ld=no
;;
esac
_LT_TAGVAR(ld_shlibs, $1)=yes
@ -5189,6 +5274,7 @@ _LT_EOF
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
_LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
_LT_TAGVAR(file_list_spec, $1)='@'
if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
@ -5208,7 +5294,7 @@ _LT_EOF
haiku*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(link_all_deplibs, $1)=yes
_LT_TAGVAR(link_all_deplibs, $1)=no
;;
os2*)
@ -5314,6 +5400,7 @@ _LT_EOF
case $cc_basename in
tcc*)
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic'
;;
xlf* | bgf* | bgxlf* | mpixlf*)
@ -5334,7 +5421,12 @@ _LT_EOF
fi
;;
netbsd*)
*-mlibc)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
;;
netbsd* | netbsdelf*-gnu)
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
wlarc=
@ -5872,11 +5964,15 @@ _LT_EOF
# Fabrice Bellard et al's Tiny C Compiler
_LT_TAGVAR(ld_shlibs, $1)=yes
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
;;
esac
;;
netbsd*)
*-mlibc)
;;
netbsd* | netbsdelf*-gnu)
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
else
@ -5977,6 +6073,9 @@ _LT_EOF
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
;;
serenity*)
;;
solaris*)
_LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
if test yes = "$GCC"; then
@ -6764,6 +6863,7 @@ if test yes != "$_lt_caught_CXX_error"; then
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
_LT_TAGVAR(always_export_symbols, $1)=no
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
_LT_TAGVAR(file_list_spec, $1)='@'
if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
@ -6851,7 +6951,7 @@ if test yes != "$_lt_caught_CXX_error"; then
haiku*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(link_all_deplibs, $1)=yes
_LT_TAGVAR(link_all_deplibs, $1)=no
;;
hpux9*)
@ -7175,6 +7275,10 @@ if test yes != "$_lt_caught_CXX_error"; then
esac
;;
*-mlibc)
_LT_TAGVAR(ld_shlibs, $1)=yes
;;
netbsd*)
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
@ -7297,6 +7401,9 @@ if test yes != "$_lt_caught_CXX_error"; then
_LT_TAGVAR(ld_shlibs, $1)=no
;;
serenity*)
;;
sunos4*)
case $cc_basename in
CC*)

@ -10,15 +10,15 @@
# @configure_input@
# serial 4392 ltversion.m4
# serial 4441 ltversion.m4
# This file is part of GNU Libtool
m4_define([LT_PACKAGE_VERSION], [2.5.3])
m4_define([LT_PACKAGE_REVISION], [2.5.3])
m4_define([LT_PACKAGE_VERSION], [2.5.4])
m4_define([LT_PACKAGE_REVISION], [2.5.4])
AC_DEFUN([LTVERSION_VERSION],
[macro_version='2.5.3'
macro_revision='2.5.3'
[macro_version='2.5.4'
macro_revision='2.5.4'
_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
_LT_DECL(, macro_revision, 0)
])

@ -360,13 +360,16 @@ END_TEST
START_TEST(test_helper_unsigned_char_to_printable) {
// Smoke test
unsigned char uc = 0;
for (; uc < (unsigned char)-1; uc++) {
for (;; uc++) {
set_subtest("char %u", (unsigned)uc);
const char *const printable = unsignedCharToPrintable(uc);
if (printable == NULL)
fail("unsignedCharToPrintable returned NULL");
else if (strlen(printable) < (size_t)1)
fail("unsignedCharToPrintable returned empty string");
if (uc == (unsigned char)-1) {
break;
}
}
// Two concrete samples

@ -19,6 +19,7 @@
Copyright (c) 2020 Tim Gates <tim.gates@iress.com>
Copyright (c) 2021 Donghee Na <donghee.na@python.org>
Copyright (c) 2023 Sony Corporation / Snild Dolkow <snild@sony.com>
Copyright (c) 2025 Berkay Eren Ürün <berkay.ueruen@siemens.com>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@ -450,6 +451,31 @@ START_TEST(test_alloc_internal_entity) {
}
END_TEST
START_TEST(test_alloc_parameter_entity) {
const char *text = "<!DOCTYPE foo ["
"<!ENTITY % param1 \"<!ENTITY internal 'some_text'>\">"
"%param1;"
"]> <foo>&internal;content</foo>";
int i;
const int alloc_test_max_repeats = 30;
for (i = 0; i < alloc_test_max_repeats; i++) {
g_allocation_count = i;
XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
!= XML_STATUS_ERROR)
break;
alloc_teardown();
alloc_setup();
}
g_allocation_count = -1;
if (i == 0)
fail("Parameter entity processed despite duff allocator");
if (i == alloc_test_max_repeats)
fail("Parameter entity not processed at max allocation count");
}
END_TEST
/* Test the robustness against allocation failure of element handling
* Based on test_dtd_default_handling().
*/
@ -2079,6 +2105,7 @@ make_alloc_test_case(Suite *s) {
tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_external_entity);
tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_ext_entity_set_encoding);
tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_internal_entity);
tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_parameter_entity);
tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_default_handling);
tcase_add_test(tc_alloc, test_alloc_explicit_encoding);
tcase_add_test(tc_alloc, test_alloc_set_base);

@ -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-2024 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2016-2025 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>
@ -19,6 +19,7 @@
Copyright (c) 2020 Tim Gates <tim.gates@iress.com>
Copyright (c) 2021 Donghee Na <donghee.na@python.org>
Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild@sony.com>
Copyright (c) 2024-2025 Berkay Eren Ürün <berkay.ueruen@siemens.com>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@ -1191,6 +1192,22 @@ START_TEST(test_not_standalone_handler_accept) {
}
END_TEST
START_TEST(test_entity_start_tag_level_greater_than_one) {
const char *const text = "<!DOCTYPE t1 [\n"
" <!ENTITY e1 'hello'>\n"
"]>\n"
"<t1>\n"
" <t2>&e1;</t2>\n"
"</t1>\n";
XML_Parser parser = XML_ParserCreate(NULL);
assert_true(_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text),
/*isFinal*/ XML_TRUE)
== XML_STATUS_OK);
XML_ParserFree(parser);
}
END_TEST
START_TEST(test_wfc_no_recursive_entity_refs) {
const char *text = "<!DOCTYPE doc [\n"
" <!ENTITY entity '&#38;entity;'>\n"
@ -1202,6 +1219,93 @@ START_TEST(test_wfc_no_recursive_entity_refs) {
}
END_TEST
START_TEST(test_no_indirectly_recursive_entity_refs) {
struct TestCase {
const char *doc;
bool usesParameterEntities;
};
const struct TestCase cases[] = {
// general entity + character data
{"<!DOCTYPE a [\n"
" <!ENTITY e1 '&e2;'>\n"
" <!ENTITY e2 '&e1;'>\n"
"]><a>&e2;</a>\n",
false},
// general entity + attribute value
{"<!DOCTYPE a [\n"
" <!ENTITY e1 '&e2;'>\n"
" <!ENTITY e2 '&e1;'>\n"
"]><a k1='&e2;' />\n",
false},
// parameter entity
{"<!DOCTYPE doc [\n"
" <!ENTITY % p1 '&#37;p2;'>\n"
" <!ENTITY % p2 '&#37;p1;'>\n"
" <!ENTITY % define_g \"<!ENTITY g '&#37;p2;'>\">\n"
" %define_g;\n"
"]>\n"
"<doc/>\n",
true},
};
const XML_Bool reset_or_not[] = {XML_TRUE, XML_FALSE};
for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
for (size_t j = 0; j < sizeof(reset_or_not) / sizeof(reset_or_not[0]);
j++) {
const XML_Bool reset_wanted = reset_or_not[j];
const char *const doc = cases[i].doc;
const bool usesParameterEntities = cases[i].usesParameterEntities;
set_subtest("[%i,reset=%i] %s", (int)i, (int)j, doc);
#ifdef XML_DTD // both GE and DTD
const bool rejection_expected = true;
#elif XML_GE == 1 // GE but not DTD
const bool rejection_expected = ! usesParameterEntities;
#else // neither DTD nor GE
const bool rejection_expected = false;
#endif
XML_Parser parser = XML_ParserCreate(NULL);
#ifdef XML_DTD
if (usesParameterEntities) {
assert_true(
XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS)
== 1);
}
#else
UNUSED_P(usesParameterEntities);
#endif // XML_DTD
const enum XML_Status status
= _XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc),
/*isFinal*/ XML_TRUE);
if (rejection_expected) {
assert_true(status == XML_STATUS_ERROR);
assert_true(XML_GetErrorCode(parser) == XML_ERROR_RECURSIVE_ENTITY_REF);
} else {
assert_true(status == XML_STATUS_OK);
}
if (reset_wanted) {
// This covers free'ing of (eventually) all three open entity lists by
// XML_ParserReset.
XML_ParserReset(parser, NULL);
}
// This covers free'ing of (eventually) all three open entity lists by
// XML_ParserFree (unless XML_ParserReset has already done that above).
XML_ParserFree(parser);
}
}
}
END_TEST
START_TEST(test_recursive_external_parameter_entity_2) {
struct TestCase {
const char *doc;
@ -1417,7 +1521,9 @@ START_TEST(test_suspend_parser_between_char_data_calls) {
XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
g_resumable = XML_TRUE;
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
// can't use SINGLE_BYTES here, because it'll return early on suspension, and
// we won't know exactly how much input we actually managed to give Expat.
if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
!= XML_STATUS_SUSPENDED)
xml_failure(g_parser);
if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
@ -1446,7 +1552,9 @@ START_TEST(test_repeated_stop_parser_between_char_data_calls) {
XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
g_resumable = XML_TRUE;
g_abortable = XML_FALSE;
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
// can't use SINGLE_BYTES here, because it'll return early on suspension, and
// we won't know exactly how much input we actually managed to give Expat.
if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
!= XML_STATUS_SUSPENDED)
fail("Failed to double-suspend parser");
@ -1830,12 +1938,19 @@ END_TEST
/* Test suspending the parser in cdata handler */
START_TEST(test_suspend_parser_between_cdata_calls) {
if (g_chunkSize != 0) {
// this test does not use SINGLE_BYTES, because of suspension
return;
}
const char *text = long_cdata_text;
enum XML_Status result;
XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
g_resumable = XML_TRUE;
result = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
// can't use SINGLE_BYTES here, because it'll return early on suspension, and
// we won't know exactly how much input we actually managed to give Expat.
result = XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE);
if (result != XML_STATUS_SUSPENDED) {
if (result == XML_STATUS_ERROR)
xml_failure(g_parser);
@ -2378,6 +2493,11 @@ END_TEST
* entity. Exercises some obscure code in XML_ParserReset().
*/
START_TEST(test_reset_in_entity) {
if (g_chunkSize != 0) {
// this test does not use SINGLE_BYTES, because of suspension
return;
}
const char *text = "<!DOCTYPE doc [\n"
"<!ENTITY wombat 'wom'>\n"
"<!ENTITY entity 'hi &wom; there'>\n"
@ -2387,7 +2507,9 @@ START_TEST(test_reset_in_entity) {
g_resumable = XML_TRUE;
XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
// can't use SINGLE_BYTES here, because it'll return early on suspension, and
// we won't know exactly how much input we actually managed to give Expat.
if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
== XML_STATUS_ERROR)
xml_failure(g_parser);
XML_GetParsingStatus(g_parser, &status);
@ -3634,7 +3756,9 @@ START_TEST(test_suspend_xdecl) {
XML_SetXmlDeclHandler(g_parser, entity_suspending_xdecl_handler);
XML_SetUserData(g_parser, g_parser);
g_resumable = XML_TRUE;
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
// can't use SINGLE_BYTES here, because it'll return early on suspension, and
// we won't know exactly how much input we actually managed to give Expat.
if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
!= XML_STATUS_SUSPENDED)
xml_failure(g_parser);
if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
@ -3830,13 +3954,20 @@ END_TEST
/* Test syntax error is caught at parse resumption */
START_TEST(test_resume_entity_with_syntax_error) {
if (g_chunkSize != 0) {
// this test does not use SINGLE_BYTES, because of suspension
return;
}
const char *text = "<!DOCTYPE doc [\n"
"<!ENTITY foo '<suspend>Hi</wombat>'>\n"
"]>\n"
"<doc>&foo;</doc>\n";
XML_SetStartElementHandler(g_parser, start_element_suspender);
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
// can't use SINGLE_BYTES here, because it'll return early on suspension, and
// we won't know exactly how much input we actually managed to give Expat.
if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
!= XML_STATUS_SUSPENDED)
xml_failure(g_parser);
if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR)
@ -3960,7 +4091,7 @@ START_TEST(test_skipped_null_loaded_ext_entity) {
= {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n"
"<!ENTITY % pe2 '%pe1;'>\n"
"%pe2;\n",
external_entity_null_loader};
external_entity_null_loader, NULL};
XML_SetUserData(g_parser, &test_data);
XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
@ -3978,7 +4109,7 @@ START_TEST(test_skipped_unloaded_ext_entity) {
= {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n"
"<!ENTITY % pe2 '%pe1;'>\n"
"%pe2;\n",
NULL};
NULL, NULL};
XML_SetUserData(g_parser, &test_data);
XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
@ -5278,6 +5409,151 @@ START_TEST(test_pool_integrity_with_unfinished_attr) {
}
END_TEST
/* Test a possible early return location in internalEntityProcessor */
START_TEST(test_entity_ref_no_elements) {
const char *const text = "<!DOCTYPE foo [\n"
"<!ENTITY e1 \"test\">\n"
"]> <foo>&e1;"; // intentionally missing newline
XML_Parser parser = XML_ParserCreate(NULL);
assert_true(_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
== XML_STATUS_ERROR);
assert_true(XML_GetErrorCode(parser) == XML_ERROR_NO_ELEMENTS);
XML_ParserFree(parser);
}
END_TEST
/* Tests if chained entity references lead to unbounded recursion */
START_TEST(test_deep_nested_entity) {
const size_t N_LINES = 60000;
const size_t SIZE_PER_LINE = 50;
char *const text = (char *)malloc((N_LINES + 4) * SIZE_PER_LINE);
if (text == NULL) {
fail("malloc failed");
}
char *textPtr = text;
// Create the XML
textPtr += snprintf(textPtr, SIZE_PER_LINE,
"<!DOCTYPE foo [\n"
" <!ENTITY s0 'deepText'>\n");
for (size_t i = 1; i < N_LINES; ++i) {
textPtr += snprintf(textPtr, SIZE_PER_LINE, " <!ENTITY s%lu '&s%lu;'>\n",
(long unsigned)i, (long unsigned)(i - 1));
}
snprintf(textPtr, SIZE_PER_LINE, "]> <foo>&s%lu;</foo>\n",
(long unsigned)(N_LINES - 1));
const XML_Char *const expected = XCS("deepText");
CharData storage;
CharData_Init(&storage);
XML_Parser parser = XML_ParserCreate(NULL);
XML_SetCharacterDataHandler(parser, accumulate_characters);
XML_SetUserData(parser, &storage);
if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
== XML_STATUS_ERROR)
xml_failure(parser);
CharData_CheckXMLChars(&storage, expected);
XML_ParserFree(parser);
free(text);
}
END_TEST
/* Tests if chained entity references in attributes
lead to unbounded recursion */
START_TEST(test_deep_nested_attribute_entity) {
const size_t N_LINES = 60000;
const size_t SIZE_PER_LINE = 100;
char *const text = (char *)malloc((N_LINES + 4) * SIZE_PER_LINE);
if (text == NULL) {
fail("malloc failed");
}
char *textPtr = text;
// Create the XML
textPtr += snprintf(textPtr, SIZE_PER_LINE,
"<!DOCTYPE foo [\n"
" <!ENTITY s0 'deepText'>\n");
for (size_t i = 1; i < N_LINES; ++i) {
textPtr += snprintf(textPtr, SIZE_PER_LINE, " <!ENTITY s%lu '&s%lu;'>\n",
(long unsigned)i, (long unsigned)(i - 1));
}
snprintf(textPtr, SIZE_PER_LINE, "]> <foo name='&s%lu;'>mainText</foo>\n",
(long unsigned)(N_LINES - 1));
AttrInfo doc_info[] = {{XCS("name"), XCS("deepText")}, {NULL, NULL}};
ElementInfo info[] = {{XCS("foo"), 1, NULL, NULL}, {NULL, 0, NULL, NULL}};
info[0].attributes = doc_info;
XML_Parser parser = XML_ParserCreate(NULL);
ParserAndElementInfo parserPlusElemenInfo = {parser, info};
XML_SetStartElementHandler(parser, counting_start_element_handler);
XML_SetUserData(parser, &parserPlusElemenInfo);
if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
== XML_STATUS_ERROR)
xml_failure(parser);
XML_ParserFree(parser);
free(text);
}
END_TEST
START_TEST(test_deep_nested_entity_delayed_interpretation) {
const size_t N_LINES = 70000;
const size_t SIZE_PER_LINE = 100;
char *const text = (char *)malloc((N_LINES + 4) * SIZE_PER_LINE);
if (text == NULL) {
fail("malloc failed");
}
char *textPtr = text;
// Create the XML
textPtr += snprintf(textPtr, SIZE_PER_LINE,
"<!DOCTYPE foo [\n"
" <!ENTITY %% s0 'deepText'>\n");
for (size_t i = 1; i < N_LINES; ++i) {
textPtr += snprintf(textPtr, SIZE_PER_LINE,
" <!ENTITY %% s%lu '&#37;s%lu;'>\n", (long unsigned)i,
(long unsigned)(i - 1));
}
snprintf(textPtr, SIZE_PER_LINE,
" <!ENTITY %% define_g \"<!ENTITY g '&#37;s%lu;'>\">\n"
" %%define_g;\n"
"]>\n"
"<foo/>\n",
(long unsigned)(N_LINES - 1));
XML_Parser parser = XML_ParserCreate(NULL);
XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
== XML_STATUS_ERROR)
xml_failure(parser);
XML_ParserFree(parser);
free(text);
}
END_TEST
START_TEST(test_nested_entity_suspend) {
const char *const text = "<!DOCTYPE a [\n"
" <!ENTITY e1 '<!--e1-->'>\n"
@ -5308,6 +5584,35 @@ START_TEST(test_nested_entity_suspend) {
}
END_TEST
START_TEST(test_nested_entity_suspend_2) {
const char *const text = "<!DOCTYPE doc [\n"
" <!ENTITY ge1 'head1Ztail1'>\n"
" <!ENTITY ge2 'head2&ge1;tail2'>\n"
" <!ENTITY ge3 'head3&ge2;tail3'>\n"
"]>\n"
"<doc>&ge3;</doc>";
const XML_Char *const expected = XCS("head3") XCS("head2") XCS("head1")
XCS("Z") XCS("tail1") XCS("tail2") XCS("tail3");
CharData storage;
CharData_Init(&storage);
XML_Parser parser = XML_ParserCreate(NULL);
ParserPlusStorage parserPlusStorage = {parser, &storage};
XML_SetCharacterDataHandler(parser, accumulate_char_data_and_suspend);
XML_SetUserData(parser, &parserPlusStorage);
enum XML_Status status = XML_Parse(parser, text, (int)strlen(text), XML_TRUE);
while (status == XML_STATUS_SUSPENDED) {
status = XML_ResumeParser(parser);
}
if (status != XML_STATUS_OK)
xml_failure(parser);
CharData_CheckXMLChars(&storage, expected);
XML_ParserFree(parser);
}
END_TEST
/* Regression test for quadratic parsing on large tokens */
START_TEST(test_big_tokens_scale_linearly) {
const struct {
@ -5968,7 +6273,9 @@ make_basic_test_case(Suite *s) {
tcase_add_test(tc_basic, test_wfc_undeclared_entity_with_external_subset);
tcase_add_test(tc_basic, test_not_standalone_handler_reject);
tcase_add_test(tc_basic, test_not_standalone_handler_accept);
tcase_add_test(tc_basic, test_entity_start_tag_level_greater_than_one);
tcase_add_test__if_xml_ge(tc_basic, test_wfc_no_recursive_entity_refs);
tcase_add_test(tc_basic, test_no_indirectly_recursive_entity_refs);
tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_invalid_parse);
tcase_add_test__if_xml_ge(tc_basic, test_dtd_default_handling);
tcase_add_test(tc_basic, test_dtd_attr_handling);
@ -6147,7 +6454,13 @@ make_basic_test_case(Suite *s) {
tcase_add_test(tc_basic, test_empty_element_abort);
tcase_add_test__ifdef_xml_dtd(tc_basic,
test_pool_integrity_with_unfinished_attr);
tcase_add_test__if_xml_ge(tc_basic, test_entity_ref_no_elements);
tcase_add_test__if_xml_ge(tc_basic, test_deep_nested_entity);
tcase_add_test__if_xml_ge(tc_basic, test_deep_nested_attribute_entity);
tcase_add_test__if_xml_ge(tc_basic,
test_deep_nested_entity_delayed_interpretation);
tcase_add_test__if_xml_ge(tc_basic, test_nested_entity_suspend);
tcase_add_test__if_xml_ge(tc_basic, test_nested_entity_suspend_2);
tcase_add_test(tc_basic, test_big_tokens_scale_linearly);
tcase_add_test(tc_basic, test_set_reparse_deferral);
tcase_add_test(tc_basic, test_reparse_deferral_is_inherited);

@ -8,7 +8,7 @@
Copyright (c) 2003-2006 Karl Waclawek <karl@waclawek.net>
Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
Copyright (c) 2017-2023 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2017-2025 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
Licensed under the MIT license:
@ -32,10 +32,18 @@
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#define _POSIX_C_SOURCE 1 // fdopen
#if defined(_MSC_VER)
# include <io.h> // _open, _close
#else
# include <unistd.h> // close
#endif
#include <fcntl.h> // open
#include <sys/stat.h>
#include <assert.h>
#include <stddef.h> // ptrdiff_t
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "expat.h"
@ -52,17 +60,18 @@
# define XML_FMT_STR "s"
#endif
static void
static int
usage(const char *prog, int rc) {
fprintf(stderr, "usage: %s [-n] filename bufferSize nr_of_loops\n", prog);
exit(rc);
return rc;
}
int
main(int argc, char *argv[]) {
XML_Parser parser;
char *XMLBuf, *XMLBufEnd, *XMLBufPtr;
FILE *fd;
int fd;
FILE *file;
struct stat fileAttr;
int nrOfLoops, bufferSize, i, isFinal;
size_t fileSize;
@ -76,34 +85,51 @@ main(int argc, char *argv[]) {
ns = 1;
j = 1;
} else
usage(argv[0], 1);
return usage(argv[0], 1);
}
}
if (argc != j + 4)
usage(argv[0], 1);
return usage(argv[0], 1);
if (stat(argv[j + 1], &fileAttr) != 0) {
fprintf(stderr, "could not access file '%s'\n", argv[j + 1]);
fd = open(argv[j + 1], O_RDONLY);
if (fd == -1) {
fprintf(stderr, "could not open file '%s'\n", argv[j + 1]);
return 2;
}
fd = fopen(argv[j + 1], "r");
if (! fd) {
fprintf(stderr, "could not open file '%s'\n", argv[j + 1]);
exit(2);
if (fstat(fd, &fileAttr) != 0) {
close(fd);
fprintf(stderr, "could not fstat file '%s'\n", argv[j + 1]);
return 2;
}
file = fdopen(fd, "r");
if (! file) {
close(fd);
fprintf(stderr, "could not fdopen file '%s'\n", argv[j + 1]);
return 2;
}
bufferSize = atoi(argv[j + 2]);
nrOfLoops = atoi(argv[j + 3]);
if (bufferSize <= 0 || nrOfLoops <= 0) {
fclose(file);
close(fd);
fprintf(stderr, "buffer size and nr of loops must be greater than zero.\n");
exit(3);
return 3;
}
XMLBuf = malloc(fileAttr.st_size);
fileSize = fread(XMLBuf, sizeof(char), fileAttr.st_size, fd);
fclose(fd);
if (XMLBuf == NULL) {
fclose(file);
close(fd);
fprintf(stderr, "ouf of memory.\n");
return 5;
}
fileSize = fread(XMLBuf, sizeof(char), fileAttr.st_size, file);
fclose(file);
close(fd);
if (ns)
parser = XML_ParserCreateNS(NULL, '!');
@ -132,7 +158,7 @@ main(int argc, char *argv[]) {
XML_GetCurrentColumnNumber(parser));
free(XMLBuf);
XML_ParserFree(parser);
exit(4);
return 4;
}
XMLBufPtr += bufferSize;
} while (! isFinal);

@ -202,6 +202,12 @@ _XML_Parse_SINGLE_BYTES(XML_Parser parser, const char *s, int len,
for (; len > chunksize; len -= chunksize, s += chunksize) {
enum XML_Status res = XML_Parse(parser, s, chunksize, XML_FALSE);
if (res != XML_STATUS_OK) {
if ((res == XML_STATUS_SUSPENDED) && (len > chunksize)) {
fail("Use of function _XML_Parse_SINGLE_BYTES with a chunk size "
"greater than 0 (from g_chunkSize) does not work well with "
"suspension. Please consider use of plain XML_Parse at this "
"place in your test, instead.");
}
return res;
}
}

@ -1842,6 +1842,15 @@ element_decl_suspender(void *userData, const XML_Char *name,
XML_FreeContentModel(g_parser, model);
}
void XMLCALL
suspend_after_element_declaration(void *userData, const XML_Char *name,
XML_Content *model) {
UNUSED_P(name);
XML_Parser parser = (XML_Parser)userData;
assert_true(XML_StopParser(parser, /*resumable*/ XML_TRUE) == XML_STATUS_OK);
XML_FreeContentModel(parser, model);
}
void XMLCALL
accumulate_pi_characters(void *userData, const XML_Char *target,
const XML_Char *data) {
@ -1882,6 +1891,20 @@ accumulate_entity_decl(void *userData, const XML_Char *entityName,
CharData_AppendXMLChars(storage, XCS("\n"), 1);
}
void XMLCALL
accumulate_char_data_and_suspend(void *userData, const XML_Char *s, int len) {
ParserPlusStorage *const parserPlusStorage = (ParserPlusStorage *)userData;
CharData_AppendXMLChars(parserPlusStorage->storage, s, len);
for (int i = 0; i < len; i++) {
if (s[i] == 'Z') {
XML_StopParser(parserPlusStorage->parser, /*resumable=*/XML_TRUE);
break;
}
}
}
void XMLCALL
accumulate_start_element(void *userData, const XML_Char *name,
const XML_Char **atts) {

@ -325,6 +325,7 @@ extern int XMLCALL external_entity_devaluer(XML_Parser parser,
typedef struct ext_hdlr_data {
const char *parse_text;
XML_ExternalEntityRefHandler handler;
CharData *storage;
} ExtHdlrData;
extern int XMLCALL external_entity_oneshot_loader(XML_Parser parser,
@ -557,6 +558,10 @@ extern void XMLCALL suspending_comment_handler(void *userData,
extern void XMLCALL element_decl_suspender(void *userData, const XML_Char *name,
XML_Content *model);
extern void XMLCALL suspend_after_element_declaration(void *userData,
const XML_Char *name,
XML_Content *model);
extern void XMLCALL accumulate_pi_characters(void *userData,
const XML_Char *target,
const XML_Char *data);
@ -569,6 +574,10 @@ extern void XMLCALL accumulate_entity_decl(
const XML_Char *systemId, const XML_Char *publicId,
const XML_Char *notationName);
extern void XMLCALL accumulate_char_data_and_suspend(void *userData,
const XML_Char *s,
int len);
extern void XMLCALL accumulate_start_element(void *userData,
const XML_Char *name,
const XML_Char **atts);

@ -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-2024 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2016-2025 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:
@ -129,9 +129,11 @@ void _check_set_test_info(char const *function, char const *filename,
* Prototypes for the actual implementation.
*/
# if defined(__GNUC__)
# if defined(__has_attribute)
# if __has_attribute(noreturn)
__attribute__((noreturn))
# endif
# endif
void
_fail(const char *file, int line, const char *msg);
Suite *suite_create(const char *name);

@ -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-2024 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2016-2025 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>
@ -59,6 +59,9 @@
#include "handlers.h"
#include "misc_tests.h"
void XMLCALL accumulate_characters_ext_handler(void *userData,
const XML_Char *s, int len);
/* Test that a failure to allocate the parser structure fails gracefully */
START_TEST(test_misc_alloc_create_parser) {
XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free};
@ -208,7 +211,7 @@ START_TEST(test_misc_version) {
if (! versions_equal(&read_version, &parsed_version))
fail("Version mismatch");
if (xcstrcmp(version_text, XCS("expat_2.6.4"))) /* needs bump on releases */
if (xcstrcmp(version_text, XCS("expat_2.7.0"))) /* needs bump on releases */
fail("XML_*_VERSION in expat.h out of sync?\n");
}
END_TEST
@ -294,6 +297,7 @@ START_TEST(test_misc_stop_during_end_handler_issue_240_1) {
parser = XML_ParserCreate(NULL);
XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
assert_true(mydata != NULL);
mydata->parser = parser;
mydata->deep = 0;
XML_SetUserData(parser, mydata);
@ -315,6 +319,7 @@ START_TEST(test_misc_stop_during_end_handler_issue_240_2) {
parser = XML_ParserCreate(NULL);
XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
assert_true(mydata != NULL);
mydata->parser = parser;
mydata->deep = 0;
XML_SetUserData(parser, mydata);
@ -328,20 +333,31 @@ START_TEST(test_misc_stop_during_end_handler_issue_240_2) {
END_TEST
START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) {
const char *const inputOne = "<!DOCTYPE d [\n"
const char *const inputOne
= "<!DOCTYPE d [\n"
"<!ENTITY % element_d '<!ELEMENT d (#PCDATA)*>'>\n"
"%element_d;\n"
"<!ENTITY % e ']><d/>'>\n"
"\n"
"%e;";
const char *const inputTwo
= "<!DOCTYPE d [\n"
"<!ENTITY % element_d '<!ELEMENT d (#PCDATA)*>'>\n"
"%element_d;\n"
"<!ENTITY % e1 ']><d/>'><!ENTITY % e2 '&#37;e1;'>\n"
"\n"
"%e2;";
const char *const inputThree = "<!DOCTYPE d [\n"
const char *const inputThree
= "<!DOCTYPE d [\n"
"<!ENTITY % element_d '<!ELEMENT d (#PCDATA)*>'>\n"
"%element_d;\n"
"<!ENTITY % e ']><d'>\n"
"\n"
"%e;/>";
const char *const inputIssue317 = "<!DOCTYPE doc [\n"
const char *const inputIssue317
= "<!DOCTYPE doc [\n"
"<!ENTITY % element_doc '<!ELEMENT doc (#PCDATA)*>'>\n"
"%element_doc;\n"
"<!ENTITY % foo ']>\n"
"<doc>Hell<oc (#PCDATA)*>'>\n"
"%foo;\n"
@ -349,16 +365,29 @@ START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) {
"<doc>Hello, world</dVc>";
const char *const inputs[] = {inputOne, inputTwo, inputThree, inputIssue317};
const XML_Bool suspendOrNot[] = {XML_FALSE, XML_TRUE};
size_t inputIndex = 0;
for (; inputIndex < sizeof(inputs) / sizeof(inputs[0]); inputIndex++) {
set_subtest("%s", inputs[inputIndex]);
for (size_t suspendOrNotIndex = 0;
suspendOrNotIndex < sizeof(suspendOrNot) / sizeof(suspendOrNot[0]);
suspendOrNotIndex++) {
const char *const input = inputs[inputIndex];
const XML_Bool suspend = suspendOrNot[suspendOrNotIndex];
if (suspend && (g_chunkSize > 0)) {
// We cannot use _XML_Parse_SINGLE_BYTES below due to suspension, and
// so chunk sizes >0 would only repeat the very same test
// due to use of plain XML_Parse; we are saving upon that runtime:
return;
}
set_subtest("[input=%d suspend=%s] %s", (int)inputIndex,
suspend ? "true" : "false", input);
XML_Parser parser;
enum XML_Status parseResult;
int setParamEntityResult;
XML_Size lineNumber;
XML_Size columnNumber;
const char *const input = inputs[inputIndex];
parser = XML_ParserCreate(NULL);
setParamEntityResult
@ -366,19 +395,49 @@ START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) {
if (setParamEntityResult != 1)
fail("Failed to set XML_PARAM_ENTITY_PARSING_ALWAYS.");
parseResult = _XML_Parse_SINGLE_BYTES(parser, input, (int)strlen(input), 0);
if (suspend) {
XML_SetUserData(parser, parser);
XML_SetElementDeclHandler(parser, suspend_after_element_declaration);
}
if (suspend) {
// can't use SINGLE_BYTES here, because it'll return early on
// suspension, and we won't know exactly how much input we actually
// managed to give Expat.
parseResult = XML_Parse(parser, input, (int)strlen(input), 0);
while (parseResult == XML_STATUS_SUSPENDED) {
parseResult = XML_ResumeParser(parser);
}
if (parseResult != XML_STATUS_ERROR) {
// can't use SINGLE_BYTES here, because it'll return early on
// suspension, and we won't know exactly how much input we actually
// managed to give Expat.
parseResult = XML_Parse(parser, "", 0, 1);
}
while (parseResult == XML_STATUS_SUSPENDED) {
parseResult = XML_ResumeParser(parser);
}
} else {
parseResult
= _XML_Parse_SINGLE_BYTES(parser, input, (int)strlen(input), 0);
if (parseResult != XML_STATUS_ERROR) {
parseResult = _XML_Parse_SINGLE_BYTES(parser, "", 0, 1);
}
}
if (parseResult != XML_STATUS_ERROR) {
fail("Parsing was expected to fail but succeeded.");
}
}
if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
fail("Error code does not match XML_ERROR_INVALID_TOKEN");
lineNumber = XML_GetCurrentLineNumber(parser);
if (lineNumber != 4)
if (lineNumber != 6)
fail("XML_GetCurrentLineNumber does not work as expected.");
columnNumber = XML_GetCurrentColumnNumber(parser);
@ -388,6 +447,7 @@ START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) {
XML_ParserFree(parser);
}
}
}
END_TEST
START_TEST(test_misc_tag_mismatch_reset_leak) {
@ -519,6 +579,45 @@ START_TEST(test_misc_stopparser_rejects_unstarted_parser) {
}
END_TEST
/* Adaptation of accumulate_characters that takes ExtHdlrData input to work with
* test_renter_loop_finite_content below */
void XMLCALL
accumulate_characters_ext_handler(void *userData, const XML_Char *s, int len) {
ExtHdlrData *const test_data = (ExtHdlrData *)userData;
CharData_AppendXMLChars(test_data->storage, s, len);
}
/* Test that internalEntityProcessor does not re-enter forever;
* based on files tests/xmlconf/xmltest/valid/ext-sa/012.{xml,ent} */
START_TEST(test_renter_loop_finite_content) {
CharData storage;
CharData_Init(&storage);
const char *const text = "<!DOCTYPE doc [\n"
"<!ENTITY e1 '&e2;'>\n"
"<!ENTITY e2 '&e3;'>\n"
"<!ENTITY e3 SYSTEM '012.ent'>\n"
"<!ENTITY e4 '&e5;'>\n"
"<!ENTITY e5 '(e5)'>\n"
"<!ELEMENT doc (#PCDATA)>\n"
"]>\n"
"<doc>&e1;</doc>\n";
ExtHdlrData test_data = {"&e4;\n", external_entity_null_loader, &storage};
const XML_Char *const expected = XCS("(e5)\n");
XML_Parser parser = XML_ParserCreate(NULL);
assert_true(parser != NULL);
XML_SetUserData(parser, &test_data);
XML_SetExternalEntityRefHandler(parser, external_entity_oneshot_loader);
XML_SetCharacterDataHandler(parser, accumulate_characters_ext_handler);
if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
== XML_STATUS_ERROR)
xml_failure(parser);
CharData_CheckXMLChars(&storage, expected);
XML_ParserFree(parser);
}
END_TEST
void
make_miscellaneous_test_case(Suite *s) {
TCase *tc_misc = tcase_create("miscellaneous tests");
@ -545,4 +644,5 @@ make_miscellaneous_test_case(Suite *s) {
tcase_add_test(tc_misc, test_misc_char_handler_stop_without_leak);
tcase_add_test(tc_misc, test_misc_resumeparser_not_crashing);
tcase_add_test(tc_misc, test_misc_stopparser_rejects_unstarted_parser);
tcase_add_test__if_xml_ge(tc_misc, test_renter_loop_finite_content);
}

@ -2,8 +2,8 @@
# EXPAT TEST SCRIPT FOR W3C XML TEST SUITE
#
# This script can be used to exercise Expat against the
# w3c.org xml test suite, available from
# http://www.w3.org/XML/Test/xmlts20020606.zip.
# w3c.org xml test suite, available from:
# https://www.w3.org/XML/Test/xmlts20020606.zip
#
# To run this script, first set XMLWF below so that xmlwf can be
# found, then set the output directory with OUTPUT.
@ -30,6 +30,7 @@
# Copyright (c) 2002 Karl Waclawek <karl@waclawek.net>
# 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>
# Licensed under the MIT license:
#
# Permission is hereby granted, free of charge, to any person obtaining

@ -14,7 +14,7 @@
; Copyright (c) 2001 Tim Peters <tim.peters@gmail.com>
; Copyright (c) 2001-2005 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
; Copyright (c) 2006-2017 Karl Waclawek <karl@waclawek.net>
; Copyright (c) 2007-2024 Sebastian Pipping <sebastian@pipping.org>
; Copyright (c) 2007-2025 Sebastian Pipping <sebastian@pipping.org>
; Copyright (c) 2022 Johnny Jazeix <jazeix@gmail.com>
; Copyright (c) 2024 Dag-Erling Smørgrav <des@des.dev>
; Licensed under the MIT license:
@ -38,14 +38,14 @@
; OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
; USE OR OTHER DEALINGS IN THE SOFTWARE.
#define expatVer "2.6.4"
#define expatVer "2.7.0"
[Setup]
AppName=Expat
AppId=expat
AppVersion={#expatVer}
AppVerName=Expat {#expatVer}
AppCopyright=Copyright © 1997-2022 Thai Open Source Software Center, Clark Cooper, and the Expat maintainers
AppCopyright=Copyright © 1997-2025 Thai Open Source Software Center, Clark Cooper, and the Expat maintainers
AppPublisher=The Expat Developers
AppPublisherURL=https://libexpat.github.io/
AppSupportURL=https://libexpat.github.io/
@ -75,7 +75,7 @@ Flags: ignoreversion; Source: COPYING; DestDir: "{app}"; De
Flags: ignoreversion; Source: README.md; DestDir: "{app}"; DestName: README.txt
Flags: ignoreversion; Source: doc\*.html; DestDir: "{app}\Doc"
Flags: ignoreversion; Source: doc\*.css; DestDir: "{app}\Doc"
Flags: ignoreversion; Source: doc\*.xml; DestDir: "{app}\Doc"
Flags: ignoreversion; Source: doc\*.xml; DestDir: "{app}\Source\doc"
Flags: ignoreversion; Source: win32\bin\Release\*.dll; DestDir: "{app}\Bin"
Flags: ignoreversion; Source: win32\bin\Release\*.lib; DestDir: "{app}\Bin"
Flags: ignoreversion; Source: win32\version.rc.cmake; DestDir: "{app}\Source\win32"

@ -14,6 +14,7 @@
Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
Copyright (c) 2017 Franek Korta <fkorta@gmail.com>
Copyright (c) 2022 Sean McBride <sean@rogue-research.com>
Copyright (c) 2025 Hanno Böck <hanno@gentoo.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@ -55,7 +56,7 @@
# define EXPAT_read_count_t int
# define EXPAT_read_req_t unsigned int
#else /* POSIX */
/* http://pubs.opengroup.org/onlinepubs/009695399/functions/read.html */
/* https://pubs.opengroup.org/onlinepubs/009695399/functions/read.html */
# define EXPAT_read read
# define EXPAT_read_count_t ssize_t
# define EXPAT_read_req_t size_t

Loading…
Cancel
Save