You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@stdcxx.apache.org by Farid Zaripov <Fa...@epam.com> on 2007/06/12 19:36:25 UTC

MSVC8 CRT "Secure Template Overloads" feature and stdcxx

  The MSVC8 CRT have the following feature: all  functions, working with 
sting buffers
(i.e. strcpy, strcat, sprintf, ...) have the security-enhanced versions 
with suffix "_s"
(i.e. strcpy_s, strcat_s, sprintf_s, ...). And if #defined macro
_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1
then will be defined template overloads of the such functions, i.e.:

  template <size_t size>
  char *strcpy(char (&dest)[size], const char *src)
  {
     return strcpy_s(dest, size, src);
  }

  So that the following code:

  char szBuf[10];
  strcpy(szBuf, "test");

  will be replaced to:

  char szBuf[10];
  strcpy<10>(szBuf, "test");

  but the following code:

  char *szBuf = new char [10];
  strcpy(szBuf, "test");

  will be leaved as is.

  The full information on this topic here: 
http://msdn2.microsoft.com/en-us/library/ms175759(VS.80).aspx

  I've tried to compile the stdcxx library with defined 
_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1
and _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1, but the configure 
step has failed to
detect this functions because of the compiler cannot decide which 
function address is taken.

  Here the list of the that functions:

<cstdio>: gets sprintf tmpnam vsprintf
<cstdlib>: div mbstowcs wcstombs
<cstring>: strcat strcpy strncat strncpy
<cwchar>: mbsrtowcs swprintf vswprintf wcrtomb wcscat wcscpy wcsncat 
wcsncpy wcsrtombs

  The div(int, int) function failed to detect because of the presence 
the "extern C++" div(long, long) overload.

  I propose to make changes in headers.inc file to check this functions 
not by takig the address, but by call the functions.

  The proposed patch is attached, but I not sure about passing 0 as 
va_list argument while testing vsprintf() and vswprintf().
 
Farid.


Re: MSVC8 CRT "Secure Template Overloads" feature and stdcxx

Posted by Martin Sebor <se...@roguewave.com>.
Farid Zaripov wrote:
>> -----Original Message-----
>> From: Martin Sebor [mailto:sebor@roguewave.com] 
>> Sent: Wednesday, June 13, 2007 8:40 PM
>> To: stdcxx-dev@incubator.apache.org
>> Subject: Re: MSVC8 CRT "Secure Template Overloads" feature and stdcxx
>>
> 
> [...]
>> Btw., since you're working on these tests, a useful enhancement
>> (optimization) would be to test all the declarations in the 
>> whole header first and only test each function individually 
>> if the big test fails. Doing it this way would dramatically 
>> speed up the configuration process. The trick would be to 
>> keep the list of the functions in the big test in sync with 
>> the list used for the individual little tests. One way to 
>> deal with it would be to generate the big test from the 
>> individual list as the first step and fall back on the 
>> current mechanism.
>>
> 
>   I have created JIRA issue on that:
> http://issues.apache.org/jira/browse/STDCXX-451

Thanks, that'll help us remember to get back to it after the
release when we have some spare cycles to work on enhancements.

Martin

> 
> Farid.


RE: MSVC8 CRT "Secure Template Overloads" feature and stdcxx

Posted by Farid Zaripov <Fa...@epam.com>.
> -----Original Message-----
> From: Martin Sebor [mailto:sebor@roguewave.com] 
> Sent: Wednesday, June 13, 2007 8:40 PM
> To: stdcxx-dev@incubator.apache.org
> Subject: Re: MSVC8 CRT "Secure Template Overloads" feature and stdcxx
> 

[...]
> Btw., since you're working on these tests, a useful enhancement
> (optimization) would be to test all the declarations in the 
> whole header first and only test each function individually 
> if the big test fails. Doing it this way would dramatically 
> speed up the configuration process. The trick would be to 
> keep the list of the functions in the big test in sync with 
> the list used for the individual little tests. One way to 
> deal with it would be to generate the big test from the 
> individual list as the first step and fall back on the 
> current mechanism.
> 

  I have created JIRA issue on that:
http://issues.apache.org/jira/browse/STDCXX-451

Farid.

RE: MSVC8 CRT "Secure Template Overloads" feature and stdcxx

