14

What'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 Standard 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.

jwfearn
  • 28,781
  • 28
  • 95
  • 122
  • 10
    Using these so-called "safe" functions is not best practice. –  Jan 30 '10 at 18:57
  • 5
    Why can you not use the safe C++ standard library equivalents? (Or why does the title say C/C++ standard library functions if you refuse to use the C++ standard library) – jalf Jan 30 '10 at 18:58
  • 3
    GCC already does format string verification for the regular C standard library functions. It's implemented using a special keyword, so you can even do that with your own functions taking standard format strings. – Stéphan Kochen Jan 30 '10 at 19:03
  • The C standard already has a set of "Safe" versions of these functions. Use the version in the standard: s__n__printf() and family. – Martin York Jan 30 '10 at 19:32
  • 1
    The functions aren't particularly easy to write - doing the job properly takes considerable care and effort (I know; I tried - and didn't finish). They aren't dreadfully hard - just fiddly, endlessly fiddly. And testing is a hard, too. – Jonathan Leffler Jan 30 '10 at 19:34
  • @Martin York: one of the good features of the TR24731 '_s' functions is that the formatting functions do not support the '%n' (mis)feature. – Jonathan Leffler Jan 30 '10 at 19:35
  • See also: http://stackoverflow.com/questions/372980/ - but note that I recently found, to my considerable chagrin, that the MS interfaces to the '_s' functions are not the same as the interfaces to the TR24731 functions. So simply using the TR24731 functions is not sufficient... – Jonathan Leffler Jan 30 '10 at 19:37
  • 2
    @Neil Butterworth: Why are the "safe" functions are not best-practice? Perhaps you could cite a link to an explanation? What IS the best practice on the Mac? – jwfearn Jan 30 '10 at 22:55
  • 2
    @Shteef: Thanks so much for your comment. I'll bite, what IS the secret keyword to enable format string verification in GCC? How about a link? – jwfearn Jan 30 '10 at 23:02
  • @jwfearn: *"What IS the best practice on the Mac"* - see [Apple Secure Coding Guide](https://developer.apple.com/library/iOs/documentation/Security/Conceptual/SecureCodingGuide/SecureCodingGuide.pdf). Apple, like Linux, does not provide TR24731. Apple does provide the BSD alternatives, however. – jww Aug 24 '14 at 22:38
  • 1
    @anon: *"Using these so-called "safe" functions is not best practice"* - Apple and Microsoft disagree with you. Drepper happens to agree with you (assuming he can be thought of as the voice of Linux in this case). Linux has some of the most spectacular failures. `libupnp` for the win (and for all those unpatched routers): CVE-2012-5958 CVE-2012-5959 CVE-2012-5960 CVE-2012-5961 CVE-2012-5962 CVE-2012-5963 CVE-2012-5964 CVE-2012-5965. – jww Aug 24 '14 at 23:20

9 Answers9

16

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!

Artyom
  • 31,019
  • 21
  • 127
  • 215
  • 4
    strncpy / strncat are safe but are a pain to use correctly. strncpy requires the caller to add the 0 terminator. strncat requires the user to calculate how much to copy, not the size of the destination buffer. – R Samuel Klatchko Jan 30 '10 at 19:53
  • Note that Microsoft's vsnprintf() cannot be standard (C99) compliant because the C99 definition requires vsnprintf() to add a terminating null unless the length of the buffer is zero (and that has a special meaning). I presume MS knows what it means when it says that its vsnprintf() does not always add the terminal null, but that just means that MS (probably) implemented it before the standard canonized the correct behaviour, and then felt unable to risk changing the erroneous definition (even though it is hard to see any working code breaking as a result of the change). – Jonathan Leffler Jan 30 '10 at 20:01
  • 1
    @Artyom, Thanks for your answer. You may safely assume that I AM an idiot. In particular, you can bet that I will eventually err with any function that is "safe if I read the manual". – jwfearn Jan 30 '10 at 22:51
  • 4
    @jwfearn -- the point is that MS created their own "safe" functions instead of adopting safe functions of C99. For example, fopen_s is total "crap", sprintf_s as well - use snprintf. And so on. Yes, strncpy and strncat are tricy but still, it is much better to stay withing the standard then... Don't beleve everything you read about "unsafe-funtions" – Artyom Jan 31 '10 at 04:57
  • 1
    Actually, TR24731 post-dates the equivalent functions from MS - MS implemented something, then submitted their system to the Standard C committee. What was 'standardized' (to the extent it is standardized; it is a tech report at the moment) was different from the MS proposal. – Jonathan Leffler Jan 31 '10 at 07:30
  • strncpy is not safe. It does not guarantee to null-terminate the string. Using it correctly is error-prone. – George Jul 13 '16 at 17:05
12

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.

jwfearn
  • 28,781
  • 28
  • 95
  • 122
6

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.

R Samuel Klatchko
  • 74,869
  • 16
  • 134
  • 187
  • 1
    vfprintf() is unsafe because it supports the '%n' directive (to report the number of bytes written at the time when the directive is processed). This was a funny (bad?) move on the C89 standardization process - it requires an output parameter (pointer to int) in `printf()` et al. That much is unsafe - but the rest isn't. – Jonathan Leffler Jan 30 '10 at 20:03
5

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).

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • @Jonathan Leffler: do you know if these APIs are available on the Mac? – jwfearn Jan 30 '10 at 23:08
  • They are not in the main system library - /usr/lib/libSystem.B.dylib. I haven't checked every dylib on the machine, but I suspect they are conspicuous by their absence, here and on most Unix-based machines. Someone did create the safe library for the string routines about, oh, 6 months or so ago; you might be able to find that on the web (ask me if you can't). – Jonathan Leffler Jan 31 '10 at 03:22
  • I did a thorough search (`find / -name '*.dylib' -print0 | xargs -0 nm -og | grep '_s$'`) and didn't find any of the TR 24731 safe functions. There were a number of functions that ended '_s', but none that are relevant. – Jonathan Leffler Jan 31 '10 at 07:23
