...
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 |
---|
|
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 |
---|
|
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 |
---|
|
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 |
---|
|
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;
}
|
...