summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2019-06-11 17:16:50 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2019-06-13 12:22:29 +0200
commit01a13882bb59a6960904a7a78ad608146a6dc510 (patch)
tree67e4d57beb48ea2ac87fc3f2371ec6ca54e6cc92 /include
parent29d0b6b0526ed9b661db9f1c8dbd2abbff11483a (diff)
src: add reference counter for dynamic datatypes
There are two datatypes are using runtime datatype allocation: * Concatenations. * Integer, that require byteorder adjustment. From the evaluation / postprocess step, transformations are common, hence expressions may end up fetching (infering) datatypes from an existing one. This patch adds a reference counter to release the dynamic datatype object when it is shared. The API includes the following helper functions: * datatype_set(expr, datatype), to assign a datatype to an expression. This helper already deals with reference counting for dynamic datatypes. This also drops the reference counter of any previous datatype (to deal with the datatype replacement case). * datatype_get(datatype) bumps the reference counter. This function also deals with nul-pointers, that occurs when the datatype is unset. * datatype_free() drops the reference counter, and it also releases the datatype if there are not more clients of it. Rule of thumb is: The reference counter of any newly allocated datatype is set to zero. This patch also updates every spot to use datatype_set() for non-dynamic datatypes, for consistency. In this case, the helper just makes an simple assignment. Note that expr_alloc() has been updated to call datatype_get() on the datatype that is assigned to this new expression. Moreover, expr_free() calls datatype_free(). This fixes valgrind reports like this one: ==28352== 1,350 (440 direct, 910 indirect) bytes in 5 blocks are definitely lost in loss recor 3 of 3 ==28352== at 0x4C2BBAF: malloc (vg_replace_malloc.c:299) ==28352== by 0x4E79558: xmalloc (utils.c:36) ==28352== by 0x4E7963D: xzalloc (utils.c:65) ==28352== by 0x4E6029B: dtype_alloc (datatype.c:1073) ==28352== by 0x4E6029B: concat_type_alloc (datatype.c:1127) ==28352== by 0x4E6D3B3: netlink_delinearize_set (netlink.c:578) ==28352== by 0x4E6D68E: list_set_cb (netlink.c:648) ==28352== by 0x5D74023: nftnl_set_list_foreach (set.c:780) ==28352== by 0x4E6D6F3: netlink_list_sets (netlink.c:669) ==28352== by 0x4E5A7A3: cache_init_objects (rule.c:159) ==28352== by 0x4E5A7A3: cache_init (rule.c:216) ==28352== by 0x4E5A7A3: cache_update (rule.c:266) ==28352== by 0x4E7E0EE: nft_evaluate (libnftables.c:388) ==28352== by 0x4E7EADD: nft_run_cmd_from_filename (libnftables.c:479) ==28352== by 0x109A53: main (main.c:310) This patch also removes the DTYPE_F_CLONE flag which is broken and not needed anymore since proper reference counting is in place. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'include')
-rw-r--r--include/datatype.h7
-rw-r--r--include/expression.h2
2 files changed, 6 insertions, 3 deletions
diff --git a/include/datatype.h b/include/datatype.h
index 14ece282..23f45ab7 100644
--- a/include/datatype.h
+++ b/include/datatype.h
@@ -117,12 +117,10 @@ struct expr;
*
* @DTYPE_F_ALLOC: datatype is dynamically allocated
* @DTYPE_F_PREFIX: preferred representation for ranges is a prefix
- * @DTYPE_F_CLONE: this is an instance from original datatype
*/
enum datatype_flags {
DTYPE_F_ALLOC = (1 << 0),
DTYPE_F_PREFIX = (1 << 1),
- DTYPE_F_CLONE = (1 << 2),
};
/**
@@ -140,6 +138,7 @@ enum datatype_flags {
* @print: function to print a constant of this type
* @parse: function to parse a symbol and return an expression
* @sym_tbl: symbol table for this type
+ * @refcnt: reference counter (only for DTYPE_F_ALLOC)
*/
struct datatype {
uint32_t type;
@@ -158,10 +157,14 @@ struct datatype {
struct error_record *(*parse)(const struct expr *sym,
struct expr **res);
const struct symbol_table *sym_tbl;
+ unsigned int refcnt;
};
extern const struct datatype *datatype_lookup(enum datatypes type);
extern const struct datatype *datatype_lookup_byname(const char *name);
+extern struct datatype *datatype_get(const struct datatype *dtype);
+extern void datatype_set(struct expr *expr, const struct datatype *dtype);
+extern void datatype_free(const struct datatype *dtype);
extern struct error_record *symbol_parse(const struct expr *sym,
struct expr **res);
diff --git a/include/expression.h b/include/expression.h
index ef412554..4de53682 100644
--- a/include/expression.h
+++ b/include/expression.h
@@ -415,7 +415,7 @@ static inline void symbol_expr_set_type(struct expr *expr,
const struct datatype *dtype)
{
if (expr->etype == EXPR_SYMBOL)
- expr->dtype = dtype;
+ datatype_set(expr, dtype);
}
struct expr *variable_expr_alloc(const struct location *loc,