From d45dfe4ebd4d6165b762ed1f32689ff02e57f4ac Mon Sep 17 00:00:00 2001 From: Jeff Lucovsky Date: Tue, 21 Apr 2026 10:45:18 -0400 Subject: [PATCH] ftp: don't halt the flow when raising too_many_transactions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The first version of the event set done=true on state->curr_tx and returned NULL when the limit hit. curr_tx is usually the active command just received — marking it done mid-request throws off response matching, and subsequent commands in the flow stop getting logged. SMB behavior is mirrored here: Walk the tx list, find the oldest tx that isn't done, mark it done and tag it with the event, then fall through and create the new tx so the flow parsing continues. One stale tx gets reaped per overflow so memory stays bounded. Issue: 8489 (cherry picked from commit 5ddd808e9bc737ea0699b4822ac609c456744310) --- src/app-layer-ftp.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/app-layer-ftp.c b/src/app-layer-ftp.c index 8c403da1fd..11de01995f 100644 --- a/src/app-layer-ftp.c +++ b/src/app-layer-ftp.c @@ -222,11 +222,17 @@ static FTPTransaction *FTPTransactionCreate(FtpState *state) SCEnter(); FTPTransaction *firsttx = TAILQ_FIRST(&state->tx_list); if (firsttx && state->tx_cnt - firsttx->tx_id > ftp_config_maxtx) { - FTPTransaction *event_tx = state->curr_tx ? state->curr_tx : firsttx; - event_tx->done = true; - event_tx->tx_data.updated_ts = true; - AppLayerDecoderEventsSetEventRaw(&event_tx->tx_data.events, FtpEventTooManyTransactions); - return NULL; + FTPTransaction *tx_old; + TAILQ_FOREACH (tx_old, &state->tx_list, next) { + if (!tx_old->done) { + tx_old->done = true; + tx_old->tx_data.updated_ts = true; + tx_old->tx_data.updated_tc = true; + AppLayerDecoderEventsSetEventRaw( + &tx_old->tx_data.events, FtpEventTooManyTransactions); + break; + } + } } FTPTransaction *tx = FTPCalloc(1, sizeof(*tx)); if (tx == NULL) {