detect/pcre: skip flow captures on flowless packets

DetectPcrePayloadMatch dispatched each capture group through a chain of
captype tests whose flow-variable arm also required a non-NULL flow, and
closed with an else that called BUG_ON(1) on the grounds that the
captype was impossible. A capture typed VAR_TYPE_FLOW_VAR on a packet
inspected without a flow, such as an ICMPv4 error message, matched no
arm of that chain and reached the else. BUG_ON expands to assert()
wherever assert.h is available and NDEBUG is unset and to
exit(EXIT_FAILURE) otherwise, so one pcre rule whose flow capture
matched such a packet killed the process.

Test the captype before the substring is extracted and skip a flow
capture when there is no flow, so nothing is allocated for a capture
that has nowhere to go. The remaining capture groups of the same pcre
still run: a rule that captures one group into a flow variable and the
next into a packet variable still stores the packet variable.

The SCFree(str_ptr) below BUG_ON(1) could never run, because BUG_ON
terminates the process first. Use DEBUG_VALIDATE_BUG_ON instead, which
compiles out unless debug validation is enabled, so a captype the parser
cannot produce releases its capture rather than ending the process.

Issue: 8862
pull/16213/head
Jeff Lucovsky 2 months ago committed by Victor Julien
parent b71178b667
commit 6afe490b46

@ -1,4 +1,4 @@
/* Copyright (C) 2007-2025 Open Information Security Foundation
/* Copyright (C) 2007-2026 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
@ -276,6 +276,10 @@ int DetectPcrePayloadMatch(DetectEngineThreadCtx *det_ctx, const Signature *s,
uint8_t x;
for (x = 0; x < pe->idx; x++) {
SCLogDebug("capturing %u", x);
if (pe->captypes[x] == VAR_TYPE_FLOW_VAR && f == NULL) {
/* no flow to store the capture in, so don't extract it. */
continue;
}
const char *pcre2_str_ptr = NULL;
ret = pcre2_substring_get_bynumber(
match, x + 1, (PCRE2_UCHAR8 **)&pcre2_str_ptr, &capture_len);
@ -327,7 +331,7 @@ int DetectPcrePayloadMatch(DetectEngineThreadCtx *det_ctx, const Signature *s,
(void)DetectVarStoreMatch(det_ctx, pe->capids[x], (uint8_t *)str_ptr,
(uint16_t)capture_len, DETECT_VAR_TYPE_PKT_POSTMATCH);
} else if (pe->captypes[x] == VAR_TYPE_FLOW_VAR && f != NULL) {
} else if (pe->captypes[x] == VAR_TYPE_FLOW_VAR) {
(void)DetectVarStoreMatch(det_ctx, pe->capids[x], (uint8_t *)str_ptr,
(uint16_t)capture_len, DETECT_VAR_TYPE_FLOW_POSTMATCH);
@ -336,7 +340,7 @@ int DetectPcrePayloadMatch(DetectEngineThreadCtx *det_ctx, const Signature *s,
(uint16_t)capture_len);
} else {
BUG_ON(1); // Impossible captype
DEBUG_VALIDATE_BUG_ON(1); // Impossible captype
SCFree(str_ptr);
}
}

Loading…
Cancel
Save