From 928f2893ad194a95539879b1ae0f6af3f8a845b7 Mon Sep 17 00:00:00 2001 From: Denis Balashov Date: Tue, 9 Jun 2026 11:33:05 +0300 Subject: [PATCH 1/2] detect: guard rate filter callback registration, return bool on failure SCDetectEngineRegisterRateFilterCallback() dereferences the result of DetectEngineGetCurrent() unconditionally. Add a NULL guard with SCLogError and return false so callers can detect registration failure. Flagged by Svace and confirmed by gcc -fanalyzer. Ticket: 8560 --- src/detect-engine.c | 7 ++++++- src/detect.h | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/detect-engine.c b/src/detect-engine.c index c526154027b2..850f221256d7 100644 --- a/src/detect-engine.c +++ b/src/detect-engine.c @@ -5203,12 +5203,17 @@ void DetectLowerSetupCallback( } } -void SCDetectEngineRegisterRateFilterCallback(SCDetectRateFilterFunc fn, void *arg) +bool SCDetectEngineRegisterRateFilterCallback(SCDetectRateFilterFunc fn, void *arg) { DetectEngineCtx *de_ctx = DetectEngineGetCurrent(); + if (de_ctx == NULL) { + SCLogError("no detection engine available for rate filter callback registration"); + return false; + } de_ctx->RateFilterCallback = fn; de_ctx->rate_filter_callback_arg = arg; DetectEngineDeReference(&de_ctx); + return true; } int DetectEngineThreadCtxGetJsonContext(DetectEngineThreadCtx *det_ctx) diff --git a/src/detect.h b/src/detect.h index 9f1f5e0bfb59..37e923424dc9 100644 --- a/src/detect.h +++ b/src/detect.h @@ -1214,7 +1214,7 @@ typedef struct DetectEngineCtx_ { * This callback is added to the current detection engine and will be * copied to all future detection engines over rule reloads. */ -void SCDetectEngineRegisterRateFilterCallback(SCDetectRateFilterFunc cb, void *arg); +bool SCDetectEngineRegisterRateFilterCallback(SCDetectRateFilterFunc cb, void *arg); /* Engine groups profiles (low, medium, high, custom) */ enum { From 22fb69c54043b98f2ef4c2357a3740177f146e8c Mon Sep 17 00:00:00 2001 From: Denis Balashov Date: Tue, 9 Jun 2026 11:33:26 +0300 Subject: [PATCH 2/2] examples: check rate filter callback registration result Check DetectEngineEnabled() before registering, and warn if the registration call returns false. --- examples/lib/custom/main.c | 8 +++++++- examples/lib/live/main.c | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/examples/lib/custom/main.c b/examples/lib/custom/main.c index b11b6e01d7e6..ea513cdeef07 100644 --- a/examples/lib/custom/main.c +++ b/examples/lib/custom/main.c @@ -253,7 +253,13 @@ int main(int argc, char **argv) * ThreadVars will be ready. */ SuricataInit(); - SCDetectEngineRegisterRateFilterCallback(RateFilterCallback, NULL); + if (DetectEngineEnabled()) { + if (!SCDetectEngineRegisterRateFilterCallback(RateFilterCallback, NULL)) { + SCLogWarning("rate filter callback registration failed"); + } + } else { + SCLogWarning("detection engine not enabled, rate filter callback not registered"); + } /* Spawn our worker threads. */ pthread_t worker; diff --git a/examples/lib/live/main.c b/examples/lib/live/main.c index 572a7dde241a..5a58fe5ce4de 100644 --- a/examples/lib/live/main.c +++ b/examples/lib/live/main.c @@ -306,7 +306,13 @@ int main(int argc, char **argv) * ThreadVars will be ready. */ SuricataInit(); - SCDetectEngineRegisterRateFilterCallback(RateFilterCallback, NULL); + if (DetectEngineEnabled()) { + if (!SCDetectEngineRegisterRateFilterCallback(RateFilterCallback, NULL)) { + SCLogWarning("rate filter callback registration failed"); + } + } else { + SCLogWarning("detection engine not enabled, rate filter callback not registered"); + } /* Spawn our worker threads, one for each interface. */ pthread_t workers[MAX_INTERFACES];