Re: [PATCH v5] Coccinelle: semantic code search for missing put_device()

2019-02-15 Thread Julia Lawall


On Fri, 15 Feb 2019, Markus Elfring wrote:

> > +@search exists@
> > +local idexpression id;
> > +expression x,e,e1;
> > +position p1,p2;
> > +type T,T1,T2,T3;
> > +@@
> > +
> > +id = of_find_device_by_node@p1(x)
> > +... when != e = id
> > +if (id == NULL || ...) { ... return ...; }
> > +... when != put_device(>dev)
> …
> > +when != if (id) { ... put_device(>dev) ... }
> …
>
> I would interpret this SmPL code in the way that the if statement
> for the pointer check is “optional” in this line.
> Is it an extra and redundant SmPL specification when the reference
> release function could eventually be found just anywhere within
> an implementation?

The proposed when code is correct.  It is not redundant, because it checks
for a particular control-flow pattern.

julia

>
>
> Will a need evolve to develop a similar source code search approach
> for safer resource management with other function combinations?
>
> Regards,
> Markus
>

Re: [PATCH v5] Coccinelle: semantic code search for missing put_device()

2019-02-15 Thread Markus Elfring
> +@search exists@
> +local idexpression id;
> +expression x,e,e1;
> +position p1,p2;
> +type T,T1,T2,T3;
> +@@
> +
> +id = of_find_device_by_node@p1(x)
> +... when != e = id
> +if (id == NULL || ...) { ... return ...; }
> +... when != put_device(>dev)
…
> +when != if (id) { ... put_device(>dev) ... }
…

I would interpret this SmPL code in the way that the if statement
for the pointer check is “optional” in this line.
Is it an extra and redundant SmPL specification when the reference
release function could eventually be found just anywhere within
an implementation?


Will a need evolve to develop a similar source code search approach
for safer resource management with other function combinations?

Regards,
Markus


Re: [PATCH v5] coccinelle: semantic code search for missing put_device()

2019-02-15 Thread Markus Elfring
> In a function, for a local variable returned by calling
> of_find_device_by_node(),

I suggest to reconsider this information once more.

1. Will an other wording be more appropriate for the storage of
   a function return value?

2. Can the restriction “local” be omitted?

3. Will any macros be involved eventually?


> c, for the rest of the situation, the current function should release the
>reference by calling put_device,

Can it happen that on other function will perform the desired reference release?


> this code search will report the
>corresponding error message.

Rewording?
A code search can report an error with a specific confidence.


> v5->v4:

Such version information would be sufficient also without arrows, wouldn't it?


> - add a SPDX identifierfix

Would you like to fix a typo at the end?


> +@script:python depends on report@
> +p1 << search.p1;
> +p2 << search.p2;
> +@@
> +
> +coccilib.report.print_report(p2[0], "ERROR: missing put_device; "
> +   + "call of_find_device_by_node on line "
> +   + p1[0].line
> +   + ", but without a corresponding object release "
> +   + "within this function.")

I find your interpretation of my reminder for the preferred avoidance
of split string literals interesting somehow.

Can the following source code variant be more appropriate?

