On Tue, 20 Oct 2026 08:49:44 +0000
Morten Brørup <[email protected]> wrote:
> On architectures where rte_memcpy() is defined as memcpy(),
> GCC warns about source/destination overflow when copying more than the
> source/destination size, even for code paths that are not taken in cases
> where the sizes are smaller.
>
> The relevant compiler warnings were disabled for GCC at the two
> occurrences, and comments describing the reason were added.
>
> NB:
> It has not been investigated which GCC versions are affected.
> GCC version 10 and up was chosen because that was what the previous
> versions of x86 rte_memcpy() disabled sligthly similar warnings for.
>
> PS:
> The alternative was to obfuscate the code, but that would make the code
> less readable, and might have unintended effects on architectures and
> compilers not suffering by this issue.
>
> Bugzilla ID: 2061
> Fixes: ee0822a0ef41 ("stack: introduce pile")
>
> The pile was introduce with this DPDK release, so no need to backport.
>
> Reported-by: Ali Alnubani <[email protected]>
> Signed-off-by: Morten Brørup <[email protected]>
> ---
I don't like using compiler pragmas for this. It also means that if
compiler gets fixed or behaves differently you will never see it.
AI analysis shows some other options.
Root cause is --buildtype=debug, i.e. -O0, not the GCC version. At -O0 nothing
removes the dead n_bulk > 0 path for rte_stack_push(s, &obj, 1), so the
constant 256-byte memcpy is checked against obj (8 bytes) and warns. Reproduced
with GCC 13.3 and 14.2 at -O0; silent at -Og and above. That means the
GCC_VERSION >= 100000 gate is wrong at both ends: any GCC with the warning
fires (overflow since 8, overread since 11), and on GCC 10 the
-Wstringop-overread pragma itself is a -Wpragmas error under -Werror. If the
pragma stays, drop the version gate (keep RTE_TOOLCHAIN_GCC) and fix the
comment: GCC does not “know” the path is dead, that is the whole problem.
This should have a big ass comment, and it should use same pragma set as
existing one in lib/ring.
Other alternative is to use bulk object array as structure and do assignment.
But that replaces ugly pragmas with ugly casts...
--- a/lib/stack/rte_stack_pile.h
+++ b/lib/stack/rte_stack_pile.h
@@
+/* Bulk object array as a single object, so a copy is one assignment. */
+struct rte_stack_pile_bulk_objs {
+ void *objs[RTE_STACK_PILE_BULK_SIZE];
+};
+
@@ __rte_stack_pile_bulk_pop_elems
for (unsigned int i = 0; i < num; i++, tmp = tmp->next)
- rte_memcpy(&obj_table[i * RTE_STACK_PILE_BULK_SIZE],
- ((struct rte_stack_pile_bulk_elem
*)tmp)->objs,
- sizeof(void *) *
RTE_STACK_PILE_BULK_SIZE);
+ *(struct rte_stack_pile_bulk_objs *)&obj_table[i *
RTE_STACK_PILE_BULK_SIZE] =
+ *(struct rte_stack_pile_bulk_objs *)((struct
rte_stack_pile_bulk_elem *)tmp)->objs;
@@ __rte_stack_pile_push
for (i = 0; i < n_bulk; i++, tmp = tmp->next)
- rte_memcpy(((struct rte_stack_pile_bulk_elem *)tmp)->objs,
- &obj_table[(n_bulk - i - 1) *
RTE_STACK_PILE_BULK_SIZE],
- sizeof(void *) * RTE_STACK_PILE_BULK_SIZE);
+ *(struct rte_stack_pile_bulk_objs *)((struct
rte_stack_pile_bulk_elem *)tmp)->objs =
+ *(const struct rte_stack_pile_bulk_objs
*)&obj_table[(n_bulk - i - 1) * RTE_STACK_PILE_BULK_SIZE];