What are some alternatives to the Microsoft security enhanced functions such as strncpy_s
or _itoa_s
? Although developing in MS environment the goal is to write code that could be ported easily to other platforms.

- 30,036
- 10
- 99
- 142

- 1,319
- 2
- 12
- 20
-
2what for are you using C strings? To connect with C Api? – Mykola Golubyev May 13 '09 at 14:32
10 Answers
If you really want to program in C:
Use the plain old standard strncpy
.
If you're programming in C++:
Use the plain old standard string class std::string
.
(hint: You probably want the latter. C strings are just bugs waiting to happen, even if you use the "secure" *_s
functions. C++ added a string class for a reason)

- 243,077
- 51
- 345
- 550
Rageous is correct, there is no complex logic behind it.
I would just use Microsoft's version for now and if you decide to port to another OS later, THEN implement it yourself for the target platform and use preprocessor commands to specify your implementation on the non-Windows platform(s).

- 27,121
- 13
- 66
- 85
Try strlcpy. Though not standard C, it exists on a number of platforms and you can download implementations as the source code is available free of charge. See http://www.gratisoft.us/todd/papers/strlcpy.html

- 4,359
- 9
- 43
- 63
I think @codeLizard is asking about how to write compatible code to handle all the functions that Microsoft has deprecated in favor of their secure versions, not just the string functions.
Functions based on Microsoft's secure functions are included in Annex K of the C11 standard, but the annex is not widely supported outside of MSVS.
You can write macros and inline functions in an include file to map back and forth between some of the traditional and secure versions. I posted a set of conversion macros here, If you want to copy them, get them from the liked page; more complete, better comments than below.
However, the approach doesn't work for mapping traditional functions to the secure versions that take size arguments unless the size arguments are also present in the traditional functions. Also, the secure functions differ in exception behaviors, and sometimes in return values. My current conversions don't account for that. When I have time, I'll attempt to improve them where I can to do just that. In the meantime, I'll leave it as an exercise for the reader.
I recommend using the secure functions in new code if you can, use the macro plus function solution if portability to non-MS compilers if required, and also as a bridge for reusing legacy code until you have time to update it with the secure functions.
Here is an abbreviated version of the above linked macro / inline function approach:
#pragma once
#if !defined(FCN_S_MACROS_H)
#define FCN_S_MACROS_H
#include <cstdio>
#include <string> // Need this for _stricmp
using namespace std;
#if (defined(_MSC_VER) && (_MSC_VER >= 1400) ) // _MSC_VER==MSVC 2005
// The function plus macro strategy could be used to maintain
// consistent exception behaviors and return values.
inline extern
FILE* fcnSMacro_fopen_s(char *fname, char *mode)
{ FILE *fptr;
fopen_s(&fptr, fname, mode);
return fptr;
}
#define fopen(fname, mode) fcnSMacro_fopen_s((fname), mode))
#define fprintf(fptr, ...) fprintf_s((fptr), __VA_ARGS__)
#define fscanf fscanf_s
#define strncpy(dest, source, count) strcpy_s((dest), (count), (source))
// Can't map sprinf to sprintf_s (size argument unavailable).
// #define sprintf ???
...
#else
#define fopen_s(fp, fmt, mode) *(fp)=fopen( (fmt), (mode))
#define fprintf_s fprintf
#define fscanf_s fscanf
#define strcpy_s(dest, count, source) strncpy( (dest), (source), (count) )
...
#endif //_MSC_VER
#endif // FCN_S_MACROS_H
-
The C++11 standard does not mention `strncpy_s()` explicitly. The C11 standard has `strncpy_s()` in optional Annex K (normative, but optional). Unfortunately the Microsoft versions of the safe functions don't match the specifications of [TR 24731 or Annex K](https://stackoverflow.com/questions/372980/). That makes them problematic for portability on two counts: (1) most non-Microsoft platforms have not implemented the Annex K functions at all, and (2) if a platform has implemented them, there will be differences between what works with Microsoft and what works other platforms. – Jonathan Leffler Feb 04 '16 at 06:31
-
The C++11 standard references the C99 standard and not the C11 standard. And the current C++ standard is C++14, of course. – Jonathan Leffler Feb 04 '16 at 06:32
-
@Jonathan. Right about the optional Annex K. I should have mentioned that. I've been writing code exclusively in Visual Studio over the last few years. I think I saw a Gnu compiler command line option for Annex K (can't recall for sure), so I assumed it was widely supported these days. Is that true? Sloppy of me not to confirm it myself. – riderBill Feb 05 '16 at 19:24
-
I hope support for them *is* widespread. I resented Microsoft's imposition of the secure variants at first, but looking closer, I see the need. I write a lot code to answer engineering questions. Only my team has access to the source code, I'm the only user of the platform, execution time is more important than security (Murphy will prove differently some day). Even so, in practice, the (I assume) slower execution of the secure variants is likely negligible; IO and string manipulation are rare in innermost loops. I'll admit my guilt of not having profiled to quantify the difference, however. – riderBill Feb 05 '16 at 20:27
-
1Support for the Annex K functions is minimal outside the Microsoft world, for the reasons outlined in my first comment — and elaborated in the cross-referenced question. Note that a few years ago (which means things may have changed), the lead maintainer of GNU LibC refused to countenance the addition of the Annex K functions to GNU LibC. The POSIX committee was sceptical about about their merits, too. – Jonathan Leffler Feb 05 '16 at 20:36
-
@Jonnathan. Thanks. I just googled it myself to confirm it. I'll edit my answer to reflect the lack of non-ms support. – riderBill Feb 08 '16 at 20:08
-
I was poking around the interweb today and came a cross several comments about thread safety of `strerror_s()`, and lack thereof with the standard `strerror()` function. [See this](http://stackoverflow.com/questions/900338/why-cant-i-use-strerror). If you write multi-threaded code, that is another reason to switch to the secure versions. Assuming that's an option, of course. – riderBill Feb 10 '16 at 00:57
-
See POSIX [`strerror_r()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/strerror_r.html) for the POSIX view of the thread-safe world. This is more or less equivalent to `strerror_s()` — you have `int strerror_r(int errnum, char *strerrbuf, size_t buflen);` vs `errno_t strerror_s(char *s, rsize_t maxsize, errno_t errnum);` so they are not drop-in equivalents (and `strerror_s()` will detect misuses in ways that `strerror_r()` will not). – Jonathan Leffler Feb 10 '16 at 01:06
-
@Jonnathan. Thanks for the edit. Hard to proofread my own writing; I thought I changed "...Annex K of the C++11..." to "...Annex K of the *C11..." – riderBill Feb 10 '16 at 18:33
As far as I understand, strncpy_s has no complex logic: just takes minimum of string length, source and destination data sizes and copies resulting amount of chars into destination. If you need it so much, why not to implement it yourself?
You may be interested in the Apache Portable Runtime project:
The mission of the Apache Portable Runtime (APR) project is to create and maintain software libraries that provide a predictable and consistent interface to underlying platform-specific implementations.
autoconf can also take care of some of these platform-specific differences (by setting #defines, etc), although my experience with it under Windows leaves something to be desired.

- 8,527
- 1
- 30
- 43
Yes, try the https://rurban.github.io/safeclib/.
This is the platform independent implementation of the C11 Annex K on top of all libc's. It is mostly compatible to the Windows sec_api. Windows deviates a bit from the spec with some functions.
strncpy_s
is one of the most tricky APIs in the sec_api. Windows does not detect overflow of the two lengths, not an overlap of the two strings.
And what to do when the 4th argument count = 0 is also questionable. The spec http://en.cppreference.com/w/c/string/byte/strncpy says A zero return value implies ... that the result in s1 is null terminated, but on windows this is wrong. It just aborts too early.
See e.g. the wine implementation: https://github.com/mirror/reactos/blob/master/reactos/lib/sdk/crt/wine/heap.c#L577
And for the _s
secure suffix one should assume that wrongly copied bytes into the destination buffer are cleared from prying eyes when an run-time error occured. Not so on Windows with their sec_api. They just set the very first byte to 0.

- 4,025
- 24
- 27
You could either provide an own implementation for platforms that don't have this function. Or use a macro to reduce the arguments by one and map to the standard string function.

- 344,408
- 85
- 689
- 683