You forgot to leave room for the null character

char final[33];
strncpy(final,md5S,32);
final[32] = '\0';
Answer from rouzier on Stack Overflow
🌐
Reddit
reddit.com › r/c_programming › safest way to copy a string?
r/C_Programming on Reddit: Safest way to copy a string?
May 7, 2023 -

I just fell foul of the fact that strncpy does not add an old terminator if the destination buffer is shorter than the source string. Is there a single function standard library replacement that I could drop in to the various places strncpy is used that would copy a null terminated string up to the length of the destination buffer, guaranteeing early (but correct) termination of the destination string, if the destination buffer is too short?

Edit:

  • Yes, I do need C-null terminated strings. This C API is called by something else that provides a buffer for me to copy into, with the expectation that it’s null terminated

Edit 2:

  • I know I can write a helper function that’s shared across relevant parts of the code, but I don’t want to do that because then each of those modules that need the function becomes coupled to a shared helper header file, which is fine in isolation but “oh I want to use this code in another project, better make sure I take all the misc dependencies” is best avoided. Necessary if necessary, but if possible using a standard function, even better.

Discussions

Implementing a string copy function in C - Stack Overflow
My point is that there aren't many times when you are okay with getting a possibly truncated string copied. In this case, for example, you would know the length of the source string and allocate the destination string with the right size. Most of the times, the advice to use strncpy() because ... More on stackoverflow.com
🌐 stackoverflow.com
string - Copying n chars with strncpy more efficiently in C - Stack Overflow
Firstly, for strncpy, "No null-character is implicitly appended to the end of destination, so destination will only be null-terminated if the length of the C string in source is less than num." We use memcpy() because strncpy() checks each byte for 0 on every copy. More on stackoverflow.com
🌐 stackoverflow.com
Statically copy C-string of variable length - Stack Overflow
I don't wish to simply set temp_cpy ... modified within the function, but input_str should remain intact. ... You must have storage space somewhere for the contents of your string copy. There is no magical way to make a copy of something, that doesn't require additional storage. This however can be on the stack, as apposed to the heap, using a variable-length ... More on stackoverflow.com
🌐 stackoverflow.com
c++ - Proper way to copy C strings - Stack Overflow
The man page in linux even states this. As long as you check the length first it's fine. If not something is wrong anyway as non NUL terminated strings is a very bad thing. The advice is well intended but it always misses the problem with not NUL terminating the string. More on stackoverflow.com
🌐 stackoverflow.com
🌐
TutorialsPoint
tutorialspoint.com › c_standard_library › c_function_strncpy.htm
C library - strncpy() function
#include <stdio.h> #include <string.h> void customStrncpy(char* dest, const char* src, size_t n) { size_t i; for (i = 0; i < n && src[i] != '\0'; i++) { dest[i] = src[i]; } while (i < n) { // Fill remaining characters with null terminators dest[i] = '\0'; i++; } } int main() { char source[] = "String Copy!"; // Fixed length char destination[15]; customStrncpy(destination, source, 10); printf("Custom copied string: %s\n", destination); return 0; }
🌐
Sternum IoT
sternumiot.com › home › strcpy and strncpy c functions – syntax, examples, and security best practices
strcpy and strncpy C Functions | Syntax, Examples & Security Best Practices | Sternum IoT
January 30, 2024 - Original value of destination: "Original text" Current value of destination after running strcpy: "Final text" As mentioned, the main distinction between these two functions lies in how they manage string length during the copy process: strcpy() transfers the source string (including its null-terminator) into the destination buffer without regard for the size of either buffer.
🌐
W3Resource
w3resource.com › c-programming › string › c-strncpy.php
C strncpy() function
3 weeks ago - C strncpy() function (string.h): The strncpy() function is used to copy n characters of string2 to string1. If n is less than or equal to the length of string2, a null character (\0) is not appended to the copied string.
🌐
Cplusplus
cplusplus.com › reference › string › string › copy
std::string::copy
Copies a substring of the current value of the string object into the array pointed by s. This substring contains the len characters that start at position pos.
Find elsewhere
🌐
Mafford
mafford.com › text › the-many-ways-to-copy-a-string-in-c
The many ways to copy a string in C — Martyn Afford
The only way to avoid this security issue while continuing to use strcpy is to make sure the source is a valid C string, its length is known and it's shorter than the destination buffer[1]. For instance, it would be perfectly safe to strcpy a constant string of known length into a suitably sized buffer. However, as the multitude of other copying functions highlights, there are many contexts that require better solutions. After the issues with strcpy, this standard function offers hope with its extra length parameter.
🌐
Programiz
programiz.com › c-programming › examples › string-copy
C Program to Copy String Without Using strcpy()
However, in this example, we will copy a string manually without using the strcpy() function. #include <stdio.h> int main() { char s1[100], s2[100], i; printf("Enter string s1: "); fgets(s1, sizeof(s1), stdin); for (i = 0; s1[i] != '\0'; ++i) { s2[i] = s1[i]; } s2[i] = '\0'; printf("String ...
🌐
DEV Community
dev.to › sjmulder › string-copy-in-c-38k9
String copy in C - DEV Community
August 12, 2023 - void strcpy_1(char *src, char *dst) { size_t len, i; len = strlen(src); for (i=0; i < len; i++) dst[i] = src[i]; dst[len] = '\0'; } We find the length of the string, then copy it over one char at a time.
🌐
Scaler
scaler.com › home › topics › c strcpy()
C strcpy() - Scaler Topics
July 14, 2024 - Suppose in any situation you want to copy the content of one string to another string without deleting the original string. You can use the strcpy() function instead of any looping statements.
Top answer
1 of 6
6

