aboutsummaryrefslogtreecommitdiff
path: root/contrib/expat/tests
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/expat/tests')
-rw-r--r--contrib/expat/tests/Makefile.in99
-rw-r--r--contrib/expat/tests/alloc_tests.c242
-rw-r--r--contrib/expat/tests/basic_tests.c8
-rw-r--r--contrib/expat/tests/benchmark/Makefile.in35
-rw-r--r--contrib/expat/tests/common.c11
-rw-r--r--contrib/expat/tests/handlers.c29
-rw-r--r--contrib/expat/tests/minicheck.h3
-rw-r--r--contrib/expat/tests/misc_tests.c101
-rw-r--r--contrib/expat/tests/nsalloc_tests.c11
9 files changed, 466 insertions, 73 deletions
diff --git a/contrib/expat/tests/Makefile.in b/contrib/expat/tests/Makefile.in
index eb00a068cbd2..830560e2daba 100644
--- a/contrib/expat/tests/Makefile.in
+++ b/contrib/expat/tests/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# Makefile.in generated by automake 1.18.1 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+# Copyright (C) 1994-2025 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -102,6 +102,8 @@ am__make_running_with_option = \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+am__rm_f = rm -f $(am__rm_f_notfound)
+am__rm_rf = rm -rf $(am__rm_f_notfound)
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
@@ -324,10 +326,9 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__uninstall_files_from_dir = { \
- test -z "$$files" \
- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
- $(am__cd) "$$dir" && rm -f $$files; }; \
+ { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && echo $$files | $(am__xargs_n) 40 $(am__rm_f); }; \
}
am__recheck_rx = ^[ ]*:recheck:[ ]*
am__global_test_result_rx = ^[ ]*:global-test-result:[ ]*
@@ -415,12 +416,13 @@ am__sh_e_setup = case $$- in *e*) set +e;; esac
# Default flags passed to test drivers.
am__common_driver_flags = \
--color-tests "$$am__color_tests" \
+ $$am__collect_skipped_logs \
--enable-hard-errors "$$am__enable_hard_errors" \
--expect-failure "$$am__expect_failure"
# To be inserted before the command running the test. Creates the
# directory for the log if needed. Stores in $dir the directory
# containing $f, in $tst the test, in $log the log. Executes the
-# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and
+# developer-defined test setup AM_TESTS_ENVIRONMENT (if any), and
# passes TESTS_ENVIRONMENT. Set up options for the wrapper that
# will run the test scripts (or their associated LOG_COMPILER, if
# thy have one).
@@ -439,6 +441,11 @@ if test -f "./$$f"; then dir=./; \
elif test -f "$$f"; then dir=; \
else dir="$(srcdir)/"; fi; \
tst=$$dir$$f; log='$@'; \
+if test -n '$(IGNORE_SKIPPED_LOGS)'; then \
+ am__collect_skipped_logs='--collect-skipped-logs no'; \
+else \
+ am__collect_skipped_logs=''; \
+fi; \
if test -n '$(DISABLE_HARD_ERRORS)'; then \
am__enable_hard_errors=no; \
else \
@@ -620,8 +627,10 @@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
+am__rm_f_notfound = @am__rm_f_notfound@
am__tar = @am__tar@
am__untar = @am__untar@
+am__xargs_n = @am__xargs_n@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
@@ -757,13 +766,8 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
$(am__aclocal_m4_deps):
clean-checkPROGRAMS:
- @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
- echo " rm -f" $$list; \
- rm -f $$list || exit $$?; \
- test -n "$(EXEEXT)" || exit 0; \
- list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
- echo " rm -f" $$list; \
- rm -f $$list
+ $(am__rm_f) $(check_PROGRAMS)
+ test -z "$(EXEEXT)" || $(am__rm_f) $(check_PROGRAMS:$(EXEEXT)=)
runtests$(EXEEXT): $(runtests_OBJECTS) $(runtests_DEPENDENCIES) $(EXTRA_runtests_DEPENDENCIES)
@rm -f runtests$(EXEEXT)
@@ -810,7 +814,7 @@ distclean-compile:
$(am__depfiles_remade):
@$(MKDIR_P) $(@D)
- @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+ @: >>$@
am--depfiles: $(am__depfiles_remade)
@@ -974,7 +978,6 @@ distclean-tags:
am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)
am--force-recheck:
@:
-
$(TEST_SUITE_LOG): $(TEST_LOGS)
@$(am__set_TESTS_bases); \
am__f_ok () { test -f "$$1" && test -r "$$1"; }; \
@@ -1050,10 +1053,37 @@ $(TEST_SUITE_LOG): $(TEST_LOGS)
result_count $$1 "XPASS:" $$xpass "$$red"; \
result_count $$1 "ERROR:" $$error "$$mgn"; \
}; \
+ output_system_information () \
+ { \
+ echo; \
+ { uname -a | $(AWK) '{ \
+ printf "System information (uname -a):"; \
+ for (i = 1; i < NF; ++i) \
+ { \
+ if (i != 2) \
+ printf " %s", $$i; \
+ } \
+ printf "\n"; \
+}'; } 2>&1; \
+ if test -r /etc/os-release; then \
+ echo "Distribution information (/etc/os-release):"; \
+ sed 8q /etc/os-release; \
+ elif test -r /etc/issue; then \
+ echo "Distribution information (/etc/issue):"; \
+ cat /etc/issue; \
+ fi; \
+ }; \
+ please_report () \
+ { \
+echo "Some test(s) failed. Please report this to $(PACKAGE_BUGREPORT),"; \
+echo "together with the test-suite.log file (gzipped) and your system"; \
+echo "information. Thanks."; \
+ }; \
{ \
echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \
$(am__rst_title); \
create_testsuite_report --no-color; \
+ output_system_information; \
echo; \
echo ".. contents:: :depth: 2"; \
echo; \
@@ -1073,26 +1103,25 @@ $(TEST_SUITE_LOG): $(TEST_LOGS)
create_testsuite_report --maybe-color; \
echo "$$col$$br$$std"; \
if $$success; then :; else \
- echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \
+ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG) for debugging.$${std}";\
if test -n "$(PACKAGE_BUGREPORT)"; then \
- echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \
+ please_report | sed -e "s/^/$${col}/" -e s/'$$'/"$${std}"/; \
fi; \
echo "$$col$$br$$std"; \
fi; \
$$success || exit 1
check-TESTS: $(check_PROGRAMS)
- @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list
- @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list
- @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @$(am__rm_f) $(RECHECK_LOGS)
+ @$(am__rm_f) $(RECHECK_LOGS:.log=.trs)
+ @$(am__rm_f) $(TEST_SUITE_LOG)
@set +e; $(am__set_TESTS_bases); \
log_list=`for i in $$bases; do echo $$i.log; done`; \
- trs_list=`for i in $$bases; do echo $$i.trs; done`; \
- log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \
+ log_list=`echo $$log_list`; \
$(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \
exit $$?;
recheck: all $(check_PROGRAMS)
- @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @$(am__rm_f) $(TEST_SUITE_LOG)
@set +e; $(am__set_TESTS_bases); \
bases=`for i in $$bases; do echo $$i; done \
| $(am__list_recheck_tests)` || exit 1; \
@@ -1130,6 +1159,7 @@ runtests_cxx.log: runtests_cxx$(EXEEXT)
@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \
@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT)
+
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
@@ -1215,15 +1245,15 @@ install-strip:
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
- -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
- -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs)
- -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ -$(am__rm_f) $(TEST_LOGS)
+ -$(am__rm_f) $(TEST_LOGS:.log=.trs)
+ -$(am__rm_f) $(TEST_SUITE_LOG)
clean-generic:
distclean-generic:
- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -$(am__rm_f) $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@@ -1234,7 +1264,7 @@ clean-am: clean-checkPROGRAMS clean-generic clean-libtool \
mostlyclean-am
distclean: distclean-recursive
- -rm -f ./$(DEPDIR)/acc_tests.Po
+ -rm -f ./$(DEPDIR)/acc_tests.Po
-rm -f ./$(DEPDIR)/acc_tests_cxx.Po
-rm -f ./$(DEPDIR)/alloc_tests.Po
-rm -f ./$(DEPDIR)/alloc_tests_cxx.Po
@@ -1307,7 +1337,7 @@ install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-recursive
- -rm -f ./$(DEPDIR)/acc_tests.Po
+ -rm -f ./$(DEPDIR)/acc_tests.Po
-rm -f ./$(DEPDIR)/acc_tests_cxx.Po
-rm -f ./$(DEPDIR)/alloc_tests.Po
-rm -f ./$(DEPDIR)/alloc_tests_cxx.Po
@@ -1376,3 +1406,10 @@ uninstall-am:
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
+
+# Tell GNU make to disable its built-in pattern rules.
+%:: %,v
+%:: RCS/%,v
+%:: RCS/%
+%:: s.%
+%:: SCCS/s.%
diff --git a/contrib/expat/tests/alloc_tests.c b/contrib/expat/tests/alloc_tests.c
index 12ea3b2a81d2..5ae6c6a72025 100644
--- a/contrib/expat/tests/alloc_tests.c
+++ b/contrib/expat/tests/alloc_tests.c
@@ -10,7 +10,7 @@
Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net>
- Copyright (c) 2016-2023 Sebastian Pipping <sebastian@pipping.org>
+ Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2017-2022 Rhodri James <rhodri@wildebeest.org.uk>
Copyright (c) 2017 Joe Orton <jorton@redhat.com>
Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
@@ -46,10 +46,16 @@
# undef NDEBUG /* because test suite relies on assert(...) at the moment */
#endif
+#include <math.h> /* NAN, INFINITY */
+#include <stdbool.h>
+#include <stdint.h> /* for SIZE_MAX */
#include <string.h>
#include <assert.h>
+#include "expat_config.h"
+
#include "expat.h"
+#include "internal.h"
#include "common.h"
#include "minicheck.h"
#include "dummy.h"
@@ -323,7 +329,7 @@ START_TEST(test_alloc_run_external_parser) {
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 +440,7 @@ START_TEST(test_alloc_internal_entity) {
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 +2091,226 @@ START_TEST(test_alloc_reset_after_external_entity_parser_create_fail) {
}
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
+ = (long long *)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 = "<e>";
+ 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 @@ make_alloc_test_case(Suite *s) {
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 --git a/contrib/expat/tests/basic_tests.c b/contrib/expat/tests/basic_tests.c
index e813df8b6fd2..0231e0949ee9 100644
--- a/contrib/expat/tests/basic_tests.c
+++ b/contrib/expat/tests/basic_tests.c
@@ -412,13 +412,13 @@ START_TEST(test_utf16_le_epilog_newline) {
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);
@@ -3123,6 +3123,10 @@ START_TEST(test_buffer_can_grow_to_max) {
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);
diff --git a/contrib/expat/tests/benchmark/Makefile.in b/contrib/expat/tests/benchmark/Makefile.in
index d0e6d0769db0..e72e901a39af 100644
--- a/contrib/expat/tests/benchmark/Makefile.in
+++ b/contrib/expat/tests/benchmark/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# Makefile.in generated by automake 1.18.1 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+# Copyright (C) 1994-2025 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -101,6 +101,8 @@ am__make_running_with_option = \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+am__rm_f = rm -f $(am__rm_f_notfound)
+am__rm_rf = rm -rf $(am__rm_f_notfound)
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
@@ -320,8 +322,10 @@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
+am__rm_f_notfound = @am__rm_f_notfound@
am__tar = @am__tar@
am__untar = @am__untar@
+am__xargs_n = @am__xargs_n@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
@@ -403,13 +407,8 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
$(am__aclocal_m4_deps):
clean-noinstPROGRAMS:
- @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
- echo " rm -f" $$list; \
- rm -f $$list || exit $$?; \
- test -n "$(EXEEXT)" || exit 0; \
- list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
- echo " rm -f" $$list; \
- rm -f $$list
+ $(am__rm_f) $(noinst_PROGRAMS)
+ test -z "$(EXEEXT)" || $(am__rm_f) $(noinst_PROGRAMS:$(EXEEXT)=)
benchmark$(EXEEXT): $(benchmark_OBJECTS) $(benchmark_DEPENDENCIES) $(EXTRA_benchmark_DEPENDENCIES)
@rm -f benchmark$(EXEEXT)
@@ -425,7 +424,7 @@ distclean-compile:
$(am__depfiles_remade):
@$(MKDIR_P) $(@D)
- @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+ @: >>$@
am--depfiles: $(am__depfiles_remade)
@@ -507,6 +506,7 @@ cscopelist-am: $(am__tagged_files)
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
@@ -568,8 +568,8 @@ mostlyclean-generic:
clean-generic:
distclean-generic:
- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -$(am__rm_f) $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@@ -580,7 +580,7 @@ clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
mostlyclean-am
distclean: distclean-am
- -rm -f ./$(DEPDIR)/benchmark.Po
+ -rm -f ./$(DEPDIR)/benchmark.Po
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
@@ -626,7 +626,7 @@ install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
- -rm -f ./$(DEPDIR)/benchmark.Po
+ -rm -f ./$(DEPDIR)/benchmark.Po
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
@@ -667,3 +667,10 @@ uninstall-am:
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
+
+# Tell GNU make to disable its built-in pattern rules.
+%:: %,v
+%:: RCS/%,v
+%:: RCS/%
+%:: s.%
+%:: SCCS/s.%
diff --git a/contrib/expat/tests/common.c b/contrib/expat/tests/common.c
index b158385f56a8..b2537d0deee1 100644
--- a/contrib/expat/tests/common.c
+++ b/contrib/expat/tests/common.c
@@ -303,7 +303,14 @@ duff_reallocator(void *ptr, size_t size) {
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,6 +318,8 @@ portable_strndup(const char *s, size_t n) {
return NULL;
}
+ n = portable_strnlen(s, n);
+
char *const buffer = (char *)malloc(n + 1);
if (buffer == NULL) {
errno = ENOMEM;
diff --git a/contrib/expat/tests/handlers.c b/contrib/expat/tests/handlers.c
index ac459507580b..5bca2b1f551e 100644
--- a/contrib/expat/tests/handlers.c
+++ b/contrib/expat/tests/handlers.c
@@ -10,7 +10,7 @@
Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net>
- Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org>
+ Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2017-2022 Rhodri James <rhodri@wildebeest.org.uk>
Copyright (c) 2017 Joe Orton <jorton@redhat.com>
Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
@@ -89,15 +89,15 @@ start_element_event_handler2(void *userData, const XML_Char *name,
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,7 +132,7 @@ counting_start_element_handler(void *userData, const XML_Char *name,
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;
}
@@ -147,7 +147,7 @@ counting_start_element_handler(void *userData, const XML_Char *name,
fail("Attribute not recognised");
return;
}
- if (xcstrcmp(atts[1], attr->value)) {
+ if (xcstrcmp(atts[1], attr->value) != 0) {
fail("Attribute has wrong value");
return;
}
@@ -1110,7 +1110,7 @@ external_entity_devaluer(XML_Parser parser, const XML_Char *context,
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)
@@ -1276,7 +1276,7 @@ external_entity_duff_loader(XML_Parser parser, const XML_Char *context,
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);
@@ -1552,15 +1552,16 @@ verify_attlist_decl_handler(void *userData, const XML_Char *element_name,
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 +1752,7 @@ param_entity_match_handler(void *userData, const XML_Char *entityName,
* 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;
diff --git a/contrib/expat/tests/minicheck.h b/contrib/expat/tests/minicheck.h
index 29ae4cb2420d..140eaaa5c105 100644
--- a/contrib/expat/tests/minicheck.h
+++ b/contrib/expat/tests/minicheck.h
@@ -134,8 +134,7 @@ void _check_set_test_info(char const *function, char const *filename,
__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 --git a/contrib/expat/tests/misc_tests.c b/contrib/expat/tests/misc_tests.c
index fb95014b142f..2a8054546a12 100644
--- a/contrib/expat/tests/misc_tests.c
+++ b/contrib/expat/tests/misc_tests.c
@@ -70,7 +70,7 @@ START_TEST(test_misc_alloc_create_parser) {
/* 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 +90,7 @@ START_TEST(test_misc_alloc_create_parser_with_encoding) {
/* 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 +211,8 @@ START_TEST(test_misc_version) {
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.7.3"))
+ != 0) /* needs bump on releases */
fail("XML_*_VERSION in expat.h out of sync?\n");
}
END_TEST
@@ -678,6 +679,98 @@ START_TEST(test_misc_expected_event_ptr_issue_980) {
}
END_TEST
+START_TEST(test_misc_sync_entity_tolerated) {
+ const char *const doc = "<!DOCTYPE t0 [\n"
+ " <!ENTITY a '<t1></t1>'>\n"
+ " <!ENTITY b '<t2>two</t2>'>\n"
+ " <!ENTITY c '<t3>three<t4>four</t4>three</t3>'>\n"
+ " <!ENTITY d '<t5>&b;</t5>'>\n"
+ "]>\n"
+ "<t0>&a;&b;&c;&d;</t0>\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
+ {"<!DOCTYPE t0 [\n"
+ " <!ENTITY open '<t1>'>\n"
+ " <!ENTITY close '</t1>'>\n"
+ "]>\n"
+ "<t0>&open;&close;</t0>\n",
+ XML_STATUS_OK, XML_ERROR_NONE, 5, 4},
+ // Opened by tag, closed by entity (non-root case)
+ {"<!DOCTYPE t0 [\n"
+ " <!ENTITY g0 ''>\n"
+ " <!ENTITY g1 '&g0;</t1>'>\n"
+ "]>\n"
+ "<t0><t1>&g1;</t0>\n",
+ XML_STATUS_ERROR, XML_ERROR_TAG_MISMATCH, 5, 8},
+ // Opened by tag, closed by entity (root case)
+ {"<!DOCTYPE t0 [\n"
+ " <!ENTITY g0 ''>\n"
+ " <!ENTITY g1 '&g0;</t0>'>\n"
+ "]>\n"
+ "<t0>&g1;\n",
+ XML_STATUS_ERROR, XML_ERROR_NO_ELEMENTS, 5, 4},
+ // Opened by entity, closed by tag <-- regression from 2.7.0
+ {"<!DOCTYPE t0 [\n"
+ " <!ENTITY g0 ''>\n"
+ " <!ENTITY g1 '<t1>&g0;'>\n"
+ "]>\n"
+ "<t0>&g1;</t1></t0>\n",
+ XML_STATUS_ERROR, XML_ERROR_TAG_MISMATCH, 5, 4},
+ // Opened by tag, closed by entity; then the other way around
+ {"<!DOCTYPE t0 [\n"
+ " <!ENTITY open '<t1>'>\n"
+ " <!ENTITY close '</t1>'>\n"
+ "]>\n"
+ "<t0><t1>&close;&open;</t1></t0>\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
+
void
make_miscellaneous_test_case(Suite *s) {
TCase *tc_misc = tcase_create("miscellaneous tests");
@@ -706,4 +799,6 @@ make_miscellaneous_test_case(Suite *s) {
tcase_add_test(tc_misc, test_misc_stopparser_rejects_unstarted_parser);
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_sync_entity_tolerated);
+ tcase_add_test(tc_misc, test_misc_async_entity_rejected);
}
diff --git a/contrib/expat/tests/nsalloc_tests.c b/contrib/expat/tests/nsalloc_tests.c
index ec88586af1d4..60fa87f83461 100644
--- a/contrib/expat/tests/nsalloc_tests.c
+++ b/contrib/expat/tests/nsalloc_tests.c
@@ -10,7 +10,7 @@
Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net>
- Copyright (c) 2016-2023 Sebastian Pipping <sebastian@pipping.org>
+ Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2017-2022 Rhodri James <rhodri@wildebeest.org.uk>
Copyright (c) 2017 Joe Orton <jorton@redhat.com>
Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
@@ -83,7 +83,7 @@ START_TEST(test_nsalloc_xmlns) {
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 +454,15 @@ START_TEST(test_nsalloc_realloc_attributes) {
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 +528,7 @@ START_TEST(test_nsalloc_realloc_binding_uri) {
/* 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;