expat: update to 2.7.0

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

@ -350,7 +350,7 @@ sub fixDyn
# avahi # avahi
fixDynDep("avahi-daemon", "libavahi-core.so.7.1.0"); fixDynDep("avahi-daemon", "libavahi-core.so.7.1.0");
fixDynDep("avahi-daemon", "libavahi-common.so.3.5.4"); 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("avahi-daemon", "libdaemon.so.0.5.0");
fixDynDep("xtables-legacy-multi", "libxtables.so"); 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}"); #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) 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/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/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"); 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 @$(MAKE) -C $@ DESTDIR=$(TOP)/expat/staged install
expat-install: expat-install:
install -D expat/staged/usr/lib/libexpat.so.1.10.0 $(INSTALLDIR)/expat/usr/lib/libexpat.so.1.10.0 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.0 $(STRIP) $(INSTALLDIR)/expat/usr/lib/libexpat.so.1.10.1
cd $(INSTALLDIR)/expat/usr/lib && ln -sf libexpat.so.1.10.0 libexpat.so.1 cd $(INSTALLDIR)/expat/usr/lib && ln -sf libexpat.so.1.10.1 libexpat.so.1
expat-clean: expat-clean:
-@$(MAKE) -C expat clean -@$(MAKE) -C expat clean

@ -3,25 +3,25 @@
The cmake based buildsystem for expat works on Windows (cygwin, mingw, Visual The cmake based buildsystem for expat works on Windows (cygwin, mingw, Visual
Studio) and should work on all other platform cmake supports. 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: build and change into that directory:
~/expat-2.6.4$ mkdir build && cd build ~/expat-2.7.0$ mkdir build && cd build
~/expat-2.6.4/build$ ~/expat-2.7.0/build$
From that directory, call cmake first, then call make, make test and From that directory, call cmake first, then call make, make test and
make install in the usual way: 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 C compiler identification is GNU
-- The CXX compiler identification is GNU -- The CXX compiler identification is GNU
.... ....
-- Configuring done -- Configuring done
-- Generating 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 If you want to specify the install location for your files, append
-DCMAKE_INSTALL_PREFIX=/your/install/path to the cmake call. -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 Scanning dependencies of target expat
[ 5%] Building C object CMakeFiles/expat.dir/lib/xmlparse.c.o [ 5%] Building C object CMakeFiles/expat.dir/lib/xmlparse.c.o
[ 11%] Building C object CMakeFiles/expat.dir/lib/xmlrole.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) 2010 Patrick Spendrin <ps_ml@gmx.de>
# Copyright (c) 2012 Karl Waclawek <karl@waclawek.net> # 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 Sergei Nikulov <sergey.nikulov@gmail.com>
# Copyright (c) 2016 Björn Lindahl <bjorn.lindahl@foi.se> # Copyright (c) 2016 Björn Lindahl <bjorn.lindahl@foi.se>
# Copyright (c) 2016 Tobias Taschner <github@tc84.de> # Copyright (c) 2016 Tobias Taschner <github@tc84.de>
@ -30,15 +30,16 @@
# Copyright (c) 2020 Thomas Beutlich <tc@tbeu.de> # Copyright (c) 2020 Thomas Beutlich <tc@tbeu.de>
# Copyright (c) 2021 Alex Richardson <Alexander.Richardson@cl.cam.ac.uk> # Copyright (c) 2021 Alex Richardson <Alexander.Richardson@cl.cam.ac.uk>
# Copyright (c) 2022 Johnny Jazeix <jazeix@gmail.com> # 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> # Copyright (c) 2022 David Faure <david.faure@kdab.com>
# Unlike most of Expat, # Unlike most of Expat,
# this file is copyrighted under the BSD-license for buildsystem files of KDE. # 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 project(expat
VERSION VERSION
2.6.4 2.7.0
LANGUAGES LANGUAGES
C 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_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_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_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) if(UNIX OR _EXPAT_HELP)
expat_shy_set(EXPAT_WITH_LIBBSD OFF CACHE BOOL "Utilize libbsd (for arc4random_buf)") expat_shy_set(EXPAT_WITH_LIBBSD OFF CACHE BOOL "Utilize libbsd (for arc4random_buf)")
endif() endif()
@ -169,11 +170,15 @@ if(NOT _EXPAT_HELP)
mark_as_advanced(_EXPAT_M32) mark_as_advanced(_EXPAT_M32)
endif() 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 # We have to call enable_language() before modifying any CMAKE_CXX_* variables
enable_language(CXX) enable_language(CXX)
set(CMAKE_CXX_STANDARD 11) 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_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) # i.e. -std=c++11 rather than default -std=gnu++11 set(CMAKE_CXX_EXTENSIONS OFF) # i.e. -std=c++11 rather than default -std=gnu++11
endif() endif()
@ -320,7 +325,7 @@ if(FLAG_VISIBILITY)
endif() endif()
set(EXTRA_COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -fvisibility=hidden") set(EXTRA_COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -fvisibility=hidden")
endif() endif()
if(MINGW) if(MINGW AND ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU"))
# Without __USE_MINGW_ANSI_STDIO the compiler produces a false positive # Without __USE_MINGW_ANSI_STDIO the compiler produces a false positive
set(EXTRA_COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -Wno-pedantic-ms-format") set(EXTRA_COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -Wno-pedantic-ms-format")
endif() endif()
@ -467,7 +472,7 @@ foreach(build_type_upper
endforeach() endforeach()
set(LIBCURRENT 11) # sync set(LIBCURRENT 11) # sync
set(LIBREVISION 0) # with set(LIBREVISION 1) # with
set(LIBAGE 10) # configure.ac! set(LIBAGE 10) # configure.ac!
math(EXPR LIBCURRENT_MINUS_AGE "${LIBCURRENT} - ${LIBAGE}") math(EXPR LIBCURRENT_MINUS_AGE "${LIBCURRENT} - ${LIBAGE}")
@ -587,7 +592,7 @@ if(EXPAT_BUILD_TOOLS)
if(MINGW AND _EXPAT_UNICODE_WCHAR_T) if(MINGW AND _EXPAT_UNICODE_WCHAR_T)
# https://gcc.gnu.org/onlinedocs/gcc/x86-Windows-Options.html # 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() endif()
if(EXPAT_BUILD_DOCS) if(EXPAT_BUILD_DOCS)
@ -724,7 +729,7 @@ if(EXPAT_BUILD_FUZZERS)
message(SEND_ERROR message(SEND_ERROR
"OSS-Fuzz builds require the environment variable " "OSS-Fuzz builds require the environment variable "
"LIB_FUZZING_ENGINE to be set. If you are seeing this " "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.") "build setup.")
endif() endif()
@ -743,24 +748,78 @@ if(EXPAT_BUILD_FUZZERS)
target_link_libraries(${target_name} fuzzpat) target_link_libraries(${target_name} fuzzpat)
target_compile_definitions(${target_name} target_compile_definitions(${target_name}
PRIVATE ENCODING_FOR_FUZZING=${encoding_type}) 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) 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") set_target_properties(${target_name} PROPERTIES LINKER_LANGUAGE "CXX")
else() 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() endif()
set_property( set_property(
TARGET ${target_name} PROPERTY RUNTIME_OUTPUT_DIRECTORY fuzz) TARGET ${target_name} PROPERTY RUNTIME_OUTPUT_DIRECTORY fuzz)
endforeach() endforeach()
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() else()
if(EXPAT_OSSFUZZ_BUILD) if(EXPAT_OSSFUZZ_BUILD)
message(SEND_ERROR 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 " "This is likely in error - consider adding "
"-DEXPAT_BUILD_FUZZERS=ON to your cmake execution.") "-DEXPAT_BUILD_FUZZERS=ON to your cmake execution.")
endif() endif()
@ -913,13 +972,7 @@ elseif(EXPAT_CHAR_TYPE STREQUAL "wchar_t")
else() else()
set(_EXPAT_CHAR_TYPE_SUMMARY "ERROR") set(_EXPAT_CHAR_TYPE_SUMMARY "ERROR")
endif() endif()
# NOTE: We're not accessing global property GENERATOR_IS_MULTI_CONFIG get_property(_EXPAT_GENERATOR_IS_MULTI_CONFIG 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()
message(STATUS "===========================================================================") message(STATUS "===========================================================================")
message(STATUS "") message(STATUS "")

@ -11,16 +11,23 @@
!! The following topics need *additional skilled C developers* to progress !! !! The following topics need *additional skilled C developers* to progress !!
!! in a timely manner or at all (loosely ordered by descending priority): !! !! 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 !! !! - teaming up on researching and fixing future security reports and !!
!! ClusterFuzz findings with few-days-max response times in communication !! !! 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 !! !! in order to (1) have a sound fix ready before the end of a 90 days !!
!! grace period and (2) in a sustainable manner, !! !! 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 !! !! - implementing and auto-testing XML 1.0r5 support !!
!! (needs discussion before pull requests), !! !! (needs discussion before pull requests), !!
!! - smart ideas on fixing the Autotools CMake files generation issue !! !! - smart ideas on fixing the Autotools CMake files generation issue !!
!! without breaking CI (needs discussion before pull requests), !! !! without breaking CI (needs discussion before pull requests), !!
!! - the Windows binaries topic (needs requirements engineering first), !!
!! - pushing migration from `int` to `size_t` further !! !! - pushing migration from `int` to `size_t` further !!
!! including edge-cases test coverage (needs discussion before anything). !! !! including edge-cases test coverage (needs discussion before anything). !!
!! !! !! !!
@ -30,6 +37,78 @@
!! THANK YOU! Sebastian Pipping -- Berlin, 2024-03-09 !! !! 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 Release 2.6.4 Wed November 6 2024
Security fixes: Security fixes:
#915 CVE-2024-50602 -- Fix crash within function XML_ResumeParser #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 #904 tests: Resolve duplicate handler
#317 #918 tests: Improve tests on doctype closing (ex CVE-2019-15903) #317 #918 tests: Improve tests on doctype closing (ex CVE-2019-15903)
#914 Fix signedness of format strings #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) #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/ to 11:0:10 (libexpat*.so.1.10.0); see https://verbump.de/
for what these numbers do for what these numbers do

@ -11,7 +11,7 @@
> at the top of the `Changes` file. > 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 This is Expat, a C99 library for parsing
[XML 1.0 Fourth Edition](https://www.w3.org/TR/2006/REC-xml-20060816/), started by [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 document being parsed. A start tag is an example of the kind of
structures for which you may register handlers. 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 - LLVM Clang >=3.5
- Microsoft Visual Studio >=16.0/2019 (rolling `${today} minus 5 years`) - 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: Notice the *uppercase* `EXPAT` in the following example:
```cmake ```cmake
cmake_minimum_required(VERSION 3.0) # or 3.10, see below cmake_minimum_required(VERSION 3.10)
project(hello VERSION 1.0.0) project(hello VERSION 1.0.0)
@ -62,12 +62,7 @@ add_executable(hello
hello.c hello.c
) )
# a) for CMake >=3.10 (see CMake's FindEXPAT docs)
target_link_libraries(hello PUBLIC EXPAT::EXPAT) 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 ### b) `find_package` with Config Mode
@ -85,7 +80,7 @@ or
Notice the *lowercase* `expat` in the following example: Notice the *lowercase* `expat` in the following example:
```cmake ```cmake
cmake_minimum_required(VERSION 3.0) cmake_minimum_required(VERSION 3.10)
project(hello VERSION 1.0.0) project(hello VERSION 1.0.0)
@ -295,7 +290,7 @@ EXPAT_ENABLE_INSTALL:BOOL=ON
// Use /MT flag (static CRT) when compiling in MSVC // Use /MT flag (static CRT) when compiling in MSVC
EXPAT_MSVC_STATIC_CRT:BOOL=OFF 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 EXPAT_OSSFUZZ_BUILD:BOOL=OFF
// Build a shared expat library // Build a shared expat library

@ -8,12 +8,12 @@ set(CMAKE_IMPORT_FILE_VERSION 1)
# Import target "expat::expat" for configuration "NoConfig" # Import target "expat::expat" for configuration "NoConfig"
set_property(TARGET expat::expat APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG) set_property(TARGET expat::expat APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG)
set_target_properties(expat::expat PROPERTIES 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" IMPORTED_SONAME_NOCONFIG "@rpath/libexpat.@SO_MAJOR@.dylib"
) )
list(APPEND _cmake_import_check_targets expat::expat ) 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. # Commands beyond this point should not need to know the version.
set(CMAKE_IMPORT_FILE_VERSION) set(CMAKE_IMPORT_FILE_VERSION)