Posted by Farid Zaripov <Fa...@epam.com>.
> -----Original Message-----
> From: Martin Sebor [mailto:sebor@roguewave.com] 
> Sent: Monday, July 02, 2007 10:50 PM
> To: stdcxx-dev@incubator.apache.org
> Subject: Re: MSVC8 CRT "Secure Template Overloads" feature and stdcxx
> 
> >>   On gcc 3.4.4/Cygwin the va_list type is not defined in stdio.h.
> > 
> > Right. The C standard requires that <stdarg.h> be #included before 
> > calling vsnprintf(). To do what you want you'd need to find a way 
> > (ideally a general mechanism) to also #include <stdarg.h> in these 
> > tests.
> 
> So what's the status of this improvement? I didn't mean to 
> shoot it down completely, just point out the problem with it 
> on other platforms. Since this is an MSVC-specific feature it 
> wouldn't be completely inappropriate to devise an 
> MSVC-specific solution for it.

  We can extend headers.inc with additional data on headers and types,
i.e.:

# list of headers
hdrs="assert ctype errno float iso646 limits locale math setjmp signal
\
      stdarg stddef stdio stdlib string time wchar wctype new typeinfo"
hdrs="$hdrs ieeefp.h pthread.h"

# list of types in header
stdarg_h="va_list"
stddef_h="size_t ptrdiff_t"

  And then search and #include header which define the type, used in
function call.

Farid.

Re: MSVC8 CRT "Secure Template Overloads" feature and stdcxx

Posted by Martin Sebor <se...@roguewave.com>.
Martin Sebor wrote:
> Farid Zaripov wrote:
>>> -----Original Message-----
>>> From: Martin Sebor [mailto:sebor@roguewave.com] Sent: Wednesday, June 
>>> 13, 2007 6:24 PM
>>> To: stdcxx-dev@incubator.apache.org
>>> Subject: Re: MSVC8 CRT "Secure Template Overloads" feature and stdcxx
>>>
>>>>   Since va_list can be anything, we need to pass va_list type in 
>>>> function call.
>>>> We can add function template <class T> get_t () { T t; 
>>> return t; } to
>>>> the libc_decl.sh and use the followinf declaration: 
>>>> vsprintf((char*)0,0,get_t<va_list>())
>>>> in headers.inc.
>>> Wouldn't vsprintf((char*)0,0,va_list()) work?
>>
>>   I think this should work.
>>
>>> My concern here is with the va_list name: Is it required to be 
>>> declared in the same header as the functions that use it?
>>
>>   On gcc 3.4.4/Cygwin the va_list type is not defined in stdio.h.
> 
> Right. The C standard requires that <stdarg.h> be #included
> before calling vsnprintf(). To do what you want you'd need
> to find a way (ideally a general mechanism) to also #include
> <stdarg.h> in these tests.

So what's the status of this improvement? I didn't mean to shoot
it down completely, just point out the problem with it on other
platforms. Since this is an MSVC-specific feature it wouldn't be
completely inappropriate to devise an MSVC-specific solution for
it.

Martin

Re: MSVC8 CRT "Secure Template Overloads" feature and stdcxx

Posted by Martin Sebor <se...@roguewave.com>.
Farid Zaripov wrote:
>> -----Original Message-----
>> From: Martin Sebor [mailto:sebor@roguewave.com] 
>> Sent: Wednesday, June 13, 2007 6:24 PM
>> To: stdcxx-dev@incubator.apache.org
>> Subject: Re: MSVC8 CRT "Secure Template Overloads" feature and stdcxx
>>
>>>   Since va_list can be anything, we need to pass va_list type in 
>>> function call.
>>> We can add function template <class T> get_t () { T t; 
>> return t; } to 
>>> the libc_decl.sh and use the followinf declaration: 
>>> vsprintf((char*)0,0,get_t<va_list>())
>>> in headers.inc.
>> Wouldn't vsprintf((char*)0,0,va_list()) work?
> 
>   I think this should work.
> 
>> My concern here 
>> is with the va_list name: Is it required to be declared in 
>> the same header as the functions that use it?
> 
>   On gcc 3.4.4/Cygwin the va_list type is not defined in stdio.h.

Right. The C standard requires that <stdarg.h> be #included
before calling vsnprintf(). To do what you want you'd need
to find a way (ideally a general mechanism) to also #include
<stdarg.h> in these tests.

Btw., since you're working on these tests, a useful enhancement
(optimization) would be to test all the declarations in the whole
header first and only test each function individually if the big
test fails. Doing it this way would dramatically speed up the
configuration process. The trick would be to keep the list of
the functions in the big test in sync with the list used for
the individual little tests. One way to deal with it would be
to generate the big test from the individual list as the first
step and fall back on the current mechanism.

Martin


RE: MSVC8 CRT "Secure Template Overloads" feature and stdcxx

