Post by Jérémy LalPost by Arnd BergmannCan you debug into this file on i386 to see which symbol
it picks up in the end, and whether off_t is defined
as a 32-bit or 64-bit type?
After patch, preadv64.
In both cases,
(gdb) whatis off
type = off_t
(gdb) whatis off_t
type = __off64_t
Post by Arnd BergmannIt's possible that for some reason the testcase fails
to report a bug on i386 despite the code being wrong
either before or after your patch.
Ok, good, so most likely your new version just works and
it was broken on all 32-bit targets including i386 before
your patch. That leaves the question why the testcase
didn't catch that bug on i386.
What I think is going on here is that i386 calling
conventions for 64-bit function arguments happen to
make it work correctly, as they are passed on the stack
as five 32-bit words in preadv64()
<fd> <iov> <iovcnt> <off_low> <off_high>
and preadv() takes exactly the same four arguments
but ignores the last one.
On ARM EABI, the arguments are passed in six registers
instead, with the 64-bit argument in an aligned pair
of registers
<fd> <iov> <iovcnt> <_PAD_> <off_low> <off_high>
which in turn means that calling preadv() by accident
with the preadv64 arguments puts uninitialized stack
data into the 32-bit offset argument slow. The same thing
happens on mips, powerpc, xtensa, arc, nios2, openrisc
sh and riscv. On top of this, big-endian architectures
also typically flip the low and high word for the
64-bit argument, so you pass the wrong word on m68k,
parisc, s390, sparc and openrisc despite those not
inserting the padding argument.
To catch these bugs better, I think a testcase could
be added that passes and argument that has valid
32-bit offset, but garbage in the high bits, e.g.
0xffffffff00000008. On correctly working targets this
should return errno=ENXIO, while on broken i386
systems it would succeed reading from file offset 8.
Arnd