@ -1,13 +1,13 @@
# Generated by CMake # Generated by CMake
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8) 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() endif()
if(CMAKE_VERSION VERSION_LESS "2.8.12") if(CMAKE_VERSION VERSION_LESS "2.8.12")
message(FATAL_ERROR "CMake >= 2.8.12 required") message(FATAL_ERROR "CMake >= 2.8.12 required")
endif() endif()
cmake_policy(PUSH) cmake_policy(PUSH)
cmake_policy(VERSION 2.8.12...3.28) cmake_policy(VERSION 2.8.12...3.29)
#---------------------------------------------------------------- #----------------------------------------------------------------
# Generated CMake target import file. # 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) 2000-2005 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
dnl Copyright (c) 2001-2003 Greg Stein <gstein@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) 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 S. P. Zeidler <spz@netbsd.org>
dnl Copyright (c) 2017 Stephen Groat <stephen@groat.us> dnl Copyright (c) 2017 Stephen Groat <stephen@groat.us>
dnl Copyright (c) 2017-2020 Joe Orton <jorton@redhat.com> 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 dnl
LIBCURRENT=11 # sync LIBCURRENT=11 # sync
LIBREVISION=0 # with LIBREVISION=1 # with
LIBAGE=10 # CMakeLists.txt! LIBAGE=10 # CMakeLists.txt!
AC_CONFIG_HEADERS([expat_config.h]) AC_CONFIG_HEADERS([expat_config.h])

@ -2,7 +2,7 @@
## DO NOT EDIT - This file generated from ./build-aux/ltmain.in ## DO NOT EDIT - This file generated from ./build-aux/ltmain.in
## by inline-source v2019-02-19.15 ## 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. # Provide generalized library-building support services.
# Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 # Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
@ -31,8 +31,8 @@
PROGRAM=libtool PROGRAM=libtool
PACKAGE=libtool PACKAGE=libtool
VERSION=2.5.3 VERSION=2.5.4
package_revision=2.5.3 package_revision=2.5.4
## ------ ## ## ------ ##
@ -589,7 +589,7 @@ func_require_term_colors ()
# _G_HAVE_PLUSEQ_OP # _G_HAVE_PLUSEQ_OP
# Can be empty, in which case the shell is probed, "yes" if += is # 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" \ test -z "$_G_HAVE_PLUSEQ_OP" \
&& (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \
&& _G_HAVE_PLUSEQ_OP=yes && _G_HAVE_PLUSEQ_OP=yes
@ -739,7 +739,7 @@ eval 'func_dirname ()
# to NONDIR_REPLACEMENT. # to NONDIR_REPLACEMENT.
# value returned in "$func_dirname_result" # value returned in "$func_dirname_result"
# basename: Compute filename of FILE. # 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 # For efficiency, we do not delegate to the functions above but instead
# duplicate the functionality here. # duplicate the functionality here.
eval 'func_dirname_and_basename () eval 'func_dirname_and_basename ()
@ -897,7 +897,7 @@ func_mkdir_p ()
# While some portion of DIR does not yet exist... # While some portion of DIR does not yet exist...
while test ! -d "$_G_directory_path"; do while test ! -d "$_G_directory_path"; do
# ...make a list in topmost first order. Use a colon delimited # ...make a list in topmost first order. Use a colon delimited
# list incase some portion of path contains whitespace. # list in case some portion of path contains whitespace.
_G_dir_list=$_G_directory_path:$_G_dir_list _G_dir_list=$_G_directory_path:$_G_dir_list
# If the last portion added has no slash in it, the list is done # If the last portion added has no slash in it, the list is done
@ -2215,7 +2215,30 @@ func_version ()
# End: # End:
# Set a version string. # 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... # 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. ## ## Options parsing. ##
## ---------------- ## ## ---------------- ##
@ -2261,19 +2272,23 @@ usage='$progpath [OPTION]... [MODE-ARG]...'
# Short help message in response to '-h'. # Short help message in response to '-h'.
usage_message="Options: usage_message="Options:
--config show all configuration variables --config show all configuration variables
--debug enable verbose shell tracing --debug enable verbose shell tracing
-n, --dry-run display commands without modifying any files -n, --dry-run display commands without modifying any files
--features display basic configuration information and exit --features display basic configuration information
--mode=MODE use operation mode MODE --finish use operation '--mode=finish'
--no-warnings equivalent to '-Wnone' --mode=MODE use operation mode MODE
--preserve-dup-deps don't remove duplicate dependency libraries --no-finish don't update shared library cache
--quiet, --silent don't print informational messages --no-quiet, --no-silent print default informational messages
--tag=TAG use configuration variables from tag TAG --no-warnings equivalent to '-Wnone'
-v, --verbose print more informational messages than default --preserve-dup-deps don't remove duplicate dependency libraries
--version print version information --quiet, --silent don't print informational messages
-W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] --reorder-cache=DIRS reorder shared library cache for preferred DIRS
-h, --help, --help-all print short, long, or detailed help message --tag=TAG use configuration variables from tag TAG
-v, --verbose print more informational messages than default
--version print version information
-W, --warnings=CATEGORY report the warnings falling in CATEGORY [all]
-h, --help, --help-all print short, long, or detailed help message
" "
# Additional text appended to 'usage_message' in response to '--help'. # Additional text appended to 'usage_message' in response to '--help'.
@ -2306,7 +2321,7 @@ include the following information:
compiler: $LTCC compiler: $LTCC
compiler flags: $LTCFLAGS compiler flags: $LTCFLAGS
linker: $LD (gnu? $with_gnu_ld) linker: $LD (gnu? $with_gnu_ld)
version: $progname (GNU libtool) 2.5.3 version: $progname $scriptversion
automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q`
autoconf: `($AUTOCONF --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_dry_run=false
opt_help=false opt_help=false
opt_mode= opt_mode=
opt_reorder_cache=false
opt_preserve_dup_deps=false opt_preserve_dup_deps=false
opt_quiet=false opt_quiet=false
opt_finishing=true
opt_warning=
nonopt= nonopt=
preserve_args= preserve_args=
@ -2593,14 +2611,18 @@ libtool_parse_options ()
clean|compile|execute|finish|install|link|relink|uninstall) ;; clean|compile|execute|finish|install|link|relink|uninstall) ;;
# Catch anything else as an error # Catch anything else as an error
*) func_error "invalid argument for $_G_opt" *) func_error "invalid argument '$1' for $_G_opt"
exit_cmd=exit exit_cmd=exit
break
;; ;;
esac esac
shift shift
;; ;;
--no-finish)
opt_finishing=false
func_append preserve_args " $_G_opt"
;;
--no-silent|--no-quiet) --no-silent|--no-quiet)
opt_quiet=false opt_quiet=false
func_append preserve_args " $_G_opt" func_append preserve_args " $_G_opt"
@ -2616,6 +2638,24 @@ libtool_parse_options ()
func_append preserve_args " $_G_opt" 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) --silent|--quiet)
opt_quiet=: opt_quiet=:
opt_verbose=false opt_verbose=false
@ -2652,6 +2692,18 @@ libtool_parse_options ()
func_add_hook func_parse_options 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]... # libtool_validate_options [ARG]...
# --------------------------------- # ---------------------------------
@ -3181,6 +3233,15 @@ func_convert_path_front_back_pathsep ()
# end 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 # # $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 arg...
func_mode_compile () func_mode_compile ()
{ {
@ -4087,6 +4207,12 @@ if $opt_help; then
fi 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 arg...
func_mode_execute () func_mode_execute ()
{ {
@ -4271,7 +4397,7 @@ func_mode_finish ()
fi fi
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 for libdir in $libdirs; do
if test -n "$finish_cmds"; then if test -n "$finish_cmds"; then
# Do each command in the finish commands. # Do each command in the finish commands.
@ -4296,6 +4422,12 @@ func_mode_finish ()
for libdir in $libdirs; do for libdir in $libdirs; do
$ECHO " $libdir" $ECHO " $libdir"
done 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
echo "If you ever happen to want to link against installed libraries" echo "If you ever happen to want to link against installed libraries"
echo "in a given directory, LIBDIR, you must either use libtool, and" echo "in a given directory, LIBDIR, you must either use libtool, and"
@ -4532,8 +4664,15 @@ func_mode_install ()
func_append dir "$objdir" func_append dir "$objdir"
if test -n "$relink_command"; then 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. # 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 # Don't allow the user to place us outside of our expected
# location b/c this prevents finding dependent libraries that # location b/c this prevents finding dependent libraries that
@ -6782,6 +6921,7 @@ func_mode_link ()
finalize_command=$nonopt finalize_command=$nonopt
compile_rpath= compile_rpath=
compile_rpath_tail=
finalize_rpath= finalize_rpath=
compile_shlibpath= compile_shlibpath=
finalize_shlibpath= finalize_shlibpath=
@ -7337,7 +7477,8 @@ func_mode_link ()
# Tru64 UNIX uses -model [arg] to determine the layout of C++ # Tru64 UNIX uses -model [arg] to determine the layout of C++
# classes, name mangling, and exception handling. # classes, name mangling, and exception handling.
# Darwin uses the -arch flag to determine output architecture. # 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 compiler_flags " $arg"
func_append compile_command " $arg" func_append compile_command " $arg"
func_append finalize_command " $arg" func_append finalize_command " $arg"
@ -8433,10 +8574,11 @@ func_mode_link ()
case " $sys_lib_dlsearch_path " in case " $sys_lib_dlsearch_path " in
*" $absdir "*) ;; *" $absdir "*) ;;
*) *)
case "$compile_rpath " in case "$compile_rpath$compile_rpath_tail " in
*" $absdir "*) ;; *" $absdir "*) ;;
*) case $absdir in *) case $absdir in
"$progdir/"*) func_append compile_rpath " $absdir" ;; "$progdir/"*) func_append compile_rpath " $absdir" ;;
*) func_append compile_rpath_tail " $absdir" ;;
esac esac
esac esac
;; ;;
@ -8509,10 +8651,11 @@ func_mode_link ()
case " $sys_lib_dlsearch_path " in case " $sys_lib_dlsearch_path " in
*" $absdir "*) ;; *" $absdir "*) ;;
*) *)
case "$compile_rpath " in case "$compile_rpath$compile_rpath_tail " in
*" $absdir "*) ;; *" $absdir "*) ;;
*) case $absdir in *) case $absdir in
"$progdir/"*) func_append compile_rpath " $absdir" ;; "$progdir/"*) func_append compile_rpath " $absdir" ;;
*) func_append compile_rpath_tail " $absdir" ;;
esac esac
esac esac
;; ;;
@ -8588,6 +8731,7 @@ func_mode_link ()
case $host in case $host in
*-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;;
*-*-sysv4*uw2*) add_dir=-L$dir ;; *-*-sysv4*uw2*) add_dir=-L$dir ;;
*-*-emscripten*) add_dir=-L$dir ;;
*-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
*-*-unixware7*) add_dir=-L$dir ;; *-*-unixware7*) add_dir=-L$dir ;;
*-*-darwin* ) *-*-darwin* )
@ -8876,6 +9020,8 @@ func_mode_link ()
done # for deplib in $libs done # for deplib in $libs
func_append temp_rpath "$temp_rpath_tail" func_append temp_rpath "$temp_rpath_tail"
func_append compile_rpath "$compile_rpath_tail"
if test link = "$pass"; then if test link = "$pass"; then
if test prog = "$linkmode"; then if test prog = "$linkmode"; then
compile_deplibs="$new_inherited_linker_flags $compile_deplibs" compile_deplibs="$new_inherited_linker_flags $compile_deplibs"
@ -9163,6 +9309,9 @@ func_mode_link ()
revision=$number_minor revision=$number_minor
lt_irix_increment=no lt_irix_increment=no
;; ;;
*)
func_fatal_configuration "$modename: unknown library version type '$version_type'"
;;
esac esac
;; ;;
no) no)
@ -10059,20 +10208,7 @@ func_mode_link ()
last_robj= last_robj=
k=1 k=1
if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then if test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; 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
output=$output_objdir/$output_la.lnk output=$output_objdir/$output_la.lnk
func_verbose "creating linker input file list: $output" func_verbose "creating linker input file list: $output"
: > $output : > $output
@ -10091,6 +10227,19 @@ func_mode_link ()
func_append delfiles " $output" func_append delfiles " $output"
func_to_tool_file "$output" func_to_tool_file "$output"
output=$firstobj\"$file_list_spec$func_to_tool_file_result\" 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 else
if test -n "$save_libobjs"; then if test -n "$save_libobjs"; then
func_verbose "creating reloadable object files..." func_verbose "creating reloadable object files..."

