david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

[settings] Avoid memory leak when unregistering autovivified settings blocks

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown 2011-03-23 20:17:24 +00:00
parent fa6182e5f4
commit 071b4000d9
1 changed files with 27 additions and 3 deletions

View File

@ -230,6 +230,27 @@ struct generic_settings generic_settings_root = {
/** Root settings block */ /** Root settings block */
#define settings_root generic_settings_root.settings #define settings_root generic_settings_root.settings
/** Autovivified settings block */
struct autovivified_settings {
/** Reference count */
struct refcnt refcnt;
/** Generic settings block */
struct generic_settings generic;
};
/**
* Free autovivified settings block
*
* @v refcnt Reference count
*/
static void autovivified_settings_free ( struct refcnt *refcnt ) {
struct autovivified_settings *autovivified =
container_of ( refcnt, struct autovivified_settings, refcnt );
generic_settings_clear ( &autovivified->generic.settings );
free ( autovivified );
}
/** /**
* Find child named settings block * Find child named settings block
* *
@ -264,7 +285,7 @@ static struct settings * find_child_settings ( struct settings *parent,
static struct settings * autovivify_child_settings ( struct settings *parent, static struct settings * autovivify_child_settings ( struct settings *parent,
const char *name ) { const char *name ) {
struct { struct {
struct generic_settings generic; struct autovivified_settings autovivified;
char name[ strlen ( name ) + 1 /* NUL */ ]; char name[ strlen ( name ) + 1 /* NUL */ ];
} *new_child; } *new_child;
struct settings *settings; struct settings *settings;
@ -281,8 +302,11 @@ static struct settings * autovivify_child_settings ( struct settings *parent,
return NULL; return NULL;
} }
memcpy ( new_child->name, name, sizeof ( new_child->name ) ); memcpy ( new_child->name, name, sizeof ( new_child->name ) );
generic_settings_init ( &new_child->generic, NULL ); ref_init ( &new_child->autovivified.refcnt,
settings = &new_child->generic.settings; autovivified_settings_free );
generic_settings_init ( &new_child->autovivified.generic,
&new_child->autovivified.refcnt );
settings = &new_child->autovivified.generic.settings;
register_settings ( settings, parent, new_child->name ); register_settings ( settings, parent, new_child->name );
return settings; return settings;
} }