* [cocci] [RFC] Coccinelle: Use IS_ERR_OR_NULL
@ 2026-03-04 17:38 Philipp Hahn
2026-03-04 18:12 ` Julia Lawall
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Philipp Hahn @ 2026-03-04 17:38 UTC (permalink / raw)
To: cocci; +Cc: Philipp Hahn
Hello,
after a colleague of mine recently gave a talk about Coccinelle, I had look
myself and created the below semantic patch to find and convert uses of
IS_ERR() plus NULL check to IS_ERR_OR_NULL() in the Linux kernel.
On 7.0.0-rc2 the patch applies to 79 files and finds most places I identified
manually. Fantastic!
There are some cases where the checks are part of a larger expression:
- mm/kmemleak.c:1095
- mm/kmemleak.c:1155
- mm/kmemleak.c:1173
- mm/kmemleak.c:1290
- mm/kmemleak.c:1328
- mm/kmemleak.c:1241
- mm/kmemleak.c:1310
- mm/kmemleak.c:1258
- net/mac80211/tx.c:4831
- net/netlink/af_netlink.c:2670
- security/keys/internal.h:367
So far I've been unable to teach Coccinelle to also generate patches for
these. Is there some easy solution to fix my patch to also handle those cases?
There are several cases where `!ptr && WARN_ON[_ONCE](IS_ERR(ptr))` is
used; they are not found and changed.
- arch/x86/kernel/callthunks.c:215 WARN_ON_ONCE
- drivers/clk/clk.c:4561 WARN_ON_ONCE
- drivers/interconnect/core.c:793 WARN_ON
- drivers/reset/core.c:718 WARN_ON
I don't expect Cocinelle to create a patch there and would ask the maintainers,
if they prefer the WARN_ON[_ONCE] to remain or would prefer changing it to
IS_ERR_OR_NULL.
drivers/clocksource/mips-gic-timer.c:283 looks suspicious: ret != clk
I'll ask the maintainer if this is on purpose or an error.
How are new semantic patches normally handled:
- are they first discussed on some mailing list?
- should I then create the individual patches myself and send them to the
subsystem maintainers myself?
- when should the semantic patch itself be included with the Linux kernel?
Thank you for the feedback.
Philipp Hahn
---
scripts/coccinelle/api/is_err_or_null.cocci | 86 +++++++++++++++++++++
1 file changed, 86 insertions(+)
create mode 100644 scripts/coccinelle/api/is_err_or_null.cocci
diff --git a/scripts/coccinelle/api/is_err_or_null.cocci b/scripts/coccinelle/api/is_err_or_null.cocci
new file mode 100644
index 0000000000000..942ba95a206f9
--- /dev/null
+++ b/scripts/coccinelle/api/is_err_or_null.cocci
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0-only
+///
+/// Use IF_ERR_OR_NULL() instead of IS_ERR() plus a check for (not) NULL
+///
+// Copyright: (C) 2026 Philipp Hahn, FRITZ! Technology GmbH.
+// Confidence: Medium
+// Options: --no-includes --include-headers
+// Keywords: IS_ERR, IS_ERR_OR_NULL
+
+virtual patch
+virtual report
+virtual org
+
+@p1 depends on patch@
+expression E;
+@@
+(
+- E != NULL && !IS_ERR(E)
++ !IS_ERR_OR_NULL(E)
+|
+- E == NULL || IS_ERR(E)
++ !IS_ERR_OR_NULL(E)
+|
+- !IS_ERR(E) && E != NULL
++ IS_ERR_OR_NULL(E)
+|
+- IS_ERR(E) || E == NULL
++ IS_ERR_OR_NULL(E)
+)
+
+@r1 depends on report || org@
+expression E;
+position p;
+@@
+(
+ E != NULL && ... && !IS_ERR@p(E)
+|
+ E == NULL || ... || IS_ERR@p(E)
+|
+ !IS_ERR@p(E) && ... && E != NULL
+|
+ IS_ERR@p(E) || ... || E == NULL
+)
+
+@script:python depends on report@
+p << r1.p;
+@@
+coccilib.report.print_report(p[0], "opportunity for IS_ERR_OR_NULL()")
+
+@script:python depends on org@
+p << r1.p;
+@@
+coccilib.org.print_todo(p[0], "opportunity for IS_ERR_OR_NULL()")
+
+@p2 depends on patch@
+identifier I;
+expression E;
+@@
+(
+- (I = E) != NULL && !IS_ERR(I)
++ !IS_ERR_OR_NULL((I = E))
+|
+- (I = E) == NULL || IS_ERR(I)
++ IS_ERR_OR_NULL((I = E))
+)
+
+@r2 depends on report || org@
+identifier I;
+expression E;
+position p;
+@@
+(
+* (I = E) != NULL && ... && !IS_ERR@p(I)
+|
+* (I = E) == NULL || ... || IS_ERR@p(I)
+)
+
+@script:python depends on report@
+p << r2.p;
+@@
+coccilib.report.print_report(p[0], "opportunity for IS_ERR_OR_NULL()")
+
+@script:python depends on org@
+p << r2.p;
+@@
+coccilib.org.print_todo(p[0], "opportunity for IS_ERR_OR_NULL()")
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [cocci] [RFC] Coccinelle: Use IS_ERR_OR_NULL
2026-03-04 17:38 [cocci] [RFC] Coccinelle: Use IS_ERR_OR_NULL Philipp Hahn
@ 2026-03-04 18:12 ` Julia Lawall
2026-03-05 10:20 ` Markus Elfring
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Julia Lawall @ 2026-03-04 18:12 UTC (permalink / raw)
To: Philipp Hahn; +Cc: cocci
On Wed, 4 Mar 2026, Philipp Hahn wrote:
> Hello,
>
> after a colleague of mine recently gave a talk about Coccinelle, I had look
> myself and created the below semantic patch to find and convert uses of
> IS_ERR() plus NULL check to IS_ERR_OR_NULL() in the Linux kernel.
>
> On 7.0.0-rc2 the patch applies to 79 files and finds most places I identified
> manually. Fantastic!
>
> There are some cases where the checks are part of a larger expression:
> - mm/kmemleak.c:1095
> - mm/kmemleak.c:1155
> - mm/kmemleak.c:1173
> - mm/kmemleak.c:1290
> - mm/kmemleak.c:1328
> - mm/kmemleak.c:1241
> - mm/kmemleak.c:1310
> - mm/kmemleak.c:1258
> - net/mac80211/tx.c:4831
> - net/netlink/af_netlink.c:2670
> - security/keys/internal.h:367
> So far I've been unable to teach Coccinelle to also generate patches for
> these. Is there some easy solution to fix my patch to also handle those cases?
The problem is the associativity of && which is not what you would hope
for in these cases. You can write:
@@
expression e,e1;
@@
- e1 && e && !IS_ERR(e)
+ e1 && !IS_ERR_OR_NULL(e)
It doesn't catch net/mac80211/tx.c:4831 and security/keys/internal.h:367
though, which are different from the others.
>
> There are several cases where `!ptr && WARN_ON[_ONCE](IS_ERR(ptr))` is
> used; they are not found and changed.
> - arch/x86/kernel/callthunks.c:215 WARN_ON_ONCE
> - drivers/clk/clk.c:4561 WARN_ON_ONCE
> - drivers/interconnect/core.c:793 WARN_ON
> - drivers/reset/core.c:718 WARN_ON
> I don't expect Cocinelle to create a patch there and would ask the maintainers,
> if they prefer the WARN_ON[_ONCE] to remain or would prefer changing it to
> IS_ERR_OR_NULL.
You can always make another rule that will do this.
> drivers/clocksource/mips-gic-timer.c:283 looks suspicious: ret != clk
> I'll ask the maintainer if this is on purpose or an error.
>
>
> How are new semantic patches normally handled:
> - are they first discussed on some mailing list?
> - should I then create the individual patches myself and send them to the
> subsystem maintainers myself?
> - when should the semantic patch itself be included with the Linux kernel?
You can send semantic patches to whereever get_maintainer tells you to
send them. It's nice to know when the semantic patch has led to patches
that have been accepted.
Thanks for trying Coccinelle.
julia
> Thank you for the feedback.
>
> Philipp Hahn
> ---
> scripts/coccinelle/api/is_err_or_null.cocci | 86 +++++++++++++++++++++
> 1 file changed, 86 insertions(+)
> create mode 100644 scripts/coccinelle/api/is_err_or_null.cocci
>
> diff --git a/scripts/coccinelle/api/is_err_or_null.cocci b/scripts/coccinelle/api/is_err_or_null.cocci
> new file mode 100644
> index 0000000000000..942ba95a206f9
> --- /dev/null
> +++ b/scripts/coccinelle/api/is_err_or_null.cocci
> @@ -0,0 +1,86 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +///
> +/// Use IF_ERR_OR_NULL() instead of IS_ERR() plus a check for (not) NULL
> +///
> +// Copyright: (C) 2026 Philipp Hahn, FRITZ! Technology GmbH.
> +// Confidence: Medium
> +// Options: --no-includes --include-headers
> +// Keywords: IS_ERR, IS_ERR_OR_NULL
> +
> +virtual patch
> +virtual report
> +virtual org
> +
> +@p1 depends on patch@
> +expression E;
> +@@
> +(
> +- E != NULL && !IS_ERR(E)
> ++ !IS_ERR_OR_NULL(E)
> +|
> +- E == NULL || IS_ERR(E)
> ++ !IS_ERR_OR_NULL(E)
> +|
> +- !IS_ERR(E) && E != NULL
> ++ IS_ERR_OR_NULL(E)
> +|
> +- IS_ERR(E) || E == NULL
> ++ IS_ERR_OR_NULL(E)
> +)
> +
> +@r1 depends on report || org@
> +expression E;
> +position p;
> +@@
> +(
> + E != NULL && ... && !IS_ERR@p(E)
> +|
> + E == NULL || ... || IS_ERR@p(E)
> +|
> + !IS_ERR@p(E) && ... && E != NULL
> +|
> + IS_ERR@p(E) || ... || E == NULL
> +)
> +
> +@script:python depends on report@
> +p << r1.p;
> +@@
> +coccilib.report.print_report(p[0], "opportunity for IS_ERR_OR_NULL()")
> +
> +@script:python depends on org@
> +p << r1.p;
> +@@
> +coccilib.org.print_todo(p[0], "opportunity for IS_ERR_OR_NULL()")
> +
> +@p2 depends on patch@
> +identifier I;
> +expression E;
> +@@
> +(
> +- (I = E) != NULL && !IS_ERR(I)
> ++ !IS_ERR_OR_NULL((I = E))
> +|
> +- (I = E) == NULL || IS_ERR(I)
> ++ IS_ERR_OR_NULL((I = E))
> +)
> +
> +@r2 depends on report || org@
> +identifier I;
> +expression E;
> +position p;
> +@@
> +(
> +* (I = E) != NULL && ... && !IS_ERR@p(I)
> +|
> +* (I = E) == NULL || ... || IS_ERR@p(I)
> +)
> +
> +@script:python depends on report@
> +p << r2.p;
> +@@
> +coccilib.report.print_report(p[0], "opportunity for IS_ERR_OR_NULL()")
> +
> +@script:python depends on org@
> +p << r2.p;
> +@@
> +coccilib.org.print_todo(p[0], "opportunity for IS_ERR_OR_NULL()")
> --
> 2.43.0
>
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [cocci] [RFC] Coccinelle: Use IS_ERR_OR_NULL
2026-03-04 17:38 [cocci] [RFC] Coccinelle: Use IS_ERR_OR_NULL Philipp Hahn
2026-03-04 18:12 ` Julia Lawall
@ 2026-03-05 10:20 ` Markus Elfring
2026-03-06 7:15 ` Markus Elfring
2026-03-06 8:26 ` Markus Elfring
3 siblings, 0 replies; 5+ messages in thread
From: Markus Elfring @ 2026-03-05 10:20 UTC (permalink / raw)
To: Philipp Hahn; +Cc: cocci
> after a colleague of mine recently gave a talk about Coccinelle, I had look
> myself and created the below semantic patch to find and convert uses of
> IS_ERR() plus NULL check to IS_ERR_OR_NULL() in the Linux kernel.
Thanks for your growing development interests in such an area.
> On 7.0.0-rc2 the patch applies to 79 files and finds most places I identified
> manually. Fantastic!
Did your code review approach differ from another information representation?
https://elixir.bootlin.com/linux/v7.0-rc1/A/ident/IS_ERR
> How are new semantic patches normally handled:
> - are they first discussed on some mailing list?
Would you like to achieve the integration of another coccicheck script?
> - should I then create the individual patches myself and send them to the
> subsystem maintainers myself?
The change acceptance can vary between involved maintainers.
Your source code search pattern would represent a refactoring.
Such adjustments fall into the category “code cleanup”.
They might need to be combined with more convincing changes.
https://lore.kernel.org/all/?q=IS_ERR_OR_NULL
Regards,
Markus
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [cocci] [RFC] Coccinelle: Use IS_ERR_OR_NULL
2026-03-04 17:38 [cocci] [RFC] Coccinelle: Use IS_ERR_OR_NULL Philipp Hahn
2026-03-04 18:12 ` Julia Lawall
2026-03-05 10:20 ` Markus Elfring
@ 2026-03-06 7:15 ` Markus Elfring
2026-03-06 8:26 ` Markus Elfring
3 siblings, 0 replies; 5+ messages in thread
From: Markus Elfring @ 2026-03-06 7:15 UTC (permalink / raw)
To: Philipp Hahn; +Cc: cocci
…
> +@p1 depends on patch@
> +expression E;
> +@@
> +(
> +- E != NULL && !IS_ERR(E)
> ++ !IS_ERR_OR_NULL(E)
> +|
> +- E == NULL || IS_ERR(E)
> ++ !IS_ERR_OR_NULL(E)
> +|
> +- !IS_ERR(E) && E != NULL
> ++ IS_ERR_OR_NULL(E)
> +|
> +- IS_ERR(E) || E == NULL
> ++ IS_ERR_OR_NULL(E)
> +)
…
I find such case distinctions questionable.
Thus I suggest to clarify presented implementation details in more detail
also for better source code transformation approaches.
Regards,
Markus
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [cocci] [RFC] Coccinelle: Use IS_ERR_OR_NULL
2026-03-04 17:38 [cocci] [RFC] Coccinelle: Use IS_ERR_OR_NULL Philipp Hahn
` (2 preceding siblings ...)
2026-03-06 7:15 ` Markus Elfring
@ 2026-03-06 8:26 ` Markus Elfring
3 siblings, 0 replies; 5+ messages in thread
From: Markus Elfring @ 2026-03-06 8:26 UTC (permalink / raw)
To: Philipp Hahn; +Cc: cocci
…
> +@p1 depends on patch@
> +expression E;
> +@@
> +(
> +- E != NULL && !IS_ERR(E)
> ++ !IS_ERR_OR_NULL(E)
> +|
> +- E == NULL || IS_ERR(E)
> ++ !IS_ERR_OR_NULL(E)
> +|
> +- !IS_ERR(E) && E != NULL
> ++ IS_ERR_OR_NULL(E)
> +|
> +- IS_ERR(E) || E == NULL
> ++ IS_ERR_OR_NULL(E)
> +)
…
Did you get confused with the negation of any code items?
Would you get further development ideas from an SmPL code variant
like the following?
@replacements@
expression e;
@@
(
-IS_ERR(e) || e == NULL
+IS_ERR_OR_NULL(e)
|
-e == NULL || IS_ERR(e)
+IS_ERR_OR_NULL(e)
|
-!IS_ERR(e) && e != NULL
+!IS_ERR_OR_NULL(e)
|
-e != NULL && !IS_ERR(e)
+!IS_ERR_OR_NULL(e)
)
Regards,
Markus
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-03-06 8:26 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-04 17:38 [cocci] [RFC] Coccinelle: Use IS_ERR_OR_NULL Philipp Hahn
2026-03-04 18:12 ` Julia Lawall
2026-03-05 10:20 ` Markus Elfring
2026-03-06 7:15 ` Markus Elfring
2026-03-06 8:26 ` Markus Elfring
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox