[cocci] [RFC] Coccinelle: Use IS_ERR_OR_NULL
Philipp Hahn <[email protected]> Wed, 4 Mar 2026 18:38:11 +0100
| Newsgroups | fr.inria.cocci |
|---|---|
| Organization | FRITZ! Technology GmbH, Berlin, Germany |
| Message-ID | <726546e758862eac541526151f085401756edc64.1772645314.git.p.hahn@avm.de> |
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