+coccilib.report.print_report(p2[0],
+ "WARNING: missing put_device - 
of_find_device_by_node() call on line "
+ + p1[0].line
+ + ", but without a corresponding object release 
within this function.")


Will any more advanced error diagnostics be eventually developed?

Regards,
Markus


[PATCH v5] coccinelle: semantic code search for missing put_device()

2019-02-14 Thread Wen Yang
The of_find_device_by_node() takes a reference to the underlying device
structure, we should release that reference.
The implementation of this semantic code search is:
In a function, for a local variable returned by calling
of_find_device_by_node(),
a, if it is released by a function such as
   put_device()/of_dev_put()/platform_device_put() after the last use,
   it is considered that there is no reference leak;
b, if it is passed back to the caller via
   dev_get_drvdata()/platform_get_drvdata()/get_device(), etc., the
   reference will be released in other functions, and the current function
   also considers that there is no reference leak;
c, for the rest of the situation, the current function should release the
   reference by calling put_device, this code search will report the
   corresponding error message.

By using this semantic code search, we have found some object reference leaks,
such as:
commit 11907e9d3533 ("ASoC: fsl-asoc-card: fix object reference leaks in
fsl_asoc_card_probe")
commit a12085d13997 ("mtd: rawnand: atmel: fix possible object reference leak")
commit 11493f26856a ("mtd: rawnand: jz4780: fix possible object reference leak")

There are still dozens of reference leaks in the current kernel code.

Further, for the case of b, the object returned to other functions may also
have a reference leak, we will continue to develop other cocci scripts to
further check the reference leak.

Signed-off-by: Wen Yang 
Reviewed-by: Julia Lawall 
Reviewed-by: Markus Elfring 
Cc: Julia Lawall 
Cc: Gilles Muller 
Cc: Nicolas Palix 
Cc: Michal Marek 
Cc: Markus Elfring 
Cc: Masahiro Yamada 
Cc: Wen Yang 
Cc: cheng.shen...@zte.com.cn
Cc: co...@systeme.lip6.fr
Cc: linux-kernel@vger.kernel.org
---
v5->v4:
- exchange the word “patch” by “code search”
- add a SPDX identifierfix
- a split string literal can be unwanted.
- Change the content of the reported information. 
v4->v3:
- add Masahiro Yamada
- omit a blank line
- split the long message parameter
- reduce the number of metavariables
- Describe the implementation of the semantic patch, 
  explain the scenarios it can detect, 
  and further software development considerations.  
v3->v2:
- reduction of a bit of redundant C code within SmPL search specifications.
- consider the message construction without using the extra Python variable 
“msg”
v2->v1:
- put exists after search, and then drop the when exists below.
- should not use the same e as in the when's below.
- Make a new type metavariable and use it to put a cast on the result of 
  platform_get_drvdata.

 scripts/coccinelle/free/put_device.cocci | 56 
 1 file changed, 56 insertions(+)
 create mode 100644 scripts/coccinelle/free/put_device.cocci

diff --git a/scripts/coccinelle/free/put_device.cocci 
b/scripts/coccinelle/free/put_device.cocci
new file mode 100644
index 000..7395697
--- /dev/null
+++ b/scripts/coccinelle/free/put_device.cocci
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0
+/// Find missing put_device for every of_find_device_by_node.
+///
+// Confidence: Moderate
+// Copyright: (C) 2018-2019 Wen Yang, ZTE.
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual report
+virtual org
+
+@search exists@
+local idexpression id;
+expression x,e,e1;
+position p1,p2;
+type T,T1,T2,T3;
+@@
+
+id = of_find_device_by_node@p1(x)
+... when != e = id
+if (id == NULL || ...) { ... return ...; }
+... when != put_device(>dev)
+when != platform_device_put(id)
+when != of_dev_put(id)
+when != if (id) { ... put_device(>dev) ... }
+when != e1 = (T)id
+when != e1 = >dev
+when != e1 = get_device(>dev)
+when != e1 = (T1)platform_get_drvdata(id)
+(
+  return
+(id
+|(T2)dev_get_drvdata(>dev)
+|(T3)platform_get_drvdata(id)
+);
+| return@p2 ...;
+)
+
+@script:python depends on report@
+p1 << search.p1;
+p2 << search.p2;
+@@
+
+coccilib.report.print_report(p2[0], "ERROR: missing put_device; "
+ + "call of_find_device_by_node on line "
+ + p1[0].line
+ + ", but without a corresponding object release "
+ + "within this function.")
+
+@script:python depends on org@
+p1 << search.p1;
+p2 << search.p2;
+@@
+
+cocci.print_main("of_find_device_by_node", p1)
+cocci.print_secs("needed put_device", p2)
-- 
2.9.5