scripts/coccinelle: Add script for using ARRAY_END()
Subsystems (2)
cover scripts/coccinelle: Add script for using ARRAY_END()
Hi!
This is a script to help find and replace uses of ARRAY_SIZE() to find the end of an array (a pointer one past the last element). We already replaced some uses a few months ago, fixing some bugs while doing that, and now I've written a coccinelle patch to do it elsewhere.
This is the first time I write a script under scripts/coccinelle/, so take it with a grain of salt. I've tested it, and I see no false positives. However, I've found several false negatives (for example, in macros, or where the argument is a struct member).
Have a lovely night!
Alex
Alejandro Colomar (1):
scripts/coccinelle: Add script for using ARRAY_END()
scripts/coccinelle/misc/array_end.cocci | 93 +++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 scripts/coccinelle/misc/array_end.cocci
Range-diff against v0:
-: -------- > 1: f1c9dff5 scripts/coccinelle: Add script for using ARRAY_END()
Signature · 1 line
2.53.0
PATCH 1/1 scripts/coccinelle: Add script for using ARRAY_END()
Recently, we added an ARRAY_END() macro to simplify finding a pointer one past the last element in an array. Such a pointer is often called the 'end', and thus the macro name.
This script makes it easy to find more places where that macro should be used.
See also:436debc9cad8 ("array_size.h: add ARRAY_END()") 8118f197b7b7 ("mm: fix benign off-by-one bugs") a9e5620c9a9e ("kernel: fix off-by-one benign bugs") 61e9210e2392 ("mm: use ARRAY_END() instead of open-coding it")
--- scripts/coccinelle/misc/array_end.cocci | 93 +++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 scripts/coccinelle/misc/array_end.cocci
scripts/coccinelle/misc/array_end.cocci new file +93 -0
@@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// Use ARRAY_END instead of an expression derived from ARRAY_SIZE +// +// Confidence: ??? +// Copyright: 2026, Alejandro Colomar <[email protected]> +// Comments: +// Options: --no-includes --include-headers + +virtual patch +virtual context +virtual org +virtual report + +@i@ +@@ + +#include <linux/kernel.h> + +//---------------------------------------------------------- +// For context mode +//---------------------------------------------------------- + +@depends on i&&context@ +type T; +T[] a; +expression b; +@@ +( +* (a + ARRAY_SIZE(a)) +| +* (&a[0] + ARRAY_SIZE(a)) +| +* (&a[ARRAY_SIZE(a)]) +| +* (&a[ARRAY_SIZE(a) - b]) +) + +//---------------------------------------------------------- +// For patch mode +//---------------------------------------------------------- + +@depends on i&&patch@ +type T; +T[] a; +expression b; +@@ +( +- (a + ARRAY_SIZE(a)) ++ ARRAY_END(a) +| +- (&a[0] + ARRAY_SIZE(a)) ++ ARRAY_END(a) +| +- (&a[ARRAY_SIZE(a)]) ++ ARRAY_END(a) +| +- (&a[ARRAY_SIZE(a) - b]) ++ ARRAY_END(a) - b +) + +//---------------------------------------------------------- +// For org and report mode +//---------------------------------------------------------- + +@r depends on (org || report)@ +type T; +T[] a; +expression b; +position p; +@@ +( + (a@p + ARRAY_SIZE(a)) +| + (&a[0]@p + ARRAY_SIZE(a)) +| + (&a[ARRAY_SIZE(a)]@p) +| + (&a[ARRAY_SIZE(a)@p - b]) +) + +@script:python depends on org@ +p << r.p; +@@ + +coccilib.org.print_todo(p[0], "WARNING should use ARRAY_END") + +@script:python depends on report@ +p << r.p; +@@ + +msg="WARNING: Use ARRAY_END" +coccilib.report.print_report(p[0], msg) +
Signature · 1 line
2.53.0
…
Quoted 2 lines
This script makes it easy to find more places where that macro should be used.
…
Quoted 2 lines
+++
b/scripts/coccinelle/misc/array_end.cocci(quoted diff) +0
-0@@ -0,0 +1,93 @@
…
Quoted 1 line
+// Confidence: ???
I hope that a more reasonable value can be determined for this information.
…
Quoted 1 line
+// Comments:
Please omit such an empty field.
…
Review
Quoted 4 lines
+@i@
+@@(quoted diff) +2
-0+ +#include <linux/kernel.h>
I doubt that such an SmPL rule would be required.
scripts/coccinelle/misc/array_end.cocci line 22
Quoted 5 lines
scripts/coccinelle/misc/array_end.cocci new file +5
-0+ +//---------------------------------------------------------- +// For context mode +//---------------------------------------------------------- +
Please omit such extra comment lines.
Quoted 4 lines
+@depends on i&&context@
scripts/coccinelle/misc/array_end.cocci new file +3
-0+type T; +T[] a; +expression b;
scripts/coccinelle/misc/array_end.cocci line 36
Quoted 10 lines
scripts/coccinelle/misc/array_end.cocci new file +10
-0+@@ +( +* (a + ARRAY_SIZE(a)) +| +* (&a[0] + ARRAY_SIZE(a)) +| +* (&a[ARRAY_SIZE(a)]) +| +* (&a[ARRAY_SIZE(a) - b]) +)
Extra space characters may be omitted directly after SmPL asterisks.
…
Quoted 1 line
+@r depends on (org || report)@
You may omit parentheses here.
…
scripts/coccinelle/misc/array_end.cocci line 92
Quoted 6 lines
+@script:python depends on report@
scripts/coccinelle/misc/array_end.cocci new file +5
-0+p << r.p; +@@ + +msg="WARNING: Use ARRAY_END" +coccilib.report.print_report(p[0], msg)
Would the following command variant be a bit nicer?
coccilib.report.print_report(p[0], "WARNING: opportunity for ARRAY_END()")
By the way:
How do you think about to omit a cover letter for a single patch?
Regards,
Markus
Julia Lawall
maintainerQuoted 34 lines · Markus Elfring
…
Quoted 2 lines
This script makes it easy to find more places where that macro should be used.
…
Quoted 2 lines
+++
b/scripts/coccinelle/misc/array_end.cocci(quoted diff) +0
-0@@ -0,0 +1,93 @@…
Quoted 1 line
+// Confidence: ???
I hope that a more reasonable value can be determined for this information.
…
Quoted 1 line
+// Comments:
Please omit such an empty field.
…
Review
Quoted 4 lines
+@i@
+@@(quoted diff) +2
-0+ +#include <linux/kernel.h>I doubt that such an SmPL rule would be required.
Quoted 7 lines
scripts/coccinelle/misc/array_end.cocci line 22
Quoted 5 lines
scripts/coccinelle/misc/array_end.cocci new file +5
-0+ +//---------------------------------------------------------- +// For context mode +//---------------------------------------------------------- +Please omit such extra comment lines.
No problem to put such comments.
Quoted 18 lines
Quoted 6 lines
+@depends on i&&context@
scripts/coccinelle/misc/array_end.cocci new file +3
-0+type T; +T[] a; +expression b;scripts/coccinelle/misc/array_end.cocci line 36
Quoted 10 lines
scripts/coccinelle/misc/array_end.cocci new file +10
-0+@@ +( +* (a + ARRAY_SIZE(a)) +| +* (&a[0] + ARRAY_SIZE(a)) +| +* (&a[ARRAY_SIZE(a)]) +| +* (&a[ARRAY_SIZE(a) - b]) +)Extra space characters may be omitted directly after SmPL asterisks.
No concern about the spaces either.
Quoted 18 lines
…
Quoted 1 line
+@r depends on (org || report)@
You may omit parentheses here.
…
scripts/coccinelle/misc/array_end.cocci line 92
Quoted 6 lines
+@script:python depends on report@
scripts/coccinelle/misc/array_end.cocci new file +5
-0+p << r.p; +@@ + +msg="WARNING: Use ARRAY_END" +coccilib.report.print_report(p[0], msg)Would the following command variant be a bit nicer?
Quoted 1 line
coccilib.report.print_report(p[0], "WARNING: opportunity for ARRAY_END()")
Either way.
julia
Hi Julia,
Quoted 9 lines · Julia Lawall
Quoted 7 lines
scripts/coccinelle/misc/array_end.cocci line 22
Quoted 5 lines
scripts/coccinelle/misc/array_end.cocci new file +5
-0+ +//---------------------------------------------------------- +// For context mode +//---------------------------------------------------------- +Please omit such extra comment lines.
No problem to put such comments.
Okay; thanks! Although I tend to prefer without them, so I've removed them. Also, a majority of existing scripts don't have them.
Quoted 17 lines
Quoted 8 lines
Quoted 8 lines
+@depends on i&&context@
scripts/coccinelle/misc/array_end.cocci new file +7
-0+type T; +T[] a; +expression b; +@@ +( +* (a + ARRAY_SIZE(a)) +|Quoted 8 lines
scripts/coccinelle/misc/array_end.cocci line 36
Quoted 6 lines
scripts/coccinelle/misc/array_end.cocci new file +6
-0+* (&a[0] + ARRAY_SIZE(a)) +| +* (&a[ARRAY_SIZE(a)]) +| +* (&a[ARRAY_SIZE(a) - b]) +)Extra space characters may be omitted directly after SmPL asterisks.
Quoted 1 line
No concern about the spaces either.
Okay; I've kept them, as the majority has them.
Quoted 16 lines
Quoted 16 lines
…
Quoted 1 line
+@r depends on (org || report)@
You may omit parentheses here.
…
scripts/coccinelle/misc/array_end.cocci line 92
Quoted 6 lines
+@script:python depends on report@
scripts/coccinelle/misc/array_end.cocci new file +5
-0+p << r.p; +@@ + +msg="WARNING: Use ARRAY_END" +coccilib.report.print_report(p[0], msg)Would the following command variant be a bit nicer?
Quoted 3 lines
Quoted 1 line
coccilib.report.print_report(p[0], "WARNING: opportunity for ARRAY_END()")Either way.
I've taken the suggestion. Thanks for the review!
Have a lovely day!
Alex
Quoted 2 lines
julia
Signature · 1 line
<https://www.alejandro-colomar.es>
Hi Markus,
Quoted 6 lines · Markus Elfring
…
Quoted 2 lines
This script makes it easy to find more places where that macro should be used.
Thanks!
Quoted 9 lines
…
Quoted 2 lines
+++
b/scripts/coccinelle/misc/array_end.cocci(quoted diff) +0
-0@@ -0,0 +1,93 @@…
Quoted 1 line
+// Confidence: ???
I hope that a more reasonable value can be determined for this information.
I don't know how the scale works. I know the script has a few false negatives, and AFAIK there are no false positives. To what level of confidence would that belong?
Is that field a keyword, or may I be explicit such as with this?:
// Confidence: no false positives, but a few false negatives
Or maybe I should write that in Comments...
Quoted 4 lines
…
Quoted 1 line
+// Comments:
Please omit such an empty field.
Ok; thanks!
$ grep -rh '^// Comments:' scripts/coccinelle/ | sort | uniq -c
34 // Comments:
2 // Comments: -
1 // Comments: -I ... -all_includes can give more complete results
1 // Comments: Comments on code can be deleted if near code that is removed.
1 // Comments: Some false positives on empty default cases in switch statements.
1 // Comments: requires at least Coccinelle 0.2.4, lex or parse error otherwise
$ find scripts/coccinelle/ -type f | wc -l
76It seems around half of the existing scripts have that. You may want to remove those empty comments. I added it because the scripts I looked at do have it.
Quoted 7 lines
…
Review
Quoted 4 lines
+@i@
+@@(quoted diff) +2
-0+ +#include <linux/kernel.h>I doubt that such an SmPL rule would be required.
Okay, I'll remove it. Thanks!
Quoted 7 lines
scripts/coccinelle/misc/array_end.cocci line 22
Quoted 5 lines
scripts/coccinelle/misc/array_end.cocci new file +5
-0+ +//---------------------------------------------------------- +// For context mode +//---------------------------------------------------------- +Please omit such extra comment lines.
Agree. BTW, you may want to remove such lines from existing scripts:
$ grep -r '^//.*For context mode' scripts/coccinelle/ scripts/coccinelle/null/deref_null.cocci:// For context mode scripts/coccinelle/misc/boolconv.cocci:// For context mode scripts/coccinelle/misc/array_size.cocci:// For context mode scripts/coccinelle/misc/struct_size.cocci:// For context mode scripts/coccinelle/misc/newline_in_nl_msg.cocci:// For context mode scripts/coccinelle/misc/badty.cocci:// For context mode scripts/coccinelle/api/alloc/pool_zalloc-simple.cocci:// For context mode scripts/coccinelle/api/alloc/zalloc-simple.cocci:// For context mode scripts/coccinelle/api/alloc/alloc_cast.cocci:// For context mode scripts/coccinelle/api/pm_runtime.cocci:// For context mode scripts/coccinelle/api/resource_size.cocci:// For context mode scripts/coccinelle/api/vma_pages.cocci:// For context mode
Quoted 8 lines
Quoted 8 lines
+@depends on i&&context@
scripts/coccinelle/misc/array_end.cocci new file +7
-0+type T; +T[] a; +expression b; +@@ +( +* (a + ARRAY_SIZE(a)) +|
Quoted 8 lines
scripts/coccinelle/misc/array_end.cocci line 36
Quoted 6 lines
scripts/coccinelle/misc/array_end.cocci new file +6
-0+* (&a[0] + ARRAY_SIZE(a)) +| +* (&a[ARRAY_SIZE(a)]) +| +* (&a[ARRAY_SIZE(a) - b]) +)Extra space characters may be omitted directly after SmPL asterisks.
Good to know; thanks!
Although most scripts seem to be using white space (space (164) or tab (26)) after the asterisk. Please confirm if you prefer it removed in new scripts. Only 39 scripts don't have white space after it.
$ grep -rh '^\*' scripts/coccinelle/ | grep -o '^..' | sort | uniq -c
26 *
164 *
4 *(
1 *;
1 *E
1 *I
1 *P
2 *W
1 *\
1 *b
1 *c
3 *d
1 *e
4 *f
1 *g
2 *i
1 *l
4 *r
2 *s
1 *u
2 *w
5 *x
$ grep -rh '^\*' scripts/coccinelle/ | grep -o '^.\s' | sort | uniq -c | hd
00000000 20 20 20 20 20 32 36 20 2a 09 0a 20 20 20 20 31 | 26 *.. 1|
00000010 36 34 20 2a 20 0a |64 * .|
00000016
$ grep -rh '^\*' scripts/coccinelle/ | grep -o '^.\S' | wc -l
39Quoted 4 lines
…
Quoted 1 line
+@r depends on (org || report)@
You may omit parentheses here.
Ok.
Quoted 11 lines
…
scripts/coccinelle/misc/array_end.cocci line 92
Quoted 6 lines
+@script:python depends on report@
scripts/coccinelle/misc/array_end.cocci new file +5
-0+p << r.p; +@@ + +msg="WARNING: Use ARRAY_END" +coccilib.report.print_report(p[0], msg)Would the following command variant be a bit nicer?
coccilib.report.print_report(p[0], "WARNING: opportunity for ARRAY_END()")
Sounds good.
Quoted 2 lines
By the way:
How do you think about to omit a cover letter for a single patch?
Sounds reasonable. I like the cover letter as it holds the range-diff, which may become a bit confusing when it's in the same email as the patch, but maybe that's just me.
I'll send v2 in a single email.
Quoted 3 lines
Regards,
Markus
Have a lovely day!
Alex
Signature · 1 line
<https://www.alejandro-colomar.es>
Julia Lawall
maintainerQuoted 18 lines · Alejandro Colomar
Hi Markus,
Quoted 6 lines · Markus Elfring
…
Quoted 2 lines
This script makes it easy to find more places where that macro should be used.
Thanks!
Quoted 6 lines
…
Quoted 2 lines
+++
b/scripts/coccinelle/misc/array_end.cocci(quoted diff) +0
-0@@ -0,0 +1,93 @@…
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
+// Confidence: ???
I hope that a more reasonable value can be determined for this information.
I don't know how the scale works. I know the script has a few false negatives, and AFAIK there are no false positives. To what level of confidence would that belong?
Probably high would be fine. The goal is mostly to indiacte whether the results are most likely correct or whether they will require a lot of study to know if everything is ok.
Quoted 25 lines
Is that field a keyword, or may I be explicit such as with this?:
// Confidence: no false positives, but a few false negatives
Or maybe I should write that in Comments...
Quoted 4 lines
…
Quoted 1 line
+// Comments:
Please omit such an empty field.
Ok; thanks!
$ grep -rh '^// Comments:' scripts/coccinelle/ | sort | uniq -c 34 // Comments: 2 // Comments: - 1 // Comments: -I ... -all_includes can give more complete results 1 // Comments: Comments on code can be deleted if near code that is removed. 1 // Comments: Some false positives on empty default cases in switch statements. 1 // Comments: requires at least Coccinelle 0.2.4, lex or parse error otherwise $ find scripts/coccinelle/ -type f | wc -l 76
Quoted 3 lines
It seems around half of the existing scripts have that. You may want to remove those empty comments. I added it because the scripts I looked at do have it.
I don't require taht an empty comments field be removed.
Quoted 9 lines
Quoted 7 lines
…
Review
Quoted 4 lines
+@i@
+@@(quoted diff) +2
-0+ +#include <linux/kernel.h>I doubt that such an SmPL rule would be required.
Okay, I'll remove it. Thanks!
I'm lacking context. You maye need this if the file doesn't already have it. But it is hard to know if it could be include indirectly...
julia
Quoted 119 lines
Quoted 8 lines
scripts/coccinelle/misc/array_end.cocci line 22
Quoted 6 lines
scripts/coccinelle/misc/array_end.cocci new file +5
-0+ +//---------------------------------------------------------- +// For context mode +//---------------------------------------------------------- +Please omit such extra comment lines.
Agree. BTW, you may want to remove such lines from existing scripts:
$ grep -r '^//.*For context mode' scripts/coccinelle/ scripts/coccinelle/null/deref_null.cocci:// For context mode scripts/coccinelle/misc/boolconv.cocci:// For context mode scripts/coccinelle/misc/array_size.cocci:// For context mode scripts/coccinelle/misc/struct_size.cocci:// For context mode scripts/coccinelle/misc/newline_in_nl_msg.cocci:// For context mode scripts/coccinelle/misc/badty.cocci:// For context mode scripts/coccinelle/api/alloc/pool_zalloc-simple.cocci:// For context mode scripts/coccinelle/api/alloc/zalloc-simple.cocci:// For context mode scripts/coccinelle/api/alloc/alloc_cast.cocci:// For context mode scripts/coccinelle/api/pm_runtime.cocci:// For context mode scripts/coccinelle/api/resource_size.cocci:// For context mode scripts/coccinelle/api/vma_pages.cocci:// For context modeQuoted 8 lines
Quoted 8 lines
+@depends on i&&context@
scripts/coccinelle/misc/array_end.cocci new file +7
-0+type T; +T[] a; +expression b; +@@ +( +* (a + ARRAY_SIZE(a)) +|Quoted 8 lines
scripts/coccinelle/misc/array_end.cocci line 36
Quoted 6 lines
scripts/coccinelle/misc/array_end.cocci new file +6
-0+* (&a[0] + ARRAY_SIZE(a)) +| +* (&a[ARRAY_SIZE(a)]) +| +* (&a[ARRAY_SIZE(a) - b]) +)Extra space characters may be omitted directly after SmPL asterisks.
Good to know; thanks!
Although most scripts seem to be using white space (space (164) or tab (26)) after the asterisk. Please confirm if you prefer it removed in new scripts. Only 39 scripts don't have white space after it.
$ grep -rh '^\*' scripts/coccinelle/ | grep -o '^..' | sort | uniq -c 26 * 164 * 4 *( 1 *; 1 *E 1 *I 1 *P 2 *W 1 *\ 1 *b 1 *c 3 *d 1 *e 4 *f 1 *g 2 *i 1 *l 4 *r 2 *s 1 *u 2 *w 5 *x $ grep -rh '^\*' scripts/coccinelle/ | grep -o '^.\s' | sort | uniq -c | hd 00000000 20 20 20 20 20 32 36 20 2a 09 0a 20 20 20 20 31 | 26 *.. 1| 00000010 36 34 20 2a 20 0a |64 * .| 00000016 $ grep -rh '^\*' scripts/coccinelle/ | grep -o '^.\S' | wc -l 39Quoted 4 lines
…
Quoted 1 line
+@r depends on (org || report)@
You may omit parentheses here.
Ok.
Quoted 11 lines
…
scripts/coccinelle/misc/array_end.cocci line 92
Quoted 6 lines
+@script:python depends on report@
scripts/coccinelle/misc/array_end.cocci new file +5
-0+p << r.p; +@@ + +msg="WARNING: Use ARRAY_END" +coccilib.report.print_report(p[0], msg)Would the following command variant be a bit nicer?
coccilib.report.print_report(p[0], "WARNING: opportunity for ARRAY_END()")Sounds good.
Quoted 2 lines
By the way:
How do you think about to omit a cover letter for a single patch?Sounds reasonable. I like the cover letter as it holds the range-diff, which may become a bit confusing when it's in the same email as the patch, but maybe that's just me.
I'll send v2 in a single email.
Quoted 3 lines
Regards,
MarkusHave a lovely day!
Alex
Hi Julia,
On 2026-03-09T13:21:23+0100, Julia Lawall wrote:
[...]
Quoted 11 lines
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
+// Confidence: ???
I hope that a more reasonable value can be determined for this information.
I don't know how the scale works. I know the script has a few false negatives, and AFAIK there are no false positives. To what level of confidence would that belong?
Probably high would be fine. The goal is mostly to indiacte whether the results are most likely correct or whether they will require a lot of study to know if everything is ok.
Thanks! I've put high with a comment about the false negatives.
[...]
Quoted 17 lines
Quoted 17 lines
Quoted 3 lines
Quoted 1 line
+// Comments:
Please omit such an empty field.
Ok; thanks!
$ grep -rh '^// Comments:' scripts/coccinelle/ | sort | uniq -c 34 // Comments: 2 // Comments: - 1 // Comments: -I ... -all_includes can give more complete results 1 // Comments: Comments on code can be deleted if near code that is removed. 1 // Comments: Some false positives on empty default cases in switch statements. 1 // Comments: requires at least Coccinelle 0.2.4, lex or parse error otherwise $ find scripts/coccinelle/ -type f | wc -l 76
Quoted 5 lines
Quoted 3 lines
It seems around half of the existing scripts have that. You may want to remove those empty comments. I added it because the scripts I looked at do have it.
I don't require taht an empty comments field be removed.
Ok.
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
…
Review
Quoted 4 lines
+@i@
+@@(quoted diff) +2
-0+ +#include <linux/kernel.h>I doubt that such an SmPL rule would be required.
Quoted 4 lines
Quoted 1 line
Okay, I'll remove it. Thanks!
I'm lacking context. You maye need this if the file doesn't already have it. But it is hard to know if it could be include indirectly...
Hmmm, this macro is defined together with ARRAY_SIZE() in <linux/array_size.h>. I guess even if a file isn't including that already (including indirectly), it would do well in including it for using the macro, so I guess it's okay to remove it here.
The only concern would be files that *can't* possibly include it (maybe tools/?).
Quoted 1 line
julia
Cheers,
Alex
Signature · 1 line
<https://www.alejandro-colomar.es>
PATCH v2 1/1 scripts/coccinelle: Add script for using ARRAY_END()
In reply to Alejandro ColomarRecently, we added an ARRAY_END() macro to simplify finding a pointer one past the last element in an array. Such a pointer is often called the 'end', and thus the macro name.
Make it easy to find more places where that macro should be used.
See also:436debc9cad8 ("array_size.h: add ARRAY_END()") 8118f197b7b7 ("mm: fix benign off-by-one bugs") a9e5620c9a9e ("kernel: fix off-by-one benign bugs") 61e9210e2392 ("mm: use ARRAY_END() instead of open-coding it")
--- scripts/coccinelle/misc/array_end.cocci | 74 +++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 scripts/coccinelle/misc/array_end.cocci
scripts/coccinelle/misc/array_end.cocci new file +74 -0
@@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// Use ARRAY_END instead of an expression derived from ARRAY_SIZE +// +// Confidence: High +// Copyright: 2026, Alejandro Colomar <[email protected]> +// Comments: No known false positives, but has a few false negatives +// Options: --no-includes --include-headers + +virtual patch +virtual context +virtual org +virtual report + +@depends on context@ +type T; +T[] a; +expression b; +@@ +( +* (a + ARRAY_SIZE(a)) +| +* (&a[0] + ARRAY_SIZE(a)) +| +* (&a[ARRAY_SIZE(a)]) +| +* (&a[ARRAY_SIZE(a) - b]) +) + +@depends on patch@ +type T; +T[] a; +expression b; +@@ +( +- (a + ARRAY_SIZE(a)) ++ ARRAY_END(a) +| +- (&a[0] + ARRAY_SIZE(a)) ++ ARRAY_END(a) +| +- (&a[ARRAY_SIZE(a)]) ++ ARRAY_END(a) +| +- (&a[ARRAY_SIZE(a) - b]) ++ ARRAY_END(a) - b +) + +@r depends on org || report@ +type T; +T[] a; +expression b; +position p; +@@ +( + (a@p + ARRAY_SIZE(a)) +| + (&a[0]@p + ARRAY_SIZE(a)) +| + (&a[ARRAY_SIZE(a)]@p) +| + (&a[ARRAY_SIZE(a)@p - b]) +) + +@script:python depends on org@ +p << r.p; +@@ + +coccilib.org.print_todo(p[0], "WARNING should use ARRAY_END") + +@script:python depends on report@ +p << r.p; +@@ + +coccilib.report.print_report(p[0], "WARNING: opportunity for ARRAY_END")
Range-diff against v1:
1: f1c9dff5 ! 1: 9fd8d3d1 scripts/coccinelle: Add script for using ARRAY_END()
@@ Commit message
one past the last element in an array. Such a pointer is often called
the 'end', and thus the macro name.
- This script makes it easy to find more places where that macro should be
- used.
+ Make it easy to find more places where that macro should be used.
See also:
436debc9cad8 ("array_size.h: add ARRAY_END()")
@@ Commit message
61e9210e2392 ("mm: use ARRAY_END() instead of open-coding it")
Cc: Kees Cook <[email protected]>
+ Cc: Markus Elfring <[email protected]>
Cc: Julia Lawall <[email protected]>
Cc: Nicolas Palix <[email protected]>
Signed-off-by: Alejandro Colomar <[email protected]>
@@ scripts/coccinelle/misc/array_end.cocci (new)
+// SPDX-License-Identifier: GPL-2.0-only
+/// Use ARRAY_END instead of an expression derived from ARRAY_SIZE
+//
-+// Confidence: ???
++// Confidence: High
+// Copyright: 2026, Alejandro Colomar <[email protected]>
-+// Comments:
++// Comments: No known false positives, but has a few false negatives
+// Options: --no-includes --include-headers
+
+virtual patch
@@ scripts/coccinelle/misc/array_end.cocci (new)
+virtual org
+virtual report
+
-+@i@
-+@@
-+
-+#include <linux/kernel.h>
-+
-+//----------------------------------------------------------
-+// For context mode
-+//----------------------------------------------------------
-+
-+@depends on i&&context@
++@depends on context@
+type T;
+T[] a;
+expression b;
@@ scripts/coccinelle/misc/array_end.cocci (new)
+* (&a[ARRAY_SIZE(a) - b])
+)
+
-+//----------------------------------------------------------
-+// For patch mode
-+//----------------------------------------------------------
-+
-+@depends on i&&patch@
++@depends on patch@
+type T;
+T[] a;
+expression b;
@@ scripts/coccinelle/misc/array_end.cocci (new)
++ ARRAY_END(a) - b
+)
+
-+//----------------------------------------------------------
-+// For org and report mode
-+//----------------------------------------------------------
-+
-+@r depends on (org || report)@
++@r depends on org || report@
+type T;
+T[] a;
+expression b;
@@ scripts/coccinelle/misc/array_end.cocci (new)
+p << r.p;
+@@
+
-+msg="WARNING: Use ARRAY_END"
-+coccilib.report.print_report(p[0], msg)
-+
++coccilib.report.print_report(p[0], "WARNING: opportunity for ARRAY_END")Signature · 1 line
2.53.0
…
Quoted 2 lines
--- scripts/coccinelle/misc/array_end.cocci | 74 +++++++++++++++++++++++++
…
Some contributors would appreciate patch version descriptions.
https://lore.kernel.org/all/?q=%22This+looks+like+a+new+version+of+a+previously+submitted+patch%22
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst?h=v7.0-rc3#n310
May a subdirectory name be omitted from the subject prefix?
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/log/scripts/coccinelle/
…
Quoted 1 line
+// Comments: No known false positives, but has a few false negatives
Would such information motivate for any further software refinements?
…
scripts/coccinelle/misc/array_end.cocci line 68
Quoted 5 lines
+@script:python depends on org@
scripts/coccinelle/misc/array_end.cocci new file +4
-0+p << r.p; +@@ + +coccilib.org.print_todo(p[0], "WARNING should use ARRAY_END")
…
I suggest to reuse the message also from the SmPL report rule.
Regards,
Markus
Hi Markus,
Quoted 8 lines · Markus Elfring
…
Quoted 2 lines
--- scripts/coccinelle/misc/array_end.cocci | 74 +++++++++++++++++++++++++…
Some contributors would appreciate patch version descriptions.
https://lore.kernel.org/all/?q=%22This+looks+like+a+new+version+of+a+previously+submitted+patch%22
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst?h=v7.0-rc3#n310
I replied to all of your comments, and said how I would address them, in reply to v1. This v2 is in-reply-to v1, so that that sub-thread is easy to find. And at the bottom is a range-diff where you can find all the exact changes from v1 to v2.
I could have noted in plain English the changes from v1 to v2, but I thought it might be a bit redundant.
Quoted 2 lines
May a subdirectory name be omitted from the subject prefix?
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/log/scripts/coccinelle/
Yeah, we could do that. Here's what I checked for writing the subject prefix:
$ git log --oneline --author Lawall torvalds/master scripts/coccinelle/misc/ f01701ce update Coccinelle URL 92b2dada scripts/coccinelle: drop bugon.cocci c3003315 scripts: coccinelle: boolinit: drop warnings on named constants 518d8a56 scripts: coccinelle: Correct warning message b825b432 scripts: coccinelle: only suggest true/false in files that already use> 937c812d coccinelle: orplus: reorganize to improve performance 69c4907b Coccinelle: use false positive annotation f75621c6 coccinelle: bugon: reduce rule applicability c7eaa887 Coccinelle: array_size: reduce rule applicability 8f551bef Coccinelle: reduce rule applicability 74a8478f coccinelle: misc: move constants to the right 932058a5 coccinelle: misc: semantic patch to delete overly complex return code > 24f0c2d6 scripts/coccinelle: find constant additions that could be bit ors ad99ac2f scripts/coccinelle/misc/warn.cocci: use WARN 2cbd0825 scripts/coccinelle: sizeof of pointer 4619c2b8 scripts/coccinelle: address test is always true 89910581 coccinelle: semantic patch for bool issues 4a05f067 coccinelle: semantic patch to check for PTR_ERR after reassignment 29a36d4d scripts/coccinelle: improve the coverage of some semantic patches a1087ef6 scripts/coccinelle: update for compatability with Coccinelle 0.2.4
Since the latest line and a decent amount of lines have "scripts/coccinelle", I picked that. I don't have a preference, so please let me know what's the preferred one. I tend to prefer more explicit ones, even if slightly longer, but I'll take whatever the maintainers' preference is.
The only one I didn't really like was the 'scripts: coccinelle:' one. Paths are more readable if we're going to include all the subdirectories. But this is just my opinion.
Quoted 4 lines
…
Quoted 1 line
+// Comments: No known false positives, but has a few false negatives
Would such information motivate for any further software refinements?
Yes, if anyone here knows how to handle the false negatives and wants to work with me on improving those, I'm very interested.
Here's one case which isn't caught, for example (which I expect will be difficult to handle, if not impossible):
@@ -2876,7 +2876,7 @@ static struct dentry *proc_##LSM##_attr_dir_lookup(struct
inode *dir, \
{ \
return proc_pident_lookup(dir, dentry, \
LSM##_attr_dir_stuff, \
- LSM##_attr_dir_stuff + ARRAY_SIZE(LSM##_attr_dir_stuff)); \
+ ARRAY_END(LSM##_attr_dir_stuff)); \
} \
\
static const struct inode_operations proc_##LSM##_attr_dir_inode_ops = { \I could research and find other false negatives.
Cheers,
Alex
Signature · 1 line
<https://www.alejandro-colomar.es>
Hi Markus, Julia,
Quoted 22 lines · Alejandro Colomar
Quoted 4 lines
…
Quoted 1 line
+// Comments: No known false positives, but has a few false negatives
Would such information motivate for any further software refinements?
Yes, if anyone here knows how to handle the false negatives and wants to work with me on improving those, I'm very interested.
Here's one case which isn't caught, for example (which I expect will be difficult to handle, if not impossible):
@@ -2876,7 +2876,7 @@ static struct dentry *proc_##LSM##_attr_dir_lookup(struct inode *dir, \ { \ return proc_pident_lookup(dir, dentry, \ LSM##_attr_dir_stuff, \ - LSM##_attr_dir_stuff + ARRAY_SIZE(LSM##_attr_dir_stuff)); \ + ARRAY_END(LSM##_attr_dir_stuff)); \ } \ \ static const struct inode_operations proc_##LSM##_attr_dir_inode_ops = { \
Quoted 1 line
I could research and find other false negatives.
Here are more false negatives that I found manually. The semantic patch didn't find them. Does anyone know how we could improve it or why it didn't find them?
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 8d81c1e7..d883e1bd 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -555,10 +555,8 @@ static struct rtas_function rtas_function_table[] __ro_after_init = {
},
};
-#define for_each_rtas_function(funcp) \
- for (funcp = &rtas_function_table[0]; \
- funcp < &rtas_function_table[ARRAY_SIZE(rtas_function_table)]; \
- ++funcp)
+#define for_each_rtas_function(f) \
+ for (f = rtas_function_table; f < ARRAY_END(rtas_function_table); ++f)
/*
* Nearly all RTAS calls need to be serialized. All uses of the
diff --git a/arch/s390/purgatory/purgatory.c b/arch/s390/purgatory/purgatory.c
index ecb38102..3e45056b 100644
--- a/arch/s390/purgatory/purgatory.c
+++ b/arch/s390/purgatory/purgatory.c
@@ -19,7 +19,7 @@ int verify_sha256_digest(void)
struct sha256_ctx sctx;
sha256_init(&sctx);
- end = purgatory_sha_regions + ARRAY_SIZE(purgatory_sha_regions);
+ end = ARRAY_END(purgatory_sha_regions);
for (ptr = purgatory_sha_regions; ptr < end; ptr++)
sha256_update(&sctx, (uint8_t *)(ptr->start), ptr->len);
diff --git a/drivers/md/bcache/util.h b/drivers/md/bcache/util.h
index f61ab1ba..988b0773 100644
--- a/drivers/md/bcache/util.h
+++ b/drivers/md/bcache/util.h
@@ -273,9 +273,7 @@ do { \
BUILD_BUG_ON(sizeof((array)->data[0]) < sizeof(void *)); \
(array)->freelist = NULL; \
\
- for (_i = (array)->data; \
- _i < (array)->data + ARRAY_SIZE((array)->data); \
- _i++) \
+ for (_i = (array)->data; _i < ARRAY_END((array)->data); _i++) \
array_free(array, _i); \
} while (0)
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 6e38aa73..c0cd2d1e 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -444,9 +444,7 @@ ath_node_to_tid(struct ath_node *an, u8 tidno)
#define case_rtn_string(val) case val: return #val
#define ath_for_each_chanctx(_sc, _ctx) \
- for (ctx = &sc->chanctx[0]; \
- ctx <= &sc->chanctx[ARRAY_SIZE(sc->chanctx) - 1]; \
- ctx++)
+ for (ctx = &sc->chanctx[0]; ctx <= ARRAY_END(sc->chanctx) - 1; ctx++)
void ath_chanctx_init(struct ath_softc *sc);
void ath_chanctx_set_channel(struct ath_softc *sc, struct ath_chanctx *ctx,
diff --git a/drivers/net/wireless/intel/iwlwifi/mei/net.c b/drivers/net/wireless/intel/iwlwifi/mei/net.c
index eac46d1a..b0d2905d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mei/net.c
+++ b/drivers/net/wireless/intel/iwlwifi/mei/net.c
@@ -43,7 +43,7 @@ static bool iwl_mei_rx_filter_eth(const struct ethhdr *ethhdr,
return false;
for (filt = &filters->eth_filters[0];
- filt < &filters->eth_filters[0] + ARRAY_SIZE(filters->eth_filters);
+ filt < ARRAY_END(filters->eth_filters);
filt++) {
/* Assume there are no enabled filter after a disabled one */
if (!(filt->flags & SAP_ETH_FILTER_ENABLED))
@@ -142,7 +142,7 @@ iwl_mei_rx_filter_tcp_udp(struct sk_buff *skb, bool ip_match,
const struct iwl_sap_flex_filter *filt;
for (filt = &filters->flex_filters[0];
- filt < &filters->flex_filters[0] + ARRAY_SIZE(filters->flex_filters);
+ filt < ARRAY_END(filters->flex_filters);
filt++) {
if (!(filt->flags & SAP_FLEX_FILTER_ENABLED))
break;
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index f6ce6e26..a7aa3ce4 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1490,7 +1490,7 @@ static int proc_conninfo_ex(struct usb_dev_state *ps,
if (ci.num_ports < ARRAY_SIZE(ci.ports))
memmove(&ci.ports[0],
- &ci.ports[ARRAY_SIZE(ci.ports) - ci.num_ports],
+ ARRAY_END(ci.ports) - ci.num_ports,
ci.num_ports);
if (copy_to_user(arg, &ci, min(sizeof(ci), size)))
diff --git a/fs/smb/client/dfs.h b/fs/smb/client/dfs.h
index e60f0a24..4977f649 100644
--- a/fs/smb/client/dfs.h
+++ b/fs/smb/client/dfs.h
@@ -32,7 +32,7 @@ struct dfs_ref_walk {
};
#define ref_walk_start(w) ((w)->refs)
-#define ref_walk_end(w) (&(w)->refs[ARRAY_SIZE((w)->refs) - 1])
+#define ref_walk_end(w) (ARRAY_END((w)->refs) - 1)
#define ref_walk_cur(w) ((w)->ref)
#define ref_walk_descend(w) (--ref_walk_cur(w) >= ref_walk_start(w))
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 1b9b18e5..0ff49f24 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -2298,7 +2298,7 @@ static unsigned int PROG_NAME(stack_size)(const void *ctx, const struct bpf_insn
u64 regs[MAX_BPF_EXT_REG] = {}; \
\
kmsan_unpoison_memory(stack, sizeof(stack)); \
- FP = (u64) (unsigned long) &stack[ARRAY_SIZE(stack)]; \
+ FP = (u64) (unsigned long) ARRAY_END(stack); \
ARG1 = (u64) (unsigned long) ctx; \
return ___bpf_prog_run(regs, insn); \
}
@@ -2312,7 +2312,7 @@ static u64 PROG_NAME_ARGS(stack_size)(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5, \
u64 regs[MAX_BPF_EXT_REG]; \
\
kmsan_unpoison_memory(stack, sizeof(stack)); \
- FP = (u64) (unsigned long) &stack[ARRAY_SIZE(stack)]; \
+ FP = (u64) (unsigned long) ARRAY_END(stack); \
BPF_R1 = r1; \
BPF_R2 = r2; \
BPF_R3 = r3; \
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 198f8a0d..d98e42a3 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2009,7 +2009,7 @@ static struct sk_buff *tcp_maybe_skipping_dsack(struct sk_buff *skb,
static int tcp_sack_cache_ok(const struct tcp_sock *tp, const struct tcp_sack_block *cache)
{
- return cache < tp->recv_sack_cache + ARRAY_SIZE(tp->recv_sack_cache);
+ return cache < ARRAY_END(tp->recv_sack_cache);
}
static int
@@ -2109,7 +2109,7 @@ tcp_sacktag_write_queue(struct sock *sk, const struct sk_buff *ack_skb,
if (!tp->sacked_out) {
/* It's already past, so skip checking against it */
- cache = tp->recv_sack_cache + ARRAY_SIZE(tp->recv_sack_cache);
+ cache = ARRAY_END(tp->recv_sack_cache);
} else {
cache = tp->recv_sack_cache;
/* Skip empty blocks in at head of the cache */Have a lovely day!
Alex
Signature · 1 line
<https://www.alejandro-colomar.es>
Julia Lawall
maintainerQuoted 25 lines · Alejandro Colomar
Hi Markus, Julia,
Quoted 22 lines · Alejandro Colomar
Quoted 4 lines
…
Quoted 1 line
+// Comments: No known false positives, but has a few false negatives
Would such information motivate for any further software refinements?
Yes, if anyone here knows how to handle the false negatives and wants to work with me on improving those, I'm very interested.
Here's one case which isn't caught, for example (which I expect will be difficult to handle, if not impossible):
@@ -2876,7 +2876,7 @@ static struct dentry *proc_##LSM##_attr_dir_lookup(struct inode *dir, \ { \ return proc_pident_lookup(dir, dentry, \ LSM##_attr_dir_stuff, \ - LSM##_attr_dir_stuff + ARRAY_SIZE(LSM##_attr_dir_stuff)); \ + ARRAY_END(LSM##_attr_dir_stuff)); \ } \ \ static const struct inode_operations proc_##LSM##_attr_dir_inode_ops = { \
Quoted 5 lines
Quoted 1 line
I could research and find other false negatives.
Here are more false negatives that I found manually. The semantic patch didn't find them. Does anyone know how we could improve it or why it didn't find them?
Typically, some things are not found when Coccinelle is not able to parse the relevnt code. You can see this with the --verbose-parsing option. BUG indicates the line where the parsing problem was detected and bug indicates the other lines that were ignored due to the parse error.
julia
Quoted 161 lines
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 8d81c1e7..d883e1bd 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -555,10 +555,8 @@ static struct rtas_function rtas_function_table[] __ro_after_init = { }, }; -#define for_each_rtas_function(funcp) \ - for (funcp = &rtas_function_table[0]; \ - funcp < &rtas_function_table[ARRAY_SIZE(rtas_function_table)]; \ - ++funcp) +#define for_each_rtas_function(f) \ + for (f = rtas_function_table; f < ARRAY_END(rtas_function_table); ++f) /* * Nearly all RTAS calls need to be serialized. All uses of the diff --git a/arch/s390/purgatory/purgatory.c b/arch/s390/purgatory/purgatory.c index ecb38102..3e45056b 100644 --- a/arch/s390/purgatory/purgatory.c +++ b/arch/s390/purgatory/purgatory.c @@ -19,7 +19,7 @@ int verify_sha256_digest(void) struct sha256_ctx sctx; sha256_init(&sctx); - end = purgatory_sha_regions + ARRAY_SIZE(purgatory_sha_regions); + end = ARRAY_END(purgatory_sha_regions); for (ptr = purgatory_sha_regions; ptr < end; ptr++) sha256_update(&sctx, (uint8_t *)(ptr->start), ptr->len); diff --git a/drivers/md/bcache/util.h b/drivers/md/bcache/util.h index f61ab1ba..988b0773 100644 --- a/drivers/md/bcache/util.h +++ b/drivers/md/bcache/util.h @@ -273,9 +273,7 @@ do { \ BUILD_BUG_ON(sizeof((array)->data[0]) < sizeof(void *)); \ (array)->freelist = NULL; \ \ - for (_i = (array)->data; \ - _i < (array)->data + ARRAY_SIZE((array)->data); \ - _i++) \ + for (_i = (array)->data; _i < ARRAY_END((array)->data); _i++) \ array_free(array, _i); \ } while (0) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 6e38aa73..c0cd2d1e 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -444,9 +444,7 @@ ath_node_to_tid(struct ath_node *an, u8 tidno) #define case_rtn_string(val) case val: return #val #define ath_for_each_chanctx(_sc, _ctx) \ - for (ctx = &sc->chanctx[0]; \ - ctx <= &sc->chanctx[ARRAY_SIZE(sc->chanctx) - 1]; \ - ctx++) + for (ctx = &sc->chanctx[0]; ctx <= ARRAY_END(sc->chanctx) - 1; ctx++) void ath_chanctx_init(struct ath_softc *sc); void ath_chanctx_set_channel(struct ath_softc *sc, struct ath_chanctx *ctx, diff --git a/drivers/net/wireless/intel/iwlwifi/mei/net.c b/drivers/net/wireless/intel/iwlwifi/mei/net.c index eac46d1a..b0d2905d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mei/net.c +++ b/drivers/net/wireless/intel/iwlwifi/mei/net.c @@ -43,7 +43,7 @@ static bool iwl_mei_rx_filter_eth(const struct ethhdr *ethhdr, return false; for (filt = &filters->eth_filters[0]; - filt < &filters->eth_filters[0] + ARRAY_SIZE(filters->eth_filters); + filt < ARRAY_END(filters->eth_filters); filt++) { /* Assume there are no enabled filter after a disabled one */ if (!(filt->flags & SAP_ETH_FILTER_ENABLED)) @@ -142,7 +142,7 @@ iwl_mei_rx_filter_tcp_udp(struct sk_buff *skb, bool ip_match, const struct iwl_sap_flex_filter *filt; for (filt = &filters->flex_filters[0]; - filt < &filters->flex_filters[0] + ARRAY_SIZE(filters->flex_filters); + filt < ARRAY_END(filters->flex_filters); filt++) { if (!(filt->flags & SAP_FLEX_FILTER_ENABLED)) break; diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index f6ce6e26..a7aa3ce4 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1490,7 +1490,7 @@ static int proc_conninfo_ex(struct usb_dev_state *ps, if (ci.num_ports < ARRAY_SIZE(ci.ports)) memmove(&ci.ports[0], - &ci.ports[ARRAY_SIZE(ci.ports) - ci.num_ports], + ARRAY_END(ci.ports) - ci.num_ports, ci.num_ports); if (copy_to_user(arg, &ci, min(sizeof(ci), size))) diff --git a/fs/smb/client/dfs.h b/fs/smb/client/dfs.h index e60f0a24..4977f649 100644 --- a/fs/smb/client/dfs.h +++ b/fs/smb/client/dfs.h @@ -32,7 +32,7 @@ struct dfs_ref_walk { }; #define ref_walk_start(w) ((w)->refs) -#define ref_walk_end(w) (&(w)->refs[ARRAY_SIZE((w)->refs) - 1]) +#define ref_walk_end(w) (ARRAY_END((w)->refs) - 1) #define ref_walk_cur(w) ((w)->ref) #define ref_walk_descend(w) (--ref_walk_cur(w) >= ref_walk_start(w)) diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index 1b9b18e5..0ff49f24 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -2298,7 +2298,7 @@ static unsigned int PROG_NAME(stack_size)(const void *ctx, const struct bpf_insn u64 regs[MAX_BPF_EXT_REG] = {}; \ \ kmsan_unpoison_memory(stack, sizeof(stack)); \ - FP = (u64) (unsigned long) &stack[ARRAY_SIZE(stack)]; \ + FP = (u64) (unsigned long) ARRAY_END(stack); \ ARG1 = (u64) (unsigned long) ctx; \ return ___bpf_prog_run(regs, insn); \ } @@ -2312,7 +2312,7 @@ static u64 PROG_NAME_ARGS(stack_size)(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5, \ u64 regs[MAX_BPF_EXT_REG]; \ \ kmsan_unpoison_memory(stack, sizeof(stack)); \ - FP = (u64) (unsigned long) &stack[ARRAY_SIZE(stack)]; \ + FP = (u64) (unsigned long) ARRAY_END(stack); \ BPF_R1 = r1; \ BPF_R2 = r2; \ BPF_R3 = r3; \ diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 198f8a0d..d98e42a3 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2009,7 +2009,7 @@ static struct sk_buff *tcp_maybe_skipping_dsack(struct sk_buff *skb, static int tcp_sack_cache_ok(const struct tcp_sock *tp, const struct tcp_sack_block *cache) { - return cache < tp->recv_sack_cache + ARRAY_SIZE(tp->recv_sack_cache); + return cache < ARRAY_END(tp->recv_sack_cache); } static int @@ -2109,7 +2109,7 @@ tcp_sacktag_write_queue(struct sock *sk, const struct sk_buff *ack_skb, if (!tp->sacked_out) { /* It's already past, so skip checking against it */ - cache = tp->recv_sack_cache + ARRAY_SIZE(tp->recv_sack_cache); + cache = ARRAY_END(tp->recv_sack_cache); } else { cache = tp->recv_sack_cache; /* Skip empty blocks in at head of the cache */Have a lovely day!
Alex
Hi Julia,
Quoted 8 lines · Julia Lawall
Quoted 3 lines
Here are more false negatives that I found manually. The semantic patch didn't find them. Does anyone know how we could improve it or why it didn't find them?
Typically, some things are not found when Coccinelle is not able to parse the relevnt code. You can see this with the --verbose-parsing option. BUG indicates the line where the parsing problem was detected and bug indicates the other lines that were ignored due to the parse error.
Ahhh, thanks! It seems there were issues parsing unrelated code, so not a problem of the semantic patch. I'll remove the comment about false negatives and send v3.
Quoted 1 line
julia
Have a lovely night!
Alex
Signature · 1 line
<https://www.alejandro-colomar.es>
Quoted 2 lines
Here are more false negatives that I found manually. The semantic patch didn't find them.
Thanks for your clarification approach.
Quoted 1 line
Does anyone know how we could improve it
The corresponding knowledge is evolving.
Quoted 2 lines
or why it
didn't find them?
I suggest to refine case distinctions.
Can further test cases help to achieve a better understanding for the affected data processing?
…
Quoted 11 lines
+++ b/arch/powerpc/kernel/rtas.c
@@ -555,10 +555,8 @@ static struct rtas_function rtas_function_table[] __ro_after_init = {
},
};
-#define for_each_rtas_function(funcp) \
- for (funcp = &rtas_function_table[0]; \
- funcp < &rtas_function_table[ARRAY_SIZE(rtas_function_table)]; \
- ++funcp)
+#define for_each_rtas_function(f) \
+ for (f = rtas_function_table; f < ARRAY_END(rtas_function_table); ++f)Are there development challenges to reconsider for macro definitions?
…
Quoted 10 lines
+++ b/drivers/net/wireless/intel/iwlwifi/mei/net.c
@@ -43,7 +43,7 @@ static bool iwl_mei_rx_filter_eth(const struct ethhdr *ethhdr,
return false;
for (filt = &filters->eth_filters[0];
- filt < &filters->eth_filters[0] + ARRAY_SIZE(filters->eth_filters);
+ filt < ARRAY_END(filters->eth_filters);
filt++) {
/* Assume there are no enabled filter after a disabled one */
if (!(filt->flags & SAP_ETH_FILTER_ENABLED))Will any loops become better supported?
Regards,
Markus
Hi Markus,
On 2026-03-16T08:18:17+0100, Markus Elfring wrote:
[...]
Quoted 6 lines
…
Quoted 5 lines
+++ b/arch/powerpc/kernel/rtas.c @@ -555,10 +555,8 @@ static struct rtas_function rtas_function_table[] __ro_after_init = { }, };
Quoted 8 lines
Quoted 6 lines
-#define
for_each_rtas_function(funcp)\
- for (funcp = &rtas_function_table[0]; \
- funcp < &rtas_function_table[ARRAY_SIZE(rtas_function_table)]; \
- ++funcp)
+#definefor_each_rtas_function(f)\
+ for (f =rtas_function_table; f <ARRAY_END(rtas_function_table); ++f)Are there development challenges to reconsider for macro definitions?
I've seen cases within macros that were correctly reported, so it's not an issue with macros.
Quoted 5 lines
…
Quoted 4 lines
+++ b/drivers/net/wireless/intel/iwlwifi/mei/net.c @@ -43,7 +43,7 @@ static bool iwl_mei_rx_filter_eth(const struct ethhdr *ethhdr, return false;
Quoted 8 lines
Quoted 6 lines
for (filt = &filters->eth_filters[0]; - filt < &filters->eth_filters[0] + ARRAY_SIZE(filters->eth_filters); + filt < ARRAY_END(filters->eth_filters); filt++) { /* Assume there are no enabled filter after a disabled one */ if (!(filt->flags & SAP_ETH_FILTER_ENABLED))Will any loops become better supported?
I've seen cases within loops that worked correctly, so it's not an issue with loops.
After debugging like Julia suggested, it was indeed what Julia guessed:
some files can't be parsed correctly, at places unrelated to this. There's nothing we can do to improve the patch.
Have a lovely day!
Alex
Signature · 1 line
<https://www.alejandro-colomar.es>
Quoted 1 line
There's nothing we can do to improve the patch.
Can we influence the evolution any further also for components of the Coccinelle software?
Regards,
Markus
PATCH v3 1/1 scripts/coccinelle: Add script for using ARRAY_END()
In reply to Alejandro ColomarRecently, we added an ARRAY_END() macro to simplify finding a pointer one past the last element in an array. Such a pointer is often called the 'end', and thus the macro name.
Make it easy to find more places where that macro should be used.
See also:436debc9cad8 ("array_size.h: add ARRAY_END()") 8118f197b7b7 ("mm: fix benign off-by-one bugs") a9e5620c9a9e ("kernel: fix off-by-one benign bugs") 61e9210e2392 ("mm: use ARRAY_END() instead of open-coding it")
---
Hi!
This v3 only has one change: I've removed the comment about the false negatives. They were due to spatch(1) not being able to correctly parse unrelated code elsewhere.
See range-diff and interdiff at the bottom.
Have a lovely night!
Alex
scripts/coccinelle/misc/array_end.cocci | 73 +++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 scripts/coccinelle/misc/array_end.cocci
scripts/coccinelle/misc/array_end.cocci new file +73 -0
@@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// Use ARRAY_END instead of an expression derived from ARRAY_SIZE +// +// Confidence: High +// Copyright: 2026, Alejandro Colomar <[email protected]> +// Options: --no-includes --include-headers + +virtual patch +virtual context +virtual org +virtual report + +@depends on context@ +type T; +T[] a; +expression b; +@@ +( +* (a + ARRAY_SIZE(a)) +| +* (&a[0] + ARRAY_SIZE(a)) +| +* (&a[ARRAY_SIZE(a)]) +| +* (&a[ARRAY_SIZE(a) - b]) +) + +@depends on patch@ +type T; +T[] a; +expression b; +@@ +( +- (a + ARRAY_SIZE(a)) ++ ARRAY_END(a) +| +- (&a[0] + ARRAY_SIZE(a)) ++ ARRAY_END(a) +| +- (&a[ARRAY_SIZE(a)]) ++ ARRAY_END(a) +| +- (&a[ARRAY_SIZE(a) - b]) ++ ARRAY_END(a) - b +) + +@r depends on org || report@ +type T; +T[] a; +expression b; +position p; +@@ +( + (a@p + ARRAY_SIZE(a)) +| + (&a[0]@p + ARRAY_SIZE(a)) +| + (&a[ARRAY_SIZE(a)]@p) +| + (&a[ARRAY_SIZE(a)@p - b]) +) + +@script:python depends on org@ +p << r.p; +@@ + +coccilib.org.print_todo(p[0], "WARNING should use ARRAY_END") + +@script:python depends on report@ +p << r.p; +@@ + +coccilib.report.print_report(p[0], "WARNING: opportunity for ARRAY_END")
Range-diff:
1: 9fd8d3d1 ! 1: 2ae22f8b scripts/coccinelle: Add script for using ARRAY_END()
@@ scripts/coccinelle/misc/array_end.cocci (new)
+//
+// Confidence: High
+// Copyright: 2026, Alejandro Colomar <[email protected]>
-+// Comments: No known false positives, but has a few false negatives
+// Options: --no-includes --include-headers
+
+virtual patch
Signature · 1 line
2.53.0
Quoted 19 lines · Alejandro Colomar
Recently, we added an
ARRAY_END()macro to simplify finding a pointer one past the last element in an array. Such a pointer is often called the 'end', and thus the macro name.Make it easy to find more places where that macro should be used.
See also:
436debc9cad8("array_size.h: addARRAY_END()")8118f197b7b7("mm: fix benign off-by-one bugs")a9e5620c9a9e("kernel: fix off-by-one benign bugs")61e9210e2392("mm: useARRAY_END()instead of open-coding it")Cc Kees Cook <[email protected]>Cc Markus Elfring <[email protected]>Cc Julia Lawall <[email protected]>Cc Nicolas Palix <[email protected]>Signed-off-by Alejandro Colomar <[email protected]>---
Quoted 7 lines
Hi!
This v3 only has one change: I've removed the comment about the false negatives. They were due to spatch(1) not being able to correctly parse unrelated code elsewhere.
See range-diff and interdiff at the bottom.
Oops, actually, only the range-diff.
Quoted 102 lines
Have a lovely night!
Alexscripts/coccinelle/misc/array_end.cocci | 73 +++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 scripts/coccinelle/misc/array_end.cocciscripts/coccinelle/misc/array_end.cocci new file +73
-0@@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// Use ARRAY_END instead of an expression derived from ARRAY_SIZE +// +// Confidence: High +// Copyright: 2026, Alejandro Colomar <[email protected]> +// Options: --no-includes --include-headers + +virtual patch +virtual context +virtual org +virtual report + +@depends on context@ +type T; +T[] a; +expression b; +@@ +( +* (a + ARRAY_SIZE(a)) +| +* (&a[0] + ARRAY_SIZE(a)) +| +* (&a[ARRAY_SIZE(a)]) +| +* (&a[ARRAY_SIZE(a) - b]) +) + +@depends on patch@ +type T; +T[] a; +expression b; +@@ +( +- (a + ARRAY_SIZE(a)) ++ ARRAY_END(a) +| +- (&a[0] + ARRAY_SIZE(a)) ++ ARRAY_END(a) +| +- (&a[ARRAY_SIZE(a)]) ++ ARRAY_END(a) +| +- (&a[ARRAY_SIZE(a) - b]) ++ ARRAY_END(a) - b +) + +@r depends on org || report@ +type T; +T[] a; +expression b; +position p; +@@ +( + (a@p + ARRAY_SIZE(a)) +| + (&a[0]@p + ARRAY_SIZE(a)) +| + (&a[ARRAY_SIZE(a)]@p) +| + (&a[ARRAY_SIZE(a)@p - b]) +) + +@script:python depends on org@ +p << r.p; +@@ + +coccilib.org.print_todo(p[0], "WARNING should use ARRAY_END") + +@script:python depends on report@ +p << r.p; +@@ + +coccilib.report.print_report(p[0], "WARNING: opportunity for ARRAY_END")Range-diff:
1:9fd8d3d1! 1:2ae22f8bscripts/coccinelle: Add script for usingARRAY_END()
@@scripts/coccinelle/misc/array_end.cocci(new)
+//
+// Confidence: High
+// Copyright: 2026, Alejandro Colomar <[email protected]>
-+// Comments: No known false positives, but has a few false negatives
+// Options: --no-includes --include-headers
+
+virtual patchSignature · 1 line
2.53.0
Signature · 1 line
<https://www.alejandro-colomar.es>
Hi Julia, Kees,
Just a gentle ping on this patch. Is there anything else I should do to get this merged?
Have a lovely day!
Alex
Quoted 131 lines
Date: 2026-03-15 23:11:03+0100
From: Alejandro Colomar <[email protected]>Recently, we added an
ARRAY_END()macro to simplify finding a pointer one past the last element in an array. Such a pointer is often called the 'end', and thus the macro name.Make it easy to find more places where that macro should be used.
See also:
436debc9cad8("array_size.h: addARRAY_END()")8118f197b7b7("mm: fix benign off-by-one bugs")a9e5620c9a9e("kernel: fix off-by-one benign bugs")61e9210e2392("mm: useARRAY_END()instead of open-coding it")Cc Kees Cook <[email protected]>Cc Markus Elfring <[email protected]>Cc Julia Lawall <[email protected]>Cc Nicolas Palix <[email protected]>Signed-off-by Alejandro Colomar <[email protected]>---
Hi!
This v3 only has one change: I've removed the comment about the false negatives. They were due to spatch(1) not being able to correctly parse unrelated code elsewhere.
See range-diff and interdiff at the bottom.
Have a lovely night!
Alexscripts/coccinelle/misc/array_end.cocci | 73 +++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 scripts/coccinelle/misc/array_end.cocciscripts/coccinelle/misc/array_end.cocci new file +73
-0@@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// Use ARRAY_END instead of an expression derived from ARRAY_SIZE +// +// Confidence: High +// Copyright: 2026, Alejandro Colomar <[email protected]> +// Options: --no-includes --include-headers + +virtual patch +virtual context +virtual org +virtual report + +@depends on context@ +type T; +T[] a; +expression b; +@@ +( +* (a + ARRAY_SIZE(a)) +| +* (&a[0] + ARRAY_SIZE(a)) +| +* (&a[ARRAY_SIZE(a)]) +| +* (&a[ARRAY_SIZE(a) - b]) +) + +@depends on patch@ +type T; +T[] a; +expression b; +@@ +( +- (a + ARRAY_SIZE(a)) ++ ARRAY_END(a) +| +- (&a[0] + ARRAY_SIZE(a)) ++ ARRAY_END(a) +| +- (&a[ARRAY_SIZE(a)]) ++ ARRAY_END(a) +| +- (&a[ARRAY_SIZE(a) - b]) ++ ARRAY_END(a) - b +) + +@r depends on org || report@ +type T; +T[] a; +expression b; +position p; +@@ +( + (a@p + ARRAY_SIZE(a)) +| + (&a[0]@p + ARRAY_SIZE(a)) +| + (&a[ARRAY_SIZE(a)]@p) +| + (&a[ARRAY_SIZE(a)@p - b]) +) + +@script:python depends on org@ +p << r.p; +@@ + +coccilib.org.print_todo(p[0], "WARNING should use ARRAY_END") + +@script:python depends on report@ +p << r.p; +@@ + +coccilib.report.print_report(p[0], "WARNING: opportunity for ARRAY_END")Range-diff:
1:9fd8d3d1! 1:2ae22f8bscripts/coccinelle: Add script for usingARRAY_END()
@@scripts/coccinelle/misc/array_end.cocci(new)
+//
+// Confidence: High
+// Copyright: 2026, Alejandro Colomar <[email protected]>
-+// Comments: No known false positives, but has a few false negatives
+// Options: --no-includes --include-headers
+
+virtual patchSignature · 1 line
2.53.0
Signature · 1 line
<https://www.alejandro-colomar.es>
PATCH v3 1/1 scripts/coccinelle: Add script for using ARRAY_END()
In reply to Alejandro ColomarRecently, we added an ARRAY_END() macro to simplify finding a pointer one past the last element in an array. Such a pointer is often called the 'end', and thus the macro name.
Make it easy to find more places where that macro should be used.
See also:436debc9cad8 ("array_size.h: add ARRAY_END()") 8118f197b7b7 ("mm: fix benign off-by-one bugs") a9e5620c9a9e ("kernel: fix off-by-one benign bugs") 61e9210e2392 ("mm: use ARRAY_END() instead of open-coding it")
---
Hi Julia,
Resent the patch now, as you asked me to do.
Cheers,
Alex
Here's the original message that came with the patch:
Hi!
This v3 only has one change: I've removed the comment about the false negatives. They were due to spatch(1) not being able to correctly parse unrelated code elsewhere.
See range-diff and interdiff at the bottom.
Have a lovely night!
Alex
scripts/coccinelle/misc/array_end.cocci | 73 +++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 scripts/coccinelle/misc/array_end.cocci
scripts/coccinelle/misc/array_end.cocci new file +73 -0
@@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// Use ARRAY_END instead of an expression derived from ARRAY_SIZE +// +// Confidence: High +// Copyright: 2026, Alejandro Colomar <[email protected]> +// Options: --no-includes --include-headers + +virtual patch +virtual context +virtual org +virtual report + +@depends on context@ +type T; +T[] a; +expression b; +@@ +( +* (a + ARRAY_SIZE(a)) +| +* (&a[0] + ARRAY_SIZE(a)) +| +* (&a[ARRAY_SIZE(a)]) +| +* (&a[ARRAY_SIZE(a) - b]) +) + +@depends on patch@ +type T; +T[] a; +expression b; +@@ +( +- (a + ARRAY_SIZE(a)) ++ ARRAY_END(a) +| +- (&a[0] + ARRAY_SIZE(a)) ++ ARRAY_END(a) +| +- (&a[ARRAY_SIZE(a)]) ++ ARRAY_END(a) +| +- (&a[ARRAY_SIZE(a) - b]) ++ ARRAY_END(a) - b +) + +@r depends on org || report@ +type T; +T[] a; +expression b; +position p; +@@ +( + (a@p + ARRAY_SIZE(a)) +| + (&a[0]@p + ARRAY_SIZE(a)) +| + (&a[ARRAY_SIZE(a)]@p) +| + (&a[ARRAY_SIZE(a)@p - b]) +) + +@script:python depends on org@ +p << r.p; +@@ + +coccilib.org.print_todo(p[0], "WARNING should use ARRAY_END") + +@script:python depends on report@ +p << r.p; +@@ + +coccilib.report.print_report(p[0], "WARNING: opportunity for ARRAY_END")
Range-diff:
1: 9fd8d3d1 ! 1: 2ae22f8b scripts/coccinelle: Add script for using ARRAY_END()
@@ scripts/coccinelle/misc/array_end.cocci (new)
+//
+// Confidence: High
+// Copyright: 2026, Alejandro Colomar <[email protected]>
-+// Comments: No known false positives, but has a few false negatives
+// Options: --no-includes --include-headers
+
+virtual patch
Signature · 7 lines
2.53.0 ----- End forwarded message ----- -- <https://www.alejandro-colomar.es>
Quoted 17 lines · Alejandro Colomar
Recently, we added an
ARRAY_END()macro to simplify finding a pointer one past the last element in an array. Such a pointer is often called the 'end', and thus the macro name.Make it easy to find more places where that macro should be used.
See also:
436debc9cad8("array_size.h: addARRAY_END()")8118f197b7b7("mm: fix benign off-by-one bugs")a9e5620c9a9e("kernel: fix off-by-one benign bugs")61e9210e2392("mm: useARRAY_END()instead of open-coding it")Cc Kees Cook <[email protected]>Cc Markus Elfring <[email protected]>Cc Julia Lawall <[email protected]>Cc Nicolas Palix <[email protected]>Signed-off-by Alejandro Colomar <[email protected]>
Quoted 6 lines
---
Hi Julia,
Resent the patch now, as you asked me to do.
Applied, thanks.
Afterwards, I made two changes:
* Add disable zero_multiple_format to each rule to avoid considering the possibility that an array index is expressed using '\0'
* Omit outer parentheses on context and org/report rules that only match ubt don't transform, since matching a subterm gives the same result whether or not the parentheses are present.
julia
Quoted 122 lines
Cheers,
AlexHere's the original message that came with the patch:
Hi!
This v3 only has one change: I've removed the comment about the false negatives. They were due to spatch(1) not being able to correctly parse unrelated code elsewhere.
See range-diff and interdiff at the bottom.
Have a lovely night!
Alexscripts/coccinelle/misc/array_end.cocci | 73 +++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 scripts/coccinelle/misc/array_end.cocciscripts/coccinelle/misc/array_end.cocci new file +73
-0@@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// Use ARRAY_END instead of an expression derived from ARRAY_SIZE +// +// Confidence: High +// Copyright: 2026, Alejandro Colomar <[email protected]> +// Options: --no-includes --include-headers + +virtual patch +virtual context +virtual org +virtual report + +@depends on context@ +type T; +T[] a; +expression b; +@@ +( +* (a + ARRAY_SIZE(a)) +| +* (&a[0] + ARRAY_SIZE(a)) +| +* (&a[ARRAY_SIZE(a)]) +| +* (&a[ARRAY_SIZE(a) - b]) +) + +@depends on patch@ +type T; +T[] a; +expression b; +@@ +( +- (a + ARRAY_SIZE(a)) ++ ARRAY_END(a) +| +- (&a[0] + ARRAY_SIZE(a)) ++ ARRAY_END(a) +| +- (&a[ARRAY_SIZE(a)]) ++ ARRAY_END(a) +| +- (&a[ARRAY_SIZE(a) - b]) ++ ARRAY_END(a) - b +) + +@r depends on org || report@ +type T; +T[] a; +expression b; +position p; +@@ +( + (a@p + ARRAY_SIZE(a)) +| + (&a[0]@p + ARRAY_SIZE(a)) +| + (&a[ARRAY_SIZE(a)]@p) +| + (&a[ARRAY_SIZE(a)@p - b]) +) + +@script:python depends on org@ +p << r.p; +@@ + +coccilib.org.print_todo(p[0], "WARNING should use ARRAY_END") + +@script:python depends on report@ +p << r.p; +@@ + +coccilib.report.print_report(p[0], "WARNING: opportunity for ARRAY_END")Range-diff:
1:9fd8d3d1! 1:2ae22f8bscripts/coccinelle: Add script for usingARRAY_END()
@@scripts/coccinelle/misc/array_end.cocci(new)
+//
+// Confidence: High
+// Copyright: 2026, Alejandro Colomar <[email protected]>
-+// Comments: No known false positives, but has a few false negatives
+// Options: --no-includes --include-headers
+
+virtual patch
--
2.53.0----- End forwarded message -----
Hi Julia,
Quoted 33 lines
Date: 2026-09-27 11:21:54+0200
From: Julia Lawall <[email protected]>Quoted 17 lines · Alejandro Colomar
Recently, we added an
ARRAY_END()macro to simplify finding a pointer one past the last element in an array. Such a pointer is often called the 'end', and thus the macro name.Make it easy to find more places where that macro should be used.
See also:
436debc9cad8("array_size.h: addARRAY_END()")8118f197b7b7("mm: fix benign off-by-one bugs")a9e5620c9a9e("kernel: fix off-by-one benign bugs")61e9210e2392("mm: useARRAY_END()instead of open-coding it")Cc Kees Cook <[email protected]>Cc Markus Elfring <[email protected]>Cc Julia Lawall <[email protected]>Cc Nicolas Palix <[email protected]>Signed-off-by Alejandro Colomar <[email protected]>Quoted 6 lines
---
Hi Julia,
Resent the patch now, as you asked me to do.
Applied, thanks.
Quoted 8 lines
Afterwards, I made two changes:
* Add disable
zero_multiple_formatto each rule to avoid considering the possibility that an array index is expressed using '\0'* Omit outer parentheses on context and org/report rules that only match ubt don't transform, since matching a subterm gives the same result whether or not the parentheses are present.
Thanks!!
I'll look at the patch to see how it changed, out of curiosity. :)
Have a lovely day!
Alex
Quoted 126 lines
julia
Quoted 122 lines
Cheers,
AlexHere's the original message that came with the patch:
Hi!
This v3 only has one change: I've removed the comment about the false negatives. They were due to spatch(1) not being able to correctly parse unrelated code elsewhere.
See range-diff and interdiff at the bottom.
Have a lovely night!
Alexscripts/coccinelle/misc/array_end.cocci | 73 +++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 scripts/coccinelle/misc/array_end.cocciscripts/coccinelle/misc/array_end.cocci new file +73
-0@@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// Use ARRAY_END instead of an expression derived from ARRAY_SIZE +// +// Confidence: High +// Copyright: 2026, Alejandro Colomar <[email protected]> +// Options: --no-includes --include-headers + +virtual patch +virtual context +virtual org +virtual report + +@depends on context@ +type T; +T[] a; +expression b; +@@ +( +* (a + ARRAY_SIZE(a)) +| +* (&a[0] + ARRAY_SIZE(a)) +| +* (&a[ARRAY_SIZE(a)]) +| +* (&a[ARRAY_SIZE(a) - b]) +) + +@depends on patch@ +type T; +T[] a; +expression b; +@@ +( +- (a + ARRAY_SIZE(a)) ++ ARRAY_END(a) +| +- (&a[0] + ARRAY_SIZE(a)) ++ ARRAY_END(a) +| +- (&a[ARRAY_SIZE(a)]) ++ ARRAY_END(a) +| +- (&a[ARRAY_SIZE(a) - b]) ++ ARRAY_END(a) - b +) + +@r depends on org || report@ +type T; +T[] a; +expression b; +position p; +@@ +( + (a@p + ARRAY_SIZE(a)) +| + (&a[0]@p + ARRAY_SIZE(a)) +| + (&a[ARRAY_SIZE(a)]@p) +| + (&a[ARRAY_SIZE(a)@p - b]) +) + +@script:python depends on org@ +p << r.p; +@@ + +coccilib.org.print_todo(p[0], "WARNING should use ARRAY_END") + +@script:python depends on report@ +p << r.p; +@@ + +coccilib.report.print_report(p[0], "WARNING: opportunity for ARRAY_END")Range-diff:
1:9fd8d3d1! 1:2ae22f8bscripts/coccinelle: Add script for usingARRAY_END()
@@scripts/coccinelle/misc/array_end.cocci(new)
+//
+// Confidence: High
+// Copyright: 2026, Alejandro Colomar <[email protected]>
-+// Comments: No known false positives, but has a few false negatives
+// Options: --no-includes --include-headers
+
+virtual patch
--
2.53.0----- End forwarded message -----
Signature · 1 line
<https://www.alejandro-colomar.es>