From 1d8ceb26aa37f83b1a3d63d03fa2debe91478089 Mon Sep 17 00:00:00 2001 From: Snild Dolkow Date: Fri, 25 Aug 2023 18:11:55 +0200 Subject: [PATCH] tests: Run SINGLE_BYTES with variously-sized chunks The _XML_Parse_SINGLE_BYTES function currently calls XML_Parse() one byte at a time. This is useful to detect possible parsing bugs related to having to exit parsing, wait for more data, and resume. This commit makes SINGLE_BYTES even more useful by repeating all tests, changing the chunk size every time. So instead of just one byte at a time, we now also test two bytes at a time, and so on. Tests that don't use the SINGLE_BYTES also run multiple times, but are otherwise not affected. This uncovered some issues, which have been fixed in preceding commits. On failure, the chunk size is included in the "FAIL" log prints. --- expat/tests/common.c | 27 ++++++++++++++------------- expat/tests/common.h | 3 +++ expat/tests/minicheck.c | 19 ++++++++++++------- expat/tests/minicheck.h | 3 ++- expat/tests/runtests.c | 10 +++++++++- 5 files changed, 40 insertions(+), 22 deletions(-) diff --git a/expat/tests/common.c b/expat/tests/common.c index b9c53bd0..bfbd26a4 100644 --- a/expat/tests/common.c +++ b/expat/tests/common.c @@ -18,6 +18,7 @@ Copyright (c) 2019 David Loffredo Copyright (c) 2020 Tim Gates Copyright (c) 2021 Donghee Na + Copyright (c) 2023 Sony Corporation / Snild Dolkow Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -137,6 +138,9 @@ XML_Bool g_resumable = XML_FALSE; /* Used to control abort checks in some tests */ XML_Bool g_abortable = XML_FALSE; +/* Used to control _XML_Parse_SINGLE_BYTES() chunk size */ +int g_chunkSize = 1; + /* Common test functions */ void @@ -176,22 +180,19 @@ _xml_failure(XML_Parser parser, const char *file, int line) { enum XML_Status _XML_Parse_SINGLE_BYTES(XML_Parser parser, const char *s, int len, int isFinal) { - enum XML_Status res = XML_STATUS_ERROR; + const int chunksize = g_chunkSize; int offset = 0; - - if (len == 0) { - return XML_Parse(parser, s, len, isFinal); - } - - for (; offset < len; offset++) { - const int innerIsFinal = (offset == len - 1) && isFinal; - const char c = s[offset]; /* to help out-of-bounds detection */ - res = XML_Parse(parser, &c, sizeof(char), innerIsFinal); - if (res != XML_STATUS_OK) { - return res; + if (chunksize > 0) { + // parse in chunks of `chunksize` bytes as long as possible + for (; offset + chunksize < len; offset += chunksize) { + enum XML_Status res = XML_Parse(parser, s + offset, chunksize, XML_FALSE); + if (res != XML_STATUS_OK) { + return res; + } } } - return res; + // parse the final chunk, the size of which will be <= chunksize + return XML_Parse(parser, s + offset, len - offset, isFinal); } void diff --git a/expat/tests/common.h b/expat/tests/common.h index c19970ef..386f85fb 100644 --- a/expat/tests/common.h +++ b/expat/tests/common.h @@ -18,6 +18,7 @@ Copyright (c) 2019 David Loffredo Copyright (c) 2020 Tim Gates Copyright (c) 2021 Donghee Na + Copyright (c) 2023 Sony Corporation / Snild Dolkow Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -82,6 +83,8 @@ extern XML_Parser g_parser; extern XML_Bool g_resumable; extern XML_Bool g_abortable; +extern int g_chunkSize; + extern const char *long_character_data_text; extern const char *long_cdata_text; extern const char *get_buffer_test_text; diff --git a/expat/tests/minicheck.c b/expat/tests/minicheck.c index 0eee72a3..c36c96ba 100644 --- a/expat/tests/minicheck.c +++ b/expat/tests/minicheck.c @@ -176,19 +176,20 @@ handle_success(int verbosity) { } static void -handle_failure(SRunner *runner, int verbosity, const char *phase_info) { +handle_failure(SRunner *runner, int verbosity, const char *context, + const char *phase_info) { runner->nfailures++; if (verbosity != CK_SILENT) { if (strlen(_check_current_subtest) != 0) { phase_info = _check_current_subtest; } - printf("FAIL: %s (%s at %s:%d)\n", _check_current_function, phase_info, - _check_current_filename, _check_current_lineno); + printf("FAIL [%s]: %s (%s at %s:%d)\n", context, _check_current_function, + phase_info, _check_current_filename, _check_current_lineno); } } void -srunner_run_all(SRunner *runner, int verbosity) { +srunner_run_all(SRunner *runner, const char *context, int verbosity) { Suite *suite; TCase *volatile tc; assert(runner != NULL); @@ -203,14 +204,14 @@ srunner_run_all(SRunner *runner, int verbosity) { if (tc->setup != NULL) { /* setup */ if (setjmp(env)) { - handle_failure(runner, verbosity, "during setup"); + handle_failure(runner, verbosity, context, "during setup"); continue; } tc->setup(); } /* test */ if (setjmp(env)) { - handle_failure(runner, verbosity, "during actual test"); + handle_failure(runner, verbosity, context, "during actual test"); continue; } (tc->tests[i])(); @@ -219,7 +220,7 @@ srunner_run_all(SRunner *runner, int verbosity) { /* teardown */ if (tc->teardown != NULL) { if (setjmp(env)) { - handle_failure(runner, verbosity, "during teardown"); + handle_failure(runner, verbosity, context, "during teardown"); continue; } tc->teardown(); @@ -229,6 +230,10 @@ srunner_run_all(SRunner *runner, int verbosity) { } tc = tc->next_tcase; } +} + +void +srunner_summarize(SRunner *runner, int verbosity) { if (verbosity != CK_SILENT) { int passed = runner->nchecks - runner->nfailures; double percentage = ((double)passed) / runner->nchecks; diff --git a/expat/tests/minicheck.h b/expat/tests/minicheck.h index c3a44cdb..992ed768 100644 --- a/expat/tests/minicheck.h +++ b/expat/tests/minicheck.h @@ -132,7 +132,8 @@ void tcase_add_checked_fixture(TCase *, tcase_setup_function, tcase_teardown_function); void tcase_add_test(TCase *tc, tcase_test_function test); SRunner *srunner_create(Suite *suite); -void srunner_run_all(SRunner *runner, int verbosity); +void srunner_run_all(SRunner *runner, const char *context, int verbosity); +void srunner_summarize(SRunner *runner, int verbosity); int srunner_ntests_failed(SRunner *runner); void srunner_free(SRunner *runner); diff --git a/expat/tests/runtests.c b/expat/tests/runtests.c index 8950dcb8..8a228b62 100644 --- a/expat/tests/runtests.c +++ b/expat/tests/runtests.c @@ -18,6 +18,7 @@ Copyright (c) 2019 David Loffredo Copyright (c) 2020 Tim Gates Copyright (c) 2021 Donghee Na + Copyright (c) 2023 Sony Corporation / Snild Dolkow Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -95,7 +96,14 @@ main(int argc, char *argv[]) { } if (verbosity != CK_SILENT) printf("Expat version: %" XML_FMT_STR "\n", XML_ExpatVersion()); - srunner_run_all(sr, verbosity); + + for (g_chunkSize = 1; g_chunkSize <= 5; g_chunkSize++) { + char context[100]; + snprintf(context, sizeof(context), "chunksize=%d", g_chunkSize); + context[sizeof(context) - 1] = '\0'; + srunner_run_all(sr, context, verbosity); + } + srunner_summarize(sr, verbosity); nf = srunner_ntests_failed(sr); srunner_free(sr);