Re: [PATCH v2] scripts/coccinelle: Add script for using ARRAY_END()

Alejandro Colomar <[email protected]>
Newsgroups org.kernel.vger.kernel-janitors,fr.inria.cocci,org.kernel.vger.linux-kernel
Message-ID <abblv3nCut5aRk7q@devuan>
Hi Markus, Julia,

On 2026-03-09T15:32:24+0100, Alejandro Colomar wrote:
> > …
> > > +// 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.

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

-- 
<https://www.alejandro-colomar.es>
signature.asc (application/pgp-signature, 833 B)
-----BEGIN PGP SIGNATURE-----

iQIzBAABCgAdFiEES7Jt9u9GbmlWADAi64mZXMKQwqkFAmm26b8ACgkQ64mZXMKQ
wql5PBAAkykb7HqRWjEK8ldPEC6BUK0vqJdoGQjVyl6eyr9+jo1EsS2nkohZdYdn
h5kgD8XM/YmrnODA0tALE40J2COginmkNCjRaKSk/+nqOvow+Ztb0ziW7ia8yN9C
7djLetk613JM8rjGOVU3D7WcpiGpo4UWq00eqcgJlaCqLQP57vyBhtXfYS9MIUrG
b3X6sTw5sqYGYrw0o0zsRyu4KuctvGs8jkyAxcE+UK62qZNe4v87IWe8q2vbIq2f
+25sCZwrnvsb4zXNbR86oIFtaIObkT1f3yB84hJv2QLHR7L6XkaL/gvcaBmgdhfz
cVlfORcvHwpyDoXBDMbeFPmUiMA4p7XNxRaWxeB7KDb6iP4614H1lnWKAgPbHv+7
NrRPRLBjLbCUM3lXlyQw/FY+6XssjHE8mZ5ivFPy/iH7ZTpPZ/eMpp7t6XJNvzXb
yWbkMrLJumdtwIknCPeU5OANMzmuMxPh5NacULzTuBfzhKeVp+pQXyfjrqGaRILt
cF9I8nqH8FtAd0EiKZ/iCqzcgFt331ZthXrzy0e7HAMkLUNB8Orel8aU0F0w2J9o
3bFrN7tNR+AWf0HFpR3I5u8CGkAkIb/8PhUSVT5dDrMa2Q6FJUoW2cO8JfIzdJhk
yGBDeaHZzSaDSb6oKXLp3943XNwQdicd1Y91ak99LeXBBrGUwoY=
=C+Zu
-----END PGP SIGNATURE-----
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.