gcc with FORTIFY_SOURCES think that code can be exploited by buffer overflow. But that not true. This piece of code is known as Flexible Array Members. It's extension in gcc and without FORTIFY_SOURCE is everything fine. You can try valgrind. No memory leak and even overwriting memory. Version: gcc version 4.4.0 20090623 (Red Hat 4.4.0-10) (GCC) Steps to Reproduce: 1. make new file with this code $ cat fam.c #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { int n; union { int d; char string[1]; }u; }fam_t; int main( void ) { char test_string[] = "Toto je testovaci string."; size_t size = 0; size = sizeof( fam_t ) + (strlen(test_string)-1)*sizeof(char); fam_t* fam = NULL; fam = (fam_t*)malloc(size); strcpy( fam->u.string, test_string ); fam->n = size; printf("%i\t%s\n", fam->n, fam->u.string); free(fam); return 0; } 2. compile $ gcc -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -o fam fam.c 3. run it Actual results: *** buffer overflow detected ***: ./fam terminated ======= Backtrace: ========= /lib64/libc.so.6(__fortify_fail+0x37)[0x3ffb4f7537] /lib64/libc.so.6[0x3ffb4f5590] ./fam[0x4006fa] /lib64/libc.so.6(__libc_start_main+0xfd)[0x3ffb41ea2d] ./fam[0x400579] ======= Memory map: ======== 00400000-00401000 r-xp 00000000 08:02 5959039 /home/npajkovs/src/flexible-array-members/fam 00600000-00601000 rw-p 00000000 08:02 5959039 /home/npajkovs/src/flexible-array-members/fam 01c79000-01c9a000 rw-p 00000000 00:00 0 [heap] 32f3000000-32f301a000 r-xp 00000000 08:01 3068191 /lib64/libgcc_s-4.4.0-20090623.so.1 32f301a000-32f3219000 ---p 0001a000 08:01 3068191 /lib64/libgcc_s-4.4.0-20090623.so.1 32f3219000-32f321a000 rw-p 00019000 08:01 3068191 /lib64/libgcc_s-4.4.0-20090623.so.1 3ffb000000-3ffb01f000 r-xp 00000000 08:01 3068302 /lib64/ld-2.10.1.so 3ffb21e000-3ffb21f000 r--p 0001e000 08:01 3068302 /lib64/ld-2.10.1.so 3ffb21f000-3ffb220000 rw-p 0001f000 08:01 3068302 /lib64/ld-2.10.1.so 3ffb400000-3ffb564000 r-xp 00000000 08:01 3068629 /lib64/libc-2.10.1.so 3ffb564000-3ffb764000 ---p 00164000 08:01 3068629 /lib64/libc-2.10.1.so 3ffb764000-3ffb768000 r--p 00164000 08:01 3068629 /lib64/libc-2.10.1.so 3ffb768000-3ffb769000 rw-p 00168000 08:01 3068629 /lib64/libc-2.10.1.so 3ffb769000-3ffb76e000 rw-p 00000000 00:00 0 7fb68e72c000-7fb68e72e000 rw-p 00000000 00:00 0 7fb68e74b000-7fb68e74d000 rw-p 00000000 00:00 0 7fff313ac000-7fff313c1000 rw-p 00000000 00:00 0 [stack] 7fff313ff000-7fff31400000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] Neúspěšně ukončen (SIGABRT) Expected results: print on stdout message: 59 This is a testing string for flexible array members.
gcc-4.4.0-15 and later in rawhide should allow this.
This is still failing for htmldoc. Here is a modified fam.c, with a structure that is failing in htmldoc (from ps-pdf.cxx): #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct render_str /**** Render entity structure ****/ { struct render_str *prev; /* Previous rendering entity */ struct render_str *next; /* Next rendering entity */ int type; /* Type of entity */ float x, /* Position in points */ y, /* ... */ width, /* Size in points */ height; /* ... */ union { struct { int typeface, /* Typeface for text */ style; /* Style of text */ float size; /* Size of text in points */ float spacing; /* Inter-character spacing */ float rgb[3]; /* Color of text */ unsigned char buffer[1]; /* String buffer */ } text; void *image; /* Image pointer */ float box[3]; /* Box color */ unsigned char link[1]; /* Link URL */ } data; } fam_t; int main( void ) { char test_string[] = "Toto je testovaci string."; size_t size = 0; size = sizeof( fam_t ) + (strlen(test_string)-1)*sizeof(char); fam_t* fam = NULL; fam = (fam_t*)malloc(size); strcpy( fam->data.text.buffer, test_string ); printf("%s\n", fam->data.text.buffer); free(fam); return 0; }
That's nested too much, sorry, this isn't going to work with -D_FORTIFY_SOURCE=2. Either build with -D_FORTIFY_SOURCE=1, or rearrange the struct.
Or use memcpy instead of strcpy.
Another bug/problem/nasty thing with flexible array member. It seems that code is work perfectly. Valgrind said there isn't any memory leaks. Give only echo if it will be fixed. Easy solution is use memcpy. #include <stdio.h> #include <stdlib.h> #include <string.h> typedef int *ClientData; typedef struct VarTrace { ClientData clientData; /* Argument to pass to proc. */ int flags; /* What events the trace procedure is * interested in: OR-ed combination of * TCL_TRACE_READS, TCL_TRACE_WRITES, * TCL_TRACE_UNSETS and TCL_TRACE_ARRAY. */ struct VarTrace *nextPtr; /* Next in list of traces associated with a * particular variable. */ } VarTrace; typedef struct { int flags; /* Operations for which Tcl command is to be * invoked. */ size_t length; /* Number of non-NUL chars. in command. */ char command[4]; /* Space for Tcl command to invoke. Actual * size will be as large as necessary to hold * command. This field must be the last in the * structure, so that it can be larger than 4 * bytes. */ } TraceVarInfo; typedef struct { VarTrace traceInfo; TraceVarInfo traceCmdInfo; } CombinedTraceVarInfo; int main( void ) { char test_string[] = "This is testing string for flexible member array"; CombinedTraceVarInfo* ctvi; size_t size = sizeof( CombinedTraceVarInfo) + strlen(test_string) +1 - sizeof( ctvi->traceCmdInfo.command); ctvi = malloc( size ); // strcpy( ctvi->traceCmdInfo.command, test_string ); memcpy(ctvi->traceCmdInfo.command, test_string, sizeof(test_string )); printf("%s\n", ctvi->traceCmdInfo.command); free(ctvi); return 0; }
That's definitely nothing close to the standard flexible array member definition. Fix up the code. Easy fix is to put what is meant to be a flexible array member as a flexible array member (i.e. as last, array, field into CombinedTraceVarInfo).