...
Code Block |
---|
errno_t strcpy_s( char * restrict s1, rsize_t s1max, char const char * restrict s2 ); |
The signature is similar to strcpy()
but takes an extra argument of type rsize_t
that specifies the maximum length of the destination buffer. (Functions that accept parameters of type rsize_t
diagnose a constraint violation if the values of those parameters are greater than RSIZE_MAX
. Extremely large object sizes are frequently a sign that an object's size was calculated incorrectly. For example, negative numbers appear as very large positive numbers when converted to an unsigned type like size_t
. For those reasons, it is sometimes beneficial to restrict the range of object sizes to detect errors. For machines with large address spaces, ISO/IEC TR 24731-1 recommends that RSIZE_MAX
be defined as the smaller of the size of the largest object supported or (SIZE_MAX >> 1)
, even if this limit is smaller than the size of some legitimate, but very large, objects. See also INT01-A. Use rsize_t or size_t for all integer values representing the size of an object.)
The semantics of strcpy_s()
are also similar to the semantics of strcpy()
. When there are no input validation errors, the strcpy_s()
function copies characters from a source string to a destination character array up to and including the terminating null NULL character. The function returns zero on success.
...
- The source and destination pointers are checked to see if they are nullNULL.
- The maximum length of the destination buffer is checked to see if it is equal to zero, greater than
RSIZE_MAX
, or less than or equal to the length of the source string. - Copying is not allowed between objects that overlap.
When a runtime-constraint violation is detected, the destination string is set to the null NULL string (as long as it is not a null NULL pointer and the maximum length of the destination buffer is greater than zero and not greater than RSIZE_MAX
) and the function returns a nonzero value. In the following example, the strcpy_s()
function is used to copy src1
to dst1
.
...
Wiki Markup |
---|
However, the call to copy {{src2}} to {{dst2}} fails because there is insufficient space available to copy the entire string, which consists of eight characters, to the destination buffer. As a result, {{r2}} is assigned a nonzero value and {{dst2\[0\]}} is set to the nullNULL character. |
Users of the ISO/IEC TR 24731-1 functions are less likely to introduce a security flaw because the size of the destination buffer and the maximum number of characters to append must be specified. ISO/IEC TR 24731 Part II (24731-2, in progress) will offer another approach, supplying functions that allocate enough memory for their results. ISO/IEC TR 24731 functions also ensure null NULL termination of the destination string.
...
The following non-compliant code overflows its buffer if msg
is too long, and has undefined behavior if msg
is a null NULL pointer.
Code Block | ||
---|---|---|
| ||
void complain(char const char *msg) { static char const char prefix[] = "Error: "; static char const char suffix[] = "\n"; char buf[BUFSIZ]; strcpy(buf, prefix); strcat(buf, msg); strcat(buf, suffix); fputs(buf, stderr); } |
...
Code Block | ||
---|---|---|
| ||
void complain(char const char *msg) { errno_t err; static char const char prefix[] = "Error: "; static char const char suffix[] = "\n"; char buf[BUFSIZ]; if ((err = strcpy_s(buf, sizeof(buf), prefix)) != 0) { /* handle error */ } if ((err = strcat_s(buf, sizeof(buf), msg)) != 0) { /* handle error */ } if ((err = strcat_s(buf, sizeof(buf), suffix)) != 0) { /* handle error */ } fputs(buf, stderr); } |
...
Code Block | ||
---|---|---|
| ||
void complain(char const char *msg) { errno_t err; static char const char prefix[] = "Error: "; static char const char suffix[] = "\n"; char buf[BUFSIZ]; /* Ensure that more than one character is available for msg. */ static_assert(sizeof(buf) > sizeof(prefix) + sizeof(suffix), "Buffer for complain() is too small"); strcpy(buf, prefix); if ((err = strcat_s(buf, sizeof(buf), msg)) != 0) { /* handle error */ } if ((err = strcat_s(buf, sizeof(buf), suffix)) != 0) { /* handle error */ } fputs(buf, stderr); } |
...