@ -14,7 +14,7 @@
Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net> Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
Copyright (c) 2000-2004 Fred L. Drake, Jr. <fdrake@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) 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) 2017 Jakub Wilk <jwilk@jwilk.net>
Copyright (c) 2021 Tomas Korbar <tkorbar@redhat.com> Copyright (c) 2021 Tomas Korbar <tkorbar@redhat.com>
Copyright (c) 2021 Nicolas Cavallari <nicolas.cavallari@green-communications.fr> Copyright (c) 2021 Nicolas Cavallari <nicolas.cavallari@green-communications.fr>
@ -52,7 +52,7 @@
<div> <div>
<h1> <h1>
The Expat XML Parser The Expat XML Parser
<small>Release 2.6.4</small> <small>Release 2.7.0</small>
</h1> </h1>
</div> </div>
<div class="content"> <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 <code>XML_STATUS_ERROR</code> otherwise. The possible error codes
are:</p> are:</p>
<dl> <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> <dt><code>XML_ERROR_SUSPENDED</code></dt>
<dd>when suspending an already suspended parser.</dd> <dd>when suspending an already suspended parser.</dd>
<dt><code>XML_ERROR_FINISHED</code></dt> <dt><code>XML_ERROR_FINISHED</code></dt>

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

@ -9,7 +9,7 @@
Copyright (c) 2001 Scott Bronson <bronson@rinspin.com> Copyright (c) 2001 Scott Bronson <bronson@rinspin.com>
Copyright (c) 2002-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net> Copyright (c) 2002-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2009 Karl Waclawek <karl@waclawek.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) 2016 Ardo van Rangelrooij <ardo@debian.org>
Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
Copyright (c) 2020 Joe Orton <jorton@redhat.com> Copyright (c) 2020 Joe Orton <jorton@redhat.com>
@ -21,7 +21,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
<!ENTITY dhfirstname "<firstname>Scott</firstname>"> <!ENTITY dhfirstname "<firstname>Scott</firstname>">
<!ENTITY dhsurname "<surname>Bronson</surname>"> <!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. --> <!-- Please adjust this^^ date whenever cutting a new release. -->
<!ENTITY dhsection "<manvolnum>1</manvolnum>"> <!ENTITY dhsection "<manvolnum>1</manvolnum>">
<!ENTITY dhemail "<email>bronson@rinspin.com</email>"> <!ENTITY dhemail "<email>bronson@rinspin.com</email>">

