Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

This specific noncompliant code example is from the Linux Kernel Mailing List archive site, although similar examples are common.

Code Block
bgColor#FFCCCC
langc
int i;
ssize_t count = 0;

for (i = 0; i < 9; ++i) {
  count += sprintf(
    buf + count, "%02x ", ((u8 *)&slreg_num)[i]
  );
}
count += sprintf(buf + count, "\n");

...

Wiki Markup
This compliant solution shows the redesigned API for {{sprintf()}} from the CERT managed string library \[[Burch 2006|AA. Bibliography#Burch06]\].

Code Block
bgColor#ccccff
langc
errno_t sprintf_m(
  string_m buf, 
  const string_m fmt, 
  int *count, 
  ...
);

...

The previous code example can be amended as follows:

Code Block
bgColor#ccccff
langc
int i;
rsize_t count = 0;
errno_t err;

for (i = 0; i < 9; ++i) {
  err = sprintf_m(
    buf + count, "%02x ", &count, ((u8 *)&slreg_num)[i]
  );
  if (err != 0) {
    /* Handle print error */
  }
}
err = sprintf_m(
  buf + count, "%02x ", &count, ((u8 *)&slreg_num)[i]
);
if (err != 0) {
  /* Handle print error */
}

...

The ssize_t data type is designed as a "signed representation of size_t." Consequently, it is often used as a return type for functions that can return an unsigned value upon success and a negative value upon error. For instance, the POSIX read() function has the following signature:

Code Block
bgColor#FFCCCC
langc
ssize_t read(int fildes, void *buf, size_t nbyte);

...

An alternative hypothetical signature for the read() function would be

Code Block
bgColor#CCCCFF
langc
errno_t read(int fildes, void *buf, size_t nbyte, size_t* rbytes);

...

In this noncompliant code example, the error handler returns normally, while the strcpy_s() function's return value is not checked.

Code Block
bgColor#FFCCCC
langc
constraint_handler_t handle_errors(void) {
  constraint_handler_t data;
  /* define what to do when error occurs */
  return data;
}

/*...*/

set_constraint_handler(handle_errors);

/*...*/

/* Returns zero on success */
errno_t function(char *dst1){
  char src1[100] = "hello";

  strcpy_s(dst1, sizeof(dst1), src1);
  /* At this point strcpy_s may have yielded an
     error and handle_errors() might have returned */

  /* ... */
  return 0;
}

...

In this compliant solution, the error handler terminates the program, ensuring that strcpy_s() never returns unless it fully succeeds.

Code Block
bgColor#CCCCFF
langc
/*
 * The abort_handler_s() function writes a message on the
 * standard error stream and then calls the abort() function.
 */
set_constraint_handler(abort_handler_s);

/*...*/

/* Returns zero on success */
errno_t function(char *dst1){
  char src1[100] = "hello";

  strcpy_s(dst1, sizeof(dst1), src1);
  /* Because abort_handler_s() never returns,
     we only get here if strcpy_s() succeeds. */

  /* ... */
  return 0;
}

...