...
In the first noncompliant code example, ntbs
is null terminated before the call to strncpy()
. However, the subsequent execution of strncpy()
can overwrite the null-termination character.
Code Block |
---|
|
char ntbs[NTBS_SIZE];
ntbs[sizeof(ntbs)-1] = '\0';
strncpy(ntbs, source, sizeof(ntbs));
|
Wiki Markup |
---|
In the second noncompliant code example, {{memset()}} is used to clear the destination buffer; unfortunately, the third argument incorrectly specifies the size of the destination array \[[Schwarz 2005|AA. Bibliography#Schwarz 05]\]. |
Code Block |
---|
|
char ntbs[NTBS_SIZE];
memset(ntbs, 0, sizeof(ntbs)-1);
strncpy(ntbs, source, sizeof(ntbs)-1);
|
...
The correct solution depends on the programmer's intent. If the intent was to truncate a string while ensuring that the result remains a null-terminated string, this solution can be used:
Code Block |
---|
|
char ntbs[NTBS_SIZE];
strncpy(ntbs, source, sizeof(ntbs)-1);
ntbs[sizeof(ntbs)-1] = '\0';
|
...
If the intent is to copy without truncation, this example copies the data and guarantees that the resulting null-terminated byte string is null terminated. If the string cannot be copied, it is handled as an error condition.
Code Block |
---|
|
char *source = "0123456789abcdef";
char ntbs[NTBS_SIZE];
/* ... */
if (source) {
if (strlen(source) < sizeof(ntbs)) {
strcpy(ntbs, source);
}
else {
/* handle string too large condition */
}
}
else {
/* handle NULL string condition */
}
|
...
Wiki Markup |
---|
The {{strncpy_s()}} function copies up to {{n}} characters from the source array to a destination array \[[TR 24731|AA. Bibliography#ISO/IEC TR 24731-1-2007]\]. If no null character was copied from the source array, then the {{n{}}}th position in the destination array is set to a null character, guaranteeing that the resulting string is null-terminated. |
Code Block |
---|
|
char *source;
char a[NTBS_SIZE];
/* ... */
if (source) {
errno_t err = strncpy_s(a, sizeof(a), source, 5);
if (err != 0) {
/* Handle error */
}
}
else {
/* handle NULL string condition */
}
|
...
The following noncompliant code example fails to ensure that cur_msg
is properly null terminated:
Code Block |
---|
|
char *cur_msg = NULL;
size_t cur_msg_size = 1024;
/* ... */
void lessen_memory_usage(void) {
char *temp;
size_t temp_size;
/* ... */
if (cur_msg != NULL) {
temp_size = cur_msg_size/2 + 1;
temp = realloc(cur_msg, temp_size);
if (temp == NULL) {
/* Handle error condition */
}
cur_msg = temp;
cur_msg_size = temp_size;
}
}
/* ... */
|
...
In this compliant solution, the lessen_memory_usage()
function ensures that the resulting string is always properly null terminated.
Code Block |
---|
|
char *cur_msg = NULL;
size_t cur_msg_size = 1024;
/* ... */
void lessen_memory_usage(void) {
char *temp;
size_t temp_size;
/* ... */
if (cur_msg != NULL) {
temp_size = cur_msg_size/2 + 1;
temp = realloc(cur_msg, temp_size);
if (temp == NULL) {
/* Handle error condition */
}
cur_msg = temp;
cur_msg_size = temp_size;
/* ensure string is null-terminated */
cur_msg[cur_msg_size - 1] = '\0';
}
}
/* ... */
|
...