devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
To: Benoit Cousson <bcousson-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
Cc: olof-nZhT3qVonbNeoWH0uzbU5w@public.gmane.org,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	tomasz.figa-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
	swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org,
	grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org,
	rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org,
	khilman-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org,
	linux-omap-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	fparent-rdvid1DuHRBWk0Htik3J/w@public.gmane.org
Subject: Re: [RFC 01/15] scripts/dtc: fix most memory leaks in dtc
Date: Wed, 2 Oct 2013 22:59:34 +1000	[thread overview]
Message-ID: <20131002125934.GF6506@voom.fritz.box> (raw)
In-Reply-To: <1380041541-17529-2-git-send-email-bcousson-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 9048 bytes --]

On Tue, Sep 24, 2013 at 06:52:07PM +0200, Benoit Cousson wrote:
> From: Fabien Parent <fparent-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>

As noted elsewhere, please write patches against upstream dtc, not the
version in the kernel.  git://git.kernel.org/pub/scm/utils/dtc/dtc.git

> There are a few memory leaks in dtc which until now were not that important
> since they were all in the parser and only one instance of the parser was run
> per instance of dtc. The following commits will add a validation of dts through
> schema which have the same syntax as dts, i.e. the parser of dts will be reused
> to parse schema. The consequence is that instead of having the parser running
> only one time for an instance of the dtc process, the parser will run
> many many times and thus the leak that were not important until now becomes
> urgent to fix.

Hrm, yeah.  I'm aware that I haven't been very careful with memory
leaks within the parser.  Essentially, I've been treating the process
as a pool allocator with exactly one pool - I've even considered
getting rid of those free()s we do have.

If the parser's going to be invoked repeatedly, then, yes, that
certainly needs fixing.  Whether individually fixing each leak or
using a explicit pool allocator is a better option is less clear.

> dtc-lexer: Do not duplicate the string which contains literals because the
> string is directly converted afterward to an integer and is never used again.
> livetree: Add a bunch of free helper functions to clean properly the
> dt.

This is no good.  Making this assumption is a layering violation - if
the parser was changed so that this literal wasn't converted until
after another token was read, the yytext value copied in here would no
longer be valid and would break horribly.

