Cygport now sets _FORTIFY_SOURCE=2 for C and C++ but this has no effect
for C++. In <sys/features.h> __SSP_FORTIFY_LEVEL is always set to 0 if
__cplusplus is defined. This is needed because <ssp/string.h> ... use
#defines to replace the functions.
Testcase:
$ cat copy.c
#include <string.h>
char sbuf[42], *dbuf;
void to_sbuf(const char *p)
{
strcpy(sbuf, p);
}
void to_dbuf(const char *p)
{
strcpy(dbuf, p);
}
Examine preprocessed code:
$ gcc -D_FORTIFY_SOURCE=2 -O2 -E copy.c > copy2.c
$ vim copy2.c # Remove unnecessary code && pretty-print
$ cat copy2.c
typedef unsigned int size_t;
char *__strcpy_chk(char *, const char *, size_t);
extern __inline__ __attribute__((__always_inline__, __gnu_inline__)) char *
__strcpy_ichk(char * restrict dst, const char * restrict src)
{
return __builtin___strcpy_chk(dst, src, __builtin_object_size(dst, 0));
}
char sbuf[42], *dbuf;
void to_sbuf(const char *p)
{
((__builtin_object_size(sbuf, 0) != (size_t)-1)
? __builtin___strcpy_chk(sbuf, p, __builtin_object_size(sbuf, 0))
: __strcpy_ichk(sbuf, p));
}
void to_dbuf(const char *p)
{
((__builtin_object_size(dbuf, 0) != (size_t)-1)
? __builtin___strcpy_chk(dbuf, p, __builtin_object_size(dbuf, 0))
: __strcpy_ichk(dbuf, p));
}
Why are these (a ? b : c) expanded from the "#define strcpy" needed?
Both branches lead to the same __builtin___strcpy_chk() call. Is this
possibly needed for (very) old compiler versions with weaker optimization?
According to "gcc -O2 -S" outputs, the generated code is identical for
this source:
$ cat copy3.c
typedef unsigned int size_t;
char *strcpy (char *restrict, const char *restrict);
char *__strcpy_chk(char *, const char *, size_t);
char sbuf[42], *dbuf;
void to_sbuf(const char *p)
{
__strcpy_chk(sbuf, p, 42);
}
void to_dbuf(const char *p)
{
strcpy(dbuf, p);
}
The same code is generated if strcpy() is replaced itself without a
"#define strcpy":
$ cat copy4.c
typedef unsigned int size_t;
char *strcpy (char *restrict, const char *restrict);
// #if __SSP_FORTIFY_LEVEL > 0
extern __inline__ __attribute__((__always_inline__, __gnu_inline__)) char *
strcpy(char * restrict dst, const char * restrict src)
{
return __builtin___strcpy_chk(dst, src, __builtin_object_size(dst, 0));
}
// #endif
char sbuf[42], *dbuf;
void to_sbuf(const char *p)
{
strcpy(sbuf, p); // changed to __strcpy_chk(sbuf, p, 42);
}
void to_dbuf(const char *p)
{
strcpy(dbuf, p); // unchanged
}
This variant would be also compatible with C++. Same results with CLang(++).
Christian
PS: There is an outdated "#define __restrict" section in <sys/cdefs.h>
which checks for GCC version 2.95 only.
--
Problem reports: http://cygwin.com/problems.html
FAQ: http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple