summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2025-04-03 00:32:29 +0200
committerFlorian Westphal <fw@strlen.de>2025-10-29 13:44:11 +0100
commit8720428253d2ee35f59a1d7921da6d2468877257 (patch)
tree6b38205fa114ef4df7e6c23321dcaa66444cdf61 /src
parent2c3edb0cc5ab4acc0b34d4d09db91755cef49712 (diff)
src: add refcount asserts
_get() functions must not be used when refcnt is 0, as expr_free() releases expressions on 1 -> 0 transition. Also, check that a refcount would not overflow from UINT_MAX to 0. Use INT_MAX to also catch refcount leaks sooner, we don't expect 2**31 get()s on same object. This helps catching use-after-free refcounting bugs even when nft is built without ASAN support. v3: use a macro + BUG to get more info without a coredump. Signed-off-by: Florian Westphal <fw@strlen.de>
Diffstat (limited to 'src')
-rw-r--r--src/expression.c5
-rw-r--r--src/rule.c14
2 files changed, 19 insertions, 0 deletions
diff --git a/src/expression.c b/src/expression.c
index 019c263f..6c7bebe0 100644
--- a/src/expression.c
+++ b/src/expression.c
@@ -68,6 +68,7 @@ struct expr *expr_clone(const struct expr *expr)
struct expr *expr_get(struct expr *expr)
{
+ assert_refcount_safe(expr->refcnt);
expr->refcnt++;
return expr;
}
@@ -84,6 +85,8 @@ void expr_free(struct expr *expr)
{
if (expr == NULL)
return;
+
+ assert_refcount_safe(expr->refcnt);
if (--expr->refcnt > 0)
return;
@@ -343,11 +346,13 @@ static void variable_expr_clone(struct expr *new, const struct expr *expr)
new->scope = expr->scope;
new->sym = expr->sym;
+ assert_refcount_safe(expr->sym->refcnt);
expr->sym->refcnt++;
}
static void variable_expr_destroy(struct expr *expr)
{
+ assert_refcount_safe(expr->sym->refcnt);
expr->sym->refcnt--;
}
diff --git a/src/rule.c b/src/rule.c
index d0a62a3e..f51d605c 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -181,6 +181,7 @@ struct set *set_clone(const struct set *set)
struct set *set_get(struct set *set)
{
+ assert_refcount_safe(set->refcnt);
set->refcnt++;
return set;
}
@@ -189,6 +190,7 @@ void set_free(struct set *set)
{
struct stmt *stmt, *next;
+ assert_refcount_safe(set->refcnt);
if (--set->refcnt > 0)
return;
@@ -484,12 +486,14 @@ struct rule *rule_alloc(const struct location *loc, const struct handle *h)
struct rule *rule_get(struct rule *rule)
{
+ assert_refcount_safe(rule->refcnt);
rule->refcnt++;
return rule;
}
void rule_free(struct rule *rule)
{
+ assert_refcount_safe(rule->refcnt);
if (--rule->refcnt > 0)
return;
stmt_list_free(&rule->stmts);
@@ -606,6 +610,7 @@ struct symbol *symbol_get(const struct scope *scope, const char *identifier)
if (!sym)
return NULL;
+ assert_refcount_safe(sym->refcnt);
sym->refcnt++;
return sym;
@@ -613,6 +618,7 @@ struct symbol *symbol_get(const struct scope *scope, const char *identifier)
static void symbol_put(struct symbol *sym)
{
+ assert_refcount_safe(sym->refcnt);
if (--sym->refcnt == 0) {
free_const(sym->identifier);
expr_free(sym->expr);
@@ -732,6 +738,7 @@ struct chain *chain_alloc(void)
struct chain *chain_get(struct chain *chain)
{
+ assert_refcount_safe(chain->refcnt);
chain->refcnt++;
return chain;
}
@@ -741,6 +748,7 @@ void chain_free(struct chain *chain)
struct rule *rule, *next;
int i;
+ assert_refcount_safe(chain->refcnt);
if (--chain->refcnt > 0)
return;
list_for_each_entry_safe(rule, next, &chain->rules, list)
@@ -1176,6 +1184,7 @@ void table_free(struct table *table)
struct set *set, *nset;
struct obj *obj, *nobj;
+ assert_refcount_safe(table->refcnt);
if (--table->refcnt > 0)
return;
if (table->comment)
@@ -1214,6 +1223,7 @@ void table_free(struct table *table)
struct table *table_get(struct table *table)
{
+ assert_refcount_safe(table->refcnt);
table->refcnt++;
return table;
}
@@ -1687,12 +1697,14 @@ struct obj *obj_alloc(const struct location *loc)
struct obj *obj_get(struct obj *obj)
{
+ assert_refcount_safe(obj->refcnt);
obj->refcnt++;
return obj;
}
void obj_free(struct obj *obj)
{
+ assert_refcount_safe(obj->refcnt);
if (--obj->refcnt > 0)
return;
free_const(obj->comment);
@@ -2270,6 +2282,7 @@ struct flowtable *flowtable_alloc(const struct location *loc)
struct flowtable *flowtable_get(struct flowtable *flowtable)
{
+ assert_refcount_safe(flowtable->refcnt);
flowtable->refcnt++;
return flowtable;
}
@@ -2278,6 +2291,7 @@ void flowtable_free(struct flowtable *flowtable)
{
int i;
+ assert_refcount_safe(flowtable->refcnt);
if (--flowtable->refcnt > 0)
return;
handle_free(&flowtable->handle);