Mac solution for "safe" alternatives to "unsafe" C/C++ Standard Library functions? [closed]
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 11 months ago.
Improve this questionWhat's the best one-stop-shop "safe" C library solution on the Mac? I use quotes on "safe"/"unsafe" because there is much debate as to the benefits of certain Standard Library functions or their putatively improved alternatives.
Many traditional Standar开发者_开发问答d C Library functions (e.g., vfprintf
) are considered to be unsafe due to the potential for buffer overflow or other security problems.
On Windows, the Microsoft C/C++ compilers provide the "_s" functions (e.g., vfprintf_s
) as a safer alternative to the standard library calls. These functions are not drop-in replacements since they have the different signatures necessary to provide additional safety information (e.g., buffer length). They also provide other features such as invalid format string detection, different file security, etc. As far as I know, this implementation is not available on the Mac.
Does Apple (or a third party) provide anything similar for use with GCC on OSX?
In particular, I'm looking for "safe" implementations of at least the following functions:
fopen vfprintf vsprintf sprintf strncpy strcpy strcat
Please note: This question is about the Mac. I am NOT asking for your opinions about Microsoft's implementation (unless it's available on the Mac.) Although some of these functions might be easy to write myself, not all are. I am NOT asking how to write these myself. I'm NOT asking for tips on how to use STL classes to do this. I'm NOT asking how to turn off warnings. My particular needs are very specific. I'm trying to identify a best-practice Mac API that is as similar as possible to the traditional C library calls while adding safety. Of course a portable implementation that works on Mac and Windows (and other operating systems) would be even better.
First of all, print the documentation about "safe/unsafe" functions from MSDN and burn it!
fopen
Is as safe as fopen_s... Uless you are idiot and assume that returned pointer is not NULL, or provide NULL as input parameter.
vfprintf vsprintf sprintf
Just MS do not support C99, use snprintf
family.
strncpy
Is perfectly safe if you read the manual
strcpy strcat
Use strncpy
and strncat
and read specifications. (i.e. strncpy may be not null terminated)
So... once again:
Print the documentation about "safe/unsafe" functions from MSDN and burn it!
SUMMARY: on Mac, there are several APIs and compiler options that provide safer alternatives to C Standard Library functions. Here are some of them compared with Microsoft's "safe" APIs:
C MSVC PROVIDERS MAC SOLUTION --------------------------------------------------------------------------------- fopen fopen_s C none, assume fopen is safe vfprintf vfprintf_s GCC GCC_WARN_TYPECHECK_CALLS_TO_PRINTF(1) vsprintf vsprintf_s GCC, C99 GCC_WARN_TYPECHECK_CALLS_TO_PRINTF, vsnprintf(2) sprintf sprintf_s GCC, C99 GCC_WARN_TYPECHECK_CALLS_TO_PRINTF, snprintf(3) strncpy strncpy_s BSD strlcpy(4) strcpy strcpy_s BSD strlcpy strcat strcat_s BSD strlcat(5)
(1) GCC_WARN_TYPECHECK_CALLS_TO_PRINTF
is an XCode configuration option which corresponds to the GCC command-line option -Wformat
. This option produces compiler warnings of disagreement between argument types and static format strings. There are a variety of other options to control GCC's treatment of format strings. You can even use GCC's format
function attribute to enable format string checking on your own functions.
(2) vsnprintf
and (3) snprintf
are from the C99 version of the C Standard Library (available in GCC on Mac but not in MSVC on Windows).
(4) strlcpy
and (5) strlcat
are BSD library functions, available on Mac.
Instead sprintf and vsprintf, you want to use:
snprintf(buffer, buffer_size, fmt_string, args, ...);
vsnprintf(buffer, buffer_size, fmt_string, valist);
Instead of strcpy, strncpy, strcat and strncat you want to us:
strlcpy(dest, src, dest_size);
strlcat(dest, src, dest_size);
There is one important way that the strn functions can not be replaced by the strl functions. If you want to copy non-0 terminated strings, the strn functions allow you to do that by setting the length to the smaller value of the amount of copy and the size of the destination buffer. The strl functions do not do that and only work when the source string is 0 terminated.
Not sure how fopen or vfprintf are considered unsafe.
See also: SO 327980.
The Standard C committee has created a technical report, TR 24731-1, in part at Microsoft's encouragement (I believe). It standardizes the interfaces to the various functions such as vsnprintf_s()
. Sadly, however, the interface defined by the standard is incompatible with the interface defined by Microsoft, thus rendering the standard largely irrelevant.
For example, TR 24731-1 says the interface to vsnprintf_s()
is:
#define _ _STDC_WANT_LIB_EXT1_ _ 1
#include <stdarg.h>
#include <stdio.h>
int vsnprintf_s(char * restrict s, rsize_t n,
const char * restrict format, va_list arg);
Unfortunately, MSDN says the interface to vsnprintf_s()
is:
int vsnprintf_s(
char *buffer,
size_t sizeOfBuffer,
size_t count,
const char *format,
va_list argptr
);
Parameters
- buffer - Storage location for output.
- sizeOfBuffer - The size of the buffer for output.
- count - Maximum number of characters to write (not including the terminating null), or _TRUNCATE.
- format - Format specification.
- argptr - Pointer to list of arguments.
Note that this is not simply a matter of type mapping: the number of fixed arguments is different, and therefore irreconcilable. It is also unclear to me (and presumably to the standards committee too) what benefit there is to having both 'sizeOfBuffer' and 'count'; it looks like the same information twice (or, at least, code will commonly be written with the same value for both parameters).
In particular, I'm looking for "safe" implementations of at least the following functions: fopen vfprintf vsprintf sprintf strncpy strcpy strcat ...
I'm trying to identify a best-practice Mac API that is as similar as possible to the traditional C library calls while adding safety.
That's easy. Checkout the Apple Secure Coding Guide. Apple happens to use the BSD "safer" functions.
Related: while Apple and Microsoft provide safer functions, Linux does not. GNU C did not include "Bounds checking Interfaces" (ISO's TR24731) because folks like Ulrich Drepper (a GNU libc gatekeeper) objected. He objected because only the destination buffer was specified. He called the "safer" function BSD Crap. For Drepper's quote, see Re: PATCH: safe string copy and concetation on the Sourceware mailing list.
Following Drepper's advice will lead to spectacular failures. CVE-2012-5958 CVE-2012-5959 CVE-2012-5960 CVE-2012-5961 CVE-2012-5962 CVE-2012-5963 CVE-2012-5964 CVE-2012-5965 (also known as Multiple buffer overflows in libupnp) for the win! Its too bad libupnp followed Drepper's and ignored best practices and discarded "safer" functions. I wonder how many millions of routers and gateways remain unpatched even today...
Since OSX's userland is based on FreeBSD, you do have some nicer functions like strlcpy and strlcat.
The C standard already has a set of "Safe" version of these functions.
(For a particular definition of the term safe)
The snprintf() (and family) provide the safety features you are looking for. Buffer overflow checking.
The gcc compiler in addition does format string validation (but better than MS because the validation is done at compile time).
fopen() Not sure how you make that safer?
vfprintf -- These are low level functions
vsprintf -- These are low level functions
sprintf snprintf
strncpy Already the safe version
strcpy strncpy
strcat strncat
Google Summer of Code 2010: OpenAfs and Google are sponsoring a port of Microsoft's String Safe library. See http://www.openafs.org/pages/gsoc.html.
My safeclib is a portable solution. The MS implementation is buggy and unsafe, other implementations do exist, but are not portable or overly naive.
https://github.com/rurban/safeclib
精彩评论