]> git.ipfire.org Git - thirdparty/suricata-verify.git/commitdiff
tests: test for delayed tx clean with pass rule 3139/head
authorJason Ish <jason.ish@oisf.net>
Fri, 29 May 2026 21:19:02 +0000 (15:19 -0600)
committerVictor Julien <vjulien@oisf.net>
Wed, 3 Jun 2026 18:02:22 +0000 (18:02 +0000)
Ticket: #8619

A memory leak is not directly assertable, so the accumulation is made
observable through a parser that bounds its live transactions. The pcap
is a single CLDAP (LDAP-over-UDP) flow with four complete
request/response pairs plus three trailing requests with no response.
With ldap.max-tx lowered to 4, correct cleanup frees each completed pair
and the live-transaction list never exceeds the cap. Under the bug the
completed transactions are never freed, the list grows past max-tx, and
the LDAP parser raises too_many_transactions, logged as an anomaly
record independent of detection (which is why it survives the pass
rule).

The check asserts the too_many_transactions anomaly is absent: the test
fails on the buggy code and passes once cleanup is fixed.

tests/bug-8619/README.md [new file with mode: 0644]
tests/bug-8619/cldap-leak.pcap [new file with mode: 0644]
tests/bug-8619/test.rules [new file with mode: 0644]
tests/bug-8619/test.yaml [new file with mode: 0644]

diff --git a/tests/bug-8619/README.md b/tests/bug-8619/README.md
new file mode 100644 (file)
index 0000000..d88e054
--- /dev/null
@@ -0,0 +1,43 @@
+# Description
+
+Reproducer for Redmine #8619: app-layer transaction cleanup is indefinitely
+delayed when a `pass` rule matches a UDP flow.
+
+Commit `d8ddef4c` ("detect: delay tx cleanup in some edge case", Ticket #7552)
+added a condition in `AppLayerParserTransactionsCleanup` that delays
+transaction cleanup until detection has run with the correct signature group
+head (`FLOW_SGH_TOCLIENT` / `FLOW_SGH_TOSERVER`).
+
+When a `pass` rule matches a UDP flow, `FLOW_ACTION_PASS` makes `DetectFlow()`
+skip all subsequent packets in both directions. `FLOW_SGH_TOCLIENT` is never
+set and `APP_LAYER_TX_INSPECTED_TC` is never marked, so completed transactions
+are never freed for the lifetime of the flow. On long-lived UDP flows (e.g.
+continuous SNMP polling, or any UDP app-layer protocol) this causes unbounded
+memory growth.
+
+# Reproduction
+
+A pure memory leak is hard to assert on directly, so this test makes the
+accumulation observable through a parser that bounds its live transactions.
+
+The pcap is a single CLDAP (LDAP-over-UDP) flow with:
+
+- 4 complete searchRequest/searchResponse pairs (message_id 1-4). These are the
+  transactions that should be freed once complete.
+- 3 trailing searchRequests with no response (message_id 5-7).
+
+With `app-layer.protocols.ldap.max-tx=4`, correct cleanup frees each completed
+pair as it finishes, so the live-transaction list never exceeds the cap.
+
+Under the bug, the `pass` rule stops detection, the 4 completed transactions are
+never freed, the list grows past `max-tx`, and the LDAP parser raises the
+`too_many_transactions` app-layer event. That event is logged as an `anomaly`
+record (independent of detection, which is why it survives the `pass`).
+
+The check asserts the `too_many_transactions` anomaly is absent: the test FAILS
+on the buggy code and PASSES once cleanup is fixed.
+
+# PCAP
+
+Generated from the CLDAP payloads in `../ldap-udp/cldap.pcap`, replayed on a
+single UDP 4-tuple with incrementing LDAP message_ids.
diff --git a/tests/bug-8619/cldap-leak.pcap b/tests/bug-8619/cldap-leak.pcap
new file mode 100644 (file)
index 0000000..191c3ff
Binary files /dev/null and b/tests/bug-8619/cldap-leak.pcap differ
diff --git a/tests/bug-8619/test.rules b/tests/bug-8619/test.rules
new file mode 100644 (file)
index 0000000..acac72e
--- /dev/null
@@ -0,0 +1 @@
+pass udp 192.168.0.0/16 any -> any any (msg:"pass udp"; sid:1; rev:1;)
diff --git a/tests/bug-8619/test.yaml b/tests/bug-8619/test.yaml
new file mode 100644 (file)
index 0000000..327399a
--- /dev/null
@@ -0,0 +1,28 @@
+requires:
+  # May affect older versions.
+  min-version: 9
+
+args:
+  # Lower the LDAP live-transaction cap so a small pcap can demonstrate the
+  # leak. Once transactions stop being freed they pile up past this cap and
+  # the parser emits the "too_many_transactions" event.
+  - -k none --set app-layer.protocols.ldap.max-tx=4
+
+pcap: cldap-leak.pcap
+
+checks:
+  # The pass rule passes the flow, so subsequent packets skip detection and
+  # FLOW_SGH_TOCLIENT is never set. Under the bug,
+  # AppLayerParserTransactionsCleanup keeps delaying cleanup of the completed
+  # LDAP transactions for the lifetime of the flow. They accumulate in the
+  # parser, exceed ldap.max-tx, and the parser raises "too_many_transactions".
+  #
+  # With cleanup working correctly the completed transactions are freed as
+  # they finish, the cap is never reached, and no such anomaly is logged.
+  # This test therefore FAILS on the buggy code and PASSES once fixed.
+  - filter:
+      count: 0
+      match:
+        event_type: anomaly
+        anomaly.app_proto: ldap
+        anomaly.event: too_many_transactions