mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-11-07 04:36:52 -10:00
Vendor import of expat 2.10.0
This commit is contained in:
1 parent
91970165e3
commit
27ac437388
34 files changed
+1641
-192
No files matched your search
@@ -21,6 +21,86 @@
|
|||||||
// Sebastian Pipping -- Berlin, 2026-09-22 //
|
// Sebastian Pipping -- Berlin, 2026-09-22 //
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
Release 2.10.0 Mon November 2 2026
|
||||||
|
Security fixes:
|
||||||
|
#1431 CVE-2026-113351 -- Fix denial of service with use of
|
||||||
|
`XML_ParserReset`
|
||||||
|
#1433 #1436 ..
|
||||||
|
#1438 #1439 ..
|
||||||
|
#1442 CVE-2026-115506 -- Detect billion laughs attacks quicker
|
||||||
|
and more of its variations. Related payload fuzzer at:
|
||||||
|
https://github.com/hannob/lololol
|
||||||
|
Please note that a layer of compression around XML can
|
||||||
|
significantly reduce the minimum attack payload size.
|
||||||
|
In case of backporting, please note pull request #1439
|
||||||
|
in particular.
|
||||||
|
#1444 CVE-2026-117610 -- Fix initial non-final empty subparser
|
||||||
|
parse calls. Was segfaulting previously.
|
||||||
|
#1450 CVE-2026-118370 -- Protect `attIndex` and `nPrefixes` in
|
||||||
|
function `storeAtts` from signed integer overflow
|
||||||
|
|
||||||
|
Bug fixes:
|
||||||
|
#1452 lib: Initialize `m_parsingStatus.finalBuffer` in `parserInit`
|
||||||
|
to fix calling `XML_GetParsingStatus` right after
|
||||||
|
parser creation
|
||||||
|
#1457 #1459 lib: Improve `XML_Parse` for `XML_CONTEXT_BYTES == 0`
|
||||||
|
including NULL pointer arithmetic undefined behavior
|
||||||
|
and uninitialized variable access
|
||||||
|
#1458 lib: Use C99 length modifiers for `ptrdiff_t` and `size_t`
|
||||||
|
to fix support for CHERI-RISC-V
|
||||||
|
#1461 lib: Check `isCalledFromInsideHandler` first in `XML_Parse`
|
||||||
|
#1467 lib: Add missing check for a character handler reset
|
||||||
|
|
||||||
|
Other changes:
|
||||||
|
#1441 Autotools: Move `-lm` from LDFLAGS to LIBADD/LDADD
|
||||||
|
to better support compilation with `-Wl,--as-needed`
|
||||||
|
#1412 CMake: Support repeated `find_package` calls
|
||||||
|
#1413 lib: Address warning `XML_GE is not defined [-Werror=undef]`
|
||||||
|
#1415 lib: Stop delaying `callStoreEntityValue` error handling
|
||||||
|
#1415 lib: Add missing call to `poolDiscard`
|
||||||
|
#1437 lib: Add missing `NULL` check for `m_startDoctypeDeclHandler`
|
||||||
|
#1417 lib: Migrate `ENTITY.textLen` and `ENTITY.processed` from
|
||||||
|
`int` to `size_t`
|
||||||
|
#1463 lib: Fix integer truncation in `XmlGetAttributes`/`getAtts`
|
||||||
|
#1420 lib: Some more `XML_Bool` to `bool` migration
|
||||||
|
#1449 #1460 lib: Document the memory reuse black magic that function
|
||||||
|
`storeAtts` is doing
|
||||||
|
#1453 lib: Document failure to reject bad redefinitions of
|
||||||
|
predefined entities
|
||||||
|
#1432 tests: Replace `XML_SetHashSalt` with
|
||||||
|
`XML_SetHashSalt16Bytes`
|
||||||
|
#1416 #1435 Version info bumped from 14:0:13 (libexpat*.so.1.13.0)
|
||||||
|
to 14:1:13 (libexpat*.so.1.13.1); see https://verbump.de/
|
||||||
|
for what these numbers do
|
||||||
|
|
||||||
|
Infrastructure:
|
||||||
|
#1414 CI: Stop using about-to-be-removed image "macos-14"
|
||||||
|
#1418 #1434 CI: Bump MinGW Clang from 23.1.2 to 23.1.4
|
||||||
|
#1443 CI: Bump Fil-C from 0.686 to 0.687
|
||||||
|
#1456 Drop a `lib/xcsinc.c` leftover
|
||||||
|
|
||||||
|
Special thanks to:
|
||||||
|
Alexander Bluhm
|
||||||
|
Bartłomiej Dmitruk
|
||||||
|
Berkay Eren Ürün
|
||||||
|
Brooks Davis
|
||||||
|
brspoon
|
||||||
|
Funda Wang
|
||||||
|
Hanno Böck
|
||||||
|
Matthew Fernandez
|
||||||
|
Minkyung Park
|
||||||
|
Mirko Swillus
|
||||||
|
Pu Cheng
|
||||||
|
Scott Moore
|
||||||
|
Shani Yosef
|
||||||
|
Xisco Fauli
|
||||||
|
and
|
||||||
|
City of Munich Open Source Sabbatical
|
||||||
|
echo.ai
|
||||||
|
Siemens
|
||||||
|
Striga
|
||||||
|
VulnCheck
|
||||||
|
|
||||||
Release 2.9.0 Mon October 5 2026
|
Release 2.9.0 Mon October 5 2026
|
||||||
Security fixes:
|
Security fixes:
|
||||||
#1392 CVE-2026-102633 -- Integer overflow in function
|
#1392 CVE-2026-102633 -- Integer overflow in function
|
||||||
@@ -106,6 +186,7 @@ Release 2.9.0 Mon October 5 2026
|
|||||||
Wade Sparks III
|
Wade Sparks III
|
||||||
and
|
and
|
||||||
City of Munich Open Source Sabbatical
|
City of Munich Open Source Sabbatical
|
||||||
|
Siemens
|
||||||
VulnCheck
|
VulnCheck
|
||||||
|
|
||||||
Release 2.8.5 Tue September 22 2026
|
Release 2.8.5 Tue September 22 2026
|
||||||
@@ -239,6 +320,7 @@ Release 2.8.4 Mon August 31 2026
|
|||||||
and
|
and
|
||||||
City of Munich Open Source Sabbatical
|
City of Munich Open Source Sabbatical
|
||||||
Moonshot AI
|
Moonshot AI
|
||||||
|
Siemens
|
||||||
VulnCheck
|
VulnCheck
|
||||||
Z.ai
|
Z.ai
|
||||||
|
|
||||||
@@ -425,6 +507,8 @@ Release 2.8.1 Sun May 10 2026
|
|||||||
Matthew Fernandez
|
Matthew Fernandez
|
||||||
Nick Wellnhofer
|
Nick Wellnhofer
|
||||||
Tania Somanna
|
Tania Somanna
|
||||||
|
and
|
||||||
|
Siemens
|
||||||
|
|
||||||
Release 2.8.0 Fri April 24 2026
|
Release 2.8.0 Fri April 24 2026
|
||||||
Security fixes:
|
Security fixes:
|
||||||
@@ -537,6 +621,7 @@ Release 2.7.5 Tue March 17 2026
|
|||||||
AddressSanitizer
|
AddressSanitizer
|
||||||
Buttercup
|
Buttercup
|
||||||
OSS-Fuzz / ClusterFuzz
|
OSS-Fuzz / ClusterFuzz
|
||||||
|
Siemens
|
||||||
Trail of Bits
|
Trail of Bits
|
||||||
|
|
||||||
Release 2.7.4 Sat January 31 2026
|
Release 2.7.4 Sat January 31 2026
|
||||||
@@ -678,6 +763,7 @@ Release 2.7.3 Wed September 24 2025
|
|||||||
and
|
and
|
||||||
Clang/GCC UndefinedBehaviorSanitizer
|
Clang/GCC UndefinedBehaviorSanitizer
|
||||||
OSS-Fuzz / ClusterFuzz
|
OSS-Fuzz / ClusterFuzz
|
||||||
|
Siemens
|
||||||
Z3 Theorem Prover
|
Z3 Theorem Prover
|
||||||
|
|
||||||
Release 2.7.2 Tue September 16 2025
|
Release 2.7.2 Tue September 16 2025
|
||||||
@@ -791,6 +877,7 @@ Release 2.7.1 Thu March 27 2025
|
|||||||
Matthew Fernandez
|
Matthew Fernandez
|
||||||
and
|
and
|
||||||
Perl XML::Parser
|
Perl XML::Parser
|
||||||
|
Siemens
|
||||||
|
|
||||||
Release 2.7.0 Thu March 13 2025
|
Release 2.7.0 Thu March 13 2025
|
||||||
Security fixes:
|
Security fixes:
|
||||||
@@ -950,6 +1037,8 @@ Release 2.6.3 Wed September 4 2024
|
|||||||
Dag-Erling Smørgrav
|
Dag-Erling Smørgrav
|
||||||
Ferenc Géczi
|
Ferenc Géczi
|
||||||
TaiYou
|
TaiYou
|
||||||
|
and
|
||||||
|
Siemens
|
||||||
|
|
||||||
Release 2.6.2 Wed March 13 2024
|
Release 2.6.2 Wed March 13 2024
|
||||||
Security fixes:
|
Security fixes:
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
> Thank you! :heart: :pray:
|
> Thank you! :heart: :pray:
|
||||||
|
|
||||||
|
|
||||||
# Expat, Release 2.9.0
|
# Expat, Release 2.10.0
|
||||||
|
|
||||||
This is Expat, a C99 library for parsing
|
This is Expat, a C99 library for parsing
|
||||||
[XML 1.0 Fourth Edition](https://www.w3.org/TR/2006/REC-xml-20060816/), started by
|
[XML 1.0 Fourth Edition](https://www.w3.org/TR/2006/REC-xml-20060816/), started by
|
||||||
|
|||||||
+1
-1
@@ -104,7 +104,7 @@ dnl If the API changes incompatibly set LIBAGE back to 0
|
|||||||
dnl
|
dnl
|
||||||
|
|
||||||
LIBCURRENT=14 # sync
|
LIBCURRENT=14 # sync
|
||||||
LIBREVISION=0 # with
|
LIBREVISION=1 # with
|
||||||
LIBAGE=13 # CMakeLists.txt!
|
LIBAGE=13 # CMakeLists.txt!
|
||||||
|
|
||||||
AC_CONFIG_HEADERS([expat_config.h])
|
AC_CONFIG_HEADERS([expat_config.h])
|
||||||
|
|||||||
+7
-1
@@ -53,7 +53,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<div>
|
<div>
|
||||||
<h1>
|
<h1>
|
||||||
The Expat XML Parser <small>Release 2.9.0</small>
|
The Expat XML Parser <small>Release 2.10.0</small>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -2862,6 +2862,12 @@ typedef void
|
|||||||
The <code>notationName</code> argument will have a non-<code>NULL</code> value
|
The <code>notationName</code> argument will have a non-<code>NULL</code> value
|
||||||
only for unparsed entity declarations.
|
only for unparsed entity declarations.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<strong>Note:</strong> Length <code>value_length</code> can wrap around on
|
||||||
|
platforms where <code>int</code> is smaller than <code>size_t</code> including
|
||||||
|
<code>x86_64</code>.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="handler">
|
<div class="handler">
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
\\$2 \(la\\$1\(ra\\$3
|
\\$2 \(la\\$1\(ra\\$3
|
||||||
..
|
..
|
||||||
.if \n(.g .mso www.tmac
|
.if \n(.g .mso www.tmac
|
||||||
.TH XMLWF 1 "October 5, 2026" "" ""
|
.TH XMLWF 1 "November 2, 2026" "" ""
|
||||||
.SH NAME
|
.SH NAME
|
||||||
xmlwf \- Determines if an XML document is well-formed
|
xmlwf \- Determines if an XML document is well-formed
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@
|
|||||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
|
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
|
||||||
<!ENTITY dhfirstname "<firstname>Scott</firstname>">
|
<!ENTITY dhfirstname "<firstname>Scott</firstname>">
|
||||||
<!ENTITY dhsurname "<surname>Bronson</surname>">
|
<!ENTITY dhsurname "<surname>Bronson</surname>">
|
||||||
<!ENTITY dhdate "<date>October 5, 2026</date>">
|
<!ENTITY dhdate "<date>November 2, 2026</date>">
|
||||||
<!-- Please adjust this^^ date whenever cutting a new release. -->
|
<!-- Please adjust this^^ date whenever cutting a new release. -->
|
||||||
<!ENTITY dhsection "<manvolnum>1</manvolnum>">
|
<!ENTITY dhsection "<manvolnum>1</manvolnum>">
|
||||||
<!ENTITY dhemail "<email>[email protected]</email>">
|
<!ENTITY dhemail "<email>[email protected]</email>">
|
||||||
|
|||||||
+4
-1
@@ -12,6 +12,7 @@
|
|||||||
# Copyright (c) 2026 Gordon Messmer <[email protected]>
|
# Copyright (c) 2026 Gordon Messmer <[email protected]>
|
||||||
# Copyright (c) 2026 Nick Begg <[email protected]>
|
# Copyright (c) 2026 Nick Begg <[email protected]>
|
||||||
# Copyright (c) 2026 Matthew Fernandez <[email protected]>
|
# Copyright (c) 2026 Matthew Fernandez <[email protected]>
|
||||||
|
# Copyright (c) 2026 Funda Wang <[email protected]>
|
||||||
# Licensed under the MIT license:
|
# Licensed under the MIT license:
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
# Permission is hereby granted, free of charge, to any person obtaining
|
||||||
@@ -45,13 +46,14 @@ endif
|
|||||||
|
|
||||||
libexpat_la_LDFLAGS = \
|
libexpat_la_LDFLAGS = \
|
||||||
@AM_LDFLAGS@ \
|
@AM_LDFLAGS@ \
|
||||||
@LIBM@ \
|
|
||||||
-no-undefined \
|
-no-undefined \
|
||||||
-version-info @LIBCURRENT@:@LIBREVISION@:@LIBAGE@
|
-version-info @LIBCURRENT@:@LIBREVISION@:@LIBAGE@
|
||||||
if HAVE_VSCRIPT
|
if HAVE_VSCRIPT
|
||||||
libexpat_la_LDFLAGS += $(VSCRIPT_LDFLAGS),@builddir@/libexpat.map
|
libexpat_la_LDFLAGS += $(VSCRIPT_LDFLAGS),@builddir@/libexpat.map
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
libexpat_la_LIBADD = @LIBM@
|
||||||
|
|
||||||
libexpat_la_SOURCES = \
|
libexpat_la_SOURCES = \
|
||||||
xcs.c \
|
xcs.c \
|
||||||
xmlparse.c \
|
xmlparse.c \
|
||||||
@@ -113,6 +115,7 @@ uninstall-local:
|
|||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
ascii.h \
|
ascii.h \
|
||||||
asciitab.h \
|
asciitab.h \
|
||||||
|
entities.h \
|
||||||
expat_external.h \
|
expat_external.h \
|
||||||
expat.h \
|
expat.h \
|
||||||
fallthrough.h \
|
fallthrough.h \
|
||||||
|
|||||||
+5
-2
@@ -28,6 +28,7 @@
|
|||||||
# Copyright (c) 2026 Gordon Messmer <[email protected]>
|
# Copyright (c) 2026 Gordon Messmer <[email protected]>
|
||||||
# Copyright (c) 2026 Nick Begg <[email protected]>
|
# Copyright (c) 2026 Nick Begg <[email protected]>
|
||||||
# Copyright (c) 2026 Matthew Fernandez <[email protected]>
|
# Copyright (c) 2026 Matthew Fernandez <[email protected]>
|
||||||
|
# Copyright (c) 2026 Funda Wang <[email protected]>
|
||||||
# Licensed under the MIT license:
|
# Licensed under the MIT license:
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
# Permission is hereby granted, free of charge, to any person obtaining
|
||||||
@@ -205,7 +206,7 @@ am__uninstall_files_from_dir = { \
|
|||||||
am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(docdir)" \
|
am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(docdir)" \
|
||||||
"$(DESTDIR)$(includedir)"
|
"$(DESTDIR)$(includedir)"
|
||||||
LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES)
|
LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES)
|
||||||
libexpat_la_LIBADD =
|
libexpat_la_DEPENDENCIES =
|
||||||
am__libexpat_la_SOURCES_DIST = xcs.c xmlparse.c xmltok.c xmlrole.c \
|
am__libexpat_la_SOURCES_DIST = xcs.c xmlparse.c xmltok.c xmlrole.c \
|
||||||
random_arc4random.c random_arc4random.h \
|
random_arc4random.c random_arc4random.h \
|
||||||
random_arc4random_buf.c random_arc4random_buf.h \
|
random_arc4random_buf.c random_arc4random_buf.h \
|
||||||
@@ -493,8 +494,9 @@ include_HEADERS = \
|
|||||||
|
|
||||||
lib_LTLIBRARIES = libexpat.la
|
lib_LTLIBRARIES = libexpat.la
|
||||||
@WITH_TESTS_TRUE@noinst_LTLIBRARIES = libtestpat.la
|
@WITH_TESTS_TRUE@noinst_LTLIBRARIES = libtestpat.la
|
||||||
libexpat_la_LDFLAGS = @AM_LDFLAGS@ @LIBM@ -no-undefined -version-info \
|
libexpat_la_LDFLAGS = @AM_LDFLAGS@ -no-undefined -version-info \
|
||||||
@LIBCURRENT@:@LIBREVISION@:@LIBAGE@ $(am__append_1)
|
@LIBCURRENT@:@LIBREVISION@:@LIBAGE@ $(am__append_1)
|
||||||
|
libexpat_la_LIBADD = @LIBM@
|
||||||
libexpat_la_SOURCES = xcs.c xmlparse.c xmltok.c xmlrole.c \
|
libexpat_la_SOURCES = xcs.c xmlparse.c xmltok.c xmlrole.c \
|
||||||
$(am__append_2) $(am__append_3) $(am__append_4) \
|
$(am__append_2) $(am__append_3) $(am__append_4) \
|
||||||
$(am__append_5) $(am__append_6) $(am__append_7)
|
$(am__append_5) $(am__append_6) $(am__append_7)
|
||||||
@@ -507,6 +509,7 @@ doc_DATA = \
|
|||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
ascii.h \
|
ascii.h \
|
||||||
asciitab.h \
|
asciitab.h \
|
||||||
|
entities.h \
|
||||||
expat_external.h \
|
expat_external.h \
|
||||||
expat.h \
|
expat.h \
|
||||||
fallthrough.h \
|
fallthrough.h \
|
||||||
|
|||||||
+2
-1
@@ -10,7 +10,7 @@
|
|||||||
Copyright (c) 2000 Clark Cooper <[email protected]>
|
Copyright (c) 2000 Clark Cooper <[email protected]>
|
||||||
Copyright (c) 2002 Fred L. Drake, Jr. <[email protected]>
|
Copyright (c) 2002 Fred L. Drake, Jr. <[email protected]>
|
||||||
Copyright (c) 2007 Karl Waclawek <[email protected]>
|
Copyright (c) 2007 Karl Waclawek <[email protected]>
|
||||||
Copyright (c) 2017 Sebastian Pipping <[email protected]>
|
Copyright (c) 2017-2026 Sebastian Pipping <[email protected]>
|
||||||
Licensed under the MIT license:
|
Licensed under the MIT license:
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
@@ -113,6 +113,7 @@
|
|||||||
#define ASCII_LT 0x3C
|
#define ASCII_LT 0x3C
|
||||||
#define ASCII_EQUALS 0x3D
|
#define ASCII_EQUALS 0x3D
|
||||||
#define ASCII_GT 0x3E
|
#define ASCII_GT 0x3E
|
||||||
|
#define ASCII_QUEST 0x3F
|
||||||
#define ASCII_LSQB 0x5B
|
#define ASCII_LSQB 0x5B
|
||||||
#define ASCII_RSQB 0x5D
|
#define ASCII_RSQB 0x5D
|
||||||
#define ASCII_UNDERSCORE 0x5F
|
#define ASCII_UNDERSCORE 0x5F
|
||||||
|
|||||||
@@ -0,0 +1,99 @@
|
|||||||
|
/* Internal helpers related to entities
|
||||||
|
__ __ _
|
||||||
|
___\ \/ /_ __ __ _| |_
|
||||||
|
/ _ \\ /| '_ \ / _` | __|
|
||||||
|
| __// \| |_) | (_| | |_
|
||||||
|
\___/_/\_\ .__/ \__,_|\__|
|
||||||
|
|_| XML parser
|
||||||
|
|
||||||
|
Copyright (c) 2026 Sebastian Pipping <[email protected]>
|
||||||
|
Licensed under the MIT license:
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||||
|
persons to whom the Software is furnished to do so, subject to the
|
||||||
|
following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||||
|
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if ! defined(EXPAT_ENTITIES_H)
|
||||||
|
# define EXPAT_ENTITIES_H 1
|
||||||
|
|
||||||
|
# include "expat_config.h" // for XML_GE
|
||||||
|
# include "expat_external.h" // for XML_Char
|
||||||
|
# include "internal.h" // for XML_NONTESTING_STATIC
|
||||||
|
# include <stdbool.h> // for size_t
|
||||||
|
# include <stddef.h> // for size_t
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const XML_Char *name;
|
||||||
|
const XML_Char *textPtr;
|
||||||
|
size_t textLen; /* length in XML_Chars */
|
||||||
|
size_t processed; /* # of processed bytes - when suspended */
|
||||||
|
const XML_Char *systemId;
|
||||||
|
const XML_Char *base;
|
||||||
|
const XML_Char *publicId;
|
||||||
|
const XML_Char *notation;
|
||||||
|
bool open;
|
||||||
|
bool hasMore; /* true if entity has not been completely processed */
|
||||||
|
/* An entity can be open while being already completely processed (!hasMore).
|
||||||
|
The reason is the delayed closing of entities until their inner
|
||||||
|
entities are processed and closed */
|
||||||
|
bool is_param;
|
||||||
|
bool is_internal; /* true if declared in internal subset outside PE */
|
||||||
|
# if XML_GE == 1
|
||||||
|
/* Indirect accounting bytes charged when this entity is expanded: 1 per text
|
||||||
|
character, plus each reference's "&name;"/"%name;" token length and its own
|
||||||
|
expansion. Matches XML_ACCOUNT_ENTITY_EXPANSION, so it is not the
|
||||||
|
replacement-text size. 0 means "not computed yet" (an empty entity is 0
|
||||||
|
too, told apart by textLen == 0). */
|
||||||
|
XmlBigCount expandedSize;
|
||||||
|
bool beingAnalyzed; /* on the resolveEntityClosureExpandedSize depth-first
|
||||||
|
search stack; used for cycle detection */
|
||||||
|
const XML_Char
|
||||||
|
*scanPtr; /* cursor position into the entity's replacement text; NULL when
|
||||||
|
`textPtr` is NULL, else a pointer into the entity value,
|
||||||
|
ranging from `.textPtr` to `.textPtr + .textLen`. */
|
||||||
|
# endif /* XML_GE == 1 */
|
||||||
|
} ENTITY;
|
||||||
|
|
||||||
|
# if XML_GE == 1
|
||||||
|
/* How a scanEntityText call ended. */
|
||||||
|
enum EntityScanResult {
|
||||||
|
ENTITY_SCAN_COMPLETE, /* reached end of text; *expandedSize is final */
|
||||||
|
ENTITY_SCAN_BLOCKED, /* stopped at a defined entity whose expanded
|
||||||
|
size has not been computed yet; *blockerOut
|
||||||
|
names the entity whose size to compute
|
||||||
|
first */
|
||||||
|
ENTITY_SCAN_OVERFLOW /* the expanded size would exceed XmlBigCount;
|
||||||
|
callers must abort parsing */
|
||||||
|
};
|
||||||
|
|
||||||
|
XML_NONTESTING_STATIC int isCDataCommentOrPIStart(const XML_Char *pos,
|
||||||
|
size_t maxLen,
|
||||||
|
size_t *openTextLen);
|
||||||
|
|
||||||
|
XML_NONTESTING_STATIC int isPredefinedEntityName(const XML_Char *name,
|
||||||
|
size_t nameLen);
|
||||||
|
|
||||||
|
XML_NONTESTING_STATIC enum EntityScanResult
|
||||||
|
scanEntityText(XML_Parser parser, ENTITY *entity, const XML_Char **posPtr,
|
||||||
|
XmlBigCount *expandedSize, ENTITY **blockerOut);
|
||||||
|
# endif /* XML_GE == 1 */
|
||||||
|
|
||||||
|
#endif // ! defined(EXPAT_ENTITIES_H)
|
||||||
+3
-2
@@ -21,6 +21,7 @@
|
|||||||
Copyright (c) 2024 Taichi Haradaguchi <[email protected]>
|
Copyright (c) 2024 Taichi Haradaguchi <[email protected]>
|
||||||
Copyright (c) 2025 Matthew Fernandez <[email protected]>
|
Copyright (c) 2025 Matthew Fernandez <[email protected]>
|
||||||
Copyright (c) 2026 Braian Plaku <[email protected]>
|
Copyright (c) 2026 Braian Plaku <[email protected]>
|
||||||
|
Copyright (c) 2026 Xisco Fauli <[email protected]>
|
||||||
Licensed under the MIT license:
|
Licensed under the MIT license:
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
@@ -1084,7 +1085,7 @@ enum XML_Parser_Property {
|
|||||||
# if defined(XML_TESTING)
|
# if defined(XML_TESTING)
|
||||||
XML_PROP_INVALID = 0,
|
XML_PROP_INVALID = 0,
|
||||||
# endif
|
# endif
|
||||||
# if XML_GE == 1
|
# if defined(XML_GE) && XML_GE == 1
|
||||||
XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD = 1, // of type `uint64_t`
|
XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD = 1, // of type `uint64_t`
|
||||||
XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION = 2, // of type `double`
|
XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION = 2, // of type `double`
|
||||||
XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD = 3, // of type `uint64_t`
|
XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD = 3, // of type `uint64_t`
|
||||||
@@ -1146,7 +1147,7 @@ XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled);
|
|||||||
See https://semver.org
|
See https://semver.org
|
||||||
*/
|
*/
|
||||||
# define XML_MAJOR_VERSION 2
|
# define XML_MAJOR_VERSION 2
|
||||||
# define XML_MINOR_VERSION 9
|
# define XML_MINOR_VERSION 10
|
||||||
# define XML_MICRO_VERSION 0
|
# define XML_MICRO_VERSION 0
|
||||||
|
|
||||||
# ifdef __cplusplus
|
# ifdef __cplusplus
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
Copyright (c) 2001-2002 Greg Stein <[email protected]>
|
Copyright (c) 2001-2002 Greg Stein <[email protected]>
|
||||||
Copyright (c) 2002-2006 Karl Waclawek <[email protected]>
|
Copyright (c) 2002-2006 Karl Waclawek <[email protected]>
|
||||||
Copyright (c) 2016 Cristian Rodríguez <[email protected]>
|
Copyright (c) 2016 Cristian Rodríguez <[email protected]>
|
||||||
Copyright (c) 2016-2025 Sebastian Pipping <[email protected]>
|
Copyright (c) 2016-2026 Sebastian Pipping <[email protected]>
|
||||||
Copyright (c) 2017 Rhodri James <[email protected]>
|
Copyright (c) 2017 Rhodri James <[email protected]>
|
||||||
Copyright (c) 2018 Yury Gribov <[email protected]>
|
Copyright (c) 2018 Yury Gribov <[email protected]>
|
||||||
Copyright (c) 2026 Matthew Fernandez <[email protected]>
|
Copyright (c) 2026 Matthew Fernandez <[email protected]>
|
||||||
|
|||||||
+5
-3
@@ -29,6 +29,7 @@
|
|||||||
Copyright (c) 2026 Matthew Wozniczka <[email protected]>
|
Copyright (c) 2026 Matthew Wozniczka <[email protected]>
|
||||||
Copyright (c) 2026 Braian Plaku <[email protected]>
|
Copyright (c) 2026 Braian Plaku <[email protected]>
|
||||||
Copyright (c) 2026 Florian Schmaus <[email protected]>
|
Copyright (c) 2026 Florian Schmaus <[email protected]>
|
||||||
|
Copyright (c) 2026 Brooks Davis <[email protected]>
|
||||||
Licensed under the MIT license:
|
Licensed under the MIT license:
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
@@ -90,11 +91,10 @@
|
|||||||
# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "u"
|
# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "u"
|
||||||
# endif
|
# endif
|
||||||
# else
|
# else
|
||||||
# include <inttypes.h> // PRIdPTR, PRIuPTR
|
|
||||||
# define EXPAT_FMT_LLX(midpart) "%" midpart "llx"
|
# define EXPAT_FMT_LLX(midpart) "%" midpart "llx"
|
||||||
# define EXPAT_FMT_ULL(midpart) "%" midpart "llu"
|
# define EXPAT_FMT_ULL(midpart) "%" midpart "llu"
|
||||||
# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart PRIdPTR
|
# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "td"
|
||||||
# define EXPAT_FMT_SIZE_T(midpart) "%" midpart PRIuPTR
|
# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "zu"
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# ifndef UNUSED_P
|
# ifndef UNUSED_P
|
||||||
@@ -127,6 +127,8 @@ union expat_align {
|
|||||||
|
|
||||||
# include "expat.h" // so we can use type XML_Parser below
|
# include "expat.h" // so we can use type XML_Parser below
|
||||||
|
|
||||||
|
typedef unsigned long long XmlBigCount;
|
||||||
|
|
||||||
void _INTERNAL_trim_to_complete_utf8_characters(const char *from,
|
void _INTERNAL_trim_to_complete_utf8_characters(const char *from,
|
||||||
const char **fromLimRef);
|
const char **fromLimRef);
|
||||||
|
|
||||||
|
|||||||
@@ -88,3 +88,24 @@ xcsncmp(const XML_Char *a, const XML_Char *b, size_t len) {
|
|||||||
return strncmp(a, b, len);
|
return strncmp(a, b, len);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A port of `strnstr(3bsd)` to `XML_Char`
|
||||||
|
const XML_Char *
|
||||||
|
xcsnstr(const XML_Char *haystack, const XML_Char *needle, size_t maxLen) {
|
||||||
|
// NOTE: We are not calling `xcsnlen(haystack, maxLen)` because
|
||||||
|
// `haystack` could be long and `xcsnlen` could be used in a loop
|
||||||
|
// and we need to avoid quadratic runtime behavior.
|
||||||
|
if (! *needle)
|
||||||
|
return haystack; // i.e. empty needle is always a match
|
||||||
|
const size_t needleLen = xcslen(needle);
|
||||||
|
if (needleLen > maxLen)
|
||||||
|
return NULL;
|
||||||
|
const size_t maxTries = (maxLen - needleLen) + 1;
|
||||||
|
for (size_t i = 0; i < maxTries && haystack[i]; i++) {
|
||||||
|
if (haystack[i] == needle[0]
|
||||||
|
&& xcsncmp(haystack + i, needle, needleLen) == 0) {
|
||||||
|
return haystack + i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
@@ -41,4 +41,7 @@ extern size_t xcslen(const XML_Char *s);
|
|||||||
extern int xcscmp(const XML_Char *a, const XML_Char *b);
|
extern int xcscmp(const XML_Char *a, const XML_Char *b);
|
||||||
extern int xcsncmp(const XML_Char *a, const XML_Char *b, size_t len);
|
extern int xcsncmp(const XML_Char *a, const XML_Char *b, size_t len);
|
||||||
|
|
||||||
|
extern const XML_Char *xcsnstr(const XML_Char *haystack, const XML_Char *needle,
|
||||||
|
size_t maxLen);
|
||||||
|
|
||||||
#endif // ! defined(EXPAT_XCS_H)
|
#endif // ! defined(EXPAT_XCS_H)
|
||||||
+731
-138
File diff suppressed because it is too large.
Load diff
+2
-2
@@ -176,8 +176,8 @@ struct encoding {
|
|||||||
const char *);
|
const char *);
|
||||||
int (*nameLength)(const ENCODING *, const char *);
|
int (*nameLength)(const ENCODING *, const char *);
|
||||||
const char *(*skipS)(const ENCODING *, const char *);
|
const char *(*skipS)(const ENCODING *, const char *);
|
||||||
int (*getAtts)(const ENCODING *enc, const char *ptr, int attsMax,
|
size_t (*getAtts)(const ENCODING *enc, const char *ptr, size_t attsMax,
|
||||||
ATTRIBUTE *atts);
|
ATTRIBUTE *atts);
|
||||||
int (*charRefNumber)(const ENCODING *enc, const char *ptr);
|
int (*charRefNumber)(const ENCODING *enc, const char *ptr);
|
||||||
int (*predefinedEntityName)(const ENCODING *, const char *, const char *);
|
int (*predefinedEntityName)(const ENCODING *, const char *, const char *);
|
||||||
void (*updatePosition)(const ENCODING *, const char *ptr, const char *end,
|
void (*updatePosition)(const ENCODING *, const char *ptr, const char *end,
|
||||||
|
|||||||
+3
-3
@@ -1505,11 +1505,11 @@ PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
|
|||||||
first attsMax attributes are stored in atts.
|
first attsMax attributes are stored in atts.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static size_t
|
||||||
PREFIX(getAtts)(const ENCODING *enc, const char *ptr, int attsMax,
|
PREFIX(getAtts)(const ENCODING *enc, const char *ptr, size_t attsMax,
|
||||||
ATTRIBUTE *atts) {
|
ATTRIBUTE *atts) {
|
||||||
enum { other, inName, inValue } state = inName;
|
enum { other, inName, inValue } state = inName;
|
||||||
int nAtts = 0;
|
size_t nAtts = 0;
|
||||||
int open = 0; /* defined when state == inValue;
|
int open = 0; /* defined when state == inValue;
|
||||||
initialization just to shut up compilers */
|
initialization just to shut up compilers */
|
||||||
|
|
||||||
|
|||||||
+5
-2
@@ -10,6 +10,7 @@
|
|||||||
# Copyright (c) 2017-2022 Rhodri James <[email protected]>
|
# Copyright (c) 2017-2022 Rhodri James <[email protected]>
|
||||||
# Copyright (c) 2020 Jeffrey Walton <[email protected]>
|
# Copyright (c) 2020 Jeffrey Walton <[email protected]>
|
||||||
# Copyright (c) 2024 Dag-Erling Smørgrav <[email protected]>
|
# Copyright (c) 2024 Dag-Erling Smørgrav <[email protected]>
|
||||||
|
# Copyright (c) 2026 Funda Wang <[email protected]>
|
||||||
# Licensed under the MIT license:
|
# Licensed under the MIT license:
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
# Permission is hereby granted, free of charge, to any person obtaining
|
||||||
@@ -50,6 +51,7 @@ runtests_SOURCES = \
|
|||||||
dummy.c \
|
dummy.c \
|
||||||
handlers.c \
|
handlers.c \
|
||||||
hash_tests.c \
|
hash_tests.c \
|
||||||
|
entities_tests.c \
|
||||||
memcheck.c \
|
memcheck.c \
|
||||||
minicheck.c \
|
minicheck.c \
|
||||||
misc_tests.c \
|
misc_tests.c \
|
||||||
@@ -60,9 +62,9 @@ runtests_SOURCES = \
|
|||||||
structdata.c \
|
structdata.c \
|
||||||
xcs_tests.c
|
xcs_tests.c
|
||||||
|
|
||||||
runtests_LDADD = ../lib/libtestpat.la
|
runtests_LDADD = ../lib/libtestpat.la @LIBM@
|
||||||
|
|
||||||
runtests_LDFLAGS = @AM_LDFLAGS@ @LIBM@
|
runtests_LDFLAGS = @AM_LDFLAGS@
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
acc_tests.h \
|
acc_tests.h \
|
||||||
@@ -73,6 +75,7 @@ EXTRA_DIST = \
|
|||||||
dummy.h \
|
dummy.h \
|
||||||
handlers.h \
|
handlers.h \
|
||||||
hash_tests.h \
|
hash_tests.h \
|
||||||
|
entities_tests.h \
|
||||||
memcheck.h \
|
memcheck.h \
|
||||||
minicheck.h \
|
minicheck.h \
|
||||||
misc_tests.h \
|
misc_tests.h \
|
||||||
|
|||||||
+19
-12
@@ -26,6 +26,7 @@
|
|||||||
# Copyright (c) 2017-2022 Rhodri James <[email protected]>
|
# Copyright (c) 2017-2022 Rhodri James <[email protected]>
|
||||||
# Copyright (c) 2020 Jeffrey Walton <[email protected]>
|
# Copyright (c) 2020 Jeffrey Walton <[email protected]>
|
||||||
# Copyright (c) 2024 Dag-Erling Smørgrav <[email protected]>
|
# Copyright (c) 2024 Dag-Erling Smørgrav <[email protected]>
|
||||||
|
# Copyright (c) 2026 Funda Wang <[email protected]>
|
||||||
# Licensed under the MIT license:
|
# Licensed under the MIT license:
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
# Permission is hereby granted, free of charge, to any person obtaining
|
||||||
@@ -150,10 +151,10 @@ CONFIG_CLEAN_VPATH_FILES =
|
|||||||
am_runtests_OBJECTS = acc_tests.$(OBJEXT) alloc_tests.$(OBJEXT) \
|
am_runtests_OBJECTS = acc_tests.$(OBJEXT) alloc_tests.$(OBJEXT) \
|
||||||
basic_tests.$(OBJEXT) chardata.$(OBJEXT) common.$(OBJEXT) \
|
basic_tests.$(OBJEXT) chardata.$(OBJEXT) common.$(OBJEXT) \
|
||||||
dummy.$(OBJEXT) handlers.$(OBJEXT) hash_tests.$(OBJEXT) \
|
dummy.$(OBJEXT) handlers.$(OBJEXT) hash_tests.$(OBJEXT) \
|
||||||
memcheck.$(OBJEXT) minicheck.$(OBJEXT) misc_tests.$(OBJEXT) \
|
entities_tests.$(OBJEXT) memcheck.$(OBJEXT) \
|
||||||
ns_tests.$(OBJEXT) nsalloc_tests.$(OBJEXT) \
|
minicheck.$(OBJEXT) misc_tests.$(OBJEXT) ns_tests.$(OBJEXT) \
|
||||||
props_tests.$(OBJEXT) runtests.$(OBJEXT) structdata.$(OBJEXT) \
|
nsalloc_tests.$(OBJEXT) props_tests.$(OBJEXT) \
|
||||||
xcs_tests.$(OBJEXT)
|
runtests.$(OBJEXT) structdata.$(OBJEXT) xcs_tests.$(OBJEXT)
|
||||||
runtests_OBJECTS = $(am_runtests_OBJECTS)
|
runtests_OBJECTS = $(am_runtests_OBJECTS)
|
||||||
runtests_DEPENDENCIES = ../lib/libtestpat.la
|
runtests_DEPENDENCIES = ../lib/libtestpat.la
|
||||||
AM_V_lt = $(am__v_lt_@AM_V@)
|
AM_V_lt = $(am__v_lt_@AM_V@)
|
||||||
@@ -181,12 +182,13 @@ am__maybe_remake_depfiles = depfiles
|
|||||||
am__depfiles_remade = ./$(DEPDIR)/acc_tests.Po \
|
am__depfiles_remade = ./$(DEPDIR)/acc_tests.Po \
|
||||||
./$(DEPDIR)/alloc_tests.Po ./$(DEPDIR)/basic_tests.Po \
|
./$(DEPDIR)/alloc_tests.Po ./$(DEPDIR)/basic_tests.Po \
|
||||||
./$(DEPDIR)/chardata.Po ./$(DEPDIR)/common.Po \
|
./$(DEPDIR)/chardata.Po ./$(DEPDIR)/common.Po \
|
||||||
./$(DEPDIR)/dummy.Po ./$(DEPDIR)/handlers.Po \
|
./$(DEPDIR)/dummy.Po ./$(DEPDIR)/entities_tests.Po \
|
||||||
./$(DEPDIR)/hash_tests.Po ./$(DEPDIR)/memcheck.Po \
|
./$(DEPDIR)/handlers.Po ./$(DEPDIR)/hash_tests.Po \
|
||||||
./$(DEPDIR)/minicheck.Po ./$(DEPDIR)/misc_tests.Po \
|
./$(DEPDIR)/memcheck.Po ./$(DEPDIR)/minicheck.Po \
|
||||||
./$(DEPDIR)/ns_tests.Po ./$(DEPDIR)/nsalloc_tests.Po \
|
./$(DEPDIR)/misc_tests.Po ./$(DEPDIR)/ns_tests.Po \
|
||||||
./$(DEPDIR)/props_tests.Po ./$(DEPDIR)/runtests.Po \
|
./$(DEPDIR)/nsalloc_tests.Po ./$(DEPDIR)/props_tests.Po \
|
||||||
./$(DEPDIR)/structdata.Po ./$(DEPDIR)/xcs_tests.Po
|
./$(DEPDIR)/runtests.Po ./$(DEPDIR)/structdata.Po \
|
||||||
|
./$(DEPDIR)/xcs_tests.Po
|
||||||
am__mv = mv -f
|
am__mv = mv -f
|
||||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||||
@@ -650,6 +652,7 @@ runtests_SOURCES = \
|
|||||||
dummy.c \
|
dummy.c \
|
||||||
handlers.c \
|
handlers.c \
|
||||||
hash_tests.c \
|
hash_tests.c \
|
||||||
|
entities_tests.c \
|
||||||
memcheck.c \
|
memcheck.c \
|
||||||
minicheck.c \
|
minicheck.c \
|
||||||
misc_tests.c \
|
misc_tests.c \
|
||||||
@@ -660,8 +663,8 @@ runtests_SOURCES = \
|
|||||||
structdata.c \
|
structdata.c \
|
||||||
xcs_tests.c
|
xcs_tests.c
|
||||||
|
|
||||||
runtests_LDADD = ../lib/libtestpat.la
|
runtests_LDADD = ../lib/libtestpat.la @LIBM@
|
||||||
runtests_LDFLAGS = @AM_LDFLAGS@ @LIBM@
|
runtests_LDFLAGS = @AM_LDFLAGS@
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
acc_tests.h \
|
acc_tests.h \
|
||||||
alloc_tests.h \
|
alloc_tests.h \
|
||||||
@@ -671,6 +674,7 @@ EXTRA_DIST = \
|
|||||||
dummy.h \
|
dummy.h \
|
||||||
handlers.h \
|
handlers.h \
|
||||||
hash_tests.h \
|
hash_tests.h \
|
||||||
|
entities_tests.h \
|
||||||
memcheck.h \
|
memcheck.h \
|
||||||
minicheck.h \
|
minicheck.h \
|
||||||
misc_tests.h \
|
misc_tests.h \
|
||||||
@@ -738,6 +742,7 @@ distclean-compile:
|
|||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chardata.Po@am__quote@ # am--include-marker
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chardata.Po@am__quote@ # am--include-marker
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@ # am--include-marker
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@ # am--include-marker
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dummy.Po@am__quote@ # am--include-marker
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dummy.Po@am__quote@ # am--include-marker
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/entities_tests.Po@am__quote@ # am--include-marker
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/handlers.Po@am__quote@ # am--include-marker
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/handlers.Po@am__quote@ # am--include-marker
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash_tests.Po@am__quote@ # am--include-marker
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash_tests.Po@am__quote@ # am--include-marker
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memcheck.Po@am__quote@ # am--include-marker
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memcheck.Po@am__quote@ # am--include-marker
|
||||||
@@ -1184,6 +1189,7 @@ distclean: distclean-recursive
|
|||||||
-rm -f ./$(DEPDIR)/chardata.Po
|
-rm -f ./$(DEPDIR)/chardata.Po
|
||||||
-rm -f ./$(DEPDIR)/common.Po
|
-rm -f ./$(DEPDIR)/common.Po
|
||||||
-rm -f ./$(DEPDIR)/dummy.Po
|
-rm -f ./$(DEPDIR)/dummy.Po
|
||||||
|
-rm -f ./$(DEPDIR)/entities_tests.Po
|
||||||
-rm -f ./$(DEPDIR)/handlers.Po
|
-rm -f ./$(DEPDIR)/handlers.Po
|
||||||
-rm -f ./$(DEPDIR)/hash_tests.Po
|
-rm -f ./$(DEPDIR)/hash_tests.Po
|
||||||
-rm -f ./$(DEPDIR)/memcheck.Po
|
-rm -f ./$(DEPDIR)/memcheck.Po
|
||||||
@@ -1246,6 +1252,7 @@ maintainer-clean: maintainer-clean-recursive
|
|||||||
-rm -f ./$(DEPDIR)/chardata.Po
|
-rm -f ./$(DEPDIR)/chardata.Po
|
||||||
-rm -f ./$(DEPDIR)/common.Po
|
-rm -f ./$(DEPDIR)/common.Po
|
||||||
-rm -f ./$(DEPDIR)/dummy.Po
|
-rm -f ./$(DEPDIR)/dummy.Po
|
||||||
|
-rm -f ./$(DEPDIR)/entities_tests.Po
|
||||||
-rm -f ./$(DEPDIR)/handlers.Po
|
-rm -f ./$(DEPDIR)/handlers.Po
|
||||||
-rm -f ./$(DEPDIR)/hash_tests.Po
|
-rm -f ./$(DEPDIR)/hash_tests.Po
|
||||||
-rm -f ./$(DEPDIR)/memcheck.Po
|
-rm -f ./$(DEPDIR)/memcheck.Po
|
||||||
|
|||||||
@@ -475,6 +475,37 @@ START_TEST(test_amplification_isolated_external_parser) {
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_amplification_reset_neutrality) {
|
||||||
|
// Speed up the test, chunk size expected to not matter in this test
|
||||||
|
if (g_chunkSize != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char *const doc
|
||||||
|
= "<!DOCTYPE r [<!ENTITY e 'general entity'>]><r>&e;</r>";
|
||||||
|
XML_Parser parser = XML_ParserCreate(NULL);
|
||||||
|
assert_true(XML_SetPropertyDouble(
|
||||||
|
parser, XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION, 1.0)
|
||||||
|
== XML_PROP_ERROR_NONE);
|
||||||
|
assert_true(XML_SetPropertyUInt64(
|
||||||
|
parser, XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD, 0)
|
||||||
|
== XML_PROP_ERROR_NONE);
|
||||||
|
|
||||||
|
assert_true(_XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc),
|
||||||
|
/*isFinal=*/XML_TRUE)
|
||||||
|
== XML_STATUS_ERROR);
|
||||||
|
assert_true(XML_GetErrorCode(parser) == XML_ERROR_AMPLIFICATION_LIMIT_BREACH);
|
||||||
|
|
||||||
|
assert_true(XML_ParserReset(parser, NULL) == XML_STATUS_OK);
|
||||||
|
|
||||||
|
assert_true(_XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc),
|
||||||
|
/*isFinal=*/XML_TRUE)
|
||||||
|
== XML_STATUS_ERROR);
|
||||||
|
assert_true(XML_GetErrorCode(parser) == XML_ERROR_AMPLIFICATION_LIMIT_BREACH);
|
||||||
|
|
||||||
|
XML_ParserFree(parser);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
#endif // XML_GE == 1
|
#endif // XML_GE == 1
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -491,6 +522,7 @@ make_accounting_test_case(Suite *s) {
|
|||||||
tcase_add_test(tc_accounting, test_helper_unsigned_char_to_printable);
|
tcase_add_test(tc_accounting, test_helper_unsigned_char_to_printable);
|
||||||
tcase_add_test__ifdef_xml_dtd(tc_accounting,
|
tcase_add_test__ifdef_xml_dtd(tc_accounting,
|
||||||
test_amplification_isolated_external_parser);
|
test_amplification_isolated_external_parser);
|
||||||
|
tcase_add_test(tc_accounting, test_amplification_reset_neutrality);
|
||||||
#else
|
#else
|
||||||
UNUSED_P(s);
|
UNUSED_P(s);
|
||||||
#endif /* XML_GE == 1 */
|
#endif /* XML_GE == 1 */
|
||||||
|
|||||||
@@ -2330,6 +2330,47 @@ START_TEST(test_alloc_tracker_api_float_round_trip) {
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_alloc_tracker_reset_neutrality) {
|
||||||
|
// Speed up the test, chunk size expected to not matter in this test
|
||||||
|
if (g_chunkSize != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
XML_Parser parser = XML_ParserCreate(NULL);
|
||||||
|
|
||||||
|
const char *const small = "<hello/>";
|
||||||
|
|
||||||
|
// Create a document that drives `parser->m_alloc_tracker.bytesAllocated`
|
||||||
|
// towards the activation threshold
|
||||||
|
#if XML_GE == 1
|
||||||
|
const size_t bigSizeBytes
|
||||||
|
= (size_t)(1.1f * EXPAT_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT);
|
||||||
|
const char *const before = "<doc a='";
|
||||||
|
const char *const after = "'/>";
|
||||||
|
char *const big = malloc(bigSizeBytes);
|
||||||
|
assert_true(big != NULL);
|
||||||
|
memset(big, 'X', bigSizeBytes);
|
||||||
|
memcpy(big, before, strlen(before)); // without zero terminator
|
||||||
|
strcpy(big + (bigSizeBytes - strlen(after) - 1),
|
||||||
|
after); // with zero terminator
|
||||||
|
assert_true(strlen(big) == bigSizeBytes - 1); // self-test
|
||||||
|
|
||||||
|
assert_true(
|
||||||
|
_XML_Parse_SINGLE_BYTES(parser, big, strlen(big), /*isFinal=*/XML_TRUE)
|
||||||
|
== XML_STATUS_OK);
|
||||||
|
|
||||||
|
free(big);
|
||||||
|
#endif // XML_GE == 1
|
||||||
|
|
||||||
|
XML_ParserReset(parser, NULL);
|
||||||
|
|
||||||
|
assert_true(_XML_Parse_SINGLE_BYTES(parser, small, strlen(small),
|
||||||
|
/*isFinal=*/XML_TRUE)
|
||||||
|
== XML_STATUS_OK);
|
||||||
|
|
||||||
|
XML_ParserFree(parser);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_mem_api_cycle) {
|
START_TEST(test_mem_api_cycle) {
|
||||||
XML_Parser parser = XML_ParserCreate(NULL);
|
XML_Parser parser = XML_ParserCreate(NULL);
|
||||||
|
|
||||||
@@ -2445,6 +2486,7 @@ make_alloc_test_case(Suite *s) {
|
|||||||
tcase_add_test__if_xml_ge(tc_alloc, test_alloc_tracker_getbuffer_unlimited);
|
tcase_add_test__if_xml_ge(tc_alloc, test_alloc_tracker_getbuffer_unlimited);
|
||||||
tcase_add_test__if_xml_ge(tc_alloc, test_alloc_tracker_api);
|
tcase_add_test__if_xml_ge(tc_alloc, test_alloc_tracker_api);
|
||||||
tcase_add_test__if_xml_ge(tc_alloc, test_alloc_tracker_api_float_round_trip);
|
tcase_add_test__if_xml_ge(tc_alloc, test_alloc_tracker_api_float_round_trip);
|
||||||
|
tcase_add_test__if_xml_ge(tc_alloc, test_alloc_tracker_reset_neutrality);
|
||||||
|
|
||||||
tcase_add_test(tc_alloc, test_mem_api_cycle);
|
tcase_add_test(tc_alloc, test_mem_api_cycle);
|
||||||
tcase_add_test__if_xml_ge(tc_alloc, test_mem_api_unlimited);
|
tcase_add_test__if_xml_ge(tc_alloc, test_mem_api_unlimited);
|
||||||
|
|||||||
+48
-15
@@ -27,6 +27,7 @@
|
|||||||
Copyright (c) 2026 Afonso Januário <afonso-januario@hotmail.com>
|
Copyright (c) 2026 Afonso Januário <afonso-januario@hotmail.com>
|
||||||
Copyright (c) 2026 Braian Plaku <braianplaku@gmail.com>
|
Copyright (c) 2026 Braian Plaku <braianplaku@gmail.com>
|
||||||
Copyright (c) 2026 Filippo Tedeschi <filippotedeschi98@gmail.com>
|
Copyright (c) 2026 Filippo Tedeschi <filippotedeschi98@gmail.com>
|
||||||
|
Copyright (c) 2026 Alexander Bluhm <alexander.bluhm@gmx.net>
|
||||||
Licensed under the MIT license:
|
Licensed under the MIT license:
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
@@ -208,7 +209,8 @@ START_TEST(test_hash_collision) {
|
|||||||
* tests invoked from qa.sh usually provide a hash collision, but
|
* tests invoked from qa.sh usually provide a hash collision, but
|
||||||
* not always. This is an attempt to provide insurance.
|
* not always. This is an attempt to provide insurance.
|
||||||
*/
|
*/
|
||||||
#define COLLIDING_HASH_SALT (unsigned long)SIP_ULL(0xffffffffU, 0xff99fc90U)
|
const uint8_t entropy[16] = {0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0x90, 0xfc, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||||
const char *text
|
const char *text
|
||||||
= "<doc>\n"
|
= "<doc>\n"
|
||||||
"<a1/><a2/><a3/><a4/><a5/><a6/><a7/><a8/>\n"
|
"<a1/><a2/><a3/><a4/><a5/><a6/><a7/><a8/>\n"
|
||||||
@@ -219,13 +221,12 @@ START_TEST(test_hash_collision) {
|
|||||||
"<d8>This triggers the table growth and collides with b2</d8>\n"
|
"<d8>This triggers the table growth and collides with b2</d8>\n"
|
||||||
"</doc>\n";
|
"</doc>\n";
|
||||||
|
|
||||||
xmlSetHashSalt(g_parser, COLLIDING_HASH_SALT);
|
XML_SetHashSalt16Bytes(g_parser, entropy);
|
||||||
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
|
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
|
||||||
== XML_STATUS_ERROR)
|
== XML_STATUS_ERROR)
|
||||||
xml_failure(g_parser);
|
xml_failure(g_parser);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
#undef COLLIDING_HASH_SALT
|
|
||||||
|
|
||||||
START_TEST(test_hash_salt_setter) {
|
START_TEST(test_hash_salt_setter) {
|
||||||
const uint8_t entropy[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
const uint8_t entropy[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
||||||
@@ -251,6 +252,29 @@ START_TEST(test_hash_salt_setter) {
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_hash_salt_ulong) {
|
||||||
|
const unsigned long salt = 0x12345678;
|
||||||
|
XML_Parser parser = XML_ParserCreate(NULL);
|
||||||
|
|
||||||
|
// NULL parser should be rejected
|
||||||
|
assert_true(xmlSetHashSalt(NULL, salt) == 0);
|
||||||
|
|
||||||
|
// salt 0 is ignored, but accepted
|
||||||
|
assert_true(xmlSetHashSalt(parser, 0) == 1);
|
||||||
|
|
||||||
|
// Setting should be allowed more than once
|
||||||
|
assert_true(xmlSetHashSalt(parser, salt) == 1);
|
||||||
|
assert_true(xmlSetHashSalt(parser, salt) == 1);
|
||||||
|
|
||||||
|
// But not after parsing has started
|
||||||
|
assert_true(XML_Parse(parser, "", 0, XML_FALSE /* isFinal */)
|
||||||
|
== XML_STATUS_OK);
|
||||||
|
assert_true(xmlSetHashSalt(parser, salt) == 0);
|
||||||
|
|
||||||
|
XML_ParserFree(parser);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
/* Regression test for SF bug #491986. */
|
/* Regression test for SF bug #491986. */
|
||||||
START_TEST(test_danish_latin1) {
|
START_TEST(test_danish_latin1) {
|
||||||
const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
|
const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
|
||||||
@@ -2743,12 +2767,13 @@ END_TEST
|
|||||||
|
|
||||||
/* Test foreign DTD handling */
|
/* Test foreign DTD handling */
|
||||||
START_TEST(test_set_foreign_dtd) {
|
START_TEST(test_set_foreign_dtd) {
|
||||||
|
const uint8_t entropy[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8};
|
||||||
const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n";
|
const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n";
|
||||||
const char *text2 = "<doc>&entity;</doc>";
|
const char *text2 = "<doc>&entity;</doc>";
|
||||||
ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
|
ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
|
||||||
|
|
||||||
/* Check hash salt is passed through too */
|
/* Check hash salt is passed through too */
|
||||||
xmlSetHashSalt(g_parser, 0x12345678);
|
XML_SetHashSalt16Bytes(g_parser, entropy);
|
||||||
XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
|
XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
|
||||||
XML_SetUserData(g_parser, &test_data);
|
XML_SetUserData(g_parser, &test_data);
|
||||||
XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
|
XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
|
||||||
@@ -2767,7 +2792,7 @@ START_TEST(test_set_foreign_dtd) {
|
|||||||
!= XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
|
!= XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
|
||||||
fail("Failed to reject late foreign DTD setting");
|
fail("Failed to reject late foreign DTD setting");
|
||||||
/* Ditto for the hash salt */
|
/* Ditto for the hash salt */
|
||||||
if (xmlSetHashSalt(g_parser, 0x23456789))
|
if (XML_SetHashSalt16Bytes(g_parser, entropy))
|
||||||
fail("Failed to reject late hash salt change");
|
fail("Failed to reject late hash salt change");
|
||||||
|
|
||||||
/* Now finish the parse */
|
/* Now finish the parse */
|
||||||
@@ -2812,13 +2837,14 @@ END_TEST
|
|||||||
|
|
||||||
/* Test foreign DTD use with a doctype */
|
/* Test foreign DTD use with a doctype */
|
||||||
START_TEST(test_foreign_dtd_with_doctype) {
|
START_TEST(test_foreign_dtd_with_doctype) {
|
||||||
|
const uint8_t entropy[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8};
|
||||||
const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"
|
const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"
|
||||||
"<!DOCTYPE doc [<!ENTITY entity 'hello world'>]>\n";
|
"<!DOCTYPE doc [<!ENTITY entity 'hello world'>]>\n";
|
||||||
const char *text2 = "<doc>&entity;</doc>";
|
const char *text2 = "<doc>&entity;</doc>";
|
||||||
ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
|
ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
|
||||||
|
|
||||||
/* Check hash salt is passed through too */
|
/* Check hash salt is passed through too */
|
||||||
xmlSetHashSalt(g_parser, 0x12345678);
|
XML_SetHashSalt16Bytes(g_parser, entropy);
|
||||||
XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
|
XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
|
||||||
XML_SetUserData(g_parser, &test_data);
|
XML_SetUserData(g_parser, &test_data);
|
||||||
XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
|
XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
|
||||||
@@ -2837,7 +2863,7 @@ START_TEST(test_foreign_dtd_with_doctype) {
|
|||||||
!= XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
|
!= XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
|
||||||
fail("Failed to reject late foreign DTD setting");
|
fail("Failed to reject late foreign DTD setting");
|
||||||
/* Ditto for the hash salt */
|
/* Ditto for the hash salt */
|
||||||
if (xmlSetHashSalt(g_parser, 0x23456789))
|
if (XML_SetHashSalt16Bytes(g_parser, entropy))
|
||||||
fail("Failed to reject late hash salt change");
|
fail("Failed to reject late hash salt change");
|
||||||
|
|
||||||
/* Now finish the parse */
|
/* Now finish the parse */
|
||||||
@@ -4402,17 +4428,23 @@ START_TEST(test_attribute_enum_value) {
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
/* Slightly bizarrely, the library seems to silently ignore entity
|
|
||||||
* definitions for predefined entities, even when they are wrong. The
|
|
||||||
* language of the XML 1.0 spec is somewhat unhelpful as to what ought
|
|
||||||
* to happen, so this is currently treated as acceptable.
|
|
||||||
*/
|
|
||||||
START_TEST(test_predefined_entity_redefinition) {
|
START_TEST(test_predefined_entity_redefinition) {
|
||||||
|
// NOTE: This violates XML 1.0 fourth edition section
|
||||||
|
// "4.6 Predefined Entities" (that demands rejection of bad
|
||||||
|
// redefinitions) only for backwards-compatibility reasons.
|
||||||
const char *text = "<!DOCTYPE doc [\n"
|
const char *text = "<!DOCTYPE doc [\n"
|
||||||
"<!ENTITY apos 'foo'>\n"
|
" <!ENTITY amp 'bad'>\n"
|
||||||
|
" <!ENTITY apos 'bad'>\n"
|
||||||
|
" <!ENTITY gt 'bad'>\n"
|
||||||
|
" <!ENTITY lt 'bad'>\n"
|
||||||
|
" <!ENTITY quot 'bad'>\n"
|
||||||
"]>\n"
|
"]>\n"
|
||||||
"<doc>'</doc>";
|
"<doc>&'><"</doc>";
|
||||||
run_character_check(text, XCS("'"));
|
run_character_check(text, XCS("&"
|
||||||
|
"'"
|
||||||
|
">"
|
||||||
|
"<"
|
||||||
|
"\""));
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
@@ -7154,6 +7186,7 @@ make_basic_test_case(Suite *s) {
|
|||||||
tcase_add_test(tc_basic, test_nobom_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_collision);
|
||||||
tcase_add_test(tc_basic, test_hash_salt_setter);
|
tcase_add_test(tc_basic, test_hash_salt_setter);
|
||||||
|
tcase_add_test(tc_basic, test_hash_salt_ulong);
|
||||||
tcase_add_test(tc_basic, test_illegal_utf8);
|
tcase_add_test(tc_basic, test_illegal_utf8);
|
||||||
tcase_add_test(tc_basic, test_utf8_auto_align);
|
tcase_add_test(tc_basic, test_utf8_auto_align);
|
||||||
tcase_add_test(tc_basic, test_utf16);
|
tcase_add_test(tc_basic, test_utf16);
|
||||||
|
|||||||
@@ -339,3 +339,15 @@ portable_strndup(const char *s, size_t n) {
|
|||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XML_Char *
|
||||||
|
xcsdup_str(const char *s) {
|
||||||
|
const size_t len = strlen(s);
|
||||||
|
XML_Char *const buf = calloc(len + /*terminator*/ 1, sizeof(XML_Char));
|
||||||
|
if (! buf)
|
||||||
|
return NULL;
|
||||||
|
XML_Char *t = buf;
|
||||||
|
while (*s)
|
||||||
|
*t++ = *s++;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
@@ -140,4 +140,6 @@ extern void *duff_reallocator(void *ptr, size_t size);
|
|||||||
|
|
||||||
extern char *portable_strndup(const char *s, size_t n);
|
extern char *portable_strndup(const char *s, size_t n);
|
||||||
|
|
||||||
|
extern XML_Char *xcsdup_str(const char *s);
|
||||||
|
|
||||||
#endif /* XML_COMMON_H */
|
#endif /* XML_COMMON_H */
|
||||||
@@ -45,6 +45,9 @@
|
|||||||
#ifndef XML_DUMMY_H
|
#ifndef XML_DUMMY_H
|
||||||
#define XML_DUMMY_H
|
#define XML_DUMMY_H
|
||||||
|
|
||||||
|
#include "expat.h" // for XML_Content
|
||||||
|
#include "expat_external.h" // for XMLCALL, XML_Char
|
||||||
|
|
||||||
#define DUMMY_START_DOCTYPE_HANDLER_FLAG (1UL << 0)
|
#define DUMMY_START_DOCTYPE_HANDLER_FLAG (1UL << 0)
|
||||||
#define DUMMY_END_DOCTYPE_HANDLER_FLAG (1UL << 1)
|
#define DUMMY_END_DOCTYPE_HANDLER_FLAG (1UL << 1)
|
||||||
#define DUMMY_ENTITY_DECL_HANDLER_FLAG (1UL << 2)
|
#define DUMMY_ENTITY_DECL_HANDLER_FLAG (1UL << 2)
|
||||||
|
|||||||
@@ -0,0 +1,246 @@
|
|||||||
|
/* Unit tests related to internal handling of entities
|
||||||
|
__ __ _
|
||||||
|
___\ \/ /_ __ __ _| |_
|
||||||
|
/ _ \\ /| '_ \ / _` | __|
|
||||||
|
| __// \| |_) | (_| | |_
|
||||||
|
\___/_/\_\ .__/ \__,_|\__|
|
||||||
|
|_| XML parser
|
||||||
|
|
||||||
|
Copyright (c) 2026 Sebastian Pipping <[email protected]>
|
||||||
|
Licensed under the MIT license:
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||||
|
persons to whom the Software is furnished to do so, subject to the
|
||||||
|
following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||||
|
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "entities_tests.h"
|
||||||
|
#include "expat_config.h" // for XML_GE
|
||||||
|
|
||||||
|
#include "ascii.h" // for ASCII_*
|
||||||
|
#include "common.h" // for g_chunkSize, xcsdup_str
|
||||||
|
#include "entities.h" // for isCDataCommentOrPIStart, isPredefinedEntityName, ..
|
||||||
|
#include "xmltok.h" // for XML_TOK_*
|
||||||
|
#include "xcs.h" // for xcslen
|
||||||
|
|
||||||
|
#include <string.h> // for strlen
|
||||||
|
|
||||||
|
static void
|
||||||
|
assert_entity_expanded_size_equals(XML_Parser parser, const char *text,
|
||||||
|
XmlBigCount expectedExpandedSize);
|
||||||
|
|
||||||
|
static void assert_predefined_entity_name_match(const char *text,
|
||||||
|
int expectedCharacter);
|
||||||
|
|
||||||
|
static ENTITY *createGeneralEntityWithText(const char *text);
|
||||||
|
|
||||||
|
START_TEST(test_is_cdata_comment_or_pi_start) {
|
||||||
|
// Speed up the test, chunk size expected to not matter in this test
|
||||||
|
if (g_chunkSize != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
XML_Char *const cdataOpen = xcsdup_str("<![CDATA[");
|
||||||
|
XML_Char *const commentOpen = xcsdup_str("<!--");
|
||||||
|
XML_Char *const piOpen = xcsdup_str("<?");
|
||||||
|
|
||||||
|
#if XML_GE == 1
|
||||||
|
const size_t expectedCdataOpenLen = xcslen(cdataOpen);
|
||||||
|
const size_t expectedCommentOpenLen = xcslen(commentOpen);
|
||||||
|
const size_t expectedPiOpenLen = xcslen(piOpen);
|
||||||
|
|
||||||
|
size_t actualCdataOpenLen = 0;
|
||||||
|
assert_true(isCDataCommentOrPIStart(cdataOpen, expectedCdataOpenLen,
|
||||||
|
&actualCdataOpenLen)
|
||||||
|
== XML_TOK_CDATA_SECT_OPEN);
|
||||||
|
assert_true(actualCdataOpenLen == expectedCdataOpenLen);
|
||||||
|
|
||||||
|
size_t actualCommentOpenLen = 0;
|
||||||
|
assert_true(isCDataCommentOrPIStart(commentOpen, expectedCommentOpenLen,
|
||||||
|
&actualCommentOpenLen)
|
||||||
|
== XML_TOK_COMMENT);
|
||||||
|
assert_true(actualCommentOpenLen == expectedCommentOpenLen);
|
||||||
|
|
||||||
|
size_t actualPiOpenLen = 0;
|
||||||
|
assert_true(
|
||||||
|
isCDataCommentOrPIStart(piOpen, expectedPiOpenLen, &actualPiOpenLen)
|
||||||
|
== XML_TOK_PI);
|
||||||
|
assert_true(actualCdataOpenLen == expectedCdataOpenLen);
|
||||||
|
|
||||||
|
size_t dummy = 0;
|
||||||
|
assert_true(isCDataCommentOrPIStart(piOpen, 0, &dummy) == XML_TOK_INVALID);
|
||||||
|
assert_true(isCDataCommentOrPIStart(piOpen, 1, &dummy) == XML_TOK_INVALID);
|
||||||
|
#endif // XML_GE == 1
|
||||||
|
|
||||||
|
free(cdataOpen);
|
||||||
|
free(commentOpen);
|
||||||
|
free(piOpen);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
static void
|
||||||
|
assert_predefined_entity_name_match(const char *text, int expectedCharacter) {
|
||||||
|
XML_Char *const xcsText = xcsdup_str(text);
|
||||||
|
assert_true(xcsText != NULL);
|
||||||
|
|
||||||
|
#if XML_GE == 1
|
||||||
|
assert_true(isPredefinedEntityName(xcsText, xcslen(xcsText))
|
||||||
|
== expectedCharacter);
|
||||||
|
#else
|
||||||
|
UNUSED_P(expectedCharacter);
|
||||||
|
#endif // XML_GE == 1
|
||||||
|
|
||||||
|
free(xcsText);
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(test_is_predefined_entity_name) {
|
||||||
|
// Speed up the test, chunk size expected to not matter in this test
|
||||||
|
if (g_chunkSize != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
assert_predefined_entity_name_match("amp", ASCII_AMP);
|
||||||
|
assert_predefined_entity_name_match("apos", ASCII_APOS);
|
||||||
|
assert_predefined_entity_name_match("gt", ASCII_GT);
|
||||||
|
assert_predefined_entity_name_match("lt", ASCII_LT);
|
||||||
|
assert_predefined_entity_name_match("quot", ASCII_QUOT);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
static ENTITY *
|
||||||
|
createGeneralEntityWithText(const char *text) {
|
||||||
|
assert_true(text != NULL);
|
||||||
|
|
||||||
|
ENTITY *const entity = calloc(1, sizeof(ENTITY));
|
||||||
|
assert_true(entity != NULL);
|
||||||
|
|
||||||
|
entity->textPtr = xcsdup_str(text);
|
||||||
|
assert_true(entity->textPtr != NULL);
|
||||||
|
|
||||||
|
entity->textLen = xcslen(entity->textPtr);
|
||||||
|
|
||||||
|
#if XML_GE == 1
|
||||||
|
entity->scanPtr = entity->textPtr;
|
||||||
|
#endif // XML_GE == 1
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
assert_entity_expanded_size_equals(XML_Parser parser, const char *text,
|
||||||
|
XmlBigCount expectedExpandedSize) {
|
||||||
|
// Turn `text` into a general entity with that text
|
||||||
|
ENTITY *const entity = createGeneralEntityWithText(text);
|
||||||
|
|
||||||
|
#if XML_GE == 1
|
||||||
|
XmlBigCount actualExpandedSize = 0;
|
||||||
|
assert_true(scanEntityText(parser, entity, &entity->scanPtr,
|
||||||
|
&actualExpandedSize, NULL)
|
||||||
|
== ENTITY_SCAN_COMPLETE);
|
||||||
|
assert_true(entity->scanPtr == entity->textPtr + entity->textLen);
|
||||||
|
assert_true(actualExpandedSize == expectedExpandedSize);
|
||||||
|
#else
|
||||||
|
UNUSED_P(parser);
|
||||||
|
UNUSED_P(expectedExpandedSize);
|
||||||
|
#endif // XML_GE == 1
|
||||||
|
|
||||||
|
free((XML_Char *)entity->textPtr);
|
||||||
|
free(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(test_scan_entity_text) {
|
||||||
|
// Speed up the test, chunk size expected to not matter in this test
|
||||||
|
if (g_chunkSize != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char *const doc = "<!DOCTYPE doc[\n"
|
||||||
|
" <!ENTITY ten '123456789a'>\n"
|
||||||
|
"]>\n"
|
||||||
|
"<doc/>";
|
||||||
|
XML_Parser parser = XML_ParserCreate(NULL);
|
||||||
|
assert_true(parser != NULL);
|
||||||
|
assert_true(_XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc),
|
||||||
|
/*isFinal=*/XML_TRUE)
|
||||||
|
== XML_STATUS_OK);
|
||||||
|
|
||||||
|
assert_entity_expanded_size_equals(parser, "", 0);
|
||||||
|
assert_entity_expanded_size_equals(parser, "123", 3);
|
||||||
|
assert_entity_expanded_size_equals(parser, "&'><"",
|
||||||
|
strlen("&'><"") + 5);
|
||||||
|
assert_entity_expanded_size_equals(parser, "&undefined;",
|
||||||
|
strlen("&undefined;"));
|
||||||
|
|
||||||
|
// Extract entity "ten" and set its `.expandedSize` so that we can scan text
|
||||||
|
// that refers to "&ten;" without blocking
|
||||||
|
#if XML_GE == 1
|
||||||
|
ENTITY *entityTen = NULL;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
ENTITY *const entityReferencingTen
|
||||||
|
= createGeneralEntityWithText("referencing &ten;");
|
||||||
|
assert_true(entityReferencingTen != NULL);
|
||||||
|
|
||||||
|
#if XML_GE == 1
|
||||||
|
assert_true(scanEntityText(parser, entityReferencingTen,
|
||||||
|
&entityReferencingTen->scanPtr,
|
||||||
|
&entityReferencingTen->expandedSize, &entityTen)
|
||||||
|
== ENTITY_SCAN_BLOCKED);
|
||||||
|
assert_true(entityTen != NULL);
|
||||||
|
assert_true(entityReferencingTen->expandedSize == strlen("referencing "));
|
||||||
|
assert_true(entityReferencingTen->scanPtr
|
||||||
|
== entityReferencingTen->textPtr
|
||||||
|
+ entityReferencingTen->expandedSize);
|
||||||
|
XML_Char *const ten = xcsdup_str("ten");
|
||||||
|
assert_true(xcscmp(entityTen->name, ten) == 0);
|
||||||
|
free(ten);
|
||||||
|
|
||||||
|
entityTen->expandedSize = 10; // which makes it stop being a blocker
|
||||||
|
#endif // XML_GE == 1
|
||||||
|
|
||||||
|
free((XML_Char *)entityReferencingTen->textPtr);
|
||||||
|
free(entityReferencingTen);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_entity_expanded_size_equals(parser, "&ten;",
|
||||||
|
strlen("&ten;") + strlen("123456789a"));
|
||||||
|
assert_entity_expanded_size_equals(
|
||||||
|
parser, "[&ten;&ten;|&ten;]",
|
||||||
|
3 * (strlen("&ten;") + strlen("123456789a")) + strlen("[|]"));
|
||||||
|
|
||||||
|
// Cases where no entities should be recognized
|
||||||
|
assert_entity_expanded_size_equals(
|
||||||
|
parser, "<![CDATA[&ten;]]><!--&ten;--><?php &ten;?>",
|
||||||
|
strlen("<![CDATA[&ten;]]><!--&ten;--><?php &ten;?>"));
|
||||||
|
assert_entity_expanded_size_equals(parser, "<![CDATA[&ten;",
|
||||||
|
strlen("<![CDATA[&ten;"));
|
||||||
|
assert_entity_expanded_size_equals(parser, "<!--&ten;", strlen("<!--&ten;"));
|
||||||
|
assert_entity_expanded_size_equals(parser, "<?php &ten;",
|
||||||
|
strlen("<?php &ten;"));
|
||||||
|
|
||||||
|
XML_ParserFree(parser);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
void
|
||||||
|
make_entities_test_case(Suite *s) {
|
||||||
|
TCase *const tc_entities = tcase_create("entities tests");
|
||||||
|
suite_add_tcase(s, tc_entities);
|
||||||
|
tcase_add_test(tc_entities, test_is_cdata_comment_or_pi_start);
|
||||||
|
tcase_add_test(tc_entities, test_is_predefined_entity_name);
|
||||||
|
tcase_add_test(tc_entities, test_scan_entity_text);
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/* Unit tests related to internal handling of entities
|
||||||
|
__ __ _
|
||||||
|
___\ \/ /_ __ __ _| |_
|
||||||
|
/ _ \\ /| '_ \ / _` | __|
|
||||||
|
| __// \| |_) | (_| | |_
|
||||||
|
\___/_/\_\ .__/ \__,_|\__|
|
||||||
|
|_| XML parser
|
||||||
|
|
||||||
|
Copyright (c) 2026 Sebastian Pipping <[email protected]>
|
||||||
|
Licensed under the MIT license:
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||||
|
persons to whom the Software is furnished to do so, subject to the
|
||||||
|
following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||||
|
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XML_ENTITIES_TESTS_H
|
||||||
|
#define XML_ENTITIES_TESTS_H
|
||||||
|
|
||||||
|
#include "minicheck.h"
|
||||||
|
|
||||||
|
extern void make_entities_test_case(Suite *s);
|
||||||
|
|
||||||
|
#endif /* XML_ENTITIES_TESTS_H */
|
||||||
@@ -51,6 +51,7 @@
|
|||||||
#include "expat_config.h"
|
#include "expat_config.h"
|
||||||
|
|
||||||
#include "expat.h"
|
#include "expat.h"
|
||||||
|
#include "chardata.h"
|
||||||
|
|
||||||
/* Variable holding the expected handler userData */
|
/* Variable holding the expected handler userData */
|
||||||
extern const void *g_handler_data;
|
extern const void *g_handler_data;
|
||||||
|
|||||||
+180
-1
@@ -25,6 +25,7 @@
|
|||||||
Copyright (c) 2026 Evgeny Kotkov <[email protected]>
|
Copyright (c) 2026 Evgeny Kotkov <[email protected]>
|
||||||
Copyright (c) 2026 Darren Carreras <[email protected]>
|
Copyright (c) 2026 Darren Carreras <[email protected]>
|
||||||
Copyright (c) 2026 Junki Lee <[email protected]>
|
Copyright (c) 2026 Junki Lee <[email protected]>
|
||||||
|
Copyright (c) 2026 Pu Cheng <[email protected]>
|
||||||
Licensed under the MIT license:
|
Licensed under the MIT license:
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
@@ -60,6 +61,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "dummy.h" // for dummy_start_element
|
||||||
#include "expat.h"
|
#include "expat.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "minicheck.h"
|
#include "minicheck.h"
|
||||||
@@ -222,7 +224,7 @@ START_TEST(test_misc_version) {
|
|||||||
if (! versions_equal(&read_version, &parsed_version))
|
if (! versions_equal(&read_version, &parsed_version))
|
||||||
fail("Version mismatch");
|
fail("Version mismatch");
|
||||||
|
|
||||||
if (xcscmp(version_text, XCS("expat_2.9.0"))
|
if (xcscmp(version_text, XCS("expat_2.10.0"))
|
||||||
!= 0) /* needs bump on releases */
|
!= 0) /* needs bump on releases */
|
||||||
fail("XML_*_VERSION in expat.h out of sync?\n");
|
fail("XML_*_VERSION in expat.h out of sync?\n");
|
||||||
}
|
}
|
||||||
@@ -591,6 +593,26 @@ START_TEST(test_misc_stopparser_rejects_unstarted_parser) {
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
static void *
|
||||||
|
nonzero_filling_malloc(size_t size) {
|
||||||
|
void *const ptr = malloc(size);
|
||||||
|
if (ptr != NULL)
|
||||||
|
memset(ptr, 0xA5, size);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(test_misc_parsing_status_of_unstarted_parser) {
|
||||||
|
XML_Memory_Handling_Suite memsuite = {nonzero_filling_malloc, realloc, free};
|
||||||
|
XML_Parser parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
|
||||||
|
assert_true(parser != NULL);
|
||||||
|
XML_ParsingStatus status = {.parsing = XML_PARSING, .finalBuffer = XML_TRUE};
|
||||||
|
XML_GetParsingStatus(parser, &status);
|
||||||
|
assert_true(status.parsing == XML_INITIALIZED);
|
||||||
|
assert_true(status.finalBuffer == XML_FALSE);
|
||||||
|
XML_ParserFree(parser);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
/* Adaptation of accumulate_characters that takes ExtHdlrData input to work with
|
/* Adaptation of accumulate_characters that takes ExtHdlrData input to work with
|
||||||
* test_renter_loop_finite_content below */
|
* test_renter_loop_finite_content below */
|
||||||
void XMLCALL
|
void XMLCALL
|
||||||
@@ -1024,6 +1046,159 @@ START_TEST(test_misc_input_2gb) {
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
static void
|
||||||
|
dummy_start_doctype(void *userData, const XML_Char *name,
|
||||||
|
const XML_Char *systemId, const XML_Char *publicId,
|
||||||
|
int has_internal_subset) {
|
||||||
|
UNUSED_P(userData);
|
||||||
|
UNUSED_P(name);
|
||||||
|
UNUSED_P(systemId);
|
||||||
|
UNUSED_P(publicId);
|
||||||
|
UNUSED_P(has_internal_subset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
reset_start_doctype_decl_handler_not_standalone(void *userData) {
|
||||||
|
XML_Parser parser = userData;
|
||||||
|
XML_SetStartDoctypeDeclHandler(parser, NULL);
|
||||||
|
return XML_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(test_misc_start_doctype_decl_handler_reset) {
|
||||||
|
// Speed up the test, chunk size expected to not matter in this test
|
||||||
|
if (g_chunkSize != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char *const doc = "<!DOCTYPE r SYSTEM \"s\"><r/>";
|
||||||
|
|
||||||
|
XML_Parser parser = XML_ParserCreate(NULL);
|
||||||
|
|
||||||
|
XML_SetUserData(parser, parser);
|
||||||
|
XML_SetStartDoctypeDeclHandler(parser, dummy_start_doctype);
|
||||||
|
XML_SetNotStandaloneHandler(parser,
|
||||||
|
reset_start_doctype_decl_handler_not_standalone);
|
||||||
|
|
||||||
|
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_storeatts_attssize_allocation) {
|
||||||
|
// Speed up the test, chunk size expected to not matter in this test
|
||||||
|
if (g_chunkSize != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// NOTE: This has 17 attributes defined because `INIT_ATTS_SIZE` is 16.
|
||||||
|
// Array size is calculated as
|
||||||
|
// parser->m_attsSize = n + nDefaultAtts + INIT_ATTS_SIZE
|
||||||
|
// when I expected it would have needed to be
|
||||||
|
// parser->m_attsSize = n + 2 * nDefaultAtts + INIT_ATTS_SIZE .
|
||||||
|
// Please see the in-code comments in `storeAtts` for the black magic
|
||||||
|
// that makes it work nonetheless. The same memory is used as an array
|
||||||
|
// of `ATTRIBUTE` elements first, and then as an array of `XML_Char *`
|
||||||
|
// elements after.
|
||||||
|
const char *const doc = "<!DOCTYPE doc [\n"
|
||||||
|
" <!ELEMENT doc EMPTY>\n"
|
||||||
|
" <!ATTLIST doc\n"
|
||||||
|
" a01 CDATA '01'\n"
|
||||||
|
" a02 CDATA '02'\n"
|
||||||
|
" a03 CDATA '03'\n"
|
||||||
|
" a04 CDATA '04'\n"
|
||||||
|
" a05 CDATA '05'\n"
|
||||||
|
" a06 CDATA '06'\n"
|
||||||
|
" a07 CDATA '07'\n"
|
||||||
|
" a08 CDATA '08'\n"
|
||||||
|
" a09 CDATA '09'\n"
|
||||||
|
" a10 CDATA '10'\n"
|
||||||
|
" a11 CDATA '11'\n"
|
||||||
|
" a12 CDATA '12'\n"
|
||||||
|
" a13 CDATA '13'\n"
|
||||||
|
" a14 CDATA '14'\n"
|
||||||
|
" a15 CDATA '15'\n"
|
||||||
|
" a16 CDATA '16'\n"
|
||||||
|
" a17 CDATA '17'\n"
|
||||||
|
" >\n"
|
||||||
|
"]>\n"
|
||||||
|
"<doc/>\n";
|
||||||
|
|
||||||
|
init_dummy_handlers();
|
||||||
|
|
||||||
|
XML_Parser parser = XML_ParserCreate(NULL);
|
||||||
|
XML_SetStartElementHandler(
|
||||||
|
parser, dummy_start_element); // i.e. ask for calling `storeAtts`
|
||||||
|
assert_true(_XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc),
|
||||||
|
/*isFinal=*/XML_TRUE));
|
||||||
|
XML_ParserFree(parser);
|
||||||
|
|
||||||
|
assert_true(get_dummy_handler_flags() == DUMMY_START_ELEMENT_HANDLER_FLAG);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
static void
|
||||||
|
comparingPiHandler(void *userData, const XML_Char *target,
|
||||||
|
const XML_Char *data) {
|
||||||
|
UNUSED_P(userData);
|
||||||
|
|
||||||
|
XML_Char *const literalTarget = xcsdup_str("target");
|
||||||
|
XML_Char *const literalData = xcsdup_str("data");
|
||||||
|
assert_true(literalTarget != NULL);
|
||||||
|
assert_true(literalData != NULL);
|
||||||
|
|
||||||
|
assert_true(xcscmp(target, literalTarget) == 0);
|
||||||
|
assert_true(xcscmp(data, literalData) == 0);
|
||||||
|
|
||||||
|
free(literalTarget);
|
||||||
|
free(literalData);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int XMLCALL
|
||||||
|
piParsingExternalEntityHandler(XML_Parser parent, const XML_Char *context,
|
||||||
|
const XML_Char *base, const XML_Char *systemId,
|
||||||
|
const XML_Char *publicId) {
|
||||||
|
UNUSED_P(base);
|
||||||
|
UNUSED_P(systemId);
|
||||||
|
UNUSED_P(publicId);
|
||||||
|
|
||||||
|
const char *const doc = "<?target data?>";
|
||||||
|
|
||||||
|
XML_Parser subParser = XML_ExternalEntityParserCreate(parent, context, NULL);
|
||||||
|
assert_true(subParser != NULL);
|
||||||
|
|
||||||
|
// NOTE: Related test "test_empty_ext_param_entity_in_value" could be of
|
||||||
|
// interest
|
||||||
|
assert_true(_XML_Parse_SINGLE_BYTES(subParser, "", 0, /*isFinal=*/XML_FALSE)
|
||||||
|
== XML_STATUS_OK);
|
||||||
|
assert_true(_XML_Parse_SINGLE_BYTES(subParser, doc, (int)strlen(doc),
|
||||||
|
/*isFinal=*/XML_TRUE)
|
||||||
|
== XML_STATUS_OK);
|
||||||
|
|
||||||
|
XML_ParserFree(subParser);
|
||||||
|
|
||||||
|
return XML_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(test_misc_empty_nonfinal_subparser_parse) {
|
||||||
|
const char *const doc = "<!DOCTYPE root [\n"
|
||||||
|
" <!ENTITY ext SYSTEM 'external.dtd'>\n"
|
||||||
|
"]>\n"
|
||||||
|
"<root>&ext;</root>\n";
|
||||||
|
|
||||||
|
XML_Parser parser = XML_ParserCreate(NULL);
|
||||||
|
assert_true(parser != NULL);
|
||||||
|
|
||||||
|
XML_SetProcessingInstructionHandler(parser, comparingPiHandler);
|
||||||
|
XML_SetExternalEntityRefHandler(parser, piParsingExternalEntityHandler);
|
||||||
|
|
||||||
|
assert_true(_XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc),
|
||||||
|
/*isFinal=*/XML_TRUE));
|
||||||
|
|
||||||
|
XML_ParserFree(parser);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
void
|
void
|
||||||
make_miscellaneous_test_case(Suite *s) {
|
make_miscellaneous_test_case(Suite *s) {
|
||||||
TCase *tc_misc = tcase_create("miscellaneous tests");
|
TCase *tc_misc = tcase_create("miscellaneous tests");
|
||||||
@@ -1050,6 +1225,7 @@ make_miscellaneous_test_case(Suite *s) {
|
|||||||
tcase_add_test(tc_misc, test_misc_char_handler_stop_without_leak);
|
tcase_add_test(tc_misc, test_misc_char_handler_stop_without_leak);
|
||||||
tcase_add_test(tc_misc, test_misc_resumeparser_not_crashing);
|
tcase_add_test(tc_misc, test_misc_resumeparser_not_crashing);
|
||||||
tcase_add_test(tc_misc, test_misc_stopparser_rejects_unstarted_parser);
|
tcase_add_test(tc_misc, test_misc_stopparser_rejects_unstarted_parser);
|
||||||
|
tcase_add_test(tc_misc, test_misc_parsing_status_of_unstarted_parser);
|
||||||
tcase_add_test__if_xml_ge(tc_misc, test_renter_loop_finite_content);
|
tcase_add_test__if_xml_ge(tc_misc, test_renter_loop_finite_content);
|
||||||
tcase_add_test(tc_misc, test_misc_expected_event_ptr_issue_980);
|
tcase_add_test(tc_misc, test_misc_expected_event_ptr_issue_980);
|
||||||
tcase_add_test(tc_misc, test_misc_sync_entity_tolerated);
|
tcase_add_test(tc_misc, test_misc_sync_entity_tolerated);
|
||||||
@@ -1064,4 +1240,7 @@ make_miscellaneous_test_case(Suite *s) {
|
|||||||
test_misc_unknown_encoding_release_getter_parser_reset);
|
test_misc_unknown_encoding_release_getter_parser_reset);
|
||||||
tcase_add_test(tc_misc, test_misc_input_2gb);
|
tcase_add_test(tc_misc, test_misc_input_2gb);
|
||||||
tcase_add_test(tc_misc, test_misc_low_surrogate_mozilla_bug_2053153);
|
tcase_add_test(tc_misc, test_misc_low_surrogate_mozilla_bug_2053153);
|
||||||
|
tcase_add_test(tc_misc, test_misc_storeatts_attssize_allocation);
|
||||||
|
tcase_add_test(tc_misc, test_misc_start_doctype_decl_handler_reset);
|
||||||
|
tcase_add_test(tc_misc, test_misc_empty_nonfinal_subparser_parse);
|
||||||
}
|
}
|
||||||
@@ -57,6 +57,7 @@
|
|||||||
#include "acc_tests.h"
|
#include "acc_tests.h"
|
||||||
#include "alloc_tests.h"
|
#include "alloc_tests.h"
|
||||||
#include "basic_tests.h"
|
#include "basic_tests.h"
|
||||||
|
#include "entities_tests.h"
|
||||||
#include "hash_tests.h"
|
#include "hash_tests.h"
|
||||||
#include "misc_tests.h"
|
#include "misc_tests.h"
|
||||||
#include "ns_tests.h"
|
#include "ns_tests.h"
|
||||||
@@ -75,6 +76,7 @@ make_suite(void) {
|
|||||||
#endif
|
#endif
|
||||||
make_alloc_test_case(s);
|
make_alloc_test_case(s);
|
||||||
make_basic_test_case(s);
|
make_basic_test_case(s);
|
||||||
|
make_entities_test_case(s);
|
||||||
make_hash_test_case(s);
|
make_hash_test_case(s);
|
||||||
make_miscellaneous_test_case(s);
|
make_miscellaneous_test_case(s);
|
||||||
make_namespace_test_case(s);
|
make_namespace_test_case(s);
|
||||||
|
|||||||
@@ -76,6 +76,28 @@ START_TEST(test_xcs_ncmp) {
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_xcs_nstr) {
|
||||||
|
if (g_chunkSize != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const XML_Char haystack[] = {ASCII_h, ASCII_a, ASCII_y, ASCII_s, ASCII_t,
|
||||||
|
ASCII_a, ASCII_c, ASCII_k, '\0'};
|
||||||
|
const XML_Char hay[] = {ASCII_h, ASCII_a, ASCII_y, '\0'};
|
||||||
|
const XML_Char stack[] = {ASCII_s, ASCII_t, ASCII_a, ASCII_c, ASCII_k, '\0'};
|
||||||
|
const XML_Char other[] = {ASCII_o, ASCII_t, ASCII_h, ASCII_e, ASCII_r, '\0'};
|
||||||
|
|
||||||
|
assert_true(xcsnstr(haystack, haystack, xcslen(haystack)) == haystack);
|
||||||
|
assert_true(xcsnstr(haystack, hay, xcslen(haystack)) == haystack);
|
||||||
|
assert_true(xcsnstr(haystack, hay, xcslen(hay)) == haystack);
|
||||||
|
assert_true(xcsnstr(haystack, hay, xcslen(hay) - 1) == NULL);
|
||||||
|
assert_true(xcsnstr(haystack, stack, xcslen(haystack))
|
||||||
|
== haystack + xcslen(hay));
|
||||||
|
assert_true(xcsnstr(haystack, other, xcslen(haystack)) == NULL);
|
||||||
|
assert_true(xcsnstr(haystack, empty, xcslen(haystack)) == haystack);
|
||||||
|
assert_true(xcsnstr(hay, haystack, xcslen(hay)) == NULL);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
void
|
void
|
||||||
make_xcs_test_case(Suite *s) {
|
make_xcs_test_case(Suite *s) {
|
||||||
TCase *const tc_xcs = tcase_create("xcs tests");
|
TCase *const tc_xcs = tcase_create("xcs tests");
|
||||||
@@ -83,4 +105,5 @@ make_xcs_test_case(Suite *s) {
|
|||||||
tcase_add_test(tc_xcs, test_xcs_len);
|
tcase_add_test(tc_xcs, test_xcs_len);
|
||||||
tcase_add_test(tc_xcs, test_xcs_cmp);
|
tcase_add_test(tc_xcs, test_xcs_cmp);
|
||||||
tcase_add_test(tc_xcs, test_xcs_ncmp);
|
tcase_add_test(tc_xcs, test_xcs_ncmp);
|
||||||
|
tcase_add_test(tc_xcs, test_xcs_nstr);
|
||||||
}
|
}
|
||||||
+3
-2
@@ -7,6 +7,7 @@
|
|||||||
# |_| XML parser
|
# |_| XML parser
|
||||||
#
|
#
|
||||||
# Copyright (c) 2017-2026 Sebastian Pipping <[email protected]>
|
# Copyright (c) 2017-2026 Sebastian Pipping <[email protected]>
|
||||||
|
# Copyright (c) 2026 Funda Wang <[email protected]>
|
||||||
# Licensed under the MIT license:
|
# Licensed under the MIT license:
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
# Permission is hereby granted, free of charge, to any person obtaining
|
||||||
@@ -30,7 +31,7 @@
|
|||||||
|
|
||||||
bin_PROGRAMS = xmlwf
|
bin_PROGRAMS = xmlwf
|
||||||
|
|
||||||
xmlwf_LDADD = ../lib/libexpat.la
|
xmlwf_LDADD = ../lib/libexpat.la @LIBM@
|
||||||
xmlwf_SOURCES = \
|
xmlwf_SOURCES = \
|
||||||
../lib/xcs.c \
|
../lib/xcs.c \
|
||||||
xmlwf.c \
|
xmlwf.c \
|
||||||
@@ -39,7 +40,7 @@ xmlwf_SOURCES = \
|
|||||||
@[email protected]
|
@[email protected]
|
||||||
|
|
||||||
xmlwf_CPPFLAGS = @AM_CPPFLAGS@ -I$(srcdir)/../lib
|
xmlwf_CPPFLAGS = @AM_CPPFLAGS@ -I$(srcdir)/../lib
|
||||||
xmlwf_LDFLAGS = @AM_LDFLAGS@ @LIBM@
|
xmlwf_LDFLAGS = @AM_LDFLAGS@
|
||||||
|
|
||||||
if MINGW
|
if MINGW
|
||||||
if UNICODE
|
if UNICODE
|
||||||
|
|||||||
+3
-2
@@ -23,6 +23,7 @@
|
|||||||
# |_| XML parser
|
# |_| XML parser
|
||||||
#
|
#
|
||||||
# Copyright (c) 2017-2026 Sebastian Pipping <[email protected]>
|
# Copyright (c) 2017-2026 Sebastian Pipping <[email protected]>
|
||||||
|
# Copyright (c) 2026 Funda Wang <[email protected]>
|
||||||
# Licensed under the MIT license:
|
# Licensed under the MIT license:
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
# Permission is hereby granted, free of charge, to any person obtaining
|
||||||
@@ -378,7 +379,7 @@ target_alias = @target_alias@
|
|||||||
top_build_prefix = @top_build_prefix@
|
top_build_prefix = @top_build_prefix@
|
||||||
top_builddir = @top_builddir@
|
top_builddir = @top_builddir@
|
||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
xmlwf_LDADD = ../lib/libexpat.la
|
xmlwf_LDADD = ../lib/libexpat.la @LIBM@
|
||||||
xmlwf_SOURCES = \
|
xmlwf_SOURCES = \
|
||||||
../lib/xcs.c \
|
../lib/xcs.c \
|
||||||
xmlwf.c \
|
xmlwf.c \
|
||||||
@@ -387,7 +388,7 @@ xmlwf_SOURCES = \
|
|||||||
@[email protected]
|
@[email protected]
|
||||||
|
|
||||||
xmlwf_CPPFLAGS = @AM_CPPFLAGS@ -I$(srcdir)/../lib $(am__append_1)
|
xmlwf_CPPFLAGS = @AM_CPPFLAGS@ -I$(srcdir)/../lib $(am__append_1)
|
||||||
xmlwf_LDFLAGS = @AM_LDFLAGS@ @LIBM@ $(am__append_2)
|
xmlwf_LDFLAGS = @AM_LDFLAGS@ $(am__append_2)
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
codepage.h \
|
codepage.h \
|
||||||
ct.c \
|
ct.c \
|
||||||
|
|||||||
Reference in new issue
Block a user