Merge branch 'for-5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/jlawall/linux
Pull coccinelle updates from Julia Lawall. * 'for-5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/jlawall/linux: coccinelle: api: add kfree_mismatch script coccinelle: iterators: Add for_each_child.cocci script scripts: coccicheck: Change default condition for parallelism scripts: coccicheck: Add quotes to improve portability coccinelle: api: kfree_sensitive: print memset position coccinelle: misc: add flexible_array.cocci script coccinelle: api: add kvmalloc script scripts: coccicheck: Change default value for parallelism coccinelle: misc: add excluded_middle.cocci script scripts: coccicheck: Improve error feedback when coccicheck fails coccinelle: api: update kzfree script to kfree_sensitive coccinelle: misc: add uninitialized_var.cocci script coccinelle: ifnullfree: add vfree(), kvfree*() functions coccinelle: api: add kobj_to_dev.cocci script coccinelle: add patch rule for dma_alloc_coherent scripts: coccicheck: Add chain mode to list of modes
This commit is contained in:
commit
f66179ca7a
|
@ -75,8 +75,13 @@ else
|
||||||
OPTIONS="--dir $KBUILD_EXTMOD $COCCIINCLUDE"
|
OPTIONS="--dir $KBUILD_EXTMOD $COCCIINCLUDE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Use only one thread per core by default if hyperthreading is enabled
|
||||||
|
THREADS_PER_CORE=$(lscpu | grep "Thread(s) per core: " | tr -cd "[:digit:]")
|
||||||
if [ -z "$J" ]; then
|
if [ -z "$J" ]; then
|
||||||
NPROC=$(getconf _NPROCESSORS_ONLN)
|
NPROC=$(getconf _NPROCESSORS_ONLN)
|
||||||
|
if [ $THREADS_PER_CORE -gt 1 -a $NPROC -gt 4 ] ; then
|
||||||
|
NPROC=$((NPROC/2))
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
NPROC="$J"
|
NPROC="$J"
|
||||||
fi
|
fi
|
||||||
|
@ -99,7 +104,7 @@ fi
|
||||||
if [ "$MODE" = "" ] ; then
|
if [ "$MODE" = "" ] ; then
|
||||||
if [ "$ONLINE" = "0" ] ; then
|
if [ "$ONLINE" = "0" ] ; then
|
||||||
echo 'You have not explicitly specified the mode to use. Using default "report" mode.'
|
echo 'You have not explicitly specified the mode to use. Using default "report" mode.'
|
||||||
echo 'Available modes are the following: patch, report, context, org'
|
echo 'Available modes are the following: patch, report, context, org, chain'
|
||||||
echo 'You can specify the mode with "make coccicheck MODE=<mode>"'
|
echo 'You can specify the mode with "make coccicheck MODE=<mode>"'
|
||||||
echo 'Note however that some modes are not implemented by some semantic patches.'
|
echo 'Note however that some modes are not implemented by some semantic patches.'
|
||||||
fi
|
fi
|
||||||
|
@ -126,8 +131,14 @@ run_cmd_parmap() {
|
||||||
if [ $VERBOSE -ne 0 ] ; then
|
if [ $VERBOSE -ne 0 ] ; then
|
||||||
echo "Running ($NPROC in parallel): $@"
|
echo "Running ($NPROC in parallel): $@"
|
||||||
fi
|
fi
|
||||||
echo $@ >>$DEBUG_FILE
|
if [ "$DEBUG_FILE" != "/dev/null" -a "$DEBUG_FILE" != "" ]; then
|
||||||
$@ 2>>$DEBUG_FILE
|
echo $@>>$DEBUG_FILE
|
||||||
|
$@ 2>>$DEBUG_FILE
|
||||||
|
else
|
||||||
|
echo $@
|
||||||
|
$@ 2>&1
|
||||||
|
fi
|
||||||
|
|
||||||
err=$?
|
err=$?
|
||||||
if [[ $err -ne 0 ]]; then
|
if [[ $err -ne 0 ]]; then
|
||||||
echo "coccicheck failed"
|
echo "coccicheck failed"
|
||||||
|
|
|
@ -127,6 +127,16 @@ statement S;
|
||||||
if ((x==NULL) || ...) S
|
if ((x==NULL) || ...) S
|
||||||
- memset((T2)x,0,E1);
|
- memset((T2)x,0,E1);
|
||||||
|
|
||||||
|
@depends on patch@
|
||||||
|
type T, T2;
|
||||||
|
expression x;
|
||||||
|
expression E1,E2,E3,E4;
|
||||||
|
statement S;
|
||||||
|
@@
|
||||||
|
x = (T)dma_alloc_coherent(E1, E2, E3, E4);
|
||||||
|
if ((x==NULL) || ...) S
|
||||||
|
- memset((T2)x, 0, E2);
|
||||||
|
|
||||||
//----------------------------------------------------------
|
//----------------------------------------------------------
|
||||||
// For org mode
|
// For org mode
|
||||||
//----------------------------------------------------------
|
//----------------------------------------------------------
|
||||||
|
@ -199,9 +209,9 @@ statement S;
|
||||||
position p;
|
position p;
|
||||||
@@
|
@@
|
||||||
|
|
||||||
x = (T)dma_alloc_coherent@p(E2,E1,E3,E4);
|
x = (T)dma_alloc_coherent@p(E1,E2,E3,E4);
|
||||||
if ((x==NULL) || ...) S
|
if ((x==NULL) || ...) S
|
||||||
memset((T2)x,0,E1);
|
memset((T2)x,0,E2);
|
||||||
|
|
||||||
@script:python depends on org@
|
@script:python depends on org@
|
||||||
p << r2.p;
|
p << r2.p;
|
||||||
|
@ -217,7 +227,7 @@ p << r2.p;
|
||||||
x << r2.x;
|
x << r2.x;
|
||||||
@@
|
@@
|
||||||
|
|
||||||
msg="WARNING: dma_alloc_coherent use in %s already zeroes out memory, so memset is not needed" % (x)
|
msg="WARNING: dma_alloc_coherent used in %s already zeroes out memory, so memset is not needed" % (x)
|
||||||
coccilib.report.print_report(p[0], msg)
|
coccilib.report.print_report(p[0], msg)
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
|
|
|
@ -0,0 +1,228 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
///
|
||||||
|
/// Check that kvmalloc'ed memory is freed by kfree functions,
|
||||||
|
/// vmalloc'ed by vfree functions and kvmalloc'ed by kvfree
|
||||||
|
/// functions.
|
||||||
|
///
|
||||||
|
// Confidence: High
|
||||||
|
// Copyright: (C) 2020 Denis Efremov ISPRAS
|
||||||
|
// Options: --no-includes --include-headers
|
||||||
|
//
|
||||||
|
|
||||||
|
virtual patch
|
||||||
|
virtual report
|
||||||
|
virtual org
|
||||||
|
virtual context
|
||||||
|
|
||||||
|
@alloc@
|
||||||
|
expression E, E1;
|
||||||
|
position kok, vok;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
if (...) {
|
||||||
|
...
|
||||||
|
E = \(kmalloc\|kzalloc\|krealloc\|kcalloc\|
|
||||||
|
kmalloc_node\|kzalloc_node\|kmalloc_array\|
|
||||||
|
kmalloc_array_node\|kcalloc_node\)(...)@kok
|
||||||
|
...
|
||||||
|
} else {
|
||||||
|
...
|
||||||
|
E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\|
|
||||||
|
vzalloc_node\|vmalloc_exec\|vmalloc_32\|
|
||||||
|
vmalloc_32_user\|__vmalloc\|__vmalloc_node_range\|
|
||||||
|
__vmalloc_node\)(...)@vok
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
|
||||||
|
E = \(kmalloc\|kzalloc\|krealloc\|kcalloc\|kmalloc_node\|kzalloc_node\|
|
||||||
|
kmalloc_array\|kmalloc_array_node\|kcalloc_node\)(...)@kok
|
||||||
|
... when != E = E1
|
||||||
|
when any
|
||||||
|
if (E == NULL) {
|
||||||
|
...
|
||||||
|
E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\|
|
||||||
|
vzalloc_node\|vmalloc_exec\|vmalloc_32\|
|
||||||
|
vmalloc_32_user\|__vmalloc\|__vmalloc_node_range\|
|
||||||
|
__vmalloc_node\)(...)@vok
|
||||||
|
...
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
@free@
|
||||||
|
expression E;
|
||||||
|
position fok;
|
||||||
|
@@
|
||||||
|
|
||||||
|
E = \(kvmalloc\|kvzalloc\|kvcalloc\|kvzalloc_node\|kvmalloc_node\|
|
||||||
|
kvmalloc_array\)(...)
|
||||||
|
...
|
||||||
|
kvfree(E)@fok
|
||||||
|
|
||||||
|
@vfree depends on !patch@
|
||||||
|
expression E;
|
||||||
|
position a != alloc.kok;
|
||||||
|
position f != free.fok;
|
||||||
|
@@
|
||||||
|
|
||||||
|
* E = \(kmalloc\|kzalloc\|krealloc\|kcalloc\|kmalloc_node\|
|
||||||
|
* kzalloc_node\|kmalloc_array\|kmalloc_array_node\|
|
||||||
|
* kcalloc_node\)(...)@a
|
||||||
|
... when != if (...) { ... E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\|vzalloc_node\|vmalloc_exec\|vmalloc_32\|vmalloc_32_user\|__vmalloc\|__vmalloc_node_range\|__vmalloc_node\)(...); ... }
|
||||||
|
when != is_vmalloc_addr(E)
|
||||||
|
when any
|
||||||
|
* \(vfree\|vfree_atomic\|kvfree\)(E)@f
|
||||||
|
|
||||||
|
@depends on patch exists@
|
||||||
|
expression E;
|
||||||
|
position a != alloc.kok;
|
||||||
|
position f != free.fok;
|
||||||
|
@@
|
||||||
|
|
||||||
|
E = \(kmalloc\|kzalloc\|krealloc\|kcalloc\|kmalloc_node\|
|
||||||
|
kzalloc_node\|kmalloc_array\|kmalloc_array_node\|
|
||||||
|
kcalloc_node\)(...)@a
|
||||||
|
... when != if (...) { ... E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\|vzalloc_node\|vmalloc_exec\|vmalloc_32\|vmalloc_32_user\|__vmalloc\|__vmalloc_node_range\|__vmalloc_node\)(...); ... }
|
||||||
|
when != is_vmalloc_addr(E)
|
||||||
|
when any
|
||||||
|
- \(vfree\|vfree_atomic\|kvfree\)(E)@f
|
||||||
|
+ kfree(E)
|
||||||
|
|
||||||
|
@kfree depends on !patch@
|
||||||
|
expression E;
|
||||||
|
position a != alloc.vok;
|
||||||
|
position f != free.fok;
|
||||||
|
@@
|
||||||
|
|
||||||
|
* E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\|vzalloc_node\|
|
||||||
|
* vmalloc_exec\|vmalloc_32\|vmalloc_32_user\|__vmalloc\|
|
||||||
|
* __vmalloc_node_range\|__vmalloc_node\)(...)@a
|
||||||
|
... when != is_vmalloc_addr(E)
|
||||||
|
when any
|
||||||
|
* \(kfree\|kfree_sensitive\|kvfree\)(E)@f
|
||||||
|
|
||||||
|
@depends on patch exists@
|
||||||
|
expression E;
|
||||||
|
position a != alloc.vok;
|
||||||
|
position f != free.fok;
|
||||||
|
@@
|
||||||
|
|
||||||
|
E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\|vzalloc_node\|
|
||||||
|
vmalloc_exec\|vmalloc_32\|vmalloc_32_user\|__vmalloc\|
|
||||||
|
__vmalloc_node_range\|__vmalloc_node\)(...)@a
|
||||||
|
... when != is_vmalloc_addr(E)
|
||||||
|
when any
|
||||||
|
- \(kfree\|kvfree\)(E)@f
|
||||||
|
+ vfree(E)
|
||||||
|
|
||||||
|
@kvfree depends on !patch@
|
||||||
|
expression E;
|
||||||
|
position a, f;
|
||||||
|
@@
|
||||||
|
|
||||||
|
* E = \(kvmalloc\|kvzalloc\|kvcalloc\|kvzalloc_node\|kvmalloc_node\|
|
||||||
|
* kvmalloc_array\)(...)@a
|
||||||
|
... when != is_vmalloc_addr(E)
|
||||||
|
when any
|
||||||
|
* \(kfree\|kfree_sensitive\|vfree\|vfree_atomic\)(E)@f
|
||||||
|
|
||||||
|
@depends on patch exists@
|
||||||
|
expression E;
|
||||||
|
@@
|
||||||
|
|
||||||
|
E = \(kvmalloc\|kvzalloc\|kvcalloc\|kvzalloc_node\|kvmalloc_node\|
|
||||||
|
kvmalloc_array\)(...)
|
||||||
|
... when != is_vmalloc_addr(E)
|
||||||
|
when any
|
||||||
|
- \(kfree\|vfree\)(E)
|
||||||
|
+ kvfree(E)
|
||||||
|
|
||||||
|
@kvfree_switch depends on !patch@
|
||||||
|
expression alloc.E;
|
||||||
|
position f;
|
||||||
|
@@
|
||||||
|
|
||||||
|
... when != is_vmalloc_addr(E)
|
||||||
|
when any
|
||||||
|
* \(kfree\|kfree_sensitive\|vfree\|vfree_atomic\)(E)@f
|
||||||
|
|
||||||
|
@depends on patch exists@
|
||||||
|
expression alloc.E;
|
||||||
|
position f;
|
||||||
|
@@
|
||||||
|
|
||||||
|
... when != is_vmalloc_addr(E)
|
||||||
|
when any
|
||||||
|
(
|
||||||
|
- \(kfree\|vfree\)(E)@f
|
||||||
|
+ kvfree(E)
|
||||||
|
|
|
||||||
|
- kfree_sensitive(E)@f
|
||||||
|
+ kvfree_sensitive(E)
|
||||||
|
)
|
||||||
|
|
||||||
|
@script: python depends on report@
|
||||||
|
a << vfree.a;
|
||||||
|
f << vfree.f;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "WARNING kmalloc is used to allocate this memory at line %s" % (a[0].line)
|
||||||
|
coccilib.report.print_report(f[0], msg)
|
||||||
|
|
||||||
|
@script: python depends on org@
|
||||||
|
a << vfree.a;
|
||||||
|
f << vfree.f;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "WARNING kmalloc is used to allocate this memory at line %s" % (a[0].line)
|
||||||
|
coccilib.org.print_todo(f[0], msg)
|
||||||
|
|
||||||
|
@script: python depends on report@
|
||||||
|
a << kfree.a;
|
||||||
|
f << kfree.f;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "WARNING vmalloc is used to allocate this memory at line %s" % (a[0].line)
|
||||||
|
coccilib.report.print_report(f[0], msg)
|
||||||
|
|
||||||
|
@script: python depends on org@
|
||||||
|
a << kfree.a;
|
||||||
|
f << kfree.f;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "WARNING vmalloc is used to allocate this memory at line %s" % (a[0].line)
|
||||||
|
coccilib.org.print_todo(f[0], msg)
|
||||||
|
|
||||||
|
@script: python depends on report@
|
||||||
|
a << kvfree.a;
|
||||||
|
f << kvfree.f;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "WARNING kvmalloc is used to allocate this memory at line %s" % (a[0].line)
|
||||||
|
coccilib.report.print_report(f[0], msg)
|
||||||
|
|
||||||
|
@script: python depends on org@
|
||||||
|
a << kvfree.a;
|
||||||
|
f << kvfree.f;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "WARNING kvmalloc is used to allocate this memory at line %s" % (a[0].line)
|
||||||
|
coccilib.org.print_todo(f[0], msg)
|
||||||
|
|
||||||
|
@script: python depends on report@
|
||||||
|
ka << alloc.kok;
|
||||||
|
va << alloc.vok;
|
||||||
|
f << kvfree_switch.f;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "WARNING kmalloc (line %s) && vmalloc (line %s) are used to allocate this memory" % (ka[0].line, va[0].line)
|
||||||
|
coccilib.report.print_report(f[0], msg)
|
||||||
|
|
||||||
|
@script: python depends on org@
|
||||||
|
ka << alloc.kok;
|
||||||
|
va << alloc.vok;
|
||||||
|
f << kvfree_switch.f;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "WARNING kmalloc (line %s) && vmalloc (line %s) are used to allocate this memory" % (ka[0].line, va[0].line)
|
||||||
|
coccilib.org.print_todo(f[0], msg)
|
|
@ -1,13 +1,13 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
///
|
///
|
||||||
/// Use kzfree, kvfree_sensitive rather than memset or
|
/// Use kfree_sensitive, kvfree_sensitive rather than memset or
|
||||||
/// memzero_explicit followed by kfree
|
/// memzero_explicit followed by kfree.
|
||||||
///
|
///
|
||||||
// Confidence: High
|
// Confidence: High
|
||||||
// Copyright: (C) 2020 Denis Efremov ISPRAS
|
// Copyright: (C) 2020 Denis Efremov ISPRAS
|
||||||
// Options: --no-includes --include-headers
|
// Options: --no-includes --include-headers
|
||||||
//
|
//
|
||||||
// Keywords: kzfree, kvfree_sensitive
|
// Keywords: kfree_sensitive, kvfree_sensitive
|
||||||
//
|
//
|
||||||
|
|
||||||
virtual context
|
virtual context
|
||||||
|
@ -18,7 +18,8 @@ virtual report
|
||||||
@initialize:python@
|
@initialize:python@
|
||||||
@@
|
@@
|
||||||
# kmalloc_oob_in_memset uses memset to explicitly trigger out-of-bounds access
|
# kmalloc_oob_in_memset uses memset to explicitly trigger out-of-bounds access
|
||||||
filter = frozenset(['kmalloc_oob_in_memset', 'kzfree', 'kvfree_sensitive'])
|
filter = frozenset(['kmalloc_oob_in_memset',
|
||||||
|
'kfree_sensitive', 'kvfree_sensitive'])
|
||||||
|
|
||||||
def relevant(p):
|
def relevant(p):
|
||||||
return not (filter & {el.current_element for el in p})
|
return not (filter & {el.current_element for el in p})
|
||||||
|
@ -56,17 +57,13 @@ type T;
|
||||||
- memzero_explicit@m((T)E, size);
|
- memzero_explicit@m((T)E, size);
|
||||||
... when != E
|
... when != E
|
||||||
when strict
|
when strict
|
||||||
// TODO: uncomment when kfree_sensitive will be merged.
|
(
|
||||||
// Only this case is commented out because developers
|
- kfree(E)@p;
|
||||||
// may not like patches like this since kzfree uses memset
|
+ kfree_sensitive(E);
|
||||||
// internally (not memzero_explicit).
|
|
|
||||||
//(
|
|
||||||
//- kfree(E)@p;
|
|
||||||
//+ kfree_sensitive(E);
|
|
||||||
//|
|
|
||||||
- \(vfree\|kvfree\)(E)@p;
|
- \(vfree\|kvfree\)(E)@p;
|
||||||
+ kvfree_sensitive(E, size);
|
+ kvfree_sensitive(E, size);
|
||||||
//)
|
)
|
||||||
|
|
||||||
@rp_memset depends on patch@
|
@rp_memset depends on patch@
|
||||||
expression E, size;
|
expression E, size;
|
||||||
|
@ -80,7 +77,7 @@ type T;
|
||||||
when strict
|
when strict
|
||||||
(
|
(
|
||||||
- kfree(E)@p;
|
- kfree(E)@p;
|
||||||
+ kzfree(E);
|
+ kfree_sensitive(E);
|
||||||
|
|
|
|
||||||
- \(vfree\|kvfree\)(E)@p;
|
- \(vfree\|kvfree\)(E)@p;
|
||||||
+ kvfree_sensitive(E, size);
|
+ kvfree_sensitive(E, size);
|
||||||
|
@ -88,14 +85,16 @@ type T;
|
||||||
|
|
||||||
@script:python depends on report@
|
@script:python depends on report@
|
||||||
p << r.p;
|
p << r.p;
|
||||||
|
m << r.m;
|
||||||
@@
|
@@
|
||||||
|
|
||||||
coccilib.report.print_report(p[0],
|
msg = "WARNING opportunity for kfree_sensitive/kvfree_sensitive (memset at line %s)"
|
||||||
"WARNING: opportunity for kzfree/kvfree_sensitive")
|
coccilib.report.print_report(p[0], msg % (m[0].line))
|
||||||
|
|
||||||
@script:python depends on org@
|
@script:python depends on org@
|
||||||
p << r.p;
|
p << r.p;
|
||||||
|
m << r.m;
|
||||||
@@
|
@@
|
||||||
|
|
||||||
coccilib.org.print_todo(p[0],
|
msg = "WARNING opportunity for kfree_sensitive/kvfree_sensitive (memset at line %s)"
|
||||||
"WARNING: opportunity for kzfree/kvfree_sensitive")
|
coccilib.org.print_todo(p[0], msg % (m[0].line))
|
|
@ -0,0 +1,45 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
///
|
||||||
|
/// Use kobj_to_dev() instead of container_of()
|
||||||
|
///
|
||||||
|
// Confidence: High
|
||||||
|
// Copyright: (C) 2020 Denis Efremov ISPRAS
|
||||||
|
// Options: --no-includes --include-headers
|
||||||
|
//
|
||||||
|
// Keywords: kobj_to_dev, container_of
|
||||||
|
//
|
||||||
|
|
||||||
|
virtual context
|
||||||
|
virtual report
|
||||||
|
virtual org
|
||||||
|
virtual patch
|
||||||
|
|
||||||
|
|
||||||
|
@r depends on !patch@
|
||||||
|
expression ptr;
|
||||||
|
symbol kobj;
|
||||||
|
position p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
* container_of(ptr, struct device, kobj)@p
|
||||||
|
|
||||||
|
|
||||||
|
@depends on patch@
|
||||||
|
expression ptr;
|
||||||
|
@@
|
||||||
|
|
||||||
|
- container_of(ptr, struct device, kobj)
|
||||||
|
+ kobj_to_dev(ptr)
|
||||||
|
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.report.print_report(p[0], "WARNING opportunity for kobj_to_dev()")
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.org.print_todo(p[0], "WARNING opportunity for kobj_to_dev()")
|
|
@ -0,0 +1,256 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
///
|
||||||
|
/// Find if/else condition with kmalloc/vmalloc calls.
|
||||||
|
/// Suggest to use kvmalloc instead. Same for kvfree.
|
||||||
|
///
|
||||||
|
// Confidence: High
|
||||||
|
// Copyright: (C) 2020 Denis Efremov ISPRAS
|
||||||
|
// Options: --no-includes --include-headers
|
||||||
|
//
|
||||||
|
|
||||||
|
virtual patch
|
||||||
|
virtual report
|
||||||
|
virtual org
|
||||||
|
virtual context
|
||||||
|
|
||||||
|
@initialize:python@
|
||||||
|
@@
|
||||||
|
filter = frozenset(['kvfree'])
|
||||||
|
|
||||||
|
def relevant(p):
|
||||||
|
return not (filter & {el.current_element for el in p})
|
||||||
|
|
||||||
|
@kvmalloc depends on !patch@
|
||||||
|
expression E, E1, size;
|
||||||
|
identifier flags;
|
||||||
|
binary operator cmp = {<=, <, ==, >, >=};
|
||||||
|
identifier x;
|
||||||
|
type T;
|
||||||
|
position p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
* if (size cmp E1 || ...)@p {
|
||||||
|
...
|
||||||
|
* E = \(kmalloc\|kzalloc\|kcalloc\|kmalloc_node\|kzalloc_node\|
|
||||||
|
* kmalloc_array\|kmalloc_array_node\|kcalloc_node\)
|
||||||
|
* (..., size, \(flags\|GFP_KERNEL\|\(GFP_KERNEL\|flags\)|__GFP_NOWARN\), ...)
|
||||||
|
...
|
||||||
|
} else {
|
||||||
|
...
|
||||||
|
* E = \(vmalloc\|vzalloc\|vmalloc_node\|vzalloc_node\)(..., size, ...)
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
|
||||||
|
* E = \(kmalloc\|kzalloc\|kcalloc\|kmalloc_node\|kzalloc_node\|
|
||||||
|
* kmalloc_array\|kmalloc_array_node\|kcalloc_node\)
|
||||||
|
* (..., size, \(flags\|GFP_KERNEL\|\(GFP_KERNEL\|flags\)|__GFP_NOWARN\), ...)
|
||||||
|
... when != E = E1
|
||||||
|
when != size = E1
|
||||||
|
when any
|
||||||
|
* if (E == NULL)@p {
|
||||||
|
...
|
||||||
|
* E = \(vmalloc\|vzalloc\|vmalloc_node\|vzalloc_node\)(..., size, ...)
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
|
||||||
|
* T x = \(kmalloc\|kzalloc\|kcalloc\|kmalloc_node\|kzalloc_node\|
|
||||||
|
* kmalloc_array\|kmalloc_array_node\|kcalloc_node\)
|
||||||
|
* (..., size, \(flags\|GFP_KERNEL\|\(GFP_KERNEL\|flags\)|__GFP_NOWARN\), ...);
|
||||||
|
... when != x = E1
|
||||||
|
when != size = E1
|
||||||
|
when any
|
||||||
|
* if (x == NULL)@p {
|
||||||
|
...
|
||||||
|
* x = \(vmalloc\|vzalloc\|vmalloc_node\|vzalloc_node\)(..., size, ...)
|
||||||
|
...
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
@kvfree depends on !patch@
|
||||||
|
expression E;
|
||||||
|
position p : script:python() { relevant(p) };
|
||||||
|
@@
|
||||||
|
|
||||||
|
* if (is_vmalloc_addr(E))@p {
|
||||||
|
...
|
||||||
|
* vfree(E)
|
||||||
|
...
|
||||||
|
} else {
|
||||||
|
... when != krealloc(E, ...)
|
||||||
|
when any
|
||||||
|
* \(kfree\|kzfree\)(E)
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
@depends on patch@
|
||||||
|
expression E, E1, size, node;
|
||||||
|
binary operator cmp = {<=, <, ==, >, >=};
|
||||||
|
identifier flags, x;
|
||||||
|
type T;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
- if (size cmp E1)
|
||||||
|
- E = kmalloc(size, flags);
|
||||||
|
- else
|
||||||
|
- E = vmalloc(size);
|
||||||
|
+ E = kvmalloc(size, flags);
|
||||||
|
|
|
||||||
|
- if (size cmp E1)
|
||||||
|
- E = kmalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\));
|
||||||
|
- else
|
||||||
|
- E = vmalloc(size);
|
||||||
|
+ E = kvmalloc(size, GFP_KERNEL);
|
||||||
|
|
|
||||||
|
- E = kmalloc(size, flags | __GFP_NOWARN);
|
||||||
|
- if (E == NULL)
|
||||||
|
- E = vmalloc(size);
|
||||||
|
+ E = kvmalloc(size, flags);
|
||||||
|
|
|
||||||
|
- E = kmalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\));
|
||||||
|
- if (E == NULL)
|
||||||
|
- E = vmalloc(size);
|
||||||
|
+ E = kvmalloc(size, GFP_KERNEL);
|
||||||
|
|
|
||||||
|
- T x = kmalloc(size, flags | __GFP_NOWARN);
|
||||||
|
- if (x == NULL)
|
||||||
|
- x = vmalloc(size);
|
||||||
|
+ T x = kvmalloc(size, flags);
|
||||||
|
|
|
||||||
|
- T x = kmalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\));
|
||||||
|
- if (x == NULL)
|
||||||
|
- x = vmalloc(size);
|
||||||
|
+ T x = kvmalloc(size, GFP_KERNEL);
|
||||||
|
|
|
||||||
|
- if (size cmp E1)
|
||||||
|
- E = kzalloc(size, flags);
|
||||||
|
- else
|
||||||
|
- E = vzalloc(size);
|
||||||
|
+ E = kvzalloc(size, flags);
|
||||||
|
|
|
||||||
|
- if (size cmp E1)
|
||||||
|
- E = kzalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\));
|
||||||
|
- else
|
||||||
|
- E = vzalloc(size);
|
||||||
|
+ E = kvzalloc(size, GFP_KERNEL);
|
||||||
|
|
|
||||||
|
- E = kzalloc(size, flags | __GFP_NOWARN);
|
||||||
|
- if (E == NULL)
|
||||||
|
- E = vzalloc(size);
|
||||||
|
+ E = kvzalloc(size, flags);
|
||||||
|
|
|
||||||
|
- E = kzalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\));
|
||||||
|
- if (E == NULL)
|
||||||
|
- E = vzalloc(size);
|
||||||
|
+ E = kvzalloc(size, GFP_KERNEL);
|
||||||
|
|
|
||||||
|
- T x = kzalloc(size, flags | __GFP_NOWARN);
|
||||||
|
- if (x == NULL)
|
||||||
|
- x = vzalloc(size);
|
||||||
|
+ T x = kvzalloc(size, flags);
|
||||||
|
|
|
||||||
|
- T x = kzalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\));
|
||||||
|
- if (x == NULL)
|
||||||
|
- x = vzalloc(size);
|
||||||
|
+ T x = kvzalloc(size, GFP_KERNEL);
|
||||||
|
|
|
||||||
|
- if (size cmp E1)
|
||||||
|
- E = kmalloc_node(size, flags, node);
|
||||||
|
- else
|
||||||
|
- E = vmalloc_node(size, node);
|
||||||
|
+ E = kvmalloc_node(size, flags, node);
|
||||||
|
|
|
||||||
|
- if (size cmp E1)
|
||||||
|
- E = kmalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node);
|
||||||
|
- else
|
||||||
|
- E = vmalloc_node(size, node);
|
||||||
|
+ E = kvmalloc_node(size, GFP_KERNEL, node);
|
||||||
|
|
|
||||||
|
- E = kmalloc_node(size, flags | __GFP_NOWARN, node);
|
||||||
|
- if (E == NULL)
|
||||||
|
- E = vmalloc_node(size, node);
|
||||||
|
+ E = kvmalloc_node(size, flags, node);
|
||||||
|
|
|
||||||
|
- E = kmalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node);
|
||||||
|
- if (E == NULL)
|
||||||
|
- E = vmalloc_node(size, node);
|
||||||
|
+ E = kvmalloc_node(size, GFP_KERNEL, node);
|
||||||
|
|
|
||||||
|
- T x = kmalloc_node(size, flags | __GFP_NOWARN, node);
|
||||||
|
- if (x == NULL)
|
||||||
|
- x = vmalloc_node(size, node);
|
||||||
|
+ T x = kvmalloc_node(size, flags, node);
|
||||||
|
|
|
||||||
|
- T x = kmalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node);
|
||||||
|
- if (x == NULL)
|
||||||
|
- x = vmalloc_node(size, node);
|
||||||
|
+ T x = kvmalloc_node(size, GFP_KERNEL, node);
|
||||||
|
|
|
||||||
|
- if (size cmp E1)
|
||||||
|
- E = kvzalloc_node(size, flags, node);
|
||||||
|
- else
|
||||||
|
- E = vzalloc_node(size, node);
|
||||||
|
+ E = kvzalloc_node(size, flags, node);
|
||||||
|
|
|
||||||
|
- if (size cmp E1)
|
||||||
|
- E = kvzalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node);
|
||||||
|
- else
|
||||||
|
- E = vzalloc_node(size, node);
|
||||||
|
+ E = kvzalloc_node(size, GFP_KERNEL, node);
|
||||||
|
|
|
||||||
|
- E = kvzalloc_node(size, flags | __GFP_NOWARN, node);
|
||||||
|
- if (E == NULL)
|
||||||
|
- E = vzalloc_node(size, node);
|
||||||
|
+ E = kvzalloc_node(size, flags, node);
|
||||||
|
|
|
||||||
|
- E = kvzalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node);
|
||||||
|
- if (E == NULL)
|
||||||
|
- E = vzalloc_node(size, node);
|
||||||
|
+ E = kvzalloc_node(size, GFP_KERNEL, node);
|
||||||
|
|
|
||||||
|
- T x = kvzalloc_node(size, flags | __GFP_NOWARN, node);
|
||||||
|
- if (x == NULL)
|
||||||
|
- x = vzalloc_node(size, node);
|
||||||
|
+ T x = kvzalloc_node(size, flags, node);
|
||||||
|
|
|
||||||
|
- T x = kvzalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node);
|
||||||
|
- if (x == NULL)
|
||||||
|
- x = vzalloc_node(size, node);
|
||||||
|
+ T x = kvzalloc_node(size, GFP_KERNEL, node);
|
||||||
|
)
|
||||||
|
|
||||||
|
@depends on patch@
|
||||||
|
expression E;
|
||||||
|
position p : script:python() { relevant(p) };
|
||||||
|
@@
|
||||||
|
|
||||||
|
- if (is_vmalloc_addr(E))@p
|
||||||
|
- vfree(E);
|
||||||
|
- else
|
||||||
|
- kfree(E);
|
||||||
|
+ kvfree(E);
|
||||||
|
|
||||||
|
@script: python depends on report@
|
||||||
|
p << kvmalloc.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.report.print_report(p[0], "WARNING opportunity for kvmalloc")
|
||||||
|
|
||||||
|
@script: python depends on org@
|
||||||
|
p << kvmalloc.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.org.print_todo(p[0], "WARNING opportunity for kvmalloc")
|
||||||
|
|
||||||
|
@script: python depends on report@
|
||||||
|
p << kvfree.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.report.print_report(p[0], "WARNING opportunity for kvfree")
|
||||||
|
|
||||||
|
@script: python depends on org@
|
||||||
|
p << kvfree.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.org.print_todo(p[0], "WARNING opportunity for kvfree")
|
|
@ -20,8 +20,14 @@ expression E;
|
||||||
- if (E != NULL)
|
- if (E != NULL)
|
||||||
(
|
(
|
||||||
kfree(E);
|
kfree(E);
|
||||||
|
|
|
||||||
|
kvfree(E);
|
||||||
|
|
|
|
||||||
kfree_sensitive(E);
|
kfree_sensitive(E);
|
||||||
|
|
|
||||||
|
kvfree_sensitive(E, ...);
|
||||||
|
|
|
||||||
|
vfree(E);
|
||||||
|
|
|
|
||||||
debugfs_remove(E);
|
debugfs_remove(E);
|
||||||
|
|
|
|
||||||
|
@ -42,9 +48,10 @@ position p;
|
||||||
@@
|
@@
|
||||||
|
|
||||||
* if (E != NULL)
|
* if (E != NULL)
|
||||||
* \(kfree@p\|kfree_sensitive@p\|debugfs_remove@p\|debugfs_remove_recursive@p\|
|
* \(kfree@p\|kvfree@p\|kfree_sensitive@p\|kvfree_sensitive@p\|vfree@p\|
|
||||||
|
* debugfs_remove@p\|debugfs_remove_recursive@p\|
|
||||||
* usb_free_urb@p\|kmem_cache_destroy@p\|mempool_destroy@p\|
|
* usb_free_urb@p\|kmem_cache_destroy@p\|mempool_destroy@p\|
|
||||||
* dma_pool_destroy@p\)(E);
|
* dma_pool_destroy@p\)(E, ...);
|
||||||
|
|
||||||
@script:python depends on org@
|
@script:python depends on org@
|
||||||
p << r.p;
|
p << r.p;
|
||||||
|
|
|
@ -0,0 +1,358 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
// Adds missing of_node_put() before return/break/goto statement within a for_each iterator for child nodes.
|
||||||
|
//# False positives can be due to function calls within the for_each
|
||||||
|
//# loop that may encapsulate an of_node_put.
|
||||||
|
///
|
||||||
|
// Confidence: High
|
||||||
|
// Copyright: (C) 2020 Sumera Priyadarsini
|
||||||
|
// URL: http://coccinelle.lip6.fr
|
||||||
|
// Options: --no-includes --include-headers
|
||||||
|
|
||||||
|
virtual patch
|
||||||
|
virtual context
|
||||||
|
virtual org
|
||||||
|
virtual report
|
||||||
|
|
||||||
|
@r@
|
||||||
|
local idexpression n;
|
||||||
|
expression e1,e2;
|
||||||
|
iterator name for_each_node_by_name, for_each_node_by_type,
|
||||||
|
for_each_compatible_node, for_each_matching_node,
|
||||||
|
for_each_matching_node_and_match, for_each_child_of_node,
|
||||||
|
for_each_available_child_of_node, for_each_node_with_property;
|
||||||
|
iterator i;
|
||||||
|
statement S;
|
||||||
|
expression list [n1] es;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
(
|
||||||
|
for_each_node_by_name(n,e1) S
|
||||||
|
|
|
||||||
|
for_each_node_by_type(n,e1) S
|
||||||
|
|
|
||||||
|
for_each_compatible_node(n,e1,e2) S
|
||||||
|
|
|
||||||
|
for_each_matching_node(n,e1) S
|
||||||
|
|
|
||||||
|
for_each_matching_node_and_match(n,e1,e2) S
|
||||||
|
|
|
||||||
|
for_each_child_of_node(e1,n) S
|
||||||
|
|
|
||||||
|
for_each_available_child_of_node(e1,n) S
|
||||||
|
|
|
||||||
|
for_each_node_with_property(n,e1) S
|
||||||
|
)
|
||||||
|
&
|
||||||
|
i(es,n,...) S
|
||||||
|
)
|
||||||
|
|
||||||
|
@ruleone depends on patch && !context && !org && !report@
|
||||||
|
|
||||||
|
local idexpression r.n;
|
||||||
|
iterator r.i,i1;
|
||||||
|
expression e;
|
||||||
|
expression list [r.n1] es;
|
||||||
|
statement S;
|
||||||
|
@@
|
||||||
|
|
||||||
|
i(es,n,...) {
|
||||||
|
...
|
||||||
|
(
|
||||||
|
of_node_put(n);
|
||||||
|
|
|
||||||
|
e = n
|
||||||
|
|
|
||||||
|
return n;
|
||||||
|
|
|
||||||
|
i1(...,n,...) S
|
||||||
|
|
|
||||||
|
- return of_node_get(n);
|
||||||
|
+ return n;
|
||||||
|
|
|
||||||
|
+ of_node_put(n);
|
||||||
|
? return ...;
|
||||||
|
)
|
||||||
|
... when any
|
||||||
|
}
|
||||||
|
|
||||||
|
@ruletwo depends on patch && !context && !org && !report@
|
||||||
|
|
||||||
|
local idexpression r.n;
|
||||||
|
iterator r.i,i1,i2;
|
||||||
|
expression e,e1;
|
||||||
|
expression list [r.n1] es;
|
||||||
|
statement S,S2;
|
||||||
|
@@
|
||||||
|
|
||||||
|
i(es,n,...) {
|
||||||
|
...
|
||||||
|
(
|
||||||
|
of_node_put(n);
|
||||||
|
|
|
||||||
|
e = n
|
||||||
|
|
|
||||||
|
i1(...,n,...) S
|
||||||
|
|
|
||||||
|
+ of_node_put(n);
|
||||||
|
? break;
|
||||||
|
)
|
||||||
|
... when any
|
||||||
|
}
|
||||||
|
... when != n
|
||||||
|
when strict
|
||||||
|
when forall
|
||||||
|
(
|
||||||
|
n = e1;
|
||||||
|
|
|
||||||
|
?i2(...,n,...) S2
|
||||||
|
)
|
||||||
|
|
||||||
|
@rulethree depends on patch && !context && !org && !report exists@
|
||||||
|
|
||||||
|
local idexpression r.n;
|
||||||
|
iterator r.i,i1,i2;
|
||||||
|
expression e,e1;
|
||||||
|
identifier l;
|
||||||
|
expression list [r.n1] es;
|
||||||
|
statement S,S2;
|
||||||
|
@@
|
||||||
|
|
||||||
|
i(es,n,...) {
|
||||||
|
...
|
||||||
|
(
|
||||||
|
of_node_put(n);
|
||||||
|
|
|
||||||
|
e = n
|
||||||
|
|
|
||||||
|
i1(...,n,...) S
|
||||||
|
|
|
||||||
|
+ of_node_put(n);
|
||||||
|
? goto l;
|
||||||
|
)
|
||||||
|
... when any
|
||||||
|
}
|
||||||
|
... when exists
|
||||||
|
l: ... when != n
|
||||||
|
when strict
|
||||||
|
when forall
|
||||||
|
(
|
||||||
|
n = e1;
|
||||||
|
|
|
||||||
|
?i2(...,n,...) S2
|
||||||
|
)
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ruleone_context depends on !patch && (context || org || report) exists@
|
||||||
|
statement S;
|
||||||
|
expression e;
|
||||||
|
expression list[r.n1] es;
|
||||||
|
iterator r.i, i1;
|
||||||
|
local idexpression r.n;
|
||||||
|
position j0, j1;
|
||||||
|
@@
|
||||||
|
|
||||||
|
i@j0(es,n,...) {
|
||||||
|
...
|
||||||
|
(
|
||||||
|
of_node_put(n);
|
||||||
|
|
|
||||||
|
e = n
|
||||||
|
|
|
||||||
|
return n;
|
||||||
|
|
|
||||||
|
i1(...,n,...) S
|
||||||
|
|
|
||||||
|
return @j1 ...;
|
||||||
|
)
|
||||||
|
... when any
|
||||||
|
}
|
||||||
|
|
||||||
|
@ruleone_disj depends on !patch && (context || org || report)@
|
||||||
|
expression list[r.n1] es;
|
||||||
|
iterator r.i;
|
||||||
|
local idexpression r.n;
|
||||||
|
position ruleone_context.j0, ruleone_context.j1;
|
||||||
|
@@
|
||||||
|
|
||||||
|
* i@j0(es,n,...) {
|
||||||
|
...
|
||||||
|
*return @j1...;
|
||||||
|
... when any
|
||||||
|
}
|
||||||
|
|
||||||
|
@ruletwo_context depends on !patch && (context || org || report) exists@
|
||||||
|
statement S, S2;
|
||||||
|
expression e, e1;
|
||||||
|
expression list[r.n1] es;
|
||||||
|
iterator r.i, i1, i2;
|
||||||
|
local idexpression r.n;
|
||||||
|
position j0, j2;
|
||||||
|
@@
|
||||||
|
|
||||||
|
i@j0(es,n,...) {
|
||||||
|
...
|
||||||
|
(
|
||||||
|
of_node_put(n);
|
||||||
|
|
|
||||||
|
e = n
|
||||||
|
|
|
||||||
|
i1(...,n,...) S
|
||||||
|
|
|
||||||
|
break@j2;
|
||||||
|
)
|
||||||
|
... when any
|
||||||
|
}
|
||||||
|
... when != n
|
||||||
|
when strict
|
||||||
|
when forall
|
||||||
|
(
|
||||||
|
n = e1;
|
||||||
|
|
|
||||||
|
?i2(...,n,...) S2
|
||||||
|
)
|
||||||
|
|
||||||
|
@ruletwo_disj depends on !patch && (context || org || report)@
|
||||||
|
statement S2;
|
||||||
|
expression e1;
|
||||||
|
expression list[r.n1] es;
|
||||||
|
iterator r.i, i2;
|
||||||
|
local idexpression r.n;
|
||||||
|
position ruletwo_context.j0, ruletwo_context.j2;
|
||||||
|
@@
|
||||||
|
|
||||||
|
* i@j0(es,n,...) {
|
||||||
|
...
|
||||||
|
*break @j2;
|
||||||
|
... when any
|
||||||
|
}
|
||||||
|
... when != n
|
||||||
|
when strict
|
||||||
|
when forall
|
||||||
|
(
|
||||||
|
n = e1;
|
||||||
|
|
|
||||||
|
?i2(...,n,...) S2
|
||||||
|
)
|
||||||
|
|
||||||
|
@rulethree_context depends on !patch && (context || org || report) exists@
|
||||||
|
identifier l;
|
||||||
|
statement S,S2;
|
||||||
|
expression e, e1;
|
||||||
|
expression list[r.n1] es;
|
||||||
|
iterator r.i, i1, i2;
|
||||||
|
local idexpression r.n;
|
||||||
|
position j0, j3;
|
||||||
|
@@
|
||||||
|
|
||||||
|
i@j0(es,n,...) {
|
||||||
|
...
|
||||||
|
(
|
||||||
|
of_node_put(n);
|
||||||
|
|
|
||||||
|
e = n
|
||||||
|
|
|
||||||
|
i1(...,n,...) S
|
||||||
|
|
|
||||||
|
goto l@j3;
|
||||||
|
)
|
||||||
|
... when any
|
||||||
|
}
|
||||||
|
... when exists
|
||||||
|
l:
|
||||||
|
... when != n
|
||||||
|
when strict
|
||||||
|
when forall
|
||||||
|
(
|
||||||
|
n = e1;
|
||||||
|
|
|
||||||
|
?i2(...,n,...) S2
|
||||||
|
)
|
||||||
|
|
||||||
|
@rulethree_disj depends on !patch && (context || org || report) exists@
|
||||||
|
identifier l;
|
||||||
|
statement S2;
|
||||||
|
expression e1;
|
||||||
|
expression list[r.n1] es;
|
||||||
|
iterator r.i, i2;
|
||||||
|
local idexpression r.n;
|
||||||
|
position rulethree_context.j0, rulethree_context.j3;
|
||||||
|
@@
|
||||||
|
|
||||||
|
* i@j0(es,n,...) {
|
||||||
|
...
|
||||||
|
*goto l@j3;
|
||||||
|
... when any
|
||||||
|
}
|
||||||
|
... when exists
|
||||||
|
l:
|
||||||
|
... when != n
|
||||||
|
when strict
|
||||||
|
when forall
|
||||||
|
(
|
||||||
|
n = e1;
|
||||||
|
|
|
||||||
|
?i2(...,n,...) S2
|
||||||
|
)
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@script:python ruleone_org depends on org@
|
||||||
|
i << r.i;
|
||||||
|
j0 << ruleone_context.j0;
|
||||||
|
j1 << ruleone_context. j1;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "WARNING: Function \"%s\" should have of_node_put() before return " % (i)
|
||||||
|
coccilib.org.print_safe_todo(j0[0], msg)
|
||||||
|
coccilib.org.print_link(j1[0], "")
|
||||||
|
|
||||||
|
@script:python ruletwo_org depends on org@
|
||||||
|
i << r.i;
|
||||||
|
j0 << ruletwo_context.j0;
|
||||||
|
j2 << ruletwo_context.j2;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "WARNING: Function \"%s\" should have of_node_put() before break " % (i)
|
||||||
|
coccilib.org.print_safe_todo(j0[0], msg)
|
||||||
|
coccilib.org.print_link(j2[0], "")
|
||||||
|
|
||||||
|
@script:python rulethree_org depends on org@
|
||||||
|
i << r.i;
|
||||||
|
j0 << rulethree_context.j0;
|
||||||
|
j3 << rulethree_context.j3;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "WARNING: Function \"%s\" should have of_node_put() before goto " % (i)
|
||||||
|
coccilib.org.print_safe_todo(j0[0], msg)
|
||||||
|
coccilib.org.print_link(j3[0], "")
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@script:python ruleone_report depends on report@
|
||||||
|
i << r.i;
|
||||||
|
j0 << ruleone_context.j0;
|
||||||
|
j1 << ruleone_context.j1;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "WARNING: Function \"%s\" should have of_node_put() before return around line %s." % (i, j1[0].line)
|
||||||
|
coccilib.report.print_report(j0[0], msg)
|
||||||
|
|
||||||
|
@script:python ruletwo_report depends on report@
|
||||||
|
i << r.i;
|
||||||
|
j0 << ruletwo_context.j0;
|
||||||
|
j2 << ruletwo_context.j2;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "WARNING: Function \"%s\" should have of_node_put() before break around line %s." % (i,j2[0].line)
|
||||||
|
coccilib.report.print_report(j0[0], msg)
|
||||||
|
|
||||||
|
@script:python rulethree_report depends on report@
|
||||||
|
i << r.i;
|
||||||
|
j0 << rulethree_context.j0;
|
||||||
|
j3 << rulethree_context.j3;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "WARNING: Function \"%s\" should have of_node_put() before goto around lines %s." % (i,j3[0].line)
|
||||||
|
coccilib.report.print_report(j0[0], msg)
|
|
@ -0,0 +1,39 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
///
|
||||||
|
/// Condition !A || A && B is equivalent to !A || B.
|
||||||
|
///
|
||||||
|
// Confidence: High
|
||||||
|
// Copyright: (C) 2020 Denis Efremov ISPRAS
|
||||||
|
// Options: --no-includes --include-headers
|
||||||
|
|
||||||
|
virtual patch
|
||||||
|
virtual context
|
||||||
|
virtual org
|
||||||
|
virtual report
|
||||||
|
|
||||||
|
@r depends on !patch@
|
||||||
|
expression A, B;
|
||||||
|
position p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
* !A || (A &&@p B)
|
||||||
|
|
||||||
|
@depends on patch@
|
||||||
|
expression A, B;
|
||||||
|
@@
|
||||||
|
|
||||||
|
!A ||
|
||||||
|
- (A && B)
|
||||||
|
+ B
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.report.print_report(p[0], "WARNING !A || A && B is equivalent to !A || B")
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.org.print_todo(p[0], "WARNING !A || A && B is equivalent to !A || B")
|
|
@ -0,0 +1,88 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
///
|
||||||
|
/// Zero-length and one-element arrays are deprecated, see
|
||||||
|
/// Documentation/process/deprecated.rst
|
||||||
|
/// Flexible-array members should be used instead.
|
||||||
|
///
|
||||||
|
//
|
||||||
|
// Confidence: High
|
||||||
|
// Copyright: (C) 2020 Denis Efremov ISPRAS.
|
||||||
|
// Comments:
|
||||||
|
// Options: --no-includes --include-headers
|
||||||
|
|
||||||
|
virtual context
|
||||||
|
virtual report
|
||||||
|
virtual org
|
||||||
|
virtual patch
|
||||||
|
|
||||||
|
@initialize:python@
|
||||||
|
@@
|
||||||
|
def relevant(positions):
|
||||||
|
for p in positions:
|
||||||
|
if "uapi" in p.file:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
@r depends on !patch@
|
||||||
|
identifier name, array;
|
||||||
|
type T;
|
||||||
|
position p : script:python() { relevant(p) };
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
struct name {
|
||||||
|
...
|
||||||
|
* T array@p[\(0\|1\)];
|
||||||
|
};
|
||||||
|
|
|
||||||
|
struct {
|
||||||
|
...
|
||||||
|
* T array@p[\(0\|1\)];
|
||||||
|
};
|
||||||
|
|
|
||||||
|
union name {
|
||||||
|
...
|
||||||
|
* T array@p[\(0\|1\)];
|
||||||
|
};
|
||||||
|
|
|
||||||
|
union {
|
||||||
|
...
|
||||||
|
* T array@p[\(0\|1\)];
|
||||||
|
};
|
||||||
|
)
|
||||||
|
|
||||||
|
@depends on patch@
|
||||||
|
identifier name, array;
|
||||||
|
type T;
|
||||||
|
position p : script:python() { relevant(p) };
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
struct name {
|
||||||
|
...
|
||||||
|
T array@p[
|
||||||
|
- 0
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
|
||||||
|
struct {
|
||||||
|
...
|
||||||
|
T array@p[
|
||||||
|
- 0
|
||||||
|
];
|
||||||
|
};
|
||||||
|
)
|
||||||
|
|
||||||
|
@script: python depends on report@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)"
|
||||||
|
coccilib.report.print_report(p[0], msg)
|
||||||
|
|
||||||
|
@script: python depends on org@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)"
|
||||||
|
coccilib.org.print_todo(p[0], msg)
|
|
@ -0,0 +1,51 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
///
|
||||||
|
/// Please, don't reintroduce uninitialized_var().
|
||||||
|
/// From Documentation/process/deprecated.rst:
|
||||||
|
/// For any compiler warnings about uninitialized variables, just add
|
||||||
|
/// an initializer. Using warning-silencing tricks is dangerous as it
|
||||||
|
/// papers over real bugs (or can in the future), and suppresses unrelated
|
||||||
|
/// compiler warnings (e.g. "unused variable"). If the compiler thinks it
|
||||||
|
/// is uninitialized, either simply initialize the variable or make compiler
|
||||||
|
/// changes. Keep in mind that in most cases, if an initialization is
|
||||||
|
/// obviously redundant, the compiler's dead-store elimination pass will make
|
||||||
|
/// sure there are no needless variable writes.
|
||||||
|
///
|
||||||
|
// Confidence: High
|
||||||
|
// Copyright: (C) 2020 Denis Efremov ISPRAS
|
||||||
|
// Options: --no-includes --include-headers
|
||||||
|
//
|
||||||
|
|
||||||
|
virtual context
|
||||||
|
virtual report
|
||||||
|
virtual org
|
||||||
|
|
||||||
|
@r@
|
||||||
|
identifier var;
|
||||||
|
type T;
|
||||||
|
position p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
* T var =@p var;
|
||||||
|
|
|
||||||
|
* T var =@p *(&(var));
|
||||||
|
|
|
||||||
|
* var =@p var
|
||||||
|
|
|
||||||
|
* var =@p *(&(var))
|
||||||
|
)
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.report.print_report(p[0],
|
||||||
|
"WARNING this kind of initialization is deprecated (https://www.kernel.org/doc/html/latest/process/deprecated.html#uninitialized-var)")
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.org.print_todo(p[0],
|
||||||
|
"WARNING this kind of initialization is deprecated (https://www.kernel.org/doc/html/latest/process/deprecated.html#uninitialized-var)")
|
Loading…
Reference in New Issue