ARRAY_END() returns a pointer one past the end of the last element in the array argument. This pointer is useful for iterating over the elements of an array: for (T *p = a, p < ARRAY_END(a); p++) ... Cc: Kees Cook Cc: Christopher Bazley Cc: Rasmus Villemoes Cc: Marco Elver Cc: Michal Hocko Cc: Linus Torvalds Cc: Al Viro Cc: "Maciej W. Rozycki" Signed-off-by: Alejandro Colomar Message-ID: <37b1088dbd01a21d2f9d460aa510726119b3bcb0.1752193588.git.alx@kernel.org> --- drivers/block/floppy.c | 2 -- include/linux/array_size.h | 6 ++++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 5336c3c5ca36..69661840397e 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4802,8 +4802,6 @@ static void floppy_release_allocated_regions(int fdc, const struct io_region *p) } } -#define ARRAY_END(X) (&((X)[ARRAY_SIZE(X)])) - static int floppy_request_regions(int fdc) { const struct io_region *p; diff --git a/include/linux/array_size.h b/include/linux/array_size.h index 06d7d83196ca..0c4fec98822e 100644 --- a/include/linux/array_size.h +++ b/include/linux/array_size.h @@ -10,4 +10,10 @@ */ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) +/** + * ARRAY_END - get a pointer to one past the last element in array @arr + * @arr: array + */ +#define ARRAY_END(arr) (&(arr)[ARRAY_SIZE(arr)]) + #endif /* _LINUX_ARRAY_SIZE_H */ -- 2.51.0 We were wasting a byte due to an off-by-one bug. s[c]nprintf() doesn't write more than $2 bytes including the null byte, so trying to pass 'size-1' there is wasting one byte. Acked-by: Marco Elver Cc: Kees Cook Cc: Christopher Bazley Cc: Alexander Potapenko Cc: Dmitry Vyukov Cc: Alexander Potapenko Cc: Jann Horn Cc: Andrew Morton Cc: Linus Torvalds Cc: Rasmus Villemoes Cc: Marco Elver Cc: Michal Hocko Cc: Al Viro Signed-off-by: Alejandro Colomar Message-ID: <515445ae064d4b8599899bf0d8b480dadd2ff843.1752182685.git.alx@kernel.org> --- mm/kfence/kfence_test.c | 4 ++-- mm/kmsan/kmsan_test.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mm/kfence/kfence_test.c b/mm/kfence/kfence_test.c index 00034e37bc9f..5725a367246d 100644 --- a/mm/kfence/kfence_test.c +++ b/mm/kfence/kfence_test.c @@ -110,7 +110,7 @@ static bool report_matches(const struct expect_report *r) /* Title */ cur = expect[0]; - end = &expect[0][sizeof(expect[0]) - 1]; + end = ARRAY_END(expect[0]); switch (r->type) { case KFENCE_ERROR_OOB: cur += scnprintf(cur, end - cur, "BUG: KFENCE: out-of-bounds %s", @@ -140,7 +140,7 @@ static bool report_matches(const struct expect_report *r) /* Access information */ cur = expect[1]; - end = &expect[1][sizeof(expect[1]) - 1]; + end = ARRAY_END(expect[1]); switch (r->type) { case KFENCE_ERROR_OOB: diff --git a/mm/kmsan/kmsan_test.c b/mm/kmsan/kmsan_test.c index 902ec48b1e3e..b5ad5dfb2c00 100644 --- a/mm/kmsan/kmsan_test.c +++ b/mm/kmsan/kmsan_test.c @@ -105,7 +105,7 @@ static bool report_matches(const struct expect_report *r) /* Title */ cur = expected_header; - end = &expected_header[sizeof(expected_header) - 1]; + end = ARRAY_END(expected_header); cur += scnprintf(cur, end - cur, "BUG: KMSAN: %s", r->error_type); -- 2.51.0 We were wasting a byte due to an off-by-one bug. s[c]nprintf() doesn't write more than $2 bytes including the null byte, so trying to pass 'size-1' there is wasting one byte. This is essentially the same as the previous commit, in a different file. Cc: Marco Elver Cc: Kees Cook Cc: Christopher Bazley Cc: Alexander Potapenko Cc: Dmitry Vyukov Cc: Alexander Potapenko Cc: Jann Horn Cc: Andrew Morton Cc: Linus Torvalds Cc: Rasmus Villemoes Cc: Marco Elver Cc: Michal Hocko Cc: Al Viro Signed-off-by: Alejandro Colomar --- kernel/kcsan/kcsan_test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/kcsan/kcsan_test.c b/kernel/kcsan/kcsan_test.c index 219d22857c98..8ef8167be745 100644 --- a/kernel/kcsan/kcsan_test.c +++ b/kernel/kcsan/kcsan_test.c @@ -176,7 +176,7 @@ static bool __report_matches(const struct expect_report *r) /* Title */ cur = expect[0]; - end = &expect[0][sizeof(expect[0]) - 1]; + end = ARRAY_END(expect[0]); cur += scnprintf(cur, end - cur, "BUG: KCSAN: %s in ", is_assert ? "assert: race" : "data-race"); if (r->access[1].fn) { @@ -200,7 +200,7 @@ static bool __report_matches(const struct expect_report *r) /* Access 1 */ cur = expect[1]; - end = &expect[1][sizeof(expect[1]) - 1]; + end = ARRAY_END(expect[1]); if (!r->access[1].fn) cur += scnprintf(cur, end - cur, "race at unknown origin, with "); -- 2.51.0 There aren't any bugs in this code; it's purely cosmetic. By using ARRAY_END(), we prevent future issues, in case the code is modified; it has less moving parts. Also, it should be more readable (and perhaps more importantly, greppable), as there are several ways of writing an expression that gets the end of an array, which are unified by this API name. Cc: Kees Cook Cc: Linus Torvalds Signed-off-by: Alejandro Colomar --- mm/kmemleak.c | 2 +- mm/memcontrol-v1.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mm/kmemleak.c b/mm/kmemleak.c index 1ac56ceb29b6..fe33f2edfe07 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -510,7 +510,7 @@ static void mem_pool_free(struct kmemleak_object *object) { unsigned long flags; - if (object < mem_pool || object >= mem_pool + ARRAY_SIZE(mem_pool)) { + if (object < mem_pool || object >= ARRAY_END(mem_pool)) { kmem_cache_free(object_cache, object); return; } diff --git a/mm/memcontrol-v1.c b/mm/memcontrol-v1.c index 6eed14bff742..b2f37bd939fa 100644 --- a/mm/memcontrol-v1.c +++ b/mm/memcontrol-v1.c @@ -1794,7 +1794,7 @@ static int memcg_numa_stat_show(struct seq_file *m, void *v) mem_cgroup_flush_stats(memcg); - for (stat = stats; stat < stats + ARRAY_SIZE(stats); stat++) { + for (stat = stats; stat < ARRAY_END(stats); stat++) { seq_printf(m, "%s=%lu", stat->name, mem_cgroup_nr_lru_pages(memcg, stat->lru_mask, false)); @@ -1805,7 +1805,7 @@ static int memcg_numa_stat_show(struct seq_file *m, void *v) seq_putc(m, '\n'); } - for (stat = stats; stat < stats + ARRAY_SIZE(stats); stat++) { + for (stat = stats; stat < ARRAY_END(stats); stat++) { seq_printf(m, "hierarchical_%s=%lu", stat->name, mem_cgroup_nr_lru_pages(memcg, stat->lru_mask, -- 2.51.0