> 
> Signed-off-by: Fabien Parent <fparent-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
> Signed-off-by: Benoit Cousson <bcousson-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
> ---
>  scripts/dtc/dtc-lexer.l             |   2 +-
>  scripts/dtc/dtc-lexer.lex.c_shipped |   2 +-
>  scripts/dtc/dtc.c                   |   1 +
>  scripts/dtc/dtc.h                   |   1 +
>  scripts/dtc/livetree.c              | 108 +++++++++++++++++++++++++++++++++---
>  5 files changed, 105 insertions(+), 9 deletions(-)
> 
> diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l
> index 3b41bfc..4f63fbf 100644
> --- a/scripts/dtc/dtc-lexer.l
> +++ b/scripts/dtc/dtc-lexer.l
> @@ -146,7 +146,7 @@ static int pop_input_file(void);
>  		}
>  
>  <V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
> -			yylval.literal = xstrdup(yytext);
> +			yylval.literal = yytext;
>  			DPRINT("Literal: '%s'\n", yylval.literal);
>  			return DT_LITERAL;
>  		}
> diff --git a/scripts/dtc/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped
> index 2d30f41..5c0d27c 100644
> --- a/scripts/dtc/dtc-lexer.lex.c_shipped
> +++ b/scripts/dtc/dtc-lexer.lex.c_shipped
> @@ -1054,7 +1054,7 @@ case 10:
>  YY_RULE_SETUP
>  #line 148 "dtc-lexer.l"
>  {
> -			yylval.literal = xstrdup(yytext);
> +			yylval.literal = yytext;
>  			DPRINT("Literal: '%s'\n", yylval.literal);
>  			return DT_LITERAL;
>  		}
> diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c
> index a375683..215ae92 100644
> --- a/scripts/dtc/dtc.c
> +++ b/scripts/dtc/dtc.c
> @@ -256,5 +256,6 @@ int main(int argc, char *argv[])
>  		die("Unknown output format \"%s\"\n", outform);
>  	}
>  
> +	free_dt(bi);
>  	exit(0);
>  }
> diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h
> index 3e42a07..9c45fd2 100644
> --- a/scripts/dtc/dtc.h
> +++ b/scripts/dtc/dtc.h
> @@ -245,6 +245,7 @@ struct boot_info {
>  struct boot_info *build_boot_info(struct reserve_info *reservelist,
>  				  struct node *tree, uint32_t boot_cpuid_phys);
>  void sort_tree(struct boot_info *bi);
> +void free_dt(struct boot_info *bi);
>  
>  /* Checks */
>  
> diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c
> index b61465f..5c8692c 100644
> --- a/scripts/dtc/livetree.c
> +++ b/scripts/dtc/livetree.c
> @@ -20,6 +20,10 @@
>  
>  #include "dtc.h"
>  
> +static void free_node_list(struct node *n);
> +static void free_node(struct node *n);
> +static void free_property(struct property *p);
> +
>  /*
>   * Tree building functions
>   */
> @@ -144,7 +148,7 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
>  
>  	/* Add new node labels to old node */
>  	for_each_label_withdel(new_node->labels, l)
> -		add_label(&old_node->labels, l->label);
> +		add_label(&old_node->labels, xstrdup(l->label));
>  
>  	/* Move properties from the new node to the old node.  If there
>  	 * is a collision, replace the old value with the new */
> @@ -156,7 +160,7 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
>  
>  		if (new_prop->deleted) {
>  			delete_property_by_name(old_node, new_prop->name);
> -			free(new_prop);
> +			free_property(new_prop);
>  			continue;
>  		}
>  
> @@ -165,7 +169,7 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
>  			if (streq(old_prop->name, new_prop->name)) {
>  				/* Add new labels to old property */
>  				for_each_label_withdel(new_prop->labels, l)
> -					add_label(&old_prop->labels, l->label);
> +					add_label(&old_prop->labels, xstrdup(l->label));
>  
>  				old_prop->val = new_prop->val;
>  				old_prop->deleted = 0;
> @@ -191,7 +195,7 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
>  
>  		if (new_child->deleted) {
>  			delete_node_by_name(old_node, new_child->name);
> -			free(new_child);
> +			free_node(new_child);
>  			continue;
>  		}
>  
> @@ -211,7 +215,7 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
>  
>  	/* The new node contents are now merged into the old node.  Free
>  	 * the new node. */
> -	free(new_node);
> +	free_node(new_node);
>  
>  	return old_node;
>  }
> @@ -532,13 +536,13 @@ cell_t get_node_phandle(struct node *root, struct node *node)
>  	if (!get_property(node, "linux,phandle")
>  	    && (phandle_format & PHANDLE_LEGACY))
>  		add_property(node,
> -			     build_property("linux,phandle",
> +			     build_property(xstrdup("linux,phandle"),
>  					    data_append_cell(empty_data, phandle)));
>  
>  	if (!get_property(node, "phandle")
>  	    && (phandle_format & PHANDLE_EPAPR))
>  		add_property(node,
> -			     build_property("phandle",
> +			     build_property(xstrdup("phandle"),
>  					    data_append_cell(empty_data, phandle)));
>  
>  	/* If the node *does* have a phandle property, we must
> @@ -707,3 +711,93 @@ void sort_tree(struct boot_info *bi)
>  	sort_reserve_entries(bi);
>  	sort_node(bi->dt);
>  }
> +
> +static void free_marker_list(struct marker *m)
> +{
> +	struct marker *marker, *marker_next;
> +
> +	if (!m)
> +		return;
> +
> +	for (marker = m, marker_next = marker ? marker->next : NULL;
> +	     marker;
> +	     marker = marker_next, marker_next = marker ? marker->next : NULL) {

Rather hard to read version of safe-against-free list iteration.

> +		free(marker->ref);
> +		free(marker);
> +	}
> +}
> +
> +static void free_label_list(struct label *l)
> +{
> +	struct label *label, *label_next;
> +
> +	if (!l)
> +		return;
> +
> +	for (label = l, label_next = label ? label->next : NULL;
> +	     label;
> +	     label = label_next, label_next = label ? label->next : NULL) {
> +		free(label->label);
> +		free(label);
> +	}
> +}
> +
> +static void free_property(struct property *p)
> +{
> +	if (!p)
> +		return;
> +
> +	free_label_list(p->labels);
> +	free_marker_list(p->val.markers);
> +	free(p->val.val);
> +	free(p->name);
> +	free(p);
> +}
> +
> +static void free_property_list(struct property *p)
> +{
> +	struct property *next;
> +
> +	if (!p)
> +		return;
> +
> +	for (next = p->next; p; p = next, next = p ? p->next : NULL)
> +		free_property(p);
> +}
> +
> +static void free_node(struct node *n)
> +{
> +	if (!n)
> +		return;
> +
> +	free_node_list(n->children);
> +	free_label_list(n->labels);
> +	free_property_list(n->proplist);
> +	free(n->fullpath);
> +	if (n->name && *n->name)

*n->name .. so, the name can (and must) be statically allocated if
it's exactly "".  Not a useful optimization, I think.

> +		free(n->name);
> +	free(n);
> +}
> +
> +static void free_node_list(struct node *n)
> +{
> +	struct node *next;
> +
> +	if (!n)
> +		return;
> +
> +	for (next = n->next_sibling;
> +	     n;
> +	     n = next, next = n ? n->next_sibling : NULL) {
> +		free_node(n);
> +	}
> +}
> +
> +void free_dt(struct boot_info *bi)
> +{
> +	if (!bi)
> +		return;
> +
> +	free_node_list(bi->dt);
> +	free(bi);
> +}

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

  parent reply	other threads:[~2013-10-02 12:59 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-09-24 16:52 [RFC 00/15] Device Tree schemas and validation Benoit Cousson
2013-09-24 16:52 ` [RFC 01/15] scripts/dtc: fix most memory leaks in dtc Benoit Cousson
     [not found]   ` <1380041541-17529-2-git-send-email-bcousson-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
2013-10-02 12:59     ` David Gibson [this message]
     [not found]       ` <CAOwMV_zAZG3vvWS6pkyK-FbOEg_32KRO-k1SmFSh-pc9+0JiPA@mail.gmail.com>
2013-10-03 14:26         ` Fabien Parent
2013-09-24 16:52 ` [RFC 04/15] scripts/dtc: add procedure to handle dts errors Benoit Cousson
2013-09-24 16:52 ` [RFC 05/15] scripts/dtc: check type on properties Benoit Cousson
2013-09-24 16:52 ` [RFC 07/15] scripts/dtc: can inherit properties Benoit Cousson
2013-09-24 16:52 ` [RFC 11/15] scripts/dtc: check for children nodes Benoit Cousson
2013-09-24 16:52 ` [RFC 12/15] scripts/dtc: check constraints on parents Benoit Cousson
2013-09-24 16:52 ` [RFC 13/15] bindings: OMAP: add new schema files Benoit Cousson
2013-09-24 16:52 ` [RFC 14/15] scripts/dtc: validate dts against schema bindings Benoit Cousson
2013-09-24 16:52 ` [RFC 15/15] scripts/dtc: add verbose options Benoit Cousson
2013-10-01  8:06 ` [RFC 00/15] Device Tree schemas and validation Benoit Cousson
     [not found]   ` <524A8289.3050107-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
2013-10-01 13:17     ` Rob Herring
     [not found]       ` <524ACB76.1010001-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2013-10-01 15:06         ` Benoit Cousson
2013-10-01 15:17           ` Jon Loeliger
2013-10-02  8:24             ` David Gibson
2013-10-02  9:25             ` Benoit Cousson
     [not found]               ` <524BE66D.7060308-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
2013-10-02 13:22                 ` Jon Loeliger
     [not found]           ` <524AE4FB.4080906-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
2013-10-01 20:54             ` Rob Herring
     [not found]               ` <CAL_JsqJ31TGFJCSeSOqgee=OLVfSUTAYdF4nSn7X2DiCequVAw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2013-10-02 13:54                 ` David Gibson
2013-10-02 18:08                   ` Mark Brown
2013-10-02 23:38                     ` David Gibson
2013-10-03  6:52                   ` Benoit Cousson
2013-10-02 13:52         ` David Gibson
     [not found] ` <1380041541-17529-1-git-send-email-bcousson-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
2013-09-24 16:52   ` [RFC 02/15] scripts/dtc: build schema index for dts validation Benoit Cousson
2013-09-24 16:52   ` [RFC 03/15] scripts/dtc: validate each nodes and properties Benoit Cousson
2013-09-24 16:52   ` [RFC 06/15] scripts/dtc: check for required properties Benoit Cousson
2013-09-24 16:52   ` [RFC 08/15] scripts/dtc: check array size Benoit Cousson
2013-09-24 16:52   ` [RFC 09/15] scripts/dtc: check value of properties Benoit Cousson
2013-09-24 16:52   ` [RFC 10/15] scripts/dtc: add count limit on nodes Benoit Cousson
2013-10-01 22:22   ` [RFC 00/15] Device Tree schemas and validation Stephen Warren
     [not found]     ` <524B4B20.4020002-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-10-02 14:29       ` David Gibson
     [not found]         ` <20131002142914.GI6506-RXTfZT5YzpxwFLYp8hBm2A@public.gmane.org>
2013-10-03 13:53           ` Benoit Cousson
2013-10-06  3:02             ` Chaiken, Alison
2013-10-03 13:17     ` Benoit Cousson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20131002125934.GF6506@voom.fritz.box \
    --to=david-xt8fgy+axnrb3ne2bgzf6laj5h9x9tb+@public.gmane.org \
    --cc=bcousson-rdvid1DuHRBWk0Htik3J/w@public.gmane.org \
    --cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=fparent-rdvid1DuHRBWk0Htik3J/w@public.gmane.org \
    --cc=grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org \
    --cc=khilman-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org \
    --cc=linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
    --cc=linux-omap-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=olof-nZhT3qVonbNeoWH0uzbU5w@public.gmane.org \
    --cc=rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org \
    --cc=swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org \
    --cc=tomasz.figa-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).