Open lygstate opened 3 years ago
Returning an int64_t just transfers responsibility for the problem to the caller, because the return value is stored in a int32_t inside struct kevent
.
The return value of this function is stored in an intptr_t
, which is a signed long
. By default, off_t
is also a signed long
, but it can also be a long long
if the program is compiled with -D_FILE_OFFSET_BITS=64
. This is one way that it could overflow.
There's also a race between the calls to lseek()
and stat()
. If the file was truncated (or shrank) in between these two system calls, the value returned by lseek()
could be greater than sb.st_size
, which would result in a negative value being returned by the function. It would probably be better to return sb.st_size
in this case.
I think there's some benefit in sanity checking the return value a bit more, to ensure that the value isn't negative and isn't greater than the size of the file. Interestingly, I see the following clang-tidy warning:
Clang-Tidy: Narrowing conversion from 'uintptr_t' (aka 'unsigned long') to signed type 'int' is implementation-defined
I'm not sure where clang-tidy is getting uintptr_t
from..
Looking through the man pages the value returned by lseek
can be greater than the file size under normal conditions as well, as you're allowed to write past the current end of the file.
The lseek() function allows the file offset to be set beyond the end of the existing end-
of-file of the file. If data is later written at this point, subsequent reads of the data
in the gap return bytes of zeros (until data is actually written into the gap).
https://github.com/mheily/libkqueue/blob/c54b3091d41d0a90a93ef7a0124e8892500c27a6/src/linux/read.c#L53