@ -83,7 +83,7 @@
#define PACKAGE_NAME "expat" #define PACKAGE_NAME "expat"
/* Define to the full name and version of this package. */ /* 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 to the one symbol short name of this package. */
#define PACKAGE_TARNAME "expat" #define PACKAGE_TARNAME "expat"
@ -92,7 +92,7 @@
#define PACKAGE_URL "" #define PACKAGE_URL ""
/* Define to the version of this package. */ /* 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 /* 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 required in a freestanding environment). This macro is provided for
@ -100,7 +100,7 @@
#define STDC_HEADERS 1 #define STDC_HEADERS 1
/* Version number of package */ /* 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 /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */ 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 not use this file except in compliance with the License.
* You may obtain a copy of the License at * 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 * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * 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 not use this file except in compliance with the License.
* You may obtain a copy of the License at * 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 * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * 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) 2000-2005 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2001-2002 Greg Stein <gstein@users.sourceforge.net> Copyright (c) 2001-2002 Greg Stein <gstein@users.sourceforge.net>
Copyright (c) 2002-2016 Karl Waclawek <karl@waclawek.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 Cristian Rodríguez <crrodriguez@opensuse.org>
Copyright (c) 2016 Thomas Beutlich <tc@tbeu.de> Copyright (c) 2016 Thomas Beutlich <tc@tbeu.de>
Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> 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 See https://semver.org
*/ */
#define XML_MAJOR_VERSION 2 #define XML_MAJOR_VERSION 2
#define XML_MINOR_VERSION 6 #define XML_MINOR_VERSION 7
#define XML_MICRO_VERSION 4 #define XML_MICRO_VERSION 0
#ifdef __cplusplus #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) 2002-2016 Karl Waclawek <karl@waclawek.net>
Copyright (c) 2005-2009 Steven Solie <steven@solie.ca> Copyright (c) 2005-2009 Steven Solie <steven@solie.ca>
Copyright (c) 2016 Eric Rahm <erahm@mozilla.com> 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 Gaurav <g.gupta@samsung.com>
Copyright (c) 2016 Thomas Beutlich <tc@tbeu.de> Copyright (c) 2016 Thomas Beutlich <tc@tbeu.de>
Copyright (c) 2016 Gustavo Grieco <gustavo.grieco@imag.fr> Copyright (c) 2016 Gustavo Grieco <gustavo.grieco@imag.fr>
@ -39,7 +39,7 @@
Copyright (c) 2022 Sean McBride <sean@rogue-research.com> Copyright (c) 2022 Sean McBride <sean@rogue-research.com>
Copyright (c) 2023 Owain Davies <owaind@bath.edu> Copyright (c) 2023 Owain Davies <owaind@bath.edu>
Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild@sony.com> 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> Copyright (c) 2024 Hanno Böck <hanno@gentoo.org>
Licensed under the MIT license: Licensed under the MIT license:
@ -325,6 +325,10 @@ typedef struct {
const XML_Char *publicId; const XML_Char *publicId;
const XML_Char *notation; const XML_Char *notation;
XML_Bool open; 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_param;
XML_Bool is_internal; /* true if declared in internal subset outside PE */ XML_Bool is_internal; /* true if declared in internal subset outside PE */
} ENTITY; } ENTITY;
@ -415,6 +419,12 @@ typedef struct {
int *scaffIndex; int *scaffIndex;
} DTD; } DTD;
enum EntityType {
ENTITY_INTERNAL,
ENTITY_ATTRIBUTE,
ENTITY_VALUE,
};
typedef struct open_internal_entity { typedef struct open_internal_entity {
const char *internalEventPtr; const char *internalEventPtr;
const char *internalEventEndPtr; const char *internalEventEndPtr;
@ -422,6 +432,7 @@ typedef struct open_internal_entity {
ENTITY *entity; ENTITY *entity;
int startTagLevel; int startTagLevel;
XML_Bool betweenDecl; /* WFC: PE Between Declarations */ XML_Bool betweenDecl; /* WFC: PE Between Declarations */
enum EntityType type;
} OPEN_INTERNAL_ENTITY; } OPEN_INTERNAL_ENTITY;
enum XML_Account { enum XML_Account {
@ -481,8 +492,8 @@ static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc,
const char *next, const char **nextPtr, const char *next, const char **nextPtr,
XML_Bool haveMore, XML_Bool allowClosingDoctype, XML_Bool haveMore, XML_Bool allowClosingDoctype,
enum XML_Account account); enum XML_Account account);
static enum XML_Error processInternalEntity(XML_Parser parser, ENTITY *entity, static enum XML_Error processEntity(XML_Parser parser, ENTITY *entity,
XML_Bool betweenDecl); XML_Bool betweenDecl, enum EntityType type);
static enum XML_Error doContent(XML_Parser parser, int startTagLevel, static enum XML_Error doContent(XML_Parser parser, int startTagLevel,
const ENCODING *enc, const char *start, const ENCODING *enc, const char *start,
const char *end, const char **endPtr, const char *end, const char **endPtr,
@ -513,18 +524,22 @@ static enum XML_Error storeAttributeValue(XML_Parser parser,
const char *ptr, const char *end, const char *ptr, const char *end,
STRING_POOL *pool, STRING_POOL *pool,
enum XML_Account account); enum XML_Account account);
static enum XML_Error appendAttributeValue(XML_Parser parser, static enum XML_Error
const ENCODING *enc, appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
XML_Bool isCdata, const char *ptr, const char *ptr, const char *end, STRING_POOL *pool,
const char *end, STRING_POOL *pool, enum XML_Account account, const char **nextPtr);
enum XML_Account account);
static ATTRIBUTE_ID *getAttributeId(XML_Parser parser, const ENCODING *enc, static ATTRIBUTE_ID *getAttributeId(XML_Parser parser, const ENCODING *enc,
const char *start, const char *end); const char *start, const char *end);
static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType); static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType);
#if XML_GE == 1 #if XML_GE == 1
static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc, static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc,
const char *start, const char *end, const char *start, const char *end,
enum XML_Account account); 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 #else
static enum XML_Error storeSelfEntityValue(XML_Parser parser, ENTITY *entity); static enum XML_Error storeSelfEntityValue(XML_Parser parser, ENTITY *entity);
#endif #endif
@ -709,6 +724,10 @@ struct XML_ParserStruct {
const char *m_positionPtr; const char *m_positionPtr;
OPEN_INTERNAL_ENTITY *m_openInternalEntities; OPEN_INTERNAL_ENTITY *m_openInternalEntities;
OPEN_INTERNAL_ENTITY *m_freeInternalEntities; 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; XML_Bool m_defaultExpandInternalEntities;
int m_tagLevel; int m_tagLevel;
ENTITY *m_declEntity; ENTITY *m_declEntity;
@ -756,6 +775,7 @@ struct XML_ParserStruct {
ACCOUNTING m_accounting; ACCOUNTING m_accounting;
ENTITY_STATS m_entity_stats; ENTITY_STATS m_entity_stats;
#endif #endif
XML_Bool m_reenter;
}; };
#define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s))) #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) #if defined(XML_TESTING)
g_bytesScanned += (unsigned)have_now; g_bytesScanned += (unsigned)have_now;
#endif #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 (ret == XML_ERROR_NONE) {
// if we consumed nothing, remember what we had on this parse attempt. // if we consumed nothing, remember what we had on this parse attempt.
if (*endPtr == start) { if (*endPtr == start) {
@ -1139,6 +1181,8 @@ parserCreate(const XML_Char *encodingName,
parser->m_freeBindingList = NULL; parser->m_freeBindingList = NULL;
parser->m_freeTagList = NULL; parser->m_freeTagList = NULL;
parser->m_freeInternalEntities = NULL; parser->m_freeInternalEntities = NULL;
parser->m_freeAttributeEntities = NULL;
parser->m_freeValueEntities = NULL;
parser->m_groupSize = 0; parser->m_groupSize = 0;
parser->m_groupConnector = NULL; parser->m_groupConnector = NULL;
@ -1241,6 +1285,8 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) {
parser->m_eventEndPtr = NULL; parser->m_eventEndPtr = NULL;
parser->m_positionPtr = NULL; parser->m_positionPtr = NULL;
parser->m_openInternalEntities = NULL; parser->m_openInternalEntities = NULL;
parser->m_openAttributeEntities = NULL;
parser->m_openValueEntities = NULL;
parser->m_defaultExpandInternalEntities = XML_TRUE; parser->m_defaultExpandInternalEntities = XML_TRUE;
parser->m_tagLevel = 0; parser->m_tagLevel = 0;
parser->m_tagStack = NULL; parser->m_tagStack = NULL;
@ -1251,6 +1297,8 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) {
parser->m_unknownEncodingData = NULL; parser->m_unknownEncodingData = NULL;
parser->m_parentParser = NULL; parser->m_parentParser = NULL;
parser->m_parsingStatus.parsing = XML_INITIALIZED; parser->m_parsingStatus.parsing = XML_INITIALIZED;
// Reentry can only be triggered inside m_processor calls
parser->m_reenter = XML_FALSE;
#ifdef XML_DTD #ifdef XML_DTD
parser->m_isParamEntity = XML_FALSE; parser->m_isParamEntity = XML_FALSE;
parser->m_useForeignDTD = 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; openEntity->next = parser->m_freeInternalEntities;
parser->m_freeInternalEntities = openEntity; 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); moveToFreeBindingList(parser, parser->m_inheritedBindings);
FREE(parser, parser->m_unknownEncodingMem); FREE(parser, parser->m_unknownEncodingMem);
if (parser->m_unknownEncodingRelease) if (parser->m_unknownEncodingRelease)
@ -1323,6 +1389,19 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) {
return XML_TRUE; 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 enum XML_Status XMLCALL
XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) { XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) {
if (parser == NULL) 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 There's no way for the caller to determine which of the
XXX possible error cases caused the XML_STATUS_ERROR return. XXX possible error cases caused the XML_STATUS_ERROR return.
*/ */
if (parser->m_parsingStatus.parsing == XML_PARSING if (parserBusy(parser))
|| parser->m_parsingStatus.parsing == XML_SUSPENDED)
return XML_STATUS_ERROR; return XML_STATUS_ERROR;
/* Get rid of any previous encoding name */ /* Get rid of any previous encoding name */
@ -1569,7 +1647,34 @@ XML_ParserFree(XML_Parser parser) {
entityList = entityList->next; entityList = entityList->next;
FREE(parser, openEntity); 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_freeBindingList, parser);
destroyBindings(parser->m_inheritedBindings, parser); destroyBindings(parser->m_inheritedBindings, parser);
poolDestroy(&parser->m_tempPool); poolDestroy(&parser->m_tempPool);
@ -1611,8 +1716,7 @@ XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD) {
return XML_ERROR_INVALID_ARGUMENT; return XML_ERROR_INVALID_ARGUMENT;
#ifdef XML_DTD #ifdef XML_DTD
/* block after XML_Parse()/XML_ParseBuffer() has been called */ /* block after XML_Parse()/XML_ParseBuffer() has been called */
if (parser->m_parsingStatus.parsing == XML_PARSING if (parserBusy(parser))
|| parser->m_parsingStatus.parsing == XML_SUSPENDED)
return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING; return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
parser->m_useForeignDTD = useDTD; parser->m_useForeignDTD = useDTD;
return XML_ERROR_NONE; return XML_ERROR_NONE;
@ -1627,8 +1731,7 @@ XML_SetReturnNSTriplet(XML_Parser parser, int do_nst) {
if (parser == NULL) if (parser == NULL)
return; return;
/* block after XML_Parse()/XML_ParseBuffer() has been called */ /* block after XML_Parse()/XML_ParseBuffer() has been called */
if (parser->m_parsingStatus.parsing == XML_PARSING if (parserBusy(parser))
|| parser->m_parsingStatus.parsing == XML_SUSPENDED)
return; return;
parser->m_ns_triplets = do_nst ? XML_TRUE : XML_FALSE; parser->m_ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
} }
@ -1897,8 +2000,7 @@ XML_SetParamEntityParsing(XML_Parser parser,
if (parser == NULL) if (parser == NULL)
return 0; return 0;
/* block after XML_Parse()/XML_ParseBuffer() has been called */ /* block after XML_Parse()/XML_ParseBuffer() has been called */
if (parser->m_parsingStatus.parsing == XML_PARSING if (parserBusy(parser))
|| parser->m_parsingStatus.parsing == XML_SUSPENDED)
return 0; return 0;
#ifdef XML_DTD #ifdef XML_DTD
parser->m_paramEntityParsing = peParsing; parser->m_paramEntityParsing = peParsing;
@ -1915,8 +2017,7 @@ XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) {
if (parser->m_parentParser) if (parser->m_parentParser)
return XML_SetHashSalt(parser->m_parentParser, hash_salt); return XML_SetHashSalt(parser->m_parentParser, hash_salt);
/* block after XML_Parse()/XML_ParseBuffer() has been called */ /* block after XML_Parse()/XML_ParseBuffer() has been called */
if (parser->m_parsingStatus.parsing == XML_PARSING if (parserBusy(parser))
|| parser->m_parsingStatus.parsing == XML_SUSPENDED)
return 0; return 0;
parser->m_hash_secret_salt = hash_salt; parser->m_hash_secret_salt = hash_salt;
return 1; return 1;
@ -2230,6 +2331,11 @@ XML_GetBuffer(XML_Parser parser, int len) {
return parser->m_bufferEnd; return parser->m_bufferEnd;
} }
static void
triggerReenter(XML_Parser parser) {
parser->m_reenter = XML_TRUE;
}
enum XML_Status XMLCALL enum XML_Status XMLCALL
XML_StopParser(XML_Parser parser, XML_Bool resumable) { XML_StopParser(XML_Parser parser, XML_Bool resumable) {
if (parser == NULL) if (parser == NULL)
@ -2704,8 +2810,9 @@ static enum XML_Error PTRCALL
contentProcessor(XML_Parser parser, const char *start, const char *end, contentProcessor(XML_Parser parser, const char *start, const char *end,
const char **endPtr) { const char **endPtr) {
enum XML_Error result = doContent( enum XML_Error result = doContent(
parser, 0, parser->m_encoding, start, end, endPtr, parser, parser->m_parentParser ? 1 : 0, parser->m_encoding, start, end,
(XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_ACCOUNT_DIRECT); endPtr, (XML_Bool)! parser->m_parsingStatus.finalBuffer,
XML_ACCOUNT_DIRECT);
if (result == XML_ERROR_NONE) { if (result == XML_ERROR_NONE) {
if (! storeRawNames(parser)) if (! storeRawNames(parser))
return XML_ERROR_NO_MEMORY; return XML_ERROR_NO_MEMORY;
@ -2793,6 +2900,11 @@ externalEntityInitProcessor3(XML_Parser parser, const char *start,
return XML_ERROR_NONE; return XML_ERROR_NONE;
case XML_FINISHED: case XML_FINISHED:
return XML_ERROR_ABORTED; return XML_ERROR_ABORTED;
case XML_PARSING:
if (parser->m_reenter) {
return XML_ERROR_UNEXPECTED_STATE; // LCOV_EXCL_LINE
}
/* Fall through */
default: default:
start = next; start = next;
} }
@ -2966,7 +3078,7 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
reportDefault(parser, enc, s, next); reportDefault(parser, enc, s, next);
break; break;
} }
result = processInternalEntity(parser, entity, XML_FALSE); result = processEntity(parser, entity, XML_FALSE, ENTITY_INTERNAL);
if (result != XML_ERROR_NONE) if (result != XML_ERROR_NONE)
return result; return result;
} else if (parser->m_externalEntityRefHandler) { } else if (parser->m_externalEntityRefHandler) {
@ -3092,7 +3204,9 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
} }
if ((parser->m_tagLevel == 0) if ((parser->m_tagLevel == 0)
&& (parser->m_parsingStatus.parsing != XML_FINISHED)) { && (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; parser->m_processor = epilogProcessor;
else else
return epilogProcessor(parser, next, end, nextPtr); return epilogProcessor(parser, next, end, nextPtr);
@ -3153,7 +3267,9 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
} }
if ((parser->m_tagLevel == 0) if ((parser->m_tagLevel == 0)
&& (parser->m_parsingStatus.parsing != XML_FINISHED)) { && (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; parser->m_processor = epilogProcessor;
else else
return epilogProcessor(parser, next, end, nextPtr); return epilogProcessor(parser, next, end, nextPtr);
@ -3293,6 +3409,12 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
return XML_ERROR_NONE; return XML_ERROR_NONE;
case XML_FINISHED: case XML_FINISHED:
return XML_ERROR_ABORTED; return XML_ERROR_ABORTED;
case XML_PARSING:
if (parser->m_reenter) {
*nextPtr = next;
return XML_ERROR_NONE;
}
/* Fall through */
default:; default:;
} }
} }
@ -4217,6 +4339,11 @@ doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
return XML_ERROR_NONE; return XML_ERROR_NONE;
case XML_FINISHED: case XML_FINISHED:
return XML_ERROR_ABORTED; return XML_ERROR_ABORTED;
case XML_PARSING:
if (parser->m_reenter) {
return XML_ERROR_UNEXPECTED_STATE; // LCOV_EXCL_LINE
}
/* Fall through */
default:; default:;
} }
} }
@ -4549,7 +4676,7 @@ entityValueInitProcessor(XML_Parser parser, const char *s, const char *end,
} }
/* found end of entity value - can store it now */ /* found end of entity value - can store it now */
return storeEntityValue(parser, parser->m_encoding, s, end, return storeEntityValue(parser, parser->m_encoding, s, end,
XML_ACCOUNT_DIRECT); XML_ACCOUNT_DIRECT, NULL);
} else if (tok == XML_TOK_XML_DECL) { } else if (tok == XML_TOK_XML_DECL) {
enum XML_Error result; enum XML_Error result;
result = processXmlDecl(parser, 0, start, next); result = processXmlDecl(parser, 0, start, next);
@ -4676,7 +4803,7 @@ entityValueProcessor(XML_Parser parser, const char *s, const char *end,
break; break;
} }
/* found end of entity value - can store it now */ /* 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; start = next;
} }
@ -5119,9 +5246,9 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
#if XML_GE == 1 #if XML_GE == 1
// This will store the given replacement text in // This will store the given replacement text in
// parser->m_declEntity->textPtr. // parser->m_declEntity->textPtr.
enum XML_Error result enum XML_Error result = callStoreEntityValue(
= storeEntityValue(parser, enc, s + enc->minBytesPerChar, parser, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar,
next - enc->minBytesPerChar, XML_ACCOUNT_NONE); XML_ACCOUNT_NONE);
if (parser->m_declEntity) { if (parser->m_declEntity) {
parser->m_declEntity->textPtr = poolStart(&dtd->entityValuePool); parser->m_declEntity->textPtr = poolStart(&dtd->entityValuePool);
parser->m_declEntity->textLen 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; enum XML_Error result;
XML_Bool betweenDecl XML_Bool betweenDecl
= (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE); = (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) if (result != XML_ERROR_NONE)
return result; return result;
handleDefault = XML_FALSE; handleDefault = XML_FALSE;
@ -5751,6 +5878,12 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
return XML_ERROR_NONE; return XML_ERROR_NONE;
case XML_FINISHED: case XML_FINISHED:
return XML_ERROR_ABORTED; return XML_ERROR_ABORTED;
case XML_PARSING:
if (parser->m_reenter) {
*nextPtr = next;
return XML_ERROR_NONE;
}
/* Fall through */
default: default:
s = next; s = next;
tok = XmlPrologTok(enc, s, end, &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; return XML_ERROR_NONE;
case XML_FINISHED: case XML_FINISHED:
return XML_ERROR_ABORTED; return XML_ERROR_ABORTED;
case XML_PARSING:
if (parser->m_reenter) {
return XML_ERROR_UNEXPECTED_STATE; // LCOV_EXCL_LINE
}
/* Fall through */
default:; default:;
} }
} }
} }
static enum XML_Error static enum XML_Error
processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) { processEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl,
const char *textStart, *textEnd; enum EntityType type) {
const char *next; OPEN_INTERNAL_ENTITY *openEntity, **openEntityList, **freeEntityList;
enum XML_Error result; switch (type) {
OPEN_INTERNAL_ENTITY *openEntity; 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) { if (*freeEntityList) {
openEntity = parser->m_freeInternalEntities; openEntity = *freeEntityList;
parser->m_freeInternalEntities = openEntity->next; *freeEntityList = openEntity->next;
} else { } else {
openEntity openEntity
= (OPEN_INTERNAL_ENTITY *)MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY)); = (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; return XML_ERROR_NO_MEMORY;
} }
entity->open = XML_TRUE; entity->open = XML_TRUE;
entity->hasMore = XML_TRUE;
#if XML_GE == 1 #if XML_GE == 1
entityTrackingOnOpen(parser, entity, __LINE__); entityTrackingOnOpen(parser, entity, __LINE__);
#endif #endif
entity->processed = 0; entity->processed = 0;
openEntity->next = parser->m_openInternalEntities; openEntity->next = *openEntityList;
parser->m_openInternalEntities = openEntity; *openEntityList = openEntity;
openEntity->entity = entity; openEntity->entity = entity;
openEntity->type = type;
openEntity->startTagLevel = parser->m_tagLevel; openEntity->startTagLevel = parser->m_tagLevel;
openEntity->betweenDecl = betweenDecl; openEntity->betweenDecl = betweenDecl;
openEntity->internalEventPtr = NULL; openEntity->internalEventPtr = NULL;
openEntity->internalEventEndPtr = 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) { // Only internal entities make use of the reenter flag
if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) { // therefore no need to set it for other entity types
entity->processed = (int)(next - textStart); if (type == ENTITY_INTERNAL) {
parser->m_processor = internalEntityProcessor; triggerReenter(parser);
} 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;
}
} }
return result; return XML_ERROR_NONE;
} }
static enum XML_Error PTRCALL static enum XML_Error PTRCALL
internalEntityProcessor(XML_Parser parser, const char *s, const char *end, internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
const char **nextPtr) { const char **nextPtr) {
UNUSED_P(s);
UNUSED_P(end);
UNUSED_P(nextPtr);
ENTITY *entity; ENTITY *entity;
const char *textStart, *textEnd; const char *textStart, *textEnd;
const char *next; const char *next;
@ -5905,68 +6045,67 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
return XML_ERROR_UNEXPECTED_STATE; return XML_ERROR_UNEXPECTED_STATE;
entity = openEntity->entity; entity = openEntity->entity;
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 */
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_TRUE,
XML_ACCOUNT_ENTITY_EXPANSION);
} else {
result = doContent(parser, openEntity->startTagLevel,
parser->m_internalEncoding, textStart, textEnd, &next,
XML_FALSE, XML_ACCOUNT_ENTITY_EXPANSION);
}
if (result != XML_ERROR_NONE) // This will return early
return result; 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 */
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, openEntity->startTagLevel,
parser->m_internalEncoding, textStart, textEnd, &next,
XML_FALSE, XML_ACCOUNT_ENTITY_EXPANSION);
}
if (result != XML_ERROR_NONE)
return result;
// 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;
}
if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) { // Entity is complete. We cannot close it here since we need to first
entity->processed = (int)(next - (const char *)entity->textPtr); // 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; return result;
} } // End of entity processing, "if" block will return here
// Remove fully processed openEntity from open entity list.
#if XML_GE == 1 #if XML_GE == 1
entityTrackingOnClose(parser, entity, __LINE__); entityTrackingOnClose(parser, entity, __LINE__);
#endif #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; entity->open = XML_FALSE;
parser->m_openInternalEntities = openEntity->next; parser->m_openInternalEntities = parser->m_openInternalEntities->next;
/* put openEntity back in list of free instances */ /* put openEntity back in list of free instances */
openEntity->next = parser->m_freeInternalEntities; openEntity->next = parser->m_freeInternalEntities;
parser->m_freeInternalEntities = openEntity; parser->m_freeInternalEntities = openEntity;
// If there are more open entities we want to stop right here and have the if (parser->m_openInternalEntities == NULL) {
// upcoming call to XML_ResumeParser continue with entity content, or it would parser->m_processor = entity->is_param ? prologProcessor : contentProcessor;
// 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;
} }
triggerReenter(parser);
return XML_ERROR_NONE;
} }
static enum XML_Error PTRCALL static enum XML_Error PTRCALL
@ -5982,8 +6121,70 @@ static enum XML_Error
storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
const char *ptr, const char *end, STRING_POOL *pool, const char *ptr, const char *end, STRING_POOL *pool,
enum XML_Account account) { enum XML_Account account) {
enum XML_Error result const char *next = ptr;
= appendAttributeValue(parser, enc, isCdata, ptr, end, pool, account); 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) if (result)
return result; return result;
if (! isCdata && poolLength(pool) && poolLastChar(pool) == 0x20) 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 static enum XML_Error
appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
const char *ptr, const char *end, STRING_POOL *pool, 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 */ DTD *const dtd = parser->m_dtd; /* save one level of indirection */
#ifndef XML_DTD #ifndef XML_DTD
UNUSED_P(account); UNUSED_P(account);
@ -6014,6 +6215,9 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
#endif #endif
switch (tok) { switch (tok) {
case XML_TOK_NONE: case XML_TOK_NONE:
if (nextPtr) {
*nextPtr = next;
}
return XML_ERROR_NONE; return XML_ERROR_NONE;
case XML_TOK_INVALID: case XML_TOK_INVALID:
if (enc == parser->m_encoding) if (enc == parser->m_encoding)
@ -6154,21 +6358,11 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF; return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
} else { } else {
enum XML_Error result; enum XML_Error result;
const XML_Char *textEnd = entity->textPtr + entity->textLen; result = processEntity(parser, entity, XML_FALSE, ENTITY_ATTRIBUTE);
entity->open = XML_TRUE; if ((result == XML_ERROR_NONE) && (nextPtr != NULL)) {
#if XML_GE == 1 *nextPtr = next;
entityTrackingOnOpen(parser, entity, __LINE__); }
#endif return result;
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)
return result;
} }
} break; } break;
default: default:
@ -6197,7 +6391,7 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
static enum XML_Error static enum XML_Error
storeEntityValue(XML_Parser parser, const ENCODING *enc, storeEntityValue(XML_Parser parser, const ENCODING *enc,
const char *entityTextPtr, const char *entityTextEnd, 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 */ DTD *const dtd = parser->m_dtd; /* save one level of indirection */
STRING_POOL *pool = &(dtd->entityValuePool); STRING_POOL *pool = &(dtd->entityValuePool);
enum XML_Error result = XML_ERROR_NONE; enum XML_Error result = XML_ERROR_NONE;
@ -6215,8 +6409,9 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc,
return XML_ERROR_NO_MEMORY; return XML_ERROR_NO_MEMORY;
} }
const char *next;
for (;;) { for (;;) {
const char *next next
= entityTextPtr; /* XmlEntityValueTok doesn't always set the last arg */ = entityTextPtr; /* XmlEntityValueTok doesn't always set the last arg */
int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next); int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
@ -6278,16 +6473,8 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc,
} else } else
dtd->keepProcessing = dtd->standalone; dtd->keepProcessing = dtd->standalone;
} else { } else {
entity->open = XML_TRUE; result = processEntity(parser, entity, XML_FALSE, ENTITY_VALUE);
entityTrackingOnOpen(parser, entity, __LINE__); goto endEntityValue;
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)
goto endEntityValue;
} }
break; break;
} }
@ -6375,6 +6562,81 @@ endEntityValue:
# ifdef XML_DTD # ifdef XML_DTD
parser->m_prologState.inEntityValue = oldInEntityValue; parser->m_prologState.inEntityValue = oldInEntityValue;
# endif /* XML_DTD */ # 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; return result;
} }
@ -8542,11 +8804,13 @@ unsignedCharToPrintable(unsigned char c) {
return "\\xFE"; return "\\xFE";
case 255: case 255:
return "\\xFF"; return "\\xFF";
// LCOV_EXCL_START
default: default:
assert(0); /* never gets here */ assert(0); /* never gets here */
return "dead code"; return "dead code";
} }
assert(0); /* never gets here */ assert(0); /* never gets here */
// LCOV_EXCL_STOP
} }
#endif /* XML_GE == 1 */ #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/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
]) ])
# serial 62 LT_INIT # serial 63 LT_INIT
# LT_PREREQ(VERSION) # LT_PREREQ(VERSION)
@ -1100,6 +1100,21 @@ _LT_EOF
if test yes = "$lt_cv_apple_cc_single_mod"; then if test yes = "$lt_cv_apple_cc_single_mod"; then
_lt_dar_single_mod='$single_module' _lt_dar_single_mod='$single_module'
fi 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 if test yes = "$lt_cv_ld_exported_symbols_list"; then
_lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym'
else 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(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" _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], 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_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" _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 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 lt_cv_sys_max_cmd_len=12288; # 12K is about right
;; ;;
gnu*) gnu* | ironclad*)
# Under GNU Hurd, this test is not required because there is # Under GNU Hurd and Ironclad, this test is not required because there
# no limit to the length of command line arguments. # is no limit to the length of command line arguments.
# Libtool will interpret -1 as no limit whatsoever # Libtool will interpret -1 as no limit whatsoever
lt_cv_sys_max_cmd_len=-1; lt_cv_sys_max_cmd_len=-1;
;; ;;
@ -2566,28 +2581,28 @@ cygwin* | mingw* | windows* | pw32* | cegcc*)
# gcc # gcc
library_names_spec='$libname.dll.a' library_names_spec='$libname.dll.a'
# DLL is installed to $(libdir)/../bin by postinstall_cmds # 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) # it should just install on $(libdir)
# not on $(libdir)/../bin or 32 bits dlls would override 64 bit ones. # 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`~ postinstall_cmds='base_file=`basename \$file`~
dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
dldir=$destdir/`dirname \$dlpath`~ dldir=$destdir/`dirname \$dlpath`~
$install_prog $dir/$dlname $destdir/$dlname~ $install_prog $dir/$dlname $destdir/$dlname~
chmod a+x $destdir/$dlname~ chmod a+x $destdir/$dlname~
if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
eval '\''$striplib $destdir/$dlname'\'' || exit \$?; eval '\''$striplib $destdir/$dlname'\'' || exit \$?;
fi' fi'
else else
postinstall_cmds='base_file=`basename \$file`~ postinstall_cmds='base_file=`basename \$file`~
dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
dldir=$destdir/`dirname \$dlpath`~ dldir=$destdir/`dirname \$dlpath`~
test -d \$dldir || mkdir -p \$dldir~ test -d \$dldir || mkdir -p \$dldir~
$install_prog $dir/$dlname \$dldir/$dlname~ $install_prog $dir/$dlname \$dldir/$dlname~
chmod a+x \$dldir/$dlname~ chmod a+x \$dldir/$dlname~
if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
fi' fi'
fi fi
postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
dlpath=$dir/\$dldll~ dlpath=$dir/\$dldll~
@ -2784,8 +2799,9 @@ haiku*)
soname_spec='$libname$release$shared_ext$major' soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LIBRARY_PATH shlibpath_var=LIBRARY_PATH
shlibpath_overrides_runpath=no shlibpath_overrides_runpath=no
sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' sys_lib_search_path_spec='/boot/system/non-packaged/develop/lib /boot/system/develop/lib'
hardcode_into_libs=yes 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*) hpux9* | hpux10* | hpux11*)
@ -2963,6 +2979,18 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
dynamic_linker='GNU/Linux ld.so' 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*) netbsd*)
version_type=sunos version_type=sunos
need_lib_prefix=no need_lib_prefix=no
@ -2981,6 +3009,18 @@ netbsd*)
hardcode_into_libs=yes 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) newsos6)
version_type=linux # correct to gnu/linux during the next big refactor 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' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
@ -3060,6 +3100,17 @@ rdos*)
dynamic_linker=no 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*) solaris*)
version_type=linux # correct to gnu/linux during the next big refactor version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no need_lib_prefix=no
@ -3157,6 +3208,21 @@ uts4*)
shlibpath_var=LD_LIBRARY_PATH 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 dynamic_linker=no
;; ;;
@ -3621,7 +3687,11 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
lt_cv_deplibs_check_method=pass_all 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 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)$' lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
else else
@ -3655,6 +3725,10 @@ rdos*)
lt_cv_deplibs_check_method=pass_all lt_cv_deplibs_check_method=pass_all
;; ;;
serenity*)
lt_cv_deplibs_check_method=pass_all
;;
solaris*) solaris*)
lt_cv_deplibs_check_method=pass_all lt_cv_deplibs_check_method=pass_all
;; ;;
@ -4127,7 +4201,8 @@ _LT_EOF
if AC_TRY_EVAL(ac_compile); then if AC_TRY_EVAL(ac_compile); then
# Now try to grab the symbols. # Now try to grab the symbols.
nlist=conftest.nm 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. # Try sorting and uniquifying the output.
if sort "$nlist" | uniq > "$nlist"T; then if sort "$nlist" | uniq > "$nlist"T; then
mv -f "$nlist"T "$nlist" mv -f "$nlist"T "$nlist"
@ -4499,7 +4574,9 @@ m4_if([$1], [CXX], [
;; ;;
esac esac
;; ;;
netbsd*) netbsd* | netbsdelf*-gnu)
;;
*-mlibc)
;; ;;
*qnx* | *nto*) *qnx* | *nto*)
# QNX uses GNU C++, but need to define -shared option too, otherwise # QNX uses GNU C++, but need to define -shared option too, otherwise
@ -4529,6 +4606,8 @@ m4_if([$1], [CXX], [
;; ;;
psos*) psos*)
;; ;;
serenity*)
;;
solaris*) solaris*)
case $cc_basename in case $cc_basename in
CC* | sunCC*) CC* | sunCC*)
@ -4767,7 +4846,7 @@ m4_if([$1], [CXX], [
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
;; ;;
*flang* | ftn) *flang* | ftn | f18* | f95*)
# Flang compiler. # Flang compiler.
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
@ -4855,6 +4934,12 @@ m4_if([$1], [CXX], [
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _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*) *nto* | *qnx*)
# QNX uses GNU C++, but need to define -shared option too, otherwise # QNX uses GNU C++, but need to define -shared option too, otherwise
# it will coredump. # it will coredump.
@ -4871,6 +4956,9 @@ m4_if([$1], [CXX], [
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
;; ;;
serenity*)
;;
solaris*) solaris*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _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) # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC)
with_gnu_ld=yes with_gnu_ld=yes
;; ;;
openbsd*)
with_gnu_ld=no
;;
esac esac
_LT_TAGVAR(ld_shlibs, $1)=yes _LT_TAGVAR(ld_shlibs, $1)=yes
@ -5189,6 +5274,7 @@ _LT_EOF
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _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(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(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 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' _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*) haiku*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _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*) os2*)
@ -5314,6 +5400,7 @@ _LT_EOF
case $cc_basename in case $cc_basename in
tcc*) tcc*)
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic'
;; ;;
xlf* | bgf* | bgxlf* | mpixlf*) xlf* | bgf* | bgxlf* | mpixlf*)
@ -5334,7 +5421,12 @@ _LT_EOF
fi 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 if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
wlarc= wlarc=
@ -5653,14 +5745,14 @@ _LT_EOF
# Tell ltmain to make .dll files, not .so files. # Tell ltmain to make .dll files, not .so files.
shrext_cmds=.dll shrext_cmds=.dll
# FIXME: Setting linknames here is a bad hack. # FIXME: Setting linknames here is a bad hack.
_LT_TAGVAR(archive_cmds, $1)='$CC -Fe $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_cmds, $1)='$CC -Fe$output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
_LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
cp "$export_symbols" "$output_objdir/$soname.def"; cp "$export_symbols" "$output_objdir/$soname.def";
echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
else else
$SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
fi~ fi~
$CC -Fe $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ $CC -Fe$tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
linknames=' linknames='
# The linker will not automatically build a static lib if we build a DLL. # The linker will not automatically build a static lib if we build a DLL.
# _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
@ -5872,11 +5964,15 @@ _LT_EOF
# Fabrice Bellard et al's Tiny C Compiler # Fabrice Bellard et al's Tiny C Compiler
_LT_TAGVAR(ld_shlibs, $1)=yes _LT_TAGVAR(ld_shlibs, $1)=yes
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _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 esac
;; ;;
netbsd*) *-mlibc)
;;
netbsd* | netbsdelf*-gnu)
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then 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 _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
else else
@ -5977,6 +6073,9 @@ _LT_EOF
_LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_libdir_separator, $1)=:
;; ;;
serenity*)
;;
solaris*) solaris*)
_LT_TAGVAR(no_undefined_flag, $1)=' -z defs' _LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
if test yes = "$GCC"; then if test yes = "$GCC"; then
@ -6502,7 +6601,7 @@ if test yes != "$_lt_caught_CXX_error"; then
# Commands to make compiler produce verbose output that lists # Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when # what "hidden" libraries, object files and flags are used when
# linking a shared library. # linking a shared library.
output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "[[-]]L"' output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " [[-]]L"'
else else
GXX=no GXX=no
@ -6764,6 +6863,7 @@ if test yes != "$_lt_caught_CXX_error"; then
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
_LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(always_export_symbols, $1)=no
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _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 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' _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*) haiku*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _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*) hpux9*)
@ -6943,7 +7043,7 @@ if test yes != "$_lt_caught_CXX_error"; then
# explicitly linking system object files so we need to strip them # explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library # from the output so that they don't get included in the library
# dependencies. # dependencies.
output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "[[-]]L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " [[-]]L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
;; ;;
*) *)
if test yes = "$GXX"; then if test yes = "$GXX"; then
@ -7175,6 +7275,10 @@ if test yes != "$_lt_caught_CXX_error"; then
esac esac
;; ;;
*-mlibc)
_LT_TAGVAR(ld_shlibs, $1)=yes
;;
netbsd*) netbsd*)
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then 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' _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
@ -7282,7 +7386,7 @@ if test yes != "$_lt_caught_CXX_error"; then
# Commands to make compiler produce verbose output that lists # Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when # what "hidden" libraries, object files and flags are used when
# linking a shared library. # linking a shared library.
output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "[[-]]L"' output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " [[-]]L"'
else else
# FIXME: insert proper C++ library support # FIXME: insert proper C++ library support
@ -7297,6 +7401,9 @@ if test yes != "$_lt_caught_CXX_error"; then
_LT_TAGVAR(ld_shlibs, $1)=no _LT_TAGVAR(ld_shlibs, $1)=no
;; ;;
serenity*)
;;
sunos4*) sunos4*)
case $cc_basename in case $cc_basename in
CC*) CC*)
@ -7366,7 +7473,7 @@ if test yes != "$_lt_caught_CXX_error"; then
# Commands to make compiler produce verbose output that lists # Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when # what "hidden" libraries, object files and flags are used when
# linking a shared library. # linking a shared library.
output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "[[-]]L"' output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " [[-]]L"'
else else
# g++ 2.7 appears to require '-G' NOT '-shared' on this # g++ 2.7 appears to require '-G' NOT '-shared' on this
# platform. # platform.
@ -7377,7 +7484,7 @@ if test yes != "$_lt_caught_CXX_error"; then
# Commands to make compiler produce verbose output that lists # Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when # what "hidden" libraries, object files and flags are used when
# linking a shared library. # linking a shared library.
output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "[[-]]L"' output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " [[-]]L"'
fi fi
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir'

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

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

