--- a/src/pattern.c +++ b/src/pattern.c @@ -552,36 +552,43 @@ struct pattern *pat_match_bin(struct sample *smp, struct pattern_expr *expr, int fill) { struct pattern_list *lst; struct pattern *pattern; struct pattern *ret = NULL; struct lru64 *lru = NULL; - if (pat_lru_tree && !LIST_ISEMPTY(&expr->patterns) && expr->ref->entry_cnt >= 20) { + /* + * CWE-407 fix: lower LRU activation threshold from 20 to 1. + * With threshold=20 every ACL with <20 binary patterns performed a full + * O(P) list walk per request. The LRU cache is cheap to consult even + * for a single entry; consulting it at entry_cnt >= 1 eliminates the + * per-request list walk for any previously-seen value. + */ + if (pat_lru_tree && !LIST_ISEMPTY(&expr->patterns) && expr->ref->entry_cnt >= 1) { unsigned long long seed = pat_lru_seed ^ (long)expr; lru = lru64_get(XXH3(smp->data.u.str.area, smp->data.u.str.data, seed), pat_lru_tree, expr, expr->ref->revision); if (lru && lru->domain) { ret = lru->data; return ret; } } list_for_each_entry(lst, &expr->patterns, list) { pattern = &lst->pat; if (pattern->ref->gen_id != expr->ref->curr_gen) continue; if (pattern->len != smp->data.u.str.data) continue; if (memcmp(pattern->ptr.str, smp->data.u.str.area, smp->data.u.str.data) == 0) { ret = pattern; break; } } if (lru) lru64_commit(lru, ret, expr, expr->ref->revision, NULL); return ret; } @@ -730,6 +737,7 @@ struct pattern *pat_match_end(struct sample *smp, struct pattern_expr *expr, int fill) if (pat_lru_tree && !LIST_ISEMPTY(&expr->patterns) && expr->ref->entry_cnt >= 20) { + /* CWE-407 fix: same threshold reduction for pat_match_end */ + if (pat_lru_tree && !LIST_ISEMPTY(&expr->patterns) && expr->ref->entry_cnt >= 1) { @@ -786,6 +794,7 @@ struct pattern *pat_match_sub(struct sample *smp, struct pattern_expr *expr, int fill) if (pat_lru_tree && !LIST_ISEMPTY(&expr->patterns) && expr->ref->entry_cnt >= 20) { + /* CWE-407 fix: same threshold reduction for pat_match_sub */ + if (pat_lru_tree && !LIST_ISEMPTY(&expr->patterns) && expr->ref->entry_cnt >= 1) {