diff --git a/src/detect.c b/src/detect.c index 5c37099e05..48747df314 100644 --- a/src/detect.c +++ b/src/detect.c @@ -781,9 +781,7 @@ end: static inline void DetectPrefilterMergeSort(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, SigGroupHead *sgh) { - SigIntId mpm = (SigIntId)-1; - SigIntId nonmpm = (SigIntId)-1; - + SigIntId mpm, nonmpm; det_ctx->match_array_cnt = 0; SigIntId *mpm_ptr = det_ctx->pmq.rule_id_array; SigIntId *nonmpm_ptr = sgh->non_mpm_id_array; @@ -791,45 +789,74 @@ static inline void DetectPrefilterMergeSort(DetectEngineCtx *de_ctx, uint32_t n_cnt = sgh->non_mpm_id_cnt; SCLogDebug("PMQ rule id array count %d", det_ctx->pmq.rule_id_array_cnt); SCLogDebug("SGH non-MPM id count %d", sgh->non_mpm_id_cnt); + SigIntId *final_ptr; + uint32_t final_cnt; + SigIntId id; + SigIntId previous_id = (SigIntId)-1; + Signature **sig_array = de_ctx->sig_array; + Signature **match_array = det_ctx->match_array; + Signature *s; /* Load first values. */ if (likely(m_cnt)) { - mpm = *(mpm_ptr++); - m_cnt--; - } else - mpm = (SigIntId)-1; + mpm = *mpm_ptr; + } else { + /* mpm list is empty */ + final_ptr = nonmpm_ptr; + final_cnt = n_cnt; + goto final; + } if (likely(n_cnt)) { - nonmpm = *(nonmpm_ptr++); - n_cnt--; - } else - nonmpm = (SigIntId)-1; - - SigIntId previous_id = (SigIntId)-1; - Signature **sig_array = de_ctx->sig_array; - Signature **match_array = det_ctx->match_array; - Signature *s; - while (1) { - SigIntId id = MIN(mpm, nonmpm); - - if (unlikely(id == (SigIntId)-1)) - break; - else { - s = sig_array[id]; - - if (id == mpm) { - if (likely(m_cnt)) { - mpm = *(mpm_ptr++); - m_cnt--; - } else - mpm = -1; // TODO - at this point, just copy of remaining array onto the end of the list. - } else { // (id == nonmpm) - if (likely(n_cnt)) { - nonmpm = *(nonmpm_ptr++); - n_cnt--; - } else - nonmpm = -1; - } - } + nonmpm = *nonmpm_ptr; + } else { + /* non-mpm list is empty. */ + final_ptr = mpm_ptr; + final_cnt = m_cnt; + goto final; + } + while (1) { + if (mpm <= nonmpm) { + /* Take from mpm list */ + id = mpm; + + s = sig_array[id]; + /* As the mpm list can contain duplicates, check for that here. */ + if (likely(id != previous_id)) { + *match_array++ = s; + previous_id = id; + } + if (unlikely(--m_cnt == 0)) { + /* mpm list is now empty */ + final_ptr = nonmpm_ptr; + final_cnt = n_cnt; + goto final; + } + mpm_ptr++; + mpm = *mpm_ptr; + } else { + id = nonmpm; + + s = sig_array[id]; + /* As the mpm list can contain duplicates, check for that here. */ + if (likely(id != previous_id)) { + *match_array++ = s; + previous_id = id; + } + if (unlikely(--n_cnt == 0)) { + final_ptr = mpm_ptr; + final_cnt = m_cnt; + goto final; + } + nonmpm_ptr++; + nonmpm = *nonmpm_ptr; + } + } + + final: /* Only one list remaining. Just walk that list. */ + + while (final_cnt-- > 0) { + id = *final_ptr++; + s = sig_array[id]; /* As the mpm list can contain duplicates, check for that here. */ if (likely(id != previous_id)) { @@ -837,6 +864,7 @@ static inline void DetectPrefilterMergeSort(DetectEngineCtx *de_ctx, previous_id = id; } } + det_ctx->match_array_cnt = match_array - det_ctx->match_array; BUG_ON((det_ctx->pmq.rule_id_array_cnt + sgh->non_mpm_id_cnt) < det_ctx->match_array_cnt);