diff options
Diffstat (limited to 'contrib/expat/tests')
| -rw-r--r-- | contrib/expat/tests/Makefile.in | 99 | ||||
| -rw-r--r-- | contrib/expat/tests/alloc_tests.c | 242 | ||||
| -rw-r--r-- | contrib/expat/tests/basic_tests.c | 8 | ||||
| -rw-r--r-- | contrib/expat/tests/benchmark/Makefile.in | 35 | ||||
| -rw-r--r-- | contrib/expat/tests/common.c | 11 | ||||
| -rw-r--r-- | contrib/expat/tests/handlers.c | 29 | ||||
| -rw-r--r-- | contrib/expat/tests/minicheck.h | 3 | ||||
| -rw-r--r-- | contrib/expat/tests/misc_tests.c | 101 | ||||
| -rw-r--r-- | contrib/expat/tests/nsalloc_tests.c | 11 | 
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; | 