Posted by Farid Zaripov <Fa...@epam.com>.
> -----Original Message-----
> From: Martin Sebor [mailto:sebor@roguewave.com] 
> Sent: Wednesday, June 13, 2007 6:24 PM
> To: stdcxx-dev@incubator.apache.org
> Subject: Re: MSVC8 CRT "Secure Template Overloads" feature and stdcxx
> 
> >   Since va_list can be anything, we need to pass va_list type in 
> > function call.
> > We can add function template <class T> get_t () { T t; 
> return t; } to 
> > the libc_decl.sh and use the followinf declaration: 
> > vsprintf((char*)0,0,get_t<va_list>())
> > in headers.inc.
> 
> Wouldn't vsprintf((char*)0,0,va_list()) work?

  I think this should work.

> My concern here 
> is with the va_list name: Is it required to be declared in 
> the same header as the functions that use it?

  On gcc 3.4.4/Cygwin the va_list type is not defined in stdio.h.

  Read the comment from <stdarg.h>:

/* Define va_list, if desired, from __gnuc_va_list. */
/* We deliberately do not define va_list when called from
   stdio.h, because ANSI C says that stdio.h is not supposed to define
   va_list.  stdio.h needs to have access to that data type, 
   but must not use that name.  It should use the name __gnuc_va_list,
   which is safe because it is reserved for the implementation.  */

Farid.

Re: MSVC8 CRT "Secure Template Overloads" feature and stdcxx

Posted by Martin Sebor <se...@roguewave.com>.
Farid Zaripov wrote:
>> -----Original Message-----
>> From: Martin Sebor [mailto:msebor@gmail.com] On Behalf Of Martin Sebor
>> Sent: Wednesday, June 13, 2007 6:36 AM
>> To: stdcxx-dev@incubator.apache.org
>> Subject: Re: MSVC8 CRT "Secure Template Overloads" feature and stdcxx
>>
>> Farid Zaripov wrote:
>>>  The MSVC8 CRT have the following feature: all  functions, working 
>>> with sting buffers (i.e. strcpy, strcat, sprintf, ...) have the 
>>> security-enhanced versions with suffix "_s"
>>> (i.e. strcpy_s, strcat_s, sprintf_s, ...). And if #defined macro
>>> _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1
>>> then will be defined template overloads of the such functions, i.e.:
>> So the templates are disabled by default, correct? And to 
>> enable them users would have to define the macro, both during 
>> configuration as well as while building and using the library.
> 
>   Correct.
> 
>>>  The proposed patch is attached, but I not sure about passing 0 as 
>>> va_list argument while testing vsprintf() and vswprintf().
>> I don't think that's guaranteed to be well-formed. va_list 
>> could be anything, including a struct with no conversion from 
>> int. But if you can get this issue resolved and if it 
>> compiles with all your compilers (i.e., all versions of MSVC 
>> and Intel C++ on Windows, as well as gcc on Linux and 
>> Cygwin), I think it should be safe to commit the change.
> 
>   Since va_list can be anything, we need to pass va_list type in
> function call.
> We can add function template <class T> get_t () { T t; return t; } to
> the libc_decl.sh
> and use the followinf declaration: vsprintf((char*)0,0,get_t<va_list>())
> in headers.inc.

Wouldn't vsprintf((char*)0,0,va_list()) work? My concern here
is with the va_list name: Is it required to be declared in the
same header as the functions that use it?

Martin