4

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.

enter image description here


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...

jww
  • 97,681
  • 90
  • 411
  • 885
  • @jww: Those actually safer function listed in your picture are provided on Linux since long ago. Only the dysfunctional annex k was ignored as superfluous and actively harmful. – Deduplicator Feb 17 '15 at 22:19
  • @Deduplicator - out of curiosity, why do you think Annex K is dysfunctional? (BTW, its now part of the standard, and no longer an annex). – jww Feb 17 '15 at 23:37
  • Take a look (again) at this question: http://stackoverflow.com/questions/372980/do-you-use-the-tr-24731-safe-functions And as of C11 (which is still the current standard), they only made it into an optional annex (which does not imply the MS implementation will ever conform). Before it was a TR. – Deduplicator Feb 18 '15 at 00:30
  • @Deduplicator - my bad, you are right. They are still in an Annex, but they are now normative. Apparently that's been the case since 2011 (ISO/IEC 9899:2011). But I'm still curious about the dysfunctionality. – jww Feb 18 '15 at 01:00
3

Since OSX's userland is based on FreeBSD, you do have some nicer functions like strlcpy and strlcat.

Nikolai Fetissov
  • 82,306
  • 11
  • 110
  • 171
3

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
Martin York
  • 257,169
  • 86
  • 333
  • 562
  • My understanding re: fopen is that the "standard" version is specified to use default security rules which may not match the "safe" defaults of the host OS...or something like that. Not that it's a buffer overflow issue. I could be wrong. I included it in my list since MSVC provides an fopen_s function. – jwfearn Jan 30 '10 at 23:06
  • strncpy() has to be used very carefully to be safe - it does not null terminate when the source is too long for the destination. It's padding property (zero padding to full length) is sometimes a handicap, especially if you have a 20 KB buffer but are mostly schlepping 50 bytes strings around. – Jonathan Leffler Jan 31 '10 at 03:25
  • @jwfearn: in TR24731, the main difference between standard fopen() and fopen_s() is the addition of a flag, 'u'. Quoting: To the extent that the underlying system supports the concepts, files opened for writing shall be opened with exclusive (also known as non-shared) access. If the file is being created, and the first character of the mode string is not ’u’, to the extent that the underlying system supports it, the file shall have a file permission that prevents other users on the system from accessing the file. [...] – Jonathan Leffler Jan 31 '10 at 03:30
1

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.

Jeffrey Walton
  • 255
  • 2
  • 4
0

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

rurban
  • 4,025
  • 24
  • 27
  • When linking to your own site or content (or content that you are affiliated with), you [must disclose your affiliation _in the answer_](/help/promotion) in order for it not to be considered spam. Having the same text in your username as the URL or mentioning it in your profile is not considered sufficient disclosure under Stack Exchange policy. You've also linked to your repos in multiple answers. You need to disclose affiliation in all of them. – cigien Jan 15 '22 at 14:18