Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Edited by sciSpider (sch jbop) (X_X)@==(Q_Q)@

...

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
bgColor#FFCCCC
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
bgColor#ccccff
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
bgColor#ccccff
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);
}

...