diff --git a/src/detect-engine.c b/src/detect-engine.c index 009741c503..d8f9f1880e 100644 --- a/src/detect-engine.c +++ b/src/detect-engine.c @@ -1444,6 +1444,8 @@ int DetectBufferSetActiveList(DetectEngineCtx *de_ctx, Signature *s, const int l s->init_data->curbuf->id = list; s->init_data->curbuf->head = NULL; s->init_data->curbuf->tail = NULL; + s->init_data->curbuf->multi_capable = + DetectEngineBufferTypeSupportsMultiInstanceGetById(de_ctx, list); SCLogDebug("new: idx %u list %d set up curbuf %p", s->init_data->buffer_index - 1, list, s->init_data->curbuf); @@ -1470,6 +1472,7 @@ int DetectBufferGetActiveList(DetectEngineCtx *de_ctx, Signature *s) if (new_list == -1) { SCReturnInt(-1); } + int base_list = s->init_data->list; SCLogDebug("new_list %d", new_list); s->init_data->list = new_list; s->init_data->list_set = false; @@ -1482,6 +1485,8 @@ int DetectBufferGetActiveList(DetectEngineCtx *de_ctx, Signature *s) return -1; } s->init_data->curbuf = &s->init_data->buffers[s->init_data->buffer_index++]; + s->init_data->curbuf->multi_capable = + DetectEngineBufferTypeSupportsMultiInstanceGetById(de_ctx, base_list); } if (s->init_data->curbuf == NULL) { SCLogError("failed to setup buffer"); diff --git a/src/detect-parse.c b/src/detect-parse.c index 2e798d7b1c..b696b2055c 100644 --- a/src/detect-parse.c +++ b/src/detect-parse.c @@ -289,19 +289,32 @@ int DetectEngineContentModifierBufferSetup(DetectEngineCtx *de_ctx, SCLogError("no matches for previous buffer"); return -1; } - if (SignatureInitDataBufferCheckExpand(s) < 0) { - SCLogError("failed to expand rule buffer array"); - return -1; + bool reuse_buffer = false; + if (s->init_data->curbuf != NULL && (int)s->init_data->curbuf->id != sm_list) { + for (uint32_t x = 0; x < s->init_data->buffer_index; x++) { + if (s->init_data->buffers[x].id == (uint32_t)sm_list) { + s->init_data->curbuf = &s->init_data->buffers[x]; + reuse_buffer = true; + break; + } + } } - /* initialize a new buffer */ - s->init_data->curbuf = &s->init_data->buffers[s->init_data->buffer_index++]; - s->init_data->curbuf->id = sm_list; - s->init_data->curbuf->head = NULL; - s->init_data->curbuf->tail = NULL; - SCLogDebug("idx %u list %d set up curbuf %p s->init_data->buffer_index %u", - s->init_data->buffer_index - 1, sm_list, s->init_data->curbuf, - s->init_data->buffer_index); + if (!reuse_buffer) { + if (SignatureInitDataBufferCheckExpand(s) < 0) { + SCLogError("failed to expand rule buffer array"); + return -1; + } + + /* initialize a new buffer */ + s->init_data->curbuf = &s->init_data->buffers[s->init_data->buffer_index++]; + s->init_data->curbuf->id = sm_list; + s->init_data->curbuf->head = NULL; + s->init_data->curbuf->tail = NULL; + SCLogDebug("idx %u list %d set up curbuf %p s->init_data->buffer_index %u", + s->init_data->buffer_index - 1, sm_list, s->init_data->curbuf, + s->init_data->buffer_index); + } } /* transfer the sm from the pmatch list to sm_list */ @@ -469,6 +482,18 @@ void SigMatchAppendSMToList(Signature *s, SigMatch *new, const int list) SCLogDebug("reset: list %d != s->init_data->list %d", list, s->init_data->list); s->init_data->list = DETECT_SM_LIST_NOTSET; } + + if (s->init_data->curbuf != NULL && (int)s->init_data->curbuf->id != list) { + for (uint32_t x = 0; x < s->init_data->buffer_index; x++) { + if (s->init_data->buffers[x].id == (uint32_t)list && + !s->init_data->buffers[x].multi_capable) { + SCLogDebug("reusing buffer %u as it isn't multi-capable", x); + s->init_data->curbuf = &s->init_data->buffers[x]; + break; + } + } + } + if ((s->init_data->curbuf != NULL && (int)s->init_data->curbuf->id != list) || s->init_data->curbuf == NULL) { if (SignatureInitDataBufferCheckExpand(s) < 0) { diff --git a/src/detect.h b/src/detect.h index 69a5524e58..04dd49a65a 100644 --- a/src/detect.h +++ b/src/detect.h @@ -515,6 +515,8 @@ typedef struct SignatureInitDataBuffer_ { bool sm_init; /**< initialized by sigmatch, which is likely something like `urilen:10; http.uri; content:"abc";`. These need to be in the same list. Unset once `http.uri` is set up. */ + bool multi_capable; /**< true if we can have multiple instances of this buffer, so e.g. for + http.uri. */ /* sig match list */ SigMatch *head; SigMatch *tail;