diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2016-02-21 15:35:12 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2016-02-21 15:35:12 +0200 |
commit | a3f25ce24dcaff123fb71db89419d3ae12ddb57a (patch) | |
tree | 4c0875505707d167b3529c75ce208c3d7eab23c4 /src | |
parent | 08070e48d83cd34cddb08be33cf4993fc096c9c4 (diff) | |
download | grecs-a3f25ce24dcaff123fb71db89419d3ae12ddb57a.tar.gz grecs-a3f25ce24dcaff123fb71db89419d3ae12ddb57a.tar.bz2 |
Prevent memory leaks when re-processing values of string type.
* src/grecs.hin (GRECS_CONST): New flag.
* src/tree.c (grecs_string_convert): For string types, free the
old value prior to assigning the new one, unless the GRECS_CONST
flag is set. In any case, clear the GRECS_CONST flag after
assigning new value.
Diffstat (limited to 'src')
-rw-r--r-- | src/grecs.hin | 16 | ||||
-rw-r--r-- | src/tree.c | 11 |
2 files changed, 18 insertions, 9 deletions
diff --git a/src/grecs.hin b/src/grecs.hin index 48e2937..812834f 100644 --- a/src/grecs.hin +++ b/src/grecs.hin @@ -94,18 +94,22 @@ enum grecs_data_type { grecs_type_host, grecs_type_sockaddr, grecs_type_section, grecs_type_null }; -#define GRECS_DFLT 0x00 -#define GRECS_AGGR 0x01 -#define GRECS_MULT 0x02 -#define GRECS_INAC 0x04 -#define GRECS_LIST 0x08 -#define GRECS_HIDDEN 0x10 +#define GRECS_DFLT 0x00 /* Default keyword flags */ +#define GRECS_AGGR 0x01 /* Multiple entries aggregate */ +#define GRECS_MULT 0x02 /* Statement can appear multiple times */ +#define GRECS_INAC 0x04 /* Inactive keyword */ +#define GRECS_LIST 0x08 /* Value is a list of declared type */ +#define GRECS_HIDDEN 0x10 /* Hidden keyword: don't display in help output */ +#define GRECS_CONST 0x20 /* For string types: initial value is constant, + don't try to free it before assigning new value. + This flag is cleared after the first assignment. + */ enum grecs_callback_command { grecs_callback_section_begin, grecs_callback_section_end, grecs_callback_set_value }; @@ -543,23 +543,23 @@ string_to_sockaddr(struct grecs_sockaddr *sp, const char *string, res = sign ? - tmpres : tmpres; \ } int grecs_string_convert(void *target, enum grecs_data_type type, - const char *string, grecs_locus_t const *locus) + const char *string, grecs_locus_t const *locus) { switch (type) { case grecs_type_void: abort(); case grecs_type_null: break; case grecs_type_string: - *(const char**)target = grecs_strdup(string); + *(char**)target = grecs_strdup(string); break; case grecs_type_short: GETUNUM(string, short, *(short*)target, locus); break; @@ -821,16 +821,21 @@ grecs_process_ident(struct grecs_keyword *kwp, grecs_value_t *value, grecs_list_free(list); return; } grecs_list_append(list, ptr); } *(struct grecs_list**)target = list; - } else + } else { + if (kwp->type == grecs_type_string + && !(kwp->flags & GRECS_CONST)) + free(*(char**)target); grecs_string_convert(target, kwp->type, value->v.string, &value->locus); + } + kwp->flags &= ~GRECS_CONST; } struct nodeproc_closure { struct grecs_keyword *cursect; struct grecs_list *sections; |