@ -19,6 +19,7 @@
Copyright (c) 2020 Tim Gates <tim.gates@iress.com> Copyright (c) 2020 Tim Gates <tim.gates@iress.com>
Copyright (c) 2021 Donghee Na <donghee.na@python.org> Copyright (c) 2021 Donghee Na <donghee.na@python.org>
Copyright (c) 2023 Sony Corporation / Snild Dolkow <snild@sony.com> 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: Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
@ -450,6 +451,31 @@ START_TEST(test_alloc_internal_entity) {
} }
END_TEST 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 /* Test the robustness against allocation failure of element handling
* Based on test_dtd_default_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_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_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_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__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_explicit_encoding);
tcase_add_test(tc_alloc, test_alloc_set_base); tcase_add_test(tc_alloc, test_alloc_set_base);

@ -10,7 +10,7 @@
Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net> Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
Copyright (c) 2005-2007 Steven Solie <steven@solie.ca> Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net> 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-2022 Rhodri James <rhodri@wildebeest.org.uk>
Copyright (c) 2017 Joe Orton <jorton@redhat.com> Copyright (c) 2017 Joe Orton <jorton@redhat.com>
Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.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) 2020 Tim Gates <tim.gates@iress.com>
Copyright (c) 2021 Donghee Na <donghee.na@python.org> Copyright (c) 2021 Donghee Na <donghee.na@python.org>
Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild@sony.com> 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: Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
@ -1191,6 +1192,22 @@ START_TEST(test_not_standalone_handler_accept) {
} }
END_TEST 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) { START_TEST(test_wfc_no_recursive_entity_refs) {
const char *text = "<!DOCTYPE doc [\n" const char *text = "<!DOCTYPE doc [\n"
" <!ENTITY entity '&#38;entity;'>\n" " <!ENTITY entity '&#38;entity;'>\n"
@ -1202,6 +1219,93 @@ START_TEST(test_wfc_no_recursive_entity_refs) {
} }
END_TEST 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) { START_TEST(test_recursive_external_parameter_entity_2) {
struct TestCase { struct TestCase {
const char *doc; const char *doc;
@ -1417,7 +1521,9 @@ START_TEST(test_suspend_parser_between_char_data_calls) {
XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
g_resumable = XML_TRUE; 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_STATUS_SUSPENDED)
xml_failure(g_parser); xml_failure(g_parser);
if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE) 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); XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
g_resumable = XML_TRUE; g_resumable = XML_TRUE;
g_abortable = XML_FALSE; 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) != XML_STATUS_SUSPENDED)
fail("Failed to double-suspend parser"); fail("Failed to double-suspend parser");
@ -1830,12 +1938,19 @@ END_TEST
/* Test suspending the parser in cdata handler */ /* Test suspending the parser in cdata handler */
START_TEST(test_suspend_parser_between_cdata_calls) { 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; const char *text = long_cdata_text;
enum XML_Status result; enum XML_Status result;
XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
g_resumable = XML_TRUE; 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_SUSPENDED) {
if (result == XML_STATUS_ERROR) if (result == XML_STATUS_ERROR)
xml_failure(g_parser); xml_failure(g_parser);
@ -2378,6 +2493,11 @@ END_TEST
* entity. Exercises some obscure code in XML_ParserReset(). * entity. Exercises some obscure code in XML_ParserReset().
*/ */
START_TEST(test_reset_in_entity) { 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" const char *text = "<!DOCTYPE doc [\n"
"<!ENTITY wombat 'wom'>\n" "<!ENTITY wombat 'wom'>\n"
"<!ENTITY entity 'hi &wom; there'>\n" "<!ENTITY entity 'hi &wom; there'>\n"
@ -2387,7 +2507,9 @@ START_TEST(test_reset_in_entity) {
g_resumable = XML_TRUE; g_resumable = XML_TRUE;
XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 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_STATUS_ERROR)
xml_failure(g_parser); xml_failure(g_parser);
XML_GetParsingStatus(g_parser, &status); XML_GetParsingStatus(g_parser, &status);
@ -3634,7 +3756,9 @@ START_TEST(test_suspend_xdecl) {
XML_SetXmlDeclHandler(g_parser, entity_suspending_xdecl_handler); XML_SetXmlDeclHandler(g_parser, entity_suspending_xdecl_handler);
XML_SetUserData(g_parser, g_parser); XML_SetUserData(g_parser, g_parser);
g_resumable = XML_TRUE; 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_STATUS_SUSPENDED)
xml_failure(g_parser); xml_failure(g_parser);
if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE) if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
@ -3830,13 +3954,20 @@ END_TEST
/* Test syntax error is caught at parse resumption */ /* Test syntax error is caught at parse resumption */
START_TEST(test_resume_entity_with_syntax_error) { 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" const char *text = "<!DOCTYPE doc [\n"
"<!ENTITY foo '<suspend>Hi</wombat>'>\n" "<!ENTITY foo '<suspend>Hi</wombat>'>\n"
"]>\n" "]>\n"
"<doc>&foo;</doc>\n"; "<doc>&foo;</doc>\n";
XML_SetStartElementHandler(g_parser, start_element_suspender); 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_STATUS_SUSPENDED)
xml_failure(g_parser); xml_failure(g_parser);
if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR) 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 % pe1 SYSTEM 'http://example.org/two.ent'>\n"
"<!ENTITY % pe2 '%pe1;'>\n" "<!ENTITY % pe2 '%pe1;'>\n"
"%pe2;\n", "%pe2;\n",
external_entity_null_loader}; external_entity_null_loader, NULL};
XML_SetUserData(g_parser, &test_data); XML_SetUserData(g_parser, &test_data);
XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 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 % pe1 SYSTEM 'http://example.org/two.ent'>\n"
"<!ENTITY % pe2 '%pe1;'>\n" "<!ENTITY % pe2 '%pe1;'>\n"
"%pe2;\n", "%pe2;\n",
NULL}; NULL, NULL};
XML_SetUserData(g_parser, &test_data); XML_SetUserData(g_parser, &test_data);
XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
@ -5278,6 +5409,151 @@ START_TEST(test_pool_integrity_with_unfinished_attr) {
} }
END_TEST 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) { START_TEST(test_nested_entity_suspend) {
const char *const text = "<!DOCTYPE a [\n" const char *const text = "<!DOCTYPE a [\n"
" <!ENTITY e1 '<!--e1-->'>\n" " <!ENTITY e1 '<!--e1-->'>\n"
@ -5308,6 +5584,35 @@ START_TEST(test_nested_entity_suspend) {
} }
END_TEST 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 */ /* Regression test for quadratic parsing on large tokens */
START_TEST(test_big_tokens_scale_linearly) { START_TEST(test_big_tokens_scale_linearly) {
const struct { 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_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_reject);
tcase_add_test(tc_basic, test_not_standalone_handler_accept); 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__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__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__if_xml_ge(tc_basic, test_dtd_default_handling);
tcase_add_test(tc_basic, test_dtd_attr_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(tc_basic, test_empty_element_abort);
tcase_add_test__ifdef_xml_dtd(tc_basic, tcase_add_test__ifdef_xml_dtd(tc_basic,
test_pool_integrity_with_unfinished_attr); 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);
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_big_tokens_scale_linearly);
tcase_add_test(tc_basic, test_set_reparse_deferral); tcase_add_test(tc_basic, test_set_reparse_deferral);
tcase_add_test(tc_basic, test_reparse_deferral_is_inherited); 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) 2003-2006 Karl Waclawek <karl@waclawek.net>
Copyright (c) 2005-2007 Steven Solie <steven@solie.ca> 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> Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
Licensed under the MIT license: Licensed under the MIT license:
@ -32,10 +32,18 @@
USE OR OTHER DEALINGS IN THE SOFTWARE. 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 <sys/stat.h>
#include <assert.h> #include <assert.h>
#include <stddef.h> // ptrdiff_t #include <stddef.h> // ptrdiff_t
#include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
#include "expat.h" #include "expat.h"
@ -52,17 +60,18 @@
# define XML_FMT_STR "s" # define XML_FMT_STR "s"
#endif #endif
static void static int
usage(const char *prog, int rc) { usage(const char *prog, int rc) {
fprintf(stderr, "usage: %s [-n] filename bufferSize nr_of_loops\n", prog); fprintf(stderr, "usage: %s [-n] filename bufferSize nr_of_loops\n", prog);
exit(rc); return rc;
} }
int int
main(int argc, char *argv[]) { main(int argc, char *argv[]) {
XML_Parser parser; XML_Parser parser;
char *XMLBuf, *XMLBufEnd, *XMLBufPtr; char *XMLBuf, *XMLBufEnd, *XMLBufPtr;
FILE *fd; int fd;
FILE *file;
struct stat fileAttr; struct stat fileAttr;
int nrOfLoops, bufferSize, i, isFinal; int nrOfLoops, bufferSize, i, isFinal;
size_t fileSize; size_t fileSize;
@ -76,34 +85,51 @@ main(int argc, char *argv[]) {
ns = 1; ns = 1;
j = 1; j = 1;
} else } else
usage(argv[0], 1); return usage(argv[0], 1);
} }
} }
if (argc != j + 4) if (argc != j + 4)
usage(argv[0], 1); return usage(argv[0], 1);
if (stat(argv[j + 1], &fileAttr) != 0) { fd = open(argv[j + 1], O_RDONLY);
fprintf(stderr, "could not access file '%s'\n", argv[j + 1]); if (fd == -1) {
fprintf(stderr, "could not open file '%s'\n", argv[j + 1]);
return 2; return 2;
} }
fd = fopen(argv[j + 1], "r"); if (fstat(fd, &fileAttr) != 0) {
if (! fd) { close(fd);
fprintf(stderr, "could not open file '%s'\n", argv[j + 1]); fprintf(stderr, "could not fstat file '%s'\n", argv[j + 1]);
exit(2); 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]); bufferSize = atoi(argv[j + 2]);
nrOfLoops = atoi(argv[j + 3]); nrOfLoops = atoi(argv[j + 3]);
if (bufferSize <= 0 || nrOfLoops <= 0) { if (bufferSize <= 0 || nrOfLoops <= 0) {
fclose(file);
close(fd);
fprintf(stderr, "buffer size and nr of loops must be greater than zero.\n"); fprintf(stderr, "buffer size and nr of loops must be greater than zero.\n");
exit(3); return 3;
} }
XMLBuf = malloc(fileAttr.st_size); XMLBuf = malloc(fileAttr.st_size);
fileSize = fread(XMLBuf, sizeof(char), fileAttr.st_size, fd); if (XMLBuf == NULL) {
fclose(fd); 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) if (ns)
parser = XML_ParserCreateNS(NULL, '!'); parser = XML_ParserCreateNS(NULL, '!');
@ -132,7 +158,7 @@ main(int argc, char *argv[]) {
XML_GetCurrentColumnNumber(parser)); XML_GetCurrentColumnNumber(parser));
free(XMLBuf); free(XMLBuf);
XML_ParserFree(parser); XML_ParserFree(parser);
exit(4); return 4;
} }
XMLBufPtr += bufferSize; XMLBufPtr += bufferSize;
} while (! isFinal); } 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) { for (; len > chunksize; len -= chunksize, s += chunksize) {
enum XML_Status res = XML_Parse(parser, s, chunksize, XML_FALSE); enum XML_Status res = XML_Parse(parser, s, chunksize, XML_FALSE);
if (res != XML_STATUS_OK) { 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; return res;
} }
} }

