Version in base suite: 2.7.1-2 Base version: expat_2.7.1-2 Target version: expat_2.8.2-1~deb13u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/e/expat/expat_2.7.1-2.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/e/expat/expat_2.8.2-1~deb13u1.dsc .ci.sh | 4 .gitattributes | 4 .github/workflows/autotools-cmake.yml | 39 .github/workflows/clang-format.yml | 14 .github/workflows/clang-static-analyzer.yml | 18 .github/workflows/clang-tidy.yml | 14 .github/workflows/cmake-required-version.yml | 2 .github/workflows/codespell.yml | 4 .github/workflows/coverage.yml | 11 .github/workflows/coverity-scan.yml | 16 .github/workflows/cppcheck.yml | 2 .github/workflows/data/expat_config_h_cmake__expected.txt | 2 .github/workflows/data/expat_config_h_in__expected.txt | 2 .github/workflows/data/exported-symbols-unversioned.txt | 72 .github/workflows/data/exported-symbols-versioned-default.txt | 72 .github/workflows/data/exported-symbols-versioned-maximum.txt | 73 .github/workflows/data/exported-symbols.txt | 69 .github/workflows/emscripten.yml | 9 .github/workflows/expat_config_h.yml | 2 .github/workflows/freebsd.yml | 99 .github/workflows/fuzzing.yml | 44 .github/workflows/linux.yml | 20 .github/workflows/macos.yml | 6 .github/workflows/musl.yml | 2 .github/workflows/perl-integration.yml | 25 .github/workflows/scripts/mass-cppcheck.sh | 8 .github/workflows/solaris.yml | 104 .github/workflows/valid-xml.yml | 33 .github/workflows/wasi_sdk.yml | 72 .github/workflows/windows-binaries.yml | 26 .github/workflows/windows-build.yml | 45 .mailmap | 5 CONTRIBUTING.md | 102 COPYING | 2 README.md | 28 debian/changelog | 108 debian/control | 5 debian/libexpat1-dev.install | 1 debian/libexpat1.symbols | 6 debian/patches/fix-expat-cmake.patch | 4 debian/rules | 1 debian/watch | 10 expat/.gitignore | 2 expat/CMake.README | 14 expat/CMakeLists.txt | 234 expat/Changes | 468 expat/ConfigureChecks.cmake | 78 expat/Makefile.am | 10 expat/README.md | 28 expat/apply-clang-tidy.sh | 7 expat/cmake/autotools/expat.cmake | 107 expat/cmake/autotools/expat__linux.cmake.in | 107 expat/cmake/autotools/expat__macos.cmake.in | 107 expat/cmake/autotools/expat__windows.cmake.in | 107 expat/configure.ac | 224 expat/conftools/expat.m4 | 43 expat/coverage.sh | 22 expat/doc/reference.html | 4988 ++++++---- expat/doc/xmlwf.xml | 504 - expat/examples/element_declarations.c | 5 expat/expat_config.h.cmake | 30 expat/fix-xmltest-log.sh | 5 expat/fuzz/xml_lpm_fuzzer.cpp | 6 expat/fuzz/xml_parse_fuzzer.c | 20 expat/fuzz/xml_parsebuffer_fuzzer.c | 24 expat/lib/Makefile.am | 47 expat/lib/expat.h | 78 expat/lib/expat_external.h | 125 expat/lib/fallthrough.h | 49 expat/lib/internal.h | 20 expat/lib/libexpat.def.cmake | 10 expat/lib/libexpat.map.in | 124 expat/lib/memory_sanitizer.h | 51 expat/lib/random_arc4random.c | 56 expat/lib/random_arc4random.h | 39 expat/lib/random_arc4random_buf.c | 47 expat/lib/random_arc4random_buf.h | 39 expat/lib/random_dev_urandom.c | 72 expat/lib/random_dev_urandom.h | 40 expat/lib/random_getentropy.c | 60 expat/lib/random_getentropy.h | 40 expat/lib/random_getrandom.c | 95 expat/lib/random_getrandom.h | 40 expat/lib/random_rand_s.c | 88 expat/lib/random_rand_s.h | 41 expat/lib/siphash.h | 15 expat/lib/xcsinc.c | 48 expat/lib/xmlparse.c | 2238 ++-- expat/lib/xmlrole.c | 2 expat/lib/xmlrole.h | 36 expat/lib/xmltok.c | 12 expat/lib/xmltok.h | 232 expat/lib/xmltok_impl.c | 21 expat/lib/xmltok_ns.c | 5 expat/memory-sanitizer-blacklist.txt | 6 expat/qa.sh | 20 expat/tests/.gitignore | 1 expat/tests/Makefile.am | 24 expat/tests/acc_tests.c | 6 expat/tests/acc_tests_cxx.cpp | 32 expat/tests/alloc_tests.c | 242 expat/tests/alloc_tests_cxx.cpp | 32 expat/tests/basic_tests.c | 466 expat/tests/basic_tests_cxx.cpp | 32 expat/tests/chardata.c | 14 expat/tests/chardata_cxx.cpp | 32 expat/tests/common.c | 21 expat/tests/common_cxx.cpp | 32 expat/tests/dummy_cxx.cpp | 32 expat/tests/handlers.c | 126 expat/tests/handlers.h | 21 expat/tests/handlers_cxx.cpp | 32 expat/tests/memcheck.c | 6 expat/tests/memcheck_cxx.cpp | 32 expat/tests/minicheck.c | 10 expat/tests/minicheck.h | 3 expat/tests/minicheck_cxx.cpp | 32 expat/tests/misc_tests.c | 179 expat/tests/misc_tests_cxx.cpp | 32 expat/tests/ns_tests_cxx.cpp | 32 expat/tests/nsalloc_tests.c | 41 expat/tests/nsalloc_tests_cxx.cpp | 32 expat/tests/runtests_cxx.cpp | 36 expat/tests/structdata.c | 7 expat/tests/structdata_cxx.cpp | 32 expat/win32/README.txt | 4 expat/win32/build_expat_iss.bat | 168 expat/win32/expat.iss | 5 expat/xmlwf/filemap.h | 3 expat/xmlwf/unixfilemap.c | 11 expat/xmlwf/win32filemap.c | 2 expat/xmlwf/xmlfile.c | 47 expat/xmlwf/xmlwf.c | 214 expat/xmlwf/xmlwf_helpgen.py | 190 pull_request_template.md | 17 135 files changed, 9635 insertions(+), 4766 deletions(-) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp4u2sjnx5/expat_2.7.1-2.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp4u2sjnx5/expat_2.8.2-1~deb13u1.dsc: no acceptable signature found diff -Nru expat-2.7.1/.ci.sh expat-2.8.2/.ci.sh --- expat-2.7.1/.ci.sh 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.ci.sh 2026-06-25 14:07:00.000000000 +0000 @@ -6,7 +6,7 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2017-2024 Sebastian Pipping +# Copyright (c) 2017-2025 Sebastian Pipping # Copyright (c) 2017 Rolf Eike Beer # Copyright (c) 2019 Mohammed Khajapasha # Copyright (c) 2019 Manish, Kumar @@ -39,7 +39,7 @@ latest_brew_python3_bin="$(ls -1d /usr/local/Cellar/python/3.*/bin | sort -n | tail -n1)" export PATH="${latest_brew_python3_bin}${PATH:+:}${PATH}" elif [[ ${RUNNER_OS} = Linux ]]; then - export PATH="/usr/lib/llvm-19/bin:${PATH}" + export PATH="/usr/lib/llvm-21/bin:${PATH}" else echo "Unsupported RUNNER_OS \"${RUNNER_OS}\"." >&2 exit 1 diff -Nru expat-2.7.1/.gitattributes expat-2.8.2/.gitattributes --- expat-2.7.1/.gitattributes 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/.gitattributes 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,4 @@ +* text=auto +testdata/largefiles/* -text +testdata/largefiles/README.txt text=auto +*.bat text eol=crlf diff -Nru expat-2.7.1/.github/workflows/autotools-cmake.yml expat-2.8.2/.github/workflows/autotools-cmake.yml --- expat-2.7.1/.github/workflows/autotools-cmake.yml 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.github/workflows/autotools-cmake.yml 2026-06-25 14:07:00.000000000 +0000 @@ -5,7 +5,7 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2021-2025 Sebastian Pipping +# Copyright (c) 2021-2026 Sebastian Pipping # Copyright (c) 2023 Joyce Brum # Copyright (c) 2024 Dag-Erling Smørgrav # Licensed under the MIT license: @@ -45,6 +45,7 @@ checks: name: Ensure that GNU Autotools and CMake build systems agree strategy: + fail-fast: false matrix: include: - os: macos-14 @@ -56,12 +57,32 @@ - os: ubuntu-22.04 configure_args: --host=i686-w64-mingw32 cmake_args: -DCMAKE_TOOLCHAIN_FILE=cmake/mingw-toolchain.cmake + - os: ubuntu-24.04 + configure_args: >- + --enable-symbol-versioning + LDFLAGS=-Wl,--no-undefined-version + cmake_args: >- + -DEXPAT_SYMBOL_VERSIONING=ON + -DCMAKE_EXE_LINKER_FLAGS=-Wl,--no-undefined-version + -DCMAKE_MODULE_LINKER_FLAGS=-Wl,--no-undefined-version + -DCMAKE_SHARED_LINKER_FLAGS=-Wl,--no-undefined-version + - os: ubuntu-24.04 + configure_args: >- + --enable-xml-attr-info + --enable-symbol-versioning + LDFLAGS=-Wl,--no-undefined-version + cmake_args: >- + -DEXPAT_ATTR_INFO=ON + -DEXPAT_SYMBOL_VERSIONING=ON + -DCMAKE_EXE_LINKER_FLAGS=-Wl,--no-undefined-version + -DCMAKE_MODULE_LINKER_FLAGS=-Wl,--no-undefined-version + -DCMAKE_SHARED_LINKER_FLAGS=-Wl,--no-undefined-version defaults: run: shell: bash runs-on: "${{ matrix.os }}" steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: (Linux) Install build dependencies if: "${{ runner.os == 'Linux' }}" @@ -77,6 +98,7 @@ - name: (macOS) Install build dependencies if: "${{ runner.os == 'macOS' }}" run: | + brew uninstall cmake brew install \ autoconf \ automake \ @@ -168,9 +190,20 @@ - name: (Linux except MinGW) Check for identical exported symbols from both build systems if: "${{ runner.os == 'Linux' && ! contains(matrix.configure_args, 'mingw') }}" + env: + maximum: "${{ contains(matrix.configure_args, '--enable-xml-attr-info') && 'true' || 'false' }}" + symbol_versioning: "${{ contains(matrix.configure_args, '--enable-symbol-versioning') && 'true' || 'false' }}" run: | list_shared_library_symbols_sh="${GITHUB_WORKSPACE}"/.github/workflows/scripts/list-shared-library-symbols.sh - exported_symbols_txt="${GITHUB_WORKSPACE}"/.github/workflows/data/exported-symbols.txt + if ${symbol_versioning} ; then + if ${maximum} ; then + exported_symbols_txt="${GITHUB_WORKSPACE}"/.github/workflows/data/exported-symbols-versioned-maximum.txt + else + exported_symbols_txt="${GITHUB_WORKSPACE}"/.github/workflows/data/exported-symbols-versioned-default.txt + fi + else + exported_symbols_txt="${GITHUB_WORKSPACE}"/.github/workflows/data/exported-symbols-unversioned.txt + fi set -x cd expat/expat-*.*.*/ diff -Nru expat-2.7.1/.github/workflows/clang-format.yml expat-2.8.2/.github/workflows/clang-format.yml --- expat-2.7.1/.github/workflows/clang-format.yml 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.github/workflows/clang-format.yml 2026-06-25 14:07:00.000000000 +0000 @@ -5,7 +5,7 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2021-2024 Sebastian Pipping +# Copyright (c) 2021-2026 Sebastian Pipping # Copyright (c) 2023 Joyce Brum # Licensed under the MIT license: # @@ -43,21 +43,21 @@ jobs: clang_format: name: Enforce clang-format clean code - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - name: Install clang-format 19 + - name: Install clang-format 21 run: |- set -x source /etc/os-release wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - sudo add-apt-repository "deb https://apt.llvm.org/${UBUNTU_CODENAME}/ llvm-toolchain-${UBUNTU_CODENAME}-19 main" + sudo add-apt-repository "deb https://apt.llvm.org/${UBUNTU_CODENAME}/ llvm-toolchain-${UBUNTU_CODENAME}-21 main" sudo apt-get update # due to new repository sudo apt-get install --yes --no-install-recommends -V \ - clang-format-19 \ + clang-format-21 \ moreutils - echo /usr/lib/llvm-19/bin >>"${GITHUB_PATH}" + echo /usr/lib/llvm-21/bin >>"${GITHUB_PATH}" - name: Run clang-format run: | diff -Nru expat-2.7.1/.github/workflows/clang-static-analyzer.yml expat-2.8.2/.github/workflows/clang-static-analyzer.yml --- expat-2.7.1/.github/workflows/clang-static-analyzer.yml 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.github/workflows/clang-static-analyzer.yml 2026-06-25 14:07:00.000000000 +0000 @@ -5,7 +5,7 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2025 Sebastian Pipping +# Copyright (c) 2025-2026 Sebastian Pipping # Licensed under the MIT license: # # Permission is hereby granted, free of charge, to any person obtaining @@ -42,21 +42,21 @@ jobs: clang_static_analyzer: name: Enforce Clang Static Analyzer (scan-build) clean code - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - name: Install Clang 19 (including scan-build) + - name: Install Clang 21 (including scan-build) run: |- set -x source /etc/os-release wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - sudo add-apt-repository "deb https://apt.llvm.org/${UBUNTU_CODENAME}/ llvm-toolchain-${UBUNTU_CODENAME}-19 main" + sudo add-apt-repository "deb https://apt.llvm.org/${UBUNTU_CODENAME}/ llvm-toolchain-${UBUNTU_CODENAME}-21 main" sudo apt-get update # due to new repository sudo apt-get install --yes --no-install-recommends -V \ - clang-19 \ - clang-tools-19 - echo /usr/lib/llvm-19/bin >>"${GITHUB_PATH}" + clang-21 \ + clang-tools-21 + echo /usr/lib/llvm-21/bin >>"${GITHUB_PATH}" - name: Build using scan-build run: | @@ -83,7 +83,7 @@ - name: Store scan-build report if: always() - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: expat_scan_build_report_${{ github.sha }} path: html/ diff -Nru expat-2.7.1/.github/workflows/clang-tidy.yml expat-2.8.2/.github/workflows/clang-tidy.yml --- expat-2.7.1/.github/workflows/clang-tidy.yml 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.github/workflows/clang-tidy.yml 2026-06-25 14:07:00.000000000 +0000 @@ -5,7 +5,7 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2021-2024 Sebastian Pipping +# Copyright (c) 2021-2026 Sebastian Pipping # Copyright (c) 2023 Joyce Brum # Licensed under the MIT license: # @@ -43,20 +43,20 @@ jobs: clang_tidy: name: Enforce clang-tidy clean code - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - name: Install clang-tidy 19 + - name: Install clang-tidy 21 run: |- set -x source /etc/os-release wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - sudo add-apt-repository "deb https://apt.llvm.org/${UBUNTU_CODENAME}/ llvm-toolchain-${UBUNTU_CODENAME}-19 main" + sudo add-apt-repository "deb https://apt.llvm.org/${UBUNTU_CODENAME}/ llvm-toolchain-${UBUNTU_CODENAME}-21 main" sudo apt-get update # due to new repository sudo apt-get install --yes --no-install-recommends -V \ - clang-tidy-19 - echo /usr/lib/llvm-19/bin >>"${GITHUB_PATH}" + clang-tidy-21 + echo /usr/lib/llvm-21/bin >>"${GITHUB_PATH}" - name: Run clang-tidy run: | diff -Nru expat-2.7.1/.github/workflows/cmake-required-version.yml expat-2.8.2/.github/workflows/cmake-required-version.yml --- expat-2.7.1/.github/workflows/cmake-required-version.yml 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.github/workflows/cmake-required-version.yml 2026-06-25 14:07:00.000000000 +0000 @@ -46,7 +46,7 @@ name: Ensure realistic minimum CMake version requirement runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Install ancient CMake run: | diff -Nru expat-2.7.1/.github/workflows/codespell.yml expat-2.8.2/.github/workflows/codespell.yml --- expat-2.7.1/.github/workflows/codespell.yml 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.github/workflows/codespell.yml 2026-06-25 14:07:00.000000000 +0000 @@ -45,8 +45,8 @@ name: Enforce codespell-clean spelling runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: codespell-project/actions-codespell@406322ec52dd7b488e48c1c4b82e2a8b3a1bf630 # v2.1 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: codespell-project/actions-codespell@8f01853be192eb0f849a5c7d721450e7a467c579 # v2.2 with: path: expat/ # "arameter" is from "[p]arameter" in xmlwf help output diff -Nru expat-2.7.1/.github/workflows/coverage.yml expat-2.8.2/.github/workflows/coverage.yml --- expat-2.7.1/.github/workflows/coverage.yml 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.github/workflows/coverage.yml 2026-06-25 14:07:00.000000000 +0000 @@ -5,9 +5,10 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2021-2024 Sebastian Pipping +# Copyright (c) 2021-2025 Sebastian Pipping # Copyright (c) 2023 Joyce Brum # Copyright (c) 2024 Dag-Erling Smørgrav +# Copyright (c) 2026 Rosen Penev # Licensed under the MIT license: # # Permission is hereby granted, free of charge, to any person obtaining @@ -48,7 +49,7 @@ env: CFLAGS: -g3 -pipe steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Install build dependencies run: |- set -x -u @@ -65,9 +66,9 @@ gcc-multilib \ g++-multilib \ lcov \ - libbsd-dev \ lzip \ - moreutils + moreutils \ + retry # Install 32bit Wine sudo apt-get install --yes --no-install-recommends -V \ @@ -84,7 +85,7 @@ exec ./.ci.sh - name: Store coverage .info and HTML report - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: coverage path: expat/coverage__*/ diff -Nru expat-2.7.1/.github/workflows/coverity-scan.yml expat-2.8.2/.github/workflows/coverity-scan.yml --- expat-2.7.1/.github/workflows/coverity-scan.yml 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.github/workflows/coverity-scan.yml 2026-06-25 14:07:00.000000000 +0000 @@ -48,7 +48,7 @@ if: ${{ github.repository == 'libexpat/libexpat' }} runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: # The next two lines ensure clean and public-only submissions repository: libexpat/libexpat @@ -63,18 +63,18 @@ tee "${GITHUB_OUTPUT}" <<< "version=$(git describe --tags | sed -e 's,^R_,,' -e 's,_,.,g')" tee -a "${GITHUB_OUTPUT}" <<< "git_commit=$(git rev-parse HEAD)" - - name: Install Clang 19 + - name: Install Clang 21 run: |- set -x source /etc/os-release wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - sudo add-apt-repository "deb https://apt.llvm.org/${UBUNTU_CODENAME}/ llvm-toolchain-${UBUNTU_CODENAME}-19 main" + sudo add-apt-repository "deb https://apt.llvm.org/${UBUNTU_CODENAME}/ llvm-toolchain-${UBUNTU_CODENAME}-21 main" sudo apt-get update # due to new repository sudo apt-get install --yes --no-install-recommends -V \ - clang-19 \ - libclang-rt-19-dev \ - llvm-19 - echo /usr/lib/llvm-19/bin >>"${GITHUB_PATH}" + clang-21 \ + libclang-rt-21-dev \ + llvm-21 + echo /usr/lib/llvm-21/bin >>"${GITHUB_PATH}" - name: Install build dependencies run: |- @@ -118,7 +118,7 @@ description: "coverity-scan-action libexpat/libexpat / ${{ steps.determine_version.outputs.git_commit }}" - name: Offer analysis tarball for inspection - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: expat_coverity_scan_upload_${{ github.sha }} path: expat/cov-int.tgz diff -Nru expat-2.7.1/.github/workflows/cppcheck.yml expat-2.8.2/.github/workflows/cppcheck.yml --- expat-2.7.1/.github/workflows/cppcheck.yml 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.github/workflows/cppcheck.yml 2026-06-25 14:07:00.000000000 +0000 @@ -46,7 +46,7 @@ name: Run Cppcheck runs-on: macos-14 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Install runtime dependencies run: | set -x diff -Nru expat-2.7.1/.github/workflows/data/expat_config_h_cmake__expected.txt expat-2.8.2/.github/workflows/data/expat_config_h_cmake__expected.txt --- expat-2.7.1/.github/workflows/data/expat_config_h_cmake__expected.txt 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.github/workflows/data/expat_config_h_cmake__expected.txt 2026-06-25 14:07:00.000000000 +0000 @@ -5,10 +5,10 @@ HAVE_ARC4RANDOM_BUF HAVE_DLFCN_H HAVE_FCNTL_H +HAVE_GETENTROPY HAVE_GETPAGESIZE HAVE_GETRANDOM HAVE_INTTYPES_H -HAVE_LIBBSD HAVE_MEMORY_H HAVE_MMAP HAVE_STDINT_H diff -Nru expat-2.7.1/.github/workflows/data/expat_config_h_in__expected.txt expat-2.8.2/.github/workflows/data/expat_config_h_in__expected.txt --- expat-2.7.1/.github/workflows/data/expat_config_h_in__expected.txt 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.github/workflows/data/expat_config_h_in__expected.txt 2026-06-25 14:07:00.000000000 +0000 @@ -7,10 +7,10 @@ HAVE_CXX11 HAVE_DLFCN_H HAVE_FCNTL_H +HAVE_GETENTROPY HAVE_GETPAGESIZE HAVE_GETRANDOM HAVE_INTTYPES_H -HAVE_LIBBSD HAVE_MMAP HAVE_STDINT_H HAVE_STDIO_H diff -Nru expat-2.7.1/.github/workflows/data/exported-symbols-unversioned.txt expat-2.8.2/.github/workflows/data/exported-symbols-unversioned.txt --- expat-2.7.1/.github/workflows/data/exported-symbols-unversioned.txt 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/.github/workflows/data/exported-symbols-unversioned.txt 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,72 @@ +XML_DefaultCurrent +XML_ErrorString +XML_ExpatVersion +XML_ExpatVersionInfo +XML_ExternalEntityParserCreate +XML_FreeContentModel +XML_GetBase +XML_GetBuffer +XML_GetCurrentByteCount +XML_GetCurrentByteIndex +XML_GetCurrentColumnNumber +XML_GetCurrentLineNumber +XML_GetErrorCode +XML_GetFeatureList +XML_GetIdAttributeIndex +XML_GetInputContext +XML_GetParsingStatus +XML_GetSpecifiedAttributeCount +XML_MemFree +XML_MemMalloc +XML_MemRealloc +XML_Parse +XML_ParseBuffer +XML_ParserCreate +XML_ParserCreate_MM +XML_ParserCreateNS +XML_ParserFree +XML_ParserReset +XML_ResumeParser +XML_SetAllocTrackerActivationThreshold +XML_SetAllocTrackerMaximumAmplification +XML_SetAttlistDeclHandler +XML_SetBase +XML_SetBillionLaughsAttackProtectionActivationThreshold +XML_SetBillionLaughsAttackProtectionMaximumAmplification +XML_SetCdataSectionHandler +XML_SetCharacterDataHandler +XML_SetCommentHandler +XML_SetDefaultHandler +XML_SetDefaultHandlerExpand +XML_SetDoctypeDeclHandler +XML_SetElementDeclHandler +XML_SetElementHandler +XML_SetEncoding +XML_SetEndCdataSectionHandler +XML_SetEndDoctypeDeclHandler +XML_SetEndElementHandler +XML_SetEndNamespaceDeclHandler +XML_SetEntityDeclHandler +XML_SetExternalEntityRefHandler +XML_SetExternalEntityRefHandlerArg +XML_SetHashSalt +XML_SetHashSalt16Bytes +XML_SetNamespaceDeclHandler +XML_SetNotationDeclHandler +XML_SetNotStandaloneHandler +XML_SetParamEntityParsing +XML_SetProcessingInstructionHandler +XML_SetReparseDeferralEnabled +XML_SetReturnNSTriplet +XML_SetSkippedEntityHandler +XML_SetStartCdataSectionHandler +XML_SetStartDoctypeDeclHandler +XML_SetStartElementHandler +XML_SetStartNamespaceDeclHandler +XML_SetUnknownEncodingHandler +XML_SetUnparsedEntityDeclHandler +XML_SetUserData +XML_SetXmlDeclHandler +XML_StopParser +XML_UseForeignDTD +XML_UseParserAsHandlerArg diff -Nru expat-2.7.1/.github/workflows/data/exported-symbols-versioned-default.txt expat-2.8.2/.github/workflows/data/exported-symbols-versioned-default.txt --- expat-2.7.1/.github/workflows/data/exported-symbols-versioned-default.txt 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/.github/workflows/data/exported-symbols-versioned-default.txt 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,72 @@ +XML_DefaultCurrent@@LIBEXPAT_1.0.0 +XML_ErrorString@@LIBEXPAT_1.0.0 +XML_ExpatVersionInfo@@LIBEXPAT_1.95.3 +XML_ExpatVersion@@LIBEXPAT_1.95.0 +XML_ExternalEntityParserCreate@@LIBEXPAT_1.0.0 +XML_FreeContentModel@@LIBEXPAT_1.95.6 +XML_GetBase@@LIBEXPAT_1.0.0 +XML_GetBuffer@@LIBEXPAT_1.0.0 +XML_GetCurrentByteCount@@LIBEXPAT_1.1.0 +XML_GetCurrentByteIndex@@LIBEXPAT_1.0.0 +XML_GetCurrentColumnNumber@@LIBEXPAT_1.0.0 +XML_GetCurrentLineNumber@@LIBEXPAT_1.0.0 +XML_GetErrorCode@@LIBEXPAT_1.0.0 +XML_GetFeatureList@@LIBEXPAT_1.95.5 +XML_GetIdAttributeIndex@@LIBEXPAT_1.95.0 +XML_GetInputContext@@LIBEXPAT_1.95.0 +XML_GetParsingStatus@@LIBEXPAT_1.95.8 +XML_GetSpecifiedAttributeCount@@LIBEXPAT_1.1.0 +XML_MemFree@@LIBEXPAT_1.95.6 +XML_MemMalloc@@LIBEXPAT_1.95.6 +XML_MemRealloc@@LIBEXPAT_1.95.6 +XML_ParseBuffer@@LIBEXPAT_1.0.0 +XML_Parse@@LIBEXPAT_1.0.0 +XML_ParserCreate@@LIBEXPAT_1.0.0 +XML_ParserCreate_MM@@LIBEXPAT_1.95.0 +XML_ParserCreateNS@@LIBEXPAT_1.1.0 +XML_ParserFree@@LIBEXPAT_1.0.0 +XML_ParserReset@@LIBEXPAT_1.95.3 +XML_ResumeParser@@LIBEXPAT_1.95.8 +XML_SetAllocTrackerActivationThreshold@@LIBEXPAT_2.7.2 +XML_SetAllocTrackerMaximumAmplification@@LIBEXPAT_2.7.2 +XML_SetAttlistDeclHandler@@LIBEXPAT_1.95.0 +XML_SetBase@@LIBEXPAT_1.0.0 +XML_SetBillionLaughsAttackProtectionActivationThreshold@@LIBEXPAT_2.4.0 +XML_SetBillionLaughsAttackProtectionMaximumAmplification@@LIBEXPAT_2.4.0 +XML_SetCdataSectionHandler@@LIBEXPAT_1.1.0 +XML_SetCharacterDataHandler@@LIBEXPAT_1.0.0 +XML_SetCommentHandler@@LIBEXPAT_1.1.0 +XML_SetDefaultHandlerExpand@@LIBEXPAT_1.1.0 +XML_SetDefaultHandler@@LIBEXPAT_1.0.0 +XML_SetDoctypeDeclHandler@@LIBEXPAT_1.95.0 +XML_SetElementDeclHandler@@LIBEXPAT_1.95.0 +XML_SetElementHandler@@LIBEXPAT_1.0.0 +XML_SetEncoding@@LIBEXPAT_1.1.0 +XML_SetEndCdataSectionHandler@@LIBEXPAT_1.95.0 +XML_SetEndDoctypeDeclHandler@@LIBEXPAT_1.95.0 +XML_SetEndElementHandler@@LIBEXPAT_1.95.0 +XML_SetEndNamespaceDeclHandler@@LIBEXPAT_1.95.0 +XML_SetEntityDeclHandler@@LIBEXPAT_1.95.0 +XML_SetExternalEntityRefHandlerArg@@LIBEXPAT_1.1.0 +XML_SetExternalEntityRefHandler@@LIBEXPAT_1.0.0 +XML_SetHashSalt16Bytes@@LIBEXPAT_2.8.0 +XML_SetHashSalt@@LIBEXPAT_2.1.0 +XML_SetNamespaceDeclHandler@@LIBEXPAT_1.1.0 +XML_SetNotationDeclHandler@@LIBEXPAT_1.0.0 +XML_SetNotStandaloneHandler@@LIBEXPAT_1.1.0 +XML_SetParamEntityParsing@@LIBEXPAT_1.95.0 +XML_SetProcessingInstructionHandler@@LIBEXPAT_1.0.0 +XML_SetReparseDeferralEnabled@@LIBEXPAT_2.6.0 +XML_SetReturnNSTriplet@@LIBEXPAT_1.95.0 +XML_SetSkippedEntityHandler@@LIBEXPAT_1.95.4 +XML_SetStartCdataSectionHandler@@LIBEXPAT_1.95.0 +XML_SetStartDoctypeDeclHandler@@LIBEXPAT_1.95.0 +XML_SetStartElementHandler@@LIBEXPAT_1.95.0 +XML_SetStartNamespaceDeclHandler@@LIBEXPAT_1.95.0 +XML_SetUnknownEncodingHandler@@LIBEXPAT_1.0.0 +XML_SetUnparsedEntityDeclHandler@@LIBEXPAT_1.0.0 +XML_SetUserData@@LIBEXPAT_1.0.0 +XML_SetXmlDeclHandler@@LIBEXPAT_1.95.0 +XML_StopParser@@LIBEXPAT_1.95.8 +XML_UseForeignDTD@@LIBEXPAT_1.95.5 +XML_UseParserAsHandlerArg@@LIBEXPAT_1.0.0 diff -Nru expat-2.7.1/.github/workflows/data/exported-symbols-versioned-maximum.txt expat-2.8.2/.github/workflows/data/exported-symbols-versioned-maximum.txt --- expat-2.7.1/.github/workflows/data/exported-symbols-versioned-maximum.txt 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/.github/workflows/data/exported-symbols-versioned-maximum.txt 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,73 @@ +XML_DefaultCurrent@@LIBEXPAT_1.0.0 +XML_ErrorString@@LIBEXPAT_1.0.0 +XML_ExpatVersionInfo@@LIBEXPAT_1.95.3 +XML_ExpatVersion@@LIBEXPAT_1.95.0 +XML_ExternalEntityParserCreate@@LIBEXPAT_1.0.0 +XML_FreeContentModel@@LIBEXPAT_1.95.6 +XML_GetAttributeInfo@@LIBEXPAT_2.1.0 +XML_GetBase@@LIBEXPAT_1.0.0 +XML_GetBuffer@@LIBEXPAT_1.0.0 +XML_GetCurrentByteCount@@LIBEXPAT_1.1.0 +XML_GetCurrentByteIndex@@LIBEXPAT_1.0.0 +XML_GetCurrentColumnNumber@@LIBEXPAT_1.0.0 +XML_GetCurrentLineNumber@@LIBEXPAT_1.0.0 +XML_GetErrorCode@@LIBEXPAT_1.0.0 +XML_GetFeatureList@@LIBEXPAT_1.95.5 +XML_GetIdAttributeIndex@@LIBEXPAT_1.95.0 +XML_GetInputContext@@LIBEXPAT_1.95.0 +XML_GetParsingStatus@@LIBEXPAT_1.95.8 +XML_GetSpecifiedAttributeCount@@LIBEXPAT_1.1.0 +XML_MemFree@@LIBEXPAT_1.95.6 +XML_MemMalloc@@LIBEXPAT_1.95.6 +XML_MemRealloc@@LIBEXPAT_1.95.6 +XML_ParseBuffer@@LIBEXPAT_1.0.0 +XML_Parse@@LIBEXPAT_1.0.0 +XML_ParserCreate@@LIBEXPAT_1.0.0 +XML_ParserCreate_MM@@LIBEXPAT_1.95.0 +XML_ParserCreateNS@@LIBEXPAT_1.1.0 +XML_ParserFree@@LIBEXPAT_1.0.0 +XML_ParserReset@@LIBEXPAT_1.95.3 +XML_ResumeParser@@LIBEXPAT_1.95.8 +XML_SetAllocTrackerActivationThreshold@@LIBEXPAT_2.7.2 +XML_SetAllocTrackerMaximumAmplification@@LIBEXPAT_2.7.2 +XML_SetAttlistDeclHandler@@LIBEXPAT_1.95.0 +XML_SetBase@@LIBEXPAT_1.0.0 +XML_SetBillionLaughsAttackProtectionActivationThreshold@@LIBEXPAT_2.4.0 +XML_SetBillionLaughsAttackProtectionMaximumAmplification@@LIBEXPAT_2.4.0 +XML_SetCdataSectionHandler@@LIBEXPAT_1.1.0 +XML_SetCharacterDataHandler@@LIBEXPAT_1.0.0 +XML_SetCommentHandler@@LIBEXPAT_1.1.0 +XML_SetDefaultHandlerExpand@@LIBEXPAT_1.1.0 +XML_SetDefaultHandler@@LIBEXPAT_1.0.0 +XML_SetDoctypeDeclHandler@@LIBEXPAT_1.95.0 +XML_SetElementDeclHandler@@LIBEXPAT_1.95.0 +XML_SetElementHandler@@LIBEXPAT_1.0.0 +XML_SetEncoding@@LIBEXPAT_1.1.0 +XML_SetEndCdataSectionHandler@@LIBEXPAT_1.95.0 +XML_SetEndDoctypeDeclHandler@@LIBEXPAT_1.95.0 +XML_SetEndElementHandler@@LIBEXPAT_1.95.0 +XML_SetEndNamespaceDeclHandler@@LIBEXPAT_1.95.0 +XML_SetEntityDeclHandler@@LIBEXPAT_1.95.0 +XML_SetExternalEntityRefHandlerArg@@LIBEXPAT_1.1.0 +XML_SetExternalEntityRefHandler@@LIBEXPAT_1.0.0 +XML_SetHashSalt16Bytes@@LIBEXPAT_2.8.0 +XML_SetHashSalt@@LIBEXPAT_2.1.0 +XML_SetNamespaceDeclHandler@@LIBEXPAT_1.1.0 +XML_SetNotationDeclHandler@@LIBEXPAT_1.0.0 +XML_SetNotStandaloneHandler@@LIBEXPAT_1.1.0 +XML_SetParamEntityParsing@@LIBEXPAT_1.95.0 +XML_SetProcessingInstructionHandler@@LIBEXPAT_1.0.0 +XML_SetReparseDeferralEnabled@@LIBEXPAT_2.6.0 +XML_SetReturnNSTriplet@@LIBEXPAT_1.95.0 +XML_SetSkippedEntityHandler@@LIBEXPAT_1.95.4 +XML_SetStartCdataSectionHandler@@LIBEXPAT_1.95.0 +XML_SetStartDoctypeDeclHandler@@LIBEXPAT_1.95.0 +XML_SetStartElementHandler@@LIBEXPAT_1.95.0 +XML_SetStartNamespaceDeclHandler@@LIBEXPAT_1.95.0 +XML_SetUnknownEncodingHandler@@LIBEXPAT_1.0.0 +XML_SetUnparsedEntityDeclHandler@@LIBEXPAT_1.0.0 +XML_SetUserData@@LIBEXPAT_1.0.0 +XML_SetXmlDeclHandler@@LIBEXPAT_1.95.0 +XML_StopParser@@LIBEXPAT_1.95.8 +XML_UseForeignDTD@@LIBEXPAT_1.95.5 +XML_UseParserAsHandlerArg@@LIBEXPAT_1.0.0 diff -Nru expat-2.7.1/.github/workflows/data/exported-symbols.txt expat-2.8.2/.github/workflows/data/exported-symbols.txt --- expat-2.7.1/.github/workflows/data/exported-symbols.txt 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.github/workflows/data/exported-symbols.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -XML_DefaultCurrent -XML_ErrorString -XML_ExpatVersion -XML_ExpatVersionInfo -XML_ExternalEntityParserCreate -XML_FreeContentModel -XML_GetBase -XML_GetBuffer -XML_GetCurrentByteCount -XML_GetCurrentByteIndex -XML_GetCurrentColumnNumber -XML_GetCurrentLineNumber -XML_GetErrorCode -XML_GetFeatureList -XML_GetIdAttributeIndex -XML_GetInputContext -XML_GetParsingStatus -XML_GetSpecifiedAttributeCount -XML_MemFree -XML_MemMalloc -XML_MemRealloc -XML_Parse -XML_ParseBuffer -XML_ParserCreate -XML_ParserCreate_MM -XML_ParserCreateNS -XML_ParserFree -XML_ParserReset -XML_ResumeParser -XML_SetAttlistDeclHandler -XML_SetBase -XML_SetBillionLaughsAttackProtectionActivationThreshold -XML_SetBillionLaughsAttackProtectionMaximumAmplification -XML_SetCdataSectionHandler -XML_SetCharacterDataHandler -XML_SetCommentHandler -XML_SetDefaultHandler -XML_SetDefaultHandlerExpand -XML_SetDoctypeDeclHandler -XML_SetElementDeclHandler -XML_SetElementHandler -XML_SetEncoding -XML_SetEndCdataSectionHandler -XML_SetEndDoctypeDeclHandler -XML_SetEndElementHandler -XML_SetEndNamespaceDeclHandler -XML_SetEntityDeclHandler -XML_SetExternalEntityRefHandler -XML_SetExternalEntityRefHandlerArg -XML_SetHashSalt -XML_SetNamespaceDeclHandler -XML_SetNotationDeclHandler -XML_SetNotStandaloneHandler -XML_SetParamEntityParsing -XML_SetProcessingInstructionHandler -XML_SetReparseDeferralEnabled -XML_SetReturnNSTriplet -XML_SetSkippedEntityHandler -XML_SetStartCdataSectionHandler -XML_SetStartDoctypeDeclHandler -XML_SetStartElementHandler -XML_SetStartNamespaceDeclHandler -XML_SetUnknownEncodingHandler -XML_SetUnparsedEntityDeclHandler -XML_SetUserData -XML_SetXmlDeclHandler -XML_StopParser -XML_UseForeignDTD -XML_UseParserAsHandlerArg diff -Nru expat-2.7.1/.github/workflows/emscripten.yml expat-2.8.2/.github/workflows/emscripten.yml --- expat-2.7.1/.github/workflows/emscripten.yml 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.github/workflows/emscripten.yml 2026-06-25 14:07:00.000000000 +0000 @@ -5,7 +5,7 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2025 Sebastian Pipping +# Copyright (c) 2025-2026 Sebastian Pipping # Licensed under the MIT license: # # Permission is hereby granted, free of charge, to any person obtaining @@ -42,9 +42,9 @@ jobs: emscripten: name: Build with Emscripten - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Install build dependencies run: |- @@ -55,12 +55,13 @@ emscripten \ make - - name: Build using musl-tools + - name: Build using Emscripten run: | cmake_args=( -DCMAKE_C_FLAGS='-O1 -pipe -Wall -Wextra -pedantic -Wno-overlength-strings' -DCMAKE_CXX_FLAGS='-O2 -pipe -Wall -Wextra -pedantic -Wno-overlength-strings' -DEXPAT_BUILD_DOCS=OFF + -DEXPAT_SHARED_LIBS=OFF # to silence warning; not supported by Emscripten -DEXPAT_WARNINGS_AS_ERRORS=ON ) set -x diff -Nru expat-2.7.1/.github/workflows/expat_config_h.yml expat-2.8.2/.github/workflows/expat_config_h.yml --- expat-2.7.1/.github/workflows/expat_config_h.yml 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.github/workflows/expat_config_h.yml 2026-06-25 14:07:00.000000000 +0000 @@ -45,7 +45,7 @@ name: Check expat_config.h.{in,cmake} for regressions runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Check expat_config.h.{in,cmake} for regressions run: | set -v diff -Nru expat-2.7.1/.github/workflows/freebsd.yml expat-2.8.2/.github/workflows/freebsd.yml --- expat-2.7.1/.github/workflows/freebsd.yml 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/.github/workflows/freebsd.yml 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,99 @@ +# __ __ _ +# ___\ \/ /_ __ __ _| |_ +# / _ \\ /| '_ \ / _` | __| +# | __// \| |_) | (_| | |_ +# \___/_/\_\ .__/ \__,_|\__| +# |_| XML parser +# +# Copyright (c) 2025-2026 Sebastian Pipping +# Copyright (c) 2025 Daniel Engberg +# Licensed under the MIT license: +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to permit +# persons to whom the Software is furnished to do so, subject to the +# following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +# NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +# USE OR OTHER DEALINGS IN THE SOFTWARE. + +name: Build in a FreeBSD VM + +on: + pull_request: + push: + schedule: + - cron: '0 2 * * 5' # Every Friday at 2am + workflow_dispatch: + +permissions: + contents: read + +jobs: + freebsd: + name: Build in a FreeBSD VM + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + + - uses: vmactions/freebsd-vm@b84ab5559b5a1bb4b8ee2737d2506a16e1737636 # v1.4.8 + with: + release: "15.0" + usesh: true + + prepare: | + set -e -u -x + pkg install -y \ + autoconf \ + automake \ + bash \ + cmake-core \ + libtool \ + python3 \ + wget + + run: | + set -e -u -x + + compile_flags='-Wall -Wextra -pedantic -O1 -pipe' + export CFLAGS="-std=c99 ${compile_flags}" + export CXXFLAGS="-std=c++11 ${compile_flags}" + + cc -v + c++ -v + + cd expat + ./buildconf.sh + + # 1 of 2: GNU Autotools build system + mkdir build_autotools + cd build_autotools + ../configure + make -j2 CFLAGS="${CFLAGS} -Werror" + make check CFLAGS="${CFLAGS} -Werror" CXXFLAGS="${CXXFLAGS} -Werror" + make run-xmltest + make install DESTDIR="${PWD}/ROOT/" + find ROOT/ + cd .. + + # 2 of 2: CMake build system + mkdir build_cmake + cd build_cmake + cmake -S .. -B . -DEXPAT_WARNINGS_AS_ERRORS:BOOL=ON + make -j2 VERBOSE=1 + make test VERBOSE=1 + make run-xmltest VERBOSE=1 + make install DESTDIR="${PWD}/ROOT/" + find ROOT/ + cd .. diff -Nru expat-2.7.1/.github/workflows/fuzzing.yml expat-2.8.2/.github/workflows/fuzzing.yml --- expat-2.7.1/.github/workflows/fuzzing.yml 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.github/workflows/fuzzing.yml 2026-06-25 14:07:00.000000000 +0000 @@ -5,7 +5,7 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2024-2025 Sebastian Pipping +# Copyright (c) 2024-2026 Sebastian Pipping # Licensed under the MIT license: # # Permission is hereby granted, free of charge, to any person obtaining @@ -46,26 +46,27 @@ fail-fast: false matrix: fuzzer: + - xml_lpm_fuzzer - xml_parse_fuzzer_UTF-8 - xml_parsebuffer_fuzzer_UTF-16LE runs-on: ubuntu-24.04 env: fuzzer: ${{ matrix.fuzzer }} steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - name: Install Clang 19 + - name: Install Clang 21 run: |- set -x source /etc/os-release wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - sudo add-apt-repository "deb https://apt.llvm.org/${UBUNTU_CODENAME}/ llvm-toolchain-${UBUNTU_CODENAME}-19 main" + sudo add-apt-repository "deb https://apt.llvm.org/${UBUNTU_CODENAME}/ llvm-toolchain-${UBUNTU_CODENAME}-21 main" sudo apt-get update # due to new repository sudo apt-get install --yes --no-install-recommends -V \ - clang-19 \ - libclang-rt-19-dev \ - llvm-19 - echo /usr/lib/llvm-19/bin >>"${GITHUB_PATH}" + clang-21 \ + libclang-rt-21-dev \ + llvm-21 + echo /usr/lib/llvm-21/bin >>"${GITHUB_PATH}" - name: Install build dependencies run: |- @@ -77,6 +78,7 @@ libtool \ libprotobuf-dev \ lzip \ + parallel \ protobuf-compiler - name: Turn Git clone into Autotools "make dist" release tarball @@ -126,12 +128,11 @@ set -x cd expat/build/ wget -q -O corpus.zip "https://storage.googleapis.com/expat-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/expat_${fuzzer}/public.zip" - unzip -q -d corpus/ corpus.zip + unzip -q -d c/ corpus.zip - name: Run fuzzing regression tests (1 to 5 minutes) run: | fuzz_args=( - -jobs=$(nproc) -print_final_stats=1 -rss_limit_mb=2560 # from OSS-Fuzz -timeout=25 # from OSS-Fuzz @@ -140,15 +141,26 @@ set -x -o pipefail cd expat/build/ + # Configure UBSan to show (non-default) stack traces for runtime errors + # NOTE: "halt_on_error=1" we don't need to add because of the + # -fno-sanitize-recover=all for CFLAGS further up. + # NOTE: "abort_on_error=1" we don't need here because to CI, + # a non-zero exit code is all that matters. + export UBSAN_OPTIONS='print_stacktrace=1' + mkdir coverage/ export LLVM_PROFILE_FILE=coverage/expat-%p.profraw - find corpus/ -type f | sort | xargs "fuzz/${fuzzer}" "${fuzz_args[@]}" - - - name: Store fuzzing logs of last batch - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + find c/ -type f | sort \ + | parallel --max-args 1000 \ + "fuzz/${fuzzer}" "${fuzz_args[@]}" \ + |& tee fuzz-all.log + + - name: Store fuzzing logs + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + if: ${{ always() }} with: - name: ${{ matrix.fuzzer }}_${{ github.sha }}_logs_last + name: ${{ matrix.fuzzer }}_${{ github.sha }}_logs path: expat/build/fuzz-*.log if-no-files-found: error @@ -166,7 +178,7 @@ llvm-cov report fuzz/${fuzzer} -instr-profile=coverage/expat.profdata -sources ../lib/ | tee coverage/report_files.txt - name: Store coverage report - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: ${{ matrix.fuzzer }}_${{ github.sha }}_coverage path: expat/build/coverage/ diff -Nru expat-2.7.1/.github/workflows/linux.yml expat-2.8.2/.github/workflows/linux.yml --- expat-2.7.1/.github/workflows/linux.yml 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.github/workflows/linux.yml 2026-06-25 14:07:00.000000000 +0000 @@ -5,10 +5,12 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2021-2025 Sebastian Pipping +# Copyright (c) 2021-2026 Sebastian Pipping # Copyright (c) 2023 Joyce Brum # Copyright (c) 2023 Hanno Böck # Copyright (c) 2024 Dag-Erling Smørgrav +# Copyright (c) 2026 Rosen Penev +# Copyright (c) 2026 Matthew Fernandez # Licensed under the MIT license: # # Permission is hereby granted, free of charge, to any person obtaining @@ -46,6 +48,7 @@ checks: name: Perform checks strategy: + fail-fast: false matrix: include: - MODE: cmake-oos @@ -82,11 +85,11 @@ FLAT_ENV: CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-g++ LD=i686-w64-mingw32-ld QA_PROCESSOR=gcov CMAKE_ARGS="-DCMAKE_SYSTEM_NAME=Windows -DWIN32=ON -DMINGW=ON -DEXPAT_ATTR_INFO=ON" - MODE: qa-sh FLAT_ENV: CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-g++ LD=i686-w64-mingw32-ld QA_PROCESSOR=gcov CMAKE_ARGS="-DCMAKE_SYSTEM_NAME=Windows -DWIN32=ON -DMINGW=ON -DEXPAT_ATTR_INFO=ON -DEXPAT_CHAR_TYPE=wchar_t" - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 env: CFLAGS: -g3 -pipe steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Install build dependencies (MinGW) if: "${{ contains(matrix.FLAT_ENV, 'mingw') }}" run: |- @@ -97,6 +100,7 @@ sudo apt-get update # due to new architecture sudo apt-get install --yes --no-install-recommends -V \ mingw-w64 \ + retry \ wine-stable \ wine32:i386 - name: Install build dependencies (Non-MinGW) @@ -105,12 +109,13 @@ set -x source /etc/os-release wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - sudo add-apt-repository "deb https://apt.llvm.org/${UBUNTU_CODENAME}/ llvm-toolchain-${UBUNTU_CODENAME}-19 main" + sudo add-apt-repository "deb https://apt.llvm.org/${UBUNTU_CODENAME}/ llvm-toolchain-${UBUNTU_CODENAME}-21 main" sudo apt-get update # due to new repository - # NOTE: Please note the version-specific ${PATH} extension for Clang adding /usr/lib/llvm-19/bin in .ci.sh + # NOTE: Please note the version-specific ${PATH} extension for Clang adding /usr/lib/llvm-21/bin in .ci.sh sudo apt-get install --yes --no-install-recommends -V \ - clang-19 \ - libclang-rt-19-dev + clang-21 \ + libclang-rt-21-dev \ + llvm-21 - name: Install build dependencies (common) run: |- sudo apt-get install --yes --no-install-recommends -V \ @@ -119,7 +124,6 @@ gcc-multilib \ g++-multilib \ lcov \ - libbsd-dev \ lzip \ moreutils - name: Perform check "${{ matrix.MODE }}" diff -Nru expat-2.7.1/.github/workflows/macos.yml expat-2.8.2/.github/workflows/macos.yml --- expat-2.7.1/.github/workflows/macos.yml 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.github/workflows/macos.yml 2026-06-25 14:07:00.000000000 +0000 @@ -5,7 +5,7 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2020-2024 Sebastian Pipping +# Copyright (c) 2020-2025 Sebastian Pipping # Copyright (c) 2023 Joyce Brum # Copyright (c) 2024 Dag-Erling Smørgrav # Licensed under the MIT license: @@ -46,7 +46,7 @@ name: Perform checks strategy: matrix: - os: [macos-13, macos-15] + os: [macos-14, macos-15] include: - MODE: cmake-oos - MODE: distcheck @@ -54,7 +54,7 @@ FLAT_ENV: CC=clang CXX=clang++ LD=clang++ QA_SANITIZER=address runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Install build dependencies run: | sudo rm /usr/local/bin/2to3 # so that "brew link" will work diff -Nru expat-2.7.1/.github/workflows/musl.yml expat-2.8.2/.github/workflows/musl.yml --- expat-2.7.1/.github/workflows/musl.yml 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.github/workflows/musl.yml 2026-06-25 14:07:00.000000000 +0000 @@ -44,7 +44,7 @@ name: Build with musl runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Install build dependencies run: |- diff -Nru expat-2.7.1/.github/workflows/perl-integration.yml expat-2.8.2/.github/workflows/perl-integration.yml --- expat-2.7.1/.github/workflows/perl-integration.yml 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.github/workflows/perl-integration.yml 2026-06-25 14:07:00.000000000 +0000 @@ -5,7 +5,7 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2025 Sebastian Pipping +# Copyright (c) 2025-2026 Sebastian Pipping # Licensed under the MIT license: # # Permission is hereby granted, free of charge, to any person obtaining @@ -42,9 +42,24 @@ jobs: perl_integration: name: Run Perl XML::Parser integration tests + strategy: + fail-fast: false + matrix: + xml_parser_commit: + - "7096c4e45a62a23837382cf822d8c2dab780a3a1" # ==2.47 without AI + - "16fff0b90acbfb788f4c16ddc7c594ece91b5089" # ==2.59 with AI runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + + - name: Install system dependencies + if: "${{ matrix.xml_parser_commit != '7096c4e45a62a23837382cf822d8c2dab780a3a1' }}" + run: | + set -x + sudo apt-get update + sudo apt-get install --yes --no-install-recommends -V \ + libfile-sharedir-install-perl \ + libfile-sharedir-perl - name: Build and replace system Expat run: | @@ -66,12 +81,16 @@ sudo make -C build VERBOSE=1 install - name: Run Perl XML::Parser integration tests + env: + xml_parser_commit: "${{ matrix.xml_parser_commit }}" run: | set -x # NOTE: The version pin is for CI stability. - git clone --depth 1 --branch 2.47 https://github.com/cpan-authors/XML-Parser + git -c init.defaultbranch=main init XML-Parser/ cd XML-Parser/ + git fetch --depth 1 https://github.com/cpan-authors/XML-Parser "${xml_parser_commit}" + git -c advice.detachedHead=false checkout FETCH_HEAD perl Makefile.PL make -j$(nproc) diff -Nru expat-2.7.1/.github/workflows/scripts/mass-cppcheck.sh expat-2.8.2/.github/workflows/scripts/mass-cppcheck.sh --- expat-2.7.1/.github/workflows/scripts/mass-cppcheck.sh 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.github/workflows/scripts/mass-cppcheck.sh 2026-06-25 14:07:00.000000000 +0000 @@ -6,7 +6,7 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2021-2025 Sebastian Pipping +# Copyright (c) 2021-2026 Sebastian Pipping # Copyright (c) 2024 Dag-Erling Smørgrav # Licensed under the MIT license: # @@ -41,9 +41,11 @@ --error-exitcode=1 --force --check-level=exhaustive - --suppress=objectIndex - --suppress=unknownMacro + --inline-suppr '-D__has_attribute(x)=1' + '-D__has_feature(x)=1' + '-DEXPAT_FMT_SIZE_T(x)=%llu' + '-DEXPAT_FMT_ULL(x)=%llu' -DXML_CONTEXT_BYTES=${xml_context_bytes} -DXML_GE=${xml_ge} ) diff -Nru expat-2.7.1/.github/workflows/solaris.yml expat-2.8.2/.github/workflows/solaris.yml --- expat-2.7.1/.github/workflows/solaris.yml 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/.github/workflows/solaris.yml 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,104 @@ +# __ __ _ +# ___\ \/ /_ __ __ _| |_ +# / _ \\ /| '_ \ / _` | __| +# | __// \| |_) | (_| | |_ +# \___/_/\_\ .__/ \__,_|\__| +# |_| XML parser +# +# Copyright (c) 2026 Sebastian Pipping +# Licensed under the MIT license: +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to permit +# persons to whom the Software is furnished to do so, subject to the +# following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +# NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +# USE OR OTHER DEALINGS IN THE SOFTWARE. + +name: Build in a Solaris VM + +on: + pull_request: + push: + schedule: + - cron: '0 2 * * 5' # Every Friday at 2am + workflow_dispatch: + +permissions: + contents: read + +jobs: + solaris: + name: Build in a Solaris VM + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + + - uses: vmactions/solaris-vm@d30dd6c228c8661ade859e36ead7660b9a62efcc # v1.3.7 + with: + release: "11.4-gcc" # with GCC 14 as of 2026-01-11 + usesh: true + + prepare: | + set -e -u -x + + # NOTE: Exit code 0 means "all now installed and all not before". + # Exit code 3 means "all now installed and some not before". + # Exit code 4 means "all now installed and all already before". + # Command "pkg list -a" can show a list of packages available. + pkg install \ + autoconf \ + automake \ + bash \ + cmake \ + gnu-make \ + gnu-sed \ + libtool \ + || [ $? -eq 3 -o $? -eq 4 ] # see comment block above + + run: | + set -e -u -x + + compile_flags='-Wall -Wextra -pedantic -O1 -pipe' + export CFLAGS="-std=c99 ${compile_flags}" + export CXXFLAGS="-std=c++11 ${compile_flags}" + + gcc -v + g++ -v + + cd expat + ./buildconf.sh + + # 1 of 2: GNU Autotools build system + mkdir build_autotools + cd build_autotools + ../configure + gmake -j2 CFLAGS="${CFLAGS} -Werror" + gmake check CFLAGS="${CFLAGS} -Werror" CXXFLAGS="${CXXFLAGS} -Werror" + gmake run-xmltest + gmake install DESTDIR="${PWD}/ROOT/" + find ROOT/ + cd .. + + # 2 of 2: CMake build system + mkdir build_cmake + cd build_cmake + cmake -S .. -B . -DEXPAT_WARNINGS_AS_ERRORS:BOOL=ON + gmake -j2 VERBOSE=1 + gmake test VERBOSE=1 + gmake run-xmltest VERBOSE=1 + gmake install DESTDIR="${PWD}/ROOT/" + find ROOT/ + cd .. diff -Nru expat-2.7.1/.github/workflows/valid-xml.yml expat-2.8.2/.github/workflows/valid-xml.yml --- expat-2.7.1/.github/workflows/valid-xml.yml 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.github/workflows/valid-xml.yml 2026-06-25 14:07:00.000000000 +0000 @@ -5,7 +5,7 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2021-2025 Sebastian Pipping +# Copyright (c) 2021-2026 Sebastian Pipping # Copyright (c) 2023 Joyce Brum # Licensed under the MIT license: # @@ -45,17 +45,46 @@ name: Ensure well-formed and valid XML runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Install build dependencies + env: + tidy_version: 5.8.0 run: |- set -x sudo apt-get update sudo apt-get install --yes --no-install-recommends -V \ docbook \ libxml2-utils \ + moreutils \ w3c-sgml-lib + # NOTE: Ubuntu 24.04 has tidy 5.6.0 while we need more recent tidy 5.8.0 + wget --progress=dot:giga "https://github.com/htacg/tidy-html5/releases/download/${tidy_version}/tidy-${tidy_version}-Linux-64bit.deb" + sudo apt-get install --yes "./tidy-${tidy_version}-Linux-64bit.deb" + + - name: Enforce clean XML + run: | + tidy_args=( + --indent 1 + --tidy-mark no + --vertical-space yes + --wrap 90 + --write-back yes + ) + set -x -o pipefail + + # Re-indent XHTML + tidy "${tidy_args[@]}" expat/doc/reference.html + + # Drop trailing whitespace + sed 's, \+$,,' -i.bak expat/doc/reference.html + + # Replace leading tabs by spaces + expand -i -t 2 expat/doc/xmlwf.xml | sponge expat/doc/xmlwf.xml + + git -c color.ui=yes diff --exit-code # i.e. show diff and fail CI if there is a diff + - name: Ensure well-formed and valid XML run: | set -x diff -Nru expat-2.7.1/.github/workflows/wasi_sdk.yml expat-2.8.2/.github/workflows/wasi_sdk.yml --- expat-2.7.1/.github/workflows/wasi_sdk.yml 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/.github/workflows/wasi_sdk.yml 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,72 @@ +# __ __ _ +# ___\ \/ /_ __ __ _| |_ +# / _ \\ /| '_ \ / _` | __| +# | __// \| |_) | (_| | |_ +# \___/_/\_\ .__/ \__,_|\__| +# |_| XML parser +# +# Copyright (c) 2025-2026 Sebastian Pipping +# Copyright (c) 2025 Atrem Borovik +# Licensed under the MIT license: +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to permit +# persons to whom the Software is furnished to do so, subject to the +# following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +# NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +# USE OR OTHER DEALINGS IN THE SOFTWARE. + +name: Build with WASI SDK + +on: + pull_request: + push: + schedule: + - cron: '0 2 * * 5' # Every Friday at 2am + workflow_dispatch: + +permissions: + contents: read + +jobs: + wasi_sdk: + name: Build with WASI SDK + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + + - name: Install build dependencies + env: + wasi_sdk_major: "33" + wasi_sdk_minor: "0" + run: |- + set -x -u + wget "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${wasi_sdk_major}/wasi-sdk-${wasi_sdk_major}.${wasi_sdk_minor}-x86_64-linux.deb" + sudo apt-get install --yes "./wasi-sdk-${wasi_sdk_major}.${wasi_sdk_minor}-x86_64-linux.deb" + + - name: Build using WASI SDK + run: | + cmake_args=( + -DCMAKE_TOOLCHAIN_FILE=/opt/wasi-sdk/share/cmake/wasi-sdk-p1.cmake + -DCMAKE_C_FLAGS='-O1 -pipe -Wall -Wextra -pedantic -Wno-overlength-strings' + -DCMAKE_CXX_FLAGS='-O2 -pipe -Wall -Wextra -pedantic -Wno-overlength-strings' + -DEXPAT_BUILD_DOCS=OFF + -DEXPAT_BUILD_TESTS=OFF + -DEXPAT_SHARED_LIBS=OFF + -DEXPAT_WARNINGS_AS_ERRORS=ON + ) + set -x + cmake "${cmake_args[@]}" -S expat/ -B build/ + make -C build -j$(nproc) VERBOSE=1 all diff -Nru expat-2.7.1/.github/workflows/windows-binaries.yml expat-2.8.2/.github/workflows/windows-binaries.yml --- expat-2.7.1/.github/workflows/windows-binaries.yml 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.github/workflows/windows-binaries.yml 2026-06-25 14:07:00.000000000 +0000 @@ -5,7 +5,7 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2025 Sebastian Pipping +# Copyright (c) 2025-2026 Sebastian Pipping # Licensed under the MIT license: # # Permission is hereby granted, free of charge, to any person obtaining @@ -46,16 +46,16 @@ fail-fast: false matrix: include: - - runs-on: windows-2019 + - runs-on: windows-2022 cmake_build_type: Debug - cmake_generator: Visual Studio 16 2019 + cmake_generator: Visual Studio 17 2022 cmake_platform: Win32 expat_char_type: char expat_dll: libexpatd.dll expat_platform: win32 - - runs-on: windows-2019 + - runs-on: windows-2022 cmake_build_type: Debug - cmake_generator: Visual Studio 16 2019 + cmake_generator: Visual Studio 17 2022 cmake_platform: x64 expat_char_type: wchar_t expat_dll: libexpatwd.dll @@ -65,14 +65,14 @@ shell: bash runs-on: "${{ matrix.runs-on }}" steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # v2 + - uses: microsoft/setup-msbuild@30375c66a4eea26614e0d39710365f22f8b0af57 # v3.0.0 - name: Install Inno Setup shell: pwsh run: |- - Invoke-WebRequest -Uri https://files.jrsoftware.org/is/6/innosetup-6.1.2.exe -OutFile D:\\is.exe + Invoke-WebRequest -Uri https://github.com/jrsoftware/issrc/releases/download/is-6_1_2/innosetup-6.1.2.exe -OutFile D:\\is.exe Start-Process -FilePath D:\\is.exe -ArgumentList "/VERYSILENT", "/SUPPRESSMSGBOXES", "/NORESTART" -Wait - name: 'Add Inno Setup compiler to ${PATH}' @@ -113,8 +113,8 @@ sed "${inno_sed_args[@]}" win32/expat.iss > win64/expat.iss ! grep 'win32\\bin' win64/expat.iss # i.e. assert success grep win32 win64/expat.iss # purely informational - - - name: Build installer + + - name: Build installer (and the Expat binaries that go into it) env: expat_platform: ${{ matrix.expat_platform }} run: |- @@ -130,7 +130,7 @@ env: expat_platform: ${{ matrix.expat_platform }} run: |- - export PATH="${PATH}:/c/msys64/usr/bin" # for zip + export PATH="${PATH}:/c/Program Files/7-Zip" set -x cd "expat/${expat_platform}" @@ -148,10 +148,10 @@ ls -lh app/Bin/ - ( cd app && zip -9 -r ../"${zip_name}" . ) + ( cd app && 7z a -tzip -mx=9 ../"${zip_name}" . ) - name: Offer binaries for download - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: expat_${{ matrix.expat_platform }}_${{ github.sha }} path: expat/${{ matrix.expat_platform }}/expat-win*bin-*.*.*.* diff -Nru expat-2.7.1/.github/workflows/windows-build.yml expat-2.8.2/.github/workflows/windows-build.yml --- expat-2.7.1/.github/workflows/windows-build.yml 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.github/workflows/windows-build.yml 2026-06-25 14:07:00.000000000 +0000 @@ -5,7 +5,8 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2025 Sebastian Pipping +# Copyright (c) 2025-2026 Sebastian Pipping +# Copyright (c) 2026 Tania Somanna # Licensed under the MIT license: # # Permission is hereby granted, free of charge, to any person obtaining @@ -46,26 +47,49 @@ fail-fast: false matrix: include: - - runs-on: windows-2019 + - runs-on: windows-2022 cmake_build_type: Debug - cmake_generator: Visual Studio 16 2019 + cmake_generator: Visual Studio 17 2022 cmake_platform: Win32 expat_char_type: char expat_dll: libexpatd.dll + expat_sln: expat.sln - runs-on: windows-2022 cmake_build_type: Debug cmake_generator: Visual Studio 17 2022 cmake_platform: x64 expat_char_type: wchar_t expat_dll: libexpatwd.dll + expat_sln: expat.sln + - runs-on: windows-11-arm + cmake_build_type: Debug + cmake_generator: Visual Studio 17 2022 + cmake_platform: ARM64 + expat_char_type: wchar_t + expat_dll: libexpatwd.dll + expat_sln: expat.sln + - runs-on: windows-2025-vs2026 + cmake_build_type: Debug + cmake_generator: Visual Studio 18 2026 + cmake_platform: Win32 + expat_char_type: char + expat_dll: libexpatd.dll + expat_sln: expat.slnx + - runs-on: windows-2025-vs2026 + cmake_build_type: Debug + cmake_generator: Visual Studio 18 2026 + cmake_platform: x64 + expat_char_type: wchar_t + expat_dll: libexpatwd.dll + expat_sln: expat.slnx defaults: run: shell: bash runs-on: "${{ matrix.runs-on }}" steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # v2 + - uses: microsoft/setup-msbuild@30375c66a4eea26614e0d39710365f22f8b0af57 # v3.0.0 - name: Configure env: @@ -91,6 +115,7 @@ - name: Build env: cmake_build_type: ${{ matrix.cmake_build_type }} + expat_sln: ${{ matrix.expat_sln }} run: |- msbuild_args=( -m @@ -98,7 +123,7 @@ ) set -x cd expat/build - MSBuild.exe "${msbuild_args[@]}" expat.sln + MSBuild.exe "${msbuild_args[@]}" "${expat_sln}" - name: Run tests env: @@ -114,3 +139,11 @@ cd expat/build cp -v "${cmake_build_type}/${expat_dll}" "tests/${cmake_build_type}/" ctest "${ctest_args[@]}" + + - name: Ensure that file libexpat.def.cmake is not missing any symbols + run: | + symbols_txt="${GITHUB_WORKSPACE}"/.github/workflows/data/exported-symbols-unversioned.txt + while read line ; do + symbol="$(tr -d '\r' <<<"${line}")" # drops trailing carriage return + ( set -x ; grep -q -F " ${symbol} @" expat/lib/libexpat.def.cmake ) # i.e. fail CI if symbol is missing + done < "${symbols_txt}" diff -Nru expat-2.7.1/.mailmap expat-2.8.2/.mailmap --- expat-2.7.1/.mailmap 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/.mailmap 2026-06-25 14:07:00.000000000 +0000 @@ -1,14 +1,19 @@ # This file is used by "git log" +Alfonso Gregory Ben Wagner +Berkay Eren Ürün +Christian Ng <10689391+Laserbear@users.noreply.github.com> Donghee Na Franek Korta Hanno Böck Hanno Böck <990588+hannob@users.noreply.github.com> +Haris Hussain James Clark José Gutiérrez de la Concha Joyce Brum Karl Waclawek Karl Waclawek +Kartik Kenchi Kishore Kunche Martin Ettl Owain Davies diff -Nru expat-2.7.1/CONTRIBUTING.md expat-2.8.2/CONTRIBUTING.md --- expat-2.7.1/CONTRIBUTING.md 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/CONTRIBUTING.md 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,102 @@ +# Hi! :wave: + +Thanks for your interest in contributing to the libexpat project or "Expat"! :+1: + +> [!TIP] +> TL;DR: **The best move before creating a pull request** +> that is big, complex, and/or controversial +> is to [open a new issue](https://github.com/libexpat/libexpat/issues) +> and discuss options moving forward :pray: :beers: + +Below, I'll document what Expat needs and does not need, at this time. + + +# What Expat needs (and does not need) in general + +Expat is: + +- in maintenance mode, +- unfunded, +- understaffed, +- complex, +- 25+ years old in some regards, +- meant to support parsing of XML files that exceed available RAM, +- written in the memory-unsafe language C99, +- is [used in many places](https://libexpat.github.io/doc/users/), + both in [hardware](https://libexpat.github.io/doc/users/#hardware) + and in [software](https://libexpat.github.io/doc/users/), +- implementing [XML 1.0 *Fourth* Edition](https://www.w3.org/TR/2006/REC-xml-20060816/), +- targeting environments that are relevant today + and/or up to 5 years into the past. + + +## What kinds of pull requests will be welcome + +Pull requests will be most welcome when they: + +- are small, +- are easy to review, +- have low risk, +- have had GitHub Actions CI run and all-green already + in your public fork repository, +- help both you and the libexpat project :tada: + +The need for additional tests or CI will depend on the specific pull request. + + +## What kinds of pull requests will *not* be welcome + +Pull requests will *not* be welcome when: + +- the changes are big, complex, high risk, controversial + and/or hard to review, +- the exact change has been said "no" to in the past, +- the changes break API or ABI backwards compatibility, +- it fixes an issue for an unsupported + (or no-longer supported) environment, and/or +- it introduces new features + (without prior discussion and agreement + in a dedicated issue). + +Specific examples of things known to *not* be welcome: + +- Mass-changing things. +- Fixing things for some stone age version of Visual Studio. +- Adding support to ignore or recover from malformed XML. +- Adding support for XML streaming. +- Making the C code compile with a C++ compiler. +- Adding support for XML 1.0r5 without prior discussion. +- Adding support for XML 1.1 in general. +- Adding additional build systems. + + +# What Expat needs on a technical level + +- All new C code and changes to existing C code must: + - pass all existing CI + (that includes + [ASan](https://clang.llvm.org/docs/AddressSanitizer.html), + [UBSan](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html), + [clang-format](https://clang.llvm.org/docs/ClangFormat.html), + [Cppcheck](https://cppcheck.sourceforge.io/), + [codespell](https://github.com/codespell-project/codespell), + ..), + - conform to C99, + - check returns from `malloc`/`realloc` for `NULL`, + - not use recursion (when it can be controlled by user input), + - have integer overflow in mind, + - have undefined behavior in mind, and + - have security in mind in general. +- A commit should be about one — and just one — of these things: + - fixing a bug, + - improving something, + - adding something new, + - doing a refactoring, or + - adjusting whitespace. + + +# Providing feedback + +Thanks for your interest and attention! :+1: + +I'm happy about [constructive feedback](mailto:sebastian@pipping.org) to this document — thank you! :pray: diff -Nru expat-2.7.1/COPYING expat-2.8.2/COPYING --- expat-2.7.1/COPYING 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/COPYING 2026-06-25 14:07:00.000000000 +0000 @@ -1,5 +1,5 @@ Copyright (c) 1998-2000 Thai Open Source Software Center Ltd and Clark Cooper -Copyright (c) 2001-2025 Expat maintainers +Copyright (c) 2001-2026 Expat maintainers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff -Nru expat-2.7.1/README.md expat-2.8.2/README.md --- expat-2.7.1/README.md 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/README.md 2026-06-25 14:07:00.000000000 +0000 @@ -1,5 +1,4 @@ [![Run Linux CI tasks](https://github.com/libexpat/libexpat/actions/workflows/linux.yml/badge.svg)](https://github.com/libexpat/libexpat/actions/workflows/linux.yml) -[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/libexpat/libexpat?svg=true)](https://ci.appveyor.com/project/libexpat/libexpat) [![Packaging status](https://repology.org/badge/tiny-repos/expat.svg)](https://repology.org/metapackage/expat/versions) [![Downloads SourceForge](https://img.shields.io/sourceforge/dt/expat?label=Downloads%20SourceForge)](https://sourceforge.net/projects/expat/files/) [![Downloads GitHub](https://img.shields.io/github/downloads/libexpat/libexpat/total?label=Downloads%20GitHub)](https://github.com/libexpat/libexpat/releases) @@ -12,7 +11,7 @@ > at the top of the `Changes` file. -# Expat, Release 2.7.1 +# Expat, Release 2.8.2 This is Expat, a C99 library for parsing [XML 1.0 Fourth Edition](https://www.w3.org/TR/2006/REC-xml-20060816/), started by @@ -27,7 +26,8 @@ - GNU GCC >=4.5 (for use from C) or GNU GCC >=4.8.1 (for use from C++) - LLVM Clang >=3.5 -- Microsoft Visual Studio >=16.0/2019 (rolling `${today} minus 5 years`) +- Microsoft Visual Studio >=17.0/2022 + (the oldest version supported by the [official GitHub Actions Windows images](https://github.com/actions/runner-images)) Windows users can use the [`expat-win32bin-*.*.*.{exe,zip}` download](https://github.com/libexpat/libexpat/releases), @@ -120,7 +120,7 @@ FetchContent_Declare( expat GIT_REPOSITORY https://github.com/libexpat/libexpat/ - GIT_TAG 000000000_GIT_COMMIT_SHA1_HERE_000000000 # i.e. Git tag R_0_Y_Z + GIT_TAG 000000000_GIT_COMMIT_SHA1_HERE_000000000 # i.e. Git tag R_X_Y_Z SOURCE_SUBDIR expat/ ) @@ -234,11 +234,6 @@ Note: This only applies to the Expat library itself, building UTF-16 versions of xmlwf and the tests is currently not supported. -When using Expat with a project using autoconf for configuration, you -can use the probing macro in `conftools/expat.m4` to determine how to -include Expat. See the comments at the top of that file for more -information. - A reference manual is available in the file `doc/reference.html` in this distribution. @@ -291,21 +286,12 @@ // Use /MT flag (static CRT) when compiling in MSVC EXPAT_MSVC_STATIC_CRT:BOOL=OFF -// Build fuzzers via OSS-Fuzz for the expat library -EXPAT_OSSFUZZ_BUILD:BOOL=OFF - // Build a shared expat library EXPAT_SHARED_LIBS:BOOL=ON +// Define to provide symbol versioning for dependency generation +EXPAT_SYMBOL_VERSIONING:BOOL=OFF + // Treat all compiler warnings as errors EXPAT_WARNINGS_AS_ERRORS:BOOL=OFF - -// Make use of getrandom function (ON|OFF|AUTO) [default=AUTO] -EXPAT_WITH_GETRANDOM:STRING=AUTO - -// Utilize libbsd (for arc4random_buf) -EXPAT_WITH_LIBBSD:BOOL=OFF - -// Make use of syscall SYS_getrandom (ON|OFF|AUTO) [default=AUTO] -EXPAT_WITH_SYS_GETRANDOM:STRING=AUTO ``` diff -Nru expat-2.7.1/debian/changelog expat-2.8.2/debian/changelog --- expat-2.7.1/debian/changelog 2025-07-14 08:05:27.000000000 +0000 +++ expat-2.8.2/debian/changelog 2026-07-24 21:04:21.000000000 +0000 @@ -1,3 +1,111 @@ +expat (2.8.2-1~deb13u1) trixie-security; urgency=high + + * Upload 2.8.2 to trixie-security. + + -- Aron Xu Sat, 25 Jul 2026 05:04:21 +0800 + +expat (2.8.2-1) unstable; urgency=high + + * New upstream release (closes: #1138862, #1140387, #1140388, #1140557): + - fixes CVE-2026-56131: protect XML_ResumeParser() from being called from + a handler, + - fixes CVE-2026-56132: fix out-of-bound scaffolding index store in + doProlog(), + - fixes CVE-2026-50219: disallow calls to some functions to guard Expat + bindings from memory corruption, + - fixes CVE-2026-56403: integer overflow in storeAtts(), + - fixes CVE-2026-56404: integer overflow in addBinding(), + - fixes CVE-2026-56405: integer overflow in getAttributeId(), + - fixes CVE-2026-56406: integer overflow in XML_ParseBuffer(), + - fixes CVE-2026-56407: integer overflow in textLen handling, + - fixes CVE-2026-56408: integer overflow in copyString(), + - fixes CVE-2026-56409: integer overflow in output path join in xmlwf, + - fixes CVE-2026-56410: integer overflow in resolveSystemId() in xmlwf, + - fixes CVE-2026-56411: Integer overflow in notation list allocation + in xmlwf, + - fixes CVE-2026-56412: guard XML_TOK_DATA_CHARS handler calls + in doCdataSection(). + + -- Laszlo Boszormenyi (GCS) Thu, 25 Jun 2026 19:44:46 +0200 + +expat (2.8.1-1) unstable; urgency=medium + + * New upstream release. + + -- Laszlo Boszormenyi (GCS) Sat, 23 May 2026 09:01:54 +0200 + +expat (2.8.0-2) unstable; urgency=high + + * Backport upstream fixes for self-testing: + - drop casts around malloc that C99 does not need, + - drop casts around XML_GetUserData that C99 does not need. + * Backport upstream fixes for CVE-2026-45186: attribute name collision + checks allowed denial of service attacks through moderately sized + crafted XML input (closes: #1136164). + + -- Laszlo Boszormenyi (GCS) Sun, 10 May 2026 16:51:27 +0200 + +expat (2.8.0-1) unstable; urgency=high + + * New upstream release: + - fixes CVE-2026-41080: improve protection against hash flooding + (closes: #1134732). + * Update libexpat1 symbols. + + -- Laszlo Boszormenyi (GCS) Sat, 25 Apr 2026 07:19:30 +0200 + +expat (2.7.5-1) unstable; urgency=high + + * New upstream release: + - fixes CVE-2026-32776: NULL function pointer dereference for empty + external parameter entities (closes: #1131117), + - fixes CVE-2026-32777: protect from XML_TOK_INSTANCE_START infinite + loop in entityValueProcessor() (closes: #1131118), + - fixes CVE-2026-32778: NULL dereference in setContext() on retry after + an earlier ouf-of-memory condition (closes: #1131119). + + -- Laszlo Boszormenyi (GCS) Tue, 17 Mar 2026 22:23:17 +0100 + +expat (2.7.4-1) unstable; urgency=high + + * New upstream release: + - fixes CVE-2026-25210: integer overflow check for tag buffer + reallocation (closes: #1126697), + - no longer ships expat.m4 file. + * Update watch file. + + -- Laszlo Boszormenyi (GCS) Sat, 31 Jan 2026 15:29:44 +0100 + +expat (2.7.3-2) unstable; urgency=high + + * Backport upstream fix for CVE-2026-24515: make + XML_ExternalEntityParserCreate() copy unknown encoding handler user data + (closes: 1126277). + * Remove now redundant Rules-Requires-Root value. + + -- Laszlo Boszormenyi (GCS) Fri, 23 Jan 2026 16:48:32 +0100 + +expat (2.7.3-1) unstable; urgency=high + + * New upstream release: + - fix alignment of internal allocations for some non-amd64 + architectures, fixes up on the fix to CVE-2025-59375, + - fix a class of false positives where input should have been rejected + with error XML_ERROR_ASYNC_ENTITY; regression from CVE-2024-8176. + + -- Laszlo Boszormenyi (GCS) Wed, 24 Sep 2025 23:31:38 +0200 + +expat (2.7.2-1) unstable; urgency=high + + * New upstream release: + - fixes CVE-2025-59375: disallow use of disproportional amounts of + dynamic memory from within an Expat parser (closes: #1115298). + * Update fix-expat-cmake patch. + * Update libexpat1 symbols. + * Update Standards-Version to 4.7.2 . + + -- Laszlo Boszormenyi (GCS) Tue, 16 Sep 2025 19:59:38 +0200 + expat (2.7.1-2) unstable; urgency=medium * Move libc6 dependency to pre-dependency on libexpat1 to prevent diff -Nru expat-2.7.1/debian/control expat-2.8.2/debian/control --- expat-2.7.1/debian/control 2025-07-14 08:05:27.000000000 +0000 +++ expat-2.8.2/debian/control 2026-01-23 15:48:32.000000000 +0000 @@ -3,9 +3,8 @@ Priority: optional Maintainer: Laszlo Boszormenyi (GCS) Build-Depends: debhelper-compat (= 13), docbook-to-man, - docbook2x , libbsd-dev [kfreebsd-any hurd-any] -Rules-Requires-Root: no -Standards-Version: 4.7.0 + docbook2x , libbsd-dev [hurd-any] +Standards-Version: 4.7.2 Homepage: https://libexpat.github.io/ Package: libexpat1-dev diff -Nru expat-2.7.1/debian/libexpat1-dev.install expat-2.8.2/debian/libexpat1-dev.install --- expat-2.7.1/debian/libexpat1-dev.install 2021-05-10 17:20:19.000000000 +0000 +++ expat-2.8.2/debian/libexpat1-dev.install 2026-01-31 14:29:44.000000000 +0000 @@ -4,4 +4,3 @@ usr/lib/*/cmake/ usr/lib/*/pkgconfig/expat.pc ../../expat/doc/* usr/share/doc/libexpat1-dev/expat.html/ -../../expat/conftools/expat.m4 usr/share/aclocal/ diff -Nru expat-2.7.1/debian/libexpat1.symbols expat-2.8.2/debian/libexpat1.symbols --- expat-2.7.1/debian/libexpat1.symbols 2024-02-06 21:00:26.000000000 +0000 +++ expat-2.8.2/debian/libexpat1.symbols 2026-04-25 05:19:30.000000000 +0000 @@ -28,6 +28,8 @@ XML_ParserFree@Base 2.0.1 XML_ParserReset@Base 2.0.1 XML_ResumeParser@Base 2.0.1 + XML_SetAllocTrackerActivationThreshold@Base 2.7.2 + XML_SetAllocTrackerMaximumAmplification@Base 2.7.2 XML_SetAttlistDeclHandler@Base 2.0.1 XML_SetBase@Base 2.0.1 XML_SetBillionLaughsAttackProtectionActivationThreshold@Base 2.4.1 @@ -48,6 +50,7 @@ XML_SetEntityDeclHandler@Base 2.0.1 XML_SetExternalEntityRefHandler@Base 2.0.1 XML_SetExternalEntityRefHandlerArg@Base 2.0.1 + XML_SetHashSalt16Bytes@Base 2.8.0 XML_SetHashSalt@Base 2.1~beta3 XML_SetNamespaceDeclHandler@Base 2.0.1 XML_SetNotStandaloneHandler@Base 2.0.1 @@ -98,6 +101,8 @@ XML_ParserFree@Base 2.0.1 XML_ParserReset@Base 2.0.1 XML_ResumeParser@Base 2.0.1 + XML_SetAllocTrackerActivationThreshold@Base 2.7.2 + XML_SetAllocTrackerMaximumAmplification@Base 2.7.2 XML_SetAttlistDeclHandler@Base 2.0.1 XML_SetBase@Base 2.0.1 XML_SetBillionLaughsAttackProtectionActivationThreshold@Base 2.4.1 @@ -118,6 +123,7 @@ XML_SetEntityDeclHandler@Base 2.0.1 XML_SetExternalEntityRefHandler@Base 2.0.1 XML_SetExternalEntityRefHandlerArg@Base 2.0.1 + XML_SetHashSalt16Bytes@Base 2.8.0 XML_SetHashSalt@Base 2.1~beta3 XML_SetNamespaceDeclHandler@Base 2.0.1 XML_SetNotStandaloneHandler@Base 2.0.1 diff -Nru expat-2.7.1/debian/patches/fix-expat-cmake.patch expat-2.8.2/debian/patches/fix-expat-cmake.patch --- expat-2.7.1/debian/patches/fix-expat-cmake.patch 2023-06-14 20:08:48.000000000 +0000 +++ expat-2.8.2/debian/patches/fix-expat-cmake.patch 2025-09-16 17:59:38.000000000 +0000 @@ -1,8 +1,8 @@ Description: fix path for INTERFACE_INCLUDE_DIRECTORIES Author: Matteo F. Vescovi Forwarded: not-needed ---- a/expat/cmake/autotools/expat.cmake -+++ b/expat/cmake/autotools/expat.cmake +--- a/expat/cmake/autotools/expat__linux.cmake.in ++++ b/expat/cmake/autotools/expat__linux.cmake.in @@ -51,6 +51,7 @@ get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) diff -Nru expat-2.7.1/debian/rules expat-2.8.2/debian/rules --- expat-2.7.1/debian/rules 2024-03-06 05:55:07.000000000 +0000 +++ expat-2.8.2/debian/rules 2026-01-31 14:29:44.000000000 +0000 @@ -123,7 +123,6 @@ ifneq (,$(filter stage1, $(DEB_BUILD_PROFILES))) chmod 644 $(CURDIR)/debian/libexpat1-dev/usr/share/doc/libexpat1-dev/examples/* endif - chmod 644 $(CURDIR)/debian/libexpat1-dev/usr/share/aclocal/* dh_makeshlibs -a -V $(if $(with_udeb),--add-udeb=$(UPACKAGE)) dh_installdeb -a dh_shlibdeps -a -l $(CURDIR)/debian/libexpat1/usr/lib/$(DEB_HOST_MULTIARCH) diff -Nru expat-2.7.1/debian/watch expat-2.8.2/debian/watch --- expat-2.7.1/debian/watch 2025-03-27 18:56:41.000000000 +0000 +++ expat-2.8.2/debian/watch 2026-01-31 14:29:44.000000000 +0000 @@ -1,8 +1,4 @@ -version=4 -opts=uversionmangle=s/^(SNAPSHOT|RELEASE)\.//;s/(\d+)[_-](\d+)[_-](\d+)/\$1.\$2.\$3/;s/(\d+)[_-](\d+)/\$1.\$2/;s/(\d)[_\.\-\+]?((rc|pre|dev|beta|alpha|b|a)[\-\.]?\d*)$/$1~$2/;s/(\d)[_\.\-\+]?RC[\-\.]?(\d*)$/$1~rc$2/,\ -dversionmangle=s/\+(debian|dfsg|ds|deb)(\.?\d+)?$//i \ -http://sf.net/expat/expat-[vV]?(\d\S*)@ARCHIVE_EXT@ +Version: 5 -opts=uversionmangle=s/_/\./g \ -https://github.com/libexpat/libexpat/tags \ -(?:|.*/)R_(\d[\d_]*) +Source: http://sf.net/expat/ +Matching-Pattern: expat-[vV]?(\d\S*)@ARCHIVE_EXT@ diff -Nru expat-2.7.1/expat/.gitignore expat-2.8.2/expat/.gitignore --- expat-2.7.1/expat/.gitignore 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/.gitignore 2026-06-25 14:07:00.000000000 +0000 @@ -1,5 +1,7 @@ /autom4te.cache/ /cmake-build-debug/ +/CPackConfig.cmake +/CPackSourceConfig.cmake CMakeFiles/ Testing/ aclocal.m4 diff -Nru expat-2.7.1/expat/CMake.README expat-2.8.2/expat/CMake.README --- expat-2.7.1/expat/CMake.README 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/CMake.README 2026-06-25 14:07:00.000000000 +0000 @@ -3,25 +3,25 @@ The cmake based buildsystem for expat works on Windows (cygwin, mingw, Visual Studio) and should work on all other platform cmake supports. -Assuming ~/expat-2.7.1 is the source directory of expat, add a subdirectory +Assuming ~/expat-2.8.2 is the source directory of expat, add a subdirectory build and change into that directory: -~/expat-2.7.1$ mkdir build && cd build -~/expat-2.7.1/build$ +~/expat-2.8.2$ mkdir build && cd build +~/expat-2.8.2/build$ From that directory, call cmake first, then call make, make test and make install in the usual way: -~/expat-2.7.1/build$ cmake .. +~/expat-2.8.2/build$ cmake .. -- The C compiler identification is GNU -- The CXX compiler identification is GNU .... -- Configuring done -- Generating done --- Build files have been written to: /home/patrick/expat-2.7.1/build +-- Build files have been written to: /home/patrick/expat-2.8.2/build If you want to specify the install location for your files, append -DCMAKE_INSTALL_PREFIX=/your/install/path to the cmake call. -~/expat-2.7.1/build$ make && make test && make install +~/expat-2.8.2/build$ make && make test && make install Scanning dependencies of target expat [ 5%] Building C object CMakeFiles/expat.dir/lib/xmlparse.c.o [ 11%] Building C object CMakeFiles/expat.dir/lib/xmlrole.c.o @@ -36,7 +36,7 @@ make sure that gcc can be called. On Windows, you also might want to specify a special Generator for CMake: for Visual Studio builds do: -cmake .. -G "Visual Studio 16 2019" && msbuild /m expat.sln +cmake .. -G "Visual Studio 17 2022" && msbuild /m expat.sln for mingw builds do: cmake .. -G "MinGW Makefiles" -DCMAKE_INSTALL_PREFIX=D:\expat-install && gmake && gmake install diff -Nru expat-2.7.1/expat/CMakeLists.txt expat-2.8.2/expat/CMakeLists.txt --- expat-2.7.1/expat/CMakeLists.txt 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/CMakeLists.txt 2026-06-25 14:07:00.000000000 +0000 @@ -7,7 +7,7 @@ # # Copyright (c) 2010 Patrick Spendrin # Copyright (c) 2012 Karl Waclawek -# Copyright (c) 2016-2025 Sebastian Pipping +# Copyright (c) 2016-2026 Sebastian Pipping # Copyright (c) 2016 Sergei Nikulov # Copyright (c) 2016 Björn Lindahl # Copyright (c) 2016 Tobias Taschner @@ -32,14 +32,18 @@ # Copyright (c) 2022 Johnny Jazeix # Copyright (c) 2022 Mark Brand # Copyright (c) 2022 David Faure +# Copyright (c) 2025 Alfonso Gregory +# Copyright (c) 2026 Rosen Penev +# Copyright (c) 2026 Gordon Messmer +# Copyright (c) 2026 Nick Begg # Unlike most of Expat, # this file is copyrighted under the BSD-license for buildsystem files of KDE. -cmake_minimum_required(VERSION 3.13.0) +cmake_minimum_required(VERSION 3.17.0) project(expat VERSION - 2.7.1 + 2.8.2 LANGUAGES C ) @@ -118,9 +122,8 @@ if(DEFINED ${var}) # NOTE: The idea is to (ideally) only add to the cache if - # there is no cache entry, yet. "if(DEFINED CACHE{var})" - # requires CMake >=3.14. - if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.14" AND NOT DEFINED "CACHE{${var}}") + # there is no cache entry, yet. + if(NOT DEFINED "CACHE{${var}}") set("${var}" "${${var}}" CACHE "${type}" "${desc}") endif() else() @@ -136,12 +139,11 @@ expat_shy_set(EXPAT_BUILD_FUZZERS OFF CACHE BOOL "Build fuzzers for the expat library") expat_shy_set(EXPAT_BUILD_PKGCONFIG ${_EXPAT_BUILD_PKGCONFIG_DEFAULT} CACHE BOOL "Build pkg-config file") expat_shy_set(EXPAT_OSSFUZZ_BUILD OFF CACHE BOOL "Build fuzzers via OSS-Fuzz for the expat library") -if(UNIX OR _EXPAT_HELP) - expat_shy_set(EXPAT_WITH_LIBBSD OFF CACHE BOOL "Utilize libbsd (for arc4random_buf)") -endif() +mark_as_advanced(EXPAT_OSSFUZZ_BUILD) expat_shy_set(EXPAT_ENABLE_INSTALL ON CACHE BOOL "Install expat files in cmake install target") expat_shy_set(EXPAT_CONTEXT_BYTES 1024 CACHE STRING "Define to specify how much context to retain around the current parse point, 0 to disable") mark_as_advanced(EXPAT_CONTEXT_BYTES) +expat_shy_set(EXPAT_SYMBOL_VERSIONING OFF CACHE BOOL "Define to provide symbol versioning for dependency generation") expat_shy_set(EXPAT_DTD ON CACHE BOOL "Define to make parameter entity parsing functionality available") mark_as_advanced(EXPAT_DTD) expat_shy_set(EXPAT_GE ON CACHE BOOL "Define to make general entity parsing functionality available") @@ -150,10 +152,22 @@ mark_as_advanced(EXPAT_NS) expat_shy_set(EXPAT_WARNINGS_AS_ERRORS OFF CACHE BOOL "Treat all compiler warnings as errors") if(UNIX OR _EXPAT_HELP) - expat_shy_set(EXPAT_DEV_URANDOM ON CACHE BOOL "Define to include code reading entropy from `/dev/urandom'.") + expat_shy_set(EXPAT_DEV_URANDOM OFF CACHE BOOL "Define to include code reading entropy from `/dev/urandom'.") + mark_as_advanced(EXPAT_DEV_URANDOM) +endif() +if(UNIX OR WASI OR _EXPAT_HELP) + expat_shy_set(EXPAT_WITH_ARC4RANDOM "AUTO" CACHE STRING "Make use of arc4random function (ON|OFF|AUTO) [default=AUTO]") + mark_as_advanced(EXPAT_WITH_ARC4RANDOM) + expat_shy_set(EXPAT_WITH_ARC4RANDOM_BUF "AUTO" CACHE STRING "Make use of arc4random_buf function (ON|OFF|AUTO) [default=AUTO]") + mark_as_advanced(EXPAT_WITH_ARC4RANDOM_BUF) + expat_shy_set(EXPAT_WITH_GETENTROPY "AUTO" CACHE STRING "Make use of getentropy function (ON|OFF|AUTO) [default=AUTO]") + mark_as_advanced(EXPAT_WITH_GETENTROPY) +endif() +if(UNIX OR _EXPAT_HELP) expat_shy_set(EXPAT_WITH_GETRANDOM "AUTO" CACHE STRING "Make use of getrandom function (ON|OFF|AUTO) [default=AUTO]") + mark_as_advanced(EXPAT_WITH_GETRANDOM) expat_shy_set(EXPAT_WITH_SYS_GETRANDOM "AUTO" CACHE STRING "Make use of syscall SYS_getrandom (ON|OFF|AUTO) [default=AUTO]") - mark_as_advanced(EXPAT_DEV_URANDOM) + mark_as_advanced(EXPAT_WITH_SYS_GETRANDOM) endif() expat_shy_set(EXPAT_CHAR_TYPE "char" CACHE STRING "Character type to use (char|ushort|wchar_t) [default=char]") expat_shy_set(EXPAT_ATTR_INFO OFF CACHE BOOL "Define to allow retrieving the byte offsets for attribute names and values") @@ -170,15 +184,11 @@ mark_as_advanced(_EXPAT_M32) endif() -if(EXPAT_BUILD_TESTS OR EXPAT_BUILD_FUZZERS) +if(EXPAT_BUILD_FUZZERS) # We have to call enable_language() before modifying any CMAKE_CXX_* variables enable_language(CXX) - if (EXPAT_BUILD_FUZZERS) - set(CMAKE_CXX_STANDARD 17) # for std::string_view for Abseil for libprotobuf-mutator - else() - set(CMAKE_CXX_STANDARD 11) - endif() + set(CMAKE_CXX_STANDARD 17) # for std::string_view for Abseil for libprotobuf-mutator set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) # i.e. -std=c++11 rather than default -std=gnu++11 endif() @@ -191,23 +201,14 @@ message(SEND_ERROR "Please either enable option EXPAT_GE (recommended) or disable EXPAT_DTD also.") endif() -if(EXPAT_WITH_LIBBSD) - find_library(LIB_BSD NAMES bsd) - if(NOT LIB_BSD) - message(SEND_ERROR "EXPAT_WITH_LIBBSD option is enabled, but libbsd was not found") - else() - set(HAVE_LIBBSD TRUE) - endif() -endif() - if(MSVC) # For the three types of MSVC version values, please see: # - https://cmake.org/cmake/help/latest/variable/MSVC_VERSION.html # - https://sourceforge.net/p/predef/wiki/Compilers/ # - https://en.wikipedia.org/wiki/Microsoft_Visual_Studio#History set(_EXPAT_MSVC_REQUIRED_INT 1800) # i.e. 12.0/2013/1800; see PR #426 - set(_EXPAT_MSVC_SUPPORTED_INT 1920) - set(_EXPAT_MSVC_SUPPORTED_DISPLAY "Visual Studio 16.0/2019/${_EXPAT_MSVC_SUPPORTED_INT}") + set(_EXPAT_MSVC_SUPPORTED_INT 1930) + set(_EXPAT_MSVC_SUPPORTED_DISPLAY "Visual Studio 17.0/2022/${_EXPAT_MSVC_SUPPORTED_INT}") if(MSVC_VERSION VERSION_LESS ${_EXPAT_MSVC_SUPPORTED_INT}) if(MSVC_VERSION VERSION_LESS ${_EXPAT_MSVC_REQUIRED_INT}) @@ -287,6 +288,9 @@ endmacro() if(NOT WIN32) + evaluate_detection_results(EXPAT_WITH_ARC4RANDOM HAVE_ARC4RANDOM "function arc4random" "Function arc4random") + evaluate_detection_results(EXPAT_WITH_ARC4RANDOM_BUF HAVE_ARC4RANDOM_BUF "function arc4random_buf" "Function arc4random_buf") + evaluate_detection_results(EXPAT_WITH_GETENTROPY HAVE_GETENTROPY "function getentropy" "Function getentropy") evaluate_detection_results(EXPAT_WITH_GETRANDOM HAVE_GETRANDOM "function getrandom" "Function getrandom") evaluate_detection_results(EXPAT_WITH_SYS_GETRANDOM HAVE_SYSCALL_GETRANDOM "syscall SYS_getrandom" "Syscall SYS_getrandom") endif() @@ -316,8 +320,11 @@ set(EXTRA_COMPILE_FLAGS) -if(FLAG_NO_STRICT_ALIASING) - set(EXTRA_COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -fno-strict-aliasing") +if(FLAG_WSTRICT_ALIASING) + set(EXTRA_COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -Wstrict-aliasing=3") +endif() +if(FLAG_WIMPLICIT_FALLTHROUGH) + set(EXTRA_COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -Wimplicit-fallthrough") endif() if(FLAG_VISIBILITY) if(EXPAT_SHARED_LIBS) @@ -344,22 +351,16 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_COMPILE_FLAGS}") if (MSVC) + cmake_policy(GET CMP0091 _policy_cmp0091_behavior) + if (NOT _policy_cmp0091_behavior STREQUAL NEW) + message(SEND_ERROR "Policy CMP0091 behavior is '${_policy_cmp0091_behavior}' rather than 'NEW', mis-compilation detected.") + endif() + + message(STATUS "-- Using static CRT ${EXPAT_MSVC_STATIC_CRT}") if (EXPAT_MSVC_STATIC_CRT) - message("-- Using static CRT ${EXPAT_MSVC_STATIC_CRT}") - foreach(flag_var - CMAKE_CXX_FLAGS_${_EXPAT_BUILD_TYPE_UPPER} - CMAKE_CXX_FLAGS_DEBUG - CMAKE_CXX_FLAGS_RELEASE - CMAKE_CXX_FLAGS_MINSIZEREL - CMAKE_CXX_FLAGS_RELWITHDEBINFO - CMAKE_C_FLAGS_${_EXPAT_BUILD_TYPE_UPPER} - CMAKE_C_FLAGS_DEBUG - CMAKE_C_FLAGS_RELEASE - CMAKE_C_FLAGS_MINSIZEREL - CMAKE_C_FLAGS_RELWITHDEBINFO - ) - string(REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") - endforeach() + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") # .. without suffix "DLL": static + else() + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") # i.e. CMake default behavior: shared endif() endif() @@ -393,12 +394,67 @@ lib/xmlrole.c lib/xmltok.c # NOTE: ISO C forbids an empty translation unit +# lib/xcsinc.c # lib/xmltok_impl.c # lib/xmltok_ns.c ) +if(HAVE_ARC4RANDOM) + set(_EXPAT_C_SOURCES + ${_EXPAT_C_SOURCES} + lib/random_arc4random.c + lib/random_arc4random.h + ) +endif() + +if(HAVE_ARC4RANDOM_BUF) + set(_EXPAT_C_SOURCES + ${_EXPAT_C_SOURCES} + lib/random_arc4random_buf.c + lib/random_arc4random_buf.h + ) +endif() + +if(EXPAT_DEV_URANDOM) + set(_EXPAT_C_SOURCES + ${_EXPAT_C_SOURCES} + lib/random_dev_urandom.c + lib/random_dev_urandom.h + ) +endif() + +if(HAVE_GETENTROPY) + set(_EXPAT_C_SOURCES + ${_EXPAT_C_SOURCES} + lib/random_getentropy.c + lib/random_getentropy.h + ) +endif() + +if(HAVE_GETRANDOM OR HAVE_SYSCALL_GETRANDOM) + set(_EXPAT_C_SOURCES + ${_EXPAT_C_SOURCES} + lib/random_getrandom.c + lib/random_getrandom.h + ) +endif() + +if(WIN32) + set(_EXPAT_C_SOURCES + ${_EXPAT_C_SOURCES} + lib/random_rand_s.c + lib/random_rand_s.h + ) +endif() + if(EXPAT_SHARED_LIBS) set(_SHARED SHARED) + if(EXPAT_DTD OR EXPAT_GE) + set(_EXPAT_DTD_OR_GE TRUE) + else() + set(_EXPAT_DTD_OR_GE FALSE) + endif() + if(WIN32) macro(_expat_def_file_toggle source_var target_var) if(${source_var}) @@ -408,12 +464,6 @@ endif() endmacro() - if(EXPAT_DTD OR EXPAT_GE) - set(_EXPAT_DTD_OR_GE TRUE) - else() - set(_EXPAT_DTD_OR_GE FALSE) - endif() - _expat_def_file_toggle(_EXPAT_DTD_OR_GE _EXPAT_COMMENT_DTD_OR_GE) _expat_def_file_toggle(EXPAT_ATTR_INFO _EXPAT_COMMENT_ATTR_INFO) @@ -424,6 +474,20 @@ string(REPLACE "." "," _EXPAT_DLL_VERSION ${PROJECT_VERSION}.0) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/win32/version.rc.cmake" "${CMAKE_CURRENT_BINARY_DIR}/win32/version.rc") set(_EXPAT_EXTRA_SOURCES ${_EXPAT_EXTRA_SOURCES} "${CMAKE_CURRENT_BINARY_DIR}/win32/version.rc") + else() + macro(_expat_map_file_toggle source_var target_var) + if(${source_var}) + set(${target_var} " ") # i.e. not commented out, a single space + else() + set(${target_var} "#") # i.e. commented out + endif() + endmacro() + + _expat_map_file_toggle(_EXPAT_DTD_OR_GE _EXPAT_COMMENT_DTD_OR_GE) + _expat_map_file_toggle(EXPAT_ATTR_INFO _EXPAT_COMMENT_ATTR_INFO) + + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/lib/libexpat.map.in" "${CMAKE_CURRENT_BINARY_DIR}/lib/libexpat.map") + set(_EXPAT_EXTRA_SOURCES ${_EXPAT_EXTRA_SOURCES} "${CMAKE_CURRENT_BINARY_DIR}/lib/libexpat.map") endif() else() set(_SHARED STATIC) @@ -434,9 +498,6 @@ if(_EXPAT_LIBM_FOUND) target_link_libraries(expat m) endif() -if(EXPAT_WITH_LIBBSD) - target_link_libraries(expat ${LIB_BSD}) -endif() # # Library filename postfix @@ -471,21 +532,20 @@ set_property(TARGET expat PROPERTY ${build_type_upper}_POSTFIX ${EXPAT_${build_type_upper}_POSTFIX}) endforeach() -set(LIBCURRENT 11) # sync +set(LIBCURRENT 13) # sync set(LIBREVISION 2) # with -set(LIBAGE 10) # configure.ac! +set(LIBAGE 12) # configure.ac! math(EXPR LIBCURRENT_MINUS_AGE "${LIBCURRENT} - ${LIBAGE}") if(NOT WIN32) set_property(TARGET expat PROPERTY VERSION ${LIBCURRENT_MINUS_AGE}.${LIBAGE}.${LIBREVISION}) set_property(TARGET expat PROPERTY SOVERSION ${LIBCURRENT_MINUS_AGE}) set_property(TARGET expat PROPERTY NO_SONAME ${NO_SONAME}) + if(EXPAT_SYMBOL_VERSIONING) + set_property(TARGET expat PROPERTY LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_BINARY_DIR}/lib/libexpat.map") + endif() if(APPLE) - if(NOT CMAKE_VERSION VERSION_GREATER_EQUAL 3.17) - message(FATAL_ERROR "Expat requires CMake >=3.17 on platform \"APPLE\".") - endif() - # NOTE: This intends to talk CMake into compatibility with GNU Libtool math(EXPR _EXPAT_MACHO_COMPATIBILITY_VERSION "${LIBCURRENT} + 1") set(_EXPAT_MACHO_CURRENT_VERSION "${_EXPAT_MACHO_COMPATIBILITY_VERSION}.${LIBREVISION}") @@ -643,8 +703,6 @@ endif() endfunction() - set(_EXPAT_TEST_TARGETS runtests runtests_cxx) - add_executable(runtests tests/acc_tests.c tests/alloc_tests.c @@ -663,38 +721,12 @@ ${_EXPAT_C_SOURCES} ) - add_executable(runtests_cxx - tests/acc_tests_cxx.cpp - tests/alloc_tests_cxx.cpp - tests/basic_tests_cxx.cpp - tests/chardata_cxx.cpp - tests/common_cxx.cpp - tests/dummy_cxx.cpp - tests/handlers_cxx.cpp - tests/memcheck_cxx.cpp - tests/minicheck_cxx.cpp - tests/misc_tests_cxx.cpp - tests/ns_tests_cxx.cpp - tests/nsalloc_tests_cxx.cpp - tests/runtests_cxx.cpp - tests/structdata_cxx.cpp - ${_EXPAT_C_SOURCES} - ) - - foreach(_target ${_EXPAT_TEST_TARGETS}) - target_compile_definitions(${_target} PRIVATE -DXML_TESTING) - - set_property(TARGET ${_target} PROPERTY RUNTIME_OUTPUT_DIRECTORY tests) - expat_add_test(${_target} $) - - if(_EXPAT_LIBM_FOUND) - target_link_libraries(${_target} m) - endif() - - if(EXPAT_WITH_LIBBSD) - target_link_libraries(${_target} ${LIB_BSD}) - endif() - endforeach() + target_compile_definitions(runtests PRIVATE -DXML_TESTING) + set_property(TARGET runtests PROPERTY RUNTIME_OUTPUT_DIRECTORY tests) + expat_add_test(runtests $) + if(_EXPAT_LIBM_FOUND) + target_link_libraries(runtests m) + endif() add_executable(benchmark tests/benchmark/benchmark.c) set_property(TARGET benchmark PROPERTY RUNTIME_OUTPUT_DIRECTORY tests/benchmark) @@ -829,7 +861,11 @@ # C/C++ config affecting multiple targets # if(WIN32) - set(_EXPAT_STATIC_TARGETS ${_EXPAT_TEST_TARGETS}) + set(_EXPAT_STATIC_TARGETS "") # intended as "empty list" + + if(EXPAT_BUILD_TESTS) + list(APPEND _EXPAT_STATIC_TARGETS runtests) + endif() if(NOT EXPAT_SHARED_LIBS) list(APPEND _EXPAT_STATIC_TARGETS expat) endif() @@ -976,6 +1012,8 @@ message(STATUS "===========================================================================") message(STATUS "") +message(STATUS "CMake version in use ......... ${CMAKE_VERSION}") +message(STATUS "") message(STATUS "Configuration") message(STATUS " Generator .................. ${CMAKE_GENERATOR}") if(_EXPAT_GENERATOR_IS_MULTI_CONFIG) @@ -1015,10 +1053,12 @@ if(WIN32) message(STATUS " rand_s ................... ON") else() + message(STATUS " arc4random ............... ${HAVE_ARC4RANDOM}") + message(STATUS " arc4random_buf ........... ${HAVE_ARC4RANDOM_BUF}") + message(STATUS " getentropy ............... ${HAVE_GETENTROPY}") message(STATUS " getrandom ................ ${HAVE_GETRANDOM}") message(STATUS " syscall SYS_getrandom .... ${HAVE_SYSCALL_GETRANDOM}") - message(STATUS " libbsd ................... ${EXPAT_WITH_LIBBSD}") - message(STATUS " /dev/random .............. ${EXPAT_DEV_URANDOM}") + message(STATUS " /dev/urandom ............. ${EXPAT_DEV_URANDOM}") endif() message(STATUS "") if(CMAKE_GENERATOR STREQUAL "Unix Makefiles") diff -Nru expat-2.7.1/expat/Changes expat-2.8.2/expat/Changes --- expat-2.7.1/expat/Changes 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/Changes 2026-06-25 14:07:00.000000000 +0000 @@ -10,33 +10,467 @@ !! ~~~~~~~~~~~~ !! !! The following topics need *additional skilled C developers* to progress !! !! in a timely manner or at all (loosely ordered by descending priority): !! +!! _______________________ !! +!! - teaming up on fixing the UNFIXED SECURITY ISSUES listed at: !! +!! """"""""""""""""""""""" !! +!! https://github.com/libexpat/libexpat/issues/1160 !! !! !! !! - teaming up on researching and fixing future security reports and !! !! ClusterFuzz findings with few-days-max response times in communication !! !! in order to (1) have a sound fix ready before the end of a 90 days !! !! grace period and (2) in a sustainable manner, !! -!! - helping CPython Expat bindings with supporting Expat's billion laughs !! -!! attack protection API (https://github.com/python/cpython/issues/90949): !! -!! - XML_SetBillionLaughsAttackProtectionActivationThreshold !! -!! - XML_SetBillionLaughsAttackProtectionMaximumAmplification !! -!! - helping Perl's XML::Parser Expat bindings with supporting Expat's !! -!! security API (https://github.com/cpan-authors/XML-Parser/issues/102): !! -!! - XML_SetBillionLaughsAttackProtectionActivationThreshold !! -!! - XML_SetBillionLaughsAttackProtectionMaximumAmplification !! -!! - XML_SetReparseDeferralEnabled !! +!! !! !! - implementing and auto-testing XML 1.0r5 support !! !! (needs discussion before pull requests), !! -!! - smart ideas on fixing the Autotools CMake files generation issue !! -!! without breaking CI (needs discussion before pull requests), !! -!! - pushing migration from `int` to `size_t` further !! -!! including edge-cases test coverage (needs discussion before anything). !! !! !! !! For details, please reach out via e-mail to sebastian@pipping.org so we !! !! can schedule a voice call on the topic, in English or German. !! !! !! -!! THANK YOU! Sebastian Pipping -- Berlin, 2024-03-09 !! +!! THANK YOU! Sebastian Pipping -- Berlin, 2026-03-17 !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +Release 2.8.2 Thu June 25 2026 + Security fixes: + #1246 CVE-2026-50219 -- Disallow calls to functions + `XML_GetBuffer`, `XML_Parse`, `XML_ParseBuffer`, + `XML_ParserFree`, `XML_ParserReset` to guard e.g. + Expat bindings from memory corruption; + this CPython issue is related: + https://github.com/python/cpython/issues/146169 + #1267 CVE-2026-56131 -- Protect XML_ResumeParser from being called + from a handler, plugging a hole in the fix + to CVE-2026-50219 + #1272 CVE-2026-56132 -- Fix out-of-bound scaffolding index store + in `doProlog` + #1229 #1232 CVE-2026-56403 -- Integer overflow in `storeAtts` + #1249 CVE-2026-56404 -- Integer overflow in `addBinding` + #1251 CVE-2026-56405 -- Integer overflow in `getAttributeId` + #1255 CVE-2026-56406 -- Integer overflow in `XML_ParseBuffer` + #1262 CVE-2026-56407 -- Integer overflow in `textLen` handling + #565 CVE-2026-56408 -- Integer overflow in `copyString` + (commit 16e2efd867ea8567ffa012210b52ef5918e20817) + #1259 CVE-2026-56409 -- xmlwf: Integer overflow in output path join + #1252 CVE-2026-56410 -- xmlwf: Integer overflow in + `resolveSystemId` + #1263 CVE-2026-56411 -- xmlwf: Integer overflow in notation list + allocation + #1278 CVE-2026-56412 -- Guard XML_TOK_DATA_CHARS handler calls in + `doCdataSection`, plugging a hole in the fix to + CVE-2026-50219 + + Bug fixes: + #1260 xmlwf: Escape names and base URI in meta output + #1266 xmlwf: Pick a safe quote for notation system and public IDs + + Other changes: + #1257 CMake|Autotools: Stop using /dev/urandom by default + #1244 #1254 CMake: Fix guard for Unix sources of entropy + #1183 #1270 CMake|Windows: Add missing export for symbol + `XML_SetHashSalt16Bytes` + #1236 CMake: Mark option EXPAT_OSSFUZZ_BUILD as advanced + #1283 Limit output indentation for EXPAT_ENTITY_DEBUG=1 and + allow unlimited indentation via EXPAT_ENTITY_DEBUG=2 + #565 Replace some loops by use of `memcpy`, `strlen`, `wcslen` + #1220 lib: Use a size_t for group sizes + #1221 lib: Fix too-conservative integer overflow check when + appending raw name + #1222 lib: Simplify attribute allocation/management logic + #1224 Update fallthrough annotations to satisfy Clang and GCC + #1226 lib: Remove unnecessary void * casts in random code + #1228 lib: Reduce scope of locals in storeAtts + #1230 lib: Count attributes with size_t variables + #1238 Minor get-buffer improvements + #1239 #1240 lib|tests: Include header expat_config.h first + #1241 lib: Shrink size of XML_GetBuffer + #1242 lib: Remove a legacy comment + #1243 lib: XML_ParserReset: Extract repeated linked-list move logic + #1243 lib: Unify entity free lists + #1247 lib: Fix use of '0' as boolean literal + #1248 lib: Make XML_Index overflow check more intuitive + #1256 lib: Use size_t for counting string/URI lengths + #1258 lib: XML_GetInputContext: Remove use of 0 for NULL + #1261 Comment typo fixes + #1275 Teach Memory Sanitizer semantics of randomization functions + #1276 #1281 Version info bumped from 13:1:12 (libexpat*.so.1.12.1) + to 13:2:12 (libexpat*.so.1.12.2); see https://verbump.de/ + for what these numbers do + + Infrastructure: + #1231 perl-integration.yml: Bump to XML::Parser 2.59 + #1237 emscripten.yml: Bump from Ubuntu 22.04 to 24.04 + #1183 #1271 windows-build.yml: Cover completeness of file + libexpat.def.cmake + #1274 linux.yml: Make llvm-symbolizer available in CI + + Special thanks to: + Alessandro Gario + Asher Darden + Christoph Reiter + Haris Hussain + Matthew Fernandez + Kartik Kenchi + Nick Begg + Sajin S + Yousef Shanableh + and + Anthropic + Astra Security + Trail of Bits + +Release 2.8.1 Sun May 10 2026 + Security fixes: + #1216 CVE-2026-45186 -- Fix quadratic runtime from attribute name + collision checks that allowed denial of service attacks + through moderately sized crafted XML input (CWE-407). + Please note that a layer of compression around XML can + significantly reduce the minimum attack payload size. + + Other changes: + #1209 #1213 Drop more casts related to `void *` that C99 does not need + #1213 xmlwf: Streamline use of `mmap` + #1214 #1217 Version info bumped from 13:0:12 (libexpat*.so.1.12.0) + to 13:1:12 (libexpat*.so.1.12.1); see https://verbump.de/ + for what these numbers do + + Infrastructure: + #1210 CI: Cover compilation with Visual Studio 18 2026 on Windows + #1215 CI: Cover compilation for ARM64 on Windows + #1212 CI: Bump WASI SDK from 32 to 33 + + Special thanks to: + Berkay Eren Ürün + Matthew Fernandez + Nick Wellnhofer + Tania Somanna + +Release 2.8.0 Fri April 24 2026 + Security fixes: + #47 #1183 CVE-2026-41080 -- The existing hash flooding protection + (based on SipHash) only used 4 to 8 bytes of entropy for + a salt, when 16 bytes of salt are supported by the + implementation of SipHash used by Expat. Now full 16 bytes + of entropy are used to improve protection against hash + flooding attacks. + Existing API function XML_SetHashSalt is now deprecated + because of its limitations, and its use should be + considered a vulnerability. Please either use the new API + function XML_SetHashSalt16Bytes (with known-high-quality + entropy input only!) instead, or leave the derivation of + a 16-bytes hash salt from high quality entropy to Expat's + internal machinery (by *not* calling either of the two + XML_SetHashSalt* functions). + + Bug fixes: + #1188 Avoid propagating /dev/urandom file descriptor to child + processes + #1193 Fix interpretation of `errno` after randomization calls + #1195 Avoid assuming uint8_t is a character type + + Other changes: + #1180 #1199 Add support for `getentropy(3)` as a source of entropy; + this helps with protecting against hash flooding attacks, + in particular with WASI SDK (where none of the other + entropy sources supported by libexpat are available). + #1200 Autotools: Add `--without-arc4random` and + `--without-arc4random-buf` + #1200 Autotools: Make `./configure` output report on available + high quality entropy sources + #1173 Autotools|macOS: Sync CMake templates with CMake 4.3.0 + #1201 Autotools|CMake: Improve checks for `arc4random` and + `arc4random_buf` e.g. with modern glibc + #1201 CMake: Report on availability of functions `arc4random` and + `arc4random_buf` + #1201 CMake: Mark entropy related build switches as advanced + #1189 .. + #1203 #1204 Extract new files from entropy extraction code + #1194 Stop duplicating C tests 1:1 as C++ ("runtests_cxx") + #1202 Fix a comment typo in expat_external.h + #1187 Fix grammar in compile error message + #1192 examples: Build warning-free with -Wwrite-strings + #1171 tests: Address harmless warning from Coverity + #1170 #1176 Sync file headers + #1190 #1206 Version info bumped from 12:3:11 (libexpat*.so.1.11.3) + to 13:0:12 (libexpat*.so.1.12.0); see https://verbump.de/ + for what these numbers do + + Infrastructure: + #1166 #1167 .. + #1172 #1175 .. + #1178 #1179 .. + #1185 #1205 CI: Make Perl XML::Parser integration tests run against + both version 2.47 and the latest release 2.58 + #1169 CI: Adapt to breaking changes regarding Inno Setup + #1173 CI: Adapt to breaking changes regarding CMake + #1174 CI: Include public corpus of fuzzer `xml_lpm_fuzzer` with + regression testing + #1181 #1182 CI: Bump WASI SDK from 30 to 32 + + Special thanks to: + Jérôme Duval + Matthew Fernandez + +Release 2.7.5 Tue March 17 2026 + Security fixes: + #1158 CVE-2026-32776 -- Fix NULL function pointer dereference for + empty external parameter entities; it takes use of both + functions XML_ExternalEntityParserCreate and + XML_SetParamEntityParsing for an application to be + vulnerable. + #1161 #1162 CVE-2026-32777 -- Protect from XML_TOK_INSTANCE_START + infinite loop in function entityValueProcessor; it takes + use of both functions XML_ExternalEntityParserCreate and + XML_SetParamEntityParsing for an application to be + vulnerable. + #1163 CVE-2026-32778 -- Fix NULL dereference in function setContext + on retry after an earlier ouf-of-memory condition; it takes + use of function XML_ParserCreateNS or XML_ParserCreate_MM + for an application to be vulnerable. + #1160 Three more unfixed vulnerabilities left + + Other changes: + #1146 #1147 Autotools: Fix condition for symbol versioning check, in + particular when compiling with slibtool (not libtool) + #1156 Address Cppcheck >=2.20.0 warnings + #1153 tests: Make test_buffer_can_grow_to_max work for MinGW on + Ubuntu 24.04 + #1157 #1159 Version info bumped from 12:2:11 (libexpat*.so.1.11.2) + to 12:3:11 (libexpat*.so.1.11.3); see https://verbump.de/ + for what these numbers do + + Infrastructure: + #1148 CI: Fix FreeBSD and Solaris CI + #1149 CI: Bump to WASI SDK 30 + #1153 CI: Adapt to breaking changes with Ubuntu 22.04 + #1156 CI: Adapt to breaking changes in Cppcheck + + Special thanks to: + Berkay Eren Ürün + Christian Ng + Fabio Scaccabarozzi + Francesco Bertolaccini + Mark Brand + Rhodri James + and + AddressSanitizer + Buttercup + OSS-Fuzz / ClusterFuzz + Trail of Bits + +Release 2.7.4 Sat January 31 2026 + Security fixes: + #1131 CVE-2026-24515 -- Function XML_ExternalEntityParserCreate + failed to copy the encoding handler data passed to + XML_SetUnknownEncodingHandler from the parent to the new + subparser. This can cause a NULL dereference (CWE-476) from + external entities that declare use of an unknown encoding. + The expected impact is denial of service. It takes use of + both functions XML_ExternalEntityParserCreate and + XML_SetUnknownEncodingHandler for an application to be + vulnerable. + #1075 CVE-2026-25210 -- Add missing check for integer overflow + related to buffer size determination in function doContent + + Bug fixes: + #1073 lib: Fix missing undoing of group size expansion in doProlog + failure cases + #1107 xmlwf: Fix a memory leak + #1104 WASI: Fix format specifiers for 32bit WASI SDK + + Other changes: + #1105 lib: Fix strict aliasing + #1106 lib: Leverage feature "flexible array member" of C99 + #1051 lib: Swap (size_t)(-1) for C99 equivalent SIZE_MAX + #1109 lib|xmlwf: Return NULL instead of 0 for pointers + #1068 lib|Windows: Clean up use of macro _MSC_EXTENSIONS with MSVC + #1112 lib: Remove unused import + #1110 xmlwf: Warn about XXE in --help output (and man page) + #1102 #1103 WASI: Stop using getpid + #1113 #1130 Autotools: Drop file expat.m4 that provided obsolete Autoconf + macro AM_WITH_EXPAT + #1123 Autotools: Limit -Wno-pedantic-ms-format to MinGW + #1129 #1134 .. + #1087 Autotools|macOS: Sync CMake templates with CMake 4.0 + #1139 #1140 Autotools|CMake: Introduce off-by-default symbol versioning + The related build system flags are: + - For Autotools, configure with --enable-symbol-versioning + - For CMake, configure with -DEXPAT_SYMBOL_VERSIONING=ON + Please double-check for consequences before activating + this inside distro packaging. Bug reports welcome! + #1117 Autotools|CMake: Remove libbsd support + #1105 Autotools|CMake: Stop using -fno-strict-aliasing, and use + -Wstrict-aliasing=3 instead + #1124 Autotools|CMake: Prefer command gsed (GNU sed) over sed + (e.g. for Solaris) inside fix-xmltest-log.sh + #1067 CMake: Detect and warn about unusable check_c_compiler_flag + #1137 CMake: Drop support for CMake <3.17 + #1138 CMake|Windows: Fix libexpat.def.cmake version comments + + #1086 #1110 docs: Add warning about external reference handlers and XXE + #1066 docs: Be explicit that parent parsers need to outlive + subparsers + #1089 .. + #1090 #1091 .. + #1092 #1093 .. + #1094 #1098 .. + #1115 #1116 docs: Misc non-content improvements to doc/reference.html + #1132 #1133 Version info bumped from 12:1:11 (libexpat*.so.1.11.1) + to 12:2:11 (libexpat*.so.1.11.2); see https://verbump.de/ + for what these numbers do + + Infrastructure: + #1119 #1121 Document guidelines for contributing to Expat + #1120 Introduce a pull request template + #1074 CI: Stop using about-to-be-removed image "macos-13" + #1083 #1088 CI: Mitigate random Wine crashes + #1104 CI: Cover compilation with WASI SDK + #1116 CI: Enforce clean doc XML formatting + #1124 .. + #1135 #1136 CI: Cover Solaris 11.4 + #1125 CI: Extend CI coverage of FreeBSD + #1139 #1140 CI: Cover symbol versioning + #1114 xmlwf: Reformat helpgen code (using Black 25.12.0) + #1071 .gitignore: Add files CPackConfig.cmake and + CPackSourceConfig.cmake + + Special thanks to: + Alfonso Gregory + Bénédikt Tran + Gordon Messmer + Hanno Böck + Jakub Kulík + Matthew Fernandez + Neil Pang + Rosen Penev + and + Artiphishell Inc. + +Release 2.7.3 Wed September 24 2025 + Security fixes: + #1046 #1048 Fix alignment of internal allocations for some non-amd64 + architectures (e.g. sparc32); fixes up on the fix to + CVE-2025-59375 from #1034 (of Expat 2.7.2 and related + backports) + #1059 Fix a class of false positives where input should have been + rejected with error XML_ERROR_ASYNC_ENTITY; regression from + CVE-2024-8176 fix pull request #973 (of Expat 2.7.0 and + related backports). Please check the added unit tests for + example documents. + + Other changes: + #1043 Prove and regression-proof absence of integer overflow + from function expat_realloc + #1062 Remove "harmless" cast that truncated a size_t to unsigned + #1049 Autotools: Remove "ln -s" discovery + #1054 docs: Be consistent with use of floating point around + XML_SetAllocTrackerMaximumAmplification + #1056 docs: Make it explicit that XML_GetCurrentColumnNumber + starts at 0 + #1057 docs: Better integrate the effect of the activation + thresholds + #1058 docs: Fix an in-comment typo in expat.h + #1045 docs: Fix a typo in README.md + #1041 docs: Improve change log of release 2.7.2 + #1053 xmlwf: Resolve use of functions XML_GetErrorLineNumber + and XML_GetErrorColumnNumber + #1032 Windows: Normalize .bat files to CRLF line endings + #1060 #1061 Version info bumped from 12:0:11 (libexpat*.so.1.11.0) + to 12:1:11 (libexpat*.so.1.11.1); see https://verbump.de/ + for what these numbers do + + Infrastructure: + #1047 #1050 CI: Cleanup UndefinedBehaviorSanitizer fatality + #1044 CI|Linux: Stop aborting at first job failure + #1052 CI|FreeBSD: Upgrade to FreeBSD 15.0 + #1039 CI|FreeBSD: Do not install CMake meta-package + + Special thanks to: + Bénédikt Tran + Berkay Eren Ürün + Daniel Engberg + Hanno Böck + Matthew Fernandez + Rolf Eike Beer + Sam James + Tim Bray + and + Clang/GCC UndefinedBehaviorSanitizer + OSS-Fuzz / ClusterFuzz + Z3 Theorem Prover + +Release 2.7.2 Tue September 16 2025 + Security fixes: + #1018 #1034 CVE-2025-59375 -- Disallow use of disproportional amounts of + dynamic memory from within an Expat parser (e.g. previously + a ~250 KiB sized document was able to cause allocation of + ~800 MiB from the heap, i.e. an "amplification" of factor + ~3,300); once a threshold (that defaults to 64 MiB) is + reached, a maximum amplification factor (that defaults to + 100.0) is enforced, and violating documents are rejected + with an out-of-memory error. + There are two new API functions to fine-tune this new + behavior: + - XML_SetAllocTrackerActivationThreshold + - XML_SetAllocTrackerMaximumAmplification . + If you ever need to increase these defaults for non-attack + XML payload, please file a bug report with libexpat. + There is also a new environment variable + EXPAT_MALLOC_DEBUG=(0|1|2) to control the verbosity + of allocations debugging at runtime, disabled by default. + 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. + Distributors intending to backport (or cherry-pick) the + fix need to copy 99% of the related pull request, not just + the "lib: Implement tracking of dynamic memory allocations" + commit, to not end up with a state that literally does both + too much and too little at the same time. Appending ".diff" + to the pull request URL could be of help. + + Other changes: + #1008 #1017 Autotools|macOS: Sync CMake templates with CMake 3.31 + #1007 CMake: Drop support for CMake <3.15 + #1004 CMake: Fix off_t detection for -Werror + #1007 CMake|Windows: Fix -DEXPAT_MSVC_STATIC_CRT=ON + #1013 Windows: Drop support for Visual Studio <=16.0/2019 + #1026 xmlwf: Mention supported environment variables in + --help output + #1024 xmlwf: Fix (internal) help generator + #1034 docs: Promote the contract to call function + XML_FreeContentModel when registering a custom + element declaration handler (via a call to function + XML_SetElementDeclHandler) + #1027 docs: Add missing

..

wrap + #994 docs: Drop AppVeyor badge + #1000 tests: Fix portable_strndup + #1036 Drop casts around malloc/free/realloc that C99 does not need + #1010 Replace empty for loops with while loops + #1011 Add const with internal XmlInitUnknownEncodingNS + #14 #1037 Drop an OpenVMS support leftover + #999 #1001 Address more clang-tidy warnings + #1030 #1038 Version info bumped from 11:2:10 (libexpat*.so.1.10.2) + to 12:0:11 (libexpat*.so.1.11.0); see https://verbump.de/ + for what these numbers do + + Infrastructure: + #1003 CI: Cover compilation on FreeBSD + #1009 #1035 CI: Upgrade Clang from 19 to 21 + #1031 CI: Make calling Cppcheck without --suppress=objectIndex + and --suppress=unknownMacro possible + #1013 CI|Windows: Get off of deprecated image "windows-2019" + #1008 #1017 .. + #1023 #1025 CI: Adapt to breaking changes in GitHub Actions + + Special thanks to: + Alexander Bluhm + Neil Pang + Theo Buehler + and + GNU Time + OSS-Fuzz / ClusterFuzz + Perl XML::Parser + Release 2.7.1 Thu March 27 2025 Bug fixes: #980 #989 Restore event pointer behavior from Expat 2.6.4 @@ -54,7 +488,7 @@ #983 #984 Fix printf format specifiers for 32bit Emscripten #992 docs: Promote OpenSSF Best Practices self-certification #978 tests/benchmark: Resolve mistaken double close - #986 Address compiler warnings + #986 Address Frama-C warnings #990 #993 Version info bumped from 11:1:10 (libexpat*.so.1.10.1) to 11:2:10 (libexpat*.so.1.10.2); see https://verbump.de/ for what these numbers do @@ -1474,7 +1908,7 @@ - Bug Fixes: #1742315: Harmful XML_ParserCreateNS suggestion. #1785430: Expat build fails on linux-amd64 with gcc version>=4.1 -O3. - #1983953, 2517952, 2517962, 2649838: + #1983953, 2517952, 2517962, 2649838: Build modifications using autoreconf instead of buildconf.sh. #2815947, #2884086: OBJEXT and EXEEXT support while building. #2517938: xmlwf should return non-zero exit status if not well-formed. @@ -1500,7 +1934,7 @@ See bug #2990652 and patch #3312568. Added run-benchmark target to Makefile.in - relies on testdata module present in the same relative location as in the repository. - + Release 2.0.1 Tue June 5 2007 - Fixed bugs #1515266, #1515600: The character data handler's calling of XML_StopParser() was not handled properly; if the parser was diff -Nru expat-2.7.1/expat/ConfigureChecks.cmake expat-2.8.2/expat/ConfigureChecks.cmake --- expat-2.7.1/expat/ConfigureChecks.cmake 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/ConfigureChecks.cmake 2026-06-25 14:07:00.000000000 +0000 @@ -22,16 +22,29 @@ check_symbol_exists("mmap" "sys/mman.h" HAVE_MMAP) check_symbol_exists("getrandom" "sys/random.h" HAVE_GETRANDOM) -if(EXPAT_WITH_LIBBSD) - set(CMAKE_REQUIRED_LIBRARIES "${LIB_BSD}") - set(_bsd "bsd/") -else() - set(_bsd "") -endif() -check_symbol_exists("arc4random_buf" "${_bsd}stdlib.h" HAVE_ARC4RANDOM_BUF) -if(NOT HAVE_ARC4RANDOM_BUF) - check_symbol_exists("arc4random" "${_bsd}stdlib.h" HAVE_ARC4RANDOM) -endif() +check_c_source_compiles(" + #if ! defined(_DEFAULT_SOURCE) + # define _DEFAULT_SOURCE 1 /* for glibc */ + #endif + #include + int main(void) { + char dummy[123]; + arc4random_buf(dummy, 0U); + return 0; + }" + HAVE_ARC4RANDOM_BUF) + +check_c_source_compiles(" + #if ! defined(_DEFAULT_SOURCE) + # define _DEFAULT_SOURCE 1 /* for glibc */ + #endif + #include + int main(void) { + arc4random(); + return 0; + }" + HAVE_ARC4RANDOM) + set(CMAKE_REQUIRED_LIBRARIES) #/* Define to 1 if you have the ANSI C header files. */ @@ -50,6 +63,7 @@ #include int main(void) { const off_t offset = -123; + (void)offset; return 0; }" HAVE_OFF_T) @@ -60,6 +74,27 @@ endif() check_c_source_compiles(" + // NOTE: Please keep this block in sync with its two siblings in files + // `configure.ac` and `lib/random_getentropy.c`! + #if defined(__APPLE__) + # include + #else + # if defined(__GLIBC__) && ! defined(_DEFAULT_SOURCE) + # define _DEFAULT_SOURCE 1 + # endif + # if ! defined(_GNU_SOURCE) + # define _GNU_SOURCE 1 /* for musl */ + # endif + # include + #endif // ! defined(__APPLE__) + + int main(void) { + return getentropy(NULL, 0U); + } + " + HAVE_GETENTROPY) + +check_c_source_compiles(" #define _GNU_SOURCE #include /* for NULL */ #include /* for syscall */ @@ -70,7 +105,26 @@ }" HAVE_SYSCALL_GETRANDOM) -check_c_compiler_flag("-fno-strict-aliasing" FLAG_NO_STRICT_ALIASING) -check_c_compiler_flag("-fvisibility=hidden" FLAG_VISIBILITY) +# If the compiler produces non-English messages and does not +# listen to CMake's request for English through environment variables +# LC_ALL/LC_MESSAGES/LANG, then command `check_c_compiler_flag` can produce +# false positives as seen with e.g. `cl` of MSVC 19.44.35217 configured +# to report errors in Italian language. +check_c_compiler_flag("-no-such-thing" _FLAG_DETECTION_UNUSABLE) + +if (_FLAG_DETECTION_UNUSABLE) + message(WARNING + "Your compiler breaks CMake's command `check_c_compiler_flag`." + " HINT: Is it configured to report errors in a language other" + " than English?" + ) + set(FLAG_WSTRICT_ALIASING FALSE) + set(FLAG_WIMPLICIT_FALLTHROUGH FALSE) + set(FLAG_VISIBILITY FALSE) +else() + check_c_compiler_flag("-Wstrict-aliasing=3" FLAG_WSTRICT_ALIASING) + check_c_compiler_flag("-Wimplicit-fallthrough" FLAG_WIMPLICIT_FALLTHROUGH) + check_c_compiler_flag("-fvisibility=hidden" FLAG_VISIBILITY) +endif() check_library_exists(m cos "" _EXPAT_LIBM_FOUND) diff -Nru expat-2.7.1/expat/Makefile.am expat-2.8.2/expat/Makefile.am --- expat-2.7.1/expat/Makefile.am 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/Makefile.am 2026-06-25 14:07:00.000000000 +0000 @@ -6,7 +6,7 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2017-2025 Sebastian Pipping +# Copyright (c) 2017-2026 Sebastian Pipping # Copyright (c) 2018 KangLin # Copyright (c) 2022 Johnny Jazeix # Copyright (c) 2023 Sony Corporation / Snild Dolkow @@ -58,10 +58,8 @@ pkgconfigdir = $(libdir)/pkgconfig -dist_cmake_DATA = \ - cmake/autotools/expat.cmake - nodist_cmake_DATA = \ + cmake/autotools/expat.cmake \ cmake/autotools/expat-config-version.cmake \ cmake/autotools/expat-noconfig.cmake \ cmake/expat-config.cmake @@ -70,6 +68,9 @@ _EXTRA_DIST_CMAKE = \ + cmake/autotools/expat__linux.cmake.in \ + cmake/autotools/expat__macos.cmake.in \ + cmake/autotools/expat__windows.cmake.in \ cmake/autotools/expat-noconfig__linux.cmake.in \ cmake/autotools/expat-noconfig__macos.cmake.in \ cmake/autotools/expat-noconfig__windows.cmake.in \ @@ -93,7 +94,6 @@ $(_EXTRA_DIST_CMAKE) \ $(_EXTRA_DIST_WINDOWS) \ \ - conftools/expat.m4 \ conftools/get-version.sh \ \ fuzz/xml_lpm_fuzzer.cpp \ diff -Nru expat-2.7.1/expat/README.md expat-2.8.2/expat/README.md --- expat-2.7.1/expat/README.md 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/README.md 2026-06-25 14:07:00.000000000 +0000 @@ -1,5 +1,4 @@ [![Run Linux CI tasks](https://github.com/libexpat/libexpat/actions/workflows/linux.yml/badge.svg)](https://github.com/libexpat/libexpat/actions/workflows/linux.yml) -[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/libexpat/libexpat?svg=true)](https://ci.appveyor.com/project/libexpat/libexpat) [![Packaging status](https://repology.org/badge/tiny-repos/expat.svg)](https://repology.org/metapackage/expat/versions) [![Downloads SourceForge](https://img.shields.io/sourceforge/dt/expat?label=Downloads%20SourceForge)](https://sourceforge.net/projects/expat/files/) [![Downloads GitHub](https://img.shields.io/github/downloads/libexpat/libexpat/total?label=Downloads%20GitHub)](https://github.com/libexpat/libexpat/releases) @@ -12,7 +11,7 @@ > at the top of the `Changes` file. -# Expat, Release 2.7.1 +# Expat, Release 2.8.2 This is Expat, a C99 library for parsing [XML 1.0 Fourth Edition](https://www.w3.org/TR/2006/REC-xml-20060816/), started by @@ -27,7 +26,8 @@ - GNU GCC >=4.5 (for use from C) or GNU GCC >=4.8.1 (for use from C++) - LLVM Clang >=3.5 -- Microsoft Visual Studio >=16.0/2019 (rolling `${today} minus 5 years`) +- Microsoft Visual Studio >=17.0/2022 + (the oldest version supported by the [official GitHub Actions Windows images](https://github.com/actions/runner-images)) Windows users can use the [`expat-win32bin-*.*.*.{exe,zip}` download](https://github.com/libexpat/libexpat/releases), @@ -120,7 +120,7 @@ FetchContent_Declare( expat GIT_REPOSITORY https://github.com/libexpat/libexpat/ - GIT_TAG 000000000_GIT_COMMIT_SHA1_HERE_000000000 # i.e. Git tag R_0_Y_Z + GIT_TAG 000000000_GIT_COMMIT_SHA1_HERE_000000000 # i.e. Git tag R_X_Y_Z SOURCE_SUBDIR expat/ ) @@ -234,11 +234,6 @@ Note: This only applies to the Expat library itself, building UTF-16 versions of xmlwf and the tests is currently not supported. -When using Expat with a project using autoconf for configuration, you -can use the probing macro in `conftools/expat.m4` to determine how to -include Expat. See the comments at the top of that file for more -information. - A reference manual is available in the file `doc/reference.html` in this distribution. @@ -291,21 +286,12 @@ // Use /MT flag (static CRT) when compiling in MSVC EXPAT_MSVC_STATIC_CRT:BOOL=OFF -// Build fuzzers via OSS-Fuzz for the expat library -EXPAT_OSSFUZZ_BUILD:BOOL=OFF - // Build a shared expat library EXPAT_SHARED_LIBS:BOOL=ON +// Define to provide symbol versioning for dependency generation +EXPAT_SYMBOL_VERSIONING:BOOL=OFF + // Treat all compiler warnings as errors EXPAT_WARNINGS_AS_ERRORS:BOOL=OFF - -// Make use of getrandom function (ON|OFF|AUTO) [default=AUTO] -EXPAT_WITH_GETRANDOM:STRING=AUTO - -// Utilize libbsd (for arc4random_buf) -EXPAT_WITH_LIBBSD:BOOL=OFF - -// Make use of syscall SYS_getrandom (ON|OFF|AUTO) [default=AUTO] -EXPAT_WITH_SYS_GETRANDOM:STRING=AUTO ``` diff -Nru expat-2.7.1/expat/apply-clang-tidy.sh expat-2.8.2/expat/apply-clang-tidy.sh --- expat-2.7.1/expat/apply-clang-tidy.sh 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/apply-clang-tidy.sh 2026-06-25 14:07:00.000000000 +0000 @@ -6,7 +6,7 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2024-2025 Sebastian Pipping +# Copyright (c) 2024-2026 Sebastian Pipping # Licensed under the MIT license: # # Permission is hereby granted, free of charge, to any person obtaining @@ -33,6 +33,9 @@ cd "$(dirname "$(type -P "$0")")" checks_to_enable=( + bugprone-narrowing-conversions + bugprone-suspicious-string-compare + misc-no-recursion readability-avoid-const-params-in-decls readability-named-parameter ) @@ -62,6 +65,7 @@ -DENCODING_FOR_FUZZING=UTF-8 -DXML_ATTR_INFO + -DXML_CLANG_TIDY -DXML_DTD -DXML_GE -DXML_NS @@ -75,6 +79,7 @@ # https://github.com/libexpat/libexpat/issues/119 files=( $( git ls-files -- \*.c | grep -v \ + -e '^lib/xcsinc\.c$' \ -e '^xmlwf/ct\.c$' \ -e '^xmlwf/xmlmime\.c$' \ -e '^xmlwf/win32filemap\.c$' \ diff -Nru expat-2.7.1/expat/cmake/autotools/expat.cmake expat-2.8.2/expat/cmake/autotools/expat.cmake --- expat-2.7.1/expat/cmake/autotools/expat.cmake 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/cmake/autotools/expat.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,107 +0,0 @@ -# Generated by CMake - -if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8) - message(FATAL_ERROR "CMake >= 2.8.12 required") -endif() -if(CMAKE_VERSION VERSION_LESS "2.8.12") - message(FATAL_ERROR "CMake >= 2.8.12 required") -endif() -cmake_policy(PUSH) -cmake_policy(VERSION 2.8.12...3.29) -#---------------------------------------------------------------- -# Generated CMake target import file. -#---------------------------------------------------------------- - -# Commands may need to know the format version. -set(CMAKE_IMPORT_FILE_VERSION 1) - -# Protect against multiple inclusion, which would fail when already imported targets are added once more. -set(_cmake_targets_defined "") -set(_cmake_targets_not_defined "") -set(_cmake_expected_targets "") -foreach(_cmake_expected_target IN ITEMS expat::expat) - list(APPEND _cmake_expected_targets "${_cmake_expected_target}") - if(TARGET "${_cmake_expected_target}") - list(APPEND _cmake_targets_defined "${_cmake_expected_target}") - else() - list(APPEND _cmake_targets_not_defined "${_cmake_expected_target}") - endif() -endforeach() -unset(_cmake_expected_target) -if(_cmake_targets_defined STREQUAL _cmake_expected_targets) - unset(_cmake_targets_defined) - unset(_cmake_targets_not_defined) - unset(_cmake_expected_targets) - unset(CMAKE_IMPORT_FILE_VERSION) - cmake_policy(POP) - return() -endif() -if(NOT _cmake_targets_defined STREQUAL "") - string(REPLACE ";" ", " _cmake_targets_defined_text "${_cmake_targets_defined}") - string(REPLACE ";" ", " _cmake_targets_not_defined_text "${_cmake_targets_not_defined}") - message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_cmake_targets_defined_text}\nTargets not yet defined: ${_cmake_targets_not_defined_text}\n") -endif() -unset(_cmake_targets_defined) -unset(_cmake_targets_not_defined) -unset(_cmake_expected_targets) - - -# Compute the installation prefix relative to this file. -get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) -get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) -get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) -get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) -if(_IMPORT_PREFIX STREQUAL "/") - set(_IMPORT_PREFIX "") -endif() - -# Create imported target expat::expat -add_library(expat::expat SHARED IMPORTED) - -set_target_properties(expat::expat PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" - INTERFACE_LINK_LIBRARIES "m" -) - -# Load information for each installed configuration. -file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/expat-*.cmake") -foreach(_cmake_config_file IN LISTS _cmake_config_files) - include("${_cmake_config_file}") -endforeach() -unset(_cmake_config_file) -unset(_cmake_config_files) - -# Cleanup temporary variables. -set(_IMPORT_PREFIX) - -# Loop over all imported files and verify that they actually exist -foreach(_cmake_target IN LISTS _cmake_import_check_targets) - if(CMAKE_VERSION VERSION_LESS "3.28" - OR NOT DEFINED _cmake_import_check_xcframework_for_${_cmake_target} - OR NOT IS_DIRECTORY "${_cmake_import_check_xcframework_for_${_cmake_target}}") - foreach(_cmake_file IN LISTS "_cmake_import_check_files_for_${_cmake_target}") - if(NOT EXISTS "${_cmake_file}") - message(FATAL_ERROR "The imported target \"${_cmake_target}\" references the file - \"${_cmake_file}\" -but this file does not exist. Possible reasons include: -* The file was deleted, renamed, or moved to another location. -* An install or uninstall procedure did not complete successfully. -* The installation package was faulty and contained - \"${CMAKE_CURRENT_LIST_FILE}\" -but not all the files it references. -") - endif() - endforeach() - endif() - unset(_cmake_file) - unset("_cmake_import_check_files_for_${_cmake_target}") -endforeach() -unset(_cmake_target) -unset(_cmake_import_check_targets) - -# This file does not depend on other imported targets which have -# been exported from the same project but in a separate export set. - -# Commands beyond this point should not need to know the version. -set(CMAKE_IMPORT_FILE_VERSION) -cmake_policy(POP) diff -Nru expat-2.7.1/expat/cmake/autotools/expat__linux.cmake.in expat-2.8.2/expat/cmake/autotools/expat__linux.cmake.in --- expat-2.7.1/expat/cmake/autotools/expat__linux.cmake.in 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/expat/cmake/autotools/expat__linux.cmake.in 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,107 @@ +# Generated by CMake + +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8) + message(FATAL_ERROR "CMake >= 2.8.12 required") +endif() +if(CMAKE_VERSION VERSION_LESS "2.8.12") + message(FATAL_ERROR "CMake >= 2.8.12 required") +endif() +cmake_policy(PUSH) +cmake_policy(VERSION 2.8.12...3.29) +#---------------------------------------------------------------- +# Generated CMake target import file. +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Protect against multiple inclusion, which would fail when already imported targets are added once more. +set(_cmake_targets_defined "") +set(_cmake_targets_not_defined "") +set(_cmake_expected_targets "") +foreach(_cmake_expected_target IN ITEMS expat::expat) + list(APPEND _cmake_expected_targets "${_cmake_expected_target}") + if(TARGET "${_cmake_expected_target}") + list(APPEND _cmake_targets_defined "${_cmake_expected_target}") + else() + list(APPEND _cmake_targets_not_defined "${_cmake_expected_target}") + endif() +endforeach() +unset(_cmake_expected_target) +if(_cmake_targets_defined STREQUAL _cmake_expected_targets) + unset(_cmake_targets_defined) + unset(_cmake_targets_not_defined) + unset(_cmake_expected_targets) + unset(CMAKE_IMPORT_FILE_VERSION) + cmake_policy(POP) + return() +endif() +if(NOT _cmake_targets_defined STREQUAL "") + string(REPLACE ";" ", " _cmake_targets_defined_text "${_cmake_targets_defined}") + string(REPLACE ";" ", " _cmake_targets_not_defined_text "${_cmake_targets_not_defined}") + message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_cmake_targets_defined_text}\nTargets not yet defined: ${_cmake_targets_not_defined_text}\n") +endif() +unset(_cmake_targets_defined) +unset(_cmake_targets_not_defined) +unset(_cmake_expected_targets) + + +# Compute the installation prefix relative to this file. +get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +if(_IMPORT_PREFIX STREQUAL "/") + set(_IMPORT_PREFIX "") +endif() + +# Create imported target expat::expat +add_library(expat::expat SHARED IMPORTED) + +set_target_properties(expat::expat PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" + INTERFACE_LINK_LIBRARIES "m" +) + +# Load information for each installed configuration. +file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/expat-*.cmake") +foreach(_cmake_config_file IN LISTS _cmake_config_files) + include("${_cmake_config_file}") +endforeach() +unset(_cmake_config_file) +unset(_cmake_config_files) + +# Cleanup temporary variables. +set(_IMPORT_PREFIX) + +# Loop over all imported files and verify that they actually exist +foreach(_cmake_target IN LISTS _cmake_import_check_targets) + if(CMAKE_VERSION VERSION_LESS "3.28" + OR NOT DEFINED _cmake_import_check_xcframework_for_${_cmake_target} + OR NOT IS_DIRECTORY "${_cmake_import_check_xcframework_for_${_cmake_target}}") + foreach(_cmake_file IN LISTS "_cmake_import_check_files_for_${_cmake_target}") + if(NOT EXISTS "${_cmake_file}") + message(FATAL_ERROR "The imported target \"${_cmake_target}\" references the file + \"${_cmake_file}\" +but this file does not exist. Possible reasons include: +* The file was deleted, renamed, or moved to another location. +* An install or uninstall procedure did not complete successfully. +* The installation package was faulty and contained + \"${CMAKE_CURRENT_LIST_FILE}\" +but not all the files it references. +") + endif() + endforeach() + endif() + unset(_cmake_file) + unset("_cmake_import_check_files_for_${_cmake_target}") +endforeach() +unset(_cmake_target) +unset(_cmake_import_check_targets) + +# This file does not depend on other imported targets which have +# been exported from the same project but in a separate export set. + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) +cmake_policy(POP) diff -Nru expat-2.7.1/expat/cmake/autotools/expat__macos.cmake.in expat-2.8.2/expat/cmake/autotools/expat__macos.cmake.in --- expat-2.7.1/expat/cmake/autotools/expat__macos.cmake.in 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/expat/cmake/autotools/expat__macos.cmake.in 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,107 @@ +# Generated by CMake + +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8) + message(FATAL_ERROR "CMake >= 2.8.12 required") +endif() +if(CMAKE_VERSION VERSION_LESS "2.8.12") + message(FATAL_ERROR "CMake >= 2.8.12 required") +endif() +cmake_policy(PUSH) +cmake_policy(VERSION 2.8.12...4.1) +#---------------------------------------------------------------- +# Generated CMake target import file. +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Protect against multiple inclusion, which would fail when already imported targets are added once more. +set(_cmake_targets_defined "") +set(_cmake_targets_not_defined "") +set(_cmake_expected_targets "") +foreach(_cmake_expected_target IN ITEMS expat::expat) + list(APPEND _cmake_expected_targets "${_cmake_expected_target}") + if(TARGET "${_cmake_expected_target}") + list(APPEND _cmake_targets_defined "${_cmake_expected_target}") + else() + list(APPEND _cmake_targets_not_defined "${_cmake_expected_target}") + endif() +endforeach() +unset(_cmake_expected_target) +if(_cmake_targets_defined STREQUAL _cmake_expected_targets) + unset(_cmake_targets_defined) + unset(_cmake_targets_not_defined) + unset(_cmake_expected_targets) + unset(CMAKE_IMPORT_FILE_VERSION) + cmake_policy(POP) + return() +endif() +if(NOT _cmake_targets_defined STREQUAL "") + string(REPLACE ";" ", " _cmake_targets_defined_text "${_cmake_targets_defined}") + string(REPLACE ";" ", " _cmake_targets_not_defined_text "${_cmake_targets_not_defined}") + message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_cmake_targets_defined_text}\nTargets not yet defined: ${_cmake_targets_not_defined_text}\n") +endif() +unset(_cmake_targets_defined) +unset(_cmake_targets_not_defined) +unset(_cmake_expected_targets) + + +# Compute the installation prefix relative to this file. +get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +if(_IMPORT_PREFIX STREQUAL "/") + set(_IMPORT_PREFIX "") +endif() + +# Create imported target expat::expat +add_library(expat::expat SHARED IMPORTED) + +set_target_properties(expat::expat PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" + INTERFACE_LINK_LIBRARIES "m" +) + +# Load information for each installed configuration. +file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/expat-*.cmake") +foreach(_cmake_config_file IN LISTS _cmake_config_files) + include("${_cmake_config_file}") +endforeach() +unset(_cmake_config_file) +unset(_cmake_config_files) + +# Cleanup temporary variables. +set(_IMPORT_PREFIX) + +# Loop over all imported files and verify that they actually exist +foreach(_cmake_target IN LISTS _cmake_import_check_targets) + if(CMAKE_VERSION VERSION_LESS "3.28" + OR NOT DEFINED _cmake_import_check_xcframework_for_${_cmake_target} + OR NOT IS_DIRECTORY "${_cmake_import_check_xcframework_for_${_cmake_target}}") + foreach(_cmake_file IN LISTS "_cmake_import_check_files_for_${_cmake_target}") + if(NOT EXISTS "${_cmake_file}") + message(FATAL_ERROR "The imported target \"${_cmake_target}\" references the file + \"${_cmake_file}\" +but this file does not exist. Possible reasons include: +* The file was deleted, renamed, or moved to another location. +* An install or uninstall procedure did not complete successfully. +* The installation package was faulty and contained + \"${CMAKE_CURRENT_LIST_FILE}\" +but not all the files it references. +") + endif() + endforeach() + endif() + unset(_cmake_file) + unset("_cmake_import_check_files_for_${_cmake_target}") +endforeach() +unset(_cmake_target) +unset(_cmake_import_check_targets) + +# This file does not depend on other imported targets which have +# been exported from the same project but in a separate export set. + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) +cmake_policy(POP) diff -Nru expat-2.7.1/expat/cmake/autotools/expat__windows.cmake.in expat-2.8.2/expat/cmake/autotools/expat__windows.cmake.in --- expat-2.7.1/expat/cmake/autotools/expat__windows.cmake.in 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/expat/cmake/autotools/expat__windows.cmake.in 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,107 @@ +# Generated by CMake + +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8) + message(FATAL_ERROR "CMake >= 2.8.12 required") +endif() +if(CMAKE_VERSION VERSION_LESS "2.8.12") + message(FATAL_ERROR "CMake >= 2.8.12 required") +endif() +cmake_policy(PUSH) +cmake_policy(VERSION 2.8.12...3.29) +#---------------------------------------------------------------- +# Generated CMake target import file. +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Protect against multiple inclusion, which would fail when already imported targets are added once more. +set(_cmake_targets_defined "") +set(_cmake_targets_not_defined "") +set(_cmake_expected_targets "") +foreach(_cmake_expected_target IN ITEMS expat::expat) + list(APPEND _cmake_expected_targets "${_cmake_expected_target}") + if(TARGET "${_cmake_expected_target}") + list(APPEND _cmake_targets_defined "${_cmake_expected_target}") + else() + list(APPEND _cmake_targets_not_defined "${_cmake_expected_target}") + endif() +endforeach() +unset(_cmake_expected_target) +if(_cmake_targets_defined STREQUAL _cmake_expected_targets) + unset(_cmake_targets_defined) + unset(_cmake_targets_not_defined) + unset(_cmake_expected_targets) + unset(CMAKE_IMPORT_FILE_VERSION) + cmake_policy(POP) + return() +endif() +if(NOT _cmake_targets_defined STREQUAL "") + string(REPLACE ";" ", " _cmake_targets_defined_text "${_cmake_targets_defined}") + string(REPLACE ";" ", " _cmake_targets_not_defined_text "${_cmake_targets_not_defined}") + message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_cmake_targets_defined_text}\nTargets not yet defined: ${_cmake_targets_not_defined_text}\n") +endif() +unset(_cmake_targets_defined) +unset(_cmake_targets_not_defined) +unset(_cmake_expected_targets) + + +# Compute the installation prefix relative to this file. +get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +if(_IMPORT_PREFIX STREQUAL "/") + set(_IMPORT_PREFIX "") +endif() + +# Create imported target expat::expat +add_library(expat::expat SHARED IMPORTED) + +set_target_properties(expat::expat PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" + INTERFACE_LINK_LIBRARIES "m" +) + +# Load information for each installed configuration. +file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/expat-*.cmake") +foreach(_cmake_config_file IN LISTS _cmake_config_files) + include("${_cmake_config_file}") +endforeach() +unset(_cmake_config_file) +unset(_cmake_config_files) + +# Cleanup temporary variables. +set(_IMPORT_PREFIX) + +# Loop over all imported files and verify that they actually exist +foreach(_cmake_target IN LISTS _cmake_import_check_targets) + if(CMAKE_VERSION VERSION_LESS "3.28" + OR NOT DEFINED _cmake_import_check_xcframework_for_${_cmake_target} + OR NOT IS_DIRECTORY "${_cmake_import_check_xcframework_for_${_cmake_target}}") + foreach(_cmake_file IN LISTS "_cmake_import_check_files_for_${_cmake_target}") + if(NOT EXISTS "${_cmake_file}") + message(FATAL_ERROR "The imported target \"${_cmake_target}\" references the file + \"${_cmake_file}\" +but this file does not exist. Possible reasons include: +* The file was deleted, renamed, or moved to another location. +* An install or uninstall procedure did not complete successfully. +* The installation package was faulty and contained + \"${CMAKE_CURRENT_LIST_FILE}\" +but not all the files it references. +") + endif() + endforeach() + endif() + unset(_cmake_file) + unset("_cmake_import_check_files_for_${_cmake_target}") +endforeach() +unset(_cmake_target) +unset(_cmake_import_check_targets) + +# This file does not depend on other imported targets which have +# been exported from the same project but in a separate export set. + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) +cmake_policy(POP) diff -Nru expat-2.7.1/expat/configure.ac expat-2.8.2/expat/configure.ac --- expat-2.7.1/expat/configure.ac 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/configure.ac 2026-06-25 14:07:00.000000000 +0000 @@ -11,7 +11,7 @@ dnl Copyright (c) 2000-2005 Fred L. Drake, Jr. dnl Copyright (c) 2001-2003 Greg Stein dnl Copyright (c) 2006-2012 Karl Waclawek -dnl Copyright (c) 2016-2025 Sebastian Pipping +dnl Copyright (c) 2016-2026 Sebastian Pipping dnl Copyright (c) 2017 S. P. Zeidler dnl Copyright (c) 2017 Stephen Groat dnl Copyright (c) 2017-2020 Joe Orton @@ -24,6 +24,11 @@ dnl Copyright (c) 2020 Jeffrey Walton dnl Copyright (c) 2024 Ferenc Géczi dnl Copyright (c) 2024 Dag-Erling Smørgrav +dnl Copyright (c) 2025 Matthew Fernandez +dnl Copyright (c) 2025 Alfonso Gregory +dnl Copyright (c) 2026 Rosen Penev +dnl Copyright (c) 2026 Gordon Messmer +dnl Copyright (c) 2026 Fabio Scaccabarozzi dnl Licensed under the MIT license: dnl dnl Permission is hereby granted, free of charge, to any person obtaining @@ -84,9 +89,9 @@ dnl If the API changes incompatibly set LIBAGE back to 0 dnl -LIBCURRENT=11 # sync +LIBCURRENT=13 # sync LIBREVISION=2 # with -LIBAGE=10 # CMakeLists.txt! +LIBAGE=12 # CMakeLists.txt! AC_CONFIG_HEADERS([expat_config.h]) AH_TOP([#ifndef EXPAT_CONFIG_H @@ -95,7 +100,6 @@ AM_PROG_AR AC_PROG_INSTALL -AC_PROG_LN_S AC_PROG_MAKE_SET LT_PREREQ([2.4]) @@ -117,10 +121,12 @@ dnl GCC don't support it and it causes extra warnings that are only dnl distracting; avoid. AX_APPEND_COMPILE_FLAGS([-fexceptions], [AM_CFLAGS]) - AX_APPEND_COMPILE_FLAGS([-fno-strict-aliasing -Wmissing-prototypes -Wstrict-prototypes], [AM_CFLAGS]) + AX_APPEND_COMPILE_FLAGS([-Wstrict-aliasing=3 -Wmissing-prototypes -Wstrict-prototypes], [AM_CFLAGS]) AX_APPEND_COMPILE_FLAGS([-pedantic -Wduplicated-cond -Wduplicated-branches -Wlogical-op], [AM_CFLAGS]) AX_APPEND_COMPILE_FLAGS([-Wrestrict -Wnull-dereference -Wjump-misses-init -Wdouble-promotion], [AM_CFLAGS]) - AX_APPEND_COMPILE_FLAGS([-Wshadow -Wformat=2 -Wno-pedantic-ms-format -Wmisleading-indentation], [AM_CFLAGS])]) + AX_APPEND_COMPILE_FLAGS([-Wshadow -Wformat=2 -Wmisleading-indentation], [AM_CFLAGS]) + AS_CASE(["${host_os}"], [mingw*], [AX_APPEND_COMPILE_FLAGS([-Wno-pedantic-ms-format], [AM_CFLAGS])]) + ]) AC_LANG_PUSH([C++]) AC_PROG_CXX @@ -131,11 +137,23 @@ dnl GCC don't support it and it causes extra warnings that are only dnl distracting; avoid. AX_APPEND_COMPILE_FLAGS([-fexceptions], [AM_CXXFLAGS]) - AX_APPEND_COMPILE_FLAGS([-fno-strict-aliasing], [AM_CXXFLAGS])]) + AX_APPEND_COMPILE_FLAGS([-Wstrict-aliasing=3], [AM_CXXFLAGS])]) AC_LANG_POP([C++]) AS_IF([test "$GCC" = yes], - [AX_APPEND_LINK_FLAGS([-fno-strict-aliasing],[AM_LDFLAGS])]) + [AX_APPEND_LINK_FLAGS([-Wstrict-aliasing=3],[AM_LDFLAGS])]) + +AC_ARG_ENABLE([symbol-versioning], + [AS_HELP_STRING([--enable-symbol-versioning], + [provide symbol versioning for dependency generation @<:@default=no@:>@])], + [enable_symbol_versioning=$enableval], + [enable_symbol_versioning=no]) +AS_IF([test "x$enable_symbol_versioning" != xno], + [VSCRIPT_LDFLAGS="-Wl,--version-script" + AC_SUBST([VSCRIPT_LDFLAGS]) + ]) +AM_CONDITIONAL([HAVE_VSCRIPT], + [test "x$enable_symbol_versioning" != xno]) dnl patching ${archive_cmds} to affect generation of file "libtool" to fix linking with clang (issue #312) AS_CASE(["$LD"],[*clang*], @@ -199,48 +217,110 @@ LT_LIB_M -AC_ARG_WITH([libbsd], - [AS_HELP_STRING([--with-libbsd], [utilize libbsd (for arc4random_buf)])], +AC_ARG_WITH([arc4random], + [AS_HELP_STRING([--with-arc4random], + [enforce the use of arc4random function in the system @<:@default=check@:>@]) +AS_HELP_STRING([--without-arc4random], + [skip auto detect of arc4random @<:@default=check@:>@])], + [], + [with_arc4random=check]) + +AC_ARG_WITH([arc4random-buf], + [AS_HELP_STRING([--with-arc4random-buf], + [enforce the use of arc4random_buf function in the system @<:@default=check@:>@]) +AS_HELP_STRING([--without-arc4random-buf], + [skip auto detect of arc4random_buf @<:@default=check@:>@])], [], - [with_libbsd=no]) -AS_IF([test "x${with_libbsd}" != xno], - [AC_CHECK_LIB([bsd], - [arc4random_buf], - [], - [AS_IF([test "x${with_libbsd}" = xyes], - [AC_MSG_ERROR([Enforced use of libbsd cannot be satisfied.])])])]) -AC_MSG_CHECKING([for arc4random_buf (BSD, libbsd or glibc 2.36+)]) -AC_LINK_IFELSE([AC_LANG_SOURCE([ - #if defined(HAVE_LIBBSD) - # include - #else - # include /* for arc4random_buf on BSD */ - #endif - int main(void) { - char dummy[[123]]; // double brackets for m4 - arc4random_buf(dummy, 0U); - return 0; - } - ])], - [AC_DEFINE([HAVE_ARC4RANDOM_BUF], [1], [Define to 1 if you have the `arc4random_buf' function.]) - AC_MSG_RESULT([yes])], - [AC_MSG_RESULT([no]) + [with_arc4random_buf=check]) - AC_MSG_CHECKING([for arc4random (BSD, macOS, libbsd or glibc 2.36+)]) +have_arc4random=false +have_arc4random_buf=false + +AS_IF([test "x${with_arc4random_buf}" != xno], + [AC_MSG_CHECKING([for arc4random_buf (BSD or glibc 2.36+)]) AC_LINK_IFELSE([AC_LANG_SOURCE([ - #if defined(HAVE_LIBBSD) - # include - #else - # include + #if ! defined(_DEFAULT_SOURCE) + # define _DEFAULT_SOURCE 1 /* for glibc */ + #endif + #include + int main(void) { + char dummy[[123]]; // double brackets for m4 + arc4random_buf(dummy, 0U); + return 0; + } + ])], + [AC_DEFINE([HAVE_ARC4RANDOM_BUF], [1], [Define to 1 if you have the `arc4random_buf' function.]) + have_arc4random_buf=true + AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AS_IF([test "x${with_arc4random_buf}" = xyes], + [AC_MSG_ERROR([enforced the use of arc4random_buf --with-arc4random-buf, but not detected])])])]) + +AS_IF([test "x${with_arc4random}" != xno], + [AC_MSG_CHECKING([for arc4random (BSD, macOS, or glibc 2.36+)]) + AC_LINK_IFELSE([AC_LANG_SOURCE([ + #if ! defined(_DEFAULT_SOURCE) + # define _DEFAULT_SOURCE 1 /* for glibc */ #endif + #include int main(void) { arc4random(); return 0; } ])], [AC_DEFINE([HAVE_ARC4RANDOM], [1], [Define to 1 if you have the `arc4random' function.]) + have_arc4random=true + AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AS_IF([test "x${with_arc4random}" = xyes], + [AC_MSG_ERROR([enforced the use of arc4random --with-arc4random, but not detected])])])]) + +AM_CONDITIONAL([WITH_ARC4RANDOM], [test x${have_arc4random} = xtrue]) +AM_CONDITIONAL([WITH_ARC4RANDOM_BUF], [test x${have_arc4random_buf} = xtrue]) + +have_getentropy=false + +AC_ARG_WITH([getentropy], + [AS_HELP_STRING([--with-getentropy], + [enforce the use of getentropy function in the system @<:@default=check@:>@]) +AS_HELP_STRING([--without-getentropy], + [skip auto detect of getentropy @<:@default=check@:>@])], + [], + [with_getentropy=check]) + +AS_IF([test "x$with_getentropy" != xno], + [AC_MSG_CHECKING([for getentropy (BSD, macOS 10.12+, glibc 2.25+)]) + AC_LINK_IFELSE([AC_LANG_SOURCE([ + // NOTE: Please keep this block in sync with its two siblings in files + // 'ConfigureChecks.cmake' and 'lib/random_getentropy.c'! + #if defined(__APPLE__) + # include + #else + # if defined(__GLIBC__) && ! defined(_DEFAULT_SOURCE) + # define _DEFAULT_SOURCE 1 + # endif + # if ! defined(_GNU_SOURCE) + # define _GNU_SOURCE 1 /* for musl */ + # endif + # include + #endif // ! defined(__APPLE__) + + int main(void) { + return getentropy(NULL, 0U); + } + ])], + [AC_DEFINE([HAVE_GETENTROPY], [1], [Define to 1 if you have the `getentropy' function.]) + have_getentropy=true AC_MSG_RESULT([yes])], - [AC_MSG_RESULT([no])])]) + [AC_MSG_RESULT([no]) + AS_IF([test "x$with_getentropy" = xyes], + [AC_MSG_ERROR([enforced the use of getentropy --with-getentropy, but not detected])])])]) + +AM_CONDITIONAL([WITH_GETENTROPY], [test x${have_getentropy} = xtrue]) + +have_either_getrandom=false +have_getrandom_function=false +have_getrandom_syscall=false AC_ARG_WITH([getrandom], [AS_HELP_STRING([--with-getrandom], @@ -260,6 +340,8 @@ } ])], [AC_DEFINE([HAVE_GETRANDOM], [1], [Define to 1 if you have the `getrandom' function.]) + have_either_getrandom=true + have_getrandom_function=true AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AS_IF([test "x$with_getrandom" = xyes], @@ -286,11 +368,15 @@ } ])], [AC_DEFINE([HAVE_SYSCALL_GETRANDOM], [1], [Define to 1 if you have `syscall' and `SYS_getrandom'.]) + have_either_getrandom=true + have_getrandom_syscall=true AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AS_IF([test "x$with_sys_getrandom" = xyes], [AC_MSG_ERROR([enforced the use of syscall SYS_getrandom --with-sys-getrandom, but not detected])])])]) +AM_CONDITIONAL([WITH_EITHER_GETRANDOM], [test x${have_either_getrandom} = xtrue]) + dnl Only needed for xmlwf: AC_CHECK_HEADERS(fcntl.h unistd.h) AC_TYPE_OFF_T @@ -309,8 +395,23 @@ [Define as 1/0 to enable/disable support for general entities.]) AC_DEFINE([XML_DTD], 1, [Define to make parameter entity parsing functionality available.]) -AC_DEFINE([XML_DEV_URANDOM], 1, - [Define to include code reading entropy from `/dev/urandom'.]) + + +have_dev_urandom=false + +AC_ARG_WITH([dev-urandom], + [AS_HELP_STRING([--with-dev-urandom], + [enforce the use of /dev/urandom in the system @<:@default=no@:>@]) +AS_HELP_STRING([--without-dev-urandom], + [enforce not using /dev/urandom in the system @<:@default=no@:>@])], + [with_dev_urandom=${withval}], + []) + +AS_IF([test "x${with_dev_urandom}" = "xyes"], + [have_dev_urandom=true + AC_DEFINE([XML_DEV_URANDOM], 1, + [Define to include code reading entropy from `/dev/urandom'.])]) + AC_ARG_ENABLE([xml-attr-info], [AS_HELP_STRING([--enable-xml-attr-info], @@ -381,9 +482,14 @@ dnl that are either set to "" when enabled or to "#" when disabled dnl (because they are used to dynamically comment out certain things) AS_IF([test "x${enable_xml_attr_info}" = xyes], - [EXPAT_ATTR_INFO=ON], - [EXPAT_ATTR_INFO=OFF]) + [EXPAT_ATTR_INFO=ON + _EXPAT_COMMENT_ATTR_INFO=" "], + [EXPAT_ATTR_INFO=OFF + _EXPAT_COMMENT_ATTR_INFO="#"]) +AC_SUBST([_EXPAT_COMMENT_ATTR_INFO]) EXPAT_DTD=ON +_EXPAT_COMMENT_DTD_OR_GE=" " +AC_SUBST([_EXPAT_COMMENT_DTD_OR_GE]) AS_IF([test "x${_INTERNAL_LARGE_SIZE_TRUE}" = x], [EXPAT_LARGE_SIZE=ON], [EXPAT_LARGE_SIZE=OFF]) @@ -440,17 +546,28 @@ AC_SUBST([CMAKE_SHARED_LIBRARY_PREFIX]) AS_CASE("${host_os}", - [darwin*], [CMAKE_NOCONFIG_SOURCE=cmake/autotools/expat-noconfig__macos.cmake.in], - [mingw*|cygwin*], [CMAKE_NOCONFIG_SOURCE=cmake/autotools/expat-noconfig__windows.cmake.in], - [CMAKE_NOCONFIG_SOURCE=cmake/autotools/expat-noconfig__linux.cmake.in]) + [darwin*], [ + CMAKE_SOURCE=cmake/autotools/expat__macos.cmake.in + CMAKE_NOCONFIG_SOURCE=cmake/autotools/expat-noconfig__macos.cmake.in + ], + [mingw*|cygwin*], [ + CMAKE_SOURCE=cmake/autotools/expat__windows.cmake.in + CMAKE_NOCONFIG_SOURCE=cmake/autotools/expat-noconfig__windows.cmake.in + ], + [ + CMAKE_SOURCE=cmake/autotools/expat__linux.cmake.in + CMAKE_NOCONFIG_SOURCE=cmake/autotools/expat-noconfig__linux.cmake.in + ]) AC_CONFIG_FILES([Makefile] [expat.pc] [cmake/expat-config.cmake] + [cmake/autotools/expat.cmake:${CMAKE_SOURCE}] [cmake/autotools/expat-config-version.cmake] [cmake/autotools/expat-noconfig.cmake:${CMAKE_NOCONFIG_SOURCE}] [doc/Makefile] [examples/Makefile] [lib/Makefile] + [lib/libexpat.map] [tests/Makefile] [tests/benchmark/Makefile] [xmlwf/Makefile]) @@ -470,4 +587,17 @@ CPPFLAGS: ${CPPFLAGS} CFLAGS: ${CFLAGS} CXXFLAGS: ${CXXFLAGS} - LDFLAGS: ${LDFLAGS}]) + LDFLAGS: ${LDFLAGS} + +Entropy sources: + arc4random: ${have_arc4random} + arc4random_buf: ${have_arc4random_buf} + getentropy: ${have_getentropy} + getrandom: ${have_getrandom_function} + syscall SYS_getrandom: ${have_getrandom_syscall} + /dev/urandom: ${have_dev_urandom} + +Continue with e.g.: + make -j2 + make check + sudo make install]) diff -Nru expat-2.7.1/expat/conftools/expat.m4 expat-2.8.2/expat/conftools/expat.m4 --- expat-2.7.1/expat/conftools/expat.m4 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/conftools/expat.m4 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -dnl Check if --with-expat[=PREFIX] is specified and -dnl Expat >= 1.95.0 is installed in the system. -dnl If yes, substitute EXPAT_CFLAGS, EXPAT_LIBS with regard to -dnl the specified PREFIX and set with_expat to PREFIX, or 'yes' if PREFIX -dnl has not been specified. Also HAVE_LIBEXPAT, HAVE_EXPAT_H are defined. -dnl If --with-expat has not been specified, set with_expat to 'no'. -dnl In addition, an Automake conditional EXPAT_INSTALLED is set accordingly. -dnl This is necessary to adapt a whole lot of packages that have expat -dnl bundled as a static library. -AC_DEFUN([AM_WITH_EXPAT], -[ AC_ARG_WITH(expat, - [ --with-expat=PREFIX Use system Expat library], - , with_expat=no) - - AM_CONDITIONAL(EXPAT_INSTALLED, test $with_expat != no) - - EXPAT_CFLAGS= - EXPAT_LIBS= - if test $with_expat != no; then - if test $with_expat != yes; then - EXPAT_CFLAGS="-I$with_expat/include" - EXPAT_LIBS="-L$with_expat/lib" - fi - AC_CHECK_LIB(expat, XML_ParserCreate, - [ EXPAT_LIBS="$EXPAT_LIBS -lexpat" - expat_found=yes ], - [ expat_found=no ], - "$EXPAT_LIBS") - if test $expat_found = no; then - AC_MSG_ERROR([Could not find the Expat library]) - fi - expat_save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $EXPAT_CFLAGS" - AC_CHECK_HEADERS(expat.h, , expat_found=no) - if test $expat_found = no; then - AC_MSG_ERROR([Could not find expat.h]) - fi - CFLAGS="$expat_save_CFLAGS" - fi - - AC_SUBST(EXPAT_CFLAGS) - AC_SUBST(EXPAT_LIBS) -]) diff -Nru expat-2.7.1/expat/coverage.sh expat-2.8.2/expat/coverage.sh --- expat-2.7.1/expat/coverage.sh 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/coverage.sh 2026-06-25 14:07:00.000000000 +0000 @@ -6,9 +6,10 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2017-2024 Sebastian Pipping +# Copyright (c) 2017-2025 Sebastian Pipping # Copyright (c) 2018 Marco Maggi # Copyright (c) 2019 Mohammed Khajapasha +# Copyright (c) 2026 Rosen Penev # Licensed under the MIT license: # # Permission is hereby granted, free of charge, to any person obtaining @@ -39,11 +40,6 @@ _get_build_dir() { - local libbsd_part= - if ${with_libbsd}; then - libbsd_part=__libbsd - fi - local mingw_part= if ${with_mingw}; then mingw_part=__windows @@ -78,7 +74,7 @@ dtd_part=__dtd fi - echo "build__${version}__xml_context_${xml_context}${libbsd_part}${mingw_part}${char_part}${ge_part}${dtd_part}${xml_attr_part}${m32_part}" + echo "build__${version}__xml_context_${xml_context}${mingw_part}${char_part}${ge_part}${dtd_part}${xml_attr_part}${m32_part}" } @@ -102,7 +98,6 @@ cmake_args+=( -DEXPAT_CONTEXT_BYTES=${xml_context} ) fi - ${with_libbsd} && cmake_args+=( -DEXPAT_WITH_LIBBSD=ON ) ${with_mingw} && cmake_args+=( -DCMAKE_TOOLCHAIN_FILE="${abs_source_dir}"/cmake/mingw-toolchain.cmake ) ${with_m32} && cmake_args+=( -D_EXPAT_M32=ON ) ${with_ge} || cmake_args+=( -DEXPAT_GE=OFF ) @@ -195,10 +190,17 @@ done fi + # NOTE: This is meant to mitigate Wine crashing randomly in CI + if ${with_mingw} && [[ ${CI} = true ]]; then + local retry='retry --times 5 --' + else + local retry= + fi + set -x make CTEST_OUTPUT_ON_FAILURE=1 test if ${with_dtd}; then - make run-xmltest + ${retry} make run-xmltest fi lcov -c -d "${capture_dir}" -o "${coverage_info}-test" &>> run.log @@ -304,7 +306,6 @@ # All combinations: with_unsigned_char=false - with_libbsd=false with_m32=false with_dtd=true with_ge=true @@ -323,7 +324,6 @@ done # Single cases: - with_libbsd=true _build_case with_unsigned_char=true _build_case with_m32=true _build_case with_dtd=false with_ge=true _build_case diff -Nru expat-2.7.1/expat/doc/reference.html expat-2.8.2/expat/doc/reference.html --- expat-2.7.1/expat/doc/reference.html 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/doc/reference.html 2026-06-25 14:07:00.000000000 +0000 @@ -1,9 +1,9 @@ - + - - - - Expat XML Parser - - - - - - -
-

- The Expat XML Parser - Release 2.7.1 -

-
-
- -

Expat is a library, written in C, for parsing XML documents. It's -the underlying XML parser for the open source Mozilla project, Perl's -XML::Parser, Python's xml.parsers.expat, and -other open-source XML parsers.

- -

This library is the creation of James Clark, who's also given us -groff (an nroff look-alike), Jade (an implementation of ISO's DSSSL -stylesheet language for SGML), XP (a Java XML parser package), XT (a -Java XSL engine). James was also the technical lead on the XML -Working Group at W3C that produced the XML specification.

- -

This is free software, licensed under the MIT/X Consortium license. You may download it -from the Expat home page. -

- -

The bulk of this document was originally commissioned as an article -by XML.com. They graciously allowed -Clark Cooper to retain copyright and to distribute it with Expat. -This version has been substantially extended to include documentation -on features which have been added since the original article was -published, and additional information on using the original -interface.

- -
-

Table of Contents

- - -
-

Overview

- -

Expat is a stream-oriented parser. You register callback (or -handler) functions with the parser and then start feeding it the -document. As the parser recognizes parts of the document, it will -call the appropriate handler for that part (if you've registered one.) -The document is fed to the parser in pieces, so you can start parsing -before you have all the document. This also allows you to parse really -huge documents that won't fit into memory.

- -

Expat can be intimidating due to the many kinds of handlers and -options you can set. But you only need to learn four functions in -order to do 90% of what you'll want to do with it:

- -
- -
XML_ParserCreate
-
Create a new parser object.
- -
XML_SetElementHandler
-
Set handlers for start and end tags.
- -
XML_SetCharacterDataHandler
-
Set handler for text.
- -
XML_Parse
-
Pass a buffer full of document to the parser
-
- -

These functions and others are described in the reference part of this document. The reference -section also describes in detail the parameters passed to the -different types of handlers.

- -

Let's look at a very simple example program that only uses 3 of the -above functions (it doesn't need to set a character handler.) The -program outline.c prints an -element outline, indenting child elements to distinguish them from the -parent element that contains them. The start handler does all the -work. It prints two indenting spaces for every level of ancestor -elements, then it prints the element and attribute -information. Finally it increments the global Depth -variable.

-
+      
+ +

+ Overview +

+ +

+ Expat is a stream-oriented parser. You register callback (or handler) functions + with the parser and then start feeding it the document. As the parser recognizes + parts of the document, it will call the appropriate handler for that part (if + you've registered one.) The document is fed to the parser in pieces, so you can + start parsing before you have all the document. This also allows you to parse + really huge documents that won't fit into memory. +

+ +

+ Expat can be intimidating due to the many kinds of handlers and options you can + set. But you only need to learn four functions in order to do 90% of what you'll + want to do with it: +

+ +
+
+ XML_ParserCreate +
+ +
+ Create a new parser object. +
+ +
+ XML_SetElementHandler +
+ +
+ Set handlers for start and end tags. +
+ +
+ XML_SetCharacterDataHandler +
+ +
+ Set handler for text. +
+ +
+ XML_Parse +
+ +
+ Pass a buffer full of document to the parser +
+
+ +

+ These functions and others are described in the reference part of this document. The reference section also + describes in detail the parameters passed to the different types of handlers. +

+ +

+ Let's look at a very simple example program that only uses 3 of the above + functions (it doesn't need to set a character handler.) The program outline.c prints an element outline, indenting child + elements to distinguish them from the parent element that contains them. The + start handler does all the work. It prints two indenting spaces for every level + of ancestor elements, then it prints the element and attribute information. + Finally it increments the global Depth variable. +

+ +
 int Depth;
 
 void XMLCALL
@@ -258,39 +548,41 @@
   Depth++;
 }  /* End of start handler */
 
+

+ The end tag simply does the bookkeeping work of decrementing Depth. +

-

The end tag simply does the bookkeeping work of decrementing -Depth.

-
+      
 void XMLCALL
 end(void *data, const char *el) {
   Depth--;
 }  /* End of end handler */
 
+

+ Note the XMLCALL annotation used for the callbacks. This is used to + ensure that the Expat and the callbacks are using the same calling convention in + case the compiler options used for Expat itself and the client code are + different. Expat tries not to care what the default calling convention is, though + it may require that it be compiled with a default convention of "cdecl" on some + platforms. For code which uses Expat, however, the calling convention is + specified by the XMLCALL annotation on most platforms; callbacks + should be defined using this annotation. +

+ +

+ The XMLCALL annotation was added in Expat 1.95.7, but existing + working Expat applications don't need to add it (since they are already using the + "cdecl" calling convention, or they wouldn't be working). The annotation is only + needed if the default calling convention may be something other than "cdecl". To + use the annotation safely with older versions of Expat, you can conditionally + define it after including Expat's header file: +

-

Note the XMLCALL annotation used for the callbacks. -This is used to ensure that the Expat and the callbacks are using the -same calling convention in case the compiler options used for Expat -itself and the client code are different. Expat tries not to care -what the default calling convention is, though it may require that it -be compiled with a default convention of "cdecl" on some platforms. -For code which uses Expat, however, the calling convention is -specified by the XMLCALL annotation on most platforms; -callbacks should be defined using this annotation.

- -

The XMLCALL annotation was added in Expat 1.95.7, but -existing working Expat applications don't need to add it (since they -are already using the "cdecl" calling convention, or they wouldn't be -working). The annotation is only needed if the default calling -convention may be something other than "cdecl". To use the annotation -safely with older versions of Expat, you can conditionally define it -after including Expat's header file:

- -
+      
 #include <expat.h>
 
 #ifndef XMLCALL
-#if defined(_MSC_EXTENSIONS) && !defined(__BEOS__) && !defined(__CYGWIN__)
+#if defined(_MSC_VER) && !defined(__BEOS__) && !defined(__CYGWIN__)
 #define XMLCALL __cdecl
 #elif defined(__GNUC__)
 #define XMLCALL __attribute__((cdecl))
@@ -299,186 +591,256 @@
 #endif
 #endif
 
+

+ After creating the parser, the main program just has the job of shoveling the + document to the parser so that it can do its work. +

+ +
+ +

+ Building and Installing Expat +

+ +

+ The Expat distribution comes as a compressed (with GNU gzip) tar file. You may + download the latest version from Source Forge. After unpacking this, + cd into the directory. Then follow either the Win32 directions or Unix directions + below. +

+ +

+ Building under Win32 +

+ +

+ If you're using the GNU compiler under cygwin, follow the Unix directions in the + next section. Otherwise if you have Microsoft's Developer Studio installed, you + can use CMake to generate a .sln file, e.g. cmake -G"Visual + Studio 17 2022" -DCMAKE_BUILD_TYPE=RelWithDebInfo . , and build Expat + using msbuild /m expat.sln after. +

+ +

+ Alternatively, you may download the Win32 binary package that contains the + "expat.h" include file and a pre-built DLL. +

+ +

+ Building under Unix (or GNU) +

+ +

+ First you'll need to run the configure shell script in order to configure the + Makefiles and headers for your system. +

+ +

+ If you're happy with all the defaults that configure picks for you, and you have + permission on your system to install into /usr/local, you can install Expat with + this sequence of commands: +

-

After creating the parser, the main program just has the job of -shoveling the document to the parser so that it can do its work.

- -
-

Building and Installing Expat

- -

The Expat distribution comes as a compressed (with GNU gzip) tar -file. You may download the latest version from Source Forge. After -unpacking this, cd into the directory. Then follow either the Win32 -directions or Unix directions below.

- -

Building under Win32

- -

If you're using the GNU compiler under cygwin, follow the Unix -directions in the next section. Otherwise if you have Microsoft's -Developer Studio installed, -you can use CMake to generate a .sln file, e.g. - -cmake -G"Visual Studio 16 2019" -DCMAKE_BUILD_TYPE=RelWithDebInfo . -, and build Expat using msbuild /m expat.sln after.

- -

Alternatively, you may download the Win32 binary package that -contains the "expat.h" include file and a pre-built DLL.

- -

Building under Unix (or GNU)

- -

First you'll need to run the configure shell script in order to -configure the Makefiles and headers for your system.

- -

If you're happy with all the defaults that configure picks for you, -and you have permission on your system to install into /usr/local, you -can install Expat with this sequence of commands:

- -
+      
 ./configure
 make
 make install
 
+

+ There are some options that you can provide to this script, but the only one + we'll mention here is the --prefix option. You can find out all the + options available by running configure with just the --help option. +

+ +

+ By default, the configure script sets things up so that the library gets + installed in /usr/local/lib and the associated header file in + /usr/local/include. But if you were to give the option, + --prefix=/home/me/mystuff, then the library and header would get + installed in /home/me/mystuff/lib and + /home/me/mystuff/include respectively. +

+ +

+ Configuring Expat Using the Pre-Processor +

+ +

+ Expat's feature set can be configured using a small number of pre-processor + definitions. The symbols are: +

+ +
+
+ XML_GE +
+ +
+ Added in Expat 2.6.0. Include support for general + entities (syntax &e1; to reference and syntax + <!ENTITY e1 'value1'> (an internal general entity) or + <!ENTITY e2 SYSTEM 'file2'> (an external general entity) to + declare). With XML_GE enabled, general entities will be replaced + by their declared replacement text; for this to work for external + general entities, in addition an XML_ExternalEntityRefHandler must + be set using XML_SetExternalEntityRefHandler. + Also, enabling XML_GE makes the functions XML_SetBillionLaughsAttackProtectionMaximumAmplification + and XML_SetBillionLaughsAttackProtectionActivationThreshold + available.
+ With XML_GE disabled, Expat has a smaller memory footprint and can + be faster, but will not load external general entities and will replace all + general entities (except the predefined + five: amp, apos, gt, + lt, quot) with a self-reference: for example, + referencing an entity e1 via &e1; will be + replaced by text &e1;. +
+ +
+ XML_DTD +
+ +
+ Include support for using and reporting DTD-based content. If this is defined, + default attribute values from an external DTD subset are reported and attribute + value normalization occurs based on the type of attributes defined in the + external subset. Without this, Expat has a smaller memory footprint and can be + faster, but will not load external parameter entities or process conditional + sections. If defined, makes the functions XML_SetBillionLaughsAttackProtectionMaximumAmplification + and XML_SetBillionLaughsAttackProtectionActivationThreshold + available. +
+ +
+ XML_NS +
+ +
+ When defined, support for the Namespaces in XML + specification is included. +
+ +
+ XML_UNICODE +
+ +
+ When defined, character data reported to the application is encoded in UTF-16 + using wide characters of the type XML_Char. This is implied if + XML_UNICODE_WCHAR_T is defined. +
+ +
+ XML_UNICODE_WCHAR_T +
+ +
+ If defined, causes the XML_Char character type to be defined using + the wchar_t type; otherwise, unsigned short is used. + Defining this implies XML_UNICODE. +
+ +
+ XML_LARGE_SIZE +
+ +
+ If defined, causes the XML_Size and XML_Index integer + types to be at least 64 bits in size. This is intended to support processing of + very large input streams, where the return values of XML_GetCurrentByteIndex, XML_GetCurrentLineNumber and + XML_GetCurrentColumnNumber could + overflow. It may not be supported by all compilers, and is turned off by + default. +
+ +
+ XML_CONTEXT_BYTES +
+ +
+ The number of input bytes of markup context which the parser will ensure are + available for reporting via XML_GetInputContext. This is normally set to + 1024, and must be set to a positive integer to enable. If this is set to zero, + the input context will not be available and XML_GetInputContext will always report + NULL. Without this, Expat has a smaller memory footprint and can + be faster. +
+ +
+ XML_STATIC +
+ +
+ On Windows, this should be set if Expat is going to be linked statically with + the code that calls it; this is required to get all the right MSVC magic + annotations correct. This is ignored on other platforms. +
+ +
+ XML_ATTR_INFO +
+ +
+ If defined, makes the additional function XML_GetAttributeInfo available for reporting + attribute byte offsets. +
+
+ +
+ +

+ Using Expat +

+ +

+ Compiling and Linking Against Expat +

+ +

+ Unless you installed Expat in a location not expected by your compiler and + linker, all you have to do to use Expat in your programs is to include the Expat + header (#include <expat.h>) in your files that make calls to + it and to tell the linker that it needs to link against the Expat library. On + Unix systems, this would usually be done with the -lexpat argument. + Otherwise, you'll need to tell the compiler where to look for the Expat header + and the linker where to find the Expat library. You may also need to take steps + to tell the operating system where to find this library at run time. +

+ +

+ On a Unix-based system, here's what a Makefile might look like when Expat is + installed in a standard location: +

-

There are some options that you can provide to this script, but the -only one we'll mention here is the --prefix option. You -can find out all the options available by running configure with just -the --help option.

- -

By default, the configure script sets things up so that the library -gets installed in /usr/local/lib and the associated -header file in /usr/local/include. But if you were to -give the option, --prefix=/home/me/mystuff, then the -library and header would get installed in -/home/me/mystuff/lib and -/home/me/mystuff/include respectively.

- -

Configuring Expat Using the Pre-Processor

- -

Expat's feature set can be configured using a small number of -pre-processor definitions. The symbols are:

- -
-
XML_GE
-
-Added in Expat 2.6.0. -Include support for -general entities -(syntax &e1; to reference and -syntax <!ENTITY e1 'value1'> (an internal general entity) or -<!ENTITY e2 SYSTEM 'file2'> (an external general entity) to declare). -With XML_GE enabled, general entities will be replaced by their declared replacement text; -for this to work for external general entities, in addition an -XML_ExternalEntityRefHandler must be set using -XML_SetExternalEntityRefHandler. -Also, enabling XML_GE makes -the functions -XML_SetBillionLaughsAttackProtectionMaximumAmplification and - -XML_SetBillionLaughsAttackProtectionActivationThreshold available. -
-With XML_GE disabled, Expat has a smaller memory footprint and can be faster, but will -not load external general entities and will replace all general entities -(except the predefined five: -amp, apos, gt, lt, quot) -with a self-reference: -for example, referencing an entity e1 via &e1; will be replaced -by text &e1;. -
- -
XML_DTD
-
Include support for using and reporting DTD-based content. If -this is defined, default attribute values from an external DTD subset -are reported and attribute value normalization occurs based on the -type of attributes defined in the external subset. Without -this, Expat has a smaller memory footprint and can be faster, but will -not load external parameter entities or process conditional sections. If defined, makes -the functions -XML_SetBillionLaughsAttackProtectionMaximumAmplification and - -XML_SetBillionLaughsAttackProtectionActivationThreshold available.
- -
XML_NS
-
When defined, support for the Namespaces in XML -specification is included.
- -
XML_UNICODE
-
When defined, character data reported to the application is -encoded in UTF-16 using wide characters of the type -XML_Char. This is implied if -XML_UNICODE_WCHAR_T is defined.
- -
XML_UNICODE_WCHAR_T
-
If defined, causes the XML_Char character type to be -defined using the wchar_t type; otherwise, unsigned -short is used. Defining this implies -XML_UNICODE.
- -
XML_LARGE_SIZE
-
If defined, causes the XML_Size and XML_Index -integer types to be at least 64 bits in size. This is intended to support -processing of very large input streams, where the return values of -XML_GetCurrentByteIndex, -XML_GetCurrentLineNumber and -XML_GetCurrentColumnNumber -could overflow. It may not be supported by all compilers, and is turned -off by default.
- -
XML_CONTEXT_BYTES
-
The number of input bytes of markup context which the parser will -ensure are available for reporting via XML_GetInputContext. This is -normally set to 1024, and must be set to a positive integer to enable. -If this is set to zero, the input context will not be available and XML_GetInputContext will -always report NULL. Without this, Expat has a smaller memory -footprint and can be faster.
- -
XML_STATIC
-
On Windows, this should be set if Expat is going to be linked -statically with the code that calls it; this is required to get all -the right MSVC magic annotations correct. This is ignored on other -platforms.
- -
XML_ATTR_INFO
-
If defined, makes the additional function XML_GetAttributeInfo available -for reporting attribute byte offsets.
-
- -
-

Using Expat

- -

Compiling and Linking Against Expat

- -

Unless you installed Expat in a location not expected by your -compiler and linker, all you have to do to use Expat in your programs -is to include the Expat header (#include <expat.h>) -in your files that make calls to it and to tell the linker that it -needs to link against the Expat library. On Unix systems, this would -usually be done with the -lexpat argument. Otherwise, -you'll need to tell the compiler where to look for the Expat header -and the linker where to find the Expat library. You may also need to -take steps to tell the operating system where to find this library at -run time.

- -

On a Unix-based system, here's what a Makefile might look like when -Expat is installed in a standard location:

- -
+      
 CC=cc
 LDFLAGS=
 LIBS= -lexpat
 xmlapp: xmlapp.o
         $(CC) $(LDFLAGS) -o xmlapp xmlapp.o $(LIBS)
 
+

+ If you installed Expat in, say, /home/me/mystuff, then the Makefile + would look like this: +

-

If you installed Expat in, say, /home/me/mystuff, then -the Makefile would look like this:

- -
+      
 CC=cc
 CFLAGS= -I/home/me/mystuff/include
 LDFLAGS=
@@ -486,65 +848,71 @@
 xmlapp: xmlapp.o
         $(CC) $(LDFLAGS) -o xmlapp xmlapp.o $(LIBS)
 
+

+ You'd also have to set the environment variable LD_LIBRARY_PATH to + /home/me/mystuff/lib (or to + ${LD_LIBRARY_PATH}:/home/me/mystuff/lib if LD_LIBRARY_PATH already + has some directories in it) in order to run your application. +

+ +

+ Expat Basics +

+ +

+ As we saw in the example in the overview, the first step in parsing an XML + document with Expat is to create a parser object. There are three functions in the Expat API for creating a parser object. + However, only two of these (XML_ParserCreate and XML_ParserCreateNS) can be used for constructing + a parser for a top-level document. The object returned by these functions is an + opaque pointer (i.e. "expat.h" declares it as void *) to data with further + internal structure. In order to free the memory associated with this object you + must call XML_ParserFree. Note that if + you have provided any user data that gets stored in the + parser, then your application is responsible for freeing it prior to calling + XML_ParserFree. +

+ +

+ The objects returned by the parser creation functions are good for parsing only + one XML document or external parsed entity. If your application needs to parse + many XML documents, then it needs to create a parser object for each one. The + best way to deal with this is to create a higher level object that contains all + the default initialization you want for your parser objects. +

+ +

+ Walking through a document hierarchy with a stream oriented parser will require a + good stack mechanism in order to keep track of current context. For instance, to + answer the simple question, "What element does this text belong to?" requires a + stack, since the parser may have descended into other elements that are children + of the current one and has encountered this text on the way out. +

+ +

+ The things you're likely to want to keep on a stack are the currently opened + element and it's attributes. You push this information onto the stack in the + start handler and you pop it off in the end handler. +

+ +

+ For some tasks, it is sufficient to just keep information on what the depth of + the stack is (or would be if you had one.) The outline program shown above + presents one example. Another such task would be skipping over a complete + element. When you see the start tag for the element you want to skip, you set a + skip flag and record the depth at which the element started. When the end tag + handler encounters the same depth, the skipped element has ended and the flag may + be cleared. If you follow the convention that the root element starts at 1, then + you can use the same variable for skip flag and skip depth. +

-

You'd also have to set the environment variable -LD_LIBRARY_PATH to /home/me/mystuff/lib (or -to ${LD_LIBRARY_PATH}:/home/me/mystuff/lib if -LD_LIBRARY_PATH already has some directories in it) in order to run -your application.

- -

Expat Basics

- -

As we saw in the example in the overview, the first step in parsing -an XML document with Expat is to create a parser object. There are three functions in the Expat API for creating a -parser object. However, only two of these (XML_ParserCreate and XML_ParserCreateNS) can be used for -constructing a parser for a top-level document. The object returned -by these functions is an opaque pointer (i.e. "expat.h" declares it as -void *) to data with further internal structure. In order to free the -memory associated with this object you must call XML_ParserFree. Note that if you have -provided any user data that gets stored in the -parser, then your application is responsible for freeing it prior to -calling XML_ParserFree.

- -

The objects returned by the parser creation functions are good for -parsing only one XML document or external parsed entity. If your -application needs to parse many XML documents, then it needs to create -a parser object for each one. The best way to deal with this is to -create a higher level object that contains all the default -initialization you want for your parser objects.

- -

Walking through a document hierarchy with a stream oriented parser -will require a good stack mechanism in order to keep track of current -context. For instance, to answer the simple question, "What element -does this text belong to?" requires a stack, since the parser may have -descended into other elements that are children of the current one and -has encountered this text on the way out.

- -

The things you're likely to want to keep on a stack are the -currently opened element and it's attributes. You push this -information onto the stack in the start handler and you pop it off in -the end handler.

- -

For some tasks, it is sufficient to just keep information on what -the depth of the stack is (or would be if you had one.) The outline -program shown above presents one example. Another such task would be -skipping over a complete element. When you see the start tag for the -element you want to skip, you set a skip flag and record the depth at -which the element started. When the end tag handler encounters the -same depth, the skipped element has ended and the flag may be -cleared. If you follow the convention that the root element starts at -1, then you can use the same variable for skip flag and skip -depth.

- -
+      
 void
 init_info(Parseinfo *info) {
-  info->skip = 0;
-  info->depth = 1;
+  info->skip = 0;
+  info->depth = 1;
   /* Other initializations here */
 }  /* End of init_info */
 
@@ -552,87 +920,91 @@
 rawstart(void *data, const char *el, const char **attr) {
   Parseinfo *inf = (Parseinfo *) data;
 
-  if (! inf->skip) {
+  if (! inf->skip) {
     if (should_skip(inf, el, attr)) {
-      inf->skip = inf->depth;
+      inf->skip = inf->depth;
     }
     else
       start(inf, el, attr);     /* This does rest of start handling */
   }
 
-  inf->depth++;
+  inf->depth++;
 }  /* End of rawstart */
 
 void XMLCALL
 rawend(void *data, const char *el) {
   Parseinfo *inf = (Parseinfo *) data;
 
-  inf->depth--;
+  inf->depth--;
 
-  if (! inf->skip)
+  if (! inf->skip)
     end(inf, el);              /* This does rest of end handling */
 
-  if (inf->skip == inf->depth)
-    inf->skip = 0;
+  if (inf->skip == inf->depth)
+    inf->skip = 0;
 }  /* End rawend */
 
+

+ Notice in the above example the difference in how depth is manipulated in the + start and end handlers. The end tag handler should be the mirror image of the + start tag handler. This is necessary to properly model containment. Since, in the + start tag handler, we incremented depth after the main body of start tag + code, then in the end handler, we need to manipulate it before the main + body. If we'd decided to increment it first thing in the start handler, then we'd + have had to decrement it last thing in the end handler. +

+ +

+ Communicating between handlers +

+ +

+ In order to be able to pass information between different handlers without using + globals, you'll need to define a data structure to hold the shared variables. You + can then tell Expat (with the XML_SetUserData function) to pass a pointer to this + structure to the handlers. This is the first argument received by most handlers. + In the reference section, an argument to a callback + function is named userData and have type void * if the + user data is passed; it will have the type XML_Parser if the parser + itself is passed. When the parser is passed, the user data may be retrieved using + XML_GetUserData. +

+ +

+ One common case where multiple calls to a single handler may need to communicate + using an application data structure is the case when content passed to the + character data handler (set by XML_SetCharacterDataHandler) needs to + be accumulated. A common first-time mistake with any of the event-oriented + interfaces to an XML parser is to expect all the text contained in an element to + be reported by a single call to the character data handler. Expat, like many + other XML parsers, reports such data as a sequence of calls; there's no way to + know when the end of the sequence is reached until a different callback is made. + A buffer referenced by the user data structure proves both an effective and + convenient place to accumulate character data. +

+ + +

+ XML Version +

+ +

+ Expat is an XML 1.0 parser, and as such never complains based on the value of the + version pseudo-attribute in the XML declaration, if present. +

+ +

+ If an application needs to check the version number (to support alternate + processing), it should use the XML_SetXmlDeclHandler function to set a + handler that uses the information in the XML declaration to determine what to do. + This example shows how to check that only a version number of "1.0" + is accepted: +

-

Notice in the above example the difference in how depth is -manipulated in the start and end handlers. The end tag handler should -be the mirror image of the start tag handler. This is necessary to -properly model containment. Since, in the start tag handler, we -incremented depth after the main body of start tag code, then -in the end handler, we need to manipulate it before the main -body. If we'd decided to increment it first thing in the start -handler, then we'd have had to decrement it last thing in the end -handler.

- -

Communicating between handlers

- -

In order to be able to pass information between different handlers -without using globals, you'll need to define a data structure to hold -the shared variables. You can then tell Expat (with the XML_SetUserData function) to pass a -pointer to this structure to the handlers. This is the first -argument received by most handlers. In the reference section, an argument to a callback function is named -userData and have type void * if the user -data is passed; it will have the type XML_Parser if the -parser itself is passed. When the parser is passed, the user data may -be retrieved using XML_GetUserData.

- -

One common case where multiple calls to a single handler may need -to communicate using an application data structure is the case when -content passed to the character data handler (set by XML_SetCharacterDataHandler) needs to be accumulated. A -common first-time mistake with any of the event-oriented interfaces to -an XML parser is to expect all the text contained in an element to be -reported by a single call to the character data handler. Expat, like -many other XML parsers, reports such data as a sequence of calls; -there's no way to know when the end of the sequence is reached until a -different callback is made. A buffer referenced by the user data -structure proves both an effective and convenient place to accumulate -character data.

- - - - -

XML Version

- -

Expat is an XML 1.0 parser, and as such never complains based on -the value of the version pseudo-attribute in the XML -declaration, if present.

- -

If an application needs to check the version number (to support -alternate processing), it should use the XML_SetXmlDeclHandler function to -set a handler that uses the information in the XML declaration to -determine what to do. This example shows how to check that only a -version number of "1.0" is accepted:

- -
+      
 static int wrong_version;
 static XML_Parser parser;
 
@@ -658,201 +1030,272 @@
   ...
 }
 
+

+ Namespace Processing +

+ +

+ When the parser is created using the XML_ParserCreateNS, function, Expat performs + namespace processing. Under namespace processing, Expat consumes + xmlns and xmlns:... attributes, which declare + namespaces for the scope of the element in which they occur. This means that your + start handler will not see these attributes. Your application can still be + informed of these declarations by setting namespace declaration handlers with + XML_SetNamespaceDeclHandler. +

+ +

+ Element type and attribute names that belong to a given namespace are passed to + the appropriate handler in expanded form. By default this expanded form is a + concatenation of the namespace URI, the separator character (which is the 2nd + argument to XML_ParserCreateNS), + and the local name (i.e. the part after the colon). Names with undeclared + prefixes are not well-formed when namespace processing is enabled, and will + trigger an error. Unprefixed attribute names are never expanded, and unprefixed + element names are only expanded when they are in the scope of a default + namespace. +

+ +

+ However if XML_SetReturnNSTriplet has been called with + a non-zero do_nst parameter, then the expanded form for names with + an explicit prefix is a concatenation of: URI, separator, local name, separator, + prefix. +

+ +

+ You can set handlers for the start of a namespace declaration and for the end of + a scope of a declaration with the XML_SetNamespaceDeclHandler function. + The StartNamespaceDeclHandler is called prior to the start tag handler and the + EndNamespaceDeclHandler is called after the corresponding end tag that ends the + namespace's scope. The namespace start handler gets passed the prefix and URI for + the namespace. For a default namespace declaration (xmlns='...'), the prefix will + be NULL. The URI will be NULL for the case where the + default namespace is being unset. The namespace end handler just gets the prefix + for the closing scope. +

+ +

+ These handlers are called for each declaration. So if, for instance, a start tag + had three namespace declarations, then the StartNamespaceDeclHandler would be + called three times before the start tag handler is called, once for each + declaration. +

+ +

+ Character Encodings +

+ +

+ While XML is based on Unicode, and every XML processor is required to recognized + UTF-8 and UTF-16 (1 and 2 byte encodings of Unicode), other encodings may be + declared in XML documents or entities. For the main document, an XML declaration + may contain an encoding declaration: +

-

Namespace Processing

- -

When the parser is created using the XML_ParserCreateNS, function, Expat -performs namespace processing. Under namespace processing, Expat -consumes xmlns and xmlns:... attributes, -which declare namespaces for the scope of the element in which they -occur. This means that your start handler will not see these -attributes. Your application can still be informed of these -declarations by setting namespace declaration handlers with XML_SetNamespaceDeclHandler.

- -

Element type and attribute names that belong to a given namespace -are passed to the appropriate handler in expanded form. By default -this expanded form is a concatenation of the namespace URI, the -separator character (which is the 2nd argument to XML_ParserCreateNS), and the local -name (i.e. the part after the colon). Names with undeclared prefixes -are not well-formed when namespace processing is enabled, and will -trigger an error. Unprefixed attribute names are never expanded, -and unprefixed element names are only expanded when they are in the -scope of a default namespace.

- -

However if XML_SetReturnNSTriplet has been called with a non-zero -do_nst parameter, then the expanded form for names with -an explicit prefix is a concatenation of: URI, separator, local name, -separator, prefix.

- -

You can set handlers for the start of a namespace declaration and -for the end of a scope of a declaration with the XML_SetNamespaceDeclHandler -function. The StartNamespaceDeclHandler is called prior to the start -tag handler and the EndNamespaceDeclHandler is called after the -corresponding end tag that ends the namespace's scope. The namespace -start handler gets passed the prefix and URI for the namespace. For a -default namespace declaration (xmlns='...'), the prefix will be -NULL. -The URI will be NULL for the case where the default namespace is being -unset. The namespace end handler just gets the prefix for the closing -scope.

- -

These handlers are called for each declaration. So if, for -instance, a start tag had three namespace declarations, then the -StartNamespaceDeclHandler would be called three times before the start -tag handler is called, once for each declaration.

- -

Character Encodings

- -

While XML is based on Unicode, and every XML processor is required -to recognized UTF-8 and UTF-16 (1 and 2 byte encodings of Unicode), -other encodings may be declared in XML documents or entities. For the -main document, an XML declaration may contain an encoding -declaration:

-
+      
 <?xml version="1.0" encoding="ISO-8859-2"?>
 
+

+ External parsed entities may begin with a text declaration, which looks like an + XML declaration with just an encoding declaration: +

-

External parsed entities may begin with a text declaration, which -looks like an XML declaration with just an encoding declaration:

-
+      
 <?xml encoding="Big5"?>
 
+

+ With Expat, you may also specify an encoding at the time of creating a parser. + This is useful when the encoding information may come from a source outside the + document itself (like a higher level protocol.) +

+ +

+ There are four built-in + encodings in Expat: +

+ +
    +
  • UTF-8 +
  • + +
  • UTF-16 +
  • + +
  • ISO-8859-1 +
  • + +
  • US-ASCII +
  • +
-

With Expat, you may also specify an encoding at the time of -creating a parser. This is useful when the encoding information may -come from a source outside the document itself (like a higher level -protocol.)

- -

There are four built-in encodings -in Expat:

-
    -
  • UTF-8
  • -
  • UTF-16
  • -
  • ISO-8859-1
  • -
  • US-ASCII
  • -
- -

Anything else discovered in an encoding declaration or in the -protocol encoding specified in the parser constructor, triggers a call -to the UnknownEncodingHandler. This handler gets passed -the encoding name and a pointer to an XML_Encoding data -structure. Your handler must fill in this structure and return -XML_STATUS_OK if it knows how to deal with the -encoding. Otherwise the handler should return -XML_STATUS_ERROR. The handler also gets passed a pointer -to an optional application data structure that you may indicate when -you set the handler.

- -

Expat places restrictions on character encodings that it can -support by filling in the XML_Encoding structure. -include file:

-
    -
  1. Every ASCII character that can appear in a well-formed XML document -must be represented by a single byte, and that byte must correspond to -it's ASCII encoding (except for the characters $@\^'{}~)
  2. -
  3. Characters must be encoded in 4 bytes or less.
  4. -
  5. All characters encoded must have Unicode scalar values less than or -equal to 65535 (0xFFFF)This does not apply to the built-in support -for UTF-16 and UTF-8
  6. -
  7. No character may be encoded by more that one distinct sequence of -bytes
  8. -
- -

XML_Encoding contains an array of integers that -correspond to the 1st byte of an encoding sequence. If the value in -the array for a byte is zero or positive, then the byte is a single -byte encoding that encodes the Unicode scalar value contained in the -array. A -1 in this array indicates a malformed byte. If the value is --2, -3, or -4, then the byte is the beginning of a 2, 3, or 4 byte -sequence respectively. Multi-byte sequences are sent to the convert -function pointed at in the XML_Encoding structure. This -function should return the Unicode scalar value for the sequence or -1 -if the sequence is malformed.

- -

One pitfall that novice Expat users are likely to fall into is that -although Expat may accept input in various encodings, the strings that -it passes to the handlers are always encoded in UTF-8 or UTF-16 -(depending on how Expat was compiled). Your application is responsible -for any translation of these strings into other encodings.

- -

Handling External Entity References

- -

Expat does not read or parse external entities directly. Note that -any external DTD is a special case of an external entity. If you've -set no ExternalEntityRefHandler, then external entity -references are silently ignored. Otherwise, it calls your handler with -the information needed to read and parse the external entity.

- -

Your handler isn't actually responsible for parsing the entity, but -it is responsible for creating a subsidiary parser with XML_ExternalEntityParserCreate that will do the job. This -returns an instance of XML_Parser that has handlers and -other data structures initialized from the parent parser. You may then -use XML_Parse or XML_ParseBuffer calls against this -parser. Since external entities my refer to other external entities, -your handler should be prepared to be called recursively.

- -

Parsing DTDs

- -

In order to parse parameter entities, before starting the parse, -you must call XML_SetParamEntityParsing with one of the following -arguments:

-
-
XML_PARAM_ENTITY_PARSING_NEVER
-
Don't parse parameter entities or the external subset
-
XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE
-
Parse parameter entities and the external subset unless -standalone was set to "yes" in the XML declaration.
-
XML_PARAM_ENTITY_PARSING_ALWAYS
-
Always parse parameter entities and the external subset
-
- -

In order to read an external DTD, you also have to set an external -entity reference handler as described above.

- -

Temporarily Stopping Parsing

- -

Expat 1.95.8 introduces a new feature: its now possible to stop -parsing temporarily from within a handler function, even if more data -has already been passed into the parser. Applications for this -include

- -
    -
  • Supporting the XInclude specification.
  • - -
  • Delaying further processing until additional information is - available from some other source.
  • - -
  • Adjusting processor load as task priorities shift within an - application.
  • - -
  • Stopping parsing completely (simply free or reset the parser - instead of resuming in the outer parsing loop). This can be useful - if an application-domain error is found in the XML being parsed or if - the result of the parse is determined not to be useful after - all.
  • -
- -

To take advantage of this feature, the main parsing loop of an -application needs to support this specifically. It cannot be -supported with a parsing loop compatible with Expat 1.95.7 or -earlier (though existing loops will continue to work without -supporting the stop/resume feature).

+

+ Anything else discovered in an encoding declaration or in the protocol encoding + specified in the parser constructor, triggers a call to the + UnknownEncodingHandler. This handler gets passed the encoding name + and a pointer to an XML_Encoding data structure. Your handler must + fill in this structure and return XML_STATUS_OK if it knows how to + deal with the encoding. Otherwise the handler should return + XML_STATUS_ERROR. The handler also gets passed a pointer to an + optional application data structure that you may indicate when you set the + handler. +

+ +

+ Expat places restrictions on character encodings that it can support by filling + in the XML_Encoding structure. include file: +

+ +
    +
  1. Every ASCII character that can appear in a well-formed XML document must be + represented by a single byte, and that byte must correspond to it's ASCII + encoding (except for the characters $@\^'{}~) +
  2. + +
  3. Characters must be encoded in 4 bytes or less. +
  4. + +
  5. All characters encoded must have Unicode scalar values less than or equal to + 65535 (0xFFFF)This does not apply to the built-in support for UTF-16 and + UTF-8 +
  6. + +
  7. No character may be encoded by more that one distinct sequence of bytes +
  8. +
+ +

+ XML_Encoding contains an array of integers that correspond to the + 1st byte of an encoding sequence. If the value in the array for a byte is zero or + positive, then the byte is a single byte encoding that encodes the Unicode scalar + value contained in the array. A -1 in this array indicates a malformed byte. If + the value is -2, -3, or -4, then the byte is the beginning of a 2, 3, or 4 byte + sequence respectively. Multi-byte sequences are sent to the convert function + pointed at in the XML_Encoding structure. This function should + return the Unicode scalar value for the sequence or -1 if the sequence is + malformed. +

+ +

+ One pitfall that novice Expat users are likely to fall into is that although + Expat may accept input in various encodings, the strings that it passes to the + handlers are always encoded in UTF-8 or UTF-16 (depending on how Expat was + compiled). Your application is responsible for any translation of these strings + into other encodings. +

+ +

+ Handling External Entity References +

+ +

+ Expat does not read or parse external entities directly. Note that any external + DTD is a special case of an external entity. If you've set no + ExternalEntityRefHandler, then external entity references are + silently ignored. Otherwise, it calls your handler with the information needed to + read and parse the external entity. +

+ +

+ Your handler isn't actually responsible for parsing the entity, but it is + responsible for creating a subsidiary parser with XML_ExternalEntityParserCreate that + will do the job. This returns an instance of XML_Parser that has + handlers and other data structures initialized from the parent parser. You may + then use XML_Parse or XML_ParseBuffer calls against this parser. Since + external entities my refer to other external entities, your handler should be + prepared to be called recursively. +

+ +

+ Parsing DTDs +

+ +

+ In order to parse parameter entities, before starting the parse, you must call + XML_SetParamEntityParsing + with one of the following arguments: +

+ +
+
+ XML_PARAM_ENTITY_PARSING_NEVER +
+ +
+ Don't parse parameter entities or the external subset +
+ +
+ XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE +
+ +
+ Parse parameter entities and the external subset unless standalone + was set to "yes" in the XML declaration. +
+ +
+ XML_PARAM_ENTITY_PARSING_ALWAYS +
+ +
+ Always parse parameter entities and the external subset +
+
+ +

+ In order to read an external DTD, you also have to set an external entity + reference handler as described above. +

+ +

+ Temporarily Stopping Parsing +

+ +

+ Expat 1.95.8 introduces a new feature: its now possible to stop parsing + temporarily from within a handler function, even if more data has already been + passed into the parser. Applications for this include +

-

An application that uses this feature for a single parser will have -the rough structure (in pseudo-code):

+
    +
  • Supporting the XInclude + specification. +
  • + +
  • Delaying further processing until additional information is available from + some other source. +
  • + +
  • Adjusting processor load as task priorities shift within an application. +
  • + +
  • Stopping parsing completely (simply free or reset the parser instead of + resuming in the outer parsing loop). This can be useful if an application-domain + error is found in the XML being parsed or if the result of the parse is + determined not to be useful after all. +
  • +
-
+      

+ To take advantage of this feature, the main parsing loop of an application needs + to support this specifically. It cannot be supported with a parsing loop + compatible with Expat 1.95.7 or earlier (though existing loops will continue to + work without supporting the stop/resume feature). +

+ +

+ An application that uses this feature for a single parser will have the rough + structure (in pseudo-code): +

+ +
 fd = open_input()
 p = create_parser()
 
@@ -869,15 +1312,18 @@
   }
 }
 
+

+ An application that may resume any of several parsers based on input (either from + the XML being parsed or some other source) will certainly have more interesting + control structures. +

+ +

+ This C function could be used for the parse_xml function mentioned + in the pseudo-code above: +

-

An application that may resume any of several parsers based on -input (either from the XML being parsed or some other source) will -certainly have more interesting control structures.

- -

This C function could be used for the parse_xml -function mentioned in the pseudo-code above:

- -
+      
 #define BUFF_SIZE 10240
 
 /* Parse a document from the open file descriptor 'fd' until the parse
@@ -916,14 +1362,14 @@
   }
 }
 
+

+ The corresponding continue_parsing function is somewhat simpler, + since it only need deal with the return code from XML_ResumeParser; it can delegate the input + handling to the parse_xml function: +

-

The corresponding continue_parsing function is -somewhat simpler, since it only need deal with the return code from -XML_ResumeParser; it can -delegate the input handling to the parse_xml -function:

- -
+      
 /* Continue parsing a document which had been suspended.  The 'p' and
    'fd' arguments are the same as passed to parse_xml().  Return
    non-zero when the parse is suspended.
@@ -945,274 +1391,345 @@
   return parse_xml(p, fd);
 }
 
+

+ Now that we've seen what a mess the top-level parsing loop can become, what have + we gained? Very simply, we can now use the XML_StopParser function to stop parsing, without + having to go to great lengths to avoid additional processing that we're expecting + to ignore. As a bonus, we get to stop parsing temporarily, and come back + to it when we're ready. +

+ +

+ To stop parsing from a handler function, use the XML_StopParser function. This function takes two + arguments; the parser being stopped and a flag indicating whether the parse can + be resumed in the future. +

+ + +
+ + +

+ Expat Reference +

+ +

+ Parser Creation +

+ +

+ XML_ParserCreate +

-

Now that we've seen what a mess the top-level parsing loop can -become, what have we gained? Very simply, we can now use the XML_StopParser function to stop -parsing, without having to go to great lengths to avoid additional -processing that we're expecting to ignore. As a bonus, we get to stop -parsing temporarily, and come back to it when we're -ready.

- -

To stop parsing from a handler function, use the XML_StopParser function. This function -takes two arguments; the parser being stopped and a flag indicating -whether the parse can be resumed in the future.

- - - - -
- - -

Expat Reference

- -

Parser Creation

- -

XML_ParserCreate

-
+      
 XML_Parser XMLCALL
 XML_ParserCreate(const XML_Char *encoding);
 
-
-

-Construct a new parser. If encoding is non-NULL, it specifies a -character encoding to use for the document. This overrides the document -encoding declaration. There are four built-in encodings: -

-
    -
  • US-ASCII
  • -
  • UTF-8
  • -
  • UTF-16
  • -
  • ISO-8859-1
  • -
-

-Any other value will invoke a call to the UnknownEncodingHandler. -

-
+
+

+ Construct a new parser. If encoding is non-NULL, it specifies a + character encoding to use for the document. This overrides the document + encoding declaration. There are four built-in encodings: +

+ +
    +
  • US-ASCII +
  • + +
  • UTF-8 +
  • + +
  • UTF-16 +
  • + +
  • ISO-8859-1 +
  • +
+ +

+ Any other value will invoke a call to the UnknownEncodingHandler. +

+
+ +

+ XML_ParserCreateNS +

-

XML_ParserCreateNS

-
+      
 XML_Parser XMLCALL
 XML_ParserCreateNS(const XML_Char *encoding,
                    XML_Char sep);
 
-
-Constructs a new parser that has namespace processing in effect. Namespace -expanded element names and attribute names are returned as a concatenation -of the namespace URI, sep, and the local part of the name. This -means that you should pick a character for sep that can't be part -of an URI. Since Expat does not check namespace URIs for conformance, the -only safe choice for a namespace separator is a character that is illegal -in XML. For instance, '\xFF' is not legal in UTF-8, and -'\xFFFF' is not legal in UTF-16. There is a special case when -sep is the null character '\0': the namespace URI and -the local part will be concatenated without any separator - this is intended -to support RDF processors. It is a programming error to use the null separator -with namespace triplets.
- -

Note: -Expat does not validate namespace URIs (beyond encoding) -against RFC 3986 today (and is not required to do so with regard to -the XML 1.0 namespaces specification) but it may start doing that -in future releases. Before that, an application using Expat must -be ready to receive namespace URIs containing non-URI characters. -

+
+ Constructs a new parser that has namespace processing in effect. Namespace + expanded element names and attribute names are returned as a concatenation of the + namespace URI, sep, and the local part of the name. This means that you + should pick a character for sep that can't be part of an URI. Since + Expat does not check namespace URIs for conformance, the only safe choice for a + namespace separator is a character that is illegal in XML. For instance, + '\xFF' is not legal in UTF-8, and '\xFFFF' is not legal + in UTF-16. There is a special case when sep is the null character + '\0': the namespace URI and the local part will be concatenated + without any separator - this is intended to support RDF processors. It is a + programming error to use the null separator with namespace triplets. +
+ +

+ Note: Expat does not validate namespace URIs (beyond encoding) + against RFC 3986 today (and is not required to do so with regard to the XML 1.0 + namespaces specification) but it may start doing that in future releases. Before + that, an application using Expat must be ready to receive namespace URIs + containing non-URI characters. +

+ +

+ XML_ParserCreate_MM +

-

XML_ParserCreate_MM

-
+      
 XML_Parser XMLCALL
 XML_ParserCreate_MM(const XML_Char *encoding,
                     const XML_Memory_Handling_Suite *ms,
-		    const XML_Char *sep);
+                    const XML_Char *sep);
 
-
+
+      
 typedef struct {
   void *(XMLCALL *malloc_fcn)(size_t size);
   void *(XMLCALL *realloc_fcn)(void *ptr, size_t size);
   void (XMLCALL *free_fcn)(void *ptr);
 } XML_Memory_Handling_Suite;
 
-
-

Construct a new parser using the suite of memory handling functions -specified in ms. If ms is NULL, then use the -standard set of memory management functions. If sep is -non-NULL, then namespace processing is enabled in the created parser -and the character pointed at by sep is used as the separator between -the namespace URI and the local part of the name.

-
+
+

+ Construct a new parser using the suite of memory handling functions specified + in ms. If ms is NULL, then use the + standard set of memory management functions. If sep is + non-NULL, then namespace processing is enabled in the created + parser and the character pointed at by sep is used as the separator between the + namespace URI and the local part of the name. +

+
+ +

+ XML_ExternalEntityParserCreate +

-

XML_ExternalEntityParserCreate

-
+      
 XML_Parser XMLCALL
 XML_ExternalEntityParserCreate(XML_Parser p,
                                const XML_Char *context,
                                const XML_Char *encoding);
 
-
-Construct a new XML_Parser object for parsing an external -general entity. Context is the context argument passed in a call to a -ExternalEntityRefHandler. Other state information such as handlers, -user data, namespace processing is inherited from the parser passed as -the 1st argument. So you shouldn't need to call any of the behavior -changing functions on this parser (unless you want it to act -differently than the parent parser). -
+
+

+ Construct a new XML_Parser object for parsing an external general + entity. Context is the context argument passed in a call to a + ExternalEntityRefHandler. Other state information such as handlers, user data, + namespace processing is inherited from the parser passed as the 1st argument. + So you shouldn't need to call any of the behavior changing functions on this + parser (unless you want it to act differently than the parent parser). +

+ +

+ Note: Please be sure to free subparsers created by + XML_ExternalEntityParserCreate + prior to freeing their related parent parser, as subparsers reference + and use parts of their respective parent parser, internally. Parent parsers + must outlive subparsers. +

+
+ +

+ XML_ParserFree +

-

XML_ParserFree

-
+      
 void XMLCALL
 XML_ParserFree(XML_Parser p);
 
-
-Free memory used by the parser. Your application is responsible for -freeing any memory associated with user data. -
+
+

+ Free memory used by the parser. +

+ +

+ Note: Your application is responsible for freeing any memory + associated with user data. +

+ +

+ Note: Please be sure to free subparsers created by + XML_ExternalEntityParserCreate + prior to freeing their related parent parser, as subparsers reference + and use parts of their respective parent parser, internally. Parent parsers + must outlive subparsers. +

+
+ +

+ XML_ParserReset +

-

XML_ParserReset

-
+      
 XML_Bool XMLCALL
 XML_ParserReset(XML_Parser p,
                 const XML_Char *encoding);
 
-
-Clean up the memory structures maintained by the parser so that it may -be used again. After this has been called, parser is -ready to start parsing a new document. All handlers are cleared from -the parser, except for the unknownEncodingHandler. The parser's external -state is re-initialized except for the values of ns and ns_triplets. -This function may not be used on a parser created using XML_ExternalEntityParserCreate; it will return XML_FALSE in that case. Returns -XML_TRUE on success. Your application is responsible for -dealing with any memory associated with user data. -
- -

Parsing

- -

To state the obvious: the three parsing functions XML_Parse, -XML_ParseBuffer and -XML_GetBuffer must not be called from within a handler -unless they operate on a separate parser instance, that is, one that -did not call the handler. For example, it is OK to call the parsing -functions from within an XML_ExternalEntityRefHandler, -if they apply to the parser created by -XML_ExternalEntityParserCreate.

- -

Note: The len argument passed to these functions -should be considerably less than the maximum value for an integer, -as it could create an integer overflow situation if the added -lengths of a buffer and the unprocessed portion of the previous buffer -exceed the maximum integer value. Input data at the end of a buffer -will remain unprocessed if it is part of an XML token for which the -end is not part of that buffer.

- -

The application must make a concluding -XML_Parse or -XML_ParseBuffer call -with isFinal set to XML_TRUE.

+
+ Clean up the memory structures maintained by the parser so that it may be used + again. After this has been called, parser is ready to start parsing + a new document. All handlers are cleared from the parser, except for the + unknownEncodingHandler. The parser's external state is re-initialized except for + the values of ns and ns_triplets. This function may not be used on a parser + created using XML_ExternalEntityParserCreate; it + will return XML_FALSE in that case. Returns XML_TRUE on + success. Your application is responsible for dealing with any memory associated + with user data. +
+ +

+ Parsing +

+ +

+ To state the obvious: the three parsing functions XML_Parse, XML_ParseBuffer and XML_GetBuffer as well as the two cleanup functions + XML_ParserFree and XML_ParserReset must not be called from within a + handler unless they operate on a separate parser instance, that is, one that did + not call the handler. For example, it is OK to call the parsing functions from + within an XML_ExternalEntityRefHandler, if they apply to the parser + created by XML_ExternalEntityParserCreate. +

+ +

+ Note: The len argument passed to these functions should be + considerably less than the maximum value for an integer, as it could create an + integer overflow situation if the added lengths of a buffer and the unprocessed + portion of the previous buffer exceed the maximum integer value. Input data at + the end of a buffer will remain unprocessed if it is part of an XML token for + which the end is not part of that buffer. +

+ +

+ The application must make a + concluding XML_Parse or XML_ParseBuffer call with isFinal set + to XML_TRUE. +

+ +

+ XML_Parse +

-

XML_Parse

-
+      
 enum XML_Status XMLCALL
 XML_Parse(XML_Parser p,
           const char *s,
           int len,
           int isFinal);
 
-
+
+      
 enum XML_Status {
   XML_STATUS_ERROR = 0,
   XML_STATUS_OK = 1
 };
 
-
-

-Parse some more of the document. The string s is a buffer -containing part (or perhaps all) of the document. The number of bytes of s -that are part of the document is indicated by len. This means -that s doesn't have to be null-terminated. It also means that -if len is larger than the number of bytes in the block of -memory that s points at, then a memory fault is likely. -Negative values for len are rejected since Expat 2.2.1. -The -isFinal parameter informs the parser that this is the last -piece of the document. Frequently, the last piece is empty (i.e. -len is zero.) -

- -

-If a parse error occurred, it returns XML_STATUS_ERROR. -Otherwise it returns XML_STATUS_OK value. -Note that regardless of the return value, there is no guarantee that all -provided input has been parsed; only after the -concluding call will all handler callbacks and parsing errors have -happened. -

- -

-Simplified, XML_Parse can be considered a convenience wrapper -that is pairing calls -to XML_GetBuffer -and XML_ParseBuffer -(when Expat is built with macro XML_CONTEXT_BYTES -defined to a positive value, which is both common and default). -XML_Parse is then functionally equivalent to calling -XML_GetBuffer, -memcpy, and -XML_ParseBuffer. -

- -

-To avoid double copying of the input, direct use of functions -XML_GetBuffer and -XML_ParseBuffer is advised -for most production use, e.g. -if you're using read or similar functionality to fill your -buffers, fill directly into the buffer from -XML_GetBuffer, -then parse with XML_ParseBuffer. -

-
+
+

+ Parse some more of the document. The string s is a buffer + containing part (or perhaps all) of the document. The number of bytes of s that + are part of the document is indicated by len. This means that + s doesn't have to be null-terminated. It also means that if + len is larger than the number of bytes in the block of memory that + s points at, then a memory fault is likely. Negative values for + len are rejected since Expat 2.2.1. The isFinal + parameter informs the parser that this is the last piece of the document. + Frequently, the last piece is empty (i.e. len is zero.) +

+ +

+ If a parse error occurred, it returns XML_STATUS_ERROR. Otherwise + it returns XML_STATUS_OK value. Note that regardless of the return + value, there is no guarantee that all provided input has been parsed; only + after the concluding call will all handler callbacks and + parsing errors have happened. +

+ +

+ Simplified, XML_Parse can be considered a convenience wrapper that + is pairing calls to XML_GetBuffer and + XML_ParseBuffer (when Expat is + built with macro XML_CONTEXT_BYTES defined to a positive value, + which is both common and default). XML_Parse is then functionally + equivalent to calling XML_GetBuffer, + memcpy, and XML_ParseBuffer. +

+ +

+ To avoid double copying of the input, direct use of functions XML_GetBuffer and XML_ParseBuffer is advised for most production + use, e.g. if you're using read or similar functionality to fill + your buffers, fill directly into the buffer from XML_GetBuffer, then parse with XML_ParseBuffer. +

+
+ +

+ XML_ParseBuffer +

-

XML_ParseBuffer

-
+      
 enum XML_Status XMLCALL
 XML_ParseBuffer(XML_Parser p,
                 int len,
                 int isFinal);
 
-
-

-This is just like XML_Parse, -except in this case Expat provides the buffer. By obtaining the -buffer from Expat with the XML_GetBuffer function, the application can avoid double -copying of the input. -

- -

-Negative values for len are rejected since Expat 2.6.3. -

-
+
+

+ This is just like XML_Parse, except in + this case Expat provides the buffer. By obtaining the buffer from Expat with + the XML_GetBuffer function, the + application can avoid double copying of the input. +

+ +

+ Negative values for len are rejected since Expat 2.6.3. +

+
+ +

+ XML_GetBuffer +

-

XML_GetBuffer

-
+      
 void * XMLCALL
 XML_GetBuffer(XML_Parser p,
               int len);
 
-
-Obtain a buffer of size len to read a piece of the document -into. A NULL value is returned if Expat can't allocate enough memory for -this buffer. A NULL value may also be returned if len is zero. -This has to be called prior to every call to -XML_ParseBuffer. A -typical use would look like this: +
+ Obtain a buffer of size len to read a piece of the document into. A + NULL value is returned if Expat can't allocate enough memory for + this buffer. A NULL value may also be returned if len + is zero. This has to be called prior to every call to XML_ParseBuffer. A typical use would look like + this: -
+        
 for (;;) {
   int bytes_read;
   void *buff = XML_GetBuffer(p, BUFF_SIZE);
@@ -1233,115 +1750,168 @@
     break;
 }
 
-
+
-

XML_StopParser

-
+      

+ XML_StopParser +

+ +
 enum XML_Status XMLCALL
 XML_StopParser(XML_Parser p,
                XML_Bool resumable);
 
-
- -

Stops parsing, causing XML_Parse or XML_ParseBuffer to return. Must be called from within a -call-back handler, except when aborting (when resumable -is XML_FALSE) an already suspended parser. Some -call-backs may still follow because they would otherwise get -lost, including

-
    -
  • the end element handler for empty elements when stopped in the - start element handler,
  • -
  • the end namespace declaration handler when stopped in the end - element handler,
  • -
  • the character data handler when stopped in the character data handler - while making multiple call-backs on a contiguous chunk of characters,
  • -
-

and possibly others.

- -

This can be called from most handlers, including DTD related -call-backs, except when parsing an external parameter entity and -resumable is XML_TRUE. Returns -XML_STATUS_OK when successful, -XML_STATUS_ERROR otherwise. The possible error codes -are:

-
-
XML_ERROR_NOT_STARTED
-
- when stopping or suspending a parser before it has started, - added in Expat 2.6.4. -
-
XML_ERROR_SUSPENDED
-
when suspending an already suspended parser.
-
XML_ERROR_FINISHED
-
when the parser has already finished.
-
XML_ERROR_SUSPEND_PE
-
when suspending while parsing an external PE.
-
- -

Since the stop/resume feature requires application support in the -outer parsing loop, it is an error to call this function for a parser -not being handled appropriately; see Temporarily Stopping Parsing for more information.

- -

When resumable is XML_TRUE then parsing -is suspended, that is, XML_Parse and XML_ParseBuffer return XML_STATUS_SUSPENDED. -Otherwise, parsing is aborted, that is, XML_Parse and XML_ParseBuffer return -XML_STATUS_ERROR with error code -XML_ERROR_ABORTED.

- -

Note: -This will be applied to the current parser instance only, that is, if -there is a parent parser then it will continue parsing when the -external entity reference handler returns. It is up to the -implementation of that handler to call XML_StopParser on the parent parser -(recursively), if one wants to stop parsing altogether.

+
+

+ Stops parsing, causing XML_Parse or + XML_ParseBuffer to return. Must be + called from within a call-back handler, except when aborting (when + resumable is XML_FALSE) an already suspended parser. + Some call-backs may still follow because they would otherwise get lost, + including +

+ +
    +
  • the end element handler for empty elements when stopped in the start + element handler, +
  • + +
  • the end namespace declaration handler when stopped in the end element + handler, +
  • + +
  • the character data handler when stopped in the character data handler while + making multiple call-backs on a contiguous chunk of characters, +
  • +
+ +

+ and possibly others. +

+ +

+ This can be called from most handlers, including DTD related call-backs, except + when parsing an external parameter entity and resumable is + XML_TRUE. Returns XML_STATUS_OK when successful, + XML_STATUS_ERROR otherwise. The possible error codes are: +

+ +
+
+ XML_ERROR_NOT_STARTED +
+ +
+ when stopping or suspending a parser before it has started, added in Expat + 2.6.4. +
+ +
+ XML_ERROR_SUSPENDED +
+ +
+ when suspending an already suspended parser. +
+ +
+ XML_ERROR_FINISHED +
+ +
+ when the parser has already finished. +
+ +
+ XML_ERROR_SUSPEND_PE +
+ +
+ when suspending while parsing an external PE. +
+
+ +

+ Since the stop/resume feature requires application support in the outer parsing + loop, it is an error to call this function for a parser not being handled + appropriately; see Temporarily Stopping Parsing for + more information. +

+ +

+ When resumable is XML_TRUE then parsing is + suspended, that is, XML_Parse + and XML_ParseBuffer return + XML_STATUS_SUSPENDED. Otherwise, parsing is aborted, that + is, XML_Parse and XML_ParseBuffer return + XML_STATUS_ERROR with error code XML_ERROR_ABORTED. +

+ +

+ Note: This will be applied to the current parser instance + only, that is, if there is a parent parser then it will continue parsing when + the external entity reference handler returns. It is up to the implementation + of that handler to call XML_StopParser on the parent parser (recursively), + if one wants to stop parsing altogether. +

+ +

+ When suspended, parsing can be resumed by calling XML_ResumeParser. +

+ +

+ New in Expat 1.95.8. +

+
+ +

+ XML_ResumeParser +

-

When suspended, parsing can be resumed by calling XML_ResumeParser.

- -

New in Expat 1.95.8.

-
- -

XML_ResumeParser

-
+      
 enum XML_Status XMLCALL
 XML_ResumeParser(XML_Parser p);
 
-
-

Resumes parsing after it has been suspended with XML_StopParser. Must not be called from -within a handler call-back. Returns same status codes as XML_Parse or XML_ParseBuffer. An additional error -code, XML_ERROR_NOT_SUSPENDED, will be returned if the -parser was not currently suspended.

- -

Note: -This must be called on the most deeply nested child parser instance -first, and on its parent parser only after the child parser has -finished, to be applied recursively until the document entity's parser -is restarted. That is, the parent parser will not resume by itself -and it is up to the application to call XML_ResumeParser on it at the -appropriate moment.

- -

New in Expat 1.95.8.

-
+
+

+ Resumes parsing after it has been suspended with XML_StopParser. Must not be called from within a + handler call-back. Returns same status codes as XML_Parse or XML_ParseBuffer. An additional error code, + XML_ERROR_NOT_SUSPENDED, will be returned if the parser was not + currently suspended. +

+ +

+ Note: This must be called on the most deeply nested child + parser instance first, and on its parent parser only after the child parser has + finished, to be applied recursively until the document entity's parser is + restarted. That is, the parent parser will not resume by itself and it is up to + the application to call XML_ResumeParser on it at the appropriate + moment. +

+ +

+ New in Expat 1.95.8. +

+
+ +

+ XML_GetParsingStatus +

-

XML_GetParsingStatus

-
+      
 void XMLCALL
 XML_GetParsingStatus(XML_Parser p,
                      XML_ParsingStatus *status);
 
-
+
+      
 enum XML_Parsing {
   XML_INITIALIZED,
   XML_PARSING,
@@ -1354,244 +1924,322 @@
   XML_Bool finalBuffer;
 } XML_ParsingStatus;
 
-
-

Returns status of parser with respect to being initialized, -parsing, finished, or suspended, and whether the final buffer is being -processed. The status parameter must not be -NULL.

- -

New in Expat 1.95.8.

-
- - -

Handler Setting

- -

Although handlers are typically set prior to parsing and left alone, an -application may choose to set or change the handler for a parsing event -while the parse is in progress. For instance, your application may choose -to ignore all text not descended from a para element. One -way it could do this is to set the character handler when a para start tag -is seen, and unset it for the corresponding end tag.

- -

A handler may be unset by providing a NULL pointer to the -appropriate handler setter. None of the handler setting functions have -a return value.

- -

Your handlers will be receiving strings in arrays of type -XML_Char. This type is conditionally defined in expat.h as -either char, wchar_t or unsigned short. -The former implies UTF-8 encoding, the latter two imply UTF-16 encoding. -Note that you'll receive them in this form independent of the original -encoding of the document.

- -
-

XML_SetStartElementHandler

-
+      
+

+ Returns status of parser with respect to being initialized, parsing, finished, + or suspended, and whether the final buffer is being processed. The + status parameter must not be NULL. +

+ +

+ New in Expat 1.95.8. +

+
+ +

+ Handler Setting +

+ +

+ Although handlers are typically set prior to parsing and left alone, an + application may choose to set or change the handler for a parsing event while the + parse is in progress. For instance, your application may choose to ignore all + text not descended from a para element. One way it could do this is + to set the character handler when a para start tag is seen, and unset it for the + corresponding end tag. +

+ +

+ A handler may be unset by providing a NULL pointer to the + appropriate handler setter. None of the handler setting functions have a return + value. +

+ +

+ Your handlers will be receiving strings in arrays of type XML_Char. + This type is conditionally defined in expat.h as either char, + wchar_t or unsigned short. The former implies UTF-8 + encoding, the latter two imply UTF-16 encoding. Note that you'll receive them in + this form independent of the original encoding of the document. +

+ +
+

+ XML_SetStartElementHandler +

+ +
 void XMLCALL
 XML_SetStartElementHandler(XML_Parser p,
                            XML_StartElementHandler start);
 
-
+
+        
 typedef void
 (XMLCALL *XML_StartElementHandler)(void *userData,
                                    const XML_Char *name,
                                    const XML_Char **atts);
 
-

Set handler for start (and empty) tags. Attributes are passed to the start -handler as a pointer to a vector of char pointers. Each attribute seen in -a start (or empty) tag occupies 2 consecutive places in this vector: the -attribute name followed by the attribute value. These pairs are terminated -by a NULL pointer.

-

Note that an empty tag generates a call to both start and end handlers -(in that order).

-
- -
-

XML_SetEndElementHandler

-
+        

+ Set handler for start (and empty) tags. Attributes are passed to the start + handler as a pointer to a vector of char pointers. Each attribute seen in a + start (or empty) tag occupies 2 consecutive places in this vector: the + attribute name followed by the attribute value. These pairs are terminated by a + NULL pointer. +

+ +

+ Note that an empty tag generates a call to both start and end handlers (in that + order). +

+
+ +
+

+ XML_SetEndElementHandler +

+ +
 void XMLCALL
 XML_SetEndElementHandler(XML_Parser p,
                          XML_EndElementHandler);
 
-
+
+        
 typedef void
 (XMLCALL *XML_EndElementHandler)(void *userData,
                                  const XML_Char *name);
 
-

Set handler for end (and empty) tags. As noted above, an empty tag -generates a call to both start and end handlers.

-
- -
-

XML_SetElementHandler

-
+        

+ Set handler for end (and empty) tags. As noted above, an empty tag generates a + call to both start and end handlers. +

+
+ +
+

+ XML_SetElementHandler +

+ +
 void XMLCALL
 XML_SetElementHandler(XML_Parser p,
                       XML_StartElementHandler start,
                       XML_EndElementHandler end);
 
-

Set handlers for start and end tags with one call.

-
+

+ Set handlers for start and end tags with one call. +

+
+ +
+

+ XML_SetCharacterDataHandler +

-
-

XML_SetCharacterDataHandler

-
+        
 void XMLCALL
 XML_SetCharacterDataHandler(XML_Parser p,
                             XML_CharacterDataHandler charhndl)
 
-
+
+        
 typedef void
 (XMLCALL *XML_CharacterDataHandler)(void *userData,
                                     const XML_Char *s,
                                     int len);
 
-

Set a text handler. The string your handler receives -is NOT null-terminated. You have to use the length argument -to deal with the end of the string. A single block of contiguous text -free of markup may still result in a sequence of calls to this handler. -In other words, if you're searching for a pattern in the text, it may -be split across calls to this handler. Note: Setting this handler to NULL -may NOT immediately terminate call-backs if the parser is currently -processing such a single block of contiguous markup-free text, as the parser -will continue calling back until the end of the block is reached.

-
- -
-

XML_SetProcessingInstructionHandler

-
+        

+ Set a text handler. The string your handler receives is NOT + null-terminated. You have to use the length argument to deal with the end + of the string. A single block of contiguous text free of markup may still + result in a sequence of calls to this handler. In other words, if you're + searching for a pattern in the text, it may be split across calls to this + handler. Note: Setting this handler to NULL may NOT + immediately terminate call-backs if the parser is currently processing + such a single block of contiguous markup-free text, as the parser will continue + calling back until the end of the block is reached. +

+
+ +
+

+ XML_SetProcessingInstructionHandler +

+ +
 void XMLCALL
 XML_SetProcessingInstructionHandler(XML_Parser p,
                                     XML_ProcessingInstructionHandler proc)
 
-
+
+        
 typedef void
 (XMLCALL *XML_ProcessingInstructionHandler)(void *userData,
                                             const XML_Char *target,
                                             const XML_Char *data);
 
 
-

Set a handler for processing instructions. The target is the first word -in the processing instruction. The data is the rest of the characters in -it after skipping all whitespace after the initial word.

-
- -
-

XML_SetCommentHandler

-
+        

+ Set a handler for processing instructions. The target is the first word in the + processing instruction. The data is the rest of the characters in it after + skipping all whitespace after the initial word. +

+
+ +
+

+ XML_SetCommentHandler +

+ +
 void XMLCALL
 XML_SetCommentHandler(XML_Parser p,
                       XML_CommentHandler cmnt)
 
-
+
+        
 typedef void
 (XMLCALL *XML_CommentHandler)(void *userData,
                               const XML_Char *data);
 
-

Set a handler for comments. The data is all text inside the comment -delimiters.

-
- -
-

XML_SetStartCdataSectionHandler

-
+        

+ Set a handler for comments. The data is all text inside the comment delimiters. +

+
+ +
+

+ XML_SetStartCdataSectionHandler +

+ +
 void XMLCALL
 XML_SetStartCdataSectionHandler(XML_Parser p,
                                 XML_StartCdataSectionHandler start);
 
-
+
+        
 typedef void
 (XMLCALL *XML_StartCdataSectionHandler)(void *userData);
 
-

Set a handler that gets called at the beginning of a CDATA section.

-
+

+ Set a handler that gets called at the beginning of a CDATA section. +

+
+ +
+

+ XML_SetEndCdataSectionHandler +

-
-

XML_SetEndCdataSectionHandler

-
+        
 void XMLCALL
 XML_SetEndCdataSectionHandler(XML_Parser p,
                               XML_EndCdataSectionHandler end);
 
-
+
+        
 typedef void
 (XMLCALL *XML_EndCdataSectionHandler)(void *userData);
 
-

Set a handler that gets called at the end of a CDATA section.

-
+

+ Set a handler that gets called at the end of a CDATA section. +

+
+ +
+

+ XML_SetCdataSectionHandler +

-
-

XML_SetCdataSectionHandler

-
+        
 void XMLCALL
 XML_SetCdataSectionHandler(XML_Parser p,
                            XML_StartCdataSectionHandler start,
                            XML_EndCdataSectionHandler end)
 
-

Sets both CDATA section handlers with one call.

-
+

+ Sets both CDATA section handlers with one call. +

+
+ +
+

+ XML_SetDefaultHandler +

-
-

XML_SetDefaultHandler

-
+        
 void XMLCALL
 XML_SetDefaultHandler(XML_Parser p,
                       XML_DefaultHandler hndl)
 
-
+
+        
 typedef void
 (XMLCALL *XML_DefaultHandler)(void *userData,
                               const XML_Char *s,
                               int len);
 
+

+ Sets a handler for any characters in the document which wouldn't otherwise be + handled. This includes both data for which no handlers can be set (like some + kinds of DTD declarations) and data which could be reported but which currently + has no handler set. The characters are passed exactly as they were present in + the XML document except that they will be encoded in UTF-8 or UTF-16. Line + boundaries are not normalized. Note that a byte order mark character is not + passed to the default handler. There are no guarantees about how characters are + divided between calls to the default handler: for example, a comment might be + split between multiple calls. Setting the handler with this call has the side + effect of turning off expansion of references to internally defined general + entities. Instead these references are passed to the default handler. +

+ +

+ See also XML_DefaultCurrent. +

+
+ +
+

+ XML_SetDefaultHandlerExpand +

-

Sets a handler for any characters in the document which wouldn't -otherwise be handled. This includes both data for which no handlers -can be set (like some kinds of DTD declarations) and data which could -be reported but which currently has no handler set. The characters -are passed exactly as they were present in the XML document except -that they will be encoded in UTF-8 or UTF-16. Line boundaries are not -normalized. Note that a byte order mark character is not passed to the -default handler. There are no guarantees about how characters are -divided between calls to the default handler: for example, a comment -might be split between multiple calls. Setting the handler with -this call has the side effect of turning off expansion of references -to internally defined general entities. Instead these references are -passed to the default handler.

- -

See also XML_DefaultCurrent.

-
- -
-

XML_SetDefaultHandlerExpand

-
+        
 void XMLCALL
 XML_SetDefaultHandlerExpand(XML_Parser p,
                             XML_DefaultHandler hndl)
 
-
+
+        
 typedef void
 (XMLCALL *XML_DefaultHandler)(void *userData,
                               const XML_Char *s,
                               int len);
 
-

This sets a default handler, but doesn't inhibit the expansion of -internal entity references. The entity reference will not be passed -to the default handler.

- -

See also XML_DefaultCurrent.

-
- -
-

XML_SetExternalEntityRefHandler

-
+        

+ This sets a default handler, but doesn't inhibit the expansion of internal + entity references. The entity reference will not be passed to the default + handler. +

+ +

+ See also XML_DefaultCurrent. +

+
+ +
+

+ XML_SetExternalEntityRefHandler +

+ +
 void XMLCALL
 XML_SetExternalEntityRefHandler(XML_Parser p,
                                 XML_ExternalEntityRefHandler hndl)
 
-
+
+        
 typedef int
 (XMLCALL *XML_ExternalEntityRefHandler)(XML_Parser p,
                                         const XML_Char *context,
@@ -1599,109 +2247,151 @@
                                         const XML_Char *systemId,
                                         const XML_Char *publicId);
 
-

Set an external entity reference handler. This handler is also -called for processing an external DTD subset if parameter entity parsing -is in effect. (See -XML_SetParamEntityParsing.)

- -

The context parameter specifies the parsing context in -the format expected by the context argument to XML_ExternalEntityParserCreate. code is -valid only until the handler returns, so if the referenced entity is -to be parsed later, it must be copied. context is NULL -only when the entity is a parameter entity, which is how one can -differentiate between general and parameter entities.

- -

The base parameter is the base to use for relative -system identifiers. It is set by XML_SetBase and may be NULL. The -publicId parameter is the public id given in the entity -declaration and may be NULL. systemId is the system -identifier specified in the entity declaration and is never NULL.

- -

There are a couple of ways in which this handler differs from -others. First, this handler returns a status indicator (an -integer). XML_STATUS_OK should be returned for successful -handling of the external entity reference. Returning -XML_STATUS_ERROR indicates failure, and causes the -calling parser to return an -XML_ERROR_EXTERNAL_ENTITY_HANDLING error.

- -

Second, instead of having the user data as its first argument, it -receives the parser that encountered the entity reference. This, along -with the context parameter, may be used as arguments to a call to -XML_ExternalEntityParserCreate. Using the returned -parser, the body of the external entity can be recursively parsed.

- -

Since this handler may be called recursively, it should not be saving -information into global or static variables.

-
+

+ Set an external entity reference handler. This handler is also called for + processing an external DTD subset if parameter entity parsing is in effect. + (See XML_SetParamEntityParsing.) +

+ +

+ Warning: Using an external entity reference handler can lead + to XXE + vulnerabilities. It should only be used in applications that do not parse + untrusted XML input. +

+ +

+ The context parameter specifies the parsing context in the format + expected by the context argument to XML_ExternalEntityParserCreate. + code is valid only until the handler returns, so if the referenced + entity is to be parsed later, it must be copied. context is + NULL only when the entity is a parameter entity, which is how one + can differentiate between general and parameter entities. +

+ +

+ The base parameter is the base to use for relative system + identifiers. It is set by XML_SetBase + and may be NULL. The publicId parameter is the public + id given in the entity declaration and may be NULL. + systemId is the system identifier specified in the entity + declaration and is never NULL. +

+ +

+ There are a couple of ways in which this handler differs from others. First, + this handler returns a status indicator (an integer). + XML_STATUS_OK should be returned for successful handling of the + external entity reference. Returning XML_STATUS_ERROR indicates + failure, and causes the calling parser to return an + XML_ERROR_EXTERNAL_ENTITY_HANDLING error. +

+ +

+ Second, instead of having the user data as its first argument, it receives the + parser that encountered the entity reference. This, along with the context + parameter, may be used as arguments to a call to XML_ExternalEntityParserCreate. + Using the returned parser, the body of the external entity can be recursively + parsed. +

+ +

+ Since this handler may be called recursively, it should not be saving + information into global or static variables. +

+
+ +

+ XML_SetExternalEntityRefHandlerArg +

-

XML_SetExternalEntityRefHandlerArg

-
+      
 void XMLCALL
 XML_SetExternalEntityRefHandlerArg(XML_Parser p,
                                    void *arg)
 
-
-

Set the argument passed to the ExternalEntityRefHandler. If -arg is not NULL, it is the new value passed to the -handler set using XML_SetExternalEntityRefHandler; if arg is -NULL, the argument passed to the handler function will be the parser -object itself.

- -

Note: -The type of arg and the type of the first argument to the -ExternalEntityRefHandler do not match. This function takes a -void * to be passed to the handler, while the handler -accepts an XML_Parser. This is a historical accident, -but will not be corrected before Expat 2.0 (at the earliest) to avoid -causing compiler warnings for code that's known to work with this -API. It is the responsibility of the application code to know the -actual type of the argument passed to the handler and to manage it -properly.

-
- -
-

XML_SetSkippedEntityHandler

-
+      
+

+ Set the argument passed to the ExternalEntityRefHandler. If arg is + not NULL, it is the new value passed to the handler set using + XML_SetExternalEntityRefHandler; + if arg is NULL, the argument passed to the handler + function will be the parser object itself. +

+ +

+ Note: The type of arg and the type of the first + argument to the ExternalEntityRefHandler do not match. This function takes a + void * to be passed to the handler, while the handler accepts an + XML_Parser. This is a historical accident, but will not be + corrected before Expat 2.0 (at the earliest) to avoid causing compiler warnings + for code that's known to work with this API. It is the responsibility of the + application code to know the actual type of the argument passed to the handler + and to manage it properly. +

+
+ +
+

+ XML_SetSkippedEntityHandler +

+ +
 void XMLCALL
 XML_SetSkippedEntityHandler(XML_Parser p,
                             XML_SkippedEntityHandler handler)
 
-
+
+        
 typedef void
 (XMLCALL *XML_SkippedEntityHandler)(void *userData,
                                     const XML_Char *entityName,
                                     int is_parameter_entity);
 
-

Set a skipped entity handler. This is called in two situations:

-
    -
  1. An entity reference is encountered for which no declaration - has been read and this is not an error.
  2. -
  3. An internal entity reference is read, but not expanded, because - XML_SetDefaultHandler - has been called.
  4. -
-

The is_parameter_entity argument will be non-zero for -a parameter entity and zero for a general entity.

Note: Skipped -parameter entities in declarations and skipped general entities in -attribute values cannot be reported, because the event would be out of -sync with the reporting of the declarations or attribute values

-
- -
-

XML_SetUnknownEncodingHandler

-
+        

+ Set a skipped entity handler. This is called in two situations: +

+ +
    +
  1. An entity reference is encountered for which no declaration has been read + and this is not an error. +
  2. + +
  3. An internal entity reference is read, but not expanded, because XML_SetDefaultHandler has been + called. +
  4. +
+ +

+ The is_parameter_entity argument will be non-zero for a parameter + entity and zero for a general entity. +

+ +

+ Note: Skipped parameter entities in declarations and skipped general entities + in attribute values cannot be reported, because the event would be out of sync + with the reporting of the declarations or attribute values +

+
+ +
+

+ XML_SetUnknownEncodingHandler +

+ +
 void XMLCALL
 XML_SetUnknownEncodingHandler(XML_Parser p,
                               XML_UnknownEncodingHandler enchandler,
-			      void *encodingHandlerData)
+                              void *encodingHandlerData)
 
-
+
+        
 typedef int
 (XMLCALL *XML_UnknownEncodingHandler)(void *encodingHandlerData,
                                       const XML_Char *name,
@@ -1714,115 +2404,147 @@
   void (XMLCALL *release)(void *data);
 } XML_Encoding;
 
-

Set a handler to deal with encodings other than the built in set. This should be done before -XML_Parse or XML_ParseBuffer have been called on the -given parser.

If the handler knows how to deal with an encoding -with the given name, it should fill in the info data -structure and return XML_STATUS_OK. Otherwise it -should return XML_STATUS_ERROR. The handler will be called -at most once per parsed (external) entity. The optional application -data pointer encodingHandlerData will be passed back to -the handler.

- -

The map array contains information for every possible leading -byte in a byte sequence. If the corresponding value is >= 0, then it's -a single byte sequence and the byte encodes that Unicode value. If the -value is -1, then that byte is invalid as the initial byte in a sequence. -If the value is -n, where n is an integer > 1, then n is the number of -bytes in the sequence and the actual conversion is accomplished by a -call to the function pointed at by convert. This function may return -1 -if the sequence itself is invalid. The convert pointer may be NULL if -there are only single byte codes. The data parameter passed to the convert -function is the data pointer from XML_Encoding. The -string s is NOT null-terminated and points at the sequence of -bytes to be converted.

- -

The function pointed at by release is called by the -parser when it is finished with the encoding. It may be NULL.

-
- -
-

XML_SetStartNamespaceDeclHandler

-
+        

+ Set a handler to deal with encodings other than the built in set. This should be done before + XML_Parse or XML_ParseBuffer have been called on the given + parser. +

+ +

+ If the handler knows how to deal with an encoding with the given name, it + should fill in the info data structure and return + XML_STATUS_OK. Otherwise it should return + XML_STATUS_ERROR. The handler will be called at most once per + parsed (external) entity. The optional application data pointer + encodingHandlerData will be passed back to the handler. +

+ +

+ The map array contains information for every possible leading byte in a byte + sequence. If the corresponding value is >= 0, then it's a single byte + sequence and the byte encodes that Unicode value. If the value is -1, then that + byte is invalid as the initial byte in a sequence. If the value is -n, where n + is an integer > 1, then n is the number of bytes in the sequence and the + actual conversion is accomplished by a call to the function pointed at by + convert. This function may return -1 if the sequence itself is invalid. The + convert pointer may be NULL if there are only single byte codes. + The data parameter passed to the convert function is the data pointer from + XML_Encoding. The string s is NOT null-terminated and + points at the sequence of bytes to be converted. +

+ +

+ The function pointed at by release is called by the parser when it + is finished with the encoding. It may be NULL. +

+
+ +
+

+ XML_SetStartNamespaceDeclHandler +

+ +
 void XMLCALL
 XML_SetStartNamespaceDeclHandler(XML_Parser p,
-			         XML_StartNamespaceDeclHandler start);
+                                 XML_StartNamespaceDeclHandler start);
 
-
+
+        
 typedef void
 (XMLCALL *XML_StartNamespaceDeclHandler)(void *userData,
                                          const XML_Char *prefix,
                                          const XML_Char *uri);
 
-

Set a handler to be called when a namespace is declared. Namespace -declarations occur inside start tags. But the namespace declaration start -handler is called before the start tag handler for each namespace declared -in that start tag.

-
- -
-

XML_SetEndNamespaceDeclHandler

-
+        

+ Set a handler to be called when a namespace is declared. Namespace declarations + occur inside start tags. But the namespace declaration start handler is called + before the start tag handler for each namespace declared in that start tag. +

+
+ +
+

+ XML_SetEndNamespaceDeclHandler +

+ +
 void XMLCALL
 XML_SetEndNamespaceDeclHandler(XML_Parser p,
-			       XML_EndNamespaceDeclHandler end);
+                               XML_EndNamespaceDeclHandler end);
 
-
+
+        
 typedef void
 (XMLCALL *XML_EndNamespaceDeclHandler)(void *userData,
                                        const XML_Char *prefix);
 
-

Set a handler to be called when leaving the scope of a namespace -declaration. This will be called, for each namespace declaration, -after the handler for the end tag of the element in which the -namespace was declared.

-
- -
-

XML_SetNamespaceDeclHandler

-
+        

+ Set a handler to be called when leaving the scope of a namespace declaration. + This will be called, for each namespace declaration, after the handler for the + end tag of the element in which the namespace was declared. +

+
+ +
+

+ XML_SetNamespaceDeclHandler +

+ +
 void XMLCALL
 XML_SetNamespaceDeclHandler(XML_Parser p,
                             XML_StartNamespaceDeclHandler start,
                             XML_EndNamespaceDeclHandler end)
 
-

Sets both namespace declaration handlers with a single call.

-
+

+ Sets both namespace declaration handlers with a single call. +

+
+ +
+

+ XML_SetXmlDeclHandler +

-
-

XML_SetXmlDeclHandler

-
+        
 void XMLCALL
 XML_SetXmlDeclHandler(XML_Parser p,
-		      XML_XmlDeclHandler xmldecl);
+                      XML_XmlDeclHandler xmldecl);
 
-
+
+        
 typedef void
 (XMLCALL *XML_XmlDeclHandler)(void            *userData,
                               const XML_Char  *version,
                               const XML_Char  *encoding,
                               int             standalone);
 
-

Sets a handler that is called for XML declarations and also for -text declarations discovered in external entities. The way to -distinguish is that the version parameter will be NULL -for text declarations. The encoding parameter may be NULL -for an XML declaration. The standalone argument will -contain -1, 0, or 1 indicating respectively that there was no -standalone parameter in the declaration, that it was given as no, or -that it was given as yes.

-
- -
-

XML_SetStartDoctypeDeclHandler

-
+        

+ Sets a handler that is called for XML declarations and also for text + declarations discovered in external entities. The way to distinguish is that + the version parameter will be NULL for text + declarations. The encoding parameter may be NULL for + an XML declaration. The standalone argument will contain -1, 0, or + 1 indicating respectively that there was no standalone parameter in the + declaration, that it was given as no, or that it was given as yes. +

+
+ +
+

+ XML_SetStartDoctypeDeclHandler +

+ +
 void XMLCALL
 XML_SetStartDoctypeDeclHandler(XML_Parser p,
-			       XML_StartDoctypeDeclHandler start);
+                               XML_StartDoctypeDeclHandler start);
 
-
+
+        
 typedef void
 (XMLCALL *XML_StartDoctypeDeclHandler)(void           *userData,
                                        const XML_Char *doctypeName,
@@ -1830,52 +2552,71 @@
                                        const XML_Char *pubid,
                                        int            has_internal_subset);
 
-

Set a handler that is called at the start of a DOCTYPE declaration, -before any external or internal subset is parsed. Both sysid -and pubid may be NULL. The has_internal_subset -will be non-zero if the DOCTYPE declaration has an internal subset.

-
- -
-

XML_SetEndDoctypeDeclHandler

-
+        

+ Set a handler that is called at the start of a DOCTYPE declaration, before any + external or internal subset is parsed. Both sysid and + pubid may be NULL. The + has_internal_subset will be non-zero if the DOCTYPE declaration + has an internal subset. +

+
+ +
+

+ XML_SetEndDoctypeDeclHandler +

+ +
 void XMLCALL
 XML_SetEndDoctypeDeclHandler(XML_Parser p,
-			     XML_EndDoctypeDeclHandler end);
+                             XML_EndDoctypeDeclHandler end);
 
-
+
+        
 typedef void
 (XMLCALL *XML_EndDoctypeDeclHandler)(void *userData);
 
-

Set a handler that is called at the end of a DOCTYPE declaration, -after parsing any external subset.

-
- -
-

XML_SetDoctypeDeclHandler

-
+        

+ Set a handler that is called at the end of a DOCTYPE declaration, after parsing + any external subset. +

+
+ +
+

+ XML_SetDoctypeDeclHandler +

+ +
 void XMLCALL
 XML_SetDoctypeDeclHandler(XML_Parser p,
-			  XML_StartDoctypeDeclHandler start,
-			  XML_EndDoctypeDeclHandler end);
+                          XML_StartDoctypeDeclHandler start,
+                          XML_EndDoctypeDeclHandler end);
 
-

Set both doctype handlers with one call.

-
+

+ Set both doctype handlers with one call. +

+
+ +
+

+ XML_SetElementDeclHandler +

-
-

XML_SetElementDeclHandler

-
+        
 void XMLCALL
 XML_SetElementDeclHandler(XML_Parser p,
-			  XML_ElementDeclHandler eldecl);
+                          XML_ElementDeclHandler eldecl);
 
-
+
+        
 typedef void
 (XMLCALL *XML_ElementDeclHandler)(void *userData,
                                   const XML_Char *name,
                                   XML_Content *model);
 
-
+
+        
 enum XML_Content_Type {
   XML_CTYPE_EMPTY = 1,
   XML_CTYPE_ANY,
@@ -1895,55 +2636,65 @@
 typedef struct XML_cp XML_Content;
 
 struct XML_cp {
-  enum XML_Content_Type		type;
-  enum XML_Content_Quant	quant;
-  const XML_Char *		name;
-  unsigned int			numchildren;
-  XML_Content *			children;
+  enum XML_Content_Type         type;
+  enum XML_Content_Quant        quant;
+  const XML_Char *              name;
+  unsigned int                  numchildren;
+  XML_Content *                 children;
 };
 
-

Sets a handler for element declarations in a DTD. The handler gets -called with the name of the element in the declaration and a pointer -to a structure that contains the element model. It's the user code's -responsibility to free model when finished with it. See -XML_FreeContentModel. -There is no need to free the model from the handler, it can be kept -around and freed at a later stage.

- -

The model argument is the root of a tree of -XML_Content nodes. If type equals -XML_CTYPE_EMPTY or XML_CTYPE_ANY, then -quant will be XML_CQUANT_NONE, and the other -fields will be zero or NULL. If type is -XML_CTYPE_MIXED, then quant will be -XML_CQUANT_NONE or XML_CQUANT_REP and -numchildren will contain the number of elements that are -allowed to be mixed in and children points to an array of -XML_Content structures that will all have type -XML_CTYPE_NAME with no quantification. Only the root node can be type -XML_CTYPE_EMPTY, XML_CTYPE_ANY, or -XML_CTYPE_MIXED.

- -

For type XML_CTYPE_NAME, the name field -points to the name and the numchildren and -children fields will be zero and NULL. The -quant field will indicate any quantifiers placed on the -name.

- -

Types XML_CTYPE_CHOICE and XML_CTYPE_SEQ -indicate a choice or sequence respectively. The -numchildren field indicates how many nodes in the choice -or sequence and children points to the nodes.

-
- -
-

XML_SetAttlistDeclHandler

-
+        

+ Sets a handler for element declarations in a DTD. The handler gets called with + the name of the element in the declaration and a pointer to a structure that + contains the element model. It's the user code's responsibility to free model + when finished with via a call to XML_FreeContentModel. There is no need to + free the model from the handler, it can be kept around and freed at a later + stage. +

+ +

+ The model argument is the root of a tree of + XML_Content nodes. If type equals + XML_CTYPE_EMPTY or XML_CTYPE_ANY, then + quant will be XML_CQUANT_NONE, and the other fields + will be zero or NULL. If type is + XML_CTYPE_MIXED, then quant will be + XML_CQUANT_NONE or XML_CQUANT_REP and + numchildren will contain the number of elements that are allowed + to be mixed in and children points to an array of + XML_Content structures that will all have type XML_CTYPE_NAME with + no quantification. Only the root node can be type XML_CTYPE_EMPTY, + XML_CTYPE_ANY, or XML_CTYPE_MIXED. +

+ +

+ For type XML_CTYPE_NAME, the name field points to the + name and the numchildren and children fields will be + zero and NULL. The quant field will indicate any + quantifiers placed on the name. +

+ +

+ Types XML_CTYPE_CHOICE and XML_CTYPE_SEQ indicate a + choice or sequence respectively. The numchildren field indicates + how many nodes in the choice or sequence and children points to + the nodes. +

+
+ +
+

+ XML_SetAttlistDeclHandler +

+ +
 void XMLCALL
 XML_SetAttlistDeclHandler(XML_Parser p,
                           XML_AttlistDeclHandler attdecl);
 
-
+
+        
 typedef void
 (XMLCALL *XML_AttlistDeclHandler)(void           *userData,
                                   const XML_Char *elname,
@@ -1952,443 +2703,693 @@
                                   const XML_Char *dflt,
                                   int            isrequired);
 
-

Set a handler for attlist declarations in the DTD. This handler is -called for each attribute. So a single attlist declaration -with multiple attributes declared will generate multiple calls to this -handler. The elname parameter returns the name of the -element for which the attribute is being declared. The attribute name -is in the attname parameter. The attribute type is in the -att_type parameter. It is the string representing the -type in the declaration with whitespace removed.

- -

The dflt parameter holds the default value. It will be -NULL in the case of "#IMPLIED" or "#REQUIRED" attributes. You can -distinguish these two cases by checking the isrequired -parameter, which will be true in the case of "#REQUIRED" attributes. -Attributes which are "#FIXED" will have also have a true -isrequired, but they will have the non-NULL fixed value -in the dflt parameter.

-
- -
-

XML_SetEntityDeclHandler

-
+        

+ Set a handler for attlist declarations in the DTD. This handler is called for + each attribute. So a single attlist declaration with multiple + attributes declared will generate multiple calls to this handler. The + elname parameter returns the name of the element for which the + attribute is being declared. The attribute name is in the attname + parameter. The attribute type is in the att_type parameter. It is + the string representing the type in the declaration with whitespace removed. +

+ +

+ The dflt parameter holds the default value. It will be + NULL in the case of "#IMPLIED" or "#REQUIRED" attributes. You can + distinguish these two cases by checking the isrequired parameter, + which will be true in the case of "#REQUIRED" attributes. Attributes which are + "#FIXED" will have also have a true isrequired, but they will have + the non-NULL fixed value in the dflt parameter. +

+
+ +
+

+ XML_SetEntityDeclHandler +

+ +
 void XMLCALL
 XML_SetEntityDeclHandler(XML_Parser p,
-			 XML_EntityDeclHandler handler);
+                         XML_EntityDeclHandler handler);
 
-
+
+        
 typedef void
 (XMLCALL *XML_EntityDeclHandler)(void           *userData,
                                  const XML_Char *entityName,
                                  int            is_parameter_entity,
                                  const XML_Char *value,
-                                 int            value_length, 
+                                 int            value_length,
                                  const XML_Char *base,
                                  const XML_Char *systemId,
                                  const XML_Char *publicId,
                                  const XML_Char *notationName);
 
-

Sets a handler that will be called for all entity declarations. -The is_parameter_entity argument will be non-zero in the -case of parameter entities and zero otherwise.

- -

For internal entities (<!ENTITY foo "bar">), -value will be non-NULL and systemId, -publicId, and notationName will all be NULL. -The value string is not null-terminated; the length is -provided in the value_length parameter. Do not use -value_length to test for internal entities, since it is -legal to have zero-length values. Instead check for whether or not -value is NULL.

The notationName -argument will have a non-NULL value only for unparsed entity -declarations.

-
- -
-

XML_SetUnparsedEntityDeclHandler

-
+        

+ Sets a handler that will be called for all entity declarations. The + is_parameter_entity argument will be non-zero in the case of + parameter entities and zero otherwise. +

+ +

+ For internal entities (<!ENTITY foo "bar">), + value will be non-NULL and systemId, + publicId, and notationName will all be + NULL. The value string is not null-terminated; the length + is provided in the value_length parameter. Do not use + value_length to test for internal entities, since it is legal to + have zero-length values. Instead check for whether or not value is + NULL. +

+ +

+ The notationName argument will have a non-NULL value + only for unparsed entity declarations. +

+
+ +
+

+ XML_SetUnparsedEntityDeclHandler +

+ +
 void XMLCALL
 XML_SetUnparsedEntityDeclHandler(XML_Parser p,
                                  XML_UnparsedEntityDeclHandler h)
 
-
+
+        
 typedef void
 (XMLCALL *XML_UnparsedEntityDeclHandler)(void *userData,
-                                         const XML_Char *entityName, 
+                                         const XML_Char *entityName,
                                          const XML_Char *base,
                                          const XML_Char *systemId,
                                          const XML_Char *publicId,
                                          const XML_Char *notationName);
 
-

Set a handler that receives declarations of unparsed entities. These -are entity declarations that have a notation (NDATA) field:

+

+ Set a handler that receives declarations of unparsed entities. These are entity + declarations that have a notation (NDATA) field: +

-
+        
+
 <!ENTITY logo SYSTEM "images/logo.gif" NDATA gif>
-
-

This handler is obsolete and is provided for backwards -compatibility. Use instead XML_SetEntityDeclHandler.

-
- -
-

XML_SetNotationDeclHandler

-
+
+
+ +

+ This handler is obsolete and is provided for backwards compatibility. Use + instead XML_SetEntityDeclHandler. +

+
+ +
+

+ XML_SetNotationDeclHandler +

+ +
 void XMLCALL
 XML_SetNotationDeclHandler(XML_Parser p,
                            XML_NotationDeclHandler h)
 
-
+
+        
 typedef void
-(XMLCALL *XML_NotationDeclHandler)(void *userData, 
+(XMLCALL *XML_NotationDeclHandler)(void *userData,
                                    const XML_Char *notationName,
                                    const XML_Char *base,
                                    const XML_Char *systemId,
                                    const XML_Char *publicId);
 
-

Set a handler that receives notation declarations.

-
+

+ Set a handler that receives notation declarations. +

+
+ +
+

+ XML_SetNotStandaloneHandler +

-
-

XML_SetNotStandaloneHandler

-
+        
 void XMLCALL
 XML_SetNotStandaloneHandler(XML_Parser p,
                             XML_NotStandaloneHandler h)
 
-
-typedef int 
+
+        
+typedef int
 (XMLCALL *XML_NotStandaloneHandler)(void *userData);
 
-

Set a handler that is called if the document is not "standalone". -This happens when there is an external subset or a reference to a -parameter entity, but does not have standalone set to "yes" in an XML -declaration. If this handler returns XML_STATUS_ERROR, -then the parser will throw an XML_ERROR_NOT_STANDALONE -error.

-
- -

Parse position and error reporting functions

- -

These are the functions you'll want to call when the parse -functions return XML_STATUS_ERROR (a parse error has -occurred), although the position reporting functions are useful outside -of errors. The position reported is the byte position (in the original -document or entity encoding) of the first of the sequence of -characters that generated the current event (or the error that caused -the parse functions to return XML_STATUS_ERROR.) The -exceptions are callbacks triggered by declarations in the document -prologue, in which case they exact position reported is somewhere in the -relevant markup, but not necessarily as meaningful as for other -events.

- -

The position reporting functions are accurate only outside of the -DTD. In other words, they usually return bogus information when -called from within a DTD declaration handler.

+

+ Set a handler that is called if the document is not "standalone". This happens + when there is an external subset or a reference to a parameter entity, but does + not have standalone set to "yes" in an XML declaration. If this handler returns + XML_STATUS_ERROR, then the parser will throw an + XML_ERROR_NOT_STANDALONE error. +

+
+ +

+ Parse position and error reporting functions +

+ +

+ These are the functions you'll want to call when the parse functions return + XML_STATUS_ERROR (a parse error has occurred), although the position + reporting functions are useful outside of errors. The position reported is the + byte position (in the original document or entity encoding) of the first of the + sequence of characters that generated the current event (or the error that caused + the parse functions to return XML_STATUS_ERROR.) The exceptions are + callbacks triggered by declarations in the document prologue, in which case they + exact position reported is somewhere in the relevant markup, but not necessarily + as meaningful as for other events. +

+ +

+ The position reporting functions are accurate only outside of the DTD. In other + words, they usually return bogus information when called from within a DTD + declaration handler. +

+ +

+ XML_GetErrorCode +

-

XML_GetErrorCode

-
+      
 enum XML_Error XMLCALL
 XML_GetErrorCode(XML_Parser p);
 
-
-Return what type of error has occurred. -
+
+ Return what type of error has occurred. +
+ +

+ XML_ErrorString +

-

XML_ErrorString

-
+      
 const XML_LChar * XMLCALL
 XML_ErrorString(enum XML_Error code);
 
-
-Return a string describing the error corresponding to code. -The code should be one of the enums that can be returned from -XML_GetErrorCode. -
+
+ Return a string describing the error corresponding to code. The code should be + one of the enums that can be returned from XML_GetErrorCode. +
+ +

+ XML_GetCurrentByteIndex +

-

XML_GetCurrentByteIndex

-
+      
 XML_Index XMLCALL
 XML_GetCurrentByteIndex(XML_Parser p);
 
-
-Return the byte offset of the position. This always corresponds to -the values returned by XML_GetCurrentLineNumber and XML_GetCurrentColumnNumber. -
+
+ Return the byte offset of the position. This always corresponds to the values + returned by XML_GetCurrentLineNumber and + XML_GetCurrentColumnNumber. +
+ +

+ XML_GetCurrentLineNumber +

-

XML_GetCurrentLineNumber

-
+      
 XML_Size XMLCALL
 XML_GetCurrentLineNumber(XML_Parser p);
 
-
-Return the line number of the position. The first line is reported as -1. -
+
+ Return the line number of the position. The first line is reported as + 1. +
+ +

+ XML_GetCurrentColumnNumber +

-

XML_GetCurrentColumnNumber

-
+      
 XML_Size XMLCALL
 XML_GetCurrentColumnNumber(XML_Parser p);
 
-
-Return the offset, from the beginning of the current line, of -the position. -
+
+ Return the offset, from the beginning of the current line, of the + position. The first column is reported as 0. +
+ +

+ XML_GetCurrentByteCount +

-

XML_GetCurrentByteCount

-
+      
 int XMLCALL
 XML_GetCurrentByteCount(XML_Parser p);
 
-
-Return the number of bytes in the current event. Returns -0 if the event is inside a reference to an internal -entity and for the end-tag event for empty element tags (the later can -be used to distinguish empty-element tags from empty elements using -separate start and end tags). -
+
+ Return the number of bytes in the current event. Returns 0 if the + event is inside a reference to an internal entity and for the end-tag event for + empty element tags (the later can be used to distinguish empty-element tags from + empty elements using separate start and end tags). +
+ +

+ XML_GetInputContext +

-

XML_GetInputContext

-
+      
 const char * XMLCALL
 XML_GetInputContext(XML_Parser p,
                     int *offset,
                     int *size);
 
-
- -

Returns the parser's input buffer, sets the integer pointed at by -offset to the offset within this buffer of the current -parse position, and set the integer pointed at by size to -the size of the returned buffer.

- -

This should only be called from within a handler during an active -parse and the returned buffer should only be referred to from within -the handler that made the call. This input buffer contains the -untranslated bytes of the input.

- -

Only a limited amount of context is kept, so if the event -triggering a call spans over a very large amount of input, the actual -parse position may be before the beginning of the buffer.

- -

If XML_CONTEXT_BYTES is zero, this will always -return NULL.

-
- -

Attack Protection

+
+

+ Returns the parser's input buffer, sets the integer pointed at by + offset to the offset within this buffer of the current parse + position, and set the integer pointed at by size to the size of + the returned buffer. +

+ +

+ This should only be called from within a handler during an active parse and the + returned buffer should only be referred to from within the handler that made + the call. This input buffer contains the untranslated bytes of the input. +

+ +

+ Only a limited amount of context is kept, so if the event triggering a call + spans over a very large amount of input, the actual parse position may be + before the beginning of the buffer. +

+ +

+ If XML_CONTEXT_BYTES is zero, this will always return + NULL. +

+
+ +

+ Attack Protection +

+ +

+ XML_SetBillionLaughsAttackProtectionMaximumAmplification +

-

XML_SetBillionLaughsAttackProtectionMaximumAmplification

-
+      
 /* Added in Expat 2.4.0. */
 XML_Bool XMLCALL
 XML_SetBillionLaughsAttackProtectionMaximumAmplification(XML_Parser p,
                                                          float maximumAmplificationFactor);
 
-
-

- Sets the maximum tolerated amplification factor - for protection against - billion laughs attacks - (default: 100.0) - of parser p to maximumAmplificationFactor, and - returns XML_TRUE upon success and XML_FALSE upon error. -

- - The amplification factor is calculated as .. -
-    amplification := (direct + indirect) / direct
-  
- .. while parsing, whereas - direct is the number of bytes read from the primary document in parsing and - indirect is the number of bytes added by expanding entities and reading of external DTD files, combined. - -

For a call to XML_SetBillionLaughsAttackProtectionMaximumAmplification to succeed:

-
    -
  • parser p must be a non-NULL root parser (without any parent parsers) and
  • -
  • maximumAmplificationFactor must be non-NaN and greater than or equal to 1.0.
  • -
- -

- Note: - If you ever need to increase this value for non-attack payload, - please file a bug report. -

- -

- Note: - Peak amplifications - of factor 15,000 for the entire payload and - of factor 30,000 in the middle of parsing - have been observed with small benign files in practice. - - So if you do reduce the maximum allowed amplification, - please make sure that the activation threshold is still big enough - to not end up with undesired false positives (i.e. benign files being rejected). -

-
+
+

+ Sets the maximum tolerated amplification factor for protection against billion laughs + attacks (default: 100.0) of parser p to + maximumAmplificationFactor, and returns XML_TRUE upon + success and XML_FALSE upon error. +

+ +

+ Once the threshold for + activation is reached, the amplification factor is calculated as .. +

+ +
amplification := (direct + indirect) / direct
+

+ .. while parsing, whereas direct is the number of bytes read from + the primary document in parsing and indirect is the number of + bytes added by expanding entities and reading of external DTD files, combined. +

+ +

+ For a call to + XML_SetBillionLaughsAttackProtectionMaximumAmplification to + succeed: +

+ +
    +
  • parser p must be a non-NULL root parser (without + any parent parsers) and +
  • + +
  • + maximumAmplificationFactor must be non-NaN and + greater than or equal to 1.0. +
  • +
+ +

+ Note: If you ever need to increase this value for non-attack + payload, please file a + bug report. +

+ +

+ Note: Peak amplifications of factor 15,000 for the entire + payload and of factor 30,000 in the middle of parsing have been observed with + small benign files in practice. So if you do reduce the maximum allowed + amplification, please make sure that the activation threshold is still big + enough to not end up with undesired false positives (i.e. benign files being + rejected). +

+
+ +

+ XML_SetBillionLaughsAttackProtectionActivationThreshold +

-

XML_SetBillionLaughsAttackProtectionActivationThreshold

-
+      
 /* Added in Expat 2.4.0. */
 XML_Bool XMLCALL
 XML_SetBillionLaughsAttackProtectionActivationThreshold(XML_Parser p,
                                                         unsigned long long activationThresholdBytes);
 
-
-

- Sets number of output bytes (including amplification from entity expansion and reading DTD files) - needed to activate protection against - billion laughs attacks - (default: 8 MiB) - of parser p to activationThresholdBytes, and - returns XML_TRUE upon success and XML_FALSE upon error. -

- -

For a call to XML_SetBillionLaughsAttackProtectionActivationThreshold to succeed:

-
    -
  • parser p must be a non-NULL root parser (without any parent parsers).
  • -
- -

- Note: - If you ever need to increase this value for non-attack payload, - please file a bug report. -

- -

- Note: - Activation thresholds below 4 MiB are known to break support for - DITA 1.3 payload - and are hence not recommended. -

-
+
+

+ Sets number of output bytes (including amplification from entity expansion and + reading DTD files) needed to activate protection against billion laughs + attacks (default: 8 MiB) of parser p to + activationThresholdBytes, and returns XML_TRUE upon + success and XML_FALSE upon error. +

+ +

+ For a call to + XML_SetBillionLaughsAttackProtectionActivationThreshold to + succeed: +

+ +
    +
  • parser p must be a non-NULL root parser (without + any parent parsers). +
  • +
+ +

+ Note: If you ever need to increase this value for non-attack + payload, please file a + bug report. +

+ +

+ Note: Activation thresholds below 4 MiB are known to break + support for DITA + 1.3 payload and are hence not recommended. +

+
+ +

+ XML_SetAllocTrackerMaximumAmplification +

+ +
+/* Added in Expat 2.7.2. */
+XML_Bool
+XML_SetAllocTrackerMaximumAmplification(XML_Parser p,
+                                        float maximumAmplificationFactor);
+
+
+

+ Sets the maximum tolerated amplification factor between direct input and bytes + of dynamic memory allocated (default: 100.0) of parser + p to maximumAmplificationFactor, and returns + XML_TRUE upon success and XML_FALSE upon error. +

+ +

+ Note: There are three types of allocations that intentionally + bypass tracking and limiting: +

+ + + +

+ Once the threshold for + activation is reached, the amplification factor is calculated as .. +

+ +
amplification := allocated / direct
+

+ .. while parsing, whereas direct is the number of bytes read from + the primary document in parsing and allocated is the number of + bytes of dynamic memory allocated in the parser hierarchy. +

+ +

+ For a call to XML_SetAllocTrackerMaximumAmplification to succeed: +

+ +
    +
  • parser p must be a non-NULL root parser (without + any parent parsers) and +
  • + +
  • + maximumAmplificationFactor must be non-NaN and + greater than or equal to 1.0. +
  • +
+ +

+ Note: If you ever need to increase this value for non-attack + payload, please file a + bug report. +

+ +

+ Note: Amplifications factors greater than 100.0 + can been observed near the start of parsing even with benign files in practice. + So if you do reduce the maximum allowed amplification, please make sure that + the activation threshold is still big enough to not end up with undesired false + positives (i.e. benign files being rejected). +

+
+ +

+ XML_SetAllocTrackerActivationThreshold +

+ +
+/* Added in Expat 2.7.2. */
+XML_Bool
+XML_SetAllocTrackerActivationThreshold(XML_Parser p,
+                                       unsigned long long activationThresholdBytes);
+
+
+

+ Sets number of allocated bytes of dynamic memory needed to activate protection + against disproportionate use of RAM (default: 64 MiB) of parser + p to activationThresholdBytes, and returns + XML_TRUE upon success and XML_FALSE upon error. +

+ +

+ Note: For types of allocations that intentionally bypass + tracking and limiting, please see XML_SetAllocTrackerMaximumAmplification + above. +

+ +

+ For a call to XML_SetAllocTrackerActivationThreshold to succeed: +

+ +
    +
  • parser p must be a non-NULL root parser (without + any parent parsers). +
  • +
+ +

+ Note: If you ever need to increase this value for non-attack + payload, please file a + bug report. +

+
+ +

+ XML_SetReparseDeferralEnabled +

-

XML_SetReparseDeferralEnabled

-
+      
 /* Added in Expat 2.6.0. */
 XML_Bool XMLCALL
 XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled);
 
-
-

- Large tokens may require many parse calls before enough data is available for Expat to parse it in full. - If Expat retried parsing the token on every parse call, parsing could take quadratic time. - To avoid this, Expat only retries once a significant amount of new data is available. - This function allows disabling this behavior. -

-

- The enabled argument should be XML_TRUE or XML_FALSE. -

-

- Returns XML_TRUE on success, and XML_FALSE on error. -

-
+
+

+ Large tokens may require many parse calls before enough data is available for + Expat to parse it in full. If Expat retried parsing the token on every parse + call, parsing could take quadratic time. To avoid this, Expat only retries once + a significant amount of new data is available. This function allows disabling + this behavior. +

+ +

+ The enabled argument should be XML_TRUE or + XML_FALSE. +

+ +

+ Returns XML_TRUE on success, and XML_FALSE on error. +

+
+ +

+ Miscellaneous functions +

+ +

+ The functions in this section either obtain state information from the parser or + can be used to dynamically set parser options. +

+ +

+ XML_SetUserData +

-

Miscellaneous functions

- -

The functions in this section either obtain state information from -the parser or can be used to dynamically set parser options.

- -

XML_SetUserData

-
+      
 void XMLCALL
 XML_SetUserData(XML_Parser p,
                 void *userData);
 
-
-This sets the user data pointer that gets passed to handlers. It -overwrites any previous value for this pointer. Note that the -application is responsible for freeing the memory associated with -userData when it is finished with the parser. So if you -call this when there's already a pointer there, and you haven't freed -the memory associated with it, then you've probably just leaked -memory. -
+
+ This sets the user data pointer that gets passed to handlers. It overwrites any + previous value for this pointer. Note that the application is responsible for + freeing the memory associated with userData when it is finished with + the parser. So if you call this when there's already a pointer there, and you + haven't freed the memory associated with it, then you've probably just leaked + memory. +
+ +

+ XML_GetUserData +

-

XML_GetUserData

-
+      
 void * XMLCALL
 XML_GetUserData(XML_Parser p);
 
-
-This returns the user data pointer that gets passed to handlers. -It is actually implemented as a macro. -
+
+ This returns the user data pointer that gets passed to handlers. It is actually + implemented as a macro. +
+ +

+ XML_UseParserAsHandlerArg +

-

XML_UseParserAsHandlerArg

-
+      
 void XMLCALL
 XML_UseParserAsHandlerArg(XML_Parser p);
 
-
-After this is called, handlers receive the parser in their -userData arguments. The user data can still be obtained -using the XML_GetUserData function. -
+
+ After this is called, handlers receive the parser in their userData + arguments. The user data can still be obtained using the XML_GetUserData function. +
+ +

+ XML_SetBase +

-

XML_SetBase

-
+      
 enum XML_Status XMLCALL
 XML_SetBase(XML_Parser p,
             const XML_Char *base);
 
-
-Set the base to be used for resolving relative URIs in system -identifiers. The return value is XML_STATUS_ERROR if -there's no memory to store base, otherwise it's -XML_STATUS_OK. -
+
+ Set the base to be used for resolving relative URIs in system identifiers. The + return value is XML_STATUS_ERROR if there's no memory to store base, + otherwise it's XML_STATUS_OK. +
+ +

+ XML_GetBase +

-

XML_GetBase

-
+      
 const XML_Char * XMLCALL
 XML_GetBase(XML_Parser p);
 
-
-Return the base for resolving relative URIs. -
+
+ Return the base for resolving relative URIs. +
+ +

+ XML_GetSpecifiedAttributeCount +

-

XML_GetSpecifiedAttributeCount

-
+      
 int XMLCALL
 XML_GetSpecifiedAttributeCount(XML_Parser p);
 
-
-When attributes are reported to the start handler in the atts vector, -attributes that were explicitly set in the element occur before any -attributes that receive their value from default information in an -ATTLIST declaration. This function returns the number of attributes -that were explicitly set times two, thus giving the offset in the -atts array passed to the start tag handler of the first -attribute set due to defaults. It supplies information for the last -call to a start handler. If called inside a start handler, then that -means the current call. -
+
+ When attributes are reported to the start handler in the atts vector, attributes + that were explicitly set in the element occur before any attributes that receive + their value from default information in an ATTLIST declaration. This function + returns the number of attributes that were explicitly set times two, thus giving + the offset in the atts array passed to the start tag handler of the + first attribute set due to defaults. It supplies information for the last call to + a start handler. If called inside a start handler, then that means the current + call. +
+ +

+ XML_GetIdAttributeIndex +

-

XML_GetIdAttributeIndex

-
+      
 int XMLCALL
 XML_GetIdAttributeIndex(XML_Parser p);
 
-
-Returns the index of the ID attribute passed in the atts array in the -last call to XML_StartElementHandler, or -1 if there is no ID -attribute. If called inside a start handler, then that means the -current call. -
+
+ Returns the index of the ID attribute passed in the atts array in the last call + to XML_StartElementHandler, + or -1 if there is no ID attribute. If called inside a start handler, then that + means the current call. +
+ +

+ XML_GetAttributeInfo +

-

XML_GetAttributeInfo

-
+      
 const XML_AttrInfo * XMLCALL
 XML_GetAttributeInfo(XML_Parser parser);
 
-
+
+      
 typedef struct {
   XML_Index  nameStart;  /* Offset to beginning of the attribute name. */
   XML_Index  nameEnd;    /* Offset after the attribute name's last byte. */
@@ -2396,188 +3397,281 @@
   XML_Index  valueEnd;   /* Offset after the attribute value's last byte. */
 } XML_AttrInfo;
 
-
-Returns an array of XML_AttrInfo structures for the -attribute/value pairs passed in the last call to the -XML_StartElementHandler that were specified -in the start-tag rather than defaulted. Each attribute/value pair counts -as 1; thus the number of entries in the array is -XML_GetSpecifiedAttributeCount(parser) / 2. -
+
+ Returns an array of XML_AttrInfo structures for the attribute/value + pairs passed in the last call to the XML_StartElementHandler that + were specified in the start-tag rather than defaulted. Each attribute/value pair + counts as 1; thus the number of entries in the array is + XML_GetSpecifiedAttributeCount(parser) / 2. +
+ +

+ XML_SetEncoding +

-

XML_SetEncoding

-
+      
 enum XML_Status XMLCALL
 XML_SetEncoding(XML_Parser p,
                 const XML_Char *encoding);
 
-
-Set the encoding to be used by the parser. It is equivalent to -passing a non-NULL encoding argument to the parser creation functions. -It must not be called after XML_Parse or XML_ParseBuffer have been called on the given parser. -Returns XML_STATUS_OK on success or -XML_STATUS_ERROR on error. -
+
+ Set the encoding to be used by the parser. It is equivalent to passing a + non-NULL encoding argument to the parser creation functions. It must + not be called after XML_Parse or + XML_ParseBuffer have been called on + the given parser. Returns XML_STATUS_OK on success or + XML_STATUS_ERROR on error. +
+ +

+ XML_SetParamEntityParsing +

-

XML_SetParamEntityParsing

-
+      
 int XMLCALL
 XML_SetParamEntityParsing(XML_Parser p,
                           enum XML_ParamEntityParsing code);
 
-
-This enables parsing of parameter entities, including the external -parameter entity that is the external DTD subset, according to -code. -The choices for code are: -
    -
  • XML_PARAM_ENTITY_PARSING_NEVER
  • -
  • XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE
  • -
  • XML_PARAM_ENTITY_PARSING_ALWAYS
  • -
-Note: If XML_SetParamEntityParsing is called after -XML_Parse or XML_ParseBuffer, then it has -no effect and will always return 0. -
+
+ This enables parsing of parameter entities, including the external parameter + entity that is the external DTD subset, according to code. The + choices for code are: +
    +
  • + XML_PARAM_ENTITY_PARSING_NEVER +
  • + +
  • + XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE +
  • + +
  • + XML_PARAM_ENTITY_PARSING_ALWAYS +
  • +
+ Note: If XML_SetParamEntityParsing is called after + XML_Parse or XML_ParseBuffer, then it has no effect and + will always return 0. +
+ +

+ XML_SetHashSalt (deprecated) +

-

XML_SetHashSalt

-
+      
 int XMLCALL
-XML_SetHashSalt(XML_Parser p,
+XML_SetHashSalt(XML_Parser parser,
                 unsigned long hash_salt);
 
-
-Sets the hash salt to use for internal hash calculations. -Helps in preventing DoS attacks based on predicting hash -function behavior. In order to have an effect this must be called -before parsing has started. Returns 1 if successful, 0 when called -after XML_Parse or XML_ParseBuffer. -

Note: This call is optional, as the parser will auto-generate -a new random salt value if no value has been set at the start of parsing.

-

Note: One should not call XML_SetHashSalt with a -hash salt value of 0, as this value is used as sentinel value to indicate -that XML_SetHashSalt has not been called. Consequently -such a call will have no effect, even if it returns 1.

-
+
+ Sets the hash salt to use for internal hash calculations. Helps in preventing DoS + attacks based on predicting hash function behavior. In order to have an effect + this must be called before parsing has started. Returns 1 if successful, 0 when + called after XML_Parse or XML_ParseBuffer or when + parser is NULL. +

+ Note: Function XML_SetHashSalt is + deprecated. Please use function XML_SetHashSalt16Bytes instead for better + security. XML_SetHashSalt only provides 4 to 8 bytes of entropy + (depending on the size of type unsigned long) while the SipHash + implementation used by Expat can leverage up to 16 bytes of entropy — at least + twice as much. Function XML_SetHashSalt16Bytes of Expat >=2.8.0 + (and where backported) matches the amount of entropy supported by SipHash. +

+ +

+ Note: This call is optional, as the parser will auto-generate a new + random salt value internally if no value has been set by the start of parsing. +

+ +

+ Note: One should not call XML_SetHashSalt with a hash salt + value of 0, as this value is used as sentinel value to indicate that + XML_SetHashSalt has not been called. Consequently such a + call will have no effect, even if it returns 1. +

+
+ +

+ XML_SetHashSalt16Bytes +

-

XML_UseForeignDTD

-
+      
+/* Added in Expat 2.8.0. */
+XML_Bool XMLCALL
+XML_SetHashSalt16Bytes(XML_Parser parser,
+                       const uint8_t entropy[16]);
+
+
+ Sets the hash salt to use for internal hash calculations. Helps in preventing DoS + attacks based on predicting hash function behavior. In order to have an effect + this must be called before parsing has started. Returns XML_TRUE if + successful, XML_FALSE when called after XML_Parse or + XML_ParseBuffer or when parser is NULL. +

+ Note: Setting a salt that is not from a source of high quality + entropy (like getentropy(3)) will make the parser vulnerable to + hash flooding attacks. +

+ +

+ Note: This call is optional, as the parser will auto-generate a new + random salt value internally if no value has been set by the start of parsing. +

+
+ +

+ XML_UseForeignDTD +

+ +
 enum XML_Error XMLCALL
 XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD);
 
-
-

This function allows an application to provide an external subset -for the document type declaration for documents which do not specify -an external subset of their own. For documents which specify an -external subset in their DOCTYPE declaration, the application-provided -subset will be ignored. If the document does not contain a DOCTYPE -declaration at all and useDTD is true, the -application-provided subset will be parsed, but the -startDoctypeDeclHandler and -endDoctypeDeclHandler functions, if set, will not be -called. The setting of parameter entity parsing, controlled using -XML_SetParamEntityParsing, will be honored.

- -

The application-provided external subset is read by calling the -external entity reference handler set via XML_SetExternalEntityRefHandler with both -publicId and systemId set to NULL.

- -

If this function is called after parsing has begun, it returns -XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING and ignores -useDTD. If called when Expat has been compiled without -DTD support, it returns -XML_ERROR_FEATURE_REQUIRES_XML_DTD. Otherwise, it -returns XML_ERROR_NONE.

- -

Note: For the purpose of checking WFC: Entity Declared, passing -useDTD == XML_TRUE will make the parser behave as if -the document had a DTD with an external subset. This holds true even if -the external entity reference handler returns without action.

-
+
+

+ This function allows an application to provide an external subset for the + document type declaration for documents which do not specify an external subset + of their own. For documents which specify an external subset in their DOCTYPE + declaration, the application-provided subset will be ignored. If the document + does not contain a DOCTYPE declaration at all and useDTD is true, + the application-provided subset will be parsed, but the + startDoctypeDeclHandler and endDoctypeDeclHandler + functions, if set, will not be called. The setting of parameter entity parsing, + controlled using XML_SetParamEntityParsing, will be + honored. +

+ +

+ The application-provided external subset is read by calling the external entity + reference handler set via XML_SetExternalEntityRefHandler + with both publicId and systemId set to + NULL. +

+ +

+ If this function is called after parsing has begun, it returns + XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING and ignores + useDTD. If called when Expat has been compiled without DTD + support, it returns XML_ERROR_FEATURE_REQUIRES_XML_DTD. Otherwise, + it returns XML_ERROR_NONE. +

+ +

+ Note: For the purpose of checking WFC: Entity Declared, passing + useDTD == XML_TRUE will make the parser behave as if the document + had a DTD with an external subset. This holds true even if the external entity + reference handler returns without action. +

+
+ +

+ XML_SetReturnNSTriplet +

-

XML_SetReturnNSTriplet

-
+      
 void XMLCALL
 XML_SetReturnNSTriplet(XML_Parser parser,
                        int        do_nst);
 
-
-

-This function only has an effect when using a parser created with -XML_ParserCreateNS, -i.e. when namespace processing is in effect. The do_nst -sets whether or not prefixes are returned with names qualified with a -namespace prefix. If this function is called with do_nst -non-zero, then afterwards namespace qualified names (that is qualified -with a prefix as opposed to belonging to a default namespace) are -returned as a triplet with the three parts separated by the namespace -separator specified when the parser was created. The order of -returned parts is URI, local name, and prefix.

If -do_nst is zero, then namespaces are reported in the -default manner, URI then local_name separated by the namespace -separator.

-
+
+

+ This function only has an effect when using a parser created with + XML_ParserCreateNS, i.e. when + namespace processing is in effect. The do_nst sets whether or not + prefixes are returned with names qualified with a namespace prefix. If this + function is called with do_nst non-zero, then afterwards namespace + qualified names (that is qualified with a prefix as opposed to belonging to a + default namespace) are returned as a triplet with the three parts separated by + the namespace separator specified when the parser was created. The order of + returned parts is URI, local name, and prefix. +

+ +

+ If do_nst is zero, then namespaces are reported in the default + manner, URI then local_name separated by the namespace separator. +

+
+ +

+ XML_DefaultCurrent +

-

XML_DefaultCurrent

-
+      
 void XMLCALL
 XML_DefaultCurrent(XML_Parser parser);
 
-
-This can be called within a handler for a start element, end element, -processing instruction or character data. It causes the corresponding -markup to be passed to the default handler set by XML_SetDefaultHandler or -XML_SetDefaultHandlerExpand. It does nothing if there is -not a default handler. -
+
+ This can be called within a handler for a start element, end element, processing + instruction or character data. It causes the corresponding markup to be passed to + the default handler set by XML_SetDefaultHandler or XML_SetDefaultHandlerExpand. It does + nothing if there is not a default handler. +
+ +

+ XML_ExpatVersion +

-

XML_ExpatVersion

-
+      
 XML_LChar * XMLCALL
 XML_ExpatVersion();
 
-
-Return the library version as a string (e.g. "expat_1.95.1"). -
+
+ Return the library version as a string (e.g. "expat_1.95.1"). +
+ +

+ XML_ExpatVersionInfo +

-

XML_ExpatVersionInfo

-
+      
 struct XML_Expat_Version XMLCALL
 XML_ExpatVersionInfo();
 
-
+
+      
 typedef struct {
   int major;
   int minor;
   int micro;
 } XML_Expat_Version;
 
-
-Return the library version information as a structure. -Some macros are also defined that support compile-time tests of the -library version: -
    -
  • XML_MAJOR_VERSION
  • -
  • XML_MINOR_VERSION
  • -
  • XML_MICRO_VERSION
  • -
-Testing these constants is currently the best way to determine if -particular parts of the Expat API are available. -
+
+ Return the library version information as a structure. Some macros are also + defined that support compile-time tests of the library version: +
    +
  • + XML_MAJOR_VERSION +
  • + +
  • + XML_MINOR_VERSION +
  • + +
  • + XML_MICRO_VERSION +
  • +
+ Testing these constants is currently the best way to determine if particular + parts of the Expat API are available. +
+ +

+ XML_GetFeatureList +

-

XML_GetFeatureList

-
+      
 const XML_Feature * XMLCALL
 XML_GetFeatureList();
 
-
+
+      
 enum XML_FeatureEnum {
   XML_FEATURE_END = 0,
   XML_FEATURE_UNICODE,
@@ -2597,114 +3691,140 @@
   long int              value;
 } XML_Feature;
 
-
-

Returns a list of "feature" records, providing details on how -Expat was configured at compile time. Most applications should not -need to worry about this, but this information is otherwise not -available from Expat. This function allows code that does need to -check these features to do so at runtime.

- -

The return value is an array of XML_Feature, -terminated by a record with a feature of -XML_FEATURE_END and name of NULL, -identifying the feature-test macros Expat was compiled with. Since an -application that requires this kind of information needs to determine -the type of character the name points to, records for the -XML_FEATURE_SIZEOF_XML_CHAR and -XML_FEATURE_SIZEOF_XML_LCHAR will be located at the -beginning of the list, followed by XML_FEATURE_UNICODE -and XML_FEATURE_UNICODE_WCHAR_T, if they are present at -all.

- -

Some features have an associated value. If there isn't an -associated value, the value field is set to 0. At this -time, the following features have been defined to have values:

- -
-
XML_FEATURE_SIZEOF_XML_CHAR
-
The number of bytes occupied by one XML_Char - character.
-
XML_FEATURE_SIZEOF_XML_LCHAR
-
The number of bytes occupied by one XML_LChar - character.
-
XML_FEATURE_CONTEXT_BYTES
-
The maximum number of characters of context which can be - reported by XML_GetInputContext.
-
-
+
+

+ Returns a list of "feature" records, providing details on how Expat was + configured at compile time. Most applications should not need to worry about + this, but this information is otherwise not available from Expat. This function + allows code that does need to check these features to do so at runtime. +

+ +

+ The return value is an array of XML_Feature, terminated by a + record with a feature of XML_FEATURE_END and + name of NULL, identifying the feature-test macros + Expat was compiled with. Since an application that requires this kind of + information needs to determine the type of character the name + points to, records for the XML_FEATURE_SIZEOF_XML_CHAR and + XML_FEATURE_SIZEOF_XML_LCHAR will be located at the beginning of + the list, followed by XML_FEATURE_UNICODE and + XML_FEATURE_UNICODE_WCHAR_T, if they are present at all. +

+ +

+ Some features have an associated value. If there isn't an associated value, the + value field is set to 0. At this time, the following features have + been defined to have values: +

+ +
+
+ XML_FEATURE_SIZEOF_XML_CHAR +
+ +
+ The number of bytes occupied by one XML_Char character. +
+ +
+ XML_FEATURE_SIZEOF_XML_LCHAR +
+ +
+ The number of bytes occupied by one XML_LChar character. +
+ +
+ XML_FEATURE_CONTEXT_BYTES +
+ +
+ The maximum number of characters of context which can be reported by + XML_GetInputContext. +
+
+
+ +

+ XML_FreeContentModel +

-

XML_FreeContentModel

-
+      
 void XMLCALL
 XML_FreeContentModel(XML_Parser parser, XML_Content *model);
 
-
-Function to deallocate the model argument passed to the -XML_ElementDeclHandler callback set using XML_ElementDeclHandler. -This function should not be used for any other purpose. -
- -

The following functions allow external code to share the memory -allocator an XML_Parser has been configured to use. This -is especially useful for third-party libraries that interact with a -parser object created by application code, or heavily layered -applications. This can be essential when using dynamically loaded -libraries which use different C standard libraries (this can happen on -Windows, at least).

+
+ Function to deallocate the model argument passed to the + XML_ElementDeclHandler callback set using XML_ElementDeclHandler. This function + should not be used for any other purpose. +
+ +

+ The following functions allow external code to share the memory allocator an + XML_Parser has been configured to use. This is especially useful for + third-party libraries that interact with a parser object created by application + code, or heavily layered applications. This can be essential when using + dynamically loaded libraries which use different C standard libraries (this can + happen on Windows, at least). +

+ +

+ XML_MemMalloc +

-

XML_MemMalloc

-
+      
 void * XMLCALL
 XML_MemMalloc(XML_Parser parser, size_t size);
 
-
-Allocate size bytes of memory using the allocator the -parser object has been configured to use. Returns a -pointer to the memory or NULL on failure. Memory allocated in this -way must be freed using XML_MemFree. -
+
+ Allocate size bytes of memory using the allocator the + parser object has been configured to use. Returns a pointer to the + memory or NULL on failure. Memory allocated in this way must be + freed using XML_MemFree. +
+ +

+ XML_MemRealloc +

-

XML_MemRealloc

-
+      
 void * XMLCALL
 XML_MemRealloc(XML_Parser parser, void *ptr, size_t size);
 
-
-Allocate size bytes of memory using the allocator the -parser object has been configured to use. -ptr must point to a block of memory allocated by XML_MemMalloc or -XML_MemRealloc, or be NULL. This function tries to -expand the block pointed to by ptr if possible. Returns -a pointer to the memory or NULL on failure. On success, the original -block has either been expanded or freed. On failure, the original -block has not been freed; the caller is responsible for freeing the -original block. Memory allocated in this way must be freed using -XML_MemFree. -
+
+ Allocate size bytes of memory using the allocator the + parser object has been configured to use. ptr must + point to a block of memory allocated by XML_MemMalloc or XML_MemRealloc, or be + NULL. This function tries to expand the block pointed to by + ptr if possible. Returns a pointer to the memory or + NULL on failure. On success, the original block has either been + expanded or freed. On failure, the original block has not been freed; the caller + is responsible for freeing the original block. Memory allocated in this way must + be freed using XML_MemFree. +
+ +

+ XML_MemFree +

-

XML_MemFree

-
+      
 void XMLCALL
 XML_MemFree(XML_Parser parser, void *ptr);
 
-
-Free a block of memory pointed to by ptr. The block must -have been allocated by XML_MemMalloc or XML_MemRealloc, or be NULL. -
- -
- - - -
- +
+ Free a block of memory pointed to by ptr. The block must have been + allocated by XML_MemMalloc or + XML_MemRealloc, or be NULL. +
+ +
+ + + + diff -Nru expat-2.7.1/expat/doc/xmlwf.xml expat-2.8.2/expat/doc/xmlwf.xml --- expat-2.7.1/expat/doc/xmlwf.xml 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/doc/xmlwf.xml 2026-06-25 14:07:00.000000000 +0000 @@ -9,7 +9,7 @@ Copyright (c) 2001 Scott Bronson Copyright (c) 2002-2003 Fred L. Drake, Jr. Copyright (c) 2009 Karl Waclawek - Copyright (c) 2016-2025 Sebastian Pipping + Copyright (c) 2016-2026 Sebastian Pipping Copyright (c) 2016 Ardo van Rangelrooij Copyright (c) 2017 Rhodri James Copyright (c) 2020 Joe Orton @@ -21,7 +21,7 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [ Scott"> Bronson"> - March 27, 2025"> + June 25, 2026"> 1"> bronson@rinspin.com"> @@ -29,8 +29,8 @@ XMLWF"> - Debian GNU/Linux"> GNU"> + Debian &gnu;/Linux"> ]> @@ -84,73 +84,77 @@ DESCRIPTION - &dhpackage; uses the Expat library to - determine if an XML document is well-formed. It is - non-validating. - - - - If you do not specify any files on the command-line, and you - have a recent version of &dhpackage;, the - input file will be read from standard input. - + &dhpackage; uses the Expat library to + determine if an XML document is well-formed. It is + non-validating. + + + If you do not specify any files on the command-line, and you + have a recent version of &dhpackage;, the + input file will be read from standard input. + WELL-FORMED DOCUMENTS - - - A well-formed document must adhere to the - following rules: - - - - - The file begins with an XML declaration. For instance, - <?xml version="1.0" standalone="yes"?>. - NOTE: - &dhpackage; does not currently - check for a valid XML declaration. - - - Every start tag is either empty (<tag/>) - or has a corresponding end tag. - - - There is exactly one root element. This element must contain - all other elements in the document. Only comments, white - space, and processing instructions may come after the close - of the root element. - - - All elements nest properly. - - - All attribute values are enclosed in quotes (either single - or double). - + + A well-formed document must adhere to the + following rules: + + + + + The file begins with an XML declaration. For instance, + <?xml version="1.0" standalone="yes"?>. + NOTE: + &dhpackage; does not currently + check for a valid XML declaration. + + + + + Every start tag is either empty (<tag/>) + or has a corresponding end tag. + + + + + There is exactly one root element. This element must contain + all other elements in the document. Only comments, white + space, and processing instructions may come after the close + of the root element. + + + + + All elements nest properly. + + + + + All attribute values are enclosed in quotes (either single + or double). + + - - - If the document has a DTD, and it strictly complies with that - DTD, then the document is also considered valid. - &dhpackage; is a non-validating parser -- - it does not check the DTD. However, it does support - external entities (see the option). - + + If the document has a DTD, and it strictly complies with that + DTD, then the document is also considered valid. + &dhpackage; is a non-validating parser -- + it does not check the DTD. However, it does support + external entities (see the option). + OPTIONS - - -When an option includes an argument, you may specify the argument either -separately (" output") or concatenated with the -option ("output"). &dhpackage; -supports both. - - + + When an option includes an argument, you may specify the argument either + separately (" output") or concatenated with the + option ("output"). &dhpackage; + supports both. + @@ -158,19 +162,31 @@ Sets the maximum tolerated amplification factor - for protection against billion laughs attacks (default: 100.0). + for protection against amplification attacks + like the billion laughs attack + (default: 100.0 + for the sum of direct and indirect output and also + for allocations of dynamic memory). The amplification factor is calculated as .. - amplification := (direct + indirect) / direct + amplification := (direct + indirect) / direct + + + .. with regard to use of entities and .. + + + amplification := allocated / direct - .. while parsing, whereas + .. with regard to dynamic memory while parsing. <direct> is the number of bytes read - from the primary document in parsing and + from the primary document in parsing, <indirect> is the number of bytes added by expanding entities and reading of external DTD files, - combined. + combined, and + <allocated> is the total number of bytes of dynamic memory + allocated (and not freed) per hierarchy of parsers. NOTE: @@ -185,8 +201,10 @@ Sets the number of output bytes (including amplification) - needed to activate protection against billion laughs attacks - (default: 8 MiB). + needed to activate protection against amplification attacks + like billion laughs + (default: 8 MiB for the sum of direct and indirect output, + and 64 MiB for allocations of dynamic memory). This can be thought of as an "activation threshold". @@ -200,60 +218,60 @@ - - If the input file is well-formed and &dhpackage; - doesn't encounter any errors, the input file is simply copied to - the output directory unchanged. - This implies no namespaces (turns off ) and - requires to specify an output directory. - + + If the input file is well-formed and &dhpackage; + doesn't encounter any errors, the input file is simply copied to + the output directory unchanged. + This implies no namespaces (turns off ) and + requires to specify an output directory. + output-dir - - Specifies a directory to contain transformed - representations of the input files. - By default, outputs a canonical representation - (described below). - You can select different output formats using , - and . - - - The output filenames will - be exactly the same as the input filenames or "STDIN" if the input is - coming from standard input. Therefore, you must be careful that the - output file does not go into the same directory as the input - file. Otherwise, &dhpackage; will delete the - input file before it generates the output file (just like running - cat < file > file in most shells). - - - Two structurally equivalent XML documents have a byte-for-byte - identical canonical XML representation. - Note that ignorable white space is considered significant and - is treated equivalently to data. - More on canonical XML can be found at - http://www.jclark.com/xml/canonxml.html . - + + Specifies a directory to contain transformed + representations of the input files. + By default, outputs a canonical representation + (described below). + You can select different output formats using , + and . + + + The output filenames will + be exactly the same as the input filenames or "STDIN" if the input is + coming from standard input. Therefore, you must be careful that the + output file does not go into the same directory as the input + file. Otherwise, &dhpackage; will delete the + input file before it generates the output file (just like running + cat < file > file in most shells). + + + Two structurally equivalent XML documents have a byte-for-byte + identical canonical XML representation. + Note that ignorable white space is considered significant and + is treated equivalently to data. + More on canonical XML can be found at + http://www.jclark.com/xml/canonxml.html . + encoding - - Specifies the character encoding for the document, overriding - any document encoding declaration. &dhpackage; - supports four built-in encodings: - US-ASCII, - UTF-8, - UTF-16, and - ISO-8859-1. - Also see the option. - + + Specifies the character encoding for the document, overriding + any document encoding declaration. &dhpackage; + supports four built-in encodings: + US-ASCII, + UTF-8, + UTF-16, and + ISO-8859-1. + Also see the option. + @@ -298,21 +316,21 @@ - - Outputs some strange sort of XML file that completely - describes the input file, including character positions. - Requires to specify an output file. - + + Outputs some strange sort of XML file that completely + describes the input file, including character positions. + Requires to specify an output file. + - - Turns on namespace processing. (describe namespaces) - disables namespaces. - + + Turns on namespace processing. (describe namespaces) + disables namespaces. + @@ -320,9 +338,9 @@ - Adds a doctype and notation declarations to canonical XML output. - This matches the example output used by the formal XML test cases. - Requires to specify an output file. + Adds a doctype and notation declarations to canonical XML output. + This matches the example output used by the formal XML test cases. + Requires to specify an output file. @@ -330,15 +348,15 @@ - - Tells &dhpackage; to process external DTDs and parameter - entities. - - - Normally &dhpackage; never parses parameter - entities. tells it to always parse them. - implies . - + + Tells &dhpackage; to process external DTDs and parameter + entities. + + + Normally &dhpackage; never parses parameter + entities. tells it to always parse them. + implies . + @@ -355,47 +373,47 @@ - - Normally &dhpackage; memory-maps the XML file - before parsing; this can result in faster parsing on many - platforms. - turns off memory-mapping and uses normal file - IO calls instead. - Of course, memory-mapping is automatically turned off - when reading from standard input. - - - Use of memory-mapping can cause some platforms to report - substantially higher memory usage for - &dhpackage;, but this appears to be a matter of - the operating system reporting memory in a strange way; there is - not a leak in &dhpackage;. - + + Normally &dhpackage; memory-maps the XML file + before parsing; this can result in faster parsing on many + platforms. + turns off memory-mapping and uses normal file + IO calls instead. + Of course, memory-mapping is automatically turned off + when reading from standard input. + + + Use of memory-mapping can cause some platforms to report + substantially higher memory usage for + &dhpackage;, but this appears to be a matter of + the operating system reporting memory in a strange way; there is + not a leak in &dhpackage;. + - - Prints an error if the document is not standalone. - A document is standalone if it has no external subset and no - references to parameter entities. - + + Prints an error if the document is not standalone. + A document is standalone if it has no external subset and no + references to parameter entities. + - - Turns on timings. This tells Expat to parse the entire file, - but not perform any processing. - This gives a fairly accurate idea of the raw speed of Expat itself - without client overhead. - turns off most of the output options - (, , , ...). - + + Turns on timings. This tells Expat to parse the entire file, + but not perform any processing. + This gives a fairly accurate idea of the raw speed of Expat itself + without client overhead. + turns off most of the output options + (, , , ...). + @@ -403,104 +421,102 @@ - - Prints the version of the Expat library being used, including some - information on the compile-time configuration of the library, and - then exits. - + + Prints the version of the Expat library being used, including some + information on the compile-time configuration of the library, and + then exits. + - - Enables support for Windows code pages. - Normally, &dhpackage; will throw an error if it - runs across an encoding that it is not equipped to handle itself. With - , &dhpackage; will try to use a Windows code - page. See also . - + + Enables support for Windows code pages. + Normally, &dhpackage; will throw an error if it + runs across an encoding that it is not equipped to handle itself. With + , &dhpackage; will try to use a Windows code + page. See also . + - - Turns on parsing external entities. - - - Non-validating parsers are not required to resolve external - entities, or even expand entities at all. - Expat always expands internal entities (?), - but external entity parsing must be enabled explicitly. - - - External entities are simply entities that obtain their - data from outside the XML file currently being parsed. - - - This is an example of an internal entity: - + + Turns on parsing external entities. + (CAREFUL! This makes xmlwf vulnerable to external entity attacks (XXE).) + + + Non-validating parsers are not required to resolve external + entities, or even expand entities at all. + Expat always expands internal entities (?), + but external entity parsing must be enabled explicitly. + + + External entities are simply entities that obtain their + data from outside the XML file currently being parsed. + + + This is an example of an internal entity: + <!ENTITY vers '1.0.2'> - - - - And here are some examples of external entities: + + + + And here are some examples of external entities: - + <!ENTITY header SYSTEM "header-&vers;.xml"> (parsed) <!ENTITY logo SYSTEM "logo.png" PNG> (unparsed) - - - + + - - (Two hyphens.) - Terminates the list of options. This is only needed if a filename - starts with a hyphen. For example: - - + + (Two hyphens.) + Terminates the list of options. This is only needed if a filename + starts with a hyphen. For example: + + &dhpackage; -- -myfile.xml - - - will run &dhpackage; on the file - -myfile.xml. - + + + will run &dhpackage; on the file + -myfile.xml. + - - - Older versions of &dhpackage; do not support - reading from standard input. - + + Older versions of &dhpackage; do not support + reading from standard input. + - OUTPUT - - &dhpackage; outputs nothing for files which are problem-free. - If any input file is not well-formed, or if the output for any - input file cannot be opened, &dhpackage; prints a single - line describing the problem to standard output. + OUTPUT + &dhpackage; outputs nothing for files which are problem-free. + If any input file is not well-formed, or if the output for any + input file cannot be opened, &dhpackage; prints a single + line describing the problem to standard output. - If the option is not provided, &dhpackage; - halts upon encountering a well-formedness or output-file error. - If is provided, &dhpackage; continues - processing the remaining input files, describing problems found with any of them. + If the option is not provided, &dhpackage; + halts upon encountering a well-formedness or output-file error. + If is provided, &dhpackage; continues + processing the remaining input files, describing problems found with any of them. - EXIT STATUS + EXIT STATUS For options | or |, &dhpackage; always exits with status code 0. For other cases, the following exit status codes are returned: @@ -529,39 +545,37 @@ - + BUGS - - The errors should go to standard error, not standard output. - - - There should be a way to get to send its - output to standard output rather than forcing the user to send - it to a file. - - - I have no idea why anyone would want to use the - , , and - options. If someone could explain it to - me, I'd like to add this information to this manpage. - + + The errors should go to standard error, not standard output. + + + There should be a way to get to send its + output to standard output rather than forcing the user to send + it to a file. + + + I have no idea why anyone would want to use the + , , and + options. If someone could explain it to + me, I'd like to add this information to this manpage. + SEE ALSO - - - + + The Expat home page: https://libexpat.github.io/ The W3 XML 1.0 specification (fourth edition): https://www.w3.org/TR/2006/REC-xml-20060816/ Billion laughs attack: https://en.wikipedia.org/wiki/Billion_laughs_attack - - - + + @@ -571,8 +585,8 @@ in December 2001 for the &debian; system (but may be used by others). Permission is granted to copy, distribute and/or modify this document under - the terms of the GNU Free Documentation + the terms of the &gnu; Free Documentation License, Version 1.1. - + diff -Nru expat-2.7.1/expat/examples/element_declarations.c expat-2.8.2/expat/examples/element_declarations.c --- expat-2.7.1/expat/examples/element_declarations.c 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/examples/element_declarations.c 2026-06-25 14:07:00.000000000 +0000 @@ -16,6 +16,7 @@ Copyright (c) 2017 Rhodri James Copyright (c) 2019 Zhongyuan Zhou Copyright (c) 2024 Hanno Böck + Copyright (c) 2026 Matthew Fernandez Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -82,7 +83,7 @@ return newStackTop; } -static char * +static const char * contentTypeName(enum XML_Content_Type contentType) { switch (contentType) { case XML_CTYPE_EMPTY: @@ -102,7 +103,7 @@ } } -static char * +static const char * contentQuantName(enum XML_Content_Quant contentQuant) { switch (contentQuant) { case XML_CQUANT_NONE: diff -Nru expat-2.7.1/expat/expat_config.h.cmake expat-2.8.2/expat/expat_config.h.cmake --- expat-2.7.1/expat/expat_config.h.cmake 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/expat_config.h.cmake 2026-06-25 14:07:00.000000000 +0000 @@ -1,7 +1,7 @@ /* expat_config.h.cmake. Based upon generated expat_config.h.in. */ #ifndef EXPAT_CONFIG_H -#define EXPAT_CONFIG_H 1 +# define EXPAT_CONFIG_H 1 /* 1234 = LIL_ENDIAN, 4321 = BIGENDIAN */ #cmakedefine BYTEORDER @BYTEORDER@ @@ -24,12 +24,12 @@ /* Define to 1 if you have the `getrandom' function. */ #cmakedefine HAVE_GETRANDOM +/* Define to 1 if you have the `getentropy' function. */ +#cmakedefine HAVE_GETENTROPY + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_INTTYPES_H -/* Define to 1 if you have the `bsd' library (-lbsd). */ -#cmakedefine HAVE_LIBBSD - /* Define to 1 if you have the header file. */ #cmakedefine HAVE_MEMORY_H @@ -61,7 +61,7 @@ #cmakedefine HAVE_UNISTD_H /* Name of package */ -#define PACKAGE "@PACKAGE_NAME@" +# define PACKAGE "@PACKAGE_NAME@" /* Define to the address where bug reports for this package should be sent. */ #cmakedefine PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" @@ -76,15 +76,15 @@ #cmakedefine PACKAGE_TARNAME "@PACKAGE_TARNAME@" /* Define to the home page for this package. */ -#define PACKAGE_URL "" +# define PACKAGE_URL "" /* Define to the version of this package. */ #cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@" /* Define to 1 if you have the ANSI C header files. */ -#ifndef STDC_HEADERS +# ifndef STDC_HEADERS #cmakedefine STDC_HEADERS -#endif +# endif /* whether byteorder is bigendian */ #cmakedefine WORDS_BIGENDIAN @@ -95,26 +95,26 @@ /* Define to specify how much context to retain around the current parse point, 0 to disable. */ -#define XML_CONTEXT_BYTES @XML_CONTEXT_BYTES@ +# define XML_CONTEXT_BYTES @XML_CONTEXT_BYTES@ -#if ! defined(_WIN32) +# if ! defined(_WIN32) /* Define to include code reading entropy from `/dev/urandom'. */ #cmakedefine XML_DEV_URANDOM -#endif +# endif /* Define to make parameter entity parsing functionality available. */ #cmakedefine XML_DTD /* Define as 1/0 to enable/disable support for general entities. */ -#define XML_GE @XML_GE@ +# define XML_GE @XML_GE@ /* Define to make XML Namespaces functionality available. */ #cmakedefine XML_NS /* Define to __FUNCTION__ or "" if `__func__' does not conform to ANSI C. */ -#ifdef _MSC_VER -# define __func__ __FUNCTION__ -#endif +# ifdef _MSC_VER +# define __func__ __FUNCTION__ +# endif /* Define to `long' if does not define. */ #cmakedefine off_t @off_t@ diff -Nru expat-2.7.1/expat/fix-xmltest-log.sh expat-2.8.2/expat/fix-xmltest-log.sh --- expat-2.7.1/expat/fix-xmltest-log.sh 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/fix-xmltest-log.sh 2026-06-25 14:07:00.000000000 +0000 @@ -6,7 +6,7 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2019-2022 Sebastian Pipping +# Copyright (c) 2019-2026 Sebastian Pipping # Copyright (c) 2024 Dag-Erling Smørgrav # Licensed under the MIT license: # @@ -31,9 +31,10 @@ set -e +sed="$(type -P gsed sed false | head -n 1)" # e.g. for Solaris filename="${1:-tests/xmltest.log}" -sed -i.bak \ +exec "${sed}" -i.bak \ -e '# convert DOS line endings to Unix without resorting to dos2unix' \ -e $'s/\r//' \ \ diff -Nru expat-2.7.1/expat/fuzz/xml_lpm_fuzzer.cpp expat-2.8.2/expat/fuzz/xml_lpm_fuzzer.cpp --- expat-2.7.1/expat/fuzz/xml_lpm_fuzzer.cpp 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/fuzz/xml_lpm_fuzzer.cpp 2026-06-25 14:07:00.000000000 +0000 @@ -354,8 +354,10 @@ if (g_external_entity) { XML_Parser ext_parser = XML_ExternalEntityParserCreate(parser, context, g_encoding); - rc = Parse(ext_parser, g_external_entity, g_external_entity_size, 1); - XML_ParserFree(ext_parser); + if (ext_parser != NULL) { + rc = Parse(ext_parser, g_external_entity, g_external_entity_size, 1); + XML_ParserFree(ext_parser); + } } return rc; diff -Nru expat-2.7.1/expat/fuzz/xml_parse_fuzzer.c expat-2.8.2/expat/fuzz/xml_parse_fuzzer.c --- expat-2.7.1/expat/fuzz/xml_parse_fuzzer.c 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/fuzz/xml_parse_fuzzer.c 2026-06-25 14:07:00.000000000 +0000 @@ -15,6 +15,7 @@ */ #include +#include // for INT_MAX #include #include "expat.h" @@ -65,8 +66,9 @@ XML_SetUserData(p, p); XML_SetElementHandler(p, start, end); XML_SetCharacterDataHandler(p, may_stop_character_handler); - XML_Parse(p, (const XML_Char *)data, size, 0); - if (XML_Parse(p, (const XML_Char *)data, size, 1) == XML_STATUS_ERROR) { + assert(size <= INT_MAX); + XML_Parse(p, (const XML_Char *)data, (int)size, 0); + if (XML_Parse(p, (const XML_Char *)data, (int)size, 1) == XML_STATUS_ERROR) { XML_ErrorString(XML_GetErrorCode(p)); } XML_GetCurrentLineNumber(p); @@ -89,15 +91,17 @@ XML_Parser externalEntityParser = XML_ExternalEntityParserCreate(parentParser, "e1", NULL); - assert(externalEntityParser); - ParseOneInput(externalEntityParser, data, size); - XML_ParserFree(externalEntityParser); + if (externalEntityParser != NULL) { + ParseOneInput(externalEntityParser, data, size); + XML_ParserFree(externalEntityParser); + } XML_Parser externalDtdParser = XML_ExternalEntityParserCreate(parentParser, NULL, NULL); - assert(externalDtdParser); - ParseOneInput(externalDtdParser, data, size); - XML_ParserFree(externalDtdParser); + if (externalDtdParser != NULL) { + ParseOneInput(externalDtdParser, data, size); + XML_ParserFree(externalDtdParser); + } // finally frees this parser which served as parent XML_ParserFree(parentParser); diff -Nru expat-2.7.1/expat/fuzz/xml_parsebuffer_fuzzer.c expat-2.8.2/expat/fuzz/xml_parsebuffer_fuzzer.c --- expat-2.7.1/expat/fuzz/xml_parsebuffer_fuzzer.c 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/fuzz/xml_parsebuffer_fuzzer.c 2026-06-25 14:07:00.000000000 +0000 @@ -15,6 +15,7 @@ */ #include +#include // for INT_MAX #include #include @@ -66,16 +67,17 @@ XML_SetUserData(p, p); XML_SetElementHandler(p, start, end); XML_SetCharacterDataHandler(p, may_stop_character_handler); - void *buf = XML_GetBuffer(p, size); + assert(size <= INT_MAX); + void *buf = XML_GetBuffer(p, (int)size); assert(buf); memcpy(buf, data, size); - XML_ParseBuffer(p, size, 0); - buf = XML_GetBuffer(p, size); + XML_ParseBuffer(p, (int)size, 0); + buf = XML_GetBuffer(p, (int)size); if (buf == NULL) { return; } memcpy(buf, data, size); - if (XML_ParseBuffer(p, size, 1) == XML_STATUS_ERROR) { + if (XML_ParseBuffer(p, (int)size, 1) == XML_STATUS_ERROR) { XML_ErrorString(XML_GetErrorCode(p)); } XML_GetCurrentLineNumber(p); @@ -101,15 +103,17 @@ XML_Parser externalEntityParser = XML_ExternalEntityParserCreate(parentParser, "e1", NULL); - assert(externalEntityParser); - ParseOneInput(externalEntityParser, data, size); - XML_ParserFree(externalEntityParser); + if (externalEntityParser != NULL) { + ParseOneInput(externalEntityParser, data, size); + XML_ParserFree(externalEntityParser); + } XML_Parser externalDtdParser = XML_ExternalEntityParserCreate(parentParser, NULL, NULL); - assert(externalDtdParser); - ParseOneInput(externalDtdParser, data, size); - XML_ParserFree(externalDtdParser); + if (externalDtdParser != NULL) { + ParseOneInput(externalDtdParser, data, size); + XML_ParserFree(externalDtdParser); + } // finally frees this parser which served as parent XML_ParserFree(parentParser); diff -Nru expat-2.7.1/expat/lib/Makefile.am expat-2.8.2/expat/lib/Makefile.am --- expat-2.7.1/expat/lib/Makefile.am 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/lib/Makefile.am 2026-06-25 14:07:00.000000000 +0000 @@ -6,9 +6,12 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2017-2024 Sebastian Pipping +# Copyright (c) 2017-2026 Sebastian Pipping # Copyright (c) 2017 Tomasz Kłoczko # Copyright (c) 2019 David Loffredo +# Copyright (c) 2026 Gordon Messmer +# Copyright (c) 2026 Nick Begg +# Copyright (c) 2026 Matthew Fernandez # Licensed under the MIT license: # # Permission is hereby granted, free of charge, to any person obtaining @@ -45,12 +48,51 @@ @LIBM@ \ -no-undefined \ -version-info @LIBCURRENT@:@LIBREVISION@:@LIBAGE@ +if HAVE_VSCRIPT +libexpat_la_LDFLAGS += $(VSCRIPT_LDFLAGS),@builddir@/libexpat.map +endif libexpat_la_SOURCES = \ xmlparse.c \ xmltok.c \ xmlrole.c +if WITH_ARC4RANDOM + libexpat_la_SOURCES += \ + random_arc4random.c \ + random_arc4random.h +endif + +if WITH_ARC4RANDOM_BUF + libexpat_la_SOURCES += \ + random_arc4random_buf.c \ + random_arc4random_buf.h +endif + +if ! MINGW + libexpat_la_SOURCES += \ + random_dev_urandom.c \ + random_dev_urandom.h +endif + +if WITH_GETENTROPY + libexpat_la_SOURCES += \ + random_getentropy.c \ + random_getentropy.h +endif + +if WITH_EITHER_GETRANDOM + libexpat_la_SOURCES += \ + random_getrandom.c \ + random_getrandom.h +endif + +if MINGW + libexpat_la_SOURCES += \ + random_rand_s.c \ + random_rand_s.h +endif + if WITH_TESTS libtestpat_la_CPPFLAGS = -DXML_TESTING @@ -72,14 +114,17 @@ asciitab.h \ expat_external.h \ expat.h \ + fallthrough.h \ iasciitab.h \ internal.h \ latin1tab.h \ libexpat.def.cmake \ + memory_sanitizer.h \ nametab.h \ siphash.h \ utf8tab.h \ winconfig.h \ + xcsinc.c \ xmlrole.h \ xmltok.h \ xmltok_impl.c \ diff -Nru expat-2.7.1/expat/lib/expat.h expat-2.8.2/expat/lib/expat.h --- expat-2.7.1/expat/lib/expat.h 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/lib/expat.h 2026-06-25 14:07:00.000000000 +0000 @@ -11,7 +11,7 @@ Copyright (c) 2000-2005 Fred L. Drake, Jr. Copyright (c) 2001-2002 Greg Stein Copyright (c) 2002-2016 Karl Waclawek - Copyright (c) 2016-2025 Sebastian Pipping + Copyright (c) 2016-2026 Sebastian Pipping Copyright (c) 2016 Cristian Rodríguez Copyright (c) 2016 Thomas Beutlich Copyright (c) 2017 Rhodri James @@ -19,6 +19,7 @@ Copyright (c) 2023 Hanno Böck Copyright (c) 2023 Sony Corporation / Snild Dolkow Copyright (c) 2024 Taichi Haradaguchi <20001722@ymail.ne.jp> + Copyright (c) 2025 Matthew Fernandez Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -42,21 +43,22 @@ */ #ifndef Expat_INCLUDED -#define Expat_INCLUDED 1 +# define Expat_INCLUDED 1 -#include -#include "expat_external.h" +# include // for uint8_t +# include +# include "expat_external.h" -#ifdef __cplusplus +# ifdef __cplusplus extern "C" { -#endif +# endif struct XML_ParserStruct; typedef struct XML_ParserStruct *XML_Parser; typedef unsigned char XML_Bool; -#define XML_TRUE ((XML_Bool)1) -#define XML_FALSE ((XML_Bool)0) +# define XML_TRUE ((XML_Bool)1) +# define XML_FALSE ((XML_Bool)0) /* The XML_Status enum gives the possible return values for several API functions. The preprocessor #defines are included so this @@ -73,11 +75,11 @@ */ enum XML_Status { XML_STATUS_ERROR = 0, -#define XML_STATUS_ERROR XML_STATUS_ERROR +# define XML_STATUS_ERROR XML_STATUS_ERROR XML_STATUS_OK = 1, -#define XML_STATUS_OK XML_STATUS_OK +# define XML_STATUS_OK XML_STATUS_OK XML_STATUS_SUSPENDED = 2 -#define XML_STATUS_SUSPENDED XML_STATUS_SUSPENDED +# define XML_STATUS_SUSPENDED XML_STATUS_SUSPENDED }; enum XML_Error { @@ -276,7 +278,7 @@ /* Prepare a parser object to be reused. This is particularly valuable when memory allocation overhead is disproportionately high, - such as when a large number of small documnents need to be parsed. + such as when a large number of small documents need to be parsed. All handlers are cleared from the parser, except for the unknownEncodingHandler. The parser's external state is re-initialized except for the values of ns and ns_triplets. @@ -680,7 +682,7 @@ XML_SetUserData(XML_Parser parser, void *userData); /* Returns the last value set by XML_SetUserData or NULL. */ -#define XML_GetUserData(parser) (*(void **)(parser)) +# define XML_GetUserData(parser) (*(void **)(parser)) /* This is equivalent to supplying an encoding argument to XML_ParserCreate. On success XML_SetEncoding returns non-zero, @@ -752,7 +754,7 @@ XMLPARSEAPI(int) XML_GetIdAttributeIndex(XML_Parser parser); -#ifdef XML_ATTR_INFO +# ifdef XML_ATTR_INFO /* Source file byte offsets for the start and end of attribute names and values. The value indices are exclusive of surrounding quotes; thus in a UTF-8 source file an attribute value of "blah" will yield: @@ -773,7 +775,7 @@ */ XMLPARSEAPI(const XML_AttrInfo *) XML_GetAttributeInfo(XML_Parser parser); -#endif +# endif /* Parses some input. Returns XML_STATUS_ERROR if a fatal error is detected. The last call to XML_Parse must have isFinal true; len @@ -916,10 +918,21 @@ function behavior. This must be called before parsing is started. Returns 1 if successful, 0 when called after parsing has started. Note: If parser == NULL, the function will do nothing and return 0. + DEPRECATED since Expat 2.8.0. */ XMLPARSEAPI(int) XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt); +/* Sets the hash salt to use for internal hash calculations. + Helps in preventing DoS attacks based on predicting hash function behavior. + This must be called before parsing is started. + Returns XML_TRUE if successful, XML_FALSE when called after parsing has + started or when parser is NULL. + Added in Expat 2.8.0. +*/ +XMLPARSEAPI(XML_Bool) +XML_SetHashSalt16Bytes(XML_Parser parser, const uint8_t entropy[16]); + /* If XML_Parse or XML_ParseBuffer have returned XML_STATUS_ERROR, then XML_GetErrorCode returns information about the error. */ @@ -970,9 +983,9 @@ XML_GetInputContext(XML_Parser parser, int *offset, int *size); /* For backwards compatibility with previous versions. */ -#define XML_GetErrorLineNumber XML_GetCurrentLineNumber -#define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber -#define XML_GetErrorByteIndex XML_GetCurrentByteIndex +# define XML_GetErrorLineNumber XML_GetCurrentLineNumber +# define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber +# define XML_GetErrorByteIndex XML_GetCurrentByteIndex /* Frees the content model passed to the element declaration handler */ XMLPARSEAPI(void) @@ -1032,7 +1045,10 @@ XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT, XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT, /* Added in Expat 2.6.0. */ - XML_FEATURE_GE + XML_FEATURE_GE, + /* Added in Expat 2.7.2. */ + XML_FEATURE_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION_DEFAULT, + XML_FEATURE_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT, /* Additional features must be added to the end of this enum. */ }; @@ -1045,7 +1061,7 @@ XMLPARSEAPI(const XML_Feature *) XML_GetFeatureList(void); -#if defined(XML_DTD) || (defined(XML_GE) && XML_GE == 1) +# if defined(XML_DTD) || (defined(XML_GE) && XML_GE == 1) /* Added in Expat 2.4.0 for XML_DTD defined and * added in Expat 2.6.0 for XML_GE == 1. */ XMLPARSEAPI(XML_Bool) @@ -1057,7 +1073,17 @@ XMLPARSEAPI(XML_Bool) XML_SetBillionLaughsAttackProtectionActivationThreshold( XML_Parser parser, unsigned long long activationThresholdBytes); -#endif + +/* Added in Expat 2.7.2. */ +XMLPARSEAPI(XML_Bool) +XML_SetAllocTrackerMaximumAmplification(XML_Parser parser, + float maximumAmplificationFactor); + +/* Added in Expat 2.7.2. */ +XMLPARSEAPI(XML_Bool) +XML_SetAllocTrackerActivationThreshold( + XML_Parser parser, unsigned long long activationThresholdBytes); +# endif /* Added in Expat 2.6.0. */ XMLPARSEAPI(XML_Bool) @@ -1066,12 +1092,12 @@ /* Expat follows the semantic versioning convention. See https://semver.org */ -#define XML_MAJOR_VERSION 2 -#define XML_MINOR_VERSION 7 -#define XML_MICRO_VERSION 1 +# define XML_MAJOR_VERSION 2 +# define XML_MINOR_VERSION 8 +# define XML_MICRO_VERSION 2 -#ifdef __cplusplus +# ifdef __cplusplus } -#endif +# endif #endif /* not Expat_INCLUDED */ diff -Nru expat-2.7.1/expat/lib/expat_external.h expat-2.8.2/expat/lib/expat_external.h --- expat-2.7.1/expat/lib/expat_external.h 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/lib/expat_external.h 2026-06-25 14:07:00.000000000 +0000 @@ -12,9 +12,10 @@ Copyright (c) 2001-2002 Greg Stein Copyright (c) 2002-2006 Karl Waclawek Copyright (c) 2016 Cristian Rodríguez - Copyright (c) 2016-2019 Sebastian Pipping + Copyright (c) 2016-2025 Sebastian Pipping Copyright (c) 2017 Rhodri James Copyright (c) 2018 Yury Gribov + Copyright (c) 2026 Matthew Fernandez Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -38,14 +39,14 @@ */ #ifndef Expat_External_INCLUDED -#define Expat_External_INCLUDED 1 +# define Expat_External_INCLUDED 1 /* External API definitions */ /* Expat tries very hard to make the API boundary very specifically defined. There are two macros defined to control this boundary; each of these can be defined before including this header to - achieve some different behavior, but doing so it not recommended or + achieve some different behavior, but doing so is not recommended or tested frequently. XMLCALL - The calling convention to use for all calls across the @@ -64,12 +65,12 @@ compiled with the cdecl calling convention as the default since system headers may assume the cdecl convention. */ -#ifndef XMLCALL -# if defined(_MSC_VER) -# define XMLCALL __cdecl -# elif defined(__GNUC__) && defined(__i386) && ! defined(__INTEL_COMPILER) -# define XMLCALL __attribute__((cdecl)) -# else +# ifndef XMLCALL +# if defined(_MSC_VER) +# define XMLCALL __cdecl +# elif defined(__GNUC__) && defined(__i386) && ! defined(__INTEL_COMPILER) +# define XMLCALL __attribute__((cdecl)) +# else /* For any platform which uses this definition and supports more than one calling convention, we need to extend this definition to declare the convention used on that platform, if it's possible to @@ -80,86 +81,86 @@ pre-processor and how to specify the same calling convention as the platform's malloc() implementation. */ -# define XMLCALL -# endif -#endif /* not defined XMLCALL */ +# define XMLCALL +# endif +# endif /* not defined XMLCALL */ -#if ! defined(XML_STATIC) && ! defined(XMLIMPORT) -# ifndef XML_BUILDING_EXPAT +# if ! defined(XML_STATIC) && ! defined(XMLIMPORT) +# ifndef XML_BUILDING_EXPAT /* using Expat from an application */ -# if defined(_MSC_EXTENSIONS) && ! defined(__BEOS__) && ! defined(__CYGWIN__) -# define XMLIMPORT __declspec(dllimport) +# if defined(_MSC_VER) && ! defined(__BEOS__) && ! defined(__CYGWIN__) +# define XMLIMPORT __declspec(dllimport) +# endif + # endif +# endif /* not defined XML_STATIC */ +# ifndef XML_ENABLE_VISIBILITY +# define XML_ENABLE_VISIBILITY 0 # endif -#endif /* not defined XML_STATIC */ -#ifndef XML_ENABLE_VISIBILITY -# define XML_ENABLE_VISIBILITY 0 -#endif - -#if ! defined(XMLIMPORT) && XML_ENABLE_VISIBILITY -# define XMLIMPORT __attribute__((visibility("default"))) -#endif +# if ! defined(XMLIMPORT) && XML_ENABLE_VISIBILITY +# define XMLIMPORT __attribute__((visibility("default"))) +# endif /* If we didn't define it above, define it away: */ -#ifndef XMLIMPORT -# define XMLIMPORT -#endif - -#if defined(__GNUC__) \ - && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)) -# define XML_ATTR_MALLOC __attribute__((__malloc__)) -#else -# define XML_ATTR_MALLOC -#endif - -#if defined(__GNUC__) \ - && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) -# define XML_ATTR_ALLOC_SIZE(x) __attribute__((__alloc_size__(x))) -#else -# define XML_ATTR_ALLOC_SIZE(x) -#endif - -#define XMLPARSEAPI(type) XMLIMPORT type XMLCALL +# ifndef XMLIMPORT +# define XMLIMPORT +# endif -#ifdef __cplusplus -extern "C" { -#endif +# if defined(__GNUC__) \ + && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)) +# define XML_ATTR_MALLOC __attribute__((__malloc__)) +# else +# define XML_ATTR_MALLOC +# endif -#ifdef XML_UNICODE_WCHAR_T -# ifndef XML_UNICODE -# define XML_UNICODE +# if defined(__GNUC__) \ + && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) +# define XML_ATTR_ALLOC_SIZE(x) __attribute__((__alloc_size__(x))) +# else +# define XML_ATTR_ALLOC_SIZE(x) # endif -# if defined(__SIZEOF_WCHAR_T__) && (__SIZEOF_WCHAR_T__ != 2) -# error "sizeof(wchar_t) != 2; Need -fshort-wchar for both Expat and libc" + +# define XMLPARSEAPI(type) XMLIMPORT type XMLCALL + +# ifdef __cplusplus +extern "C" { # endif -#endif -#ifdef XML_UNICODE /* Information is UTF-16 encoded. */ # ifdef XML_UNICODE_WCHAR_T +# ifndef XML_UNICODE +# define XML_UNICODE +# endif +# if defined(__SIZEOF_WCHAR_T__) && (__SIZEOF_WCHAR_T__ != 2) +# error "sizeof(wchar_t) != 2; Need -fshort-wchar for both Expat and libc" +# endif +# endif + +# ifdef XML_UNICODE /* Information is UTF-16 encoded. */ +# ifdef XML_UNICODE_WCHAR_T typedef wchar_t XML_Char; typedef wchar_t XML_LChar; -# else +# else typedef unsigned short XML_Char; typedef char XML_LChar; -# endif /* XML_UNICODE_WCHAR_T */ -#else /* Information is UTF-8 encoded. */ +# endif /* XML_UNICODE_WCHAR_T */ +# else /* Information is UTF-8 encoded. */ typedef char XML_Char; typedef char XML_LChar; -#endif /* XML_UNICODE */ +# endif /* XML_UNICODE */ -#ifdef XML_LARGE_SIZE /* Use large integers for file/stream positions. */ +# ifdef XML_LARGE_SIZE /* Use large integers for file/stream positions. */ typedef long long XML_Index; typedef unsigned long long XML_Size; -#else +# else typedef long XML_Index; typedef unsigned long XML_Size; -#endif /* XML_LARGE_SIZE */ +# endif /* XML_LARGE_SIZE */ -#ifdef __cplusplus +# ifdef __cplusplus } -#endif +# endif #endif /* not Expat_External_INCLUDED */ diff -Nru expat-2.7.1/expat/lib/fallthrough.h expat-2.8.2/expat/lib/fallthrough.h --- expat-2.7.1/expat/lib/fallthrough.h 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/expat/lib/fallthrough.h 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,49 @@ +/* + __ __ _ + ___\ \/ /_ __ __ _| |_ + / _ \\ /| '_ \ / _` | __| + | __// \| |_) | (_| | |_ + \___/_/\_\ .__/ \__,_|\__| + |_| XML parser + + Copyright (c) 2026 Nick Begg + Licensed under the MIT license: + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the + following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef FALLTHROUGH_H +# define FALLTHROUGH_H 1 + +// Explicit fallthrough in switch case to avoid warnings +// with compiler flag -Wimplicit-fallthrough. + +# define EXPAT_FALLTHROUGH \ + do { \ + } while (0) + +# if defined(__has_attribute) +# if __has_attribute(fallthrough) +# undef EXPAT_FALLTHROUGH +# define EXPAT_FALLTHROUGH __attribute__((fallthrough)) +# endif +# endif + +#endif // FALLTHROUGH_H diff -Nru expat-2.7.1/expat/lib/internal.h expat-2.8.2/expat/lib/internal.h --- expat-2.7.1/expat/lib/internal.h 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/lib/internal.h 2026-06-25 14:07:00.000000000 +0000 @@ -28,7 +28,7 @@ Copyright (c) 2002-2003 Fred L. Drake, Jr. Copyright (c) 2002-2006 Karl Waclawek Copyright (c) 2003 Greg Stein - Copyright (c) 2016-2025 Sebastian Pipping + Copyright (c) 2016-2026 Sebastian Pipping Copyright (c) 2018 Yury Gribov Copyright (c) 2019 David Loffredo Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow @@ -108,10 +108,12 @@ #endif #include // ULONG_MAX +#include // size_t #if defined(_WIN32) \ && (! defined(__USE_MINGW_ANSI_STDIO) \ || (1 - __USE_MINGW_ANSI_STDIO - 1 == 0)) +# define EXPAT_FMT_LLX(midpart) "%" midpart "I64x" # define EXPAT_FMT_ULL(midpart) "%" midpart "I64u" # if defined(_WIN64) // Note: modifiers "td" and "zu" do not work for MinGW # define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "I64d" @@ -121,13 +123,14 @@ # define EXPAT_FMT_SIZE_T(midpart) "%" midpart "u" # endif #else +# define EXPAT_FMT_LLX(midpart) "%" midpart "llx" # define EXPAT_FMT_ULL(midpart) "%" midpart "llu" # if ! defined(ULONG_MAX) # error Compiler did not define ULONG_MAX for us # elif ULONG_MAX == 18446744073709551615u // 2^64-1 # define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "ld" # define EXPAT_FMT_SIZE_T(midpart) "%" midpart "lu" -# elif defined(EMSCRIPTEN) // 32bit mode Emscripten +# elif defined(__wasm32__) // 32bit mode Emscripten or WASI SDK # define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "ld" # define EXPAT_FMT_SIZE_T(midpart) "%" midpart "zu" # else @@ -148,6 +151,16 @@ 100.0f #define EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT \ 8388608 // 8 MiB, 2^23 + +#define EXPAT_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION_DEFAULT 100.0f +#define EXPAT_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT \ + 67108864 // 64 MiB, 2^26 + +// NOTE: If function expat_alloc was user facing, EXPAT_MALLOC_ALIGNMENT would +// have to take sizeof(long double) into account +#define EXPAT_MALLOC_ALIGNMENT sizeof(long long) // largest parser (sub)member +#define EXPAT_MALLOC_PADDING ((EXPAT_MALLOC_ALIGNMENT) - sizeof(size_t)) + /* NOTE END */ #include "expat.h" // so we can use type XML_Parser below @@ -171,6 +184,9 @@ #endif XML_Bool g_reparseDeferralEnabledDefault; // written ONLY in runtests.c #if defined(XML_TESTING) +void *expat_malloc(XML_Parser parser, size_t size, int sourceLine); +void expat_free(XML_Parser parser, void *ptr, int sourceLine); +void *expat_realloc(XML_Parser parser, void *ptr, size_t size, int sourceLine); extern unsigned int g_bytesScanned; // used for testing only #endif diff -Nru expat-2.7.1/expat/lib/libexpat.def.cmake expat-2.8.2/expat/lib/libexpat.def.cmake --- expat-2.7.1/expat/lib/libexpat.def.cmake 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/lib/libexpat.def.cmake 2026-06-25 14:07:00.000000000 +0000 @@ -1,6 +1,7 @@ ; DEF file for MS VC++ EXPORTS +; added some time before version 1.95.4 XML_DefaultCurrent @1 XML_ErrorString @2 XML_ExpatVersion @3 @@ -55,8 +56,8 @@ XML_SetUserData @52 XML_SetXmlDeclHandler @53 XML_UseParserAsHandlerArg @54 -; added with version 1.95.3 XML_ParserReset @55 +; added with version 1.95.4 XML_SetSkippedEntityHandler @56 ; added with version 1.95.5 XML_GetFeatureList @57 @@ -70,7 +71,7 @@ XML_StopParser @63 XML_ResumeParser @64 XML_GetParsingStatus @65 -; added with version 2.1.1 +; added with version 2.1.0 @_EXPAT_COMMENT_ATTR_INFO@ XML_GetAttributeInfo @66 XML_SetHashSalt @67 ; internal @68 removed with version 2.3.1 @@ -79,3 +80,8 @@ @_EXPAT_COMMENT_DTD_OR_GE@ XML_SetBillionLaughsAttackProtectionMaximumAmplification @70 ; added with version 2.6.0 XML_SetReparseDeferralEnabled @71 +; added with version 2.7.2 +@_EXPAT_COMMENT_DTD_OR_GE@ XML_SetAllocTrackerMaximumAmplification @72 +@_EXPAT_COMMENT_DTD_OR_GE@ XML_SetAllocTrackerActivationThreshold @73 +; added with version 2.8.0 + XML_SetHashSalt16Bytes @74 diff -Nru expat-2.7.1/expat/lib/libexpat.map.in expat-2.8.2/expat/lib/libexpat.map.in --- expat-2.7.1/expat/lib/libexpat.map.in 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/expat/lib/libexpat.map.in 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,124 @@ +LIBEXPAT_1.0.0 { + global: + XML_DefaultCurrent; + XML_ErrorString; + XML_ExternalEntityParserCreate; + XML_GetBase; + XML_GetBuffer; + XML_GetCurrentByteIndex; + XML_GetCurrentColumnNumber; + XML_GetCurrentLineNumber; + XML_GetErrorCode; + XML_Parse; + XML_ParseBuffer; + XML_ParserCreate; + XML_ParserFree; + XML_SetBase; + XML_SetCharacterDataHandler; + XML_SetDefaultHandler; + XML_SetElementHandler; + XML_SetExternalEntityRefHandler; + XML_SetNotationDeclHandler; + XML_SetProcessingInstructionHandler; + XML_SetUnknownEncodingHandler; + XML_SetUnparsedEntityDeclHandler; + XML_SetUserData; + XML_UseParserAsHandlerArg; +}; + +LIBEXPAT_1.1.0 { + global: + XML_GetCurrentByteCount; + XML_GetSpecifiedAttributeCount; + XML_ParserCreateNS; + XML_SetCdataSectionHandler; + XML_SetCommentHandler; + XML_SetDefaultHandlerExpand; + XML_SetEncoding; + XML_SetExternalEntityRefHandlerArg; + XML_SetNamespaceDeclHandler; + XML_SetNotStandaloneHandler; +} LIBEXPAT_1.0.0; + +LIBEXPAT_1.95.0 { + global: + XML_ExpatVersion; + XML_GetIdAttributeIndex; + XML_GetInputContext; + XML_ParserCreate_MM; + XML_SetAttlistDeclHandler; + XML_SetDoctypeDeclHandler; + XML_SetElementDeclHandler; + XML_SetEndCdataSectionHandler; + XML_SetEndDoctypeDeclHandler; + XML_SetEndElementHandler; + XML_SetEndNamespaceDeclHandler; + XML_SetEntityDeclHandler; + XML_SetParamEntityParsing; + XML_SetReturnNSTriplet; + XML_SetStartCdataSectionHandler; + XML_SetStartDoctypeDeclHandler; + XML_SetStartElementHandler; + XML_SetStartNamespaceDeclHandler; + XML_SetXmlDeclHandler; +} LIBEXPAT_1.1.0; + +LIBEXPAT_1.95.3 { + global: + XML_ExpatVersionInfo; + XML_ParserReset; +} LIBEXPAT_1.95.0; + +LIBEXPAT_1.95.4 { + global: + XML_SetSkippedEntityHandler; +} LIBEXPAT_1.95.3; + +LIBEXPAT_1.95.5 { + global: + XML_GetFeatureList; + XML_UseForeignDTD; +} LIBEXPAT_1.95.4; + +LIBEXPAT_1.95.6 { + global: + XML_FreeContentModel; + XML_MemFree; + XML_MemMalloc; + XML_MemRealloc; +} LIBEXPAT_1.95.5; + +LIBEXPAT_1.95.8 { + global: + XML_GetParsingStatus; + XML_ResumeParser; + XML_StopParser; +} LIBEXPAT_1.95.6; + +LIBEXPAT_2.1.0 { + global: +@_EXPAT_COMMENT_ATTR_INFO@ XML_GetAttributeInfo; + XML_SetHashSalt; +} LIBEXPAT_1.95.8; + +LIBEXPAT_2.4.0 { + global: +@_EXPAT_COMMENT_DTD_OR_GE@ XML_SetBillionLaughsAttackProtectionActivationThreshold; +@_EXPAT_COMMENT_DTD_OR_GE@ XML_SetBillionLaughsAttackProtectionMaximumAmplification; +} LIBEXPAT_2.1.0; + +LIBEXPAT_2.6.0 { + global: + XML_SetReparseDeferralEnabled; +} LIBEXPAT_2.4.0; + +LIBEXPAT_2.7.2 { + global: +@_EXPAT_COMMENT_DTD_OR_GE@ XML_SetAllocTrackerActivationThreshold; +@_EXPAT_COMMENT_DTD_OR_GE@ XML_SetAllocTrackerMaximumAmplification; +} LIBEXPAT_2.6.0; + +LIBEXPAT_2.8.0 { + global: + XML_SetHashSalt16Bytes; +} LIBEXPAT_2.7.2; diff -Nru expat-2.7.1/expat/lib/memory_sanitizer.h expat-2.8.2/expat/lib/memory_sanitizer.h --- expat-2.7.1/expat/lib/memory_sanitizer.h 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/expat/lib/memory_sanitizer.h 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,51 @@ +/* + __ __ _ + ___\ \/ /_ __ __ _| |_ + / _ \\ /| '_ \ / _` | __| + | __// \| |_) | (_| | |_ + \___/_/\_\ .__/ \__,_|\__| + |_| XML parser + + Copyright (c) 2026 Matthew Fernandez + Licensed under the MIT license: + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the + following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#if ! defined(MEMORY_SANITIZER_H) +# define MEMORY_SANITIZER_H 1 + +# if defined(__has_feature) +# if __has_feature(memory_sanitizer) +# include + +// inform Memory Sanitizer that [base, base + extent) is now initialized +# define MSAN_UNPOISON(base, extent) __msan_unpoison((base), (extent)) + +# endif +# endif + +# if ! defined(MSAN_UNPOISON) +# define MSAN_UNPOISON(base, extent) \ + do { \ + } while (0) +# endif + +#endif // ! defined(MEMORY_SANITIZER_H) diff -Nru expat-2.7.1/expat/lib/random_arc4random.c expat-2.8.2/expat/lib/random_arc4random.c --- expat-2.7.1/expat/lib/random_arc4random.c 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/expat/lib/random_arc4random.c 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,56 @@ +/* + __ __ _ + ___\ \/ /_ __ __ _| |_ + / _ \\ /| '_ \ / _` | __| + | __// \| |_) | (_| | |_ + \___/_/\_\ .__/ \__,_|\__| + |_| XML parser + + Copyright (c) 2017-2026 Sebastian Pipping + Copyright (c) 2026 Matthew Fernandez + Licensed under the MIT license: + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the + following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "random_arc4random.h" + +#if ! defined(_DEFAULT_SOURCE) +# define _DEFAULT_SOURCE 1 /* for glibc */ +#endif + +#include // for uint32_t +#include // for arc4random +#include // for memcpy + +void +writeRandomBytes_arc4random(void *target, size_t count) { + size_t bytesWrittenTotal = 0; + + while (bytesWrittenTotal < count) { + const uint32_t random32 = arc4random(); + + size_t toUse = count - bytesWrittenTotal; + if (toUse > sizeof(random32)) + toUse = sizeof(random32); + memcpy((char *)target + bytesWrittenTotal, &random32, toUse); + bytesWrittenTotal += toUse; + } +} diff -Nru expat-2.7.1/expat/lib/random_arc4random.h expat-2.8.2/expat/lib/random_arc4random.h --- expat-2.7.1/expat/lib/random_arc4random.h 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/expat/lib/random_arc4random.h 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,39 @@ +/* + __ __ _ + ___\ \/ /_ __ __ _| |_ + / _ \\ /| '_ \ / _` | __| + | __// \| |_) | (_| | |_ + \___/_/\_\ .__/ \__,_|\__| + |_| XML parser + + Copyright (c) 2026 Sebastian Pipping + Licensed under the MIT license: + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the + following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#if ! defined(RANDOM_ACR4RANDOM_H) +# define RANDOM_ACR4RANDOM_H 1 + +# include // for size_t + +void writeRandomBytes_arc4random(void *target, size_t count); + +#endif // ! defined(RANDOM_ACR4RANDOM_H) diff -Nru expat-2.7.1/expat/lib/random_arc4random_buf.c expat-2.8.2/expat/lib/random_arc4random_buf.c --- expat-2.7.1/expat/lib/random_arc4random_buf.c 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/expat/lib/random_arc4random_buf.c 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,47 @@ +/* + __ __ _ + ___\ \/ /_ __ __ _| |_ + / _ \\ /| '_ \ / _` | __| + | __// \| |_) | (_| | |_ + \___/_/\_\ .__/ \__,_|\__| + |_| XML parser + + Copyright (c) 2026 Sebastian Pipping + Copyright (c) 2026 Matthew Fernandez + Licensed under the MIT license: + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the + following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "random_arc4random_buf.h" + +#if ! defined(_DEFAULT_SOURCE) +# define _DEFAULT_SOURCE 1 /* for glibc */ +#endif + +#include "memory_sanitizer.h" +#include // for arc4random_buf + +void +writeRandomBytes_arc4random_buf(void *target, size_t count) { + arc4random_buf(target, count); + // MSan does not understand `arc4random_buf`, so explain its effects + MSAN_UNPOISON(target, count); +} diff -Nru expat-2.7.1/expat/lib/random_arc4random_buf.h expat-2.8.2/expat/lib/random_arc4random_buf.h --- expat-2.7.1/expat/lib/random_arc4random_buf.h 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/expat/lib/random_arc4random_buf.h 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,39 @@ +/* + __ __ _ + ___\ \/ /_ __ __ _| |_ + / _ \\ /| '_ \ / _` | __| + | __// \| |_) | (_| | |_ + \___/_/\_\ .__/ \__,_|\__| + |_| XML parser + + Copyright (c) 2026 Sebastian Pipping + Licensed under the MIT license: + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the + following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#if ! defined(RANDOM_ACR4RANDOM_BUF_H) +# define RANDOM_ACR4RANDOM_BUF_H 1 + +# include // for size_t + +void writeRandomBytes_arc4random_buf(void *target, size_t count); + +#endif // ! defined(RANDOM_ACR4RANDOM_BUF_H) diff -Nru expat-2.7.1/expat/lib/random_dev_urandom.c expat-2.8.2/expat/lib/random_dev_urandom.c --- expat-2.7.1/expat/lib/random_dev_urandom.c 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/expat/lib/random_dev_urandom.c 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,72 @@ +/* + __ __ _ + ___\ \/ /_ __ __ _| |_ + / _ \\ /| '_ \ / _` | __| + | __// \| |_) | (_| | |_ + \___/_/\_\ .__/ \__,_|\__| + |_| XML parser + + Copyright (c) 2017-2026 Sebastian Pipping + Copyright (c) 2026 Matthew Fernandez + Licensed under the MIT license: + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the + following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "random_dev_urandom.h" + +#if ! defined(_POSIX_C_SOURCE) \ + || (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE < 200809L)) +# define _POSIX_C_SOURCE 200809L // for O_CLOEXEC +#endif + +#include +#include // open +#include // close + +/* Extract entropy from /dev/urandom */ +bool +writeRandomBytes_dev_urandom(void *target, size_t count) { + int success = false; /* full count bytes written? */ + size_t bytesWrittenTotal = 0; + + const int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC); + if (fd < 0) { + return false; + } + + do { + void *const currentTarget = (char *)target + bytesWrittenTotal; + const size_t bytesToWrite = count - bytesWrittenTotal; + + errno = 0; + + const ssize_t bytesWrittenMore = read(fd, currentTarget, bytesToWrite); + + if (bytesWrittenMore > 0) { + bytesWrittenTotal += bytesWrittenMore; + if (bytesWrittenTotal >= count) + success = true; + } + } while (! success && (errno == EINTR)); + + close(fd); + return success; +} diff -Nru expat-2.7.1/expat/lib/random_dev_urandom.h expat-2.8.2/expat/lib/random_dev_urandom.h --- expat-2.7.1/expat/lib/random_dev_urandom.h 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/expat/lib/random_dev_urandom.h 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,40 @@ +/* + __ __ _ + ___\ \/ /_ __ __ _| |_ + / _ \\ /| '_ \ / _` | __| + | __// \| |_) | (_| | |_ + \___/_/\_\ .__/ \__,_|\__| + |_| XML parser + + Copyright (c) 2026 Sebastian Pipping + Licensed under the MIT license: + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the + following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#if ! defined(RANDOM_DEV_URANDOM_H) +# define RANDOM_DEV_URANDOM_H 1 + +# include +# include // for size_t + +bool writeRandomBytes_dev_urandom(void *target, size_t count); + +#endif // ! defined(RANDOM_DEV_URANDOM_H) diff -Nru expat-2.7.1/expat/lib/random_getentropy.c expat-2.8.2/expat/lib/random_getentropy.c --- expat-2.7.1/expat/lib/random_getentropy.c 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/expat/lib/random_getentropy.c 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,60 @@ +/* + __ __ _ + ___\ \/ /_ __ __ _| |_ + / _ \\ /| '_ \ / _` | __| + | __// \| |_) | (_| | |_ + \___/_/\_\ .__/ \__,_|\__| + |_| XML parser + + Copyright (c) 2026 Sebastian Pipping + Copyright (c) 2026 Matthew Fernandez + Licensed under the MIT license: + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the + following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "random_getentropy.h" + +// NOTE: Please keep this block in sync with its two siblings in files +// `configure.ac` and `ConfigureChecks.cmake`! +#if defined(__APPLE__) +# include +#else +# if defined(__GLIBC__) && ! defined(_DEFAULT_SOURCE) +# define _DEFAULT_SOURCE 1 +# endif +# if ! defined(_GNU_SOURCE) +# define _GNU_SOURCE 1 /* for musl */ +# endif +# include +#endif // ! defined(__APPLE__) + +#include "memory_sanitizer.h" +#include + +bool +writeRandomBytes_getentropy(void *target, size_t count) { + errno = 0; + const bool success = getentropy(target, count); + // MSan does not understand `getentropy`, so explain its effects + if (success) + MSAN_UNPOISON(target, count); + return success; +} diff -Nru expat-2.7.1/expat/lib/random_getentropy.h expat-2.8.2/expat/lib/random_getentropy.h --- expat-2.7.1/expat/lib/random_getentropy.h 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/expat/lib/random_getentropy.h 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,40 @@ +/* + __ __ _ + ___\ \/ /_ __ __ _| |_ + / _ \\ /| '_ \ / _` | __| + | __// \| |_) | (_| | |_ + \___/_/\_\ .__/ \__,_|\__| + |_| XML parser + + Copyright (c) 2026 Sebastian Pipping + Licensed under the MIT license: + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the + following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#if ! defined(RANDOM_GETENTROPY_H) +# define RANDOM_GETENTROPY_H 1 + +# include +# include // for size_t + +bool writeRandomBytes_getentropy(void *target, size_t count); + +#endif // ! defined(RANDOM_GETENTROPY_H) diff -Nru expat-2.7.1/expat/lib/random_getrandom.c expat-2.8.2/expat/lib/random_getrandom.c --- expat-2.7.1/expat/lib/random_getrandom.c 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/expat/lib/random_getrandom.c 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,95 @@ +/* + __ __ _ + ___\ \/ /_ __ __ _| |_ + / _ \\ /| '_ \ / _` | __| + | __// \| |_) | (_| | |_ + \___/_/\_\ .__/ \__,_|\__| + |_| XML parser + + Copyright (c) 2017-2026 Sebastian Pipping + Copyright (c) 2017 Chanho Park + Copyright (c) 2022 Sean McBride + Copyright (c) 2026 Matthew Fernandez + Licensed under the MIT license: + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the + following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "expat_config.h" // for HAVE_GETRANDOM, HAVE_SYSCALL_GETRANDOM + +#include "random_getrandom.h" + +#if defined(HAVE_GETRANDOM) +# include /* getrandom */ +#endif + +#if defined(HAVE_SYSCALL_GETRANDOM) +# if ! defined(_GNU_SOURCE) +# define _GNU_SOURCE 1 /* syscall prototype */ +# endif +# include /* syscall */ +# include /* SYS_getrandom */ +#endif // defined(HAVE_SYSCALL_GETRANDOM) + +#if ! defined(GRND_NONBLOCK) +# define GRND_NONBLOCK 0x0001 +#endif /* defined(GRND_NONBLOCK) */ + +#include "memory_sanitizer.h" +#include +#include +#include // for INT_MAX + +/* Obtain entropy on Linux 3.17+ */ +bool +writeRandomBytes_getrandom_nonblock(void *target, size_t count) { + int success = false; /* full count bytes written? */ + size_t bytesWrittenTotal = 0; + const unsigned int getrandomFlags = GRND_NONBLOCK; + + do { + void *const currentTarget = (char *)target + bytesWrittenTotal; + const size_t bytesToWrite = count - bytesWrittenTotal; + + assert(bytesToWrite <= INT_MAX); + + errno = 0; + + const int bytesWrittenMore = +#if defined(HAVE_GETRANDOM) + (int)getrandom(currentTarget, bytesToWrite, getrandomFlags); + // MSan understands `getrandom`, so does not need extra guidance +#else + (int)syscall(SYS_getrandom, currentTarget, bytesToWrite, + getrandomFlags); + // MSan does not understand `syscall`, so explain its effects + if (bytesWrittenMore > 0) + MSAN_UNPOISON(currentTarget, bytesWrittenMore); +#endif + + if (bytesWrittenMore > 0) { + bytesWrittenTotal += bytesWrittenMore; + if (bytesWrittenTotal >= count) + success = true; + } + } while (! success && (errno == EINTR)); + + return success; +} diff -Nru expat-2.7.1/expat/lib/random_getrandom.h expat-2.8.2/expat/lib/random_getrandom.h --- expat-2.7.1/expat/lib/random_getrandom.h 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/expat/lib/random_getrandom.h 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,40 @@ +/* + __ __ _ + ___\ \/ /_ __ __ _| |_ + / _ \\ /| '_ \ / _` | __| + | __// \| |_) | (_| | |_ + \___/_/\_\ .__/ \__,_|\__| + |_| XML parser + + Copyright (c) 2026 Sebastian Pipping + Licensed under the MIT license: + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the + following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#if ! defined(RANDOM_GETRANDOM_H) +# define RANDOM_GETRANDOM_H 1 + +# include +# include // for size_t + +bool writeRandomBytes_getrandom_nonblock(void *target, size_t count); + +#endif // ! defined(RANDOM_GETRANDOM_H) diff -Nru expat-2.7.1/expat/lib/random_rand_s.c expat-2.8.2/expat/lib/random_rand_s.c --- expat-2.7.1/expat/lib/random_rand_s.c 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/expat/lib/random_rand_s.c 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,88 @@ +/* + __ __ _ + ___\ \/ /_ __ __ _| |_ + / _ \\ /| '_ \ / _` | __| + | __// \| |_) | (_| | |_ + \___/_/\_\ .__/ \__,_|\__| + |_| XML parser + + Copyright (c) 2019 David Loffredo + Copyright (c) 2019-2026 Sebastian Pipping + Copyright (c) 2019 Ben Wagner + Copyright (c) 2019 Vadim Zeitlin + Copyright (c) 2026 Matthew Fernandez + Licensed under the MIT license: + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the + following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "random_rand_s.h" + +/* force stdlib to define rand_s() */ +#if ! defined(_CRT_RAND_S) +# define _CRT_RAND_S +#endif + +// Workaround MinGW GCC trouble with recognizing `rand_s`, likely related +// to return type `error_t`; the symptom was: +// > error: implicit declaration of function ‘rand_s’ +#if defined(__MINGW32__) +# include +#endif + +#include // for rand_s +#include // for memcpy + +// Help clang-tidy out with prototype of function `rand_s` +#if defined(XML_CLANG_TIDY) +int rand_s(unsigned int *); +#endif + +/* Provide declaration of rand_s() for MinGW-32 (not 64, which has it), + as it didn't declare it in its header prior to version 5.3.0 of its + runtime package (mingwrt, containing stdlib.h). The upstream fix + was introduced at https://osdn.net/projects/mingw/ticket/39658 . */ +#if defined(__MINGW32__) && defined(__MINGW32_VERSION) \ + && __MINGW32_VERSION < 5003000L && ! defined(__MINGW64_VERSION_MAJOR) +__declspec(dllimport) int rand_s(unsigned int *); +#endif + +/* Obtain entropy on Windows using the rand_s() function which + * generates cryptographically secure random numbers. Internally it + * uses RtlGenRandom API which is present in Windows XP and later. + */ +bool +writeRandomBytes_rand_s(void *target, size_t count) { + size_t bytesWrittenTotal = 0; + + while (bytesWrittenTotal < count) { + unsigned int random32 = 0; + + if (rand_s(&random32)) + return false; /* failure */ + + size_t toUse = count - bytesWrittenTotal; + if (toUse > sizeof(random32)) + toUse = sizeof(random32); + memcpy((char *)target + bytesWrittenTotal, &random32, toUse); + bytesWrittenTotal += toUse; + } + return true; /* success */ +} diff -Nru expat-2.7.1/expat/lib/random_rand_s.h expat-2.8.2/expat/lib/random_rand_s.h --- expat-2.7.1/expat/lib/random_rand_s.h 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/expat/lib/random_rand_s.h 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,41 @@ +/* + __ __ _ + ___\ \/ /_ __ __ _| |_ + / _ \\ /| '_ \ / _` | __| + | __// \| |_) | (_| | |_ + \___/_/\_\ .__/ \__,_|\__| + |_| XML parser + + Copyright (c) 2019 David Loffredo + Copyright (c) 2026 Sebastian Pipping + Licensed under the MIT license: + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the + following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#if ! defined(RANDOM_RAND_S_H) +# define RANDOM_RAND_S_H 1 + +# include +# include // for size_t + +bool writeRandomBytes_rand_s(void *target, size_t count); + +#endif // ! defined(RANDOM_RAND_S_H) diff -Nru expat-2.7.1/expat/lib/siphash.h expat-2.8.2/expat/lib/siphash.h --- expat-2.7.1/expat/lib/siphash.h 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/lib/siphash.h 2026-06-25 14:07:00.000000000 +0000 @@ -100,6 +100,7 @@ #include /* size_t */ #include /* uint64_t uint32_t uint8_t */ +#include "fallthrough.h" /* * Workaround to not require a C++11 compiler for using ULL suffix @@ -234,25 +235,25 @@ switch (left) { case 7: b |= (uint64_t)H->buf[6] << 48; - /* fall through */ + EXPAT_FALLTHROUGH; case 6: b |= (uint64_t)H->buf[5] << 40; - /* fall through */ + EXPAT_FALLTHROUGH; case 5: b |= (uint64_t)H->buf[4] << 32; - /* fall through */ + EXPAT_FALLTHROUGH; case 4: b |= (uint64_t)H->buf[3] << 24; - /* fall through */ + EXPAT_FALLTHROUGH; case 3: b |= (uint64_t)H->buf[2] << 16; - /* fall through */ + EXPAT_FALLTHROUGH; case 2: b |= (uint64_t)H->buf[1] << 8; - /* fall through */ + EXPAT_FALLTHROUGH; case 1: b |= (uint64_t)H->buf[0] << 0; - /* fall through */ + EXPAT_FALLTHROUGH; case 0: break; } diff -Nru expat-2.7.1/expat/lib/xcsinc.c expat-2.8.2/expat/lib/xcsinc.c --- expat-2.7.1/expat/lib/xcsinc.c 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/expat/lib/xcsinc.c 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,48 @@ +/* This file is included from other .c files! + __ __ _ + ___\ \/ /_ __ __ _| |_ + / _ \\ /| '_ \ / _` | __| + | __// \| |_) | (_| | |_ + \___/_/\_\ .__/ \__,_|\__| + |_| XML parser + + Copyright (c) 2022 Sebastian Pipping + Licensed under the MIT license: + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the + following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +static size_t +xcslen(const XML_Char *s) { +#ifdef XML_UNICODE +# ifdef XML_UNICODE_WCHAR_T + return wcslen(s); +# else + // XML_Char is unsigned short + size_t len = 0; + while (s[len]) { + len++; + } + return len; +# endif +#else + return strlen(s); +#endif +} diff -Nru expat-2.7.1/expat/lib/xmlparse.c expat-2.8.2/expat/lib/xmlparse.c --- expat-2.7.1/expat/lib/xmlparse.c 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/lib/xmlparse.c 2026-06-25 14:07:00.000000000 +0000 @@ -1,4 +1,4 @@ -/* d19ae032c224863c1527ba44d228cc34b99192c3a4c5a27af1f4e054d45ee031 (2.7.1+) +/* 5de44e6750c6cc78818f06ed552f522a1241df0299395250e1792cb339389daf (2.8.2+) __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| @@ -13,7 +13,7 @@ Copyright (c) 2002-2016 Karl Waclawek Copyright (c) 2005-2009 Steven Solie Copyright (c) 2016 Eric Rahm - Copyright (c) 2016-2025 Sebastian Pipping + Copyright (c) 2016-2026 Sebastian Pipping Copyright (c) 2016 Gaurav Copyright (c) 2016 Thomas Beutlich Copyright (c) 2016 Gustavo Grieco @@ -41,6 +41,15 @@ Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow Copyright (c) 2024-2025 Berkay Eren Ürün Copyright (c) 2024 Hanno Böck + Copyright (c) 2025-2026 Matthew Fernandez + Copyright (c) 2025 Atrem Borovik + Copyright (c) 2025 Alfonso Gregory + Copyright (c) 2026 Rosen Penev + Copyright (c) 2026 Francesco Bertolaccini + Copyright (c) 2026 Christian Ng + Copyright (c) 2026 Nick Begg + Copyright (c) 2026 Kartik Kenchi + Copyright (c) 2026 Haris Hussain Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -80,28 +89,16 @@ # error XML_CONTEXT_BYTES must be defined, non-empty and >=0 (0 to disable, >=1 to enable; 1024 is a common default) #endif -#if defined(HAVE_SYSCALL_GETRANDOM) -# if ! defined(_GNU_SOURCE) -# define _GNU_SOURCE 1 /* syscall prototype */ -# endif -#endif - -#ifdef _WIN32 -/* force stdlib to define rand_s() */ -# if ! defined(_CRT_RAND_S) -# define _CRT_RAND_S -# endif -#endif - #include #include #include /* memset(), memcpy() */ #include -#include /* UINT_MAX */ +#include /* INT_MAX, LLONG_MAX, LONG_MAX, UINT_MAX */ #include /* fprintf */ -#include /* getenv, rand_s */ -#include /* uintptr_t */ +#include /* getenv */ +#include /* SIZE_MAX, uintptr_t */ #include /* isnan */ +#include #ifdef _WIN32 # define getpid GetCurrentProcessId @@ -120,32 +117,36 @@ #include "ascii.h" #include "expat.h" #include "siphash.h" +#include "xcsinc.c" + +#if defined(HAVE_ARC4RANDOM) +# include "random_arc4random.h" +#endif /* defined(HAVE_ARC4RANDOM) */ + +#if defined(HAVE_ARC4RANDOM_BUF) +# include "random_arc4random_buf.h" +#endif // defined(HAVE_ARC4RANDOM_BUF) + +#if defined(XML_DEV_URANDOM) +# include "random_dev_urandom.h" +#endif /* defined(XML_DEV_URANDOM) */ + +#if defined(HAVE_GETENTROPY) +# include "random_getentropy.h" +#endif // defined(HAVE_GETENTROPY) #if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) -# if defined(HAVE_GETRANDOM) -# include /* getrandom */ -# else -# include /* syscall */ -# include /* SYS_getrandom */ -# endif -# if ! defined(GRND_NONBLOCK) -# define GRND_NONBLOCK 0x0001 -# endif /* defined(GRND_NONBLOCK) */ -#endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */ - -#if defined(HAVE_LIBBSD) \ - && (defined(HAVE_ARC4RANDOM_BUF) || defined(HAVE_ARC4RANDOM)) -# include -#endif +# include "random_getrandom.h" +#endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */ -#if defined(_WIN32) && ! defined(LOAD_LIBRARY_SEARCH_SYSTEM32) -# define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800 -#endif +#if defined(_WIN32) +# include "random_rand_s.h" +#endif /* defined(_WIN32) */ #if ! defined(HAVE_GETRANDOM) && ! defined(HAVE_SYSCALL_GETRANDOM) \ && ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) \ - && ! defined(XML_DEV_URANDOM) && ! defined(_WIN32) \ - && ! defined(XML_POOR_ENTROPY) + && ! defined(HAVE_GETENTROPY) && ! defined(XML_DEV_URANDOM) \ + && ! defined(_WIN32) && ! defined(XML_POOR_ENTROPY) # error You do not have support for any sources of high quality entropy \ enabled. For end user security, that is probably not what you want. \ \ @@ -154,13 +155,12 @@ * Linux >=3.17 + glibc (including <2.25) (syscall SYS_getrandom): HAVE_SYSCALL_GETRANDOM, \ * BSD / macOS >=10.7 / glibc >=2.36 (arc4random_buf): HAVE_ARC4RANDOM_BUF, \ * BSD / macOS (including <10.7) / glibc >=2.36 (arc4random): HAVE_ARC4RANDOM, \ - * libbsd (arc4random_buf): HAVE_ARC4RANDOM_BUF + HAVE_LIBBSD, \ - * libbsd (arc4random): HAVE_ARC4RANDOM + HAVE_LIBBSD, \ + * BSD / macOS >=10.12 / glibc >=2.25 (getentropy): HAVE_GETENTROPY, \ * Linux (including <3.17) / BSD / macOS (including <10.7) / Solaris >=8 (/dev/urandom): XML_DEV_URANDOM, \ * Windows >=Vista (rand_s): _WIN32. \ \ - If insist on not using any of these, bypass this error by defining \ - XML_POOR_ENTROPY; you have been warned. \ + If you insist on not using any of these, bypass this error by defining \ + XML_POOR_ENTROPY and be vulnerable to hash flooding; you have been warned. \ \ If you have reasons to patch this detection code away or need changes \ to the build system, please open a bug. Thank you! @@ -211,6 +211,12 @@ #endif +#ifdef XML_LARGE_SIZE +# define XML_INDEX_MAX LLONG_MAX +#else +# define XML_INDEX_MAX LONG_MAX +#endif + /* Round up n to be a multiple of sz, where sz is a power of 2. */ #define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1)) @@ -234,7 +240,7 @@ unsigned char power; size_t size; size_t used; - const XML_Memory_Handling_Suite *mem; + XML_Parser parser; } HASH_TABLE; static size_t keylen(KEY s); @@ -274,8 +280,8 @@ struct binding *prevPrefixBinding; const struct attribute_id *attId; XML_Char *uri; - int uriLen; - int uriAlloc; + size_t uriLen; + size_t uriAlloc; } BINDING; typedef struct prefix { @@ -287,9 +293,9 @@ const XML_Char *str; const XML_Char *localPart; const XML_Char *prefix; - int strLen; - int uriLen; - int prefixLen; + size_t strLen; + size_t uriLen; + size_t prefixLen; } TAG_NAME; /* TAG represents an open element. @@ -310,8 +316,11 @@ const char *rawName; /* tagName in the original encoding */ int rawNameLength; TAG_NAME name; /* tagName in the API encoding */ - char *buf; /* buffer for name components */ - char *bufEnd; /* end of the buffer */ + union { + char *raw; /* for byte-level access (rawName storage) */ + XML_Char *str; /* for character-level access (converted name) */ + } buf; /* buffer for name components */ + char *bufEnd; /* end of the buffer */ BINDING *bindings; } TAG; @@ -348,7 +357,7 @@ typedef struct block { struct block *next; int size; - XML_Char s[1]; + XML_Char s[]; } BLOCK; typedef struct { @@ -357,7 +366,7 @@ const XML_Char *end; XML_Char *ptr; XML_Char *start; - const XML_Memory_Handling_Suite *mem; + XML_Parser parser; } STRING_POOL; /* The XML_Char before the name is used to determine whether @@ -385,9 +394,10 @@ const XML_Char *name; PREFIX *prefix; const ATTRIBUTE_ID *idAtt; - int nDefaultAtts; - int allocDefaultAtts; + size_t nDefaultAtts; + size_t allocDefaultAtts; DEFAULT_ATTRIBUTE *defaultAtts; + HASH_TABLE defaultAttsNames; } ELEMENT_TYPE; typedef struct { @@ -417,6 +427,7 @@ unsigned scaffCount; int scaffLevel; int *scaffIndex; + size_t scaffIndexSize; } DTD; enum EntityType { @@ -452,6 +463,14 @@ unsigned long long activationThresholdBytes; } ACCOUNTING; +typedef struct MALLOC_TRACKER { + XmlBigCount bytesAllocated; + XmlBigCount peakBytesAllocated; // updated live only for debug level >=2 + unsigned long debugLevel; + float maximumAmplificationFactor; // >=1.0 + XmlBigCount activationThresholdBytes; +} MALLOC_TRACKER; + typedef struct entity_stats { unsigned int countEverOpened; unsigned int currentDepth; @@ -555,27 +574,24 @@ static void FASTCALL normalizePublicId(XML_Char *s); -static DTD *dtdCreate(const XML_Memory_Handling_Suite *ms); +static DTD *dtdCreate(XML_Parser parser); /* do not call if m_parentParser != NULL */ -static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms); -static void dtdDestroy(DTD *p, XML_Bool isDocEntity, - const XML_Memory_Handling_Suite *ms); +static void dtdReset(DTD *p, XML_Parser parser); +static void dtdDestroy(DTD *p, XML_Bool isDocEntity, XML_Parser parser); static int dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, - const XML_Memory_Handling_Suite *ms); + XML_Parser parser); static int copyEntityTable(XML_Parser oldParser, HASH_TABLE *newTable, STRING_POOL *newPool, const HASH_TABLE *oldTable); static NAMED *lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize); -static void FASTCALL hashTableInit(HASH_TABLE *table, - const XML_Memory_Handling_Suite *ms); +static void FASTCALL hashTableInit(HASH_TABLE *table, XML_Parser parser); static void FASTCALL hashTableClear(HASH_TABLE *table); static void FASTCALL hashTableDestroy(HASH_TABLE *table); static void FASTCALL hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table); static NAMED *FASTCALL hashTableIterNext(HASH_TABLE_ITER *iter); -static void FASTCALL poolInit(STRING_POOL *pool, - const XML_Memory_Handling_Suite *ms); +static void FASTCALL poolInit(STRING_POOL *pool, XML_Parser parser); static void FASTCALL poolClear(STRING_POOL *pool); static void FASTCALL poolDestroy(STRING_POOL *pool); static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc, @@ -583,8 +599,11 @@ static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc, const char *ptr, const char *end); static XML_Bool FASTCALL poolGrow(STRING_POOL *pool); +static bool FASTCALL poolGrowUntil(STRING_POOL *pool, size_t needed); static const XML_Char *FASTCALL poolCopyString(STRING_POOL *pool, const XML_Char *s); +static const XML_Char *FASTCALL poolCopyStringNoFinish(STRING_POOL *pool, + const XML_Char *s); static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n); static const XML_Char *FASTCALL poolAppendString(STRING_POOL *pool, @@ -595,15 +614,15 @@ static ELEMENT_TYPE *getElementType(XML_Parser parser, const ENCODING *enc, const char *ptr, const char *end); -static XML_Char *copyString(const XML_Char *s, - const XML_Memory_Handling_Suite *memsuite); +static XML_Char *copyString(const XML_Char *s, XML_Parser parser); -static unsigned long generate_hash_secret_salt(XML_Parser parser); +static struct sipkey generate_hash_secret_salt(void); static XML_Bool startParsing(XML_Parser parser); static XML_Parser parserCreate(const XML_Char *encodingName, const XML_Memory_Handling_Suite *memsuite, - const XML_Char *nameSep, DTD *dtd); + const XML_Char *nameSep, DTD *dtd, + XML_Parser parentParser); static void parserInit(XML_Parser parser, const XML_Char *encodingName); @@ -627,24 +646,48 @@ int sourceLine); static void entityTrackingOnClose(XML_Parser parser, ENTITY *entity, int sourceLine); +#endif /* XML_GE == 1 */ static XML_Parser getRootParserOf(XML_Parser parser, unsigned int *outLevelDiff); -#endif /* XML_GE == 1 */ static unsigned long getDebugLevel(const char *variableName, unsigned long defaultDebugLevel); +static bool poolAppendChar(STRING_POOL *pool, XML_Char c); + +static bool poolAppendChars(STRING_POOL *pool, const XML_Char *s, size_t len); + #define poolStart(pool) ((pool)->start) #define poolLength(pool) ((pool)->ptr - (pool)->start) #define poolChop(pool) ((void)--(pool->ptr)) #define poolLastChar(pool) (((pool)->ptr)[-1]) #define poolDiscard(pool) ((pool)->ptr = (pool)->start) #define poolFinish(pool) ((pool)->start = (pool)->ptr) -#define poolAppendChar(pool, c) \ - (((pool)->ptr == (pool)->end && ! poolGrow(pool)) \ - ? 0 \ - : ((*((pool)->ptr)++ = c), 1)) + +bool +poolAppendChar(STRING_POOL *pool, XML_Char c) { + if (pool->ptr == pool->end && ! poolGrow(pool)) + return false; + + *(pool->ptr)++ = c; + return true; +} + +bool +poolAppendChars(STRING_POOL *pool, const XML_Char *s, size_t len) { + // Detect and prevent integer overflow + if (len > SIZE_MAX / sizeof(XML_Char)) + return false; + + if (! poolGrowUntil(pool, len)) + return false; + + memcpy(pool->ptr, s, len * sizeof(XML_Char)); + pool->ptr += len; + + return true; +} #if ! defined(XML_TESTING) const @@ -723,11 +766,9 @@ const char *m_eventEndPtr; const char *m_positionPtr; OPEN_INTERNAL_ENTITY *m_openInternalEntities; - OPEN_INTERNAL_ENTITY *m_freeInternalEntities; OPEN_INTERNAL_ENTITY *m_openAttributeEntities; - OPEN_INTERNAL_ENTITY *m_freeAttributeEntities; OPEN_INTERNAL_ENTITY *m_openValueEntities; - OPEN_INTERNAL_ENTITY *m_freeValueEntities; + OPEN_INTERNAL_ENTITY *m_freeEntities; XML_Bool m_defaultExpandInternalEntities; int m_tagLevel; ENTITY *m_declEntity; @@ -747,7 +788,7 @@ TAG *m_freeTagList; BINDING *m_inheritedBindings; BINDING *m_freeBindingList; - int m_attsSize; + size_t m_attsSize; int m_nSpecifiedAtts; int m_idAttIndex; ATTRIBUTE *m_atts; @@ -761,7 +802,7 @@ STRING_POOL m_tempPool; STRING_POOL m_temp2Pool; char *m_groupConnector; - unsigned int m_groupSize; + size_t m_groupSize; XML_Char m_namespaceSeparator; XML_Parser m_parentParser; XML_ParsingStatus m_parsingStatus; @@ -770,166 +811,266 @@ XML_Bool m_useForeignDTD; enum XML_ParamEntityParsing m_paramEntityParsing; #endif - unsigned long m_hash_secret_salt; + struct sipkey m_hash_secret_salt_128; + XML_Bool m_hash_secret_salt_set; #if XML_GE == 1 ACCOUNTING m_accounting; + MALLOC_TRACKER m_alloc_tracker; ENTITY_STATS m_entity_stats; #endif XML_Bool m_reenter; + unsigned m_handlerCallDepth; }; -#define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s))) -#define REALLOC(parser, p, s) (parser->m_mem.realloc_fcn((p), (s))) -#define FREE(parser, p) (parser->m_mem.free_fcn((p))) +#if XML_GE == 1 +# define MALLOC(parser, s) (expat_malloc((parser), (s), __LINE__)) +# define REALLOC(parser, p, s) (expat_realloc((parser), (p), (s), __LINE__)) +# define FREE(parser, p) (expat_free((parser), (p), __LINE__)) +#else +# define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s))) +# define REALLOC(parser, p, s) (parser->m_mem.realloc_fcn((p), (s))) +# define FREE(parser, p) (parser->m_mem.free_fcn((p))) +#endif -XML_Parser XMLCALL -XML_ParserCreate(const XML_Char *encodingName) { - return XML_ParserCreate_MM(encodingName, NULL, NULL); -} +#if XML_GE == 1 +static void +expat_heap_stat(XML_Parser rootParser, char operator, XmlBigCount absDiff, + XmlBigCount newTotal, XmlBigCount peakTotal, int sourceLine) { + // NOTE: This can be +infinity or -nan + const float amplification + = (float)newTotal / (float)rootParser->m_accounting.countBytesDirect; + fprintf( + stderr, + "expat: Allocations(%p): Direct " EXPAT_FMT_ULL("10") ", allocated %c" EXPAT_FMT_ULL( + "10") " to " EXPAT_FMT_ULL("10") " (" EXPAT_FMT_ULL("10") " peak), amplification %8.2f (xmlparse.c:%d)\n", + (void *)rootParser, rootParser->m_accounting.countBytesDirect, operator, + absDiff, newTotal, peakTotal, (double)amplification, sourceLine); +} + +static bool +expat_heap_increase_tolerable(XML_Parser rootParser, XmlBigCount increase, + int sourceLine) { + assert(rootParser != NULL); + assert(increase > 0); + + XmlBigCount newTotal = 0; + bool tolerable = true; + + // Detect integer overflow + if ((XmlBigCount)-1 - rootParser->m_alloc_tracker.bytesAllocated < increase) { + tolerable = false; + } else { + newTotal = rootParser->m_alloc_tracker.bytesAllocated + increase; -XML_Parser XMLCALL -XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) { - XML_Char tmp[2] = {nsSep, 0}; - return XML_ParserCreate_MM(encodingName, NULL, tmp); + if (newTotal >= rootParser->m_alloc_tracker.activationThresholdBytes) { + assert(newTotal > 0); + // NOTE: This can be +infinity when dividing by zero but not -nan + const float amplification + = (float)newTotal / (float)rootParser->m_accounting.countBytesDirect; + if (amplification + > rootParser->m_alloc_tracker.maximumAmplificationFactor) { + tolerable = false; + } + } + } + + if (! tolerable && (rootParser->m_alloc_tracker.debugLevel >= 1)) { + expat_heap_stat(rootParser, '+', increase, newTotal, newTotal, sourceLine); + } + + return tolerable; } -// "xml=http://www.w3.org/XML/1998/namespace" -static const XML_Char implicitContext[] - = {ASCII_x, ASCII_m, ASCII_l, ASCII_EQUALS, ASCII_h, - ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, - ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, - ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r, - ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L, - ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9, ASCII_8, - ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m, ASCII_e, - ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, - '\0'}; +# if defined(XML_TESTING) +void * +# else +static void * +# endif +expat_malloc(XML_Parser parser, size_t size, int sourceLine) { + // Detect integer overflow + if (SIZE_MAX - size < sizeof(size_t) + EXPAT_MALLOC_PADDING) { + return NULL; + } -/* To avoid warnings about unused functions: */ -#if ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) + const XML_Parser rootParser = getRootParserOf(parser, NULL); + assert(rootParser->m_parentParser == NULL); -# if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) + const size_t bytesToAllocate = sizeof(size_t) + EXPAT_MALLOC_PADDING + size; -/* Obtain entropy on Linux 3.17+ */ -static int -writeRandomBytes_getrandom_nonblock(void *target, size_t count) { - int success = 0; /* full count bytes written? */ - size_t bytesWrittenTotal = 0; - const unsigned int getrandomFlags = GRND_NONBLOCK; + if ((XmlBigCount)-1 - rootParser->m_alloc_tracker.bytesAllocated + < bytesToAllocate) { + return NULL; // i.e. signal integer overflow as out-of-memory + } - do { - void *const currentTarget = (void *)((char *)target + bytesWrittenTotal); - const size_t bytesToWrite = count - bytesWrittenTotal; + if (! expat_heap_increase_tolerable(rootParser, bytesToAllocate, + sourceLine)) { + return NULL; // i.e. signal violation as out-of-memory + } - const int bytesWrittenMore = -# if defined(HAVE_GETRANDOM) - getrandom(currentTarget, bytesToWrite, getrandomFlags); -# else - syscall(SYS_getrandom, currentTarget, bytesToWrite, getrandomFlags); -# endif + // Actually allocate + void *const mallocedPtr = parser->m_mem.malloc_fcn(bytesToAllocate); - if (bytesWrittenMore > 0) { - bytesWrittenTotal += bytesWrittenMore; - if (bytesWrittenTotal >= count) - success = 1; - } - } while (! success && (errno == EINTR)); + if (mallocedPtr == NULL) { + return NULL; + } - return success; -} + // Update in-block recorded size + *(size_t *)mallocedPtr = size; -# endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */ + // Update accounting + rootParser->m_alloc_tracker.bytesAllocated += bytesToAllocate; -# if ! defined(_WIN32) && defined(XML_DEV_URANDOM) + // Report as needed + if (rootParser->m_alloc_tracker.debugLevel >= 2) { + if (rootParser->m_alloc_tracker.bytesAllocated + > rootParser->m_alloc_tracker.peakBytesAllocated) { + rootParser->m_alloc_tracker.peakBytesAllocated + = rootParser->m_alloc_tracker.bytesAllocated; + } + expat_heap_stat(rootParser, '+', bytesToAllocate, + rootParser->m_alloc_tracker.bytesAllocated, + rootParser->m_alloc_tracker.peakBytesAllocated, sourceLine); + } -/* Extract entropy from /dev/urandom */ -static int -writeRandomBytes_dev_urandom(void *target, size_t count) { - int success = 0; /* full count bytes written? */ - size_t bytesWrittenTotal = 0; + return (char *)mallocedPtr + sizeof(size_t) + EXPAT_MALLOC_PADDING; +} - const int fd = open("/dev/urandom", O_RDONLY); - if (fd < 0) { - return 0; +# if defined(XML_TESTING) +void +# else +static void +# endif +expat_free(XML_Parser parser, void *ptr, int sourceLine) { + assert(parser != NULL); + + if (ptr == NULL) { + return; } - do { - void *const currentTarget = (void *)((char *)target + bytesWrittenTotal); - const size_t bytesToWrite = count - bytesWrittenTotal; + const XML_Parser rootParser = getRootParserOf(parser, NULL); + assert(rootParser->m_parentParser == NULL); - const ssize_t bytesWrittenMore = read(fd, currentTarget, bytesToWrite); + // Extract size (to the eyes of malloc_fcn/realloc_fcn) and + // the original pointer returned by malloc/realloc + void *const mallocedPtr = (char *)ptr - EXPAT_MALLOC_PADDING - sizeof(size_t); + const size_t bytesAllocated + = sizeof(size_t) + EXPAT_MALLOC_PADDING + *(size_t *)mallocedPtr; - if (bytesWrittenMore > 0) { - bytesWrittenTotal += bytesWrittenMore; - if (bytesWrittenTotal >= count) - success = 1; - } - } while (! success && (errno == EINTR)); + // Update accounting + assert(rootParser->m_alloc_tracker.bytesAllocated >= bytesAllocated); + rootParser->m_alloc_tracker.bytesAllocated -= bytesAllocated; + + // Report as needed + if (rootParser->m_alloc_tracker.debugLevel >= 2) { + expat_heap_stat(rootParser, '-', bytesAllocated, + rootParser->m_alloc_tracker.bytesAllocated, + rootParser->m_alloc_tracker.peakBytesAllocated, sourceLine); + } - close(fd); - return success; + // NOTE: This may be freeing rootParser, so freeing has to come last + parser->m_mem.free_fcn(mallocedPtr); } -# endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */ +# if defined(XML_TESTING) +void * +# else +static void * +# endif +expat_realloc(XML_Parser parser, void *ptr, size_t size, int sourceLine) { + assert(parser != NULL); -#endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */ + if (ptr == NULL) { + return expat_malloc(parser, size, sourceLine); + } -#if defined(HAVE_ARC4RANDOM) && ! defined(HAVE_ARC4RANDOM_BUF) + if (size == 0) { + expat_free(parser, ptr, sourceLine); + return NULL; + } -static void -writeRandomBytes_arc4random(void *target, size_t count) { - size_t bytesWrittenTotal = 0; + const XML_Parser rootParser = getRootParserOf(parser, NULL); + assert(rootParser->m_parentParser == NULL); + + // Extract original size (to the eyes of the caller) and the original + // pointer returned by malloc/realloc + void *mallocedPtr = (char *)ptr - EXPAT_MALLOC_PADDING - sizeof(size_t); + const size_t prevSize = *(size_t *)mallocedPtr; - while (bytesWrittenTotal < count) { - const uint32_t random32 = arc4random(); - size_t i = 0; + // Classify upcoming change + const bool isIncrease = (size > prevSize); + const size_t absDiff + = (size > prevSize) ? (size - prevSize) : (prevSize - size); - for (; (i < sizeof(random32)) && (bytesWrittenTotal < count); - i++, bytesWrittenTotal++) { - const uint8_t random8 = (uint8_t)(random32 >> (i * 8)); - ((uint8_t *)target)[bytesWrittenTotal] = random8; + // Ask for permission from accounting + if (isIncrease) { + if (! expat_heap_increase_tolerable(rootParser, absDiff, sourceLine)) { + return NULL; // i.e. signal violation as out-of-memory } } -} -#endif /* defined(HAVE_ARC4RANDOM) && ! defined(HAVE_ARC4RANDOM_BUF) */ + // NOTE: Integer overflow detection has already been done for us + // by expat_heap_increase_tolerable(..) above + assert(SIZE_MAX - sizeof(size_t) - EXPAT_MALLOC_PADDING >= size); -#ifdef _WIN32 + // Actually allocate + mallocedPtr = parser->m_mem.realloc_fcn( + mallocedPtr, sizeof(size_t) + EXPAT_MALLOC_PADDING + size); -/* Provide declaration of rand_s() for MinGW-32 (not 64, which has it), - as it didn't declare it in its header prior to version 5.3.0 of its - runtime package (mingwrt, containing stdlib.h). The upstream fix - was introduced at https://osdn.net/projects/mingw/ticket/39658 . */ -# if defined(__MINGW32__) && defined(__MINGW32_VERSION) \ - && __MINGW32_VERSION < 5003000L && ! defined(__MINGW64_VERSION_MAJOR) -__declspec(dllimport) int rand_s(unsigned int *); -# endif + if (mallocedPtr == NULL) { + return NULL; + } -/* Obtain entropy on Windows using the rand_s() function which - * generates cryptographically secure random numbers. Internally it - * uses RtlGenRandom API which is present in Windows XP and later. - */ -static int -writeRandomBytes_rand_s(void *target, size_t count) { - size_t bytesWrittenTotal = 0; + // Update accounting + if (isIncrease) { + assert((XmlBigCount)-1 - rootParser->m_alloc_tracker.bytesAllocated + >= absDiff); + rootParser->m_alloc_tracker.bytesAllocated += absDiff; + } else { // i.e. decrease + assert(rootParser->m_alloc_tracker.bytesAllocated >= absDiff); + rootParser->m_alloc_tracker.bytesAllocated -= absDiff; + } + + // Report as needed + if (rootParser->m_alloc_tracker.debugLevel >= 2) { + if (rootParser->m_alloc_tracker.bytesAllocated + > rootParser->m_alloc_tracker.peakBytesAllocated) { + rootParser->m_alloc_tracker.peakBytesAllocated + = rootParser->m_alloc_tracker.bytesAllocated; + } + expat_heap_stat(rootParser, isIncrease ? '+' : '-', absDiff, + rootParser->m_alloc_tracker.bytesAllocated, + rootParser->m_alloc_tracker.peakBytesAllocated, sourceLine); + } - while (bytesWrittenTotal < count) { - unsigned int random32 = 0; - size_t i = 0; + // Update in-block recorded size + *(size_t *)mallocedPtr = size; - if (rand_s(&random32)) - return 0; /* failure */ + return (char *)mallocedPtr + sizeof(size_t) + EXPAT_MALLOC_PADDING; +} +#endif // XML_GE == 1 - for (; (i < sizeof(random32)) && (bytesWrittenTotal < count); - i++, bytesWrittenTotal++) { - const uint8_t random8 = (uint8_t)(random32 >> (i * 8)); - ((uint8_t *)target)[bytesWrittenTotal] = random8; - } - } - return 1; /* success */ +XML_Parser XMLCALL +XML_ParserCreate(const XML_Char *encodingName) { + return XML_ParserCreate_MM(encodingName, NULL, NULL); } -#endif /* _WIN32 */ +XML_Parser XMLCALL +XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) { + XML_Char tmp[2] = {nsSep, 0}; + return XML_ParserCreate_MM(encodingName, NULL, tmp); +} + +// "xml=http://www.w3.org/XML/1998/namespace" +static const XML_Char implicitContext[] + = {ASCII_x, ASCII_m, ASCII_l, ASCII_EQUALS, ASCII_h, + ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, + ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, + ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r, + ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L, + ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9, ASCII_8, + ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m, ASCII_e, + ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, + '\0'}; #if ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) @@ -958,63 +1099,85 @@ #endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */ -static unsigned long -ENTROPY_DEBUG(const char *label, unsigned long entropy) { +static struct sipkey +ENTROPY_DEBUG(const char *label, struct sipkey entropy_128) { if (getDebugLevel("EXPAT_ENTROPY_DEBUG", 0) >= 1u) { - fprintf(stderr, "expat: Entropy: %s --> 0x%0*lx (%lu bytes)\n", label, - (int)sizeof(entropy) * 2, entropy, (unsigned long)sizeof(entropy)); - } - return entropy; + fprintf(stderr, + "expat: Entropy: %s --> [0x" EXPAT_FMT_LLX( + "016") ", 0x" EXPAT_FMT_LLX("016") "] (16 bytes)\n", + label, (unsigned long long)entropy_128.k[0], + (unsigned long long)entropy_128.k[1]); + } + return entropy_128; } -static unsigned long -generate_hash_secret_salt(XML_Parser parser) { - unsigned long entropy; - (void)parser; +static struct sipkey +generate_hash_secret_salt(void) { + struct sipkey entropy; /* "Failproof" high quality providers: */ #if defined(HAVE_ARC4RANDOM_BUF) - arc4random_buf(&entropy, sizeof(entropy)); + writeRandomBytes_arc4random_buf(&entropy, sizeof(entropy)); return ENTROPY_DEBUG("arc4random_buf", entropy); #elif defined(HAVE_ARC4RANDOM) - writeRandomBytes_arc4random((void *)&entropy, sizeof(entropy)); + writeRandomBytes_arc4random(&entropy, sizeof(entropy)); return ENTROPY_DEBUG("arc4random", entropy); #else /* Try high quality providers first .. */ # ifdef _WIN32 - if (writeRandomBytes_rand_s((void *)&entropy, sizeof(entropy))) { + if (writeRandomBytes_rand_s(&entropy, sizeof(entropy))) { return ENTROPY_DEBUG("rand_s", entropy); } +# elif defined(HAVE_GETENTROPY) + if (writeRandomBytes_getentropy(&entropy, sizeof(entropy))) { + return ENTROPY_DEBUG("getentropy", entropy); + } + errno = 0; # elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) - if (writeRandomBytes_getrandom_nonblock((void *)&entropy, sizeof(entropy))) { + if (writeRandomBytes_getrandom_nonblock(&entropy, sizeof(entropy))) { return ENTROPY_DEBUG("getrandom", entropy); } # endif # if ! defined(_WIN32) && defined(XML_DEV_URANDOM) - if (writeRandomBytes_dev_urandom((void *)&entropy, sizeof(entropy))) { + if (writeRandomBytes_dev_urandom(&entropy, sizeof(entropy))) { return ENTROPY_DEBUG("/dev/urandom", entropy); } # endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */ /* .. and self-made low quality for backup: */ + entropy.k[0] = 0; + entropy.k[1] = gather_time_entropy(); +# if ! defined(__wasi__) /* Process ID is 0 bits entropy if attacker has local access */ - entropy = gather_time_entropy() ^ getpid(); + entropy.k[1] ^= getpid(); +# endif /* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */ if (sizeof(unsigned long) == 4) { - return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647); + entropy.k[1] *= 2147483647; + return ENTROPY_DEBUG("fallback(4)", entropy); } else { - return ENTROPY_DEBUG("fallback(8)", - entropy * (unsigned long)2305843009213693951ULL); + entropy.k[1] *= 2305843009213693951ULL; + return ENTROPY_DEBUG("fallback(8)", entropy); } #endif } -static unsigned long -get_hash_secret_salt(XML_Parser parser) { - if (parser->m_parentParser != NULL) - return get_hash_secret_salt(parser->m_parentParser); - return parser->m_hash_secret_salt; +static void +beforeHandler(XML_Parser parser) { + assert(parser->m_handlerCallDepth < UINT_MAX); + parser->m_handlerCallDepth++; +} + +static void +afterHandler(XML_Parser parser) { + assert(parser->m_handlerCallDepth > 0); + parser->m_handlerCallDepth--; +} + +static bool +isCalledFromInsideHandler(XML_Parser parser) { + return parser->m_handlerCallDepth > 0; } static enum XML_Error @@ -1085,8 +1248,10 @@ static XML_Bool /* only valid for root parser */ startParsing(XML_Parser parser) { /* hash functions must be initialized before setContext() is called */ - if (parser->m_hash_secret_salt == 0) - parser->m_hash_secret_salt = generate_hash_secret_salt(parser); + if (parser->m_hash_secret_salt_set != XML_TRUE) { + parser->m_hash_secret_salt_128 = generate_hash_secret_salt(); + parser->m_hash_secret_salt_set = XML_TRUE; + } if (parser->m_ns) { /* implicit context only set for root parser, since child parsers (i.e. external entity parsers) will inherit it @@ -1100,19 +1265,43 @@ XML_ParserCreate_MM(const XML_Char *encodingName, const XML_Memory_Handling_Suite *memsuite, const XML_Char *nameSep) { - return parserCreate(encodingName, memsuite, nameSep, NULL); + return parserCreate(encodingName, memsuite, nameSep, NULL, NULL); } static XML_Parser parserCreate(const XML_Char *encodingName, const XML_Memory_Handling_Suite *memsuite, const XML_Char *nameSep, - DTD *dtd) { - XML_Parser parser; + DTD *dtd, XML_Parser parentParser) { + XML_Parser parser = NULL; + +#if XML_GE == 1 + const size_t increase + = sizeof(size_t) + EXPAT_MALLOC_PADDING + sizeof(struct XML_ParserStruct); + + if (parentParser != NULL) { + const XML_Parser rootParser = getRootParserOf(parentParser, NULL); + if (! expat_heap_increase_tolerable(rootParser, increase, __LINE__)) { + return NULL; + } + } +#else + UNUSED_P(parentParser); +#endif if (memsuite) { XML_Memory_Handling_Suite *mtemp; +#if XML_GE == 1 + void *const sizeAndParser + = memsuite->malloc_fcn(sizeof(size_t) + EXPAT_MALLOC_PADDING + + sizeof(struct XML_ParserStruct)); + if (sizeAndParser != NULL) { + *(size_t *)sizeAndParser = sizeof(struct XML_ParserStruct); + parser = (XML_Parser)((char *)sizeAndParser + sizeof(size_t) + + EXPAT_MALLOC_PADDING); +#else parser = memsuite->malloc_fcn(sizeof(struct XML_ParserStruct)); if (parser != NULL) { +#endif mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem); mtemp->malloc_fcn = memsuite->malloc_fcn; mtemp->realloc_fcn = memsuite->realloc_fcn; @@ -1120,39 +1309,86 @@ } } else { XML_Memory_Handling_Suite *mtemp; - parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct)); +#if XML_GE == 1 + void *const sizeAndParser = malloc(sizeof(size_t) + EXPAT_MALLOC_PADDING + + sizeof(struct XML_ParserStruct)); + if (sizeAndParser != NULL) { + *(size_t *)sizeAndParser = sizeof(struct XML_ParserStruct); + parser = (XML_Parser)((char *)sizeAndParser + sizeof(size_t) + + EXPAT_MALLOC_PADDING); +#else + parser = malloc(sizeof(struct XML_ParserStruct)); if (parser != NULL) { +#endif mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem); mtemp->malloc_fcn = malloc; mtemp->realloc_fcn = realloc; mtemp->free_fcn = free; } - } + } // cppcheck-suppress[memleak symbolName=sizeAndParser] // Cppcheck >=2.18.0 if (! parser) return parser; +#if XML_GE == 1 + // Initialize .m_alloc_tracker + memset(&parser->m_alloc_tracker, 0, sizeof(MALLOC_TRACKER)); + if (parentParser == NULL) { + parser->m_alloc_tracker.debugLevel + = getDebugLevel("EXPAT_MALLOC_DEBUG", 0u); + parser->m_alloc_tracker.maximumAmplificationFactor + = EXPAT_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION_DEFAULT; + parser->m_alloc_tracker.activationThresholdBytes + = EXPAT_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT; + + // NOTE: This initialization needs to come this early because these fields + // are read by allocation tracking code + parser->m_parentParser = NULL; + parser->m_accounting.countBytesDirect = 0; + } else { + parser->m_parentParser = parentParser; + } + + // Record XML_ParserStruct allocation we did a few lines up before + const XML_Parser rootParser = getRootParserOf(parser, NULL); + assert(rootParser->m_parentParser == NULL); + assert(SIZE_MAX - rootParser->m_alloc_tracker.bytesAllocated >= increase); + rootParser->m_alloc_tracker.bytesAllocated += increase; + + // Report on allocation + if (rootParser->m_alloc_tracker.debugLevel >= 2) { + if (rootParser->m_alloc_tracker.bytesAllocated + > rootParser->m_alloc_tracker.peakBytesAllocated) { + rootParser->m_alloc_tracker.peakBytesAllocated + = rootParser->m_alloc_tracker.bytesAllocated; + } + + expat_heap_stat(rootParser, '+', increase, + rootParser->m_alloc_tracker.bytesAllocated, + rootParser->m_alloc_tracker.peakBytesAllocated, __LINE__); + } +#else + parser->m_parentParser = NULL; +#endif // XML_GE == 1 + parser->m_buffer = NULL; parser->m_bufferLim = NULL; parser->m_attsSize = INIT_ATTS_SIZE; - parser->m_atts - = (ATTRIBUTE *)MALLOC(parser, parser->m_attsSize * sizeof(ATTRIBUTE)); + parser->m_atts = MALLOC(parser, parser->m_attsSize * sizeof(ATTRIBUTE)); if (parser->m_atts == NULL) { FREE(parser, parser); return NULL; } #ifdef XML_ATTR_INFO - parser->m_attInfo = (XML_AttrInfo *)MALLOC( - parser, parser->m_attsSize * sizeof(XML_AttrInfo)); + parser->m_attInfo = MALLOC(parser, parser->m_attsSize * sizeof(XML_AttrInfo)); if (parser->m_attInfo == NULL) { FREE(parser, parser->m_atts); FREE(parser, parser); return NULL; } #endif - parser->m_dataBuf - = (XML_Char *)MALLOC(parser, INIT_DATA_BUF_SIZE * sizeof(XML_Char)); + parser->m_dataBuf = MALLOC(parser, INIT_DATA_BUF_SIZE * sizeof(XML_Char)); if (parser->m_dataBuf == NULL) { FREE(parser, parser->m_atts); #ifdef XML_ATTR_INFO @@ -1166,7 +1402,7 @@ if (dtd) parser->m_dtd = dtd; else { - parser->m_dtd = dtdCreate(&parser->m_mem); + parser->m_dtd = dtdCreate(parser); if (parser->m_dtd == NULL) { FREE(parser, parser->m_dataBuf); FREE(parser, parser->m_atts); @@ -1180,9 +1416,7 @@ parser->m_freeBindingList = NULL; parser->m_freeTagList = NULL; - parser->m_freeInternalEntities = NULL; - parser->m_freeAttributeEntities = NULL; - parser->m_freeValueEntities = NULL; + parser->m_freeEntities = NULL; parser->m_groupSize = 0; parser->m_groupConnector = NULL; @@ -1200,8 +1434,8 @@ parser->m_protocolEncodingName = NULL; - poolInit(&parser->m_tempPool, &(parser->m_mem)); - poolInit(&parser->m_temp2Pool, &(parser->m_mem)); + poolInit(&parser->m_tempPool, parser); + poolInit(&parser->m_temp2Pool, parser); parserInit(parser, encodingName); if (encodingName && ! parser->m_protocolEncodingName) { @@ -1233,7 +1467,7 @@ parser->m_processor = prologInitProcessor; XmlPrologStateInit(&parser->m_prologState); if (encodingName != NULL) { - parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem)); + parser->m_protocolEncodingName = copyString(encodingName, parser); } parser->m_curBase = NULL; XmlInitEncoding(&parser->m_initEncoding, &parser->m_encoding, 0); @@ -1295,16 +1529,18 @@ parser->m_unknownEncodingMem = NULL; parser->m_unknownEncodingRelease = NULL; parser->m_unknownEncodingData = NULL; - parser->m_parentParser = NULL; parser->m_parsingStatus.parsing = XML_INITIALIZED; // Reentry can only be triggered inside m_processor calls parser->m_reenter = XML_FALSE; + parser->m_handlerCallDepth = 0; #ifdef XML_DTD parser->m_isParamEntity = XML_FALSE; parser->m_useForeignDTD = XML_FALSE; parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; #endif - parser->m_hash_secret_salt = 0; + parser->m_hash_secret_salt_128.k[0] = 0; + parser->m_hash_secret_salt_128.k[1] = 0; + parser->m_hash_secret_salt_set = XML_FALSE; #if XML_GE == 1 memset(&parser->m_accounting, 0, sizeof(ACCOUNTING)); @@ -1330,12 +1566,22 @@ } } +/* Moves a list of entities onto the start of another list. */ +static void +moveEntityList(OPEN_INTERNAL_ENTITY **dst, OPEN_INTERNAL_ENTITY **src) { + for (OPEN_INTERNAL_ENTITY *head = *src; head != NULL;) { + OPEN_INTERNAL_ENTITY *const openEntity = head; + head = head->next; + openEntity->next = *dst; + *dst = openEntity; + } +} + XML_Bool XMLCALL XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) { TAG *tStk; - OPEN_INTERNAL_ENTITY *openEntityList; - if (parser == NULL) + if ((parser == NULL) || isCalledFromInsideHandler(parser)) return XML_FALSE; if (parser->m_parentParser) @@ -1350,32 +1596,14 @@ tag->bindings = NULL; parser->m_freeTagList = tag; } - /* move m_openInternalEntities to m_freeInternalEntities */ - openEntityList = parser->m_openInternalEntities; - while (openEntityList) { - OPEN_INTERNAL_ENTITY *openEntity = openEntityList; - openEntityList = openEntity->next; - openEntity->next = parser->m_freeInternalEntities; - parser->m_freeInternalEntities = openEntity; - } - /* move m_openAttributeEntities to m_freeAttributeEntities (i.e. same task but - * for attributes) */ - openEntityList = parser->m_openAttributeEntities; - while (openEntityList) { - OPEN_INTERNAL_ENTITY *openEntity = openEntityList; - openEntityList = openEntity->next; - openEntity->next = parser->m_freeAttributeEntities; - parser->m_freeAttributeEntities = openEntity; - } - /* move m_openValueEntities to m_freeValueEntities (i.e. same task but - * for value entities) */ - openEntityList = parser->m_openValueEntities; - while (openEntityList) { - OPEN_INTERNAL_ENTITY *openEntity = openEntityList; - openEntityList = openEntity->next; - openEntity->next = parser->m_freeValueEntities; - parser->m_freeValueEntities = openEntity; - } + /* move m_openInternalEntities to m_freeEntities */ + moveEntityList(&parser->m_freeEntities, &parser->m_openInternalEntities); + /* move m_openAttributeEntities to m_freeEntities (i.e. same task but for + * attributes) */ + moveEntityList(&parser->m_freeEntities, &parser->m_openAttributeEntities); + /* move m_openValueEntities to m_freeEntities (i.e. same task but for value + * entities) */ + moveEntityList(&parser->m_freeEntities, &parser->m_openValueEntities); moveToFreeBindingList(parser, parser->m_inheritedBindings); FREE(parser, parser->m_unknownEncodingMem); if (parser->m_unknownEncodingRelease) @@ -1385,7 +1613,7 @@ FREE(parser, (void *)parser->m_protocolEncodingName); parser->m_protocolEncodingName = NULL; parserInit(parser, encodingName); - dtdReset(parser->m_dtd, &parser->m_mem); + dtdReset(parser->m_dtd, parser); return XML_TRUE; } @@ -1421,7 +1649,7 @@ parser->m_protocolEncodingName = NULL; else { /* Copy the new encoding name into allocated memory */ - parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem)); + parser->m_protocolEncodingName = copyString(encodingName, parser); if (! parser->m_protocolEncodingName) return XML_STATUS_ERROR; } @@ -1450,6 +1678,7 @@ XML_ExternalEntityRefHandler oldExternalEntityRefHandler; XML_SkippedEntityHandler oldSkippedEntityHandler; XML_UnknownEncodingHandler oldUnknownEncodingHandler; + void *oldUnknownEncodingHandlerData; XML_ElementDeclHandler oldElementDeclHandler; XML_AttlistDeclHandler oldAttlistDeclHandler; XML_EntityDeclHandler oldEntityDeclHandler; @@ -1470,7 +1699,8 @@ from hash tables associated with either parser without us having to worry which hash secrets each table has. */ - unsigned long oldhash_secret_salt; + struct sipkey oldhash_secret_salt_128; + XML_Bool oldhash_secret_salt_set; XML_Bool oldReparseDeferralEnabled; /* Validate the oldParser parameter before we pull everything out of it */ @@ -1495,6 +1725,7 @@ oldExternalEntityRefHandler = parser->m_externalEntityRefHandler; oldSkippedEntityHandler = parser->m_skippedEntityHandler; oldUnknownEncodingHandler = parser->m_unknownEncodingHandler; + oldUnknownEncodingHandlerData = parser->m_unknownEncodingHandlerData; oldElementDeclHandler = parser->m_elementDeclHandler; oldAttlistDeclHandler = parser->m_attlistDeclHandler; oldEntityDeclHandler = parser->m_entityDeclHandler; @@ -1515,7 +1746,8 @@ from hash tables associated with either parser without us having to worry which hash secrets each table has. */ - oldhash_secret_salt = parser->m_hash_secret_salt; + oldhash_secret_salt_128 = parser->m_hash_secret_salt_128; + oldhash_secret_salt_set = parser->m_hash_secret_salt_set; oldReparseDeferralEnabled = parser->m_reparseDeferralEnabled; #ifdef XML_DTD @@ -1523,16 +1755,12 @@ newDtd = oldDtd; #endif /* XML_DTD */ - /* Note that the magical uses of the pre-processor to make field - access look more like C++ require that `parser' be overwritten - here. This makes this function more painful to follow than it - would be otherwise. - */ if (parser->m_ns) { XML_Char tmp[2] = {parser->m_namespaceSeparator, 0}; - parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd); + parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd, oldParser); } else { - parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd); + parser + = parserCreate(encodingName, &parser->m_mem, NULL, newDtd, oldParser); } if (! parser) @@ -1554,6 +1782,7 @@ parser->m_externalEntityRefHandler = oldExternalEntityRefHandler; parser->m_skippedEntityHandler = oldSkippedEntityHandler; parser->m_unknownEncodingHandler = oldUnknownEncodingHandler; + parser->m_unknownEncodingHandlerData = oldUnknownEncodingHandlerData; parser->m_elementDeclHandler = oldElementDeclHandler; parser->m_attlistDeclHandler = oldAttlistDeclHandler; parser->m_entityDeclHandler = oldEntityDeclHandler; @@ -1568,7 +1797,8 @@ parser->m_externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg; parser->m_defaultExpandInternalEntities = oldDefaultExpandInternalEntities; parser->m_ns_triplets = oldns_triplets; - parser->m_hash_secret_salt = oldhash_secret_salt; + parser->m_hash_secret_salt_128 = oldhash_secret_salt_128; + parser->m_hash_secret_salt_set = oldhash_secret_salt_set; parser->m_reparseDeferralEnabled = oldReparseDeferralEnabled; parser->m_parentParser = oldParser; #ifdef XML_DTD @@ -1576,7 +1806,7 @@ parser->m_prologState.inEntityValue = oldInEntityValue; if (context) { #endif /* XML_DTD */ - if (! dtdCopy(oldParser, parser->m_dtd, oldDtd, &parser->m_mem) + if (! dtdCopy(oldParser, parser->m_dtd, oldDtd, parser) || ! setContext(parser, context)) { XML_ParserFree(parser); return NULL; @@ -1614,8 +1844,7 @@ void XMLCALL XML_ParserFree(XML_Parser parser) { TAG *tagList; - OPEN_INTERNAL_ENTITY *entityList; - if (parser == NULL) + if ((parser == NULL) || isCalledFromInsideHandler(parser)) return; /* free m_tagStack and m_freeTagList */ tagList = parser->m_tagStack; @@ -1629,52 +1858,39 @@ } p = tagList; tagList = tagList->parent; - FREE(parser, p->buf); + FREE(parser, p->buf.raw); destroyBindings(p->bindings, parser); FREE(parser, p); } - /* free m_openInternalEntities and m_freeInternalEntities */ - entityList = parser->m_openInternalEntities; - for (;;) { - OPEN_INTERNAL_ENTITY *openEntity; - if (entityList == NULL) { - if (parser->m_freeInternalEntities == NULL) - break; - entityList = parser->m_freeInternalEntities; - parser->m_freeInternalEntities = NULL; - } - openEntity = entityList; + /* free m_openInternalEntities */ + for (OPEN_INTERNAL_ENTITY *entityList = parser->m_openInternalEntities; + entityList != NULL;) { + OPEN_INTERNAL_ENTITY *const openEntity = entityList; entityList = entityList->next; FREE(parser, openEntity); } - /* free m_openAttributeEntities and m_freeAttributeEntities */ - entityList = parser->m_openAttributeEntities; - for (;;) { - OPEN_INTERNAL_ENTITY *openEntity; - if (entityList == NULL) { - if (parser->m_freeAttributeEntities == NULL) - break; - entityList = parser->m_freeAttributeEntities; - parser->m_freeAttributeEntities = NULL; - } - openEntity = entityList; + /* free m_openAttributeEntities */ + for (OPEN_INTERNAL_ENTITY *entityList = parser->m_openAttributeEntities; + entityList != NULL;) { + OPEN_INTERNAL_ENTITY *const 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; + /* free m_openValueEntities */ + for (OPEN_INTERNAL_ENTITY *entityList = parser->m_openValueEntities; + entityList != NULL;) { + OPEN_INTERNAL_ENTITY *const openEntity = entityList; entityList = entityList->next; FREE(parser, openEntity); } + /* free m_freeEntities */ + for (OPEN_INTERNAL_ENTITY *entityList = parser->m_freeEntities; + entityList != NULL;) { + OPEN_INTERNAL_ENTITY *const openEntity = entityList; + entityList = entityList->next; + FREE(parser, openEntity); + } + parser->m_freeEntities = NULL; destroyBindings(parser->m_freeBindingList, parser); destroyBindings(parser->m_inheritedBindings, parser); poolDestroy(&parser->m_tempPool); @@ -1688,14 +1904,16 @@ #else if (parser->m_dtd) #endif /* XML_DTD */ - dtdDestroy(parser->m_dtd, (XML_Bool)! parser->m_parentParser, - &parser->m_mem); - FREE(parser, (void *)parser->m_atts); + dtdDestroy(parser->m_dtd, (XML_Bool)! parser->m_parentParser, parser); + FREE(parser, parser->m_atts); #ifdef XML_ATTR_INFO - FREE(parser, (void *)parser->m_attInfo); + FREE(parser, parser->m_attInfo); #endif FREE(parser, parser->m_groupConnector); - FREE(parser, parser->m_buffer); + // NOTE: We are avoiding FREE(..) here because parser->m_buffer + // is not being allocated with MALLOC(..) but with plain + // .malloc_fcn(..). + parser->m_mem.free_fcn(parser->m_buffer); FREE(parser, parser->m_dataBuf); FREE(parser, parser->m_nsAtts); FREE(parser, parser->m_unknownEncodingMem); @@ -2010,19 +2228,58 @@ #endif } +// DEPRECATED since Expat 2.8.0. int XMLCALL XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) { if (parser == NULL) return 0; - if (parser->m_parentParser) - return XML_SetHashSalt(parser->m_parentParser, hash_salt); + + const XML_Parser rootParser = getRootParserOf(parser, NULL); + assert(! rootParser->m_parentParser); + /* block after XML_Parse()/XML_ParseBuffer() has been called */ - if (parserBusy(parser)) + if (parserBusy(rootParser)) return 0; - parser->m_hash_secret_salt = hash_salt; + + rootParser->m_hash_secret_salt_128.k[0] = 0; + rootParser->m_hash_secret_salt_128.k[1] = hash_salt; + + if (hash_salt != 0) { // to remain backwards compatible + rootParser->m_hash_secret_salt_set = XML_TRUE; + + if (sizeof(unsigned long) == 4) + ENTROPY_DEBUG("explicit(4)", rootParser->m_hash_secret_salt_128); + else + ENTROPY_DEBUG("explicit(8)", rootParser->m_hash_secret_salt_128); + } + return 1; } +XML_Bool XMLCALL +XML_SetHashSalt16Bytes(XML_Parser parser, const uint8_t entropy[16]) { + if (parser == NULL) + return XML_FALSE; + + if (entropy == NULL) + return XML_FALSE; + + const XML_Parser rootParser = getRootParserOf(parser, NULL); + assert(! rootParser->m_parentParser); + + /* block after XML_Parse()/XML_ParseBuffer() has been called */ + if (parserBusy(rootParser)) + return XML_FALSE; + + sip_tokey(&(rootParser->m_hash_secret_salt_128), entropy); + + rootParser->m_hash_secret_salt_set = XML_TRUE; + + ENTROPY_DEBUG("explicit(16)", rootParser->m_hash_secret_salt_128); + + return XML_TRUE; +} + enum XML_Status XMLCALL XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) { if ((parser == NULL) || (len < 0) || ((s == NULL) && (len != 0))) { @@ -2030,6 +2287,8 @@ parser->m_errorCode = XML_ERROR_INVALID_ARGUMENT; return XML_STATUS_ERROR; } + if (isCalledFromInsideHandler(parser)) + return XML_STATUS_ERROR; switch (parser->m_parsingStatus.parsing) { case XML_SUSPENDED: parser->m_errorCode = XML_ERROR_SUSPENDED; @@ -2042,7 +2301,7 @@ parser->m_errorCode = XML_ERROR_NO_MEMORY; return XML_STATUS_ERROR; } - /* fall through */ + EXPAT_FALLTHROUGH; default: parser->m_parsingStatus.parsing = XML_PARSING; } @@ -2053,7 +2312,7 @@ int nLeftOver; enum XML_Status result; /* Detect overflow (a+b > MAX <==> b > MAX-a) */ - if ((XML_Size)len > ((XML_Size)-1) / 2 - parser->m_parseEndByteIndex) { + if (len > XML_INDEX_MAX - parser->m_parseEndByteIndex) { parser->m_errorCode = XML_ERROR_NO_MEMORY; parser->m_eventPtr = parser->m_eventEndPtr = NULL; parser->m_processor = errorProcessor; @@ -2084,7 +2343,7 @@ parser->m_parsingStatus.parsing = XML_FINISHED; return XML_STATUS_OK; } - /* fall through */ + EXPAT_FALLTHROUGH; default: result = XML_STATUS_OK; } @@ -2139,7 +2398,7 @@ const char *start; enum XML_Status result = XML_STATUS_OK; - if (parser == NULL) + if ((parser == NULL) || isCalledFromInsideHandler(parser)) return XML_STATUS_ERROR; if (len < 0) { @@ -2165,11 +2424,19 @@ parser->m_errorCode = XML_ERROR_NO_MEMORY; return XML_STATUS_ERROR; } - /* fall through */ + EXPAT_FALLTHROUGH; default: parser->m_parsingStatus.parsing = XML_PARSING; } + // Detect and avoid integer overflow + if (len > XML_INDEX_MAX - parser->m_parseEndByteIndex) { + parser->m_errorCode = XML_ERROR_NO_MEMORY; + parser->m_eventPtr = parser->m_eventEndPtr = NULL; + parser->m_processor = errorProcessor; + return XML_STATUS_ERROR; + } + start = parser->m_bufferPtr; parser->m_positionPtr = start; parser->m_bufferEnd += len; @@ -2195,6 +2462,7 @@ parser->m_parsingStatus.parsing = XML_FINISHED; return result; } + break; default:; /* should not happen */ } } @@ -2205,9 +2473,32 @@ return result; } +/* Modifies `parser`’s buffer to be backed by `newBuf`. */ +static void +setParserBuffer(XML_Parser parser, char *newBuf, int newBufSize, int keep) { + parser->m_bufferLim = newBuf + newBufSize; + if (parser->m_bufferPtr) { + const int parsing + = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr); + memcpy(newBuf, parser->m_bufferPtr - keep, parsing + keep); + // NOTE: We are avoiding FREE(..) here because parser->m_buffer + // is not being allocated with MALLOC(..) but with plain + // .malloc_fcn(..). + parser->m_mem.free_fcn(parser->m_buffer); + parser->m_buffer = newBuf; + parser->m_bufferEnd = newBuf + parsing + keep; + parser->m_bufferPtr = newBuf + keep; + } else { + /* This must be a brand new buffer with no data in it yet */ + parser->m_buffer = newBuf; + parser->m_bufferEnd = newBuf; + parser->m_bufferPtr = newBuf; + } +} + void *XMLCALL XML_GetBuffer(XML_Parser parser, int len) { - if (parser == NULL) + if ((parser == NULL) || isCalledFromInsideHandler(parser)) return NULL; if (len < 0) { parser->m_errorCode = XML_ERROR_NO_MEMORY; @@ -2228,9 +2519,6 @@ parser->m_lastBufferRequestSize = len; if (len > EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferEnd) || parser->m_buffer == NULL) { -#if XML_CONTEXT_BYTES > 0 - int keep; -#endif /* XML_CONTEXT_BYTES > 0 */ /* Do not invoke signed arithmetic overflow: */ int neededSize = (int)((unsigned)len + (unsigned)EXPAT_SAFE_PTR_DIFF( @@ -2240,7 +2528,9 @@ return NULL; } #if XML_CONTEXT_BYTES > 0 - keep = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer); + const int parsed + = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer); + int keep = parsed; if (keep > XML_CONTEXT_BYTES) keep = XML_CONTEXT_BYTES; /* Detect and prevent integer overflow */ @@ -2248,16 +2538,16 @@ parser->m_errorCode = XML_ERROR_NO_MEMORY; return NULL; } - neededSize += keep; +#else + int keep = 0; #endif /* XML_CONTEXT_BYTES > 0 */ + neededSize += keep; if (parser->m_buffer && parser->m_bufferPtr && neededSize <= EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_buffer)) { #if XML_CONTEXT_BYTES > 0 - if (keep < EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer)) { - int offset - = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer) - - keep; + if (keep < parsed) { + int offset = parsed - keep; /* The buffer pointers cannot be NULL here; we have at least some bytes * in the buffer */ memmove(parser->m_buffer, &parser->m_buffer[offset], @@ -2274,7 +2564,6 @@ parser->m_bufferPtr = parser->m_buffer; #endif /* XML_CONTEXT_BYTES > 0 */ } else { - char *newBuf; int bufferSize = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_buffer); if (bufferSize == 0) @@ -2287,43 +2576,14 @@ parser->m_errorCode = XML_ERROR_NO_MEMORY; return NULL; } - newBuf = (char *)MALLOC(parser, bufferSize); - if (newBuf == 0) { + // NOTE: We are avoiding MALLOC(..) here to leave limiting + // the input size to the application using Expat. + char *const newBuf = parser->m_mem.malloc_fcn(bufferSize); + if (newBuf == NULL) { parser->m_errorCode = XML_ERROR_NO_MEMORY; return NULL; } - parser->m_bufferLim = newBuf + bufferSize; -#if XML_CONTEXT_BYTES > 0 - if (parser->m_bufferPtr) { - memcpy(newBuf, &parser->m_bufferPtr[-keep], - EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr) - + keep); - FREE(parser, parser->m_buffer); - parser->m_buffer = newBuf; - parser->m_bufferEnd - = parser->m_buffer - + EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr) - + keep; - parser->m_bufferPtr = parser->m_buffer + keep; - } else { - /* This must be a brand new buffer with no data in it yet */ - parser->m_bufferEnd = newBuf; - parser->m_bufferPtr = parser->m_buffer = newBuf; - } -#else - if (parser->m_bufferPtr) { - memcpy(newBuf, parser->m_bufferPtr, - EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr)); - FREE(parser, parser->m_buffer); - parser->m_bufferEnd - = newBuf - + EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr); - } else { - /* This must be a brand new buffer with no data in it yet */ - parser->m_bufferEnd = newBuf; - } - parser->m_bufferPtr = parser->m_buffer = newBuf; -#endif /* XML_CONTEXT_BYTES > 0 */ + setParserBuffer(parser, newBuf, bufferSize, keep); } parser->m_eventPtr = parser->m_eventEndPtr = NULL; parser->m_positionPtr = NULL; @@ -2376,7 +2636,7 @@ XML_ResumeParser(XML_Parser parser) { enum XML_Status result = XML_STATUS_OK; - if (parser == NULL) + if ((parser == NULL) || isCalledFromInsideHandler(parser)) return XML_STATUS_ERROR; if (parser->m_parsingStatus.parsing != XML_SUSPENDED) { parser->m_errorCode = XML_ERROR_NOT_SUSPENDED; @@ -2402,6 +2662,7 @@ parser->m_parsingStatus.parsing = XML_FINISHED; return result; } + break; default:; } } @@ -2463,7 +2724,7 @@ (void)offset; (void)size; #endif /* XML_CONTEXT_BYTES > 0 */ - return (const char *)0; + return NULL; } XML_Size XMLCALL @@ -2492,28 +2753,43 @@ void XMLCALL XML_FreeContentModel(XML_Parser parser, XML_Content *model) { - if (parser != NULL) - FREE(parser, model); + if (parser == NULL) + return; + + // NOTE: We are avoiding FREE(..) here because the content model + // has been created using plain .malloc_fcn(..) rather than MALLOC(..). + parser->m_mem.free_fcn(model); } void *XMLCALL XML_MemMalloc(XML_Parser parser, size_t size) { if (parser == NULL) return NULL; - return MALLOC(parser, size); + + // NOTE: We are avoiding MALLOC(..) here to not include + // user allocations with allocation tracking and limiting. + return parser->m_mem.malloc_fcn(size); } void *XMLCALL XML_MemRealloc(XML_Parser parser, void *ptr, size_t size) { if (parser == NULL) return NULL; - return REALLOC(parser, ptr, size); + + // NOTE: We are avoiding REALLOC(..) here to not include + // user allocations with allocation tracking and limiting. + return parser->m_mem.realloc_fcn(ptr, size); } void XMLCALL XML_MemFree(XML_Parser parser, void *ptr) { - if (parser != NULL) - FREE(parser, ptr); + if (parser == NULL) + return; + + // NOTE: We are avoiding FREE(..) here because XML_MemMalloc and + // XML_MemRealloc are not using MALLOC(..) and REALLOC(..) + // but plain .malloc_fcn(..) and .realloc_fcn(..), internally. + parser->m_mem.free_fcn(ptr); } void XMLCALL @@ -2713,6 +2989,13 @@ EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT}, /* Added in Expat 2.6.0. */ {XML_FEATURE_GE, XML_L("XML_GE"), 0}, + /* Added in Expat 2.7.2. */ + {XML_FEATURE_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION_DEFAULT, + XML_L("XML_AT_MAX_AMP"), + (long int)EXPAT_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION_DEFAULT}, + {XML_FEATURE_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT, + XML_L("XML_AT_ACT_THRES"), + (long int)EXPAT_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT}, #endif {XML_FEATURE_END, NULL, 0}}; @@ -2741,6 +3024,29 @@ parser->m_accounting.activationThresholdBytes = activationThresholdBytes; return XML_TRUE; } + +XML_Bool XMLCALL +XML_SetAllocTrackerMaximumAmplification(XML_Parser parser, + float maximumAmplificationFactor) { + if ((parser == NULL) || (parser->m_parentParser != NULL) + || isnan(maximumAmplificationFactor) + || (maximumAmplificationFactor < 1.0f)) { + return XML_FALSE; + } + parser->m_alloc_tracker.maximumAmplificationFactor + = maximumAmplificationFactor; + return XML_TRUE; +} + +XML_Bool XMLCALL +XML_SetAllocTrackerActivationThreshold( + XML_Parser parser, unsigned long long activationThresholdBytes) { + if ((parser == NULL) || (parser->m_parentParser != NULL)) { + return XML_FALSE; + } + parser->m_alloc_tracker.activationThresholdBytes = activationThresholdBytes; + return XML_TRUE; +} #endif /* XML_GE == 1 */ XML_Bool XMLCALL @@ -2761,10 +3067,10 @@ storeRawNames(XML_Parser parser) { TAG *tag = parser->m_tagStack; while (tag) { - int bufSize; - int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1); + size_t bufSize; + size_t nameLen = sizeof(XML_Char) * (tag->name.strLen + 1); size_t rawNameLen; - char *rawNameBuf = tag->buf + nameLen; + char *rawNameBuf = tag->buf.raw + nameLen; /* Stop if already stored. Since m_tagStack is a stack, we can stop at the first entry that has already been copied; everything below it in the stack is already been accounted for in a @@ -2777,25 +3083,25 @@ */ rawNameLen = ROUND_UP(tag->rawNameLength, sizeof(XML_Char)); /* Detect and prevent integer overflow. */ - if (rawNameLen > (size_t)INT_MAX - nameLen) + if (rawNameLen > SIZE_MAX - nameLen) return XML_FALSE; - bufSize = nameLen + (int)rawNameLen; - if (bufSize > tag->bufEnd - tag->buf) { - char *temp = (char *)REALLOC(parser, tag->buf, bufSize); + bufSize = nameLen + rawNameLen; + if (bufSize > (size_t)(tag->bufEnd - tag->buf.raw)) { + char *temp = REALLOC(parser, tag->buf.raw, bufSize); if (temp == NULL) return XML_FALSE; - /* if tag->name.str points to tag->buf (only when namespace + /* if tag->name.str points to tag->buf.str (only when namespace processing is off) then we have to update it */ - if (tag->name.str == (XML_Char *)tag->buf) + if (tag->name.str == tag->buf.str) tag->name.str = (XML_Char *)temp; /* if tag->name.localPart is set (when namespace processing is on) then update it as well, since it will always point into tag->buf */ if (tag->name.localPart) tag->name.localPart - = (XML_Char *)temp + (tag->name.localPart - (XML_Char *)tag->buf); - tag->buf = temp; + = (XML_Char *)temp + (tag->name.localPart - tag->buf.str); + tag->buf.raw = temp; tag->bufEnd = temp + bufSize; rawNameBuf = temp + nameLen; } @@ -2904,7 +3210,7 @@ if (parser->m_reenter) { return XML_ERROR_UNEXPECTED_STATE; // LCOV_EXCL_LINE } - /* Fall through */ + EXPAT_FALLTHROUGH; default: start = next; } @@ -2983,7 +3289,9 @@ *eventEndPP = end; if (parser->m_characterDataHandler) { XML_Char c = 0xA; + beforeHandler(parser); parser->m_characterDataHandler(parser->m_handlerArg, &c, 1); + afterHandler(parser); } else if (parser->m_defaultHandler) reportDefault(parser, enc, s, end); /* We are at the end of the final buffer, should we check for @@ -3036,9 +3344,11 @@ ((char *)&ch) + sizeof(XML_Char), __LINE__, XML_ACCOUNT_ENTITY_EXPANSION); #endif /* XML_GE == 1 */ - if (parser->m_characterDataHandler) + if (parser->m_characterDataHandler) { + beforeHandler(parser); parser->m_characterDataHandler(parser->m_handlerArg, &ch, 1); - else if (parser->m_defaultHandler) + afterHandler(parser); + } else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); break; } @@ -3058,9 +3368,11 @@ else if (! entity->is_internal) return XML_ERROR_ENTITY_DECLARED_IN_PE; } else if (! entity) { - if (parser->m_skippedEntityHandler) + if (parser->m_skippedEntityHandler) { + beforeHandler(parser); parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0); - else if (parser->m_defaultHandler) + afterHandler(parser); + } else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); break; } @@ -3071,10 +3383,12 @@ if (entity->textPtr) { enum XML_Error result; if (! parser->m_defaultExpandInternalEntities) { - if (parser->m_skippedEntityHandler) + if (parser->m_skippedEntityHandler) { + beforeHandler(parser); parser->m_skippedEntityHandler(parser->m_handlerArg, entity->name, 0); - else if (parser->m_defaultHandler) + afterHandler(parser); + } else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); break; } @@ -3088,9 +3402,12 @@ entity->open = XML_FALSE; if (! context) return XML_ERROR_NO_MEMORY; - if (! parser->m_externalEntityRefHandler( - parser->m_externalEntityRefHandlerArg, context, entity->base, - entity->systemId, entity->publicId)) + beforeHandler(parser); + const int status = parser->m_externalEntityRefHandler( + parser->m_externalEntityRefHandlerArg, context, entity->base, + entity->systemId, entity->publicId); + afterHandler(parser); + if (! status) return XML_ERROR_EXTERNAL_ENTITY_HANDLING; poolDiscard(&parser->m_tempPool); } else if (parser->m_defaultHandler) @@ -3098,7 +3415,6 @@ break; } case XML_TOK_START_TAG_NO_ATTS: - /* fall through */ case XML_TOK_START_TAG_WITH_ATTS: { TAG *tag; enum XML_Error result; @@ -3107,15 +3423,15 @@ tag = parser->m_freeTagList; parser->m_freeTagList = parser->m_freeTagList->parent; } else { - tag = (TAG *)MALLOC(parser, sizeof(TAG)); + tag = MALLOC(parser, sizeof(TAG)); if (! tag) return XML_ERROR_NO_MEMORY; - tag->buf = (char *)MALLOC(parser, INIT_TAG_BUF_SIZE); - if (! tag->buf) { + tag->buf.raw = MALLOC(parser, INIT_TAG_BUF_SIZE); + if (! tag->buf.raw) { FREE(parser, tag); return XML_ERROR_NO_MEMORY; } - tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE; + tag->bufEnd = tag->buf.raw + INIT_TAG_BUF_SIZE; } tag->bindings = NULL; tag->parent = parser->m_tagStack; @@ -3128,46 +3444,47 @@ { const char *rawNameEnd = tag->rawName + tag->rawNameLength; const char *fromPtr = tag->rawName; - toPtr = (XML_Char *)tag->buf; + toPtr = tag->buf.str; for (;;) { - int bufSize; - int convLen; const enum XML_Convert_Result convert_res = XmlConvert(enc, &fromPtr, rawNameEnd, (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1); - convLen = (int)(toPtr - (XML_Char *)tag->buf); + const size_t convLen = (size_t)(toPtr - tag->buf.str); if ((fromPtr >= rawNameEnd) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) { tag->name.strLen = convLen; break; } - bufSize = (int)(tag->bufEnd - tag->buf) << 1; + if (SIZE_MAX / 2 < (size_t)(tag->bufEnd - tag->buf.raw)) + return XML_ERROR_NO_MEMORY; + const size_t bufSize = (size_t)(tag->bufEnd - tag->buf.raw) * 2; { - char *temp = (char *)REALLOC(parser, tag->buf, bufSize); + char *temp = REALLOC(parser, tag->buf.raw, bufSize); if (temp == NULL) return XML_ERROR_NO_MEMORY; - tag->buf = temp; + tag->buf.raw = temp; tag->bufEnd = temp + bufSize; toPtr = (XML_Char *)temp + convLen; } } } - tag->name.str = (XML_Char *)tag->buf; + tag->name.str = tag->buf.str; *toPtr = XML_T('\0'); result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings), account); if (result) return result; - if (parser->m_startElementHandler) + if (parser->m_startElementHandler) { + beforeHandler(parser); parser->m_startElementHandler(parser->m_handlerArg, tag->name.str, (const XML_Char **)parser->m_atts); - else if (parser->m_defaultHandler) + afterHandler(parser); + } else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); poolClear(&parser->m_tempPool); break; } case XML_TOK_EMPTY_ELEMENT_NO_ATTS: - /* fall through */ case XML_TOK_EMPTY_ELEMENT_WITH_ATTS: { const char *rawName = s + enc->minBytesPerChar; enum XML_Error result; @@ -3187,14 +3504,18 @@ } poolFinish(&parser->m_tempPool); if (parser->m_startElementHandler) { + beforeHandler(parser); parser->m_startElementHandler(parser->m_handlerArg, name.str, (const XML_Char **)parser->m_atts); + afterHandler(parser); noElmHandlers = XML_FALSE; } if (parser->m_endElementHandler) { if (parser->m_startElementHandler) *eventPP = *eventEndPP; + beforeHandler(parser); parser->m_endElementHandler(parser->m_handlerArg, name.str); + afterHandler(parser); noElmHandlers = XML_FALSE; } if (noElmHandlers && parser->m_defaultHandler) @@ -3252,14 +3573,19 @@ } *uri = XML_T('\0'); } + beforeHandler(parser); parser->m_endElementHandler(parser->m_handlerArg, tag->name.str); + afterHandler(parser); } else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); while (tag->bindings) { BINDING *b = tag->bindings; - if (parser->m_endNamespaceDeclHandler) + if (parser->m_endNamespaceDeclHandler) { + beforeHandler(parser); parser->m_endNamespaceDeclHandler(parser->m_handlerArg, b->prefix->name); + afterHandler(parser); + } tag->bindings = tag->bindings->nextTagBinding; b->nextTagBinding = parser->m_freeBindingList; parser->m_freeBindingList = b; @@ -3282,8 +3608,10 @@ return XML_ERROR_BAD_CHAR_REF; if (parser->m_characterDataHandler) { XML_Char buf[XML_ENCODE_MAX]; + beforeHandler(parser); parser->m_characterDataHandler(parser->m_handlerArg, buf, XmlEncode(n, (ICHAR *)buf)); + afterHandler(parser); } else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); } break; @@ -3292,32 +3620,38 @@ case XML_TOK_DATA_NEWLINE: if (parser->m_characterDataHandler) { XML_Char c = 0xA; + beforeHandler(parser); parser->m_characterDataHandler(parser->m_handlerArg, &c, 1); + afterHandler(parser); } else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); break; case XML_TOK_CDATA_SECT_OPEN: { enum XML_Error result; - if (parser->m_startCdataSectionHandler) + if (parser->m_startCdataSectionHandler) { + beforeHandler(parser); parser->m_startCdataSectionHandler(parser->m_handlerArg); - /* BEGIN disabled code */ - /* Suppose you doing a transformation on a document that involves - changing only the character data. You set up a defaultHandler - and a characterDataHandler. The defaultHandler simply copies - characters through. The characterDataHandler does the - transformation and writes the characters out escaping them as - necessary. This case will fail to work if we leave out the - following two lines (because & and < inside CDATA sections will - be incorrectly escaped). + afterHandler(parser); + /* BEGIN disabled code */ + /* Suppose you doing a transformation on a document that involves + changing only the character data. You set up a defaultHandler + and a characterDataHandler. The defaultHandler simply copies + characters through. The characterDataHandler does the + transformation and writes the characters out escaping them as + necessary. This case will fail to work if we leave out the + following two lines (because & and < inside CDATA sections will + be incorrectly escaped). - However, now we have a start/endCdataSectionHandler, so it seems - easier to let the user deal with this. - */ - else if ((0) && parser->m_characterDataHandler) + However, now we have a start/endCdataSectionHandler, so it seems + easier to let the user deal with this. + */ + } else if ((0) && parser->m_characterDataHandler) { + beforeHandler(parser); parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf, 0); - /* END disabled code */ - else if (parser->m_defaultHandler) + afterHandler(parser); + /* END disabled code */ + } else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore, account); @@ -3337,13 +3671,18 @@ if (MUST_CONVERT(enc, s)) { ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf; XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)parser->m_dataBufEnd); + beforeHandler(parser); parser->m_characterDataHandler( parser->m_handlerArg, parser->m_dataBuf, (int)(dataPtr - (ICHAR *)parser->m_dataBuf)); - } else + afterHandler(parser); + } else { + beforeHandler(parser); parser->m_characterDataHandler( parser->m_handlerArg, (const XML_Char *)s, (int)((const XML_Char *)end - (const XML_Char *)s)); + afterHandler(parser); + } } else if (parser->m_defaultHandler) reportDefault(parser, enc, s, end); /* We are at the end of the final buffer, should we check for @@ -3368,16 +3707,21 @@ const enum XML_Convert_Result convert_res = XmlConvert( enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd); *eventEndPP = s; + beforeHandler(parser); charDataHandler(parser->m_handlerArg, parser->m_dataBuf, (int)(dataPtr - (ICHAR *)parser->m_dataBuf)); + afterHandler(parser); if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) break; *eventPP = s; } - } else + } else { + beforeHandler(parser); charDataHandler(parser->m_handlerArg, (const XML_Char *)s, (int)((const XML_Char *)next - (const XML_Char *)s)); + afterHandler(parser); + } } else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); } break; @@ -3415,7 +3759,7 @@ *nextPtr = next; return XML_ERROR_NONE; } - /* Fall through */ + EXPAT_FALLTHROUGH; default:; *eventPP = s = next; } @@ -3435,8 +3779,11 @@ /* m_startNamespaceDeclHandler will have been called for this * binding in addBindings(), so call the end handler now. */ - if (parser->m_endNamespaceDeclHandler) + if (parser->m_endNamespaceDeclHandler) { + beforeHandler(parser); parser->m_endNamespaceDeclHandler(parser->m_handlerArg, b->prefix->name); + afterHandler(parser); + } bindings = bindings->nextTagBinding; b->nextTagBinding = parser->m_freeBindingList; @@ -3460,20 +3807,14 @@ TAG_NAME *tagNamePtr, BINDING **bindingsPtr, enum XML_Account account) { DTD *const dtd = parser->m_dtd; /* save one level of indirection */ - ELEMENT_TYPE *elementType; - int nDefaultAtts; - const XML_Char **appAtts; /* the attribute list for the application */ int attIndex = 0; - int prefixLen; - int i; - int n; XML_Char *uri; int nPrefixes = 0; BINDING *binding; const XML_Char *localPart; /* lookup the element type name */ - elementType + ELEMENT_TYPE *elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str, 0); if (! elementType) { const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str); @@ -3483,78 +3824,76 @@ sizeof(ELEMENT_TYPE)); if (! elementType) return XML_ERROR_NO_MEMORY; + if (! elementType->defaultAttsNames.parser) + hashTableInit(&(elementType->defaultAttsNames), parser); if (parser->m_ns && ! setElementTypePrefix(parser, elementType)) return XML_ERROR_NO_MEMORY; } - nDefaultAtts = elementType->nDefaultAtts; + const size_t nDefaultAtts = elementType->nDefaultAtts; + + /* Detect and prevent integer overflow. */ + if (parser->m_attsSize > (size_t)INT_MAX) + return XML_ERROR_NO_MEMORY; /* get the attributes from the tokenizer */ - n = XmlGetAttributes(enc, attStr, parser->m_attsSize, parser->m_atts); + size_t n = (size_t)XmlGetAttributes(enc, attStr, (int)parser->m_attsSize, + parser->m_atts); /* Detect and prevent integer overflow */ - if (n > INT_MAX - nDefaultAtts) { + if (n > SIZE_MAX - nDefaultAtts) { return XML_ERROR_NO_MEMORY; } if (n + nDefaultAtts > parser->m_attsSize) { - int oldAttsSize = parser->m_attsSize; - ATTRIBUTE *temp; -#ifdef XML_ATTR_INFO - XML_AttrInfo *temp2; -#endif + size_t oldAttsSize = parser->m_attsSize; /* Detect and prevent integer overflow */ - if ((nDefaultAtts > INT_MAX - INIT_ATTS_SIZE) - || (n > INT_MAX - (nDefaultAtts + INIT_ATTS_SIZE))) { + if ((nDefaultAtts > SIZE_MAX - INIT_ATTS_SIZE) + || (n > SIZE_MAX - (nDefaultAtts + INIT_ATTS_SIZE))) { return XML_ERROR_NO_MEMORY; } parser->m_attsSize = n + nDefaultAtts + INIT_ATTS_SIZE; - /* Detect and prevent integer overflow. - * The preprocessor guard addresses the "always false" warning - * from -Wtype-limits on platforms where - * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ -#if UINT_MAX >= SIZE_MAX - if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(ATTRIBUTE)) { + /* Detect and prevent integer overflow. */ + if (parser->m_attsSize > SIZE_MAX / sizeof(ATTRIBUTE)) { parser->m_attsSize = oldAttsSize; return XML_ERROR_NO_MEMORY; } -#endif - temp = (ATTRIBUTE *)REALLOC(parser, (void *)parser->m_atts, - parser->m_attsSize * sizeof(ATTRIBUTE)); + ATTRIBUTE *const temp = REALLOC(parser, parser->m_atts, + parser->m_attsSize * sizeof(ATTRIBUTE)); if (temp == NULL) { parser->m_attsSize = oldAttsSize; return XML_ERROR_NO_MEMORY; } parser->m_atts = temp; #ifdef XML_ATTR_INFO - /* Detect and prevent integer overflow. - * The preprocessor guard addresses the "always false" warning - * from -Wtype-limits on platforms where - * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ -# if UINT_MAX >= SIZE_MAX - if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(XML_AttrInfo)) { + /* Detect and prevent integer overflow. */ + if (parser->m_attsSize > SIZE_MAX / sizeof(XML_AttrInfo)) { parser->m_attsSize = oldAttsSize; return XML_ERROR_NO_MEMORY; } -# endif - temp2 = (XML_AttrInfo *)REALLOC(parser, (void *)parser->m_attInfo, - parser->m_attsSize * sizeof(XML_AttrInfo)); + XML_AttrInfo *const temp2 = REALLOC( + parser, parser->m_attInfo, parser->m_attsSize * sizeof(XML_AttrInfo)); if (temp2 == NULL) { parser->m_attsSize = oldAttsSize; return XML_ERROR_NO_MEMORY; } parser->m_attInfo = temp2; #endif - if (n > oldAttsSize) - XmlGetAttributes(enc, attStr, n, parser->m_atts); + if (n > oldAttsSize) { + /* Detect and prevent integer overflow. */ + if (n > (size_t)INT_MAX) + return XML_ERROR_NO_MEMORY; + XmlGetAttributes(enc, attStr, (int)n, parser->m_atts); + } } - appAtts = (const XML_Char **)parser->m_atts; - for (i = 0; i < n; i++) { + /* the attribute list for the application */ + const XML_Char **const appAtts = (const XML_Char **)parser->m_atts; + for (size_t i = 0; i < n; i++) { ATTRIBUTE *currAtt = &parser->m_atts[i]; #ifdef XML_ATTR_INFO XML_AttrInfo *currAttInfo = &parser->m_attInfo[i]; @@ -3587,13 +3926,11 @@ (attId->name)[-1] = 1; appAtts[attIndex++] = attId->name; if (! parser->m_atts[i].normalized) { - enum XML_Error result; XML_Bool isCdata = XML_TRUE; /* figure out whether declared as other than CDATA */ if (attId->maybeTokenized) { - int j; - for (j = 0; j < nDefaultAtts; j++) { + for (size_t j = 0; j < nDefaultAtts; j++) { if (attId == elementType->defaultAtts[j].id) { isCdata = elementType->defaultAtts[j].isCdata; break; @@ -3602,7 +3939,7 @@ } /* normalize the attribute value */ - result = storeAttributeValue( + const enum XML_Error result = storeAttributeValue( parser, enc, isCdata, parser->m_atts[i].valuePtr, parser->m_atts[i].valueEnd, &parser->m_tempPool, account); if (result) @@ -3640,7 +3977,7 @@ /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */ parser->m_nSpecifiedAtts = attIndex; if (elementType->idAtt && (elementType->idAtt->name)[-1]) { - for (i = 0; i < attIndex; i += 2) + for (int i = 0; i < attIndex; i += 2) if (appAtts[i] == elementType->idAtt->name) { parser->m_idAttIndex = i; break; @@ -3649,7 +3986,7 @@ parser->m_idAttIndex = -1; /* do attribute defaulting */ - for (i = 0; i < nDefaultAtts; i++) { + for (size_t i = 0; i < nDefaultAtts; i++) { const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i; if (! (da->id->name)[-1] && da->value) { if (da->id->prefix) { @@ -3675,9 +4012,9 @@ /* expand prefixed attribute names, check for duplicates, and clear flags that say whether attributes were specified */ - i = 0; + int i = 0; if (nPrefixes) { - int j; /* hash table index */ + unsigned int j; /* hash table index */ unsigned long version = parser->m_nsAttsVersion; /* Detect and prevent invalid shift */ @@ -3690,7 +4027,6 @@ /* size of hash table must be at least 2 * (# of prefixed attributes) */ if ((nPrefixes << 1) >> parser->m_nsAttsPower) { /* true for m_nsAttsPower = 0 */ - NS_ATT *temp; /* hash table size must also be a power of 2 and >= 8 */ while (nPrefixes >> parser->m_nsAttsPower++) ; @@ -3711,15 +4047,15 @@ * from -Wtype-limits on platforms where * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX - if (nsAttsSize > (size_t)(-1) / sizeof(NS_ATT)) { + if (nsAttsSize > SIZE_MAX / sizeof(NS_ATT)) { /* Restore actual size of memory in m_nsAtts */ parser->m_nsAttsPower = oldNsAttsPower; return XML_ERROR_NO_MEMORY; } #endif - temp = (NS_ATT *)REALLOC(parser, parser->m_nsAtts, - nsAttsSize * sizeof(NS_ATT)); + NS_ATT *const temp + = REALLOC(parser, parser->m_nsAtts, nsAttsSize * sizeof(NS_ATT)); if (! temp) { /* Restore actual size of memory in m_nsAtts */ parser->m_nsAttsPower = oldNsAttsPower; @@ -3740,9 +4076,6 @@ for (; i < attIndex; i += 2) { const XML_Char *s = appAtts[i]; if (s[-1] == 2) { /* prefixed */ - ATTRIBUTE_ID *id; - const BINDING *b; - unsigned long uriHash; struct siphash sip_state; struct sipkey sip_key; @@ -3750,7 +4083,8 @@ sip24_init(&sip_state, &sip_key); ((XML_Char *)s)[-1] = 0; /* clear flag */ - id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0); + ATTRIBUTE_ID *const id + = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0); if (! id || ! id->prefix) { /* This code is walking through the appAtts array, dealing * with (in this case) a prefixed attribute name. To be in @@ -3758,7 +4092,7 @@ * has to have passed through the hash table lookup once * already. That implies that an entry for it already * exists, so the lookup above will return a pointer to - * already allocated memory. There is no opportunaity for + * already allocated memory. There is no opportunity for * the allocator to fail, so the condition above cannot be * fulfilled. * @@ -3768,15 +4102,12 @@ */ return XML_ERROR_NO_MEMORY; /* LCOV_EXCL_LINE */ } - b = id->prefix->binding; + const BINDING *const b = id->prefix->binding; if (! b) return XML_ERROR_UNBOUND_PREFIX; - for (j = 0; j < b->uriLen; j++) { - const XML_Char c = b->uri[j]; - if (! poolAppendChar(&parser->m_tempPool, c)) - return XML_ERROR_NO_MEMORY; - } + if (! poolAppendChars(&parser->m_tempPool, b->uri, b->uriLen)) + return XML_ERROR_NO_MEMORY; sip24_update(&sip_state, b->uri, b->uriLen * sizeof(XML_Char)); @@ -3785,12 +4116,13 @@ sip24_update(&sip_state, s, keylen(s) * sizeof(XML_Char)); - do { /* copies null terminator */ - if (! poolAppendChar(&parser->m_tempPool, *s)) + { + const size_t len = xcslen(s) + /*null terminator*/ 1; + if (! poolAppendChars(&parser->m_tempPool, s, len)) return XML_ERROR_NO_MEMORY; - } while (*s++); + } - uriHash = (unsigned long)sip24_final(&sip_state); + const unsigned long uriHash = (unsigned long)sip24_final(&sip_state); { /* Check hash table for duplicate of expanded name (uriName). Derived from code in lookup(parser, HASH_TABLE *table, ...). @@ -3818,10 +4150,9 @@ if (parser->m_ns_triplets) { /* append namespace separator and prefix */ parser->m_tempPool.ptr[-1] = parser->m_namespaceSeparator; s = b->prefix->name; - do { - if (! poolAppendChar(&parser->m_tempPool, *s)) - return XML_ERROR_NO_MEMORY; - } while (*s++); + const size_t len = xcslen(s) + /*null terminator*/ 1; + if (! poolAppendChars(&parser->m_tempPool, s, len)) + return XML_ERROR_NO_MEMORY; } /* store expanded name in attribute list */ @@ -3864,48 +4195,36 @@ localPart = tagNamePtr->str; } else return XML_ERROR_NONE; - prefixLen = 0; - if (parser->m_ns_triplets && binding->prefix->name) { - for (; binding->prefix->name[prefixLen++];) - ; /* prefixLen includes null terminator */ - } + size_t prefixLen = 0; + if (parser->m_ns_triplets && binding->prefix->name) + prefixLen = xcslen(binding->prefix->name) + /*null terminator*/ 1; tagNamePtr->localPart = localPart; tagNamePtr->uriLen = binding->uriLen; tagNamePtr->prefix = binding->prefix->name; tagNamePtr->prefixLen = prefixLen; - for (i = 0; localPart[i++];) - ; /* i includes null terminator */ + + const size_t localPartLen = xcslen(localPart) + /*null terminator*/ 1; /* Detect and prevent integer overflow */ - if (binding->uriLen > INT_MAX - prefixLen - || i > INT_MAX - (binding->uriLen + prefixLen)) { + if (binding->uriLen > SIZE_MAX - prefixLen + || localPartLen > SIZE_MAX - (binding->uriLen + prefixLen)) { return XML_ERROR_NO_MEMORY; } - n = i + binding->uriLen + prefixLen; - if (n > binding->uriAlloc) { - TAG *p; - + const size_t totalLen = localPartLen + binding->uriLen + prefixLen; + if (totalLen > binding->uriAlloc) { /* Detect and prevent integer overflow */ - if (n > INT_MAX - EXPAND_SPARE) { - return XML_ERROR_NO_MEMORY; - } - /* Detect and prevent integer overflow. - * The preprocessor guard addresses the "always false" warning - * from -Wtype-limits on platforms where - * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ -#if UINT_MAX >= SIZE_MAX - if ((unsigned)(n + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) { + if (totalLen > SIZE_MAX - EXPAND_SPARE + || totalLen + EXPAND_SPARE > SIZE_MAX / sizeof(XML_Char)) { return XML_ERROR_NO_MEMORY; } -#endif - uri = (XML_Char *)MALLOC(parser, (n + EXPAND_SPARE) * sizeof(XML_Char)); + uri = MALLOC(parser, (totalLen + EXPAND_SPARE) * sizeof(XML_Char)); if (! uri) return XML_ERROR_NO_MEMORY; - binding->uriAlloc = n + EXPAND_SPARE; + binding->uriAlloc = totalLen + EXPAND_SPARE; memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char)); - for (p = parser->m_tagStack; p; p = p->parent) + for (TAG *p = parser->m_tagStack; p; p = p->parent) if (p->name.str == binding->uri) p->name.str = uri; FREE(parser, binding->uri); @@ -3913,10 +4232,14 @@ } /* if m_namespaceSeparator != '\0' then uri includes it already */ uri = binding->uri + binding->uriLen; - memcpy(uri, localPart, i * sizeof(XML_Char)); + /* Detect and prevent integer overflow */ + if (localPartLen > SIZE_MAX / sizeof(XML_Char)) { + return XML_ERROR_NO_MEMORY; + } + memcpy(uri, localPart, localPartLen * sizeof(XML_Char)); /* we always have a namespace separator between localPart and prefix */ if (prefixLen) { - uri += i - 1; + uri += localPartLen - 1; *uri = parser->m_namespaceSeparator; /* replace null terminator */ memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char)); } @@ -4051,7 +4374,7 @@ ASCII_8, ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m, ASCII_e, ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0'}; - static const int xmlLen = (int)sizeof(xmlNamespace) / sizeof(XML_Char) - 1; + static const size_t xmlLen = sizeof(xmlNamespace) / sizeof(XML_Char) - 1; // "http://www.w3.org/2000/xmlns/" static const XML_Char xmlnsNamespace[] = {ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, @@ -4059,15 +4382,14 @@ ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_2, ASCII_0, ASCII_0, ASCII_0, ASCII_SLASH, ASCII_x, ASCII_m, ASCII_l, ASCII_n, ASCII_s, ASCII_SLASH, '\0'}; - static const int xmlnsLen - = (int)sizeof(xmlnsNamespace) / sizeof(XML_Char) - 1; + static const size_t xmlnsLen = sizeof(xmlnsNamespace) / sizeof(XML_Char) - 1; XML_Bool mustBeXML = XML_FALSE; XML_Bool isXML = XML_TRUE; XML_Bool isXMLNS = XML_TRUE; BINDING *b; - int len; + size_t len; /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */ if (*uri == XML_T('\0') && prefix->name) @@ -4086,6 +4408,10 @@ } for (len = 0; uri[len]; len++) { + /* Detect and prevent integer overflow */ + if (len == SIZE_MAX) { + return XML_ERROR_NO_MEMORY; + } if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len])) isXML = XML_FALSE; @@ -4126,28 +4452,24 @@ if (isXMLNS) return XML_ERROR_RESERVED_NAMESPACE_URI; - if (parser->m_namespaceSeparator) + if (parser->m_namespaceSeparator) { + /* Detect and prevent integer overflow */ + if (len == SIZE_MAX) { + return XML_ERROR_NO_MEMORY; + } len++; + } if (parser->m_freeBindingList) { b = parser->m_freeBindingList; if (len > b->uriAlloc) { /* Detect and prevent integer overflow */ - if (len > INT_MAX - EXPAND_SPARE) { - return XML_ERROR_NO_MEMORY; - } - - /* Detect and prevent integer overflow. - * The preprocessor guard addresses the "always false" warning - * from -Wtype-limits on platforms where - * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ -#if UINT_MAX >= SIZE_MAX - if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) { + if (len > SIZE_MAX - EXPAND_SPARE + || len + EXPAND_SPARE > SIZE_MAX / sizeof(XML_Char)) { return XML_ERROR_NO_MEMORY; } -#endif - XML_Char *temp = (XML_Char *)REALLOC( - parser, b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE)); + XML_Char *temp + = REALLOC(parser, b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE)); if (temp == NULL) return XML_ERROR_NO_MEMORY; b->uri = temp; @@ -4155,26 +4477,17 @@ } parser->m_freeBindingList = b->nextTagBinding; } else { - b = (BINDING *)MALLOC(parser, sizeof(BINDING)); + b = MALLOC(parser, sizeof(BINDING)); if (! b) return XML_ERROR_NO_MEMORY; /* Detect and prevent integer overflow */ - if (len > INT_MAX - EXPAND_SPARE) { + if (len > SIZE_MAX - EXPAND_SPARE + || len + EXPAND_SPARE > SIZE_MAX / sizeof(XML_Char)) { return XML_ERROR_NO_MEMORY; } - /* Detect and prevent integer overflow. - * The preprocessor guard addresses the "always false" warning - * from -Wtype-limits on platforms where - * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ -#if UINT_MAX >= SIZE_MAX - if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) { - return XML_ERROR_NO_MEMORY; - } -#endif - b->uri - = (XML_Char *)MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE)); + b->uri = MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE)); if (! b->uri) { FREE(parser, b); return XML_ERROR_NO_MEMORY; @@ -4196,9 +4509,12 @@ b->nextTagBinding = *bindingsPtr; *bindingsPtr = b; /* if attId == NULL then we are not starting a namespace scope */ - if (attId && parser->m_startNamespaceDeclHandler) + if (attId && parser->m_startNamespaceDeclHandler) { + beforeHandler(parser); parser->m_startNamespaceDeclHandler(parser->m_handlerArg, prefix->name, prefix->binding ? uri : 0); + afterHandler(parser); + } return XML_ERROR_NONE; } @@ -4260,15 +4576,20 @@ *eventEndPP = next; switch (tok) { case XML_TOK_CDATA_SECT_CLOSE: - if (parser->m_endCdataSectionHandler) + if (parser->m_endCdataSectionHandler) { + beforeHandler(parser); parser->m_endCdataSectionHandler(parser->m_handlerArg); + afterHandler(parser); + } /* BEGIN disabled code */ /* see comment under XML_TOK_CDATA_SECT_OPEN */ - else if ((0) && parser->m_characterDataHandler) + else if ((0) && parser->m_characterDataHandler) { + beforeHandler(parser); parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf, 0); - /* END disabled code */ - else if (parser->m_defaultHandler) + afterHandler(parser); + /* END disabled code */ + } else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); *startPtr = next; *nextPtr = next; @@ -4279,7 +4600,9 @@ case XML_TOK_DATA_NEWLINE: if (parser->m_characterDataHandler) { XML_Char c = 0xA; + beforeHandler(parser); parser->m_characterDataHandler(parser->m_handlerArg, &c, 1); + afterHandler(parser); } else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); break; @@ -4292,16 +4615,21 @@ const enum XML_Convert_Result convert_res = XmlConvert( enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd); *eventEndPP = next; + beforeHandler(parser); charDataHandler(parser->m_handlerArg, parser->m_dataBuf, (int)(dataPtr - (ICHAR *)parser->m_dataBuf)); + afterHandler(parser); if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) break; *eventPP = s; } - } else + } else { + beforeHandler(parser); charDataHandler(parser->m_handlerArg, (const XML_Char *)s, (int)((const XML_Char *)next - (const XML_Char *)s)); + afterHandler(parser); + } } else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); } break; @@ -4346,7 +4674,7 @@ if (parser->m_reenter) { return XML_ERROR_UNEXPECTED_STATE; // LCOV_EXCL_LINE } - /* Fall through */ + EXPAT_FALLTHROUGH; default:; *eventPP = s = next; } @@ -4540,8 +4868,10 @@ if (! storedversion) return XML_ERROR_NO_MEMORY; } + beforeHandler(parser); parser->m_xmlDeclHandler(parser->m_handlerArg, storedversion, storedEncName, standalone); + afterHandler(parser); } else if (parser->m_defaultHandler) reportDefault(parser, parser->m_encoding, s, next); if (parser->m_protocolEncodingName == NULL) { @@ -4591,8 +4921,11 @@ info.convert = NULL; info.data = NULL; info.release = NULL; - if (parser->m_unknownEncodingHandler(parser->m_unknownEncodingHandlerData, - encodingName, &info)) { + beforeHandler(parser); + const int status = parser->m_unknownEncodingHandler( + parser->m_unknownEncodingHandlerData, encodingName, &info); + afterHandler(parser); + if (status) { ENCODING *enc; parser->m_unknownEncodingMem = MALLOC(parser, XmlSizeOfUnknownEncoding()); if (! parser->m_unknownEncodingMem) { @@ -4720,7 +5053,7 @@ } /* If we get this token, we have the start of what might be a normal tag, but not a declaration (i.e. it doesn't begin with - "m_startDoctypeDeclHandler) { + beforeHandler(parser); parser->m_startDoctypeDeclHandler( parser->m_handlerArg, parser->m_doctypeName, parser->m_doctypeSysid, parser->m_doctypePubid, 1); + afterHandler(parser); parser->m_doctypeName = NULL; poolClear(&parser->m_tempPool); handleDefault = XML_FALSE; @@ -5001,7 +5345,7 @@ handleDefault = XML_FALSE; goto alreadyChecked; } - /* fall through */ + EXPAT_FALLTHROUGH; case XML_ROLE_ENTITY_PUBLIC_ID: if (! XmlIsPublicId(enc, s, next, eventPP)) return XML_ERROR_PUBLICID; @@ -5029,9 +5373,11 @@ } if (parser->m_doctypeName) { + beforeHandler(parser); parser->m_startDoctypeDeclHandler( parser->m_handlerArg, parser->m_doctypeName, parser->m_doctypeSysid, parser->m_doctypePubid, 0); + afterHandler(parser); poolClear(&parser->m_tempPool); handleDefault = XML_FALSE; } @@ -5058,14 +5404,22 @@ if (parser->m_useForeignDTD) entity->base = parser->m_curBase; dtd->paramEntityRead = XML_FALSE; - if (! parser->m_externalEntityRefHandler( - parser->m_externalEntityRefHandlerArg, 0, entity->base, - entity->systemId, entity->publicId)) + beforeHandler(parser); + const int status = parser->m_externalEntityRefHandler( + parser->m_externalEntityRefHandlerArg, 0, entity->base, + entity->systemId, entity->publicId); + afterHandler(parser); + if (! status) return XML_ERROR_EXTERNAL_ENTITY_HANDLING; if (dtd->paramEntityRead) { - if (! dtd->standalone && parser->m_notStandaloneHandler - && ! parser->m_notStandaloneHandler(parser->m_handlerArg)) - return XML_ERROR_NOT_STANDALONE; + if (! dtd->standalone && parser->m_notStandaloneHandler) { + beforeHandler(parser); + const int handlerStatus + = parser->m_notStandaloneHandler(parser->m_handlerArg); + afterHandler(parser); + if (! handlerStatus) + return XML_ERROR_NOT_STANDALONE; + } } /* if we didn't read the foreign DTD then this means that there is no external subset and we must reset dtd->hasParamEntityRefs @@ -5078,7 +5432,9 @@ } #endif /* XML_DTD */ if (parser->m_endDoctypeDeclHandler) { + beforeHandler(parser); parser->m_endDoctypeDeclHandler(parser->m_handlerArg); + afterHandler(parser); handleDefault = XML_FALSE; } break; @@ -5098,14 +5454,22 @@ return XML_ERROR_NO_MEMORY; entity->base = parser->m_curBase; dtd->paramEntityRead = XML_FALSE; - if (! parser->m_externalEntityRefHandler( - parser->m_externalEntityRefHandlerArg, 0, entity->base, - entity->systemId, entity->publicId)) + beforeHandler(parser); + const int status = parser->m_externalEntityRefHandler( + parser->m_externalEntityRefHandlerArg, 0, entity->base, + entity->systemId, entity->publicId); + afterHandler(parser); + if (! status) return XML_ERROR_EXTERNAL_ENTITY_HANDLING; if (dtd->paramEntityRead) { - if (! dtd->standalone && parser->m_notStandaloneHandler - && ! parser->m_notStandaloneHandler(parser->m_handlerArg)) - return XML_ERROR_NOT_STANDALONE; + if (! dtd->standalone && parser->m_notStandaloneHandler) { + beforeHandler(parser); + const int handlerStatus + = parser->m_notStandaloneHandler(parser->m_handlerArg); + afterHandler(parser); + if (! handlerStatus) + return XML_ERROR_NOT_STANDALONE; + } } /* if we didn't read the foreign DTD then this means that there is no external subset and we must reset dtd->hasParamEntityRefs @@ -5198,10 +5562,12 @@ poolFinish(&parser->m_tempPool); } *eventEndPP = s; + beforeHandler(parser); parser->m_attlistDeclHandler( parser->m_handlerArg, parser->m_declElementType->name, parser->m_declAttributeId->name, parser->m_declAttributeType, 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE); + afterHandler(parser); handleDefault = XML_FALSE; } } @@ -5236,10 +5602,12 @@ poolFinish(&parser->m_tempPool); } *eventEndPP = s; + beforeHandler(parser); parser->m_attlistDeclHandler( parser->m_handlerArg, parser->m_declElementType->name, parser->m_declAttributeId->name, parser->m_declAttributeType, attVal, role == XML_ROLE_FIXED_ATTRIBUTE_VALUE); + afterHandler(parser); poolClear(&parser->m_tempPool); handleDefault = XML_FALSE; } @@ -5254,16 +5622,22 @@ parser, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar, XML_ACCOUNT_NONE); if (parser->m_declEntity) { + /* Detect and prevent signed integer overflow */ + if ((size_t)poolLength(&dtd->entityValuePool) > (size_t)INT_MAX) { + return XML_ERROR_NO_MEMORY; + } parser->m_declEntity->textPtr = poolStart(&dtd->entityValuePool); parser->m_declEntity->textLen = (int)(poolLength(&dtd->entityValuePool)); poolFinish(&dtd->entityValuePool); if (parser->m_entityDeclHandler) { *eventEndPP = s; + beforeHandler(parser); parser->m_entityDeclHandler( parser->m_handlerArg, parser->m_declEntity->name, parser->m_declEntity->is_param, parser->m_declEntity->textPtr, parser->m_declEntity->textLen, parser->m_curBase, 0, 0, 0); + afterHandler(parser); handleDefault = XML_FALSE; } } else @@ -5281,10 +5655,12 @@ if (parser->m_entityDeclHandler) { *eventEndPP = s; + beforeHandler(parser); parser->m_entityDeclHandler( parser->m_handlerArg, parser->m_declEntity->name, parser->m_declEntity->is_param, parser->m_declEntity->textPtr, parser->m_declEntity->textLen, parser->m_curBase, 0, 0, 0); + afterHandler(parser); handleDefault = XML_FALSE; } } @@ -5315,9 +5691,13 @@ #ifdef XML_DTD && ! parser->m_paramEntityParsing #endif /* XML_DTD */ - && parser->m_notStandaloneHandler - && ! parser->m_notStandaloneHandler(parser->m_handlerArg)) - return XML_ERROR_NOT_STANDALONE; + && parser->m_notStandaloneHandler) { + beforeHandler(parser); + const int status = parser->m_notStandaloneHandler(parser->m_handlerArg); + afterHandler(parser); + if (! status) + return XML_ERROR_NOT_STANDALONE; + } #ifndef XML_DTD break; #else /* XML_DTD */ @@ -5329,7 +5709,7 @@ parser->m_declEntity->publicId = NULL; } #endif /* XML_DTD */ - /* fall through */ + EXPAT_FALLTHROUGH; case XML_ROLE_ENTITY_SYSTEM_ID: if (dtd->keepProcessing && parser->m_declEntity) { parser->m_declEntity->systemId @@ -5360,10 +5740,12 @@ if (dtd->keepProcessing && parser->m_declEntity && parser->m_entityDeclHandler) { *eventEndPP = s; + beforeHandler(parser); parser->m_entityDeclHandler( parser->m_handlerArg, parser->m_declEntity->name, parser->m_declEntity->is_param, 0, 0, parser->m_declEntity->base, parser->m_declEntity->systemId, parser->m_declEntity->publicId, 0); + afterHandler(parser); handleDefault = XML_FALSE; } break; @@ -5376,17 +5758,21 @@ poolFinish(&dtd->pool); if (parser->m_unparsedEntityDeclHandler) { *eventEndPP = s; + beforeHandler(parser); parser->m_unparsedEntityDeclHandler( parser->m_handlerArg, parser->m_declEntity->name, parser->m_declEntity->base, parser->m_declEntity->systemId, parser->m_declEntity->publicId, parser->m_declEntity->notation); + afterHandler(parser); handleDefault = XML_FALSE; } else if (parser->m_entityDeclHandler) { *eventEndPP = s; + beforeHandler(parser); parser->m_entityDeclHandler( parser->m_handlerArg, parser->m_declEntity->name, 0, 0, 0, parser->m_declEntity->base, parser->m_declEntity->systemId, parser->m_declEntity->publicId, parser->m_declEntity->notation); + afterHandler(parser); handleDefault = XML_FALSE; } } @@ -5493,9 +5879,11 @@ if (! systemId) return XML_ERROR_NO_MEMORY; *eventEndPP = s; + beforeHandler(parser); parser->m_notationDeclHandler( parser->m_handlerArg, parser->m_declNotationName, parser->m_curBase, systemId, parser->m_declNotationPublicId); + afterHandler(parser); handleDefault = XML_FALSE; } poolClear(&parser->m_tempPool); @@ -5503,9 +5891,11 @@ case XML_ROLE_NOTATION_NO_SYSTEM_ID: if (parser->m_declNotationPublicId && parser->m_notationDeclHandler) { *eventEndPP = s; + beforeHandler(parser); parser->m_notationDeclHandler( parser->m_handlerArg, parser->m_declNotationName, parser->m_curBase, 0, parser->m_declNotationPublicId); + afterHandler(parser); handleDefault = XML_FALSE; } poolClear(&parser->m_tempPool); @@ -5539,41 +5929,20 @@ case XML_ROLE_GROUP_OPEN: if (parser->m_prologState.level >= parser->m_groupSize) { if (parser->m_groupSize) { - { - /* Detect and prevent integer overflow */ - if (parser->m_groupSize > (unsigned int)(-1) / 2u) { - return XML_ERROR_NO_MEMORY; - } - - char *const new_connector = (char *)REALLOC( - parser, parser->m_groupConnector, parser->m_groupSize *= 2); - if (new_connector == NULL) { - parser->m_groupSize /= 2; - return XML_ERROR_NO_MEMORY; - } - parser->m_groupConnector = new_connector; + /* Detect and prevent integer overflow */ + if (parser->m_groupSize > SIZE_MAX / 2) { + return XML_ERROR_NO_MEMORY; } - if (dtd->scaffIndex) { - /* Detect and prevent integer overflow. - * The preprocessor guard addresses the "always false" warning - * from -Wtype-limits on platforms where - * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ -#if UINT_MAX >= SIZE_MAX - if (parser->m_groupSize > (size_t)(-1) / sizeof(int)) { - return XML_ERROR_NO_MEMORY; - } -#endif - - int *const new_scaff_index = (int *)REALLOC( - parser, dtd->scaffIndex, parser->m_groupSize * sizeof(int)); - if (new_scaff_index == NULL) - return XML_ERROR_NO_MEMORY; - dtd->scaffIndex = new_scaff_index; + char *const new_connector = REALLOC(parser, parser->m_groupConnector, + parser->m_groupSize *= 2); + if (new_connector == NULL) { + parser->m_groupSize /= 2; + return XML_ERROR_NO_MEMORY; } + parser->m_groupConnector = new_connector; } else { - parser->m_groupConnector - = (char *)MALLOC(parser, parser->m_groupSize = 32); + parser->m_groupConnector = MALLOC(parser, parser->m_groupSize = 32); if (! parser->m_groupConnector) { parser->m_groupSize = 0; return XML_ERROR_NO_MEMORY; @@ -5586,6 +5955,21 @@ if (myindex < 0) return XML_ERROR_NO_MEMORY; assert(dtd->scaffIndex != NULL); + if ((size_t)dtd->scaffLevel >= dtd->scaffIndexSize) { + /* Detect and prevent integer overflow */ + if (dtd->scaffIndexSize > SIZE_MAX / 2 / sizeof(int)) { + return XML_ERROR_NO_MEMORY; + } + assert(dtd->scaffIndexSize > 0); + const size_t new_size = dtd->scaffIndexSize * 2; + int *const new_scaff_index + = REALLOC(parser, dtd->scaffIndex, new_size * sizeof(int)); + if (new_scaff_index == NULL) { + return XML_ERROR_NO_MEMORY; + } + dtd->scaffIndex = new_scaff_index; + dtd->scaffIndexSize = new_size; + } dtd->scaffIndex[dtd->scaffLevel] = myindex; dtd->scaffLevel++; dtd->scaffold[myindex].type = XML_CTYPE_SEQ; @@ -5666,7 +6050,9 @@ /* cannot report skipped entities in declarations */ if ((role == XML_ROLE_PARAM_ENTITY_REF) && parser->m_skippedEntityHandler) { + beforeHandler(parser); parser->m_skippedEntityHandler(parser->m_handlerArg, name, 1); + afterHandler(parser); handleDefault = XML_FALSE; } break; @@ -5687,9 +6073,12 @@ dtd->paramEntityRead = XML_FALSE; entity->open = XML_TRUE; entityTrackingOnOpen(parser, entity, __LINE__); - if (! parser->m_externalEntityRefHandler( - parser->m_externalEntityRefHandlerArg, 0, entity->base, - entity->systemId, entity->publicId)) { + beforeHandler(parser); + const int status = parser->m_externalEntityRefHandler( + parser->m_externalEntityRefHandlerArg, 0, entity->base, + entity->systemId, entity->publicId); + afterHandler(parser); + if (! status) { entityTrackingOnClose(parser, entity, __LINE__); entity->open = XML_FALSE; return XML_ERROR_EXTERNAL_ENTITY_HANDLING; @@ -5707,9 +6096,13 @@ } } #endif /* XML_DTD */ - if (! dtd->standalone && parser->m_notStandaloneHandler - && ! parser->m_notStandaloneHandler(parser->m_handlerArg)) - return XML_ERROR_NOT_STANDALONE; + if (! dtd->standalone && parser->m_notStandaloneHandler) { + beforeHandler(parser); + const int status = parser->m_notStandaloneHandler(parser->m_handlerArg); + afterHandler(parser); + if (! status) + return XML_ERROR_NOT_STANDALONE; + } break; /* Element declaration stuff */ @@ -5730,8 +6123,11 @@ case XML_ROLE_CONTENT_EMPTY: if (dtd->in_eldecl) { if (parser->m_elementDeclHandler) { - XML_Content *content - = (XML_Content *)MALLOC(parser, sizeof(XML_Content)); + // NOTE: We are avoiding MALLOC(..) here to so that + // applications that are not using XML_FreeContentModel but + // plain free(..) or .free_fcn() to free the content model's + // memory are safe. + XML_Content *content = parser->m_mem.malloc_fcn(sizeof(XML_Content)); if (! content) return XML_ERROR_NO_MEMORY; content->quant = XML_CQUANT_NONE; @@ -5741,8 +6137,10 @@ content->type = ((role == XML_ROLE_CONTENT_ANY) ? XML_CTYPE_ANY : XML_CTYPE_EMPTY); *eventEndPP = s; + beforeHandler(parser); parser->m_elementDeclHandler( parser->m_handlerArg, parser->m_declElementType->name, content); + afterHandler(parser); handleDefault = XML_FALSE; } dtd->in_eldecl = XML_FALSE; @@ -5786,9 +6184,7 @@ return XML_ERROR_NO_MEMORY; name = el->name; dtd->scaffold[myindex].name = name; - nameLen = 0; - for (; name[nameLen++];) - ; + nameLen = xcslen(name) + /*null terminator*/ 1; /* Detect and prevent integer overflow */ if (nameLen > UINT_MAX - dtd->contentStringLen) { @@ -5824,8 +6220,10 @@ if (! model) return XML_ERROR_NO_MEMORY; *eventEndPP = s; + beforeHandler(parser); parser->m_elementDeclHandler( parser->m_handlerArg, parser->m_declElementType->name, model); + afterHandler(parser); } dtd->in_eldecl = XML_FALSE; dtd->contentStringLen = 0; @@ -5887,7 +6285,7 @@ *nextPtr = next; return XML_ERROR_NONE; } - /* Fall through */ + EXPAT_FALLTHROUGH; default: s = next; tok = XmlPrologTok(enc, s, end, &next); @@ -5967,7 +6365,7 @@ if (parser->m_reenter) { return XML_ERROR_UNEXPECTED_STATE; // LCOV_EXCL_LINE } - /* Fall through */ + EXPAT_FALLTHROUGH; default:; parser->m_eventPtr = s = next; } @@ -5977,20 +6375,18 @@ static enum XML_Error processEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl, enum EntityType type) { - OPEN_INTERNAL_ENTITY *openEntity, **openEntityList, **freeEntityList; + OPEN_INTERNAL_ENTITY *openEntity, **openEntityList; + OPEN_INTERNAL_ENTITY **const freeEntityList = &parser->m_freeEntities; switch (type) { case ENTITY_INTERNAL: parser->m_processor = internalEntityProcessor; openEntityList = &parser->m_openInternalEntities; - freeEntityList = &parser->m_freeInternalEntities; break; case ENTITY_ATTRIBUTE: openEntityList = &parser->m_openAttributeEntities; - freeEntityList = &parser->m_freeAttributeEntities; break; case ENTITY_VALUE: openEntityList = &parser->m_openValueEntities; - freeEntityList = &parser->m_freeValueEntities; break; /* default case serves merely as a safety net in case of a * wrong entityType. Therefore we exclude the following lines @@ -6008,8 +6404,7 @@ openEntity = *freeEntityList; *freeEntityList = openEntity->next; } else { - openEntity - = (OPEN_INTERNAL_ENTITY *)MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY)); + openEntity = MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY)); if (! openEntity) return XML_ERROR_NO_MEMORY; } @@ -6087,6 +6482,10 @@ // process its possible inner entities (which are added to the // m_openInternalEntities during doProlog or doContent calls above) entity->hasMore = XML_FALSE; + if (! entity->is_param + && (openEntity->startTagLevel != parser->m_tagLevel)) { + return XML_ERROR_ASYNC_ENTITY; + } triggerReenter(parser); return result; } // End of entity processing, "if" block will return here @@ -6104,8 +6503,8 @@ parser->m_openInternalEntities = parser->m_openInternalEntities->next; /* put openEntity back in list of free instances */ - openEntity->next = parser->m_freeInternalEntities; - parser->m_freeInternalEntities = openEntity; + openEntity->next = parser->m_freeEntities; + parser->m_freeEntities = openEntity; if (parser->m_openInternalEntities == NULL) { parser->m_processor = entity->is_param ? prologProcessor : contentProcessor; @@ -6181,8 +6580,8 @@ parser->m_openAttributeEntities = parser->m_openAttributeEntities->next; /* put openEntity back in list of free instances */ - openEntity->next = parser->m_freeAttributeEntities; - parser->m_freeAttributeEntities = openEntity; + openEntity->next = parser->m_freeEntities; + parser->m_freeEntities = openEntity; } // Break if an error occurred or there is nothing left to process @@ -6235,7 +6634,6 @@ return XML_ERROR_INVALID_TOKEN; case XML_TOK_CHAR_REF: { XML_Char buf[XML_ENCODE_MAX]; - int i; int n = XmlCharRefNumber(enc, ptr); if (n < 0) { if (enc == parser->m_encoding) @@ -6255,10 +6653,9 @@ * XmlEncode() is never passed a value it might return an * error for. */ - for (i = 0; i < n; i++) { - if (! poolAppendChar(pool, buf[i])) - return XML_ERROR_NO_MEMORY; - } + + if (! poolAppendChars(pool, buf, n)) + return XML_ERROR_NO_MEMORY; } break; case XML_TOK_DATA_CHARS: if (! poolAppend(pool, enc, ptr, next)) @@ -6266,7 +6663,7 @@ break; case XML_TOK_TRAILING_CR: next = ptr + enc->minBytesPerChar; - /* fall through */ + EXPAT_FALLTHROUGH; case XML_TOK_ATTRIBUTE_VALUE_S: case XML_TOK_DATA_NEWLINE: if (! isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) @@ -6277,7 +6674,7 @@ case XML_TOK_ENTITY_REF: { const XML_Char *name; ENTITY *entity; - char checkEntityDecl; + bool checkEntityDecl; XML_Char ch = (XML_Char)XmlPredefinedEntityName( enc, ptr + enc->minBytesPerChar, next - enc->minBytesPerChar); if (ch) { @@ -6320,8 +6717,11 @@ } else if (! entity) { /* Cannot report skipped entity here - see comments on parser->m_skippedEntityHandler. - if (parser->m_skippedEntityHandler) + if (parser->m_skippedEntityHandler) { + beforeHandler(parser); parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0); + afterHandler(parser); + } */ /* Cannot call the default handler because this would be out of sync with the call to the startElementHandler. @@ -6415,7 +6815,14 @@ return XML_ERROR_NO_MEMORY; } - const char *next; + const char *next = entityTextPtr; + + /* Nothing to tokenize. */ + if (entityTextPtr >= entityTextEnd) { + result = XML_ERROR_NONE; + goto endEntityValue; + } + for (;;) { next = entityTextPtr; /* XmlEntityValueTok doesn't always set the last arg */ @@ -6447,8 +6854,11 @@ /* not a well-formedness error - see XML 1.0: WFC Entity Declared */ /* cannot report skipped entity here - see comments on parser->m_skippedEntityHandler - if (parser->m_skippedEntityHandler) + if (parser->m_skippedEntityHandler) { + beforeHandler(parser); parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0); + afterHandler(parser); + } */ dtd->keepProcessing = dtd->standalone; goto endEntityValue; @@ -6464,9 +6874,12 @@ dtd->paramEntityRead = XML_FALSE; entity->open = XML_TRUE; entityTrackingOnOpen(parser, entity, __LINE__); - if (! parser->m_externalEntityRefHandler( - parser->m_externalEntityRefHandlerArg, 0, entity->base, - entity->systemId, entity->publicId)) { + beforeHandler(parser); + const int status = parser->m_externalEntityRefHandler( + parser->m_externalEntityRefHandlerArg, 0, entity->base, + entity->systemId, entity->publicId); + afterHandler(parser); + if (! status) { entityTrackingOnClose(parser, entity, __LINE__); entity->open = XML_FALSE; result = XML_ERROR_EXTERNAL_ENTITY_HANDLING; @@ -6502,17 +6915,15 @@ break; case XML_TOK_TRAILING_CR: next = entityTextPtr + enc->minBytesPerChar; - /* fall through */ + EXPAT_FALLTHROUGH; case XML_TOK_DATA_NEWLINE: - if (pool->end == pool->ptr && ! poolGrow(pool)) { + if (! poolAppendChar(pool, 0xA)) { result = XML_ERROR_NO_MEMORY; goto endEntityValue; } - *(pool->ptr)++ = 0xA; break; case XML_TOK_CHAR_REF: { XML_Char buf[XML_ENCODE_MAX]; - int i; int n = XmlCharRefNumber(enc, entityTextPtr); if (n < 0) { if (enc == parser->m_encoding) @@ -6530,12 +6941,9 @@ * XmlEncode() is never passed a value it might return an * error for. */ - for (i = 0; i < n; i++) { - if (pool->end == pool->ptr && ! poolGrow(pool)) { - result = XML_ERROR_NO_MEMORY; - goto endEntityValue; - } - *(pool->ptr)++ = buf[i]; + if (! poolAppendChars(pool, buf, n)) { + result = XML_ERROR_NO_MEMORY; + goto endEntityValue; } } break; case XML_TOK_PARTIAL: @@ -6632,8 +7040,8 @@ parser->m_openValueEntities = parser->m_openValueEntities->next; /* put openEntity back in list of free instances */ - openEntity->next = parser->m_freeValueEntities; - parser->m_freeValueEntities = openEntity; + openEntity->next = parser->m_freeEntities; + parser->m_freeEntities = openEntity; } // Break if an error occurred or there is nothing left to process @@ -6663,6 +7071,11 @@ return XML_ERROR_NO_MEMORY; } + /* Detect and prevent signed integer overflow */ + if ((size_t)poolLength(pool) > (size_t)INT_MAX) { + poolDiscard(pool); + return XML_ERROR_NO_MEMORY; + } entity->textPtr = poolStart(pool); entity->textLen = (int)(poolLength(pool)); poolFinish(pool); @@ -6715,7 +7128,9 @@ if (! data) return 0; normalizeLines(data); + beforeHandler(parser); parser->m_processingInstructionHandler(parser->m_handlerArg, target, data); + afterHandler(parser); poolClear(&parser->m_tempPool); return 1; } @@ -6735,7 +7150,9 @@ if (! data) return 0; normalizeLines(data); + beforeHandler(parser); parser->m_commentHandler(parser->m_handlerArg, data); + afterHandler(parser); poolClear(&parser->m_tempPool); return 1; } @@ -6776,15 +7193,20 @@ convert_res = XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)parser->m_dataBufEnd); *eventEndPP = s; + beforeHandler(parser); parser->m_defaultHandler(parser->m_handlerArg, parser->m_dataBuf, (int)(dataPtr - (ICHAR *)parser->m_dataBuf)); + afterHandler(parser); *eventPP = s; } while ((convert_res != XML_CONVERT_COMPLETED) && (convert_res != XML_CONVERT_INPUT_INCOMPLETE)); - } else + } else { + beforeHandler(parser); parser->m_defaultHandler( parser->m_handlerArg, (const XML_Char *)s, (int)((const XML_Char *)end - (const XML_Char *)s)); + afterHandler(parser); + } } static int @@ -6794,49 +7216,35 @@ if (value || isId) { /* The handling of default attributes gets messed up if we have a default which duplicates a non-default. */ - int i; - for (i = 0; i < type->nDefaultAtts; i++) - if (attId == type->defaultAtts[i].id) - return 1; + NAMED *const nameFound + = lookup(parser, &(type->defaultAttsNames), attId->name, 0); + if (nameFound) + return 1; if (isId && ! type->idAtt && ! attId->xmlns) type->idAtt = attId; } if (type->nDefaultAtts == type->allocDefaultAtts) { - if (type->allocDefaultAtts == 0) { - type->allocDefaultAtts = 8; - type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC( - parser, type->allocDefaultAtts * sizeof(DEFAULT_ATTRIBUTE)); - if (! type->defaultAtts) { - type->allocDefaultAtts = 0; - return 0; - } - } else { - DEFAULT_ATTRIBUTE *temp; - - /* Detect and prevent integer overflow */ - if (type->allocDefaultAtts > INT_MAX / 2) { - return 0; - } - - int count = type->allocDefaultAtts * 2; + /* Detect and prevent integer overflow */ + if (type->allocDefaultAtts > SIZE_MAX / 2) { + return 0; + } - /* Detect and prevent integer overflow. - * The preprocessor guard addresses the "always false" warning - * from -Wtype-limits on platforms where - * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ -#if UINT_MAX >= SIZE_MAX - if ((unsigned)count > (size_t)(-1) / sizeof(DEFAULT_ATTRIBUTE)) { - return 0; - } -#endif + size_t count = type->allocDefaultAtts * 2; + if (count == 0) { + count = 8; + } - temp = (DEFAULT_ATTRIBUTE *)REALLOC(parser, type->defaultAtts, - (count * sizeof(DEFAULT_ATTRIBUTE))); - if (temp == NULL) - return 0; - type->allocDefaultAtts = count; - type->defaultAtts = temp; + /* Detect and prevent integer overflow. */ + if (count > SIZE_MAX / sizeof(DEFAULT_ATTRIBUTE)) { + return 0; } + + DEFAULT_ATTRIBUTE *const temp = REALLOC( + parser, type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE))); + if (temp == NULL) + return 0; + type->allocDefaultAtts = count; + type->defaultAtts = temp; } att = type->defaultAtts + type->nDefaultAtts; att->id = attId; @@ -6844,6 +7252,12 @@ att->isCdata = isCdata; if (! isCdata) attId->maybeTokenized = XML_TRUE; + + NAMED *const nameAddedOrFound + = lookup(parser, &(type->defaultAttsNames), attId->name, sizeof(NAMED)); + if (! nameAddedOrFound) + return 0; + type->nDefaultAtts += 1; return 1; } @@ -6913,13 +7327,14 @@ } else { int i; for (i = 0; name[i]; i++) { + /* Detect and prevent signed integer overflow */ + if (i == INT_MAX) { + return NULL; + } /* attributes without prefix are *not* in the default namespace */ if (name[i] == XML_T(ASCII_COLON)) { - int j; - for (j = 0; j < i; j++) { - if (! poolAppendChar(&dtd->pool, name[j])) - return NULL; - } + if (! poolAppendChars(&dtd->pool, name, i)) + return NULL; if (! poolAppendChar(&dtd->pool, XML_T('\0'))) return NULL; id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, @@ -6947,46 +7362,39 @@ XML_Bool needSep = XML_FALSE; if (dtd->defaultPrefix.binding) { - int i; - int len; if (! poolAppendChar(&parser->m_tempPool, XML_T(ASCII_EQUALS))) return NULL; - len = dtd->defaultPrefix.binding->uriLen; + size_t len = dtd->defaultPrefix.binding->uriLen; if (parser->m_namespaceSeparator) len--; - for (i = 0; i < len; i++) { - if (! poolAppendChar(&parser->m_tempPool, - dtd->defaultPrefix.binding->uri[i])) { - /* Because of memory caching, I don't believe this line can be - * executed. - * - * This is part of a loop copying the default prefix binding - * URI into the parser's temporary string pool. Previously, - * that URI was copied into the same string pool, with a - * terminating NUL character, as part of setContext(). When - * the pool was cleared, that leaves a block definitely big - * enough to hold the URI on the free block list of the pool. - * The URI copy in getContext() therefore cannot run out of - * memory. - * - * If the pool is used between the setContext() and - * getContext() calls, the worst it can do is leave a bigger - * block on the front of the free list. Given that this is - * all somewhat inobvious and program logic can be changed, we - * don't delete the line but we do exclude it from the test - * coverage statistics. - */ - return NULL; /* LCOV_EXCL_LINE */ - } + if (! poolAppendChars(&parser->m_tempPool, dtd->defaultPrefix.binding->uri, + len)) { + /* Because of memory caching, I don't believe this line can be + * executed. + * + * This is part of a loop copying the default prefix binding + * URI into the parser's temporary string pool. Previously, + * that URI was copied into the same string pool, with a + * terminating NUL character, as part of setContext(). When + * the pool was cleared, that leaves a block definitely big + * enough to hold the URI on the free block list of the pool. + * The URI copy in getContext() therefore cannot run out of + * memory. + * + * If the pool is used between the setContext() and + * getContext() calls, the worst it can do is leave a bigger + * block on the front of the free list. Given that this is + * all somewhat inobvious and program logic can be changed, we + * don't delete the line but we do exclude it from the test + * coverage statistics. + */ + return NULL; /* LCOV_EXCL_LINE */ } needSep = XML_TRUE; } hashTableIterInit(&iter, &(dtd->prefixes)); for (;;) { - int i; - int len; - const XML_Char *s; PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter); if (! prefix) break; @@ -7001,23 +7409,21 @@ } if (needSep && ! poolAppendChar(&parser->m_tempPool, CONTEXT_SEP)) return NULL; - for (s = prefix->name; *s; s++) - if (! poolAppendChar(&parser->m_tempPool, *s)) - return NULL; + if (! poolAppendChars(&parser->m_tempPool, prefix->name, + xcslen(prefix->name))) + return NULL; if (! poolAppendChar(&parser->m_tempPool, XML_T(ASCII_EQUALS))) return NULL; - len = prefix->binding->uriLen; + size_t len = prefix->binding->uriLen; if (parser->m_namespaceSeparator) len--; - for (i = 0; i < len; i++) - if (! poolAppendChar(&parser->m_tempPool, prefix->binding->uri[i])) - return NULL; + if (! poolAppendChars(&parser->m_tempPool, prefix->binding->uri, len)) + return NULL; needSep = XML_TRUE; } hashTableIterInit(&iter, &(dtd->generalEntities)); for (;;) { - const XML_Char *s; ENTITY *e = (ENTITY *)hashTableIterNext(&iter); if (! e) break; @@ -7025,9 +7431,8 @@ continue; if (needSep && ! poolAppendChar(&parser->m_tempPool, CONTEXT_SEP)) return NULL; - for (s = e->name; *s; s++) - if (! poolAppendChar(&parser->m_tempPool, *s)) - return 0; + if (! poolAppendChars(&parser->m_tempPool, e->name, xcslen(e->name))) + return NULL; needSep = XML_TRUE; } @@ -7065,16 +7470,24 @@ else { if (! poolAppendChar(&parser->m_tempPool, XML_T('\0'))) return XML_FALSE; - prefix - = (PREFIX *)lookup(parser, &dtd->prefixes, - poolStart(&parser->m_tempPool), sizeof(PREFIX)); - if (! prefix) + const XML_Char *const prefixName = poolCopyStringNoFinish( + &dtd->pool, poolStart(&parser->m_tempPool)); + if (! prefixName) { return XML_FALSE; - if (prefix->name == poolStart(&parser->m_tempPool)) { - prefix->name = poolCopyString(&dtd->pool, prefix->name); - if (! prefix->name) - return XML_FALSE; } + + prefix = (PREFIX *)lookup(parser, &dtd->prefixes, prefixName, + sizeof(PREFIX)); + + const bool prefixNameUsed = prefix && prefix->name == prefixName; + if (prefixNameUsed) + poolFinish(&dtd->pool); + else + poolDiscard(&dtd->pool); + + if (! prefix) + return XML_FALSE; + poolDiscard(&parser->m_tempPool); } for (context = s + 1; *context != CONTEXT_SEP && *context != XML_T('\0'); @@ -7122,25 +7535,26 @@ } static DTD * -dtdCreate(const XML_Memory_Handling_Suite *ms) { - DTD *p = ms->malloc_fcn(sizeof(DTD)); +dtdCreate(XML_Parser parser) { + DTD *p = MALLOC(parser, sizeof(DTD)); if (p == NULL) return p; - poolInit(&(p->pool), ms); - poolInit(&(p->entityValuePool), ms); - hashTableInit(&(p->generalEntities), ms); - hashTableInit(&(p->elementTypes), ms); - hashTableInit(&(p->attributeIds), ms); - hashTableInit(&(p->prefixes), ms); + poolInit(&(p->pool), parser); + poolInit(&(p->entityValuePool), parser); + hashTableInit(&(p->generalEntities), parser); + hashTableInit(&(p->elementTypes), parser); + hashTableInit(&(p->attributeIds), parser); + hashTableInit(&(p->prefixes), parser); #ifdef XML_DTD p->paramEntityRead = XML_FALSE; - hashTableInit(&(p->paramEntities), ms); + hashTableInit(&(p->paramEntities), parser); #endif /* XML_DTD */ p->defaultPrefix.name = NULL; p->defaultPrefix.binding = NULL; p->in_eldecl = XML_FALSE; p->scaffIndex = NULL; + p->scaffIndexSize = 0; p->scaffold = NULL; p->scaffLevel = 0; p->scaffSize = 0; @@ -7154,15 +7568,15 @@ } static void -dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms) { +dtdReset(DTD *p, XML_Parser parser) { HASH_TABLE_ITER iter; hashTableIterInit(&iter, &(p->elementTypes)); for (;;) { ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter); if (! e) break; - if (e->allocDefaultAtts != 0) - ms->free_fcn(e->defaultAtts); + hashTableDestroy(&(e->defaultAttsNames)); + FREE(parser, e->defaultAtts); } hashTableClear(&(p->generalEntities)); #ifdef XML_DTD @@ -7179,9 +7593,10 @@ p->in_eldecl = XML_FALSE; - ms->free_fcn(p->scaffIndex); + FREE(parser, p->scaffIndex); p->scaffIndex = NULL; - ms->free_fcn(p->scaffold); + p->scaffIndexSize = 0; + FREE(parser, p->scaffold); p->scaffold = NULL; p->scaffLevel = 0; @@ -7195,15 +7610,15 @@ } static void -dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms) { +dtdDestroy(DTD *p, XML_Bool isDocEntity, XML_Parser parser) { HASH_TABLE_ITER iter; hashTableIterInit(&iter, &(p->elementTypes)); for (;;) { ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter); if (! e) break; - if (e->allocDefaultAtts != 0) - ms->free_fcn(e->defaultAtts); + hashTableDestroy(&(e->defaultAttsNames)); + FREE(parser, e->defaultAtts); } hashTableDestroy(&(p->generalEntities)); #ifdef XML_DTD @@ -7215,10 +7630,10 @@ poolDestroy(&(p->pool)); poolDestroy(&(p->entityValuePool)); if (isDocEntity) { - ms->free_fcn(p->scaffIndex); - ms->free_fcn(p->scaffold); + FREE(parser, p->scaffIndex); + FREE(parser, p->scaffold); } - ms->free_fcn(p); + FREE(parser, p); } /* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise. @@ -7226,7 +7641,7 @@ */ static int dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, - const XML_Memory_Handling_Suite *ms) { + XML_Parser parser) { HASH_TABLE_ITER iter; /* Copy the prefix table. */ @@ -7282,7 +7697,6 @@ hashTableIterInit(&iter, &(oldDtd->elementTypes)); for (;;) { - int i; ELEMENT_TYPE *newE; const XML_Char *name; const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter); @@ -7295,19 +7709,17 @@ sizeof(ELEMENT_TYPE)); if (! newE) return 0; + + if (! newE->defaultAttsNames.parser) + hashTableInit(&(newE->defaultAttsNames), parser); + if (oldE->nDefaultAtts) { - /* Detect and prevent integer overflow. - * The preprocessor guard addresses the "always false" warning - * from -Wtype-limits on platforms where - * sizeof(int) < sizeof(size_t), e.g. on x86_64. */ -#if UINT_MAX >= SIZE_MAX - if ((size_t)oldE->nDefaultAtts - > ((size_t)(-1) / sizeof(DEFAULT_ATTRIBUTE))) { + /* Detect and prevent integer overflow. */ + if (oldE->nDefaultAtts > SIZE_MAX / sizeof(DEFAULT_ATTRIBUTE)) { return 0; } -#endif newE->defaultAtts - = ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE)); + = MALLOC(parser, oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE)); if (! newE->defaultAtts) { return 0; } @@ -7319,9 +7731,10 @@ if (oldE->prefix) newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes), oldE->prefix->name, 0); - for (i = 0; i < newE->nDefaultAtts; i++) { + for (size_t i = 0; i < newE->nDefaultAtts; i++) { + const XML_Char *const attributeName = oldE->defaultAtts[i].id->name; newE->defaultAtts[i].id = (ATTRIBUTE_ID *)lookup( - oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0); + oldParser, &(newDtd->attributeIds), attributeName, 0); newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata; if (oldE->defaultAtts[i].value) { newE->defaultAtts[i].value @@ -7330,6 +7743,12 @@ return 0; } else newE->defaultAtts[i].value = NULL; + + NAMED *const nameAddedOrFound = lookup(parser, &(newE->defaultAttsNames), + attributeName, sizeof(NAMED)); + if (! nameAddedOrFound) { + return 0; + } } } @@ -7356,6 +7775,7 @@ newDtd->scaffSize = oldDtd->scaffSize; newDtd->scaffLevel = oldDtd->scaffLevel; newDtd->scaffIndex = oldDtd->scaffIndex; + newDtd->scaffIndexSize = oldDtd->scaffIndexSize; return 1; } /* End dtdCopy */ @@ -7427,24 +7847,31 @@ static XML_Bool FASTCALL keyeq(KEY s1, KEY s2) { +#ifdef XML_UNICODE +# ifdef XML_UNICODE_WCHAR_T + return (wcscmp(s1, s2) == 0) ? XML_TRUE : XML_FALSE; +# else for (; *s1 == *s2; s1++, s2++) if (*s1 == 0) return XML_TRUE; return XML_FALSE; +# endif +#else + return (strcmp(s1, s2) == 0) ? XML_TRUE : XML_FALSE; +#endif } static size_t keylen(KEY s) { - size_t len = 0; - for (; *s; s++, len++) - ; - return len; + return xcslen(s); } static void copy_salt_to_sipkey(XML_Parser parser, struct sipkey *key) { - key->k[0] = 0; - key->k[1] = get_hash_secret_salt(parser); + const XML_Parser rootParser = getRootParserOf(parser, NULL); + assert(! rootParser->m_parentParser); + + *key = rootParser->m_hash_secret_salt_128; } static unsigned long FASTCALL @@ -7469,7 +7896,7 @@ /* table->size is a power of 2 */ table->size = (size_t)1 << INIT_POWER; tsize = table->size * sizeof(NAMED *); - table->v = table->mem->malloc_fcn(tsize); + table->v = MALLOC(table->parser, tsize); if (! table->v) { table->size = 0; return NULL; @@ -7504,12 +7931,12 @@ unsigned long newMask = (unsigned long)newSize - 1; /* Detect and prevent integer overflow */ - if (newSize > (size_t)(-1) / sizeof(NAMED *)) { + if (newSize > SIZE_MAX / sizeof(NAMED *)) { return NULL; } size_t tsize = newSize * sizeof(NAMED *); - NAMED **newV = table->mem->malloc_fcn(tsize); + NAMED **newV = MALLOC(table->parser, tsize); if (! newV) return NULL; memset(newV, 0, tsize); @@ -7525,7 +7952,7 @@ } newV[j] = table->v[i]; } - table->mem->free_fcn(table->v); + FREE(table->parser, table->v); table->v = newV; table->power = newPower; table->size = newSize; @@ -7538,7 +7965,7 @@ } } } - table->v[i] = table->mem->malloc_fcn(createSize); + table->v[i] = MALLOC(table->parser, createSize); if (! table->v[i]) return NULL; memset(table->v[i], 0, createSize); @@ -7551,7 +7978,7 @@ hashTableClear(HASH_TABLE *table) { size_t i; for (i = 0; i < table->size; i++) { - table->mem->free_fcn(table->v[i]); + FREE(table->parser, table->v[i]); table->v[i] = NULL; } table->used = 0; @@ -7561,17 +7988,17 @@ hashTableDestroy(HASH_TABLE *table) { size_t i; for (i = 0; i < table->size; i++) - table->mem->free_fcn(table->v[i]); - table->mem->free_fcn(table->v); + FREE(table->parser, table->v[i]); + FREE(table->parser, table->v); } static void FASTCALL -hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms) { +hashTableInit(HASH_TABLE *p, XML_Parser parser) { p->power = 0; p->size = 0; p->used = 0; p->v = NULL; - p->mem = ms; + p->parser = parser; } static void FASTCALL @@ -7591,13 +8018,13 @@ } static void FASTCALL -poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms) { +poolInit(STRING_POOL *pool, XML_Parser parser) { pool->blocks = NULL; pool->freeBlocks = NULL; pool->start = NULL; pool->ptr = NULL; pool->end = NULL; - pool->mem = ms; + pool->parser = parser; } static void FASTCALL @@ -7624,13 +8051,13 @@ BLOCK *p = pool->blocks; while (p) { BLOCK *tem = p->next; - pool->mem->free_fcn(p); + FREE(pool->parser, p); p = tem; } p = pool->freeBlocks; while (p) { BLOCK *tem = p->next; - pool->mem->free_fcn(p); + FREE(pool->parser, p); p = tem; } } @@ -7654,15 +8081,30 @@ static const XML_Char *FASTCALL poolCopyString(STRING_POOL *pool, const XML_Char *s) { - do { - if (! poolAppendChar(pool, *s)) - return NULL; - } while (*s++); + if (! poolAppendChars(pool, s, xcslen(s) + /*null terminator*/ 1)) + return NULL; s = pool->start; poolFinish(pool); return s; } +// A version of `poolCopyString` that does not call `poolFinish` +// and reverts any partial advancement upon failure. +static const XML_Char *FASTCALL +poolCopyStringNoFinish(STRING_POOL *pool, const XML_Char *s) { + const XML_Char *const original = s; + do { + if (! poolAppendChar(pool, *s)) { + // Revert any previously successful advancement + const ptrdiff_t advancedBy = s - original; + if (advancedBy > 0) + pool->ptr -= advancedBy; + return NULL; + } + } while (*s++); + return pool->start; +} + static const XML_Char * poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n) { if (! pool->ptr && ! poolGrow(pool)) { @@ -7679,10 +8121,8 @@ */ return NULL; /* LCOV_EXCL_LINE */ } - for (; n > 0; --n, s++) { - if (! poolAppendChar(pool, *s)) - return NULL; - } + if (n > 0 && ! poolAppendChars(pool, s, n)) + return NULL; s = pool->start; poolFinish(pool); return s; @@ -7690,11 +8130,8 @@ static const XML_Char *FASTCALL poolAppendString(STRING_POOL *pool, const XML_Char *s) { - while (*s) { - if (! poolAppendChar(pool, *s)) - return NULL; - s++; - } + if (! poolAppendChars(pool, s, xcslen(s))) + return NULL; return pool->start; } @@ -7703,9 +8140,8 @@ const char *end) { if (! poolAppend(pool, enc, ptr, end)) return NULL; - if (pool->ptr == pool->end && ! poolGrow(pool)) + if (! poolAppendChar(pool, 0)) return NULL; - *(pool->ptr)++ = 0; return pool->start; } @@ -7740,7 +8176,7 @@ static XML_Bool FASTCALL poolGrow(STRING_POOL *pool) { if (pool->freeBlocks) { - if (pool->start == 0) { + if (pool->start == NULL) { pool->blocks = pool->freeBlocks; pool->freeBlocks = pool->freeBlocks->next; pool->blocks->next = NULL; @@ -7785,8 +8221,7 @@ if (bytesToAllocate == 0) return XML_FALSE; - temp = (BLOCK *)pool->mem->realloc_fcn(pool->blocks, - (unsigned)bytesToAllocate); + temp = REALLOC(pool->parser, pool->blocks, bytesToAllocate); if (temp == NULL) return XML_FALSE; pool->blocks = temp; @@ -7826,7 +8261,7 @@ if (bytesToAllocate == 0) return XML_FALSE; - tem = pool->mem->malloc_fcn(bytesToAllocate); + tem = MALLOC(pool->parser, bytesToAllocate); if (! tem) return XML_FALSE; tem->size = blockSize; @@ -7841,6 +8276,19 @@ return XML_TRUE; } +static bool FASTCALL +poolGrowUntil(STRING_POOL *pool, size_t needed) { + for (;;) { + const size_t available = pool->end - pool->ptr; + if (available >= needed) { + return true; + } + if (! poolGrow(pool)) { + return false; + } + } +} + static int FASTCALL nextScaffoldPart(XML_Parser parser) { DTD *const dtd = parser->m_dtd; /* save one level of indirection */ @@ -7848,21 +8296,22 @@ int next; if (! dtd->scaffIndex) { - /* Detect and prevent integer overflow. - * The preprocessor guard addresses the "always false" warning - * from -Wtype-limits on platforms where - * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ -#if UINT_MAX >= SIZE_MAX - if (parser->m_groupSize > ((size_t)(-1) / sizeof(int))) { + /* Detect and prevent integer overflow. */ + if (parser->m_groupSize > SIZE_MAX / sizeof(int)) { return -1; } -#endif - dtd->scaffIndex = (int *)MALLOC(parser, parser->m_groupSize * sizeof(int)); + dtd->scaffIndex = MALLOC(parser, parser->m_groupSize * sizeof(int)); if (! dtd->scaffIndex) return -1; + dtd->scaffIndexSize = parser->m_groupSize; dtd->scaffIndex[0] = 0; } + // Will casting to int be safe further down? + if (dtd->scaffCount > INT_MAX) { + return -1; + } + if (dtd->scaffCount >= dtd->scaffSize) { CONTENT_SCAFFOLD *temp; if (dtd->scaffold) { @@ -7875,26 +8324,25 @@ * from -Wtype-limits on platforms where * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX - if (dtd->scaffSize > (size_t)(-1) / 2u / sizeof(CONTENT_SCAFFOLD)) { + if (dtd->scaffSize > SIZE_MAX / 2u / sizeof(CONTENT_SCAFFOLD)) { return -1; } #endif - temp = (CONTENT_SCAFFOLD *)REALLOC( - parser, dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD)); + temp = REALLOC(parser, dtd->scaffold, + dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD)); if (temp == NULL) return -1; dtd->scaffSize *= 2; } else { - temp = (CONTENT_SCAFFOLD *)MALLOC(parser, INIT_SCAFFOLD_ELEMENTS - * sizeof(CONTENT_SCAFFOLD)); + temp = MALLOC(parser, INIT_SCAFFOLD_ELEMENTS * sizeof(CONTENT_SCAFFOLD)); if (temp == NULL) return -1; dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS; } dtd->scaffold = temp; } - next = dtd->scaffCount++; + next = (int)dtd->scaffCount++; me = &dtd->scaffold[next]; if (dtd->scaffLevel) { CONTENT_SCAFFOLD *parent @@ -7926,22 +8374,25 @@ * from -Wtype-limits on platforms where * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX - if (dtd->scaffCount > (size_t)(-1) / sizeof(XML_Content)) { + if (dtd->scaffCount > SIZE_MAX / sizeof(XML_Content)) { return NULL; } - if (dtd->contentStringLen > (size_t)(-1) / sizeof(XML_Char)) { + if (dtd->contentStringLen > SIZE_MAX / sizeof(XML_Char)) { return NULL; } #endif if (dtd->scaffCount * sizeof(XML_Content) - > (size_t)(-1) - dtd->contentStringLen * sizeof(XML_Char)) { + > SIZE_MAX - dtd->contentStringLen * sizeof(XML_Char)) { return NULL; } const size_t allocsize = (dtd->scaffCount * sizeof(XML_Content) + (dtd->contentStringLen * sizeof(XML_Char))); - ret = (XML_Content *)MALLOC(parser, allocsize); + // NOTE: We are avoiding MALLOC(..) here to so that + // applications that are not using XML_FreeContentModel but plain + // free(..) or .free_fcn() to free the content model's memory are safe. + ret = parser->m_mem.malloc_fcn(allocsize); if (! ret) return NULL; @@ -8013,12 +8464,21 @@ const XML_Char *src; dest->name = str; src = dtd->scaffold[src_node].name; - for (;;) { - *str++ = *src; - if (! *src) - break; - src++; + + const size_t nameLen = xcslen(src) + /* null terminator*/ 1; + + // Detect and prevent integer overflow + if (nameLen > SIZE_MAX / sizeof(XML_Char)) { + // NOTE: We are avoiding FREE(..) here because the model + // is not being allocated with MALLOC(..) but with plain + // .malloc_fcn(..). + parser->m_mem.free_fcn(ret); + return NULL; } + + memcpy(str, src, nameLen * sizeof(XML_Char)); + str += nameLen; + dest->numchildren = 0; dest->children = NULL; } else { @@ -8051,6 +8511,8 @@ sizeof(ELEMENT_TYPE)); if (! ret) return NULL; + if (! ret->defaultAttsNames.parser) + hashTableInit(&(ret->defaultAttsNames), getRootParserOf(parser, NULL)); if (ret->name != name) poolDiscard(&dtd->pool); else { @@ -8062,23 +8524,25 @@ } static XML_Char * -copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite) { - size_t charsRequired = 0; - XML_Char *result; - +copyString(const XML_Char *s, XML_Parser parser) { /* First determine how long the string is */ - while (s[charsRequired] != 0) { - charsRequired++; - } - /* Include the terminator */ - charsRequired++; + const size_t charsRequired = xcslen(s) + /*null terminator*/ 1; + + /* Detect and prevent integer overflow */ + if (charsRequired > SIZE_MAX / sizeof(XML_Char)) + return NULL; + + const size_t bytesRequired = charsRequired * sizeof(XML_Char); /* Now allocate space for the copy */ - result = memsuite->malloc_fcn(charsRequired * sizeof(XML_Char)); + XML_Char *const result = MALLOC(parser, bytesRequired); + if (result == NULL) return NULL; + /* Copy the original into place */ - memcpy(result, s, charsRequired * sizeof(XML_Char)); + memcpy(result, s, bytesRequired); + return result; } @@ -8093,10 +8557,10 @@ + rootParser->m_accounting.countBytesIndirect; const float amplificationFactor = rootParser->m_accounting.countBytesDirect - ? (countBytesOutput + ? ((float)countBytesOutput / (float)(rootParser->m_accounting.countBytesDirect)) - : ((lenOfShortestInclude - + rootParser->m_accounting.countBytesIndirect) + : ((float)(lenOfShortestInclude + + rootParser->m_accounting.countBytesIndirect) / (float)lenOfShortestInclude); assert(! rootParser->m_parentParser); return amplificationFactor; @@ -8245,15 +8709,25 @@ const char *const entityName = entity->name; # endif + const bool limitingWanted = rootParser->m_entity_stats.debugLevel < 2; + const int maxLimitedDepth = 10; // somewhat arbitrary + const int candidateIndentDepth + = (int)rootParser->m_entity_stats.currentDepth - 1; + const bool limitingNeeded + = limitingWanted && (candidateIndentDepth > maxLimitedDepth); + const char *const ellipisOrEmpty = limitingNeeded ? " [..] " : ""; + const int indentDepth + = limitingNeeded ? (maxLimitedDepth - /* make space for ellipis */ 2) + : candidateIndentDepth; + fprintf( stderr, - "expat: Entities(%p): Count %9u, depth %2u/%2u %*s%s%s; %s length %d (xmlparse.c:%d)\n", + "expat: Entities(%p): Count %9u, depth %2u/%2u %*s%s%s%s; %s length %d (xmlparse.c:%d)\n", (void *)rootParser, rootParser->m_entity_stats.countEverOpened, rootParser->m_entity_stats.currentDepth, - rootParser->m_entity_stats.maximumDepthSeen, - ((int)rootParser->m_entity_stats.currentDepth - 1) * 2, "", - entity->is_param ? "%" : "&", entityName, action, entity->textLen, - sourceLine); + rootParser->m_entity_stats.maximumDepthSeen, indentDepth * 2, "", + ellipisOrEmpty, entity->is_param ? "%" : "&", entityName, action, + entity->textLen, sourceLine); } static void @@ -8280,6 +8754,8 @@ rootParser->m_entity_stats.currentDepth--; } +#endif /* XML_GE == 1 */ + static XML_Parser getRootParserOf(XML_Parser parser, unsigned int *outLevelDiff) { XML_Parser rootParser = parser; @@ -8295,6 +8771,8 @@ return rootParser; } +#if XML_GE == 1 + const char * unsignedCharToPrintable(unsigned char c) { switch (c) { diff -Nru expat-2.7.1/expat/lib/xmlrole.c expat-2.8.2/expat/lib/xmlrole.c --- expat-2.7.1/expat/lib/xmlrole.c 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/lib/xmlrole.c 2026-06-25 14:07:00.000000000 +0000 @@ -16,6 +16,7 @@ Copyright (c) 2017 Rhodri James Copyright (c) 2019 David Loffredo Copyright (c) 2021 Donghee Na + Copyright (c) 2025 Alfonso Gregory Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -46,7 +47,6 @@ # include "winconfig.h" #endif -#include "expat_external.h" #include "internal.h" #include "xmlrole.h" #include "ascii.h" diff -Nru expat-2.7.1/expat/lib/xmlrole.h expat-2.8.2/expat/lib/xmlrole.h --- expat-2.7.1/expat/lib/xmlrole.h 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/lib/xmlrole.h 2026-06-25 14:07:00.000000000 +0000 @@ -10,7 +10,7 @@ Copyright (c) 2000 Clark Cooper Copyright (c) 2002 Karl Waclawek Copyright (c) 2002 Fred L. Drake, Jr. - Copyright (c) 2017-2024 Sebastian Pipping + Copyright (c) 2017-2025 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -34,19 +34,13 @@ */ #ifndef XmlRole_INCLUDED -#define XmlRole_INCLUDED 1 +# define XmlRole_INCLUDED 1 -#ifdef __VMS -/* 0 1 2 3 0 1 2 3 - 1234567890123456789012345678901 1234567890123456789012345678901 */ -# define XmlPrologStateInitExternalEntity XmlPrologStateInitExternalEnt -#endif +# include "xmltok.h" -#include "xmltok.h" - -#ifdef __cplusplus +# ifdef __cplusplus extern "C" { -#endif +# endif enum { XML_ROLE_ERROR = -1, @@ -107,11 +101,11 @@ XML_ROLE_CONTENT_ELEMENT_PLUS, XML_ROLE_PI, XML_ROLE_COMMENT, -#ifdef XML_DTD +# ifdef XML_DTD XML_ROLE_TEXT_DECL, XML_ROLE_IGNORE_SECT, XML_ROLE_INNER_PARAM_ENTITY_REF, -#endif /* XML_DTD */ +# endif /* XML_DTD */ XML_ROLE_PARAM_ENTITY_REF }; @@ -120,23 +114,23 @@ const char *end, const ENCODING *enc); unsigned level; int role_none; -#ifdef XML_DTD +# ifdef XML_DTD unsigned includeLevel; int documentEntity; int inEntityValue; -#endif /* XML_DTD */ +# endif /* XML_DTD */ } PROLOG_STATE; void XmlPrologStateInit(PROLOG_STATE *state); -#ifdef XML_DTD +# ifdef XML_DTD void XmlPrologStateInitExternalEntity(PROLOG_STATE *state); -#endif /* XML_DTD */ +# endif /* XML_DTD */ -#define XmlTokenRole(state, tok, ptr, end, enc) \ - (((state)->handler)(state, tok, ptr, end, enc)) +# define XmlTokenRole(state, tok, ptr, end, enc) \ + (((state)->handler)(state, tok, ptr, end, enc)) -#ifdef __cplusplus +# ifdef __cplusplus } -#endif +# endif #endif /* not XmlRole_INCLUDED */ diff -Nru expat-2.7.1/expat/lib/xmltok.c expat-2.8.2/expat/lib/xmltok.c --- expat-2.7.1/expat/lib/xmltok.c 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/lib/xmltok.c 2026-06-25 14:07:00.000000000 +0000 @@ -24,6 +24,8 @@ Copyright (c) 2022 Martin Ettl Copyright (c) 2022 Sean McBride Copyright (c) 2023 Hanno Böck + Copyright (c) 2025 Alfonso Gregory + Copyright (c) 2026 Nick Begg Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -56,8 +58,8 @@ # include "winconfig.h" #endif -#include "expat_external.h" #include "internal.h" +#include "fallthrough.h" #include "xmltok.h" #include "nametab.h" @@ -641,7 +643,7 @@ *(*toP)++ = lo; \ break; \ } \ - /* fall through */ \ + EXPAT_FALLTHROUGH; \ case 0x1: \ case 0x2: \ case 0x3: \ @@ -1398,7 +1400,7 @@ } ENCODING * -XmlInitUnknownEncoding(void *mem, int *table, CONVERTER convert, +XmlInitUnknownEncoding(void *mem, const int *table, CONVERTER convert, void *userData) { int i; struct unknown_encoding *e = (struct unknown_encoding *)mem; @@ -1557,7 +1559,7 @@ case 0xEF: /* possibly first byte of UTF-8 BOM */ if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE) break; - /* fall through */ + EXPAT_FALLTHROUGH; case 0x00: case 0x3C: return XML_TOK_PARTIAL; @@ -1661,7 +1663,7 @@ # undef ns ENCODING * -XmlInitUnknownEncodingNS(void *mem, int *table, CONVERTER convert, +XmlInitUnknownEncodingNS(void *mem, const int *table, CONVERTER convert, void *userData) { ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData); if (enc) diff -Nru expat-2.7.1/expat/lib/xmltok.h expat-2.8.2/expat/lib/xmltok.h --- expat-2.7.1/expat/lib/xmltok.h 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/lib/xmltok.h 2026-06-25 14:07:00.000000000 +0000 @@ -35,113 +35,113 @@ */ #ifndef XmlTok_INCLUDED -#define XmlTok_INCLUDED 1 +# define XmlTok_INCLUDED 1 -#ifdef __cplusplus +# ifdef __cplusplus extern "C" { -#endif +# endif /* The following token may be returned by XmlContentTok */ -#define XML_TOK_TRAILING_RSQB \ - -5 /* ] or ]] at the end of the scan; might be \ - start of illegal ]]> sequence */ +# define XML_TOK_TRAILING_RSQB \ + -5 /* ] or ]] at the end of the scan; might be \ + start of illegal ]]> sequence */ /* The following tokens may be returned by both XmlPrologTok and XmlContentTok. */ -#define XML_TOK_NONE -4 /* The string to be scanned is empty */ -#define XML_TOK_TRAILING_CR \ - -3 /* A CR at the end of the scan; \ - might be part of CRLF sequence */ -#define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */ -#define XML_TOK_PARTIAL -1 /* only part of a token */ -#define XML_TOK_INVALID 0 +# define XML_TOK_NONE -4 /* The string to be scanned is empty */ +# define XML_TOK_TRAILING_CR \ + -3 /* A CR at the end of the scan; \ + might be part of CRLF sequence */ +# define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */ +# define XML_TOK_PARTIAL -1 /* only part of a token */ +# define XML_TOK_INVALID 0 /* The following tokens are returned by XmlContentTok; some are also returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok. */ -#define XML_TOK_START_TAG_WITH_ATTS 1 -#define XML_TOK_START_TAG_NO_ATTS 2 -#define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag */ -#define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4 -#define XML_TOK_END_TAG 5 -#define XML_TOK_DATA_CHARS 6 -#define XML_TOK_DATA_NEWLINE 7 -#define XML_TOK_CDATA_SECT_OPEN 8 -#define XML_TOK_ENTITY_REF 9 -#define XML_TOK_CHAR_REF 10 /* numeric character reference */ +# define XML_TOK_START_TAG_WITH_ATTS 1 +# define XML_TOK_START_TAG_NO_ATTS 2 +# define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag */ +# define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4 +# define XML_TOK_END_TAG 5 +# define XML_TOK_DATA_CHARS 6 +# define XML_TOK_DATA_NEWLINE 7 +# define XML_TOK_CDATA_SECT_OPEN 8 +# define XML_TOK_ENTITY_REF 9 +# define XML_TOK_CHAR_REF 10 /* numeric character reference */ /* The following tokens may be returned by both XmlPrologTok and XmlContentTok. */ -#define XML_TOK_PI 11 /* processing instruction */ -#define XML_TOK_XML_DECL 12 /* XML decl or text decl */ -#define XML_TOK_COMMENT 13 -#define XML_TOK_BOM 14 /* Byte order mark */ +# define XML_TOK_PI 11 /* processing instruction */ +# define XML_TOK_XML_DECL 12 /* XML decl or text decl */ +# define XML_TOK_COMMENT 13 +# define XML_TOK_BOM 14 /* Byte order mark */ /* The following tokens are returned only by XmlPrologTok */ -#define XML_TOK_PROLOG_S 15 -#define XML_TOK_DECL_OPEN 16 /* */ -#define XML_TOK_NAME 18 -#define XML_TOK_NMTOKEN 19 -#define XML_TOK_POUND_NAME 20 /* #name */ -#define XML_TOK_OR 21 /* | */ -#define XML_TOK_PERCENT 22 -#define XML_TOK_OPEN_PAREN 23 -#define XML_TOK_CLOSE_PAREN 24 -#define XML_TOK_OPEN_BRACKET 25 -#define XML_TOK_CLOSE_BRACKET 26 -#define XML_TOK_LITERAL 27 -#define XML_TOK_PARAM_ENTITY_REF 28 -#define XML_TOK_INSTANCE_START 29 +# define XML_TOK_PROLOG_S 15 +# define XML_TOK_DECL_OPEN 16 /* */ +# define XML_TOK_NAME 18 +# define XML_TOK_NMTOKEN 19 +# define XML_TOK_POUND_NAME 20 /* #name */ +# define XML_TOK_OR 21 /* | */ +# define XML_TOK_PERCENT 22 +# define XML_TOK_OPEN_PAREN 23 +# define XML_TOK_CLOSE_PAREN 24 +# define XML_TOK_OPEN_BRACKET 25 +# define XML_TOK_CLOSE_BRACKET 26 +# define XML_TOK_LITERAL 27 +# define XML_TOK_PARAM_ENTITY_REF 28 +# define XML_TOK_INSTANCE_START 29 /* The following occur only in element type declarations */ -#define XML_TOK_NAME_QUESTION 30 /* name? */ -#define XML_TOK_NAME_ASTERISK 31 /* name* */ -#define XML_TOK_NAME_PLUS 32 /* name+ */ -#define XML_TOK_COND_SECT_OPEN 33 /* */ -#define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */ -#define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */ -#define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */ -#define XML_TOK_COMMA 38 +# define XML_TOK_NAME_QUESTION 30 /* name? */ +# define XML_TOK_NAME_ASTERISK 31 /* name* */ +# define XML_TOK_NAME_PLUS 32 /* name+ */ +# define XML_TOK_COND_SECT_OPEN 33 /* */ +# define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */ +# define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */ +# define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */ +# define XML_TOK_COMMA 38 /* The following token is returned only by XmlAttributeValueTok */ -#define XML_TOK_ATTRIBUTE_VALUE_S 39 +# define XML_TOK_ATTRIBUTE_VALUE_S 39 /* The following token is returned only by XmlCdataSectionTok */ -#define XML_TOK_CDATA_SECT_CLOSE 40 +# define XML_TOK_CDATA_SECT_CLOSE 40 /* With namespace processing this is returned by XmlPrologTok for a name with a colon. */ -#define XML_TOK_PREFIXED_NAME 41 +# define XML_TOK_PREFIXED_NAME 41 -#ifdef XML_DTD -# define XML_TOK_IGNORE_SECT 42 -#endif /* XML_DTD */ - -#ifdef XML_DTD -# define XML_N_STATES 4 -#else /* not XML_DTD */ -# define XML_N_STATES 3 -#endif /* not XML_DTD */ - -#define XML_PROLOG_STATE 0 -#define XML_CONTENT_STATE 1 -#define XML_CDATA_SECTION_STATE 2 -#ifdef XML_DTD -# define XML_IGNORE_SECTION_STATE 3 -#endif /* XML_DTD */ - -#define XML_N_LITERAL_TYPES 2 -#define XML_ATTRIBUTE_VALUE_LITERAL 0 -#define XML_ENTITY_VALUE_LITERAL 1 +# ifdef XML_DTD +# define XML_TOK_IGNORE_SECT 42 +# endif /* XML_DTD */ + +# ifdef XML_DTD +# define XML_N_STATES 4 +# else /* not XML_DTD */ +# define XML_N_STATES 3 +# endif /* not XML_DTD */ + +# define XML_PROLOG_STATE 0 +# define XML_CONTENT_STATE 1 +# define XML_CDATA_SECTION_STATE 2 +# ifdef XML_DTD +# define XML_IGNORE_SECTION_STATE 3 +# endif /* XML_DTD */ + +# define XML_N_LITERAL_TYPES 2 +# define XML_ATTRIBUTE_VALUE_LITERAL 0 +# define XML_ENTITY_VALUE_LITERAL 1 /* The size of the buffer passed to XmlUtf8Encode must be at least this. */ -#define XML_UTF8_ENCODE_MAX 4 +# define XML_UTF8_ENCODE_MAX 4 /* The size of the buffer passed to XmlUtf16Encode must be at least this. */ -#define XML_UTF16_ENCODE_MAX 2 +# define XML_UTF16_ENCODE_MAX 2 typedef struct position { /* first line and first column are 0 not 1 */ @@ -220,63 +220,63 @@ the prolog outside literals, comments and processing instructions. */ -#define XmlTok(enc, state, ptr, end, nextTokPtr) \ - (((enc)->scanners[state])(enc, ptr, end, nextTokPtr)) +# define XmlTok(enc, state, ptr, end, nextTokPtr) \ + (((enc)->scanners[state])(enc, ptr, end, nextTokPtr)) -#define XmlPrologTok(enc, ptr, end, nextTokPtr) \ - XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr) +# define XmlPrologTok(enc, ptr, end, nextTokPtr) \ + XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr) -#define XmlContentTok(enc, ptr, end, nextTokPtr) \ - XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr) +# define XmlContentTok(enc, ptr, end, nextTokPtr) \ + XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr) -#define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \ - XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr) +# define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \ + XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr) -#ifdef XML_DTD +# ifdef XML_DTD -# define XmlIgnoreSectionTok(enc, ptr, end, nextTokPtr) \ - XmlTok(enc, XML_IGNORE_SECTION_STATE, ptr, end, nextTokPtr) +# define XmlIgnoreSectionTok(enc, ptr, end, nextTokPtr) \ + XmlTok(enc, XML_IGNORE_SECTION_STATE, ptr, end, nextTokPtr) -#endif /* XML_DTD */ +# endif /* XML_DTD */ /* This is used for performing a 2nd-level tokenization on the content of a literal that has already been returned by XmlTok. */ -#define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \ - (((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr)) +# define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \ + (((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr)) -#define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \ - XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr) +# define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \ + XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr) -#define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \ - XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr) +# define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \ + XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr) -#define XmlNameMatchesAscii(enc, ptr1, end1, ptr2) \ - (((enc)->nameMatchesAscii)(enc, ptr1, end1, ptr2)) +# define XmlNameMatchesAscii(enc, ptr1, end1, ptr2) \ + (((enc)->nameMatchesAscii)(enc, ptr1, end1, ptr2)) -#define XmlNameLength(enc, ptr) (((enc)->nameLength)(enc, ptr)) +# define XmlNameLength(enc, ptr) (((enc)->nameLength)(enc, ptr)) -#define XmlSkipS(enc, ptr) (((enc)->skipS)(enc, ptr)) +# define XmlSkipS(enc, ptr) (((enc)->skipS)(enc, ptr)) -#define XmlGetAttributes(enc, ptr, attsMax, atts) \ - (((enc)->getAtts)(enc, ptr, attsMax, atts)) +# define XmlGetAttributes(enc, ptr, attsMax, atts) \ + (((enc)->getAtts)(enc, ptr, attsMax, atts)) -#define XmlCharRefNumber(enc, ptr) (((enc)->charRefNumber)(enc, ptr)) +# define XmlCharRefNumber(enc, ptr) (((enc)->charRefNumber)(enc, ptr)) -#define XmlPredefinedEntityName(enc, ptr, end) \ - (((enc)->predefinedEntityName)(enc, ptr, end)) +# define XmlPredefinedEntityName(enc, ptr, end) \ + (((enc)->predefinedEntityName)(enc, ptr, end)) -#define XmlUpdatePosition(enc, ptr, end, pos) \ - (((enc)->updatePosition)(enc, ptr, end, pos)) +# define XmlUpdatePosition(enc, ptr, end, pos) \ + (((enc)->updatePosition)(enc, ptr, end, pos)) -#define XmlIsPublicId(enc, ptr, end, badPtr) \ - (((enc)->isPublicId)(enc, ptr, end, badPtr)) +# define XmlIsPublicId(enc, ptr, end, badPtr) \ + (((enc)->isPublicId)(enc, ptr, end, badPtr)) -#define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \ - (((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim)) +# define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \ + (((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim)) -#define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \ - (((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim)) +# define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \ + (((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim)) typedef struct { ENCODING initEnc; @@ -299,7 +299,7 @@ typedef int(XMLCALL *CONVERTER)(void *userData, const char *p); -ENCODING *XmlInitUnknownEncoding(void *mem, int *table, CONVERTER convert, +ENCODING *XmlInitUnknownEncoding(void *mem, const int *table, CONVERTER convert, void *userData); int XmlParseXmlDeclNS(int isGeneralTextEntity, const ENCODING *enc, @@ -312,10 +312,10 @@ const char *name); const ENCODING *XmlGetUtf8InternalEncodingNS(void); const ENCODING *XmlGetUtf16InternalEncodingNS(void); -ENCODING *XmlInitUnknownEncodingNS(void *mem, int *table, CONVERTER convert, - void *userData); -#ifdef __cplusplus +ENCODING *XmlInitUnknownEncodingNS(void *mem, const int *table, + CONVERTER convert, void *userData); +# ifdef __cplusplus } -#endif +# endif #endif /* not XmlTok_INCLUDED */ diff -Nru expat-2.7.1/expat/lib/xmltok_impl.c expat-2.8.2/expat/lib/xmltok_impl.c --- expat-2.7.1/expat/lib/xmltok_impl.c 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/lib/xmltok_impl.c 2026-06-25 14:07:00.000000000 +0000 @@ -17,6 +17,7 @@ Copyright (c) 2019 David Loffredo Copyright (c) 2020 Boris Kolpackov Copyright (c) 2022 Martin Ettl + Copyright (c) 2026 Nick Begg Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -83,7 +84,7 @@ *nextTokPtr = ptr; \ return XML_TOK_INVALID; \ } \ - /* fall through */ \ + EXPAT_FALLTHROUGH; \ case BT_NMSTRT: \ case BT_HEX: \ case BT_DIGIT: \ @@ -112,7 +113,7 @@ *nextTokPtr = ptr; \ return XML_TOK_INVALID; \ } \ - /* fall through */ \ + EXPAT_FALLTHROUGH; \ case BT_NMSTRT: \ case BT_HEX: \ ptr += MINBPC(enc); \ @@ -209,7 +210,7 @@ *nextTokPtr = ptr; return XML_TOK_INVALID; } - /* fall through */ + EXPAT_FALLTHROUGH; case BT_S: case BT_CR: case BT_LF: @@ -323,7 +324,7 @@ *nextTokPtr = ptr + MINBPC(enc); return tok; } - /* fall through */ + EXPAT_FALLTHROUGH; default: *nextTokPtr = ptr; return XML_TOK_INVALID; @@ -615,7 +616,7 @@ return XML_TOK_INVALID; } } - /* fall through */ + EXPAT_FALLTHROUGH; case BT_EQUALS: { int open; # ifdef XML_NS @@ -898,7 +899,7 @@ return XML_TOK_INVALID; } } - /* fall through */ + EXPAT_FALLTHROUGH; case BT_AMP: case BT_LT: case BT_NONXML: @@ -1059,7 +1060,7 @@ /* indicate that this might be part of a CR/LF pair */ return -XML_TOK_PROLOG_S; } - /* fall through */ + EXPAT_FALLTHROUGH; case BT_S: case BT_LF: for (;;) { @@ -1074,7 +1075,7 @@ /* don't split CR/LF pair */ if (ptr + MINBPC(enc) != end) break; - /* fall through */ + EXPAT_FALLTHROUGH; default: *nextTokPtr = ptr; return XML_TOK_PROLOG_S; @@ -1189,7 +1190,7 @@ tok = XML_TOK_NMTOKEN; break; } - /* fall through */ + EXPAT_FALLTHROUGH; default: *nextTokPtr = ptr; return XML_TOK_INVALID; @@ -1484,7 +1485,7 @@ case BT_NMSTRT: if (! (BYTE_TO_ASCII(enc, ptr) & ~0x7f)) break; - /* fall through */ + EXPAT_FALLTHROUGH; default: switch (BYTE_TO_ASCII(enc, ptr)) { case 0x24: /* $ */ diff -Nru expat-2.7.1/expat/lib/xmltok_ns.c expat-2.8.2/expat/lib/xmltok_ns.c --- expat-2.7.1/expat/lib/xmltok_ns.c 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/lib/xmltok_ns.c 2026-06-25 14:07:00.000000000 +0000 @@ -12,6 +12,7 @@ Copyright (c) 2002 Fred L. Drake, Jr. Copyright (c) 2002-2006 Karl Waclawek Copyright (c) 2017-2021 Sebastian Pipping + Copyright (c) 2025 Alfonso Gregory Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -98,13 +99,13 @@ int i; XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1); if (ptr != end) - return 0; + return NULL; *p = 0; if (streqci(buf, KW_UTF_16) && enc->minBytesPerChar == 2) return enc; i = getEncodingIndex(buf); if (i == UNKNOWN_ENC) - return 0; + return NULL; return NS(encodings)[i]; } diff -Nru expat-2.7.1/expat/memory-sanitizer-blacklist.txt expat-2.8.2/expat/memory-sanitizer-blacklist.txt --- expat-2.7.1/expat/memory-sanitizer-blacklist.txt 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/memory-sanitizer-blacklist.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -# Line "hash_secret_salt = generate_hash_secret_salt(parser);" -# is mis-reported as use-of-uninitialized-value because -# its call to writeRandomBytes_getrandom uses syscall -# SYS_getrandom and MemorySanitizer does not seem to understand that -# as writing bytes to that memory (which it does). -fun:startParsing diff -Nru expat-2.7.1/expat/qa.sh expat-2.8.2/expat/qa.sh --- expat-2.7.1/expat/qa.sh 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/qa.sh 2026-06-25 14:07:00.000000000 +0000 @@ -6,10 +6,11 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2016-2023 Sebastian Pipping +# Copyright (c) 2016-2025 Sebastian Pipping # Copyright (c) 2019 Philippe Antoine # Copyright (c) 2019-2025 Hanno Böck # Copyright (c) 2024 Alexander Bluhm +# Copyright (c) 2026 Matthew Fernandez # Licensed under the MIT license: # # Permission is hereby granted, free of charge, to any person obtaining @@ -98,7 +99,7 @@ ;; memory) # https://clang.llvm.org/docs/MemorySanitizer.html - BASE_COMPILE_FLAGS+=" -fsanitize=memory -fno-omit-frame-pointer -g -O2 -fsanitize-memory-track-origins -fsanitize-blacklist=$PWD/memory-sanitizer-blacklist.txt" + BASE_COMPILE_FLAGS+=" -fsanitize=memory -fno-omit-frame-pointer -g -O2 -fsanitize-memory-track-origins" ;; undefined) # https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html @@ -175,11 +176,20 @@ CTEST_OUTPUT_ON_FAILURE=1 CTEST_PARALLEL_LEVEL=2 VERBOSE=1 - test ) - [[ $* =~ -DEXPAT_DTD=OFF ]] || make_args+=( run-xmltest ) - RUN "${MAKE}" "${make_args[@]}" + RUN "${MAKE}" "${make_args[@]}" test + + if [[ ! $* =~ -DEXPAT_DTD=OFF ]]; then + # NOTE: This is meant to mitigate Wine crashing randomly in CI + if [[ ${CC} =~ mingw ]]; then + local retry='retry --times 5 --' + else + local retry= + fi + + RUN ${retry} "${MAKE}" "${make_args[@]}" run-xmltest + fi } diff -Nru expat-2.7.1/expat/tests/.gitignore expat-2.8.2/expat/tests/.gitignore --- expat-2.7.1/expat/tests/.gitignore 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/.gitignore 2026-06-25 14:07:00.000000000 +0000 @@ -6,7 +6,6 @@ /xmltest.log Makefile runtests -runtests_cxx xmlts.zip XML-Test-Suite .libs diff -Nru expat-2.7.1/expat/tests/Makefile.am expat-2.8.2/expat/tests/Makefile.am --- expat-2.7.1/expat/tests/Makefile.am 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/Makefile.am 2026-06-25 14:07:00.000000000 +0000 @@ -6,7 +6,7 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2017-2024 Sebastian Pipping +# Copyright (c) 2017-2026 Sebastian Pipping # Copyright (c) 2017-2022 Rhodri James # Copyright (c) 2020 Jeffrey Walton # Copyright (c) 2024 Dag-Erling Smørgrav @@ -35,8 +35,8 @@ AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(srcdir)/../lib -DXML_TESTING -check_PROGRAMS = runtests runtests_cxx -TESTS = runtests runtests_cxx +check_PROGRAMS = runtests +TESTS = runtests # To support MinGW and Non-MinGW at the same time: LOG_DRIVER = $(srcdir)/../test-driver-wrapper.sh @@ -57,27 +57,9 @@ runtests.c \ structdata.c -runtests_cxx_SOURCES = \ - acc_tests_cxx.cpp \ - alloc_tests_cxx.cpp \ - basic_tests_cxx.cpp \ - chardata_cxx.cpp \ - common_cxx.cpp \ - dummy_cxx.cpp \ - handlers_cxx.cpp \ - memcheck_cxx.cpp \ - minicheck_cxx.cpp \ - misc_tests_cxx.cpp \ - nsalloc_tests_cxx.cpp \ - ns_tests_cxx.cpp \ - runtests_cxx.cpp \ - structdata_cxx.cpp - runtests_LDADD = ../lib/libtestpat.la -runtests_cxx_LDADD = ../lib/libtestpat.la runtests_LDFLAGS = @AM_LDFLAGS@ @LIBM@ -runtests_cxx_LDFLAGS = @AM_LDFLAGS@ @LIBM@ EXTRA_DIST = \ acc_tests.h \ diff -Nru expat-2.7.1/expat/tests/acc_tests.c expat-2.8.2/expat/tests/acc_tests.c --- expat-2.7.1/expat/tests/acc_tests.c 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/acc_tests.c 2026-06-25 14:07:00.000000000 +0000 @@ -10,7 +10,7 @@ Copyright (c) 2003 Greg Stein Copyright (c) 2005-2007 Steven Solie Copyright (c) 2005-2012 Karl Waclawek - Copyright (c) 2016-2024 Sebastian Pipping + Copyright (c) 2016-2026 Sebastian Pipping Copyright (c) 2017-2022 Rhodri James Copyright (c) 2017 Joe Orton Copyright (c) 2017 José Gutiérrez de la Concha @@ -41,12 +41,12 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include "expat_config.h" + #include /* NAN, INFINITY */ #include #include -#include "expat_config.h" - #include "expat.h" #include "internal.h" #include "common.h" diff -Nru expat-2.7.1/expat/tests/acc_tests_cxx.cpp expat-2.8.2/expat/tests/acc_tests_cxx.cpp --- expat-2.7.1/expat/tests/acc_tests_cxx.cpp 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/acc_tests_cxx.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -/* C++ compilation harness for the test suite. - __ __ _ - ___\ \/ /_ __ __ _| |_ - / _ \\ /| '_ \ / _` | __| - | __// \| |_) | (_| | |_ - \___/_/\_\ .__/ \__,_|\__| - |_| XML parser - - Copyright (c) 2023 Sebastian Pipping - Licensed under the MIT license: - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to permit - persons to whom the Software is furnished to do so, subject to the - following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "acc_tests.c" diff -Nru expat-2.7.1/expat/tests/alloc_tests.c expat-2.8.2/expat/tests/alloc_tests.c --- expat-2.7.1/expat/tests/alloc_tests.c 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/alloc_tests.c 2026-06-25 14:07:00.000000000 +0000 @@ -10,7 +10,7 @@ Copyright (c) 2003 Greg Stein Copyright (c) 2005-2007 Steven Solie Copyright (c) 2005-2012 Karl Waclawek - Copyright (c) 2016-2023 Sebastian Pipping + Copyright (c) 2016-2026 Sebastian Pipping Copyright (c) 2017-2022 Rhodri James Copyright (c) 2017 Joe Orton Copyright (c) 2017 José Gutiérrez de la Concha @@ -20,6 +20,7 @@ Copyright (c) 2021 Donghee Na Copyright (c) 2023 Sony Corporation / Snild Dolkow Copyright (c) 2025 Berkay Eren Ürün + Copyright (c) 2026 Matthew Fernandez Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -46,10 +47,16 @@ # undef NDEBUG /* because test suite relies on assert(...) at the moment */ #endif +#include "expat_config.h" + +#include /* NAN, INFINITY */ +#include +#include /* for SIZE_MAX */ #include #include #include "expat.h" +#include "internal.h" #include "common.h" #include "minicheck.h" #include "dummy.h" @@ -323,7 +330,7 @@ XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); XML_SetUserData(g_parser, foo_text); XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader); - g_allocation_count = i; + g_allocation_count = (int)i; if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; @@ -434,7 +441,7 @@ const unsigned int max_alloc_count = 20; for (i = 0; i < max_alloc_count; i++) { - g_allocation_count = i; + g_allocation_count = (int)i; XML_SetUnknownEncodingHandler(g_parser, unknown_released_encoding_handler, NULL); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) @@ -2085,6 +2092,225 @@ } END_TEST +#if XML_GE == 1 +static size_t +sizeRecordedFor(void *ptr) { + return *(size_t *)((char *)ptr - EXPAT_MALLOC_PADDING - sizeof(size_t)); +} +#endif // XML_GE == 1 + +START_TEST(test_alloc_tracker_size_recorded) { + XML_Memory_Handling_Suite memsuite = {malloc, realloc, free}; + + bool values[] = {true, false}; + for (size_t i = 0; i < sizeof(values) / sizeof(values[0]); i++) { + const bool useMemSuite = values[i]; + set_subtest("useMemSuite=%d", (int)useMemSuite); + XML_Parser parser = useMemSuite + ? XML_ParserCreate_MM(NULL, &memsuite, XCS("|")) + : XML_ParserCreate(NULL); + +#if XML_GE == 1 + void *ptr = expat_malloc(parser, 10, -1); + + assert_true(ptr != NULL); + assert_true(sizeRecordedFor(ptr) == 10); + + assert_true(expat_realloc(parser, ptr, SIZE_MAX / 2, -1) == NULL); + + assert_true(sizeRecordedFor(ptr) == 10); // i.e. unchanged + + ptr = expat_realloc(parser, ptr, 20, -1); + + assert_true(ptr != NULL); + assert_true(sizeRecordedFor(ptr) == 20); + + expat_free(parser, ptr, -1); +#endif + + XML_ParserFree(parser); + } +} +END_TEST + +START_TEST(test_alloc_tracker_pointer_alignment) { + XML_Parser parser = XML_ParserCreate(NULL); +#if XML_GE == 1 + assert_true(sizeof(long long) >= sizeof(size_t)); // self-test + long long *const ptr = expat_malloc(parser, 4 * sizeof(long long), -1); + ptr[0] = 0LL; + ptr[1] = 1LL; + ptr[2] = 2LL; + ptr[3] = 3LL; + expat_free(parser, ptr, -1); +#endif + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_alloc_tracker_maximum_amplification) { + if (g_reparseDeferralEnabledDefault == XML_TRUE) { + return; + } + + XML_Parser parser = XML_ParserCreate(NULL); + + // Get .m_accounting.countBytesDirect from 0 to 3 + const char *const chunk = ""; + assert_true(_XML_Parse_SINGLE_BYTES(parser, chunk, (int)strlen(chunk), + /*isFinal=*/XML_FALSE) + == XML_STATUS_OK); + +#if XML_GE == 1 + // Stop activation threshold from interfering + assert_true(XML_SetAllocTrackerActivationThreshold(parser, 0) == XML_TRUE); + + // Exceed maximum amplification: should be rejected. + assert_true(expat_malloc(parser, 1000, -1) == NULL); + + // Increase maximum amplification, and try the same amount once more: should + // work. + assert_true(XML_SetAllocTrackerMaximumAmplification(parser, 3000.0f) + == XML_TRUE); + + void *const ptr = expat_malloc(parser, 1000, -1); + assert_true(ptr != NULL); + expat_free(parser, ptr, -1); +#endif + + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_alloc_tracker_threshold) { + XML_Parser parser = XML_ParserCreate(NULL); + +#if XML_GE == 1 + // Exceed maximum amplification *before* (default) threshold: should work. + void *const ptr = expat_malloc(parser, 1000, -1); + assert_true(ptr != NULL); + expat_free(parser, ptr, -1); + + // Exceed maximum amplification *after* threshold: should be rejected. + assert_true(XML_SetAllocTrackerActivationThreshold(parser, 999) == XML_TRUE); + assert_true(expat_malloc(parser, 1000, -1) == NULL); +#endif + + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_alloc_tracker_getbuffer_unlimited) { + XML_Parser parser = XML_ParserCreate(NULL); + +#if XML_GE == 1 + // Artificially lower threshold + assert_true(XML_SetAllocTrackerActivationThreshold(parser, 0) == XML_TRUE); + + // Self-test: Prove that threshold is as rejecting as expected + assert_true(expat_malloc(parser, 1000, -1) == NULL); +#endif + // XML_GetBuffer should be allowed to pass, though + assert_true(XML_GetBuffer(parser, 1000) != NULL); + + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_alloc_tracker_api) { + XML_Parser parserWithoutParent = XML_ParserCreate(NULL); + XML_Parser parserWithParent = XML_ExternalEntityParserCreate( + parserWithoutParent, XCS("entity123"), NULL); + if (parserWithoutParent == NULL) + fail("parserWithoutParent is NULL"); + if (parserWithParent == NULL) + fail("parserWithParent is NULL"); + +#if XML_GE == 1 + // XML_SetAllocTrackerMaximumAmplification, error cases + if (XML_SetAllocTrackerMaximumAmplification(NULL, 123.0f) == XML_TRUE) + fail("Call with NULL parser is NOT supposed to succeed"); + if (XML_SetAllocTrackerMaximumAmplification(parserWithParent, 123.0f) + == XML_TRUE) + fail("Call with non-root parser is NOT supposed to succeed"); + if (XML_SetAllocTrackerMaximumAmplification(parserWithoutParent, NAN) + == XML_TRUE) + fail("Call with NaN limit is NOT supposed to succeed"); + if (XML_SetAllocTrackerMaximumAmplification(parserWithoutParent, -1.0f) + == XML_TRUE) + fail("Call with negative limit is NOT supposed to succeed"); + if (XML_SetAllocTrackerMaximumAmplification(parserWithoutParent, 0.9f) + == XML_TRUE) + fail("Call with positive limit <1.0 is NOT supposed to succeed"); + + // XML_SetAllocTrackerMaximumAmplification, success cases + if (XML_SetAllocTrackerMaximumAmplification(parserWithoutParent, 1.0f) + == XML_FALSE) + fail("Call with positive limit >=1.0 is supposed to succeed"); + if (XML_SetAllocTrackerMaximumAmplification(parserWithoutParent, 123456.789f) + == XML_FALSE) + fail("Call with positive limit >=1.0 is supposed to succeed"); + if (XML_SetAllocTrackerMaximumAmplification(parserWithoutParent, INFINITY) + == XML_FALSE) + fail("Call with positive limit >=1.0 is supposed to succeed"); + + // XML_SetAllocTrackerActivationThreshold, error cases + if (XML_SetAllocTrackerActivationThreshold(NULL, 123) == XML_TRUE) + fail("Call with NULL parser is NOT supposed to succeed"); + if (XML_SetAllocTrackerActivationThreshold(parserWithParent, 123) == XML_TRUE) + fail("Call with non-root parser is NOT supposed to succeed"); + + // XML_SetAllocTrackerActivationThreshold, success cases + if (XML_SetAllocTrackerActivationThreshold(parserWithoutParent, 123) + == XML_FALSE) + fail("Call with non-NULL parentless parser is supposed to succeed"); +#endif // XML_GE == 1 + + XML_ParserFree(parserWithParent); + XML_ParserFree(parserWithoutParent); +} +END_TEST + +START_TEST(test_mem_api_cycle) { + XML_Parser parser = XML_ParserCreate(NULL); + + void *ptr = XML_MemMalloc(parser, 10); + + assert_true(ptr != NULL); + memset(ptr, 'x', 10); // assert writability, with ASan in mind + + ptr = XML_MemRealloc(parser, ptr, 20); + + assert_true(ptr != NULL); + memset(ptr, 'y', 20); // assert writability, with ASan in mind + + XML_MemFree(parser, ptr); + + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_mem_api_unlimited) { + XML_Parser parser = XML_ParserCreate(NULL); + +#if XML_GE == 1 + assert_true(XML_SetAllocTrackerActivationThreshold(parser, 0) == XML_TRUE); +#endif + + void *ptr = XML_MemMalloc(parser, 1000); + + assert_true(ptr != NULL); + + ptr = XML_MemRealloc(parser, ptr, 2000); + + assert_true(ptr != NULL); + + XML_MemFree(parser, ptr); + + XML_ParserFree(parser); +} +END_TEST + void make_alloc_test_case(Suite *s) { TCase *tc_alloc = tcase_create("allocation tests"); @@ -2151,4 +2377,14 @@ tcase_add_test__ifdef_xml_dtd( tc_alloc, test_alloc_reset_after_external_entity_parser_create_fail); + + tcase_add_test__if_xml_ge(tc_alloc, test_alloc_tracker_size_recorded); + tcase_add_test__if_xml_ge(tc_alloc, test_alloc_tracker_pointer_alignment); + tcase_add_test__if_xml_ge(tc_alloc, test_alloc_tracker_maximum_amplification); + tcase_add_test__if_xml_ge(tc_alloc, test_alloc_tracker_threshold); + tcase_add_test__if_xml_ge(tc_alloc, test_alloc_tracker_getbuffer_unlimited); + tcase_add_test__if_xml_ge(tc_alloc, test_alloc_tracker_api); + + tcase_add_test(tc_alloc, test_mem_api_cycle); + tcase_add_test__if_xml_ge(tc_alloc, test_mem_api_unlimited); } diff -Nru expat-2.7.1/expat/tests/alloc_tests_cxx.cpp expat-2.8.2/expat/tests/alloc_tests_cxx.cpp --- expat-2.7.1/expat/tests/alloc_tests_cxx.cpp 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/alloc_tests_cxx.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -/* C++ compilation harness for the test suite. - __ __ _ - ___\ \/ /_ __ __ _| |_ - / _ \\ /| '_ \ / _` | __| - | __// \| |_) | (_| | |_ - \___/_/\_\ .__/ \__,_|\__| - |_| XML parser - - Copyright (c) 2023 Sebastian Pipping - Licensed under the MIT license: - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to permit - persons to whom the Software is furnished to do so, subject to the - following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "alloc_tests.c" diff -Nru expat-2.7.1/expat/tests/basic_tests.c expat-2.8.2/expat/tests/basic_tests.c --- expat-2.7.1/expat/tests/basic_tests.c 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/basic_tests.c 2026-06-25 14:07:00.000000000 +0000 @@ -10,7 +10,7 @@ Copyright (c) 2003 Greg Stein Copyright (c) 2005-2007 Steven Solie Copyright (c) 2005-2012 Karl Waclawek - Copyright (c) 2016-2025 Sebastian Pipping + Copyright (c) 2016-2026 Sebastian Pipping Copyright (c) 2017-2022 Rhodri James Copyright (c) 2017 Joe Orton Copyright (c) 2017 José Gutiérrez de la Concha @@ -19,7 +19,9 @@ Copyright (c) 2020 Tim Gates Copyright (c) 2021 Donghee Na Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow - Copyright (c) 2024-2025 Berkay Eren Ürün + Copyright (c) 2024-2026 Berkay Eren Ürün + Copyright (c) 2026 Francesco Bertolaccini + Copyright (c) 2026 Matthew Fernandez Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -46,18 +48,15 @@ # undef NDEBUG /* because test suite relies on assert(...) at the moment */ #endif +#include "expat_config.h" + #include +#include #include #include #include -#if ! defined(__cplusplus) -# include -#endif - -#include "expat_config.h" - #include "expat.h" #include "internal.h" #include "minicheck.h" @@ -204,6 +203,30 @@ END_TEST #undef COLLIDING_HASH_SALT +START_TEST(test_hash_salt_setter) { + const uint8_t entropy[16] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + XML_Parser parser = XML_ParserCreate(NULL); + + // NULL parser should be rejected + assert_true(XML_SetHashSalt16Bytes(NULL, entropy) == XML_FALSE); + + // NULL entropy should be rejected + assert_true(XML_SetHashSalt16Bytes(parser, NULL) == XML_FALSE); + + // Setting should be allowed more than once + assert_true(XML_SetHashSalt16Bytes(parser, entropy) == XML_TRUE); + assert_true(XML_SetHashSalt16Bytes(parser, entropy) == XML_TRUE); + + // But not after parsing has started + assert_true(XML_Parse(parser, "", 0, XML_FALSE /* isFinal */) + == XML_STATUS_OK); + assert_true(XML_SetHashSalt16Bytes(parser, entropy) == XML_FALSE); + + XML_ParserFree(parser); +} +END_TEST + /* Regression test for SF bug #491986. */ START_TEST(test_danish_latin1) { const char *text = "\n" @@ -412,13 +435,13 @@ if (first_chunk_bytes >= sizeof(text) - 1) fail("bad value of first_chunk_bytes"); - if (_XML_Parse_SINGLE_BYTES(g_parser, text, first_chunk_bytes, XML_FALSE) + if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)first_chunk_bytes, XML_FALSE) == XML_STATUS_ERROR) xml_failure(g_parser); else { enum XML_Status rc; rc = _XML_Parse_SINGLE_BYTES(g_parser, text + first_chunk_bytes, - sizeof(text) - first_chunk_bytes - 1, + (int)(sizeof(text) - first_chunk_bytes - 1), XML_TRUE); if (rc == XML_STATUS_ERROR) xml_failure(g_parser); @@ -2466,11 +2489,9 @@ {XCS("id"), XCS("one")}, {NULL, NULL}}; AttrInfo tag_info[] = {{XCS("c"), XCS("3")}, {NULL, NULL}}; - ElementInfo info[] = {{XCS("doc"), 3, XCS("id"), NULL}, - {XCS("tag"), 1, NULL, NULL}, - {NULL, 0, NULL, NULL}}; - info[0].attributes = doc_info; - info[1].attributes = tag_info; + ElementInfo info[] = {{XCS("doc"), 3, 0, XCS("id"), doc_info}, + {XCS("tag"), 1, 0, NULL, tag_info}, + {NULL, 0, 0, NULL, NULL}}; XML_Parser parser = XML_ParserCreate(NULL); assert_true(parser != NULL); @@ -2489,6 +2510,279 @@ } END_TEST +START_TEST(test_duplicate_cdata_attribute) { + /* + https://www.w3.org/TR/xml/#attdecls + + Test the following statement from the linked specification: + When more than one definition is provided for the same attribute of a given + element type, the first declaration is binding and later declarations are + ignored. + */ + + const char *text + = "\n" + "]>\n" + "\n"; + AttrInfo doc_info[] = {{XCS("attribute"), XCS("expected")}, {NULL, NULL}}; + ElementInfo info[] + = {{XCS("doc"), 0, 1, NULL, doc_info}, {NULL, 0, 0, NULL, NULL}}; + + XML_Parser parser = XML_ParserCreate(NULL); + assert_true(parser != NULL); + + ParserAndElementInfo parserAndElementInfos = { + parser, + info, + }; + + XML_SetStartElementHandler(parser, counting_start_element_handler); + XML_SetUserData(parser, &parserAndElementInfos); + + if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE) + != XML_STATUS_OK) + xml_failure(parser); + + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_duplicate_id_attribute_1) { + /* + https://www.w3.org/TR/xml/#attdecls + + Test the following statement from the linked specification: + When more than one definition is provided for the same attribute of a given + element type, the first declaration is binding and later declarations are + ignored. + */ + + const char *text + = "\n" + "]>\n" + "\n"; + AttrInfo doc_info[] = {{XCS("identifier"), XCS("expected")}, {NULL, NULL}}; + ElementInfo info[] + = {{XCS("doc"), 0, 1, NULL, doc_info}, {NULL, 0, 0, NULL, NULL}}; + + XML_Parser parser = XML_ParserCreate(NULL); + assert_true(parser != NULL); + + ParserAndElementInfo parserAndElementInfos = { + parser, + info, + }; + + XML_SetStartElementHandler(parser, counting_start_element_handler); + XML_SetUserData(parser, &parserAndElementInfos); + + if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE) + != XML_STATUS_OK) + xml_failure(parser); + + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_duplicate_id_attribute_2) { + /* + https://www.w3.org/TR/xml/#attdecls + + Test the following statement from the linked specification: + When more than one definition is provided for the same attribute of a given + element type, the first declaration is binding and later declarations are + ignored. + */ + + const char *text + = "\n" + "]>\n" + "\n"; + AttrInfo doc_info[] = {{NULL, NULL}}; + + ElementInfo info[] + = {{XCS("doc"), 0, 0, NULL, doc_info}, {NULL, 0, 0, NULL, NULL}}; + + XML_Parser parser = XML_ParserCreate(NULL); + assert_true(parser != NULL); + + ParserAndElementInfo parserAndElementInfos = { + parser, + info, + }; + + XML_SetStartElementHandler(parser, counting_start_element_handler); + XML_SetUserData(parser, &parserAndElementInfos); + + if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE) + != XML_STATUS_OK) + xml_failure(parser); + + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_duplicate_cdata_attribute_multiple_attlistdecl) { + /* + https://www.w3.org/TR/xml/#attdecls + + Test the following statement from the linked specification: + When more than one AttlistDecl is provided for a given element type, + the contents of all those provided are merged. + */ + const char *text = "\n" + " \n" + "]>\n" + "\n"; + AttrInfo doc_info[] = {{XCS("attribute"), XCS("expected")}, {NULL, NULL}}; + ElementInfo info[] + = {{XCS("doc"), 0, 1, NULL, doc_info}, {NULL, 0, 0, NULL, NULL}}; + + XML_Parser parser = XML_ParserCreate(NULL); + assert_true(parser != NULL); + + ParserAndElementInfo parserAndElementInfos = { + parser, + info, + }; + + XML_SetStartElementHandler(parser, counting_start_element_handler); + XML_SetUserData(parser, &parserAndElementInfos); + + if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE) + != XML_STATUS_OK) + xml_failure(parser); + + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_duplicate_cdata_attribute_multiple_attlistdecl_2) { + /* + https://www.w3.org/TR/xml/#attdecls + + Test the following statement from the linked specification: + When more than one AttlistDecl is provided for a given element type, + the contents of all those provided are merged. + */ + const char *text = "\n" + " \n" + " \n" + "]>\n" + "\n"; + AttrInfo doc_info[] = {{XCS("attribute"), XCS("expected_doc")}, {NULL, NULL}}; + AttrInfo tag_info[] = {{XCS("attribute"), XCS("expected_tag")}, {NULL, NULL}}; + ElementInfo info[] = {{XCS("doc"), 0, 1, NULL, doc_info}, + {XCS("tag"), 0, 1, NULL, tag_info}, + {NULL, 0, 0, NULL, NULL}}; + + XML_Parser parser = XML_ParserCreate(NULL); + assert_true(parser != NULL); + + ParserAndElementInfo parserAndElementInfos = { + parser, + info, + }; + + XML_SetStartElementHandler(parser, counting_start_element_handler); + XML_SetUserData(parser, &parserAndElementInfos); + + if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE) + != XML_STATUS_OK) + xml_failure(parser); + + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_duplicate_cdata_attribute_multiple_attlistdecl_3) { + /* + https://www.w3.org/TR/xml/#attdecls + + Test the following statement from the linked specification: + When more than one AttlistDecl is provided for a given element type, + the contents of all those provided are merged. + */ + const char *text + = "\n" + " \n" + " \n" + "]>\n" + "\n"; + AttrInfo doc_info[] = {{XCS("attribute"), XCS("expected_doc")}, + {XCS("second_attribute"), XCS("second_expected_doc")}, + {NULL, NULL}}; + AttrInfo tag_info[] = {{XCS("attribute"), XCS("expected_tag")}, {NULL, NULL}}; + ElementInfo info[] = {{XCS("doc"), 0, 2, NULL, doc_info}, + {XCS("tag"), 0, 1, NULL, tag_info}, + {NULL, 0, 0, NULL, NULL}}; + + XML_Parser parser = XML_ParserCreate(NULL); + assert_true(parser != NULL); + + ParserAndElementInfo parserAndElementInfos = { + parser, + info, + }; + + XML_SetStartElementHandler(parser, counting_start_element_handler); + XML_SetUserData(parser, &parserAndElementInfos); + + if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE) + != XML_STATUS_OK) + xml_failure(parser); + + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_duplicate_id_attribute_multiple_attlistdecl) { + /* + https://www.w3.org/TR/xml/#attdecls + + Test the following statement from the linked specification: + When more than one AttlistDecl is provided for a given element type, + the contents of all those provided are merged. + */ + const char *text = "\n" + " \n" + " \n" + "]>\n" + "\n"; + AttrInfo doc_info[] + = {{XCS("identifier"), XCS("doc_identity")}, {NULL, NULL}}; + AttrInfo tag_info[] + = {{XCS("identifier"), XCS("identifier_tag")}, {NULL, NULL}}; + ElementInfo info[] = {{XCS("doc"), 1, 0, XCS("identifier"), doc_info}, + {XCS("tag"), 0, 1, NULL, tag_info}, + {NULL, 0, 0, NULL, NULL}}; + + XML_Parser parser = XML_ParserCreate(NULL); + assert_true(parser != NULL); + + ParserAndElementInfo parserAndElementInfos = { + parser, + info, + }; + + XML_SetStartElementHandler(parser, counting_start_element_handler); + XML_SetUserData(parser, &parserAndElementInfos); + + if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE) + != XML_STATUS_OK) + xml_failure(parser); + + XML_ParserFree(parser); +} +END_TEST + /* Test reset works correctly in the middle of processing an internal * entity. Exercises some obscure code in XML_ParserReset(). */ @@ -3009,7 +3303,6 @@ /* Test odd corners of the XML_GetBuffer interface */ START_TEST(test_get_buffer_1) { const char *text = get_buffer_test_text; - void *buffer; long context_bytes; /* Attempt to allocate a negative length buffer */ @@ -3017,7 +3310,7 @@ fail("Negative length buffer not failed"); /* Now get a small buffer and extend it past valid length */ - buffer = XML_GetBuffer(g_parser, 1536); + void *const buffer = XML_GetBuffer(g_parser, 1536); if (buffer == NULL) fail("1.5K buffer failed"); assert(buffer != NULL); @@ -3052,10 +3345,9 @@ /* Test more corners of the XML_GetBuffer interface */ START_TEST(test_get_buffer_2) { const char *text = get_buffer_test_text; - void *buffer; /* Now get a decent buffer */ - buffer = XML_GetBuffer(g_parser, 1536); + void *const buffer = XML_GetBuffer(g_parser, 1536); if (buffer == NULL) fail("1.5K buffer failed"); assert(buffer != NULL); @@ -3112,17 +3404,25 @@ #if defined(__MINGW32__) && ! defined(__MINGW64__) // workaround for mingw/wine32 on GitHub CI not being able to reach 1GiB // Can we make a big allocation? - void *big = malloc(maxbuf); - if (! big) { + for (int i = 1; i <= 2; i++) { + void *const big = malloc(maxbuf); + if (big != NULL) { + free(big); + break; + } // The big allocation failed. Let's be a little lenient. maxbuf = maxbuf / 2; + fprintf(stderr, "Reducing maxbuf to %d...\n", maxbuf); } - free(big); #endif for (int i = 0; i < num_prefixes; ++i) { set_subtest("\"%s\"", prefixes[i]); XML_Parser parser = XML_ParserCreate(NULL); +#if XML_GE == 1 + assert_true(XML_SetAllocTrackerActivationThreshold(parser, (size_t)-1) + == XML_TRUE); // i.e. deactivate +#endif const int prefix_len = (int)strlen(prefixes[i]); const enum XML_Status s = _XML_Parse_SINGLE_BYTES(parser, prefixes[i], prefix_len, XML_FALSE); @@ -3402,8 +3702,7 @@ fail("Could not create external entity parser"); if (! xcstrcmp(systemId, XCS("004-2.ent"))) { - struct bom_testdata *const testdata - = (struct bom_testdata *)XML_GetUserData(parser); + struct bom_testdata *const testdata = XML_GetUserData(parser); const char *const external = testdata->external; const int split = testdata->split; testdata->nested_callback_happened = XML_TRUE; @@ -4083,6 +4382,37 @@ } END_TEST +START_TEST(test_scaff_index_shared_across_external_entity_parser) { + const char text[] + = "\n" + "\n" + "%e;\n" + "\n" + "]>\n" + ""; + ExtOption options[] + = {{XCS("ext"), + ""}, + {NULL, NULL}}; + + XML_Parser parser = XML_ParserCreate(NULL); + XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); + XML_SetUserData(parser, options); + XML_SetExternalEntityRefHandler(parser, external_entity_optioner); + XML_SetElementDeclHandler(parser, dummy_element_decl_handler); + + if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE) + == XML_STATUS_ERROR) + xml_failure(parser); + + XML_ParserFree(parser); +} +END_TEST + /* Test a different form of unknown external entity */ START_TEST(test_skipped_null_loaded_ext_entity) { const char *text = "\n" @@ -4566,6 +4896,46 @@ } END_TEST +START_TEST(test_unknown_encoding_user_data_primary) { + // This test is based on ideas contributed by Artiphishell Inc. + const char *const text = "\n" + "\n"; + XML_Parser parser = XML_ParserCreate(NULL); + XML_SetUnknownEncodingHandler(parser, + user_data_checking_unknown_encoding_handler, + (void *)(intptr_t)0xC0FFEE); + + assert_true(_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE) + == XML_STATUS_OK); + + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_unknown_encoding_user_data_secondary) { + // This test is based on ideas contributed by Artiphishell Inc. + const char *const text_main = "\n" + "]>\n" + "&ext;\n"; + const char *const text_external = "\n" + "data"; + ExtTest2 test_data = {text_external, (int)strlen(text_external), NULL, NULL}; + XML_Parser parser = XML_ParserCreate(NULL); + XML_SetExternalEntityRefHandler(parser, external_entity_loader2); + XML_SetUnknownEncodingHandler(parser, + user_data_checking_unknown_encoding_handler, + (void *)(intptr_t)0xC0FFEE); + XML_SetUserData(parser, &test_data); + + assert_true(_XML_Parse_SINGLE_BYTES(parser, text_main, (int)strlen(text_main), + XML_TRUE) + == XML_STATUS_OK); + + XML_ParserFree(parser); +} +END_TEST + /* Test an external entity parser set to use latin-1 detects UTF-16 * BOMs correctly. */ @@ -5428,7 +5798,7 @@ const size_t N_LINES = 60000; const size_t SIZE_PER_LINE = 50; - char *const text = (char *)malloc((N_LINES + 4) * SIZE_PER_LINE); + char *const text = malloc((N_LINES + 4) * SIZE_PER_LINE); if (text == NULL) { fail("malloc failed"); } @@ -5474,7 +5844,7 @@ const size_t N_LINES = 60000; const size_t SIZE_PER_LINE = 100; - char *const text = (char *)malloc((N_LINES + 4) * SIZE_PER_LINE); + char *const text = malloc((N_LINES + 4) * SIZE_PER_LINE); if (text == NULL) { fail("malloc failed"); } @@ -5495,8 +5865,8 @@ (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; + ElementInfo info[] + = {{XCS("foo"), 1, 0, NULL, doc_info}, {NULL, 0, 0, NULL, NULL}}; XML_Parser parser = XML_ParserCreate(NULL); ParserAndElementInfo parserPlusElemenInfo = {parser, info}; @@ -5517,7 +5887,7 @@ const size_t N_LINES = 70000; const size_t SIZE_PER_LINE = 100; - char *const text = (char *)malloc((N_LINES + 4) * SIZE_PER_LINE); + char *const text = malloc((N_LINES + 4) * SIZE_PER_LINE); if (text == NULL) { fail("malloc failed"); } @@ -5996,7 +6366,8 @@ } const int document_length = 65536; - char *const document = (char *)malloc(document_length); + char *const document = malloc(document_length); + assert_true(document != NULL); const XML_Memory_Handling_Suite memfuncs = { counting_malloc, @@ -6106,7 +6477,7 @@ return; // this test is slow, and doesn't use _XML_Parse_SINGLE_BYTES(). } - char *const document = (char *)malloc(document_length); + char *const document = malloc(document_length); assert_true(document != NULL); memset(document, 'x', document_length); document[0] = '<'; @@ -6209,6 +6580,24 @@ } END_TEST +START_TEST(test_empty_ext_param_entity_in_value) { + const char *text = ""; + ExtOption options[] = { + {XCS("ext.dtd"), "" + ""}, + {XCS("empty"), ""}, + {NULL, NULL}, + }; + + XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); + XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); + XML_SetUserData(g_parser, options); + if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) + == XML_STATUS_ERROR) + xml_failure(g_parser); +} +END_TEST + void make_basic_test_case(Suite *s) { TCase *tc_basic = tcase_create("basic tests"); @@ -6225,6 +6614,7 @@ tcase_add_test(tc_basic, test_bom_utf16_le); tcase_add_test(tc_basic, test_nobom_utf16_le); tcase_add_test(tc_basic, test_hash_collision); + tcase_add_test(tc_basic, test_hash_salt_setter); tcase_add_test(tc_basic, test_illegal_utf8); tcase_add_test(tc_basic, test_utf8_auto_align); tcase_add_test(tc_basic, test_utf16); @@ -6307,6 +6697,15 @@ tcase_add_test__ifdef_xml_dtd(tc_basic, test_empty_foreign_dtd); tcase_add_test(tc_basic, test_set_base); tcase_add_test(tc_basic, test_attributes); + tcase_add_test(tc_basic, test_duplicate_cdata_attribute); + tcase_add_test(tc_basic, test_duplicate_id_attribute_1); + tcase_add_test(tc_basic, test_duplicate_id_attribute_2); + tcase_add_test(tc_basic, test_duplicate_cdata_attribute_multiple_attlistdecl); + tcase_add_test(tc_basic, + test_duplicate_cdata_attribute_multiple_attlistdecl_2); + tcase_add_test(tc_basic, + test_duplicate_cdata_attribute_multiple_attlistdecl_3); + tcase_add_test(tc_basic, test_duplicate_id_attribute_multiple_attlistdecl); tcase_add_test__if_xml_ge(tc_basic, test_reset_in_entity); tcase_add_test(tc_basic, test_resume_invalid_parse); tcase_add_test(tc_basic, test_resume_resuspended); @@ -6381,6 +6780,8 @@ tcase_add_test(tc_basic, test_trailing_cr_in_att_value); tcase_add_test(tc_basic, test_standalone_internal_entity); tcase_add_test(tc_basic, test_skipped_external_entity); + tcase_add_test__ifdef_xml_dtd( + tc_basic, test_scaff_index_shared_across_external_entity_parser); tcase_add_test(tc_basic, test_skipped_null_loaded_ext_entity); tcase_add_test(tc_basic, test_skipped_unloaded_ext_entity); tcase_add_test__ifdef_xml_dtd(tc_basic, test_param_entity_with_trailing_cr); @@ -6412,6 +6813,8 @@ tcase_add_test(tc_basic, test_unknown_encoding_invalid_surrogate); tcase_add_test(tc_basic, test_unknown_encoding_invalid_high); tcase_add_test(tc_basic, test_unknown_encoding_invalid_attr_value); + tcase_add_test(tc_basic, test_unknown_encoding_user_data_primary); + tcase_add_test(tc_basic, test_unknown_encoding_user_data_secondary); tcase_add_test__if_xml_ge(tc_basic, test_ext_entity_latin1_utf16le_bom); tcase_add_test__if_xml_ge(tc_basic, test_ext_entity_latin1_utf16be_bom); tcase_add_test__if_xml_ge(tc_basic, test_ext_entity_latin1_utf16le_bom2); @@ -6454,6 +6857,7 @@ tcase_add_test(tc_basic, test_empty_element_abort); tcase_add_test__ifdef_xml_dtd(tc_basic, test_pool_integrity_with_unfinished_attr); + tcase_add_test__ifdef_xml_dtd(tc_basic, test_empty_ext_param_entity_in_value); 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); diff -Nru expat-2.7.1/expat/tests/basic_tests_cxx.cpp expat-2.8.2/expat/tests/basic_tests_cxx.cpp --- expat-2.7.1/expat/tests/basic_tests_cxx.cpp 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/basic_tests_cxx.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -/* C++ compilation harness for the test suite. - __ __ _ - ___\ \/ /_ __ __ _| |_ - / _ \\ /| '_ \ / _` | __| - | __// \| |_) | (_| | |_ - \___/_/\_\ .__/ \__,_|\__| - |_| XML parser - - Copyright (c) 2023 Sebastian Pipping - Licensed under the MIT license: - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to permit - persons to whom the Software is furnished to do so, subject to the - following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "basic_tests.c" diff -Nru expat-2.7.1/expat/tests/chardata.c expat-2.8.2/expat/tests/chardata.c --- expat-2.7.1/expat/tests/chardata.c 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/chardata.c 2026-06-25 14:07:00.000000000 +0000 @@ -47,15 +47,7 @@ #include #include "chardata.h" - -static int -xmlstrlen(const XML_Char *s) { - int len = 0; - assert(s != NULL); - while (s[len] != 0) - ++len; - return len; -} +#include "../lib/xcsinc.c" void CharData_Init(CharData *storage) { @@ -73,7 +65,7 @@ if (storage->count < 0) storage->count = 0; if (len < 0) - len = xmlstrlen(s); + len = (int)xcslen(s); if ((len + storage->count) > maxchars) { len = (maxchars - storage->count); } @@ -85,7 +77,7 @@ int CharData_CheckXMLChars(CharData *storage, const XML_Char *expected) { - int len = xmlstrlen(expected); + int len = (int)xcslen(expected); int count; assert(storage != NULL); diff -Nru expat-2.7.1/expat/tests/chardata_cxx.cpp expat-2.8.2/expat/tests/chardata_cxx.cpp --- expat-2.7.1/expat/tests/chardata_cxx.cpp 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/chardata_cxx.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -/* C++ compilation harness for the test suite. - __ __ _ - ___\ \/ /_ __ __ _| |_ - / _ \\ /| '_ \ / _` | __| - | __// \| |_) | (_| | |_ - \___/_/\_\ .__/ \__,_|\__| - |_| XML parser - - Copyright (c) 2023 Sebastian Pipping - Licensed under the MIT license: - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to permit - persons to whom the Software is furnished to do so, subject to the - following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "chardata.c" diff -Nru expat-2.7.1/expat/tests/common.c expat-2.8.2/expat/tests/common.c --- expat-2.7.1/expat/tests/common.c 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/common.c 2026-06-25 14:07:00.000000000 +0000 @@ -10,7 +10,7 @@ Copyright (c) 2003 Greg Stein Copyright (c) 2005-2007 Steven Solie Copyright (c) 2005-2012 Karl Waclawek - Copyright (c) 2016-2025 Sebastian Pipping + Copyright (c) 2016-2026 Sebastian Pipping Copyright (c) 2017-2022 Rhodri James Copyright (c) 2017 Joe Orton Copyright (c) 2017 José Gutiérrez de la Concha @@ -19,6 +19,7 @@ Copyright (c) 2020 Tim Gates Copyright (c) 2021 Donghee Na Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow + Copyright (c) 2026 Matthew Fernandez Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -41,13 +42,14 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include "expat_config.h" + #include #include #include // for SIZE_MAX #include #include -#include "expat_config.h" #include "expat.h" #include "internal.h" #include "chardata.h" @@ -261,7 +263,7 @@ void _run_ext_character_check(const char *text, ExtTest *test_data, const XML_Char *expected, const char *file, int line) { - CharData *const storage = (CharData *)malloc(sizeof(CharData)); + CharData *const storage = malloc(sizeof(CharData)); CharData_Init(storage); test_data->storage = storage; @@ -303,7 +305,14 @@ return realloc(ptr, size); } -// Portable remake of strndup(3) for C99; does not care about space efficiency +// Portable remake of strnlen(3) for C99 +static size_t +portable_strnlen(const char *s, size_t maxlen) { + const char *const end = (const char *)memchr(s, '\0', maxlen); + return (end == NULL) ? maxlen : (size_t)(end - s); +} + +// Portable remake of strndup(3) for C99 char * portable_strndup(const char *s, size_t n) { if ((s == NULL) || (n == SIZE_MAX)) { @@ -311,7 +320,9 @@ return NULL; } - char *const buffer = (char *)malloc(n + 1); + n = portable_strnlen(s, n); + + char *const buffer = malloc(n + 1); if (buffer == NULL) { errno = ENOMEM; return NULL; diff -Nru expat-2.7.1/expat/tests/common_cxx.cpp expat-2.8.2/expat/tests/common_cxx.cpp --- expat-2.7.1/expat/tests/common_cxx.cpp 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/common_cxx.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -/* C++ compilation harness for the test suite. - __ __ _ - ___\ \/ /_ __ __ _| |_ - / _ \\ /| '_ \ / _` | __| - | __// \| |_) | (_| | |_ - \___/_/\_\ .__/ \__,_|\__| - |_| XML parser - - Copyright (c) 2023 Sebastian Pipping - Licensed under the MIT license: - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to permit - persons to whom the Software is furnished to do so, subject to the - following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "common.c" diff -Nru expat-2.7.1/expat/tests/dummy_cxx.cpp expat-2.8.2/expat/tests/dummy_cxx.cpp --- expat-2.7.1/expat/tests/dummy_cxx.cpp 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/dummy_cxx.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -/* C++ compilation harness for the test suite. - __ __ _ - ___\ \/ /_ __ __ _| |_ - / _ \\ /| '_ \ / _` | __| - | __// \| |_) | (_| | |_ - \___/_/\_\ .__/ \__,_|\__| - |_| XML parser - - Copyright (c) 2023 Sebastian Pipping - Licensed under the MIT license: - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to permit - persons to whom the Software is furnished to do so, subject to the - following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "dummy.c" diff -Nru expat-2.7.1/expat/tests/handlers.c expat-2.8.2/expat/tests/handlers.c --- expat-2.7.1/expat/tests/handlers.c 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/handlers.c 2026-06-25 14:07:00.000000000 +0000 @@ -10,7 +10,7 @@ Copyright (c) 2003 Greg Stein Copyright (c) 2005-2007 Steven Solie Copyright (c) 2005-2012 Karl Waclawek - Copyright (c) 2016-2024 Sebastian Pipping + Copyright (c) 2016-2026 Sebastian Pipping Copyright (c) 2017-2022 Rhodri James Copyright (c) 2017 Joe Orton Copyright (c) 2017 José Gutiérrez de la Concha @@ -19,6 +19,9 @@ Copyright (c) 2020 Tim Gates Copyright (c) 2021 Donghee Na Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow + Copyright (c) 2026 Matthew Fernandez + Copyright (c) 2026 Berkay Eren Ürün + Copyright (c) 2026 Kartik Kenchi Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -45,12 +48,13 @@ # undef NDEBUG /* because test suite relies on assert(...) at the moment */ #endif +#include "expat_config.h" + +#include #include #include #include -#include "expat_config.h" - #include "expat.h" #include "internal.h" #include "chardata.h" @@ -89,15 +93,15 @@ const XML_Char **attr) { StructData *storage = (StructData *)userData; UNUSED_P(attr); - StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser), - XML_GetCurrentLineNumber(g_parser), STRUCT_START_TAG); + StructData_AddItem(storage, name, (int)XML_GetCurrentColumnNumber(g_parser), + (int)XML_GetCurrentLineNumber(g_parser), STRUCT_START_TAG); } void XMLCALL end_element_event_handler2(void *userData, const XML_Char *name) { StructData *storage = (StructData *)userData; - StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser), - XML_GetCurrentLineNumber(g_parser), STRUCT_END_TAG); + StructData_AddItem(storage, name, (int)XML_GetCurrentColumnNumber(g_parser), + (int)XML_GetCurrentLineNumber(g_parser), STRUCT_END_TAG); } void XMLCALL @@ -132,11 +136,11 @@ fail("ID not present"); return; } - if (id != -1 && xcstrcmp(atts[id], info->id_name)) { + if (id != -1 && xcstrcmp(atts[id], info->id_name) != 0) { fail("ID does not have the correct name"); return; } - for (i = 0; i < info->attr_count; i++) { + for (i = 0; i < info->attr_count + info->default_attr_count; i++) { attr = info->attributes; while (attr->name != NULL) { if (! xcstrcmp(atts[0], attr->name)) @@ -147,13 +151,16 @@ fail("Attribute not recognised"); return; } - if (xcstrcmp(atts[1], attr->value)) { + if (xcstrcmp(atts[1], attr->value) != 0) { fail("Attribute has wrong value"); return; } /* Remember, two entries in atts per attribute (see above) */ atts += 2; } + + // Self-test that the test case's list of expected attributes is complete + assert_true(atts[0] == NULL); } void XMLCALL @@ -407,13 +414,22 @@ return XML_STATUS_OK; } +int XMLCALL +user_data_checking_unknown_encoding_handler(void *userData, + const XML_Char *encoding, + XML_Encoding *info) { + const intptr_t number = (intptr_t)userData; + assert_true(number == 0xC0FFEE); + return long_encoding_handler(userData, encoding, info); +} + /* External Entity Handlers */ int XMLCALL external_entity_optioner(XML_Parser parser, const XML_Char *context, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId) { - ExtOption *options = (ExtOption *)XML_GetUserData(parser); + ExtOption *options = XML_GetUserData(parser); XML_Parser ext_parser; UNUSED_P(base); @@ -439,7 +455,7 @@ external_entity_loader(XML_Parser parser, const XML_Char *context, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId) { - ExtTest *test_data = (ExtTest *)XML_GetUserData(parser); + ExtTest *test_data = XML_GetUserData(parser); XML_Parser extparser; UNUSED_P(base); @@ -467,7 +483,7 @@ const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId) { XML_Parser ext_parser; - ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser); + ExtFaults *fault = XML_GetUserData(parser); UNUSED_P(base); UNUSED_P(systemId); @@ -640,7 +656,7 @@ const XML_Char *systemId, const XML_Char *publicId) { XML_Parser ext_parser; - ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser); + ExtFaults *fault = XML_GetUserData(parser); void *buffer; int parse_len = (int)strlen(fault->parse_text); @@ -971,7 +987,7 @@ == XML_STATUS_ERROR) xml_failure(ext_parser); } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) { - ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser); + ExtFaults *fault = XML_GetUserData(parser); enum XML_Status status; enum XML_Error error; @@ -1073,7 +1089,7 @@ external_entity_public(XML_Parser parser, const XML_Char *context, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId) { - const char *text1 = (const char *)XML_GetUserData(parser); + const char *text1 = XML_GetUserData(parser); const char *text2 = ""; const char *text = NULL; XML_Parser ext_parser; @@ -1110,7 +1126,7 @@ UNUSED_P(publicId); if (systemId == NULL || ! xcstrcmp(systemId, XCS("bar"))) return XML_STATUS_OK; - if (xcstrcmp(systemId, XCS("foo"))) + if (xcstrcmp(systemId, XCS("foo")) != 0) fail("Unexpected system ID"); ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); if (ext_parser == NULL) @@ -1129,7 +1145,7 @@ external_entity_oneshot_loader(XML_Parser parser, const XML_Char *context, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId) { - ExtHdlrData *test_data = (ExtHdlrData *)XML_GetUserData(parser); + ExtHdlrData *test_data = XML_GetUserData(parser); XML_Parser ext_parser; UNUSED_P(base); @@ -1154,7 +1170,7 @@ external_entity_loader2(XML_Parser parser, const XML_Char *context, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId) { - ExtTest2 *test_data = (ExtTest2 *)XML_GetUserData(parser); + ExtTest2 *test_data = XML_GetUserData(parser); XML_Parser extparser; UNUSED_P(base); @@ -1181,7 +1197,7 @@ external_entity_faulter2(XML_Parser parser, const XML_Char *context, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId) { - ExtFaults2 *test_data = (ExtFaults2 *)XML_GetUserData(parser); + ExtFaults2 *test_data = XML_GetUserData(parser); XML_Parser extparser; UNUSED_P(base); @@ -1276,7 +1292,7 @@ UNUSED_P(publicId); /* Try a few different allocation levels */ for (i = 0; i < max_alloc_count; i++) { - g_allocation_count = i; + g_allocation_count = (int)i; new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); if (new_parser != NULL) { XML_ParserFree(new_parser); @@ -1299,7 +1315,7 @@ external_entity_dbl_handler(XML_Parser parser, const XML_Char *context, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId) { - int *pcallno = (int *)XML_GetUserData(parser); + int *pcallno = XML_GetUserData(parser); int callno = *pcallno; const char *text; XML_Parser new_parser = NULL; @@ -1356,7 +1372,7 @@ external_entity_dbl_handler_2(XML_Parser parser, const XML_Char *context, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId) { - int *pcallno = (int *)XML_GetUserData(parser); + int *pcallno = XML_GetUserData(parser); int callno = *pcallno; const char *text; XML_Parser new_parser; @@ -1451,7 +1467,7 @@ external_entity_alloc(XML_Parser parser, const XML_Char *context, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId) { - const char *text = (const char *)XML_GetUserData(parser); + const char *text = XML_GetUserData(parser); XML_Parser ext_parser; int parse_res; @@ -1506,8 +1522,7 @@ UNUSED_P(base); UNUSED_P(publicId); - const struct AccountingTestCase *const testCase - = (const struct AccountingTestCase *)XML_GetUserData(parser); + const struct AccountingTestCase *const testCase = XML_GetUserData(parser); const char *externalText = NULL; if (xcstrcmp(systemId, XCS("first.ent")) == 0) { @@ -1552,15 +1567,16 @@ const XML_Char *default_value, int is_required) { AttTest *at = (AttTest *)userData; - if (xcstrcmp(element_name, at->element_name)) + if (xcstrcmp(element_name, at->element_name) != 0) fail("Unexpected element name in attribute declaration"); - if (xcstrcmp(attr_name, at->attr_name)) + if (xcstrcmp(attr_name, at->attr_name) != 0) fail("Unexpected attribute name in attribute declaration"); - if (xcstrcmp(attr_type, at->attr_type)) + if (xcstrcmp(attr_type, at->attr_type) != 0) fail("Unexpected attribute type in attribute declaration"); if ((default_value == NULL && at->default_value != NULL) || (default_value != NULL && at->default_value == NULL) - || (default_value != NULL && xcstrcmp(default_value, at->default_value))) + || (default_value != NULL + && xcstrcmp(default_value, at->default_value) != 0)) fail("Unexpected default value in attribute declaration"); if (is_required != at->is_required) fail("Requirement mismatch in attribute declaration"); @@ -1751,7 +1767,7 @@ * going to overflow an int. */ if (value_length != (int)xcstrlen(entity_value_to_match) - || xcstrncmp(value, entity_value_to_match, value_length)) { + || xcstrncmp(value, entity_value_to_match, value_length) != 0) { entity_match_flag = ENTITY_MATCH_FAIL; } else { entity_match_flag = ENTITY_MATCH_SUCCESS; @@ -1977,3 +1993,51 @@ accumulate_comment(parserPlusStorage->storage, data); XML_StopParser(parserPlusStorage->parser, XML_TRUE); } + +void XMLCALL +forbidden_calls_character_handler(void *userData, const XML_Char *s, int len) { + UNUSED_P(s); + UNUSED_P(len); + XML_Parser parser = userData; + + assert_true(parser != NULL); // self-test + + assert_true(XML_GetBuffer(parser, 123) == NULL); // i.e. rejected + + assert_true(XML_Parse(parser, "", 0, /*isFinal=*/XML_FALSE) + == XML_STATUS_ERROR); // i.e. rejected + + assert_true(XML_ParseBuffer(parser, 0, /*isFinal=*/XML_FALSE) + == XML_STATUS_ERROR); // i.e. rejected + + XML_ParserFree(parser); // rejected + + assert_true(XML_ParserReset(parser, /*encodingName=*/NULL) + == XML_FALSE); // i.e. rejected + + assert_true(XML_GetErrorCode(parser) == XML_ERROR_NONE); +} + +void XMLCALL +suspend_then_resume_character_handler(void *userData, const XML_Char *s, + int len) { + UNUSED_P(s); + UNUSED_P(len); + ResumeFromHandlerData *const data = (ResumeFromHandlerData *)userData; + + data->callCount++; + if (data->callCount > 1) { + // Reached only if the guard under test is missing: XML_ResumeParser would + // then have driven the parser re-entrantly and called us again. Bail out + // so the test fails by assertion below rather than recursing without bound. + return; + } + + // Put the parser into XML_SUSPENDED so that, without the guard, + // XML_ResumeParser would proceed into a re-entrant parse. + assert_true(XML_StopParser(data->parser, /*resumable=*/XML_TRUE) + == XML_STATUS_OK); + + // Resuming the parser from inside a handler must be rejected. + assert_true(XML_ResumeParser(data->parser) == XML_STATUS_ERROR); +} diff -Nru expat-2.7.1/expat/tests/handlers.h expat-2.8.2/expat/tests/handlers.h --- expat-2.7.1/expat/tests/handlers.h 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/handlers.h 2026-06-25 14:07:00.000000000 +0000 @@ -10,7 +10,7 @@ Copyright (c) 2003 Greg Stein Copyright (c) 2005-2007 Steven Solie Copyright (c) 2005-2012 Karl Waclawek - Copyright (c) 2016-2024 Sebastian Pipping + Copyright (c) 2016-2026 Sebastian Pipping Copyright (c) 2017-2022 Rhodri James Copyright (c) 2017 Joe Orton Copyright (c) 2017 José Gutiérrez de la Concha @@ -19,6 +19,8 @@ Copyright (c) 2020 Tim Gates Copyright (c) 2021 Donghee Na Copyright (c) 2023 Sony Corporation / Snild Dolkow + Copyright (c) 2026 Berkay Eren Ürün + Copyright (c) 2026 Kartik Kenchi Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -88,6 +90,7 @@ typedef struct elementInfo { const XML_Char *name; int attr_count; + int default_attr_count; const XML_Char *id_name; AttrInfo *attributes; } ElementInfo; @@ -159,6 +162,9 @@ const XML_Char *encoding, XML_Encoding *info); +extern int XMLCALL user_data_checking_unknown_encoding_handler( + void *userData, const XML_Char *encoding, XML_Encoding *info); + /* External Entity Handlers */ typedef struct ExtOption { @@ -608,6 +614,19 @@ extern void XMLCALL accumulate_and_suspend_comment_handler(void *userData, const XML_Char *data); +extern void XMLCALL forbidden_calls_character_handler(void *userData, + const XML_Char *s, + int len); + +typedef struct { + XML_Parser parser; + int callCount; +} ResumeFromHandlerData; + +extern void XMLCALL suspend_then_resume_character_handler(void *userData, + const XML_Char *s, + int len); + #endif /* XML_HANDLERS_H */ #ifdef __cplusplus diff -Nru expat-2.7.1/expat/tests/handlers_cxx.cpp expat-2.8.2/expat/tests/handlers_cxx.cpp --- expat-2.7.1/expat/tests/handlers_cxx.cpp 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/handlers_cxx.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -/* C++ compilation harness for the test suite. - __ __ _ - ___\ \/ /_ __ __ _| |_ - / _ \\ /| '_ \ / _` | __| - | __// \| |_) | (_| | |_ - \___/_/\_\ .__/ \__,_|\__| - |_| XML parser - - Copyright (c) 2023 Sebastian Pipping - Licensed under the MIT license: - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to permit - persons to whom the Software is furnished to do so, subject to the - following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "handlers.c" diff -Nru expat-2.7.1/expat/tests/memcheck.c expat-2.8.2/expat/tests/memcheck.c --- expat-2.7.1/expat/tests/memcheck.c 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/memcheck.c 2026-06-25 14:07:00.000000000 +0000 @@ -9,6 +9,7 @@ Copyright (c) 2017 Rhodri James Copyright (c) 2017-2023 Sebastian Pipping Copyright (c) 2022 Sean McBride + Copyright (c) 2026 Matthew Fernandez Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -55,8 +56,7 @@ /* Allocate some memory and keep track of it. */ void * tracking_malloc(size_t size) { - AllocationEntry *const entry - = (AllocationEntry *)malloc(sizeof(AllocationEntry)); + AllocationEntry *const entry = malloc(sizeof(AllocationEntry)); if (entry == NULL) { printf("Allocator failure\n"); @@ -142,7 +142,7 @@ entry = find_allocation(ptr); if (entry == NULL) { printf("Attempting to realloc unallocated memory at %p\n", ptr); - entry = (AllocationEntry *)malloc(sizeof(AllocationEntry)); + entry = malloc(sizeof(AllocationEntry)); if (entry == NULL) { printf("Reallocator failure\n"); return NULL; diff -Nru expat-2.7.1/expat/tests/memcheck_cxx.cpp expat-2.8.2/expat/tests/memcheck_cxx.cpp --- expat-2.7.1/expat/tests/memcheck_cxx.cpp 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/memcheck_cxx.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -/* C++ compilation harness for the test suite. - __ __ _ - ___\ \/ /_ __ __ _| |_ - / _ \\ /| '_ \ / _` | __| - | __// \| |_) | (_| | |_ - \___/_/\_\ .__/ \__,_|\__| - |_| XML parser - - Copyright (c) 2023 Sebastian Pipping - Licensed under the MIT license: - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to permit - persons to whom the Software is furnished to do so, subject to the - following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "memcheck.c" diff -Nru expat-2.7.1/expat/tests/minicheck.c expat-2.8.2/expat/tests/minicheck.c --- expat-2.7.1/expat/tests/minicheck.c 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/minicheck.c 2026-06-25 14:07:00.000000000 +0000 @@ -16,6 +16,7 @@ Copyright (c) 2018 Marco Maggi Copyright (c) 2019 David Loffredo Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow + Copyright (c) 2026 Matthew Fernandez Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -54,7 +55,7 @@ Suite * suite_create(const char *name) { - Suite *suite = (Suite *)calloc(1, sizeof(Suite)); + Suite *suite = calloc(1, sizeof(Suite)); if (suite != NULL) { suite->name = name; } @@ -63,7 +64,7 @@ TCase * tcase_create(const char *name) { - TCase *tc = (TCase *)calloc(1, sizeof(TCase)); + TCase *tc = calloc(1, sizeof(TCase)); if (tc != NULL) { tc->name = name; } @@ -94,8 +95,7 @@ if (tc->allocated == tc->ntests) { int nalloc = tc->allocated + 100; size_t new_size = sizeof(tcase_test_function) * nalloc; - tcase_test_function *const new_tests - = (tcase_test_function *)realloc(tc->tests, new_size); + tcase_test_function *const new_tests = realloc(tc->tests, new_size); assert(new_tests != NULL); tc->tests = new_tests; tc->allocated = nalloc; @@ -130,7 +130,7 @@ SRunner * srunner_create(Suite *suite) { - SRunner *const runner = (SRunner *)calloc(1, sizeof(SRunner)); + SRunner *const runner = calloc(1, sizeof(SRunner)); if (runner != NULL) { runner->suite = suite; } diff -Nru expat-2.7.1/expat/tests/minicheck.h expat-2.8.2/expat/tests/minicheck.h --- expat-2.7.1/expat/tests/minicheck.h 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/minicheck.h 2026-06-25 14:07:00.000000000 +0000 @@ -134,8 +134,7 @@ __attribute__((noreturn)) # endif # endif -void -_fail(const char *file, int line, const char *msg); +void _fail(const char *file, int line, const char *msg); Suite *suite_create(const char *name); TCase *tcase_create(const char *name); void suite_add_tcase(Suite *suite, TCase *tc); diff -Nru expat-2.7.1/expat/tests/minicheck_cxx.cpp expat-2.8.2/expat/tests/minicheck_cxx.cpp --- expat-2.7.1/expat/tests/minicheck_cxx.cpp 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/minicheck_cxx.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -/* C++ compilation harness for the test suite. - __ __ _ - ___\ \/ /_ __ __ _| |_ - / _ \\ /| '_ \ / _` | __| - | __// \| |_) | (_| | |_ - \___/_/\_\ .__/ \__,_|\__| - |_| XML parser - - Copyright (c) 2023 Sebastian Pipping - Licensed under the MIT license: - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to permit - persons to whom the Software is furnished to do so, subject to the - following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "minicheck.c" diff -Nru expat-2.7.1/expat/tests/misc_tests.c expat-2.8.2/expat/tests/misc_tests.c --- expat-2.7.1/expat/tests/misc_tests.c 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/misc_tests.c 2026-06-25 14:07:00.000000000 +0000 @@ -10,7 +10,7 @@ Copyright (c) 2003 Greg Stein Copyright (c) 2005-2007 Steven Solie Copyright (c) 2005-2012 Karl Waclawek - Copyright (c) 2016-2025 Sebastian Pipping + Copyright (c) 2016-2026 Sebastian Pipping Copyright (c) 2017-2022 Rhodri James Copyright (c) 2017 Joe Orton Copyright (c) 2017 José Gutiérrez de la Concha @@ -19,6 +19,9 @@ Copyright (c) 2020 Tim Gates Copyright (c) 2021 Donghee Na Copyright (c) 2023 Sony Corporation / Snild Dolkow + Copyright (c) 2025 Berkay Eren Ürün + Copyright (c) 2026 Matthew Fernandez + Copyright (c) 2026 Kartik Kenchi Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -45,11 +48,11 @@ # undef NDEBUG /* because test suite relies on assert(...) at the moment */ #endif +#include "expat_config.h" + #include #include -#include "expat_config.h" - #include "expat.h" #include "internal.h" #include "minicheck.h" @@ -70,7 +73,7 @@ /* Something this simple shouldn't need more than 10 allocations */ for (i = 0; i < max_alloc_count; i++) { - g_allocation_count = i; + g_allocation_count = (int)i; g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL); if (g_parser != NULL) break; @@ -90,7 +93,7 @@ /* Try several levels of allocation */ for (i = 0; i < max_alloc_count; i++) { - g_allocation_count = i; + g_allocation_count = (int)i; g_parser = XML_ParserCreate_MM(XCS("us-ascii"), &memsuite, NULL); if (g_parser != NULL) break; @@ -211,7 +214,8 @@ if (! versions_equal(&read_version, &parsed_version)) fail("Version mismatch"); - if (xcstrcmp(version_text, XCS("expat_2.7.1"))) /* needs bump on releases */ + if (xcstrcmp(version_text, XCS("expat_2.8.2")) + != 0) /* needs bump on releases */ fail("XML_*_VERSION in expat.h out of sync?\n"); } END_TEST @@ -296,7 +300,7 @@ parser = XML_ParserCreate(NULL); XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240); - mydata = (DataIssue240 *)malloc(sizeof(DataIssue240)); + mydata = malloc(sizeof(DataIssue240)); assert_true(mydata != NULL); mydata->parser = parser; mydata->deep = 0; @@ -318,7 +322,7 @@ parser = XML_ParserCreate(NULL); XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240); - mydata = (DataIssue240 *)malloc(sizeof(DataIssue240)); + mydata = malloc(sizeof(DataIssue240)); assert_true(mydata != NULL); mydata->parser = parser; mydata->deep = 0; @@ -678,6 +682,160 @@ } END_TEST +START_TEST(test_misc_sync_entity_tolerated) { + const char *const doc = "'>\n" + " two'>\n" + " threefourthree'>\n" + " &b;'>\n" + "]>\n" + "&a;&b;&c;&d;\n"; + XML_Parser parser = XML_ParserCreate(NULL); + + assert_true(_XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc), + /*isFinal=*/XML_TRUE) + == XML_STATUS_OK); + + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_misc_async_entity_rejected) { + struct test_case { + const char *doc; + enum XML_Status expectedStatusNoGE; + enum XML_Error expectedErrorNoGE; + XML_Size expectedErrorLine; + XML_Size expectedErrorColumn; + }; + const struct test_case cases[] = { + // Opened by one entity, closed by another + {"'>\n" + " '>\n" + "]>\n" + "&open;&close;\n", + XML_STATUS_OK, XML_ERROR_NONE, 5, 4}, + // Opened by tag, closed by entity (non-root case) + {"\n" + " '>\n" + "]>\n" + "&g1;\n", + XML_STATUS_ERROR, XML_ERROR_TAG_MISMATCH, 5, 8}, + // Opened by tag, closed by entity (root case) + {"\n" + " '>\n" + "]>\n" + "&g1;\n", + XML_STATUS_ERROR, XML_ERROR_NO_ELEMENTS, 5, 4}, + // Opened by entity, closed by tag <-- regression from 2.7.0 + {"\n" + " &g0;'>\n" + "]>\n" + "&g1;\n", + XML_STATUS_ERROR, XML_ERROR_TAG_MISMATCH, 5, 4}, + // Opened by tag, closed by entity; then the other way around + {"'>\n" + " '>\n" + "]>\n" + "&close;&open;\n", + XML_STATUS_OK, XML_ERROR_NONE, 5, 8}, + }; + + for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) { + const struct test_case testCase = cases[i]; + set_subtest("cases[%d]", (int)i); + + const char *const doc = testCase.doc; +#if XML_GE == 1 + const enum XML_Status expectedStatus = XML_STATUS_ERROR; + const enum XML_Error expectedError = XML_ERROR_ASYNC_ENTITY; +#else + const enum XML_Status expectedStatus = testCase.expectedStatusNoGE; + const enum XML_Error expectedError = testCase.expectedErrorNoGE; +#endif + + XML_Parser parser = XML_ParserCreate(NULL); + assert_true(_XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc), + /*isFinal=*/XML_TRUE) + == expectedStatus); + assert_true(XML_GetErrorCode(parser) == expectedError); +#if XML_GE == 1 + assert_true(XML_GetCurrentLineNumber(parser) == testCase.expectedErrorLine); + assert_true(XML_GetCurrentColumnNumber(parser) + == testCase.expectedErrorColumn); +#endif + XML_ParserFree(parser); + } +} +END_TEST + +START_TEST(test_misc_no_infinite_loop_issue_1161) { + XML_Parser parser = XML_ParserCreate(NULL); + + const char *text = ""; + + struct ExtOption options[] = { + {XCS("secondary.txt"), + ""}, + {XCS("tertiary.txt"), " - Licensed under the MIT license: - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to permit - persons to whom the Software is furnished to do so, subject to the - following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "misc_tests.c" diff -Nru expat-2.7.1/expat/tests/ns_tests_cxx.cpp expat-2.8.2/expat/tests/ns_tests_cxx.cpp --- expat-2.7.1/expat/tests/ns_tests_cxx.cpp 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/ns_tests_cxx.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -/* C++ compilation harness for the test suite. - __ __ _ - ___\ \/ /_ __ __ _| |_ - / _ \\ /| '_ \ / _` | __| - | __// \| |_) | (_| | |_ - \___/_/\_\ .__/ \__,_|\__| - |_| XML parser - - Copyright (c) 2023 Sebastian Pipping - Licensed under the MIT license: - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to permit - persons to whom the Software is furnished to do so, subject to the - following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "ns_tests.c" diff -Nru expat-2.7.1/expat/tests/nsalloc_tests.c expat-2.8.2/expat/tests/nsalloc_tests.c --- expat-2.7.1/expat/tests/nsalloc_tests.c 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/nsalloc_tests.c 2026-06-25 14:07:00.000000000 +0000 @@ -10,7 +10,7 @@ Copyright (c) 2003 Greg Stein Copyright (c) 2005-2007 Steven Solie Copyright (c) 2005-2012 Karl Waclawek - Copyright (c) 2016-2023 Sebastian Pipping + Copyright (c) 2016-2026 Sebastian Pipping Copyright (c) 2017-2022 Rhodri James Copyright (c) 2017 Joe Orton Copyright (c) 2017 José Gutiérrez de la Concha @@ -18,6 +18,7 @@ Copyright (c) 2019 David Loffredo Copyright (c) 2020 Tim Gates Copyright (c) 2021 Donghee Na + Copyright (c) 2026 Christian Ng Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -83,7 +84,7 @@ const unsigned int max_alloc_count = 30; for (i = 0; i < max_alloc_count; i++) { - g_allocation_count = i; + g_allocation_count = (int)i; /* Exercise more code paths with a default handler */ XML_SetDefaultHandler(g_parser, dummy_default_handler); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) @@ -454,10 +455,15 @@ nsalloc_teardown(); nsalloc_setup(); } +#if XML_GE == 1 + assert_true( + i == 0); // because expat_realloc relies on expat_malloc to some extent +#else if (i == 0) fail("Parsing worked despite failing reallocations"); else if (i == max_realloc_count) fail("Parsing failed at max reallocation count"); +#endif } END_TEST @@ -523,7 +529,7 @@ /* Now repeat with a longer URI and a duff reallocator */ for (i = 0; i < max_realloc_count; i++) { XML_ParserReset(g_parser, NULL); - g_reallocation_count = i; + g_reallocation_count = (int)i; if (_XML_Parse_SINGLE_BYTES(g_parser, second, (int)strlen(second), XML_TRUE) != XML_STATUS_ERROR) break; @@ -1500,6 +1506,34 @@ } END_TEST +/* Verify that retry after OOM in setContext() does not crash. + */ +START_TEST(test_nsalloc_set_context_zombie) { + const char *text = "Hello"; + unsigned int i; + const unsigned int max_alloc_count = 30; + + for (i = 0; i < max_alloc_count; i++) { + g_allocation_count = (int)i; + if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) + != XML_STATUS_ERROR) + break; + /* Retry on the same parser — must not crash */ + g_allocation_count = ALLOC_ALWAYS_SUCCEED; + const enum XML_Status status + = XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE); + (void)status; + + nsalloc_teardown(); + nsalloc_setup(); + } + if (i == 0) + fail("Parsing worked despite failing allocations"); + else if (i == max_alloc_count) + fail("Parsing failed even at maximum allocation count"); +} +END_TEST + void make_nsalloc_test_case(Suite *s) { TCase *tc_nsalloc = tcase_create("namespace allocation tests"); @@ -1534,4 +1568,5 @@ tcase_add_test__if_xml_ge(tc_nsalloc, test_nsalloc_long_default_in_ext); tcase_add_test(tc_nsalloc, test_nsalloc_long_systemid_in_ext); tcase_add_test(tc_nsalloc, test_nsalloc_prefixed_element); + tcase_add_test(tc_nsalloc, test_nsalloc_set_context_zombie); } diff -Nru expat-2.7.1/expat/tests/nsalloc_tests_cxx.cpp expat-2.8.2/expat/tests/nsalloc_tests_cxx.cpp --- expat-2.7.1/expat/tests/nsalloc_tests_cxx.cpp 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/nsalloc_tests_cxx.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -/* C++ compilation harness for the test suite. - __ __ _ - ___\ \/ /_ __ __ _| |_ - / _ \\ /| '_ \ / _` | __| - | __// \| |_) | (_| | |_ - \___/_/\_\ .__/ \__,_|\__| - |_| XML parser - - Copyright (c) 2023 Sebastian Pipping - Licensed under the MIT license: - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to permit - persons to whom the Software is furnished to do so, subject to the - following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "nsalloc_tests.c" diff -Nru expat-2.7.1/expat/tests/runtests_cxx.cpp expat-2.8.2/expat/tests/runtests_cxx.cpp --- expat-2.7.1/expat/tests/runtests_cxx.cpp 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/runtests_cxx.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -/* C++ compilation harness for the test suite. - - This is used to ensure the Expat headers can be included from C++ - and have everything work as expected. - __ __ _ - ___\ \/ /_ __ __ _| |_ - / _ \\ /| '_ \ / _` | __| - | __// \| |_) | (_| | |_ - \___/_/\_\ .__/ \__,_|\__| - |_| XML parser - - Copyright (c) 2005 Fred L. Drake, Jr. - Copyright (c) 2017-2023 Sebastian Pipping - Licensed under the MIT license: - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to permit - persons to whom the Software is furnished to do so, subject to the - following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "runtests.c" diff -Nru expat-2.7.1/expat/tests/structdata.c expat-2.8.2/expat/tests/structdata.c --- expat-2.7.1/expat/tests/structdata.c 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/structdata.c 2026-06-25 14:07:00.000000000 +0000 @@ -9,6 +9,7 @@ Copyright (c) 2017 Rhodri James Copyright (c) 2017-2023 Sebastian Pipping Copyright (c) 2022 Sean McBride + Copyright (c) 2026 Matthew Fernandez Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -61,7 +62,7 @@ static XML_Char * xmlstrdup(const XML_Char *s) { size_t byte_count = (xcstrlen(s) + 1) * sizeof(XML_Char); - XML_Char *const dup = (XML_Char *)malloc(byte_count); + XML_Char *const dup = malloc(byte_count); assert(dup != NULL); memcpy(dup, s, byte_count); @@ -87,8 +88,8 @@ StructDataEntry *new_entries; storage->max_count += STRUCT_EXTENSION_COUNT; - new_entries = (StructDataEntry *)realloc( - storage->entries, storage->max_count * sizeof(StructDataEntry)); + new_entries = realloc(storage->entries, + storage->max_count * sizeof(StructDataEntry)); assert(new_entries != NULL); storage->entries = new_entries; } diff -Nru expat-2.7.1/expat/tests/structdata_cxx.cpp expat-2.8.2/expat/tests/structdata_cxx.cpp --- expat-2.7.1/expat/tests/structdata_cxx.cpp 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/tests/structdata_cxx.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -/* C++ compilation harness for the test suite. - __ __ _ - ___\ \/ /_ __ __ _| |_ - / _ \\ /| '_ \ / _` | __| - | __// \| |_) | (_| | |_ - \___/_/\_\ .__/ \__,_|\__| - |_| XML parser - - Copyright (c) 2023 Sebastian Pipping - Licensed under the MIT license: - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to permit - persons to whom the Software is furnished to do so, subject to the - following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "structdata.c" diff -Nru expat-2.7.1/expat/win32/README.txt expat-2.8.2/expat/win32/README.txt --- expat-2.7.1/expat/win32/README.txt 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/win32/README.txt 2026-06-25 14:07:00.000000000 +0000 @@ -5,13 +5,13 @@ * Cygwin: This follows the Unix build procedures. -* MS Visual Studio 2019 and 2022: +* MS Visual Studio 2022: Use CMake to generate a solution file for Visual Studio, then use msbuild to compile. For example: md build cd build - cmake -G"Visual Studio 16 2019" -DCMAKE_BUILD_TYPE=RelWithDebInfo .. + cmake -G"Visual Studio 17 2022" -DCMAKE_BUILD_TYPE=RelWithDebInfo .. msbuild /m expat.sln * All MS C/C++ compilers: diff -Nru expat-2.7.1/expat/win32/build_expat_iss.bat expat-2.8.2/expat/win32/build_expat_iss.bat --- expat-2.7.1/expat/win32/build_expat_iss.bat 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/win32/build_expat_iss.bat 2026-06-25 14:07:00.000000000 +0000 @@ -1,84 +1,84 @@ -REM Batch script to build Inno Setup installer for libexpat for Windows -REM Call from parent directory, e.g.: cmd /c win32\build_expat_iss.bat -REM __ __ _ -REM ___\ \/ /_ __ __ _| |_ -REM / _ \\ /| '_ \ / _` | __| -REM | __// \| |_) | (_| | |_ -REM \___/_/\_\ .__/ \__,_|\__| -REM |_| XML parser -REM -REM Copyright (c) 2019-2024 Sebastian Pipping -REM Licensed under the MIT license: -REM -REM Permission is hereby granted, free of charge, to any person obtaining -REM a copy of this software and associated documentation files (the -REM "Software"), to deal in the Software without restriction, including -REM without limitation the rights to use, copy, modify, merge, publish, -REM distribute, sublicense, and/or sell copies of the Software, and to permit -REM persons to whom the Software is furnished to do so, subject to the -REM following conditions: -REM -REM The above copyright notice and this permission notice shall be included -REM in all copies or substantial portions of the Software. -REM -REM THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -REM EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -REM MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -REM NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -REM DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -REM OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -REM USE OR OTHER DEALINGS IN THE SOFTWARE. - -SET GENERATOR=Visual Studio 16 2019 - -REM Read by msbuild! -SET CONFIGURATION=RelWithDebInfo - -REM Where Inno Setup expects build results -SET BINDIR=win32\bin\Release - - -MD %BINDIR% || EXIT /b 1 - - -MD build_shared_char || EXIT /b 1 -CD build_shared_char || EXIT /b 1 - cmake -A Win32 -G"%GENERATOR%" -DCMAKE_BUILD_TYPE=%CONFIGURATION% -DEXPAT_WARNINGS_AS_ERRORS=ON -DEXPAT_MSVC_STATIC_CRT=ON -DEXPAT_BUILD_EXAMPLES=OFF -DEXPAT_BUILD_TESTS=OFF -DEXPAT_BUILD_TOOLS=OFF .. || EXIT /b 1 - msbuild /m expat.sln || EXIT /b 1 - DIR %CONFIGURATION% || EXIT /b 1 - CD .. || EXIT /b 1 -COPY build_shared_char\%CONFIGURATION%\libexpat.dll %BINDIR%\ || EXIT /b 1 -COPY build_shared_char\%CONFIGURATION%\libexpat.lib %BINDIR%\ || EXIT /b 1 - - -MD build_static_char || EXIT /b 1 -CD build_static_char || EXIT /b 1 - cmake -A Win32 -G"%GENERATOR%" -DCMAKE_BUILD_TYPE=%CONFIGURATION% -DEXPAT_WARNINGS_AS_ERRORS=ON -DEXPAT_MSVC_STATIC_CRT=ON -DEXPAT_BUILD_EXAMPLES=OFF -DEXPAT_BUILD_TESTS=OFF -DEXPAT_SHARED_LIBS=OFF .. || EXIT /b 1 - msbuild /m expat.sln || EXIT /b 1 - DIR %CONFIGURATION% || EXIT /b 1 - CD .. || EXIT /b 1 -COPY build_static_char\%CONFIGURATION%\libexpatMT.lib %BINDIR%\ || EXIT /b 1 -COPY build_static_char\xmlwf\%CONFIGURATION%\xmlwf.exe %BINDIR%\ || EXIT /b 1 - - -MD build_shared_wchar_t || EXIT /b 1 -CD build_shared_wchar_t || EXIT /b 1 - cmake -A Win32 -G"%GENERATOR%" -DCMAKE_BUILD_TYPE=%CONFIGURATION% -DEXPAT_WARNINGS_AS_ERRORS=ON -DEXPAT_MSVC_STATIC_CRT=ON -DEXPAT_BUILD_EXAMPLES=OFF -DEXPAT_BUILD_TESTS=OFF -DEXPAT_BUILD_TOOLS=OFF -DEXPAT_CHAR_TYPE=wchar_t .. || EXIT /b 1 - msbuild /m expat.sln || EXIT /b 1 - DIR %CONFIGURATION% || EXIT /b 1 - CD .. || EXIT /b 1 -COPY build_shared_wchar_t\%CONFIGURATION%\libexpatw.dll %BINDIR%\ || EXIT /b 1 -COPY build_shared_wchar_t\%CONFIGURATION%\libexpatw.lib %BINDIR%\ || EXIT /b 1 - - -MD build_static_wchar_t || EXIT /b 1 -CD build_static_wchar_t || EXIT /b 1 - cmake -A Win32 -G"%GENERATOR%" -DCMAKE_BUILD_TYPE=%CONFIGURATION% -DEXPAT_WARNINGS_AS_ERRORS=ON -DEXPAT_MSVC_STATIC_CRT=ON -DEXPAT_BUILD_EXAMPLES=OFF -DEXPAT_BUILD_TESTS=OFF -DEXPAT_BUILD_TOOLS=OFF -DEXPAT_SHARED_LIBS=OFF -DEXPAT_CHAR_TYPE=wchar_t .. || EXIT /b 1 - msbuild /m expat.sln || EXIT /b 1 - DIR %CONFIGURATION% || EXIT /b 1 - CD .. || EXIT /b 1 -COPY build_static_wchar_t\%CONFIGURATION%\libexpatwMT.lib %BINDIR%\ || EXIT /b 1 - - -DIR %BINDIR% || EXIT /b 1 -iscc win32\expat.iss || EXIT /b 1 +REM Batch script to build Inno Setup installer for libexpat for Windows +REM Call from parent directory, e.g.: cmd /c win32\build_expat_iss.bat +REM __ __ _ +REM ___\ \/ /_ __ __ _| |_ +REM / _ \\ /| '_ \ / _` | __| +REM | __// \| |_) | (_| | |_ +REM \___/_/\_\ .__/ \__,_|\__| +REM |_| XML parser +REM +REM Copyright (c) 2019-2025 Sebastian Pipping +REM Licensed under the MIT license: +REM +REM Permission is hereby granted, free of charge, to any person obtaining +REM a copy of this software and associated documentation files (the +REM "Software"), to deal in the Software without restriction, including +REM without limitation the rights to use, copy, modify, merge, publish, +REM distribute, sublicense, and/or sell copies of the Software, and to permit +REM persons to whom the Software is furnished to do so, subject to the +REM following conditions: +REM +REM The above copyright notice and this permission notice shall be included +REM in all copies or substantial portions of the Software. +REM +REM THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +REM EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +REM MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +REM NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +REM DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +REM OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +REM USE OR OTHER DEALINGS IN THE SOFTWARE. + +SET GENERATOR=Visual Studio 17 2022 + +REM Read by msbuild! +SET CONFIGURATION=RelWithDebInfo + +REM Where Inno Setup expects build results +SET BINDIR=win32\bin\Release + + +MD %BINDIR% || EXIT /b 1 + + +MD build_shared_char || EXIT /b 1 +CD build_shared_char || EXIT /b 1 + cmake -A Win32 -G"%GENERATOR%" -DCMAKE_BUILD_TYPE=%CONFIGURATION% -DEXPAT_WARNINGS_AS_ERRORS=ON -DEXPAT_MSVC_STATIC_CRT=ON -DEXPAT_BUILD_EXAMPLES=OFF -DEXPAT_BUILD_TESTS=OFF -DEXPAT_BUILD_TOOLS=OFF .. || EXIT /b 1 + msbuild /m expat.sln || EXIT /b 1 + DIR %CONFIGURATION% || EXIT /b 1 + CD .. || EXIT /b 1 +COPY build_shared_char\%CONFIGURATION%\libexpat.dll %BINDIR%\ || EXIT /b 1 +COPY build_shared_char\%CONFIGURATION%\libexpat.lib %BINDIR%\ || EXIT /b 1 + + +MD build_static_char || EXIT /b 1 +CD build_static_char || EXIT /b 1 + cmake -A Win32 -G"%GENERATOR%" -DCMAKE_BUILD_TYPE=%CONFIGURATION% -DEXPAT_WARNINGS_AS_ERRORS=ON -DEXPAT_MSVC_STATIC_CRT=ON -DEXPAT_BUILD_EXAMPLES=OFF -DEXPAT_BUILD_TESTS=OFF -DEXPAT_SHARED_LIBS=OFF .. || EXIT /b 1 + msbuild /m expat.sln || EXIT /b 1 + DIR %CONFIGURATION% || EXIT /b 1 + CD .. || EXIT /b 1 +COPY build_static_char\%CONFIGURATION%\libexpatMT.lib %BINDIR%\ || EXIT /b 1 +COPY build_static_char\xmlwf\%CONFIGURATION%\xmlwf.exe %BINDIR%\ || EXIT /b 1 + + +MD build_shared_wchar_t || EXIT /b 1 +CD build_shared_wchar_t || EXIT /b 1 + cmake -A Win32 -G"%GENERATOR%" -DCMAKE_BUILD_TYPE=%CONFIGURATION% -DEXPAT_WARNINGS_AS_ERRORS=ON -DEXPAT_MSVC_STATIC_CRT=ON -DEXPAT_BUILD_EXAMPLES=OFF -DEXPAT_BUILD_TESTS=OFF -DEXPAT_BUILD_TOOLS=OFF -DEXPAT_CHAR_TYPE=wchar_t .. || EXIT /b 1 + msbuild /m expat.sln || EXIT /b 1 + DIR %CONFIGURATION% || EXIT /b 1 + CD .. || EXIT /b 1 +COPY build_shared_wchar_t\%CONFIGURATION%\libexpatw.dll %BINDIR%\ || EXIT /b 1 +COPY build_shared_wchar_t\%CONFIGURATION%\libexpatw.lib %BINDIR%\ || EXIT /b 1 + + +MD build_static_wchar_t || EXIT /b 1 +CD build_static_wchar_t || EXIT /b 1 + cmake -A Win32 -G"%GENERATOR%" -DCMAKE_BUILD_TYPE=%CONFIGURATION% -DEXPAT_WARNINGS_AS_ERRORS=ON -DEXPAT_MSVC_STATIC_CRT=ON -DEXPAT_BUILD_EXAMPLES=OFF -DEXPAT_BUILD_TESTS=OFF -DEXPAT_BUILD_TOOLS=OFF -DEXPAT_SHARED_LIBS=OFF -DEXPAT_CHAR_TYPE=wchar_t .. || EXIT /b 1 + msbuild /m expat.sln || EXIT /b 1 + DIR %CONFIGURATION% || EXIT /b 1 + CD .. || EXIT /b 1 +COPY build_static_wchar_t\%CONFIGURATION%\libexpatwMT.lib %BINDIR%\ || EXIT /b 1 + + +DIR %BINDIR% || EXIT /b 1 +iscc win32\expat.iss || EXIT /b 1 diff -Nru expat-2.7.1/expat/win32/expat.iss expat-2.8.2/expat/win32/expat.iss --- expat-2.7.1/expat/win32/expat.iss 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/win32/expat.iss 2026-06-25 14:07:00.000000000 +0000 @@ -14,7 +14,7 @@ ; Copyright (c) 2001 Tim Peters ; Copyright (c) 2001-2005 Fred L. Drake, Jr. ; Copyright (c) 2006-2017 Karl Waclawek -; Copyright (c) 2007-2025 Sebastian Pipping +; Copyright (c) 2007-2026 Sebastian Pipping ; Copyright (c) 2022 Johnny Jazeix ; Copyright (c) 2024 Dag-Erling Smørgrav ; Licensed under the MIT license: @@ -38,7 +38,7 @@ ; OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE ; USE OR OTHER DEALINGS IN THE SOFTWARE. -#define expatVer "2.7.1" +#define expatVer "2.8.2" [Setup] AppName=Expat @@ -95,7 +95,6 @@ Flags: ignoreversion; Source: lib\*.def.cmake; DestDir: "{app}\Source\lib" Flags: ignoreversion; Source: examples\*.c; DestDir: "{app}\Source\examples" Flags: ignoreversion; Source: tests\*.c; DestDir: "{app}\Source\tests" -Flags: ignoreversion; Source: tests\*.cpp; DestDir: "{app}\Source\tests" Flags: ignoreversion; Source: tests\*.h; DestDir: "{app}\Source\tests" Flags: ignoreversion; Source: tests\README.md; DestDir: "{app}\Source\tests" Flags: ignoreversion; Source: tests\benchmark\*.c; DestDir: "{app}\Source\tests\benchmark" diff -Nru expat-2.7.1/expat/xmlwf/filemap.h expat-2.8.2/expat/xmlwf/filemap.h --- expat-2.7.1/expat/xmlwf/filemap.h 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/xmlwf/filemap.h 2026-06-25 14:07:00.000000000 +0000 @@ -10,6 +10,7 @@ Copyright (c) 2000 Clark Cooper Copyright (c) 2002 Fred L. Drake, Jr. Copyright (c) 2016-2017 Sebastian Pipping + Copyright (c) 2026 Matthew Fernandez Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -36,7 +37,7 @@ #include /* The following limit (for XML_Parse's int len) derives from - * this loop in xmparse.c: + * this loop in xmlparse.c: * * do { * bufferSize = (int) (2U * (unsigned) bufferSize); diff -Nru expat-2.7.1/expat/xmlwf/unixfilemap.c expat-2.8.2/expat/xmlwf/unixfilemap.c --- expat-2.7.1/expat/xmlwf/unixfilemap.c 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/xmlwf/unixfilemap.c 2026-06-25 14:07:00.000000000 +0000 @@ -10,8 +10,9 @@ Copyright (c) 2000 Clark Cooper Copyright (c) 2001-2002 Fred L. Drake, Jr. Copyright (c) 2006 Karl Waclawek - Copyright (c) 2016-2017 Sebastian Pipping + Copyright (c) 2016-2025 Sebastian Pipping Copyright (c) 2017 Rhodri James + Copyright (c) 2026 Matthew Fernandez Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -41,6 +42,7 @@ #include #include #include +#include // NULL #include #ifndef MAP_FILE @@ -93,15 +95,14 @@ close(fd); return 1; } - p = (void *)mmap((void *)0, (size_t)nbytes, PROT_READ, MAP_FILE | MAP_PRIVATE, - fd, (off_t)0); - if (p == (void *)-1) { + p = mmap(NULL, nbytes, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, (off_t)0); + if (p == MAP_FAILED) { tperror(name); close(fd); return 0; } processor(p, nbytes, name, arg); - munmap((void *)p, nbytes); + munmap(p, nbytes); close(fd); return 1; } diff -Nru expat-2.7.1/expat/xmlwf/win32filemap.c expat-2.8.2/expat/xmlwf/win32filemap.c --- expat-2.7.1/expat/xmlwf/win32filemap.c 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/xmlwf/win32filemap.c 2026-06-25 14:07:00.000000000 +0000 @@ -9,7 +9,7 @@ Copyright (c) 1997-2000 Thai Open Source Software Center Ltd Copyright (c) 2000 Clark Cooper Copyright (c) 2002 Fred L. Drake, Jr. - Copyright (c) 2016-2022 Sebastian Pipping + Copyright (c) 2016-2017 Sebastian Pipping Copyright (c) 2022 Martin Ettl Licensed under the MIT license: diff -Nru expat-2.7.1/expat/xmlwf/xmlfile.c expat-2.8.2/expat/xmlwf/xmlfile.c --- expat-2.7.1/expat/xmlwf/xmlfile.c 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/xmlwf/xmlfile.c 2026-06-25 14:07:00.000000000 +0000 @@ -11,11 +11,14 @@ Copyright (c) 2002-2003 Fred L. Drake, Jr. Copyright (c) 2004-2006 Karl Waclawek Copyright (c) 2005-2007 Steven Solie - Copyright (c) 2016-2023 Sebastian Pipping + Copyright (c) 2016-2025 Sebastian Pipping Copyright (c) 2017 Rhodri James Copyright (c) 2019 David Loffredo Copyright (c) 2021 Donghee Na Copyright (c) 2024 Hanno Böck + Copyright (c) 2025 Alfonso Gregory + Copyright (c) 2026 Matthew Fernandez + Copyright (c) 2026 Kartik Kenchi Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -56,12 +59,19 @@ #include "xmltchar.h" #include "filemap.h" +/* Function "read": */ #if defined(_MSC_VER) # include -#endif - -#ifdef HAVE_UNISTD_H +/* https://msdn.microsoft.com/en-us/library/wyssk1bs(v=vs.100).aspx */ +# define EXPAT_read _read +# define EXPAT_read_count_t int +# define EXPAT_read_req_t unsigned int +#else /* POSIX */ # include +/* https://pubs.opengroup.org/onlinepubs/009695399/functions/read.html */ +# define EXPAT_read read +# define EXPAT_read_count_t ssize_t +# define EXPAT_read_req_t size_t #endif #ifndef O_BINARY @@ -89,8 +99,8 @@ ftprintf(stdout, T("%s") T(":%") T(XML_FMT_INT_MOD) T("u") T(":%") T(XML_FMT_INT_MOD) T("u") T(": %s\n"), - filename, XML_GetErrorLineNumber(parser), - XML_GetErrorColumnNumber(parser), message); + filename, XML_GetCurrentLineNumber(parser), + XML_GetCurrentColumnNumber(parser), message); else ftprintf(stderr, T("%s: (unknown message %u)\n"), filename, (unsigned int)code); @@ -130,8 +140,22 @@ #endif ) return systemId; - *toFree = (XML_Char *)malloc((tcslen(base) + tcslen(systemId) + 2) - * sizeof(XML_Char)); + + const size_t baseLen = tcslen(base); + const size_t systemIdLen = tcslen(systemId); + + /* Detect and prevent integer overflow in the addition (without risking + underflow) */ + if (baseLen > SIZE_MAX - systemIdLen || baseLen > SIZE_MAX - systemIdLen - 2) + return systemId; + + const size_t charsRequired = baseLen + systemIdLen + 2; + + /* Detect and prevent integer overflow in the multiplication */ + if (charsRequired > SIZE_MAX / sizeof(XML_Char)) + return systemId; + + *toFree = malloc(charsRequired * sizeof(XML_Char)); if (! *toFree) return systemId; tcscpy(*toFree, base); @@ -192,7 +216,7 @@ } } for (;;) { - int nread; + EXPAT_read_count_t nread; char *buf = (char *)XML_GetBuffer(parser, g_read_size_bytes); if (! buf) { if (filename != NULL) @@ -201,14 +225,14 @@ filename != NULL ? filename : T("xmlwf")); return 0; } - nread = read(fd, buf, g_read_size_bytes); + nread = EXPAT_read(fd, buf, (EXPAT_read_req_t)g_read_size_bytes); if (nread < 0) { tperror(filename != NULL ? filename : T("STDIN")); if (filename != NULL) close(fd); return 0; } - if (XML_ParseBuffer(parser, nread, nread == 0) == XML_STATUS_ERROR) { + if (XML_ParseBuffer(parser, (int)nread, nread == 0) == XML_STATUS_ERROR) { reportError(parser, filename != NULL ? filename : T("STDIN")); if (filename != NULL) close(fd); @@ -218,7 +242,6 @@ if (filename != NULL) close(fd); break; - ; } } return 1; diff -Nru expat-2.7.1/expat/xmlwf/xmlwf.c expat-2.8.2/expat/xmlwf/xmlwf.c --- expat-2.7.1/expat/xmlwf/xmlwf.c 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/xmlwf/xmlwf.c 2026-06-25 14:07:00.000000000 +0000 @@ -11,7 +11,7 @@ Copyright (c) 2001-2003 Fred L. Drake, Jr. Copyright (c) 2004-2009 Karl Waclawek Copyright (c) 2005-2007 Steven Solie - Copyright (c) 2016-2023 Sebastian Pipping + Copyright (c) 2016-2026 Sebastian Pipping Copyright (c) 2017 Rhodri James Copyright (c) 2019 David Loffredo Copyright (c) 2020 Joe Orton @@ -19,6 +19,10 @@ Copyright (c) 2021 Tim Bray Copyright (c) 2022 Martin Ettl Copyright (c) 2022 Sean McBride + Copyright (c) 2025 Alfonso Gregory + Copyright (c) 2026 Matthew Fernandez + Copyright (c) 2026 Nick Begg + Copyright (c) 2026 Kartik Kenchi Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -54,6 +58,7 @@ #include "expat.h" #include "codepage.h" #include "internal.h" /* for UNUSED_P only */ +#include "fallthrough.h" #include "xmlfile.h" #include "xmltchar.h" @@ -65,6 +70,8 @@ # include #endif +#include "../lib/xcsinc.c" + enum ExitCode { XMLWF_EXIT_SUCCESS = 0, XMLWF_EXIT_INTERNAL_ERROR = 1, @@ -195,7 +202,7 @@ ++p; nAtts = (int)((p - atts) >> 1); if (nAtts > 1) - qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, attcmp); + qsort(atts, nAtts, sizeof(XML_Char *) * 2, attcmp); while (*atts) { puttc(T(' '), fp); fputts(*atts++, fp); @@ -251,7 +258,7 @@ ++p; nAtts = (int)((p - atts) >> 1); if (nAtts > 1) - qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, nsattcmp); + qsort(atts, nAtts, sizeof(XML_Char *) * 2, nsattcmp); while (*atts) { name = *atts++; sep = tcsrchr(name, NSSEP); @@ -303,16 +310,14 @@ static XML_Char * xcsdup(const XML_Char *s) { - XML_Char *result; - int count = 0; - int numBytes; - - /* Get the length of the string, including terminator */ - while (s[count++] != 0) { - /* Do nothing */ - } - numBytes = count * sizeof(XML_Char); - result = malloc(numBytes); + const size_t count = xcslen(s) + /* null terminator */ 1; + + // Detect and prevent integer overflow + if (count > SIZE_MAX / sizeof(XML_Char)) + return NULL; + + const size_t numBytes = count * sizeof(XML_Char); + XML_Char *const result = malloc(numBytes); if (result == NULL) return NULL; memcpy(result, s, numBytes); @@ -323,7 +328,7 @@ startDoctypeDecl(void *userData, const XML_Char *doctypeName, const XML_Char *sysid, const XML_Char *publid, int has_internal_subset) { - XmlwfUserData *data = (XmlwfUserData *)userData; + XmlwfUserData *data = userData; UNUSED_P(sysid); UNUSED_P(publid); UNUSED_P(has_internal_subset); @@ -377,29 +382,45 @@ return xcscmp(n1->notationName, n2->notationName); } +/* Write a SystemLiteral/PubidLiteral, choosing a delimiter that does not + occur in the value. The grammar forbids a literal from containing its + own delimiter, so a value reported by Expat never holds both quote + characters and a safe delimiter always exists. */ +static void +writeLiteral(FILE *fp, const XML_Char *value) { + const XML_Char quote = (tcschr(value, T('\'')) != NULL) ? T('"') : T('\''); + puttc(quote, fp); + fputts(value, fp); + puttc(quote, fp); +} + static void XMLCALL endDoctypeDecl(void *userData) { - XmlwfUserData *data = (XmlwfUserData *)userData; + XmlwfUserData *data = userData; NotationList **notations; - int notationCount = 0; + size_t notationCount = 0; NotationList *p; - int i; + size_t i; /* How many notations do we have? */ for (p = data->notationListHead; p != NULL; p = p->next) notationCount++; if (notationCount == 0) { /* Nothing to report */ - free((void *)data->currentDoctypeName); - data->currentDoctypeName = NULL; - return; + goto cleanUp; + } + + /* Detect and prevent integer overflow in the multiplication, mirroring + the guards in xcsdup() and resolveSystemId() */ + if (notationCount > SIZE_MAX / sizeof(NotationList *)) { + fprintf(stderr, "Unable to sort notations"); + goto cleanUp; } notations = malloc(notationCount * sizeof(NotationList *)); if (notations == NULL) { fprintf(stderr, "Unable to sort notations"); - freeNotations(data); - return; + goto cleanUp; } for (p = data->notationListHead, i = 0; i < notationCount; p = p->next, i++) { @@ -417,19 +438,15 @@ fputts(T("fp); fputts(notations[i]->notationName, data->fp); if (notations[i]->publicId != NULL) { - fputts(T(" PUBLIC '"), data->fp); - fputts(notations[i]->publicId, data->fp); - puttc(T('\''), data->fp); + fputts(T(" PUBLIC "), data->fp); + writeLiteral(data->fp, notations[i]->publicId); if (notations[i]->systemId != NULL) { puttc(T(' '), data->fp); - puttc(T('\''), data->fp); - fputts(notations[i]->systemId, data->fp); - puttc(T('\''), data->fp); + writeLiteral(data->fp, notations[i]->systemId); } } else if (notations[i]->systemId != NULL) { - fputts(T(" SYSTEM '"), data->fp); - fputts(notations[i]->systemId, data->fp); - puttc(T('\''), data->fp); + fputts(T(" SYSTEM "), data->fp); + writeLiteral(data->fp, notations[i]->systemId); } puttc(T('>'), data->fp); puttc(T('\n'), data->fp); @@ -439,6 +456,8 @@ fputts(T("]>\n"), data->fp); free(notations); + +cleanUp: freeNotations(data); free((void *)data->currentDoctypeName); data->currentDoctypeName = NULL; @@ -447,7 +466,7 @@ static void XMLCALL notationDecl(void *userData, const XML_Char *notationName, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId) { - XmlwfUserData *data = (XmlwfUserData *)userData; + XmlwfUserData *data = userData; NotationList *entry = malloc(sizeof(NotationList)); const char *errorMessage = "Unable to store NOTATION for output\n"; @@ -496,7 +515,7 @@ defaultCharacterData(void *userData, const XML_Char *s, int len) { UNUSED_P(s); UNUSED_P(len); - XML_DefaultCurrent((XML_Parser)userData); + XML_DefaultCurrent(userData); } static void XMLCALL @@ -504,13 +523,13 @@ const XML_Char **atts) { UNUSED_P(name); UNUSED_P(atts); - XML_DefaultCurrent((XML_Parser)userData); + XML_DefaultCurrent(userData); } static void XMLCALL defaultEndElement(void *userData, const XML_Char *name) { UNUSED_P(name); - XML_DefaultCurrent((XML_Parser)userData); + XML_DefaultCurrent(userData); } static void XMLCALL @@ -518,7 +537,7 @@ const XML_Char *data) { UNUSED_P(target); UNUSED_P(data); - XML_DefaultCurrent((XML_Parser)userData); + XML_DefaultCurrent(userData); } static void XMLCALL @@ -551,7 +570,7 @@ static void XMLCALL markup(void *userData, const XML_Char *s, int len) { - FILE *fp = ((XmlwfUserData *)XML_GetUserData((XML_Parser)userData))->fp; + FILE *fp = ((XmlwfUserData *)XML_GetUserData(userData))->fp; for (; len > 0; --len, ++s) puttc(*s, fp); } @@ -560,8 +579,11 @@ metaLocation(XML_Parser parser) { const XML_Char *uri = XML_GetBase(parser); FILE *fp = ((XmlwfUserData *)XML_GetUserData(parser))->fp; - if (uri) - ftprintf(fp, T(" uri=\"%s\""), uri); + if (uri) { + fputts(T(" uri=\""), fp); + characterData(XML_GetUserData(parser), uri, (int)tcslen(uri)); + puttc(T('"'), fp); + } ftprintf(fp, T(" byte=\"%") T(XML_FMT_INT_MOD) T("d\"") T(" nbytes=\"%d\"") T(" line=\"%") T(XML_FMT_INT_MOD) T("u\"") T(" col=\"%") @@ -573,20 +595,18 @@ static void metaStartDocument(void *userData) { - fputts(T("\n"), - ((XmlwfUserData *)XML_GetUserData((XML_Parser)userData))->fp); + fputts(T("\n"), ((XmlwfUserData *)XML_GetUserData(userData))->fp); } static void metaEndDocument(void *userData) { - fputts(T("\n"), - ((XmlwfUserData *)XML_GetUserData((XML_Parser)userData))->fp); + fputts(T("\n"), ((XmlwfUserData *)XML_GetUserData(userData))->fp); } static void XMLCALL metaStartElement(void *userData, const XML_Char *name, const XML_Char **atts) { - XML_Parser parser = (XML_Parser)userData; - XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser); + XML_Parser parser = userData; + XmlwfUserData *data = XML_GetUserData(parser); FILE *fp = data->fp; const XML_Char **specifiedAttsEnd = atts + XML_GetSpecifiedAttributeCount(parser); @@ -597,12 +617,16 @@ else idAttPtr = atts + idAttIndex; - ftprintf(fp, T("\n"), fp); do { - ftprintf(fp, T("= specifiedAttsEnd) fputts(T("\" defaulted=\"yes\"/>\n"), fp); @@ -618,10 +642,12 @@ static void XMLCALL metaEndElement(void *userData, const XML_Char *name) { - XML_Parser parser = (XML_Parser)userData; - XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser); + XML_Parser parser = userData; + XmlwfUserData *data = XML_GetUserData(parser); FILE *fp = data->fp; - ftprintf(fp, T("\n"), fp); } @@ -629,8 +655,8 @@ static void XMLCALL metaProcessingInstruction(void *userData, const XML_Char *target, const XML_Char *data) { - XML_Parser parser = (XML_Parser)userData; - XmlwfUserData *usrData = (XmlwfUserData *)XML_GetUserData(parser); + XML_Parser parser = userData; + XmlwfUserData *usrData = XML_GetUserData(parser); FILE *fp = usrData->fp; ftprintf(fp, T("fp; fputts(T("fp; fputts(T("fp; fputts(T("fp; fputts(T("fp; UNUSED_P(sysid); UNUSED_P(pubid); @@ -700,8 +726,8 @@ static void XMLCALL metaEndDoctypeDecl(void *userData) { - XML_Parser parser = (XML_Parser)userData; - XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser); + XML_Parser parser = userData; + XmlwfUserData *data = XML_GetUserData(parser); FILE *fp = data->fp; fputts(T("fp; UNUSED_P(base); ftprintf(fp, T("fp; UNUSED_P(is_param); @@ -770,8 +796,8 @@ static void XMLCALL metaStartNamespaceDecl(void *userData, const XML_Char *prefix, const XML_Char *uri) { - XML_Parser parser = (XML_Parser)userData; - XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser); + XML_Parser parser = userData; + XmlwfUserData *data = XML_GetUserData(parser); FILE *fp = data->fp; fputts(T("fp; if (! prefix) fputts(T("\n"), fp); @@ -900,6 +926,7 @@ T(" -n enable [n]amespace processing\n") T(" -p enable processing of external DTDs and [p]arameter entities\n") T(" -x enable processing of e[x]ternal entities\n") + T(" (CAREFUL! This makes xmlwf vulnerable to external entity attacks (XXE).)\n") T(" -e ENCODING override any in-document [e]ncoding declaration\n") T(" -w enable support for [W]indows code pages\n") T(" -r disable memory-mapping and use [r]ead calls instead\n") @@ -913,11 +940,11 @@ T(" -t write no XML output for [t]iming of plain parsing\n") T(" -N enable adding doctype and [n]otation declarations\n") T("\n") - T("billion laughs attack protection:\n") + T("amplification attack protection (e.g. billion laughs):\n") T(" NOTE: If you ever need to increase these values for non-attack payload, please file a bug report.\n") T("\n") T(" -a FACTOR set maximum tolerated [a]mplification factor (default: 100.0)\n") - T(" -b BYTES set number of output [b]ytes needed to activate (default: 8 MiB)\n") + T(" -b BYTES set number of output [b]ytes needed to activate (default: 8 MiB/64 MiB)\n") T("\n") T("reparse deferral:\n") T(" -q disable reparse deferral, and allow [q]uadratic parse runtime with large tokens\n") @@ -926,6 +953,16 @@ T(" -h, --help show this [h]elp message and exit\n") T(" -v, --version show program's [v]ersion number and exit\n") T("\n") + T("environment variables:\n") + T(" EXPAT_ACCOUNTING_DEBUG=(0|1|2|3)\n") + T(" Control verbosity of accounting debugging (default: 0)\n") + T(" EXPAT_ENTITY_DEBUG=(0|1|2)\n") + T(" Control verbosity of entity debugging (default: 0)\n") + T(" EXPAT_ENTROPY_DEBUG=(0|1)\n") + T(" Control verbosity of entropy debugging (default: 0)\n") + T(" EXPAT_MALLOC_DEBUG=(0|1|2)\n") + T(" Control verbosity of allocation tracker (default: 0)\n") + T("\n") T("exit status:\n") T(" 0 the input files are well-formed and the output (if requested) was written successfully\n") T(" 1 could not allocate data structures, signals a serious problem with execution environment\n") @@ -1024,7 +1061,7 @@ break; case T('p'): paramEntityParsing = XML_PARAM_ENTITY_PARSING_ALWAYS; - /* fall through */ + EXPAT_FALLTHROUGH; case T('x'): processFlags |= XML_EXTERNAL_ENTITIES; j++; @@ -1142,7 +1179,7 @@ j = 0; break; } - /* fall through */ + EXPAT_FALLTHROUGH; default: usage(argv[0], XMLWF_EXIT_USAGE_ERROR); // usage called exit(..), never gets here @@ -1171,12 +1208,15 @@ #if XML_GE == 1 XML_SetBillionLaughsAttackProtectionMaximumAmplification( parser, attackMaximumAmplification); + XML_SetAllocTrackerMaximumAmplification(parser, + attackMaximumAmplification); #endif } if (attackThresholdGiven) { #if XML_GE == 1 XML_SetBillionLaughsAttackProtectionActivationThreshold( parser, attackThresholdBytes); + XML_SetAllocTrackerActivationThreshold(parser, attackThresholdBytes); #else (void)attackThresholdBytes; // silence -Wunused-but-set-variable #endif @@ -1221,8 +1261,26 @@ } #endif } - outName = (XML_Char *)malloc((tcslen(outputDir) + tcslen(file) + 2) - * sizeof(XML_Char)); + const size_t outputDirLen = tcslen(outputDir); + const size_t fileLen = tcslen(file); + + /* Detect and prevent integer overflow in the addition (without + risking underflow) and the multiplication, mirroring the guards + in xcsdup() and resolveSystemId() */ + if (outputDirLen > SIZE_MAX - fileLen + || outputDirLen > SIZE_MAX - fileLen - 2) { + tperror(T("Could not allocate memory")); + exit(XMLWF_EXIT_INTERNAL_ERROR); + } + + const size_t charsRequired = outputDirLen + fileLen + 2; + + if (charsRequired > SIZE_MAX / sizeof(XML_Char)) { + tperror(T("Could not allocate memory")); + exit(XMLWF_EXIT_INTERNAL_ERROR); + } + + outName = malloc(charsRequired * sizeof(XML_Char)); if (! outName) { tperror(T("Could not allocate memory")); exit(XMLWF_EXIT_INTERNAL_ERROR); diff -Nru expat-2.7.1/expat/xmlwf/xmlwf_helpgen.py expat-2.8.2/expat/xmlwf/xmlwf_helpgen.py --- expat-2.7.1/expat/xmlwf/xmlwf_helpgen.py 2025-03-27 18:40:10.000000000 +0000 +++ expat-2.8.2/expat/xmlwf/xmlwf_helpgen.py 2026-06-25 14:07:00.000000000 +0000 @@ -6,7 +6,7 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2019-2023 Sebastian Pipping +# Copyright (c) 2019-2026 Sebastian Pipping # Copyright (c) 2021 Tim Bray # Licensed under the MIT license: # @@ -30,18 +30,31 @@ # USE OR OTHER DEALINGS IN THE SOFTWARE. import argparse +from textwrap import dedent -epilog = """ -exit status: - 0 the input files are well-formed and the output (if requested) was written successfully - 1 could not allocate data structures, signals a serious problem with execution environment - 2 one or more input files were not well-formed - 3 could not create an output file - 4 command-line argument error - -xmlwf of libexpat is software libre, licensed under the MIT license. -Please report bugs at https://github.com/libexpat/libexpat/issues -- thank you! -""" +epilog = dedent( + """ + environment variables: + EXPAT_ACCOUNTING_DEBUG=(0|1|2|3) + Control verbosity of accounting debugging (default: 0) + EXPAT_ENTITY_DEBUG=(0|1|2) + Control verbosity of entity debugging (default: 0) + EXPAT_ENTROPY_DEBUG=(0|1) + Control verbosity of entropy debugging (default: 0) + EXPAT_MALLOC_DEBUG=(0|1|2) + Control verbosity of allocation tracker (default: 0) + + exit status: + 0 the input files are well-formed and the output (if requested) was written successfully + 1 could not allocate data structures, signals a serious problem with execution environment + 2 one or more input files were not well-formed + 3 could not create an output file + 4 command-line argument error + + xmlwf of libexpat is software libre, licensed under the MIT license. + Please report bugs at https://github.com/libexpat/libexpat/issues -- thank you! + """ +) usage = """ %(prog)s [OPTIONS] [FILE ...] @@ -49,50 +62,121 @@ %(prog)s -v|--version """ -parser = argparse.ArgumentParser(prog='xmlwf', add_help=False, - usage=usage, - description='xmlwf - Determines if an XML document is well-formed', - formatter_class=argparse.RawTextHelpFormatter, - epilog=epilog) - -input_related = parser.add_argument_group('input control arguments') -input_related.add_argument('-s', action='store_true', help='print an error if the document is not [s]tandalone') -input_related.add_argument('-n', action='store_true', help='enable [n]amespace processing') -input_related.add_argument('-p', action='store_true', help='enable processing of external DTDs and [p]arameter entities') -input_related.add_argument('-x', action='store_true', help='enable processing of e[x]ternal entities') -input_related.add_argument('-e', action='store', metavar='ENCODING', help='override any in-document [e]ncoding declaration') -input_related.add_argument('-w', action='store_true', help='enable support for [W]indows code pages') -input_related.add_argument('-r', action='store_true', help='disable memory-mapping and use [r]ead calls instead') -input_related.add_argument('-g', metavar='BYTES', help='buffer size to request per call pair to XML_[G]etBuffer and read (default: 8 KiB)') -input_related.add_argument('-k', action='store_true', help='when processing multiple files, [k]eep processing after first file with error') - -output_related = parser.add_argument_group('output control arguments') -output_related.add_argument('-d', action='store', metavar='DIRECTORY', help='output [d]estination directory') +parser = argparse.ArgumentParser( + prog="xmlwf", + add_help=False, + usage=usage, + description="xmlwf - Determines if an XML document is well-formed", + formatter_class=argparse.RawTextHelpFormatter, + epilog=epilog, +) + +input_related = parser.add_argument_group("input control arguments") +input_related.add_argument( + "-s", action="store_true", help="print an error if the document is not [s]tandalone" +) +input_related.add_argument( + "-n", action="store_true", help="enable [n]amespace processing" +) +input_related.add_argument( + "-p", + action="store_true", + help="enable processing of external DTDs and [p]arameter entities", +) +input_related.add_argument( + "-x", + action="store_true", + help=( + "enable processing of e[x]ternal entities" + "\n" + "(CAREFUL! This makes xmlwf vulnerable to external entity attacks (XXE).)" + ), +) +input_related.add_argument( + "-e", + action="store", + metavar="ENCODING", + help="override any in-document [e]ncoding declaration", +) +input_related.add_argument( + "-w", action="store_true", help="enable support for [W]indows code pages" +) +input_related.add_argument( + "-r", + action="store_true", + help="disable memory-mapping and use [r]ead calls instead", +) +input_related.add_argument( + "-g", + metavar="BYTES", + help="buffer size to request per call pair to XML_[G]etBuffer and read (default: 8 KiB)", +) +input_related.add_argument( + "-k", + action="store_true", + help="when processing multiple files, [k]eep processing after first file with error", +) + +output_related = parser.add_argument_group("output control arguments") +output_related.add_argument( + "-d", action="store", metavar="DIRECTORY", help="output [d]estination directory" +) output_mode = output_related.add_mutually_exclusive_group() -output_mode.add_argument('-c', action='store_true', help='write a [c]opy of input XML, not canonical XML') -output_mode.add_argument('-m', action='store_true', help='write [m]eta XML, not canonical XML') -output_mode.add_argument('-t', action='store_true', help='write no XML output for [t]iming of plain parsing') -output_related.add_argument('-N', action='store_true', help='enable adding doctype and [n]otation declarations') - -billion_laughs = parser.add_argument_group('billion laughs attack protection', - description='NOTE: ' - 'If you ever need to increase these values ' - 'for non-attack payload, please file a bug report.') -billion_laughs.add_argument('-a', metavar='FACTOR', - help='set maximum tolerated [a]mplification factor (default: 100.0)') -billion_laughs.add_argument('-b', metavar='BYTES', help='set number of output [b]ytes needed to activate (default: 8 MiB)') - -reparse_deferral = parser.add_argument_group('reparse deferral') -reparse_deferral.add_argument('-q', metavar='FACTOR', - help='disable reparse deferral, and allow [q]uadratic parse runtime with large tokens') - -parser.add_argument('files', metavar='FILE', nargs='*', help='file to process (default: STDIN)') +output_mode.add_argument( + "-c", action="store_true", help="write a [c]opy of input XML, not canonical XML" +) +output_mode.add_argument( + "-m", action="store_true", help="write [m]eta XML, not canonical XML" +) +output_mode.add_argument( + "-t", action="store_true", help="write no XML output for [t]iming of plain parsing" +) +output_related.add_argument( + "-N", action="store_true", help="enable adding doctype and [n]otation declarations" +) + +billion_laughs = parser.add_argument_group( + "amplification attack protection (e.g. billion laughs)", + description=( + "NOTE: " + "If you ever need to increase these values " + "for non-attack payload, please file a bug report." + ), +) +billion_laughs.add_argument( + "-a", + metavar="FACTOR", + help="set maximum tolerated [a]mplification factor (default: 100.0)", +) +billion_laughs.add_argument( + "-b", + metavar="BYTES", + help="set number of output [b]ytes needed to activate (default: 8 MiB/64 MiB)", +) + +reparse_deferral = parser.add_argument_group("reparse deferral") +reparse_deferral.add_argument( + "-q", + action="store_true", + help="disable reparse deferral, and allow [q]uadratic parse runtime with large tokens", +) + +parser.add_argument( + "files", metavar="FILE", nargs="*", help="file to process (default: STDIN)" +) -info = parser.add_argument_group('info arguments') +info = parser.add_argument_group("info arguments") info = info.add_mutually_exclusive_group() -info.add_argument('-h', '--help', action='store_true', help='show this [h]elp message and exit') -info.add_argument('-v', '--version', action='store_true', help='show program\'s [v]ersion number and exit') +info.add_argument( + "-h", "--help", action="store_true", help="show this [h]elp message and exit" +) +info.add_argument( + "-v", + "--version", + action="store_true", + help="show program's [v]ersion number and exit", +) -if __name__ == '__main__': +if __name__ == "__main__": parser.print_help() diff -Nru expat-2.7.1/pull_request_template.md expat-2.8.2/pull_request_template.md --- expat-2.7.1/pull_request_template.md 1970-01-01 00:00:00.000000000 +0000 +++ expat-2.8.2/pull_request_template.md 2026-06-25 14:07:00.000000000 +0000 @@ -0,0 +1,17 @@ + + +# Self-Diagnosis + + +- [ ] This pull request fixes #ISSUE_NUMBER. +- [ ] This pull request is related to SOME_REFERENCE. +- [ ] This pull request is small, uncontroversial, complete, and easy to review. +- [ ] I have enabled and run all GitHub Actions CI in my fork repository, + and hence expect CI to be all-green for this pull request. +- [ ] I have read the [contribution guidelines](https://github.com/libexpat/libexpat/blob/HEAD/CONTRIBUTING.md), and this pull request meets these guidelines for contribution. +- [x] I had trouble understanding parts of this questionnaire. (Please elaborate.) + + +# Description + +TODO: This pull request does X because of Y in order to Z.