I wouldn't use strncpy for this at all. At least if I understand what you're trying to do, I'd probably do something like this:

char *duplicate(char *input, size_t max_len) {
    // compute the size of the result -- the lesser of the specified maximum
    // and the length of the input string. 
    size_t len = min(max_len, strlen(input));

    // allocate space for the result (including NUL terminator).
    char *buffer = malloc(len+1);

    if (buffer) {
        // if the allocation succeeded, copy the specified number of 
        // characters to the destination.
        memcpy(buffer, input, len);
        // and NUL terminate the result.
        buffer[len] = '\0';
    }
    // if we copied the string, return it; otherwise, return the null pointer 
    // to indicate failure.
    return buffer;
}
2 of 6
3

Firstly, for strncpy, "No null-character is implicitly appended to the end of destination, so destination will only be null-terminated if the length of the C string in source is less than num."

We use memcpy() because strncpy() checks each byte for 0 on every copy. We already know the length of the string, memcpy() does it faster.

First calculate the length of the string, then decide on what to allocate and copy

int max = 5;               // No more than 5 characters

int len = strlen(string);  // Get length of string
int to_allocate = (len > max ? max : len); // If len > max, it'll return max. If len <= max, it'll return len. So the variable will be bounded within 0...max, whichever is smaller

char *str = malloc(to_allocate + 1); // Only allocate as much as we need to
if (!str) { // handle bad allocation here }

memcpy(str,string,to_allocate); // We don't need any if's, just do the copy. memcpy is faster, since we already have done strlen() we don't need strncpy's overhead

str[to_allocate] = 0; // Make sure there's a null terminator
Top answer
1 of 2
2

You must have storage space somewhere for the contents of your string copy. There is no magical way to make a copy of something, that doesn't require additional storage.

This however can be on the stack, as apposed to the heap, using a variable-length array.

strlen and strcpy can be used to accomplish this:

void foo(const char *input_str)
{
    char temp[strlen(input_str) + 1];
    strcpy(temp, str);
    /* ... */
}

If your platform does not support VLAs, you must use heap memory. The strdup function is usually available. If it is not, it can be replicated easily with malloc. You must remember to free this memory when you are finished with it.

void foo(const char *input_str)
{
    char *temp = strdup(input_str);
    /* ... */
    free(temp);
}

or

void foo(const char *input_str)
{
    char *temp = malloc(strlen(input_str) + 1);
    strcpy(temp, input_str);
    /* ... */
    free(temp);
}

If your platform does not support VLAs, and you really can not use the heap for some reason, the only option left is a buffer of a predetermined maximum length. This is a special case, and should be avoided, if possible, as it creates additional limitations you must keep track of.

#define MAX_FOO_BUFSZ 255

void foo(const char *input_str)
{                         
    char buffer[MAX_FOO_BUFSZ + 1] = { 0 };
    strncpy(buffer, input_str, MAX_FOO_BUFSZ);    
    
    /* ... */
} 
2 of 2
0

You can also use strdup function (it is POSIX but it is supported by most implementations)

char *foo(const char *input_str)
{
    char *temp = strdup(input_str);
    if(temp)
    {
        // do some stuff
    }
    return temp;
}

Remember to free the allocated memory when not needed.

🌐
GeeksforGeeks
geeksforgeeks.org › c language › strncpy-function-in-c
strncpy() Function in C - GeeksforGeeks
August 5, 2024 - Time Complexity: O(n), where n is the number of characters to be copied. Auxiliary Space: O(1) The below example demonstrates how to use strncpy() to copy a fixed-length substring from the source string into the destination string.
🌐
IBM
ibm.com › docs › en › zos › 2.4.0
strncpy() — Copy string
We cannot provide a description for this page right now
🌐
GeeksforGeeks
geeksforgeeks.org › c++ › different-ways-to-copy-a-string-in-c-c
Different ways to copy a string in C/C++ - GeeksforGeeks
July 23, 2025 - The main difference is that memcpy() always copies the exact number of specified bytes. strcpy() and other str methods, on the other hand, will copy until it reads a NULL ('\0') byte, and then stop after that. strcpy() is not intended to be used with zero-terminated C-strings. memcpy() is hardware optimized and copies faster and works with any type of source data (like binary or encrypted bytes). strcpy() should never be used unless for any specific reason, and if you know the lengths of the strings, memcpy() is a better choice.
🌐
CodinGame
codingame.com › playgrounds › 14213 › how-to-play-with-strings-in-c › string-copy
String Copy - How to play with strings in C
CodinGame is a challenge-based training platform for programmers where you can play with the hottest programming topics. Solve games, code AI bots, learn from your peers, have fun.
🌐
C For Dummies
c-for-dummies.com › blog
To Copy or to Duplicate a String | C For Dummies Blog
December 26, 2015 - A second string copying function is available in some C language libraries, strdup(). It works similar to the strcpy() function, but you need only supply a char pointer as the first argument. The function itself allocates space for the duplicate string. This function is better than strcpy() ...
Top answer
1 of 4
30

You could use strdup() to return a copy of a C-string, as in:

#include <string.h>

const char *stringA = "foo";
char *stringB = NULL;

stringB = strdup(stringA);
/* ... */
free(stringB);
stringB = NULL; 

You could also use strcpy(), but you need to allocate space first, which isn't hard to do but can lead to an overflow error, if not done correctly:

#include <string.h>

const char *stringA = "foo";
char *stringB = NULL;

/* you must add one to cover the byte needed for the terminating null character */
stringB = (char *) malloc( strlen(stringA) + 1 ); 
strcpy( stringB, stringA );
/* ... */
free(stringB);
stringB = NULL;

If you cannot use strdup(), I would recommend the use of strncpy() instead of strcpy(). The strncpy() function copies up to — and only up to — n bytes, which helps avoid overflow errors. If strlen(stringA) + 1 > n, however, you would need to terminate stringB, yourself. But, generally, you'll know what sizes you need for things:

#include <string.h>

const char *stringA = "foo";
char *stringB = NULL;

/* you must add one to cover the byte needed for the terminating null character */
stringB = (char *) malloc( strlen(stringA) + 1 ); 
strncpy( stringB, stringA, strlen(stringA) + 1 );
/* ... */
free(stringB);
stringB = NULL;

I think strdup() is cleaner, myself, so I try to use it where working with strings exclusively. I don't know if there are serious downsides to the POSIX/non-POSIX approach, performance-wise, but I am not a C or C++ expert.

Note that I cast the result of malloc() to char *. This is because your question is tagged as a c++ question. In C++, it is required to cast the result from malloc(). In C, however, you would not cast this.

EDIT

There you go, there's one complication: strdup() is not in C or C++. So use strcpy() or strncp() with a pre-sized array or a malloc-ed pointer. It's a good habit to use strncp() instead of strcpy(), wherever you might use that function. It will help reduce the potential for errors.

2 of 4
4

If I just initialize stringB as char *stringB[23], because I know I'll never have a string longer than 22 characters (and allowing for the null terminator), is that the right way?

Almost. In C, if you know for sure that the string will never be too long:

char stringB[MAX+1];
assert(strlen(stringA) <= MAX));
strcpy(stringB, stringA);

or, if there's a possibility that the string might be too long:

char stringB[MAX+1];
strncpy(stringB, stringA, MAX+1);
if (stringB[MAX] != '\0') {
    // ERROR: stringA was too long.
    stringB[MAX] = '\0'; // if you want to use the truncated string
}

In C++, you should use std::string, unless you've proved that the overhead is prohibitive. Many implementations have a "short string optimisation", which will avoid dynamic allocation for short strings; in that case, there will be little or no overhead over using a C-style array. Access to individual characters is just as convenient as with a C-style array; in both cases, s[i] gives the character at position i as an lvalue. Copying becomes stringB = stringA; with no danger of undefined behaviour.

If you really do find that std::string is unusable, consider std::array<char,MAX+1>: a copyable class containing a fixed-size array.

If stringB is checked for equality with other C-strings, will the extra space affect anything?

If you use strcmp, then it will stop at the end of the shortest string, and will not be affected by the extra space.