Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Comments on Which functions in the C standard library must always be avoided?

Parent

Which functions in the C standard library must always be avoided?

+8
−0

It would seem that the C standard library is a collection of diverse functions that pretty much just ended up in the standard by tradition or "accident", rather than through some careful plan or rationale. During standardization of ANSI/ISO 9899:1990, they just grabbed a bunch of existing library functions in Unix and made them standard.

Some of them, like the notorious gets are even broken by design. Clearly a lot of them were invented in a time long before things like software security or even compiler optimizations were invented. Or in case of the notorious strncpy, from a time before null terminated strings were invented.

Is there a complete list of functions in the standard library that should always be avoided in any C program? Ideally covering ISO 9899:1990 to 202x versions of the language.

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.
Why should this post be closed?

0 comment threads

Post
+5
−2

Standard library functions that should never be used:

setjmp.h

  • setjmp()

    Together with longjmp(), these functions are widely recogniced as incredibly dangerous to use: they lead to spaghetti programming, they come with numerous forms of undefined behavior, they can cause unintended side-effects in the program environment, such as affecting values stored on the stack. References: MISRA-C:2012 rule 21.4, CERT C MSC22-C.

  • longjmp()
    See setjmp().

stdio.h

  • gets()
    The function has been removed from the C language (as per C11), as it was unsafe as per design. The function was already flagged as obsolete in C99. Use fgets() instead. References: ISO 9899:2011 K.3.5.4.1, also see note 404).

stdlib.h

  • atoi() family of functions.
    These have no error handling but invoke undefined behavior whenever errors occur. Completely superfluous functions that can be replaced with the strtol() family of functions. strtol(src, NULL, 10) is per definition 100% equivalent to atoi except with well-defined error handling. References: ISO 9899:2018 7.22.1.2, MISRA-C:2012 rule 21.7.

string.h

  • strncat()
    Has an awkward interface that are often misused. It is mostly a superfluous function. Also see remarks for strncpy().
  • strncpy()
    The intention of this function was never to be a safer version of strcpy(). Its sole purpose was always to handle an ancient string format on Unix systems, and that it got included in the standard library is a known mistake. This function is dangerous because it may leave the string without null termination and programmers are known to often use it incorrectly. References: Is strcpy dangerous and what should be used instead?

Standard library functions that should be used with caution:

assert.h

  • assert()
    Comes with overhead and should generally not be used in production code. In production code, it is better to use an application-specific error handler which displays errors but does not necessarily close down the whole program.

ctype.h

  • For all functions in this header, note this vulnerabilities listed by the C standard ISO 9899:2018:

    In all cases the argument is an int, the value of which shall be representable as an unsigned char or shall equal the value of the macro EOF. If the argument has any other value, the behavior is undefined.

    Therefore passing a char which possibly contains negative values to the ctype.h functions is dangerous practice.

signal.h

  • signal()
    Comes with various forms of poorly-defined behavior, particularly when called from within signal handlers.

    References: MISRA-C:2012 rule 21.5, CERT C SIG32-C.

stdarg.h

  • va_arg() family of functions.
    The presence of variable-length functions in a C program is almost always an indication of poor program design. Should be avoided unless you have very specific requirements.

stdio.h

  • Generally, this whole library is not recommended for production code, as it comes with numerous cases of poorly-defined behavior and poor type safety. References: MISRA-C:2012 rule 21.6.

    Yours sincerely likes to name this one the worst programming library ever designed for any programming language, all categories, though of course that's subjective - I'm mostly basing this on monetary damage done to mankind.

  • fflush()
    Perfectly fine to use for output streams. Invokes undefined behavior if used for input streams.

  • gets_s()
    Safe version of gets() included in C11 bounds-checking interface. It is preferred to use fgets() instead, as per C standard recommendation. References: ISO 9899:2011 K.3.5.4.1.

  • printf() family of functions.
    Poor performance functions that come with lots of undefined behavior and poor type safety. sprintf() also has specific vulnerabilities. These functions should be avoided in production code. References: MISRA-C:2012 rule 21.6.

  • scanf() family of functions.
    See remarks about printf(). Also, - scanf() is vulnerable to buffer overruns if not used correctly. fgets() is preferred to use when possible. References: CERT C INT05-C, MISRA-C:2012 rule 21.6.

  • tmpfile() family of functions.
    Comes with various vulnerability issues. References: CERT C FIO21-C.

  • feof()
    The use of loops such as while(!feof(fp)) are almost certainly incorrect - instead the various file read functions used in the loop body should have their results checked directly.

  • ungetc()
    C17 7.31.11 Future language directions:

    The use of ungetc on a binary stream where the file position indicator is zero prior to the call is an obsolescent feature.

stdlib.h

  • malloc() family of functions.
    Perfectly fine to use in hosted systems, though be aware of well-known issues in C90 and therefore don't cast the result. The malloc() family of functions should never be used in freestanding applications.

    Also note that realloc() is dangerous in case you overwrite the old pointer with the result of realloc(). In case the function fails, you create a leak.

    References: MISRA-C:2012 rule 21.3, Why should I not use dynamic memory allocation in embedded systems?

  • system()
    Comes with lots of overhead and although portable, it is often better to use system-specific API functions instead. Comes with various poorly-defined behavior. References: CERT C ENV33-C.

string.h

  • strcat()
    See remarks for strcpy().
  • strcpy()
    Perfectly fine to use, unless the size of the data to be copied is unknown or larger than the destination buffer. If no check of the incoming data size is done, there may be buffer overruns. Which is no fault of strcpy() itself, but of the calling application - that strcpy() is unsafe is mostly a myth created by Microsoft. References: Is strcpy dangerous and what should be used instead?
  • strtok()
    Modifies the caller string and uses internal state variables, which could make it unsafe in a multi-threaded environment.

This post was originally written by me here. It has been updated here and with some links to Codidact content. I won't maintain the SO post any longer.

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.

3 comment threads

strncat(3) (1 comment)
Add short description of functions. (5 comments)
I think this post would benefit a great deal with more suggestions of alternative. After all, you're ... (4 comments)
strncat(3)
alx‭ wrote over 1 year ago · edited over 1 year ago

strncat(3) is a good function. It's just that is has been misused. I thought it was a useless broken-by-design function, until I found by chance a good use of it in groff(1)'s source code (https://git.savannah.gnu.org/cgit/groff.git/tree/src/roff/troff/input.cpp?id=f720813c5f512627a246115a255989ad68dff395#n7895). Moreover, it's hard to replace it in such cases (you can, but you complicate the code unnecessarily). You can think of it as a function that does this: concatenate a null-padded character sequence into a string.

See the manual page for it, which I rewrote recently; maybe it convinces you: https://mirrors.edge.kernel.org/pub/linux/docs/man-pages/book/man-pages-6.04.01.pdf#strncat_3.

Of course, it's a niche function and it shouldn't be called as if it were strlcat(3). If one wants strlcat(3), that's what it should call (or another similar function like stpecpy() (https://github.com/shadow-maint/shadow/blob/master/lib/stpecpy.h)).