> 
>   The proposed patch of the libc_decl.sh:
> 
> 
> Index: libc_decl.sh
> ===================================================================
> --- libc_decl.sh	(revision 546575)
> +++ libc_decl.sh	(working copy)
> @@ -227,6 +227,15 @@
>  
>  #  endif   // no_namespace
>  
> +#include <stdarg.h>
> +
> +template <class T>
> +T get_t ()
> +{
> +    T t;
> +    return t;
> +}
> +
>  int main (int argc, char**)
>  {
>      // with gcc, prevent intrinsics from causing false positives
> 
> Farid.


RE: MSVC8 CRT "Secure Template Overloads" feature and stdcxx

Posted by Farid Zaripov <Fa...@epam.com>.
> -----Original Message-----
> From: Martin Sebor [mailto:msebor@gmail.com] On Behalf Of Martin Sebor
> Sent: Wednesday, June 13, 2007 6:36 AM
> To: stdcxx-dev@incubator.apache.org
> Subject: Re: MSVC8 CRT "Secure Template Overloads" feature and stdcxx
> 
> Farid Zaripov wrote:
> >  The MSVC8 CRT have the following feature: all  functions, working 
> > with sting buffers (i.e. strcpy, strcat, sprintf, ...) have the 
> > security-enhanced versions with suffix "_s"
> > (i.e. strcpy_s, strcat_s, sprintf_s, ...). And if #defined macro
> > _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1
> > then will be defined template overloads of the such functions, i.e.:
> 
> So the templates are disabled by default, correct? And to 
> enable them users would have to define the macro, both during 
> configuration as well as while building and using the library.

  Correct.

> >  The proposed patch is attached, but I not sure about passing 0 as 
> > va_list argument while testing vsprintf() and vswprintf().
> 
> I don't think that's guaranteed to be well-formed. va_list 
> could be anything, including a struct with no conversion from 
> int. But if you can get this issue resolved and if it 
> compiles with all your compilers (i.e., all versions of MSVC 
> and Intel C++ on Windows, as well as gcc on Linux and 
> Cygwin), I think it should be safe to commit the change.

  Since va_list can be anything, we need to pass va_list type in
function call.
We can add function template <class T> get_t () { T t; return t; } to
the libc_decl.sh
and use the followinf declaration: vsprintf((char*)0,0,get_t<va_list>())
in headers.inc.

  The proposed patch of the libc_decl.sh:


Index: libc_decl.sh
===================================================================
--- libc_decl.sh	(revision 546575)
+++ libc_decl.sh	(working copy)
@@ -227,6 +227,15 @@
 
 #  endif   // no_namespace
 
+#include <stdarg.h>
+
+template <class T>
+T get_t ()
+{
+    T t;
+    return t;
+}
+
 int main (int argc, char**)
 {
     // with gcc, prevent intrinsics from causing false positives

Farid.

Re: MSVC8 CRT "Secure Template Overloads" feature and stdcxx

Posted by Martin Sebor <se...@roguewave.com>.
Farid Zaripov wrote:
>  The MSVC8 CRT have the following feature: all  functions, working with 
> sting buffers
> (i.e. strcpy, strcat, sprintf, ...) have the security-enhanced versions 
> with suffix "_s"
> (i.e. strcpy_s, strcat_s, sprintf_s, ...). And if #defined macro
> _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1
> then will be defined template overloads of the such functions, i.e.:

So the templates are disabled by default, correct? And to enable them
users would have to define the macro, both during configuration as well
as while building and using the library.

> 
>  template <size_t size>
>  char *strcpy(char (&dest)[size], const char *src)
>  {
>     return strcpy_s(dest, size, src);
>  }

Hmm. I'm not sure this is actually allowed by the C++ standard. Not
that that's ever stopped Microsoft before.

[...]
>  I've tried to compile the stdcxx library with defined 
> _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1
> and _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1, but the configure 
> step has failed to
> detect this functions because of the compiler cannot decide which 
> function address is taken.
> 
>  Here the list of the that functions:
> 
> <cstdio>: gets sprintf tmpnam vsprintf
> <cstdlib>: div mbstowcs wcstombs
> <cstring>: strcat strcpy strncat strncpy
> <cwchar>: mbsrtowcs swprintf vswprintf wcrtomb wcscat wcscpy wcsncat 
> wcsncpy wcsrtombs
> 
>  The div(int, int) function failed to detect because of the presence the 
> "extern C++" div(long, long) overload.
> 
>  I propose to make changes in headers.inc file to check this functions 
> not by takig the address, but by call the functions.
> 
>  The proposed patch is attached, but I not sure about passing 0 as 
> va_list argument while testing vsprintf() and vswprintf().

I don't think that's guaranteed to be well-formed. va_list could
be anything, including a struct with no conversion from int. But
if you can get this issue resolved and if it compiles with all
your compilers (i.e., all versions of MSVC and Intel C++ on
Windows, as well as gcc on Linux and Cygwin), I think it should
be safe to commit the change.

Martin


> 
> Farid.
> 
> 
> ------------------------------------------------------------------------
> 
> Index: headers.inc
> ===================================================================
> --- headers.inc	(revision 546565)
> +++ headers.inc	(working copy)
> @@ -32,9 +32,10 @@
>  # stdio functions
>  c90_funs="clearerr fclose feof ferror fflush fgetc fgetpos fgets fopen       \
>            fprintf fputc fputs fread freopen fscanf fseek fsetpos ftell       \
> -          fwrite getc getchar gets perror printf putc putchar puts remove    \
> -          rename rewind scanf setbuf setvbuf sprintf sscanf tmpfile tmpnam   \
> -          ungetc vfprintf vprintf vsprintf"
> +          fwrite getc getchar gets((char*)0) perror printf putc putchar      \
> +          puts remove rename rewind scanf setbuf setvbuf                     \
> +          sprintf((char*)0,0,0) sscanf tmpfile tmpnam((char*)0) ungetc       \
> +          vfprintf vprintf vsprintf((char*)0,0,0)"
>  c99_funs="snprintf vsnprintf"
>  posix_funs="fileno"
>  
> @@ -42,9 +43,10 @@
>  
>  
>  # stdlib functions
> -c90_funs="abort abs atexit atof atoi atol atoll bsearch calloc div exit free \
> -          getenv labs ldiv llabs lldiv malloc mblen mbstowcs mbtowc qsort    \
> -          rand realloc srand strtod strtol strtoul system wcstombs wctomb"
> +c90_funs="abort abs atexit atof atoi atol atoll bsearch calloc div(0,0)      \
> +          exit free getenv labs ldiv llabs lldiv malloc mblen                \
> +          mbstowcs((wchar_t*)0,0,0) mbtowc qsort rand realloc srand strtod   \
> +          strtol strtoul system wcstombs((char*)0,0,0) wctomb"
>  c99_funs="strtof strtold strtoll strtoull"
>  posix_funs="mkstemp putenv setenv unsetenv"
>  
> @@ -52,23 +54,26 @@
>  
>  
>  # string functions
> -string="memchr((void*)0,0,0) memcmp memcpy memmove memset strcat             \
> -        strchr((char*)0,0) strcmp strcoll strcpy strcspn strerror strlen     \
> -        strncat strncmp strncpy strpbrk((char*)0,(char*)0)                   \
> -        strrchr((char*)0,0) strspn strstr((char*)0,(char*)0) strtok strxfrm"
> +string="memchr((void*)0,0,0) memcmp memcpy memmove memset strcat((char*)0,0) \
> +        strchr((char*)0,0) strcmp strcoll strcpy((char*)0,0) strcspn         \
> +        strerror strlen strncat((char*)0,0,0) strncmp strncpy((char*)0,0,0)  \
> +        strpbrk((char*)0,(char*)0) strrchr((char*)0,0) strspn                \
> +        strstr((char*)0,(char*)0) strtok strxfrm"
>  
>  
>  # wchar functions
>  wchar="btowc fgetwc fgetws fputwc fputws fwide fwprintf fwscanf getwc        \
> -       getwchar mbrlen mbrtowc mbsinit mbsrtowcs putwc putwchar swprintf     \
> -       swscanf ungetwc vfwprintf vswprintf vwprintf vwscanf wcrtomb wcscat   \
> -       wcschr((wchar_t*)0,0) wcscmp wcscoll wcscpy wcscspn wcsftime wcslen   \
> -       wcsncat wcsncmp wcsncpy wcspbrk((wchar_t*)0,(wchar_t*)0)              \
> -       wcsrchr((wchar_t*)0,0) wcsrtombs wcsspn                               \
> -       wcsstr((wchar_t*)0,(wchar_t*)0) wcstod wcstod wcstof wcstok wcstol    \
> -       wcstold wcstoll wcstoul wcstoull wcsxfrm wctob                        \
> -       wmemchr((wchar_t*)0,0,0) wmemcmp wmemcpy wmemmove wmemset wprintf     \
> -       wscanf"
> +       getwchar mbrlen mbrtowc mbsinit mbsrtowcs((wchar_t*)0,0,0,0) putwc    \
> +       putwchar swprintf((wchar_t*)0,0,0) swscanf ungetwc vfwprintf          \
> +       vswprintf((wchar_t*)0,0,0,0) vwprintf vwscanf wcrtomb((char*)0,0,0)   \
> +       wcscat((wchar_t*)0,0) wcschr((wchar_t*)0,0) wcscmp wcscoll            \
> +       wcscpy((wchar_t*)0,0) wcscspn wcsftime wcslen                         \
> +       wcsncat((wchar_t*)0,0,0) wcsncmp wcsncpy((wchar_t*)0,0,0)             \
> +       wcspbrk((wchar_t*)0,(wchar_t*)0) wcsrchr((wchar_t*)0,0)               \
> +       wcsrtombs((char*)0,0,0,0) wcsspn wcsstr((wchar_t*)0,(wchar_t*)0)      \
> +       wcstod wcstod wcstof wcstok wcstol wcstold wcstoll wcstoul wcstoull   \
> +       wcsxfrm wctob wmemchr((wchar_t*)0,0,0) wmemcmp wmemcpy wmemmove       \
> +       wmemset wprintf wscanf"
>  
>  
>  # wctype functions