Unsafe C and C++ String Functions: strcpy, strcat, gets, and sprintf

strcpy, strcat, gets, and sprintf all write into a destination buffer without knowing how large it is. If the input is longer than expected, they keep writing — past the end of the buffer and over whatever lives next to it in memory. That is the classic buffer overflow, and it remains one of the most exploited classes of bug in native code. This guide explains each function’s risk, the safer replacement, and how to find every call in a C or C++ codebase.

Video explainer (1:42) · Watch with transcript

Why these functions are dangerous

  • gets reads a line of input with no length limit at all — it was removed from the C11 standard for this reason
  • strcpy copies until it finds a terminating null, regardless of destination size
  • strcat appends the same way, so the risk grows with every call
  • sprintf formats into a buffer with no bound, and formatted output length is easy to underestimate

Before: an overflow waiting for long input

void greet(const char* name) {
    char message[32];
    strcpy(message, "Hello, ");
    strcat(message, name);          // overflows if name is long
    printf("%s\n", message);
}

After: bounded writes or std::string

In C++, std::string manages its own size and removes the whole class of problem. In C or performance-sensitive code, use bounded functions and check the result.

void greet(const std::string& name) {
    std::string message = "Hello, " + name;
    std::cout << message << '\n';
}
void greet(const char* name) {
    char message[32];
    int n = snprintf(message, sizeof message, "Hello, %s", name);
    if (n < 0 || (size_t)n >= sizeof message) {
        /* handle truncation */
    }
    puts(message);
}

Replacement cheat sheet

  • gets → fgets(buf, sizeof buf, stdin), or std::getline in C++
  • sprintf → snprintf with sizeof the destination
  • strcpy / strcat → std::string, or bounded copies (strncpy_s / strcat_s where available) with explicit size checks
  • Raw char arrays for text → std::string or std::string_view

Finding every unsafe call in a codebase

A text search finds the obvious calls, but legacy native code often has hundreds of them spread across modules nobody has opened in years. CodeInspector flags strcpy, strcat, gets, and sprintf calls in C and C++ files as Critical “unsafe memory pattern” findings with exact line numbers, alongside other C++ checks for long functions, deep nesting, too many parameters, large classes, missing error handling, and hardcoded credentials.

Run a scan on a GitHub repository at https://codeinspector.app and export the PDF report to plan the clean-up module by module.

Related