Versions Compared

Key

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

...

In this noncompliant code example, input_str is copied into dynamically allocated memory referenced by str. If malloc() fails, it returns a null pointer that is assigned to str. When str is dereferenced in memcpy(), the program behaves in an unpredictable manner.

Code Block
bgColor#FFCCCC
langc
size_t size = strlen(input_str)+1;
str = (char *)malloc(size);
memcpy(str, input_str, size);
/* ... */
free(str);
str = NULL;

...

To correct this error, ensure the pointer returned by malloc() is not null. This also ensures compliance with rule MEM32-C. Detect and handle memory allocation errors.

Code Block
bgColor#ccccff
langc
size_t size = strlen(input_str)+1;
str = (char *)malloc(size);
if (str == NULL) {
  /* Handle Allocation Error */
}
memcpy(str, input_str, size);
/* ... */
free(str);
str = NULL;

...

Wiki Markup
This noncompliant code example can be found in {{drivers/net/tun.c}} and affects Linux kernel 2.6.30 \[[Goodin 2009|AA. Bibliography#Goodin 2009]\].

Code Block
bgColor#FFCCCC
langc
static unsigned int tun_chr_poll(struct file *file, poll_table * wait)  {
  struct tun_file *tfile = file->private_data;
  struct tun_struct *tun = __tun_get(tfile);
  struct sock *sk = tun->sk;
  unsigned int mask = 0;

  if (!tun)
    return POLLERR;

  DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name);

  poll_wait(file, &tun->socket.wait, wait);

  if (!skb_queue_empty(&tun->readq))
    mask |= POLLIN | POLLRDNORM;

  if (sock_writeable(sk) ||
     (!test_and_set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags) &&
     sock_writeable(sk)))
    mask |= POLLOUT | POLLWRNORM;

  if (tun->dev->reg_state != NETREG_REGISTERED)
    mask = POLLERR;

  tun_put(tun);
  return mask;
}

...

This compliant solution eliminates the null pointer deference by initializing sk to tun->sk following the null pointer check.

Code Block
bgColor#ccccff
langc
static unsigned int tun_chr_poll(struct file *file, poll_table * wait)  {
  struct tun_file *tfile = file->private_data;
  struct tun_struct *tun = __tun_get(tfile);
  struct sock *sk;
  unsigned int mask = 0;

  if (!tun)
    return POLLERR;

  sk = tun->sk;

  DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name);

  poll_wait(file, &tun->socket.wait, wait);

  if (!skb_queue_empty(&tun->readq))
    mask |= POLLIN | POLLRDNORM;

  if (sock_writeable(sk) ||
     (!test_and_set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags) &&
     sock_writeable(sk)))
    mask |= POLLOUT | POLLWRNORM;

  if (tun->dev->reg_state != NETREG_REGISTERED)
    mask = POLLERR;

  tun_put(tun);
  return mask;
}

...