aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2016-02-21 15:35:12 +0200
committerSergey Poznyakoff <gray@gnu.org>2016-02-21 15:35:12 +0200
commita3f25ce24dcaff123fb71db89419d3ae12ddb57a (patch)
tree4c0875505707d167b3529c75ce208c3d7eab23c4
parent08070e48d83cd34cddb08be33cf4993fc096c9c4 (diff)
downloadgrecs-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.
-rw-r--r--src/grecs.hin16
-rw-r--r--src/tree.c11
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
@@ -97,12 +97,16 @@ enum grecs_data_type {
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,
diff --git a/src/tree.c b/src/tree.c
index 4f3189c..eea90a5 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -546,7 +546,7 @@ string_to_sockaddr(struct grecs_sockaddr *sp, const char *string,
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:
@@ -556,7 +556,7 @@ grecs_string_convert(void *target, enum grecs_data_type type,
break;
case grecs_type_string:
- *(const char**)target = grecs_strdup(string);
+ *(char**)target = grecs_strdup(string);
break;
case grecs_type_short:
@@ -824,10 +824,15 @@ grecs_process_ident(struct grecs_keyword *kwp, grecs_value_t *value,
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;
}

Return to:

Send suggestions and report system problems to the System administrator.