Here is an example of the code I wrote.
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <sys/mman.h> int main() { int fd; long pagesize; char *data; if ((fd = open("foo.txt", O_RDONLY)) == -1) { perror("open"); return 1; } pagesize = sysconf(_SC_PAGESIZE); printf("pagesize: %ld\n", pagesize); data = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, fd, 0); printf("data: %p\n", data); if (data == (void *) -1) { perror("mmap"); return 1; } printf("%d\n", data[0]); printf("%d\n", data[1]); printf("%d\n", data[2]); printf("%d\n", data[4096]); printf("%d\n", data[4097]); printf("%d\n", data[4098]); return 0; }
If I provide the zero byte of foo.txt for this program, it terminates with SIGBUS.
$ > foo.txt && gcc foo.c && ./a.out pagesize: 4096 data: 0x7f8d882ab000 Bus error
If I provided one byte of foo.txt for this program, then there is no such problem.
$ printf A > foo.txt && gcc foo.c && ./a.out pagesize: 4096 data: 0x7f5f3b679000 65 0 0 48 56 10
mmap (2) mentions the following.
Using the displayed area may result in the following signals:
SIGSEGV Attempt to write to the area displayed as read-only.
SIGBUS An attempt to access a part of the buffer that does not correspond to the file (for example, outside the file, including the case when another process cut the file).
So, if I understand this correctly, even the second test case (1-byte file) should have led to SIGBUS, because data[1] and data[2] are trying to access the part of the buffer ( data ) that does not correspond to the file .
Can you help me understand why only a file with a zero byte causes this program to crash using SIGBUS?