On Wed, Oct 26, 2022 at 4:03 AM Paul Eggert via tz <tz@iana.org> wrote:
The core dump occurred because GCC translates this:
qsort(links, nlinks, sizeof *links, qsort_linkcmp);
as if it were this:
if (nlinks == 0) __builtin_trap(); qsort(links, nlinks, sizeof *links, qsort_linkcmp);
That is, if qsort's second argument is zero, the code generated by GCC doesn't call the qsort library function. Instead, it directly executes the ud2 instruction <https://www.felixcloutier.com/x86/ud>, which raises the invalid opcode exception. Presumably this is because the GCC maintainers are in the faction that says a null pointer cannot be used to pass a size-zero object to a library function. This is likely the same faction that says "char *p = NULL; return p + 0;" has undefined behavior.
It seems odd that GCC is testing the counter nlinks and not the pointer links. Passing a null pointer is invalid — §7.10.5, §7.10.5.2, §7.1.4 of the C standard (C99 or later) indicate that. But passing nlinks as zero should not cause any trouble according to C99 or later versions of the C standard, or according to POSIX. The C90 standard is silent on the issue of a zero count. However, I think that TZ code can sidestep the whole issue by using: if (nlinks > 1) qsort(links, nlinks, sizeof(*links), qsort_linkcmp); There's no need to sort arrays of size 0 or 1. This avoids any questions about whether a count of zero is valid as an argument to qsort(). -- Jonathan Leffler <jonathan.leffler@gmail.com> #include <disclaimer.h> Guardian of DBD::Informix - v2018.1031 - http://dbi.perl.org "Blessed are we who can laugh at ourselves, for we shall never cease to be amused."