This is an automated email from the ASF dual-hosted git repository. szaszm pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git
commit 4be2c2e18ffe1867eab99d69dd41c4b2924dac8c Author: Martin Zink <[email protected]> AuthorDate: Tue Nov 18 12:35:02 2025 +0100 MINIFICPP-2671 Various ASan fixes - fixing use-after-free in LogTestController::matchesRegex - fixing container-overflow in ConnectionCountingServer.cpp - fixing container-overflow in MockSplunkHEC - fixing stack-use-after-scope in UnfocusArchiveEntry.cpp Closes #2064 Signed-off-by: Marton Szasz <[email protected]> --- extensions/libarchive/UnfocusArchiveEntry.cpp | 7 ++--- extensions/splunk/tests/MockSplunkHEC.h | 3 +- .../tests/unit/AttributesToJSONTests.cpp | 2 +- .../integration/ConnectionCountingServer.cpp | 7 ++--- libminifi/test/libtest/unit/TestBase.cpp | 34 +++++++++++----------- libminifi/test/libtest/unit/TestBase.h | 2 +- 6 files changed, 26 insertions(+), 29 deletions(-) diff --git a/extensions/libarchive/UnfocusArchiveEntry.cpp b/extensions/libarchive/UnfocusArchiveEntry.cpp index 8b49fe2fe..eb94b693f 100644 --- a/extensions/libarchive/UnfocusArchiveEntry.cpp +++ b/extensions/libarchive/UnfocusArchiveEntry.cpp @@ -151,15 +151,14 @@ la_ssize_t UnfocusArchiveEntry::WriteCallback::write_cb(struct archive *, void * } int64_t UnfocusArchiveEntry::WriteCallback::operator()(const std::shared_ptr<io::OutputStream>& stream) const { + UnfocusArchiveEntryWriteData data; + data.stream = stream; auto output_archive = archive_write_unique_ptr{archive_write_new()}; int64_t nlen = 0; archive_write_set_format(output_archive.get(), _archiveMetadata->archiveFormat); - UnfocusArchiveEntryWriteData data; - data.stream = stream; - - archive_write_open(output_archive.get(), &data, ok_cb, write_cb, ok_cb); + archive_write_open(output_archive.get(), &data, nullptr, write_cb, nullptr); // data must outlive the archive because it writes during free // Iterate entries & write from tmp file to archive std::array<char, BUFFER_SIZE> buf{}; diff --git a/extensions/splunk/tests/MockSplunkHEC.h b/extensions/splunk/tests/MockSplunkHEC.h index 854153468..eb95f40c0 100644 --- a/extensions/splunk/tests/MockSplunkHEC.h +++ b/extensions/splunk/tests/MockSplunkHEC.h @@ -130,8 +130,7 @@ class AckIndexerHandler : public MockSplunkHandler { protected: bool handlePostImpl(struct mg_connection* conn) override { - std::vector<char> data; - data.reserve(2048); + auto data = std::vector<char>(2048); mg_read(conn, data.data(), 2048); rapidjson::Document post_data; diff --git a/extensions/standard-processors/tests/unit/AttributesToJSONTests.cpp b/extensions/standard-processors/tests/unit/AttributesToJSONTests.cpp index 1fd1c7de2..e3670eb73 100644 --- a/extensions/standard-processors/tests/unit/AttributesToJSONTests.cpp +++ b/extensions/standard-processors/tests/unit/AttributesToJSONTests.cpp @@ -67,7 +67,7 @@ class AttributesToJSONTestFixture { static void assertJSONAttributesFromLog(const std::unordered_map<std::string, std::optional<std::string>>& expected_attributes) { auto match = LogTestController::getInstance().matchesRegex("key:JSONAttributes value:(.*)"); REQUIRE(match); - assertAttributes(expected_attributes, (*match)[1].str()); + assertAttributes(expected_attributes, (*match)[1]); } void assertJSONAttributesFromFile(const std::unordered_map<std::string, std::optional<std::string>>& expected_attributes) { diff --git a/libminifi/test/libtest/integration/ConnectionCountingServer.cpp b/libminifi/test/libtest/integration/ConnectionCountingServer.cpp index 86baee859..6a1fc4409 100644 --- a/libminifi/test/libtest/integration/ConnectionCountingServer.cpp +++ b/libminifi/test/libtest/integration/ConnectionCountingServer.cpp @@ -64,12 +64,11 @@ void NumberedMethodResponder::saveConnectionId(struct mg_connection* conn) { bool ReverseBodyPostHandler::handlePost(CivetServer* /*server*/, struct mg_connection* conn) { saveConnectionId(conn); - std::vector<char> request_body; - request_body.reserve(2048); - size_t read_size = mg_read(conn, request_body.data(), 2048); + auto request_body = std::vector<char>(2048); + const size_t read_size = mg_read(conn, request_body.data(), 2048); assert(read_size < 2048); std::string response_body{request_body.begin(), request_body.begin() + gsl::narrow<std::vector<char>::difference_type>(read_size)}; - std::reverse(std::begin(response_body), std::end(response_body)); + std::ranges::reverse(response_body); mg_printf(conn, "HTTP/1.1 200 OK\r\n"); mg_printf(conn, "Content-length: %zu\r\n", read_size); mg_printf(conn, "\r\n"); diff --git a/libminifi/test/libtest/unit/TestBase.cpp b/libminifi/test/libtest/unit/TestBase.cpp index 525ce13c1..0cf593b34 100644 --- a/libminifi/test/libtest/unit/TestBase.cpp +++ b/libminifi/test/libtest/unit/TestBase.cpp @@ -126,27 +126,27 @@ bool LogTestController::contains(const std::function<std::string()>& log_string_ return found; } -std::optional<std::smatch> LogTestController::matchesRegex(const std::string& regex_str, std::chrono::milliseconds timeout, std::chrono::milliseconds sleep_interval) const { +std::optional<std::vector<std::string>> LogTestController::matchesRegex(const std::string& regex_str, const std::chrono::milliseconds timeout, const std::chrono::milliseconds sleep_interval) const { if (regex_str.empty()) { return std::nullopt; } - auto start = std::chrono::steady_clock::now(); - bool found = false; - bool timed_out = false; - std::regex matcher_regex(regex_str); - std::smatch match; - do { - std::string str = getLogs(); - found = std::regex_search(str, match, matcher_regex); - auto now = std::chrono::steady_clock::now(); - timed_out = (now - start > timeout); - if (!found && !timed_out) { - std::this_thread::sleep_for(sleep_interval); + const auto start = std::chrono::steady_clock::now(); + const std::regex matcher_regex(regex_str); + while (true) { + const std::string logs = getLogs(); + if (std::smatch match; std::regex_search(logs, match, matcher_regex)) { + std::vector<std::string> results; + results.reserve(match.size()); + for (const auto& sub_match : match) { + results.push_back(sub_match.str()); + } + return std::make_optional(std::move(results)); } - } while (!found && !timed_out); - - logger_->log_info("{} {} in log output.", found ? "Successfully matched regex" : "Failed to match regex", regex_str); - return found ? std::make_optional<std::smatch>(match) : std::nullopt; + if (std::chrono::steady_clock::now() - start > timeout) { + return std::nullopt; + } + std::this_thread::sleep_for(sleep_interval); + } } size_t LogTestController::countOccurrences(const std::string& pattern) const { diff --git a/libminifi/test/libtest/unit/TestBase.h b/libminifi/test/libtest/unit/TestBase.h index 57e2b03c3..e8f48832d 100644 --- a/libminifi/test/libtest/unit/TestBase.h +++ b/libminifi/test/libtest/unit/TestBase.h @@ -135,7 +135,7 @@ class LogTestController { std::chrono::milliseconds timeout = std::chrono::seconds(3), std::chrono::milliseconds sleep_interval = std::chrono::milliseconds(200)); - std::optional<std::smatch> matchesRegex(const std::string ®ex_str, + std::optional<std::vector<std::string>> matchesRegex(const std::string ®ex_str, std::chrono::milliseconds timeout = std::chrono::seconds(3), std::chrono::milliseconds sleep_interval = std::chrono::milliseconds(200)) const;
