public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
* _FORTIFY_SOURCE has no effect for C++ due to usage of #define
@ 2018-03-06 13:39 Christian Franke
  0 siblings, 0 replies; only message in thread
From: Christian Franke @ 2018-03-06 13:39 UTC (permalink / raw)
  To: cygwin

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

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2018-03-06 12:05 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-06 13:39 _FORTIFY_SOURCE has no effect for C++ due to usage of #define Christian Franke

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).