@ -1842,6 +1842,15 @@ element_decl_suspender(void *userData, const XML_Char *name,
XML_FreeContentModel(g_parser, model); 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 void XMLCALL
accumulate_pi_characters(void *userData, const XML_Char *target, accumulate_pi_characters(void *userData, const XML_Char *target,
const XML_Char *data) { const XML_Char *data) {
@ -1882,6 +1891,20 @@ accumulate_entity_decl(void *userData, const XML_Char *entityName,
CharData_AppendXMLChars(storage, XCS("\n"), 1); 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 void XMLCALL
accumulate_start_element(void *userData, const XML_Char *name, accumulate_start_element(void *userData, const XML_Char *name,
const XML_Char **atts) { const XML_Char **atts) {

@ -325,6 +325,7 @@ extern int XMLCALL external_entity_devaluer(XML_Parser parser,
typedef struct ext_hdlr_data { typedef struct ext_hdlr_data {
const char *parse_text; const char *parse_text;
XML_ExternalEntityRefHandler handler; XML_ExternalEntityRefHandler handler;
CharData *storage;
} ExtHdlrData; } ExtHdlrData;
extern int XMLCALL external_entity_oneshot_loader(XML_Parser parser, 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, extern void XMLCALL element_decl_suspender(void *userData, const XML_Char *name,
XML_Content *model); 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, extern void XMLCALL accumulate_pi_characters(void *userData,
const XML_Char *target, const XML_Char *target,
const XML_Char *data); 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 *systemId, const XML_Char *publicId,
const XML_Char *notationName); 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, extern void XMLCALL accumulate_start_element(void *userData,
const XML_Char *name, const XML_Char *name,
const XML_Char **atts); const XML_Char **atts);

@ -14,7 +14,7 @@
Copyright (c) 2004-2006 Fred L. Drake, Jr. <fdrake@users.sourceforge.net> Copyright (c) 2004-2006 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2006-2012 Karl Waclawek <karl@waclawek.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) 2022 Rhodri James <rhodri@wildebeest.org.uk>
Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild@sony.com> Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild@sony.com>
Licensed under the MIT license: Licensed under the MIT license:
@ -129,8 +129,10 @@ void _check_set_test_info(char const *function, char const *filename,
* Prototypes for the actual implementation. * Prototypes for the actual implementation.
*/ */
# if defined(__GNUC__) # if defined(__has_attribute)
# if __has_attribute(noreturn)
__attribute__((noreturn)) __attribute__((noreturn))
# endif
# endif # endif
void void
_fail(const char *file, int line, const char *msg); _fail(const char *file, int line, const char *msg);

@ -10,7 +10,7 @@
Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net> Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
Copyright (c) 2005-2007 Steven Solie <steven@solie.ca> Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net> 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-2022 Rhodri James <rhodri@wildebeest.org.uk>
Copyright (c) 2017 Joe Orton <jorton@redhat.com> Copyright (c) 2017 Joe Orton <jorton@redhat.com>
Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com> Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
@ -59,6 +59,9 @@
#include "handlers.h" #include "handlers.h"
#include "misc_tests.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 */ /* Test that a failure to allocate the parser structure fails gracefully */
START_TEST(test_misc_alloc_create_parser) { START_TEST(test_misc_alloc_create_parser) {
XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free}; 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)) if (! versions_equal(&read_version, &parsed_version))
fail("Version mismatch"); 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"); fail("XML_*_VERSION in expat.h out of sync?\n");
} }
END_TEST END_TEST
@ -294,6 +297,7 @@ START_TEST(test_misc_stop_during_end_handler_issue_240_1) {
parser = XML_ParserCreate(NULL); parser = XML_ParserCreate(NULL);
XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240); XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
mydata = (DataIssue240 *)malloc(sizeof(DataIssue240)); mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
assert_true(mydata != NULL);
mydata->parser = parser; mydata->parser = parser;
mydata->deep = 0; mydata->deep = 0;
XML_SetUserData(parser, mydata); XML_SetUserData(parser, mydata);
@ -315,6 +319,7 @@ START_TEST(test_misc_stop_during_end_handler_issue_240_2) {
parser = XML_ParserCreate(NULL); parser = XML_ParserCreate(NULL);
XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240); XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
mydata = (DataIssue240 *)malloc(sizeof(DataIssue240)); mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
assert_true(mydata != NULL);
mydata->parser = parser; mydata->parser = parser;
mydata->deep = 0; mydata->deep = 0;
XML_SetUserData(parser, mydata); XML_SetUserData(parser, mydata);
@ -328,64 +333,119 @@ START_TEST(test_misc_stop_during_end_handler_issue_240_2) {
END_TEST END_TEST
START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) { START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) {
const char *const inputOne = "<!DOCTYPE d [\n" const char *const inputOne
"<!ENTITY % e ']><d/>'>\n" = "<!DOCTYPE d [\n"
"\n" "<!ENTITY % element_d '<!ELEMENT d (#PCDATA)*>'>\n"
"%e;"; "%element_d;\n"
"<!ENTITY % e ']><d/>'>\n"
"\n"
"%e;";
const char *const inputTwo const char *const inputTwo
= "<!DOCTYPE d [\n" = "<!DOCTYPE d [\n"
"<!ENTITY % element_d '<!ELEMENT d (#PCDATA)*>'>\n"
"%element_d;\n"
"<!ENTITY % e1 ']><d/>'><!ENTITY % e2 '&#37;e1;'>\n" "<!ENTITY % e1 ']><d/>'><!ENTITY % e2 '&#37;e1;'>\n"
"\n" "\n"
"%e2;"; "%e2;";
const char *const inputThree = "<!DOCTYPE d [\n" const char *const inputThree
"<!ENTITY % e ']><d'>\n" = "<!DOCTYPE d [\n"
"\n" "<!ENTITY % element_d '<!ELEMENT d (#PCDATA)*>'>\n"
"%e;/>"; "%element_d;\n"
const char *const inputIssue317 = "<!DOCTYPE doc [\n" "<!ENTITY % e ']><d'>\n"
"<!ENTITY % foo ']>\n" "\n"
"<doc>Hell<oc (#PCDATA)*>'>\n" "%e;/>";
"%foo;\n" const char *const inputIssue317
"]>\n" = "<!DOCTYPE doc [\n"
"<doc>Hello, world</dVc>"; "<!ENTITY % element_doc '<!ELEMENT doc (#PCDATA)*>'>\n"
"%element_doc;\n"
"<!ENTITY % foo ']>\n"
"<doc>Hell<oc (#PCDATA)*>'>\n"
"%foo;\n"
"]>\n"
"<doc>Hello, world</dVc>";
const char *const inputs[] = {inputOne, inputTwo, inputThree, inputIssue317}; const char *const inputs[] = {inputOne, inputTwo, inputThree, inputIssue317};
const XML_Bool suspendOrNot[] = {XML_FALSE, XML_TRUE};
size_t inputIndex = 0; size_t inputIndex = 0;
for (; inputIndex < sizeof(inputs) / sizeof(inputs[0]); inputIndex++) { for (; inputIndex < sizeof(inputs) / sizeof(inputs[0]); inputIndex++) {
set_subtest("%s", inputs[inputIndex]); for (size_t suspendOrNotIndex = 0;
XML_Parser parser; suspendOrNotIndex < sizeof(suspendOrNot) / sizeof(suspendOrNot[0]);
enum XML_Status parseResult; suspendOrNotIndex++) {
int setParamEntityResult; const char *const input = inputs[inputIndex];
XML_Size lineNumber; const XML_Bool suspend = suspendOrNot[suspendOrNotIndex];
XML_Size columnNumber; if (suspend && (g_chunkSize > 0)) {
const char *const input = inputs[inputIndex]; // We cannot use _XML_Parse_SINGLE_BYTES below due to suspension, and
// so chunk sizes >0 would only repeat the very same test
parser = XML_ParserCreate(NULL); // due to use of plain XML_Parse; we are saving upon that runtime:
setParamEntityResult return;
= XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); }
if (setParamEntityResult != 1)
fail("Failed to set XML_PARAM_ENTITY_PARSING_ALWAYS."); set_subtest("[input=%d suspend=%s] %s", (int)inputIndex,
suspend ? "true" : "false", input);
parseResult = _XML_Parse_SINGLE_BYTES(parser, input, (int)strlen(input), 0); XML_Parser parser;
if (parseResult != XML_STATUS_ERROR) { enum XML_Status parseResult;
parseResult = _XML_Parse_SINGLE_BYTES(parser, "", 0, 1); int setParamEntityResult;
XML_Size lineNumber;
XML_Size columnNumber;
parser = XML_ParserCreate(NULL);
setParamEntityResult
= XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
if (setParamEntityResult != 1)
fail("Failed to set XML_PARAM_ENTITY_PARSING_ALWAYS.");
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) { if (parseResult != XML_STATUS_ERROR) {
fail("Parsing was expected to fail but succeeded."); fail("Parsing was expected to fail but succeeded.");
} }
}
if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN) if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
fail("Error code does not match XML_ERROR_INVALID_TOKEN"); fail("Error code does not match XML_ERROR_INVALID_TOKEN");
lineNumber = XML_GetCurrentLineNumber(parser); lineNumber = XML_GetCurrentLineNumber(parser);
if (lineNumber != 4) if (lineNumber != 6)
fail("XML_GetCurrentLineNumber does not work as expected."); fail("XML_GetCurrentLineNumber does not work as expected.");
columnNumber = XML_GetCurrentColumnNumber(parser); columnNumber = XML_GetCurrentColumnNumber(parser);
if (columnNumber != 0) if (columnNumber != 0)
fail("XML_GetCurrentColumnNumber does not work as expected."); fail("XML_GetCurrentColumnNumber does not work as expected.");
XML_ParserFree(parser); XML_ParserFree(parser);
}
} }
} }
END_TEST END_TEST
@ -519,6 +579,45 @@ START_TEST(test_misc_stopparser_rejects_unstarted_parser) {
} }
END_TEST 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 void
make_miscellaneous_test_case(Suite *s) { make_miscellaneous_test_case(Suite *s) {
TCase *tc_misc = tcase_create("miscellaneous tests"); 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_char_handler_stop_without_leak);
tcase_add_test(tc_misc, test_misc_resumeparser_not_crashing); tcase_add_test(tc_misc, test_misc_resumeparser_not_crashing);
tcase_add_test(tc_misc, test_misc_stopparser_rejects_unstarted_parser); 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 # EXPAT TEST SCRIPT FOR W3C XML TEST SUITE
# #
# This script can be used to exercise Expat against the # This script can be used to exercise Expat against the
# w3c.org xml test suite, available from # w3c.org xml test suite, available from:
# http://www.w3.org/XML/Test/xmlts20020606.zip. # https://www.w3.org/XML/Test/xmlts20020606.zip
# #
# To run this script, first set XMLWF below so that xmlwf can be # To run this script, first set XMLWF below so that xmlwf can be
# found, then set the output directory with OUTPUT. # found, then set the output directory with OUTPUT.
@ -30,6 +30,7 @@
# Copyright (c) 2002 Karl Waclawek <karl@waclawek.net> # Copyright (c) 2002 Karl Waclawek <karl@waclawek.net>
# Copyright (c) 2008-2019 Sebastian Pipping <sebastian@pipping.org> # Copyright (c) 2008-2019 Sebastian Pipping <sebastian@pipping.org>
# Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> # Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
# Copyright (c) 2025 Hanno Böck <hanno@gentoo.org>
# Licensed under the MIT license: # Licensed under the MIT license:
# #
# Permission is hereby granted, free of charge, to any person obtaining # 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 Tim Peters <tim.peters@gmail.com>
; Copyright (c) 2001-2005 Fred L. Drake, Jr. <fdrake@users.sourceforge.net> ; Copyright (c) 2001-2005 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
; Copyright (c) 2006-2017 Karl Waclawek <karl@waclawek.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) 2022 Johnny Jazeix <jazeix@gmail.com>
; Copyright (c) 2024 Dag-Erling Smørgrav <des@des.dev> ; Copyright (c) 2024 Dag-Erling Smørgrav <des@des.dev>
; Licensed under the MIT license: ; Licensed under the MIT license:
@ -38,14 +38,14 @@
; OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE ; OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
; USE OR OTHER DEALINGS IN THE SOFTWARE. ; USE OR OTHER DEALINGS IN THE SOFTWARE.
#define expatVer "2.6.4" #define expatVer "2.7.0"
[Setup] [Setup]
AppName=Expat AppName=Expat
AppId=expat AppId=expat
AppVersion={#expatVer} AppVersion={#expatVer}
AppVerName=Expat {#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 AppPublisher=The Expat Developers
AppPublisherURL=https://libexpat.github.io/ AppPublisherURL=https://libexpat.github.io/
AppSupportURL=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: README.md; DestDir: "{app}"; DestName: README.txt
Flags: ignoreversion; Source: doc\*.html; DestDir: "{app}\Doc" Flags: ignoreversion; Source: doc\*.html; DestDir: "{app}\Doc"
Flags: ignoreversion; Source: doc\*.css; 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\*.dll; DestDir: "{app}\Bin"
Flags: ignoreversion; Source: win32\bin\Release\*.lib; DestDir: "{app}\Bin" Flags: ignoreversion; Source: win32\bin\Release\*.lib; DestDir: "{app}\Bin"
Flags: ignoreversion; Source: win32\version.rc.cmake; DestDir: "{app}\Source\win32" 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 Rhodri James <rhodri@wildebeest.org.uk>
Copyright (c) 2017 Franek Korta <fkorta@gmail.com> Copyright (c) 2017 Franek Korta <fkorta@gmail.com>
Copyright (c) 2022 Sean McBride <sean@rogue-research.com> Copyright (c) 2022 Sean McBride <sean@rogue-research.com>
Copyright (c) 2025 Hanno Böck <hanno@gentoo.org>
Licensed under the MIT license: Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
@ -55,7 +56,7 @@
# define EXPAT_read_count_t int # define EXPAT_read_count_t int
# define EXPAT_read_req_t unsigned int # define EXPAT_read_req_t unsigned int
#else /* POSIX */ #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 read
# define EXPAT_read_count_t ssize_t # define EXPAT_read_count_t ssize_t
# define EXPAT_read_req_t size_t # define EXPAT_read_req_t size_t

Loading…
Cancel
Save