compiling the following code with -O2, the program will core dump. I check the assembly code output, it seems the 'strlen' function call is replaced by the 'builtin strlen' funciton and will read the first four byte on a invalid memory page. And if i replace the mmap with malloc and run under the Valgrind[3.5.0],the Valgrind also reports 'Invalid read of size 4'. Ps:How to workaround this piece of code???I think there are two ways a.mmap 4 bytes or more to make sure the strlen will not read the invalid memory b.use the gcc option '-fno-builtin-strlen' to make sure the 'strlen' is not replaced. But I'm not sure is there a more elegant way to workaroud this?? ==================================================================== #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/mman.h> typedef struct _x_t { int offset; //'strlen' is replaced iff. this field exists. char data[0]; }x_t; int main() { //make a 4K memory page. char *buff=mmap(NULL,4096,PROT_WRITE | PROT_READ ,MAP_PRIVATE | MAP_ANONYMOUS,0,0); char *buffer = buff+4096-11; strcpy(buffer,"0123456789"); x_t *x=(x_t*)buffer; printf("%d\n",strlen(x->data)); //read a invalid page. munmap(buff,4096); return 0; }
You should make the struct packed, because otherwise you are accessing it unaligned.
(In reply to comment #1) > You should make the struct packed, because otherwise you are accessing it > unaligned. > I think the main problem coming from that GCC replace the 'strlen' function with the following code. .L2: movl (%ecx), %eax //$ecx is the beginning of string.. addl $4, %ecx //seems to access the content in 4 bytes each time. leal -16843009(%eax), %edx notl %eax andl %eax, %edx andl $-2139062144, %edx je .L2 But it seems the piece of code can only be used when the valid memory size is 4*N,otherwise it will make a 'Invalid read'... So under what sitaution, GCC will replace 'strlen' call with the above code.
(In reply to comment #1) > You should make the struct packed, because otherwise you are accessing it > unaligned. > If I recompile it with -O0, the assembly code call 'strlen' function.And I use Valgrind to run it,there is no 'Invalid read'
The compiler can assume that *x is correctly aligned, so this is not a bug.
(In reply to comment #1) > You should make the struct packed, because otherwise you are accessing it > unaligned. > 3ku for your reply.Your reply is much more useful than Axxx's reply.3ku very much:).
Just a littke more: alignof (struct _x_t) is 4 therefor so is the alignof(_x_t ::data).
(In reply to comment #6) > Just a littke more: alignof (struct _x_t) is 4 therefor so is the alignof(_x_t > ::data). > 3ku very much,with your explanation I think I can understand it..3ku very much.