Some POSIX functions take one argument that is a buffer and another one that represents the size of the buffer. It is up to the developer to make
sure the two arguments do match and that the size argument does not exceed the buffer’s size.
Why is this an issue?
When the size argument exceeds the actual size of the buffer, the memory management functions will either read or write data past the buffer memory
boundary into adjacent memory. Because the memory might be uninitialized or contain other pieces of data, the behavior of the affected function can
not be predicted and will likely trigger bugs.
What is the potential impact?
Buffer boundaries violations can lead to serious security issues.
Information disclosure
In some scenarios, insecure functions can lead to information disclosure. For instance, if an attacker can cause a buffer overread, they might be
able to disclose data in memory that they’re not supposed to have access to. This could potentially allow them to access sensitive information, such
as passwords or encryption keys. An example of a buffer overread is provided with the Heartbleed vulnerability. ==== Code execution
In some cases, an attacker can craft input in a way that allows them to gain unauthorized access to your system. For example, they might be able to
overwrite a function’s return address in memory, causing your program to execute code of the attacker’s choosing. This could potentially give the
attacker full control over your system.
Denial of service
If an attacker can trigger a buffer overflow by providing oversized input, it can cause the program to crash. If the attacker repeats this process,
it can continually disrupt the service, denying access to other users. This can be particularly damaging for services that require high availability,
such as online platforms or databases.
In some cases, the input might cause the program to enter an infinite loop or consume excessive memory, slowing down the system or even causing it
to become unresponsive. This type of attack is known as a resource exhaustion DoS attack.
Exceptions
Functions related to sockets using the type socklen_t
are not checked. This is because these functions are using a C-style polymorphic
pattern using union
. It relies on a mismatch between allocated memory and sizes of structures and it creates false positives.
How to fix it
Code examples
In the following code example, memchr
is used to find the first occurrence of the @
character in a buffer,
array
. The second argument does not match the size of this buffer, so it may find an occurrence of the character after the end of the
buffer and read data it is not supposed to. If the returned pos
pointer is later used to write characters, this could unexpectedly
overwrite data.
Noncompliant code example
char array[10];
initialize(array);
char *pos = memchr(array, '@', 42); // Noncompliant
Compliant solution
char array[10];
initialize(array);
char *pos = memchr(array, '@', sizeof(array));
Resources
Articles & blog posts
Standards
External coding guidelines