Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Simplified examples.

...

The width and precision arguments to sprintfprintf() format directives must be of type int. According to C99:

...

Passing them as any other type leads to undefined behavior. In this noncompliant code example, the width and precision are specified using parameters declared to be of size_t type. These are unsigned types that may not be the same size as int.

Code Block
bgColor#ffcccc
char *fmtintint print_int(int i, size_t width, size_t prec) {
  int n;
  char *buf;
  const char fmt[] n = printf("%*.*d";

  /* determine the size of the buffer */
  n = snprintf(NULL, 0, fmt, width, prec, i);

  /* check for snprintf() failure */
  if (n < 0) {
    return NULL;
  }

  /* check for malloc() failure */
  buf = (char *)malloc(n + 1);
  if (NULL == buf) {
    return NULL;
  }

  /* check again for snprintf() failure */
  n = snprintf(buf, n + 1, fmt, width, prec, i);
  if (n < 0) {
    free(buf);
    buf = NULL;
  }

  return buf;
}

Compliant Solution

In this compliant solution, the field width and precision arguments to sprintfprintf() format directives are of type int.

Code Block
bgColor#ccccff
char *fmtintint print_int(int i, int width, int prec) {
  int n;
  char *buf;
  const char fmt[] n = printf("%*.*d";

  /* determine the size of the buffer */
  n = snprintf(NULL, 0, fmt, width, prec, i);

  /* check for snprintf() failure */
  if (n < 0) {
    return NULL;
  }

  /* check for malloc() failure */
  buf = (char *)malloc(n + 1);
  if (NULL == buf) {
    return NULL;
  }

  /* check again for snprintf() failure */
  n = snprintf(buf, n + 1, fmt, width, prec, i);
  if (n < 0) {
    free(buf);
    buf = NULL;
  }

  return buf;
}

Risk Assessment

In most cases, incorrectly specified format strings will result in abnormal program termination.

...