Detect C++ buffer overflows in POSIX functions

by g. ann campbell|

Buffer overflows have been responsible for some of the most notorious crashes, worms, and hacks for more than 30 years, including the Morris worm, the Code Red worm, and the ping of death. More recently, VPNs have been compromised via buffer overflow; an overflow-related code execution flaw was found in macOS Mojave (fixed in Catalina); and a WhatsApp buffer overflow exposed users' private messages, location, and even camera and mic feeds. In short, buffer overflows aren't just bugs that could crash your program; they also represent serious threats to security. That's why we're excited to announce the availability of a new C and C++ rule to detect overflows in most POSIX functions: S5782, "POSIX functions should not be called with arguments that trigger buffer overflows".

We wrote some test code to demonstrate the types of issues raised by this rule:

You can see from the screenshot that a buffer overflow issue is raised at line 17, but let's take a closer look. The godbolt.org compiler explorer shows what happens when the code is run:

The idea was to write the binary content  of the `abc struct`. What's written instead is some apparent garbage (this is actually the address of the `struct` as read from the `ptr` variable on line 23), followed by the contents of the `secret` variable, which is declared on line 24, followed by some random garbage left over in memory. This all happens because the Address of Operator (`&`) is used in error in the write call:

void f_wrong(const ABC *abc) {
    const size_t size = sizeof(ABC);
    write(1, &abc, size);
}

Instead of writing out the contents of the struct, the call writes its addressand whatever's stored in the 68 bytes after that. Why 68 bytes? Well, as you can see from the issue message in the first screenshot, the `struct` is 76 bytes long on this architecture but its address is only 8 bytes. That means that whatever happens to be in the following 68 bytes in memory will also be printed out. Unfortunately, in this case it happens to be sensitive data. 

Rule S5782 is able to detect that `&abc` is shorter than the number of bytes to print out and raises an issue to report the buffer over-read. The rule covers both over-reads and over-writes via 97 of the 132 functions in the POSIX standard that manipulate buffers. 

This new rule is classified as a Security Vulnerability rule because as we've just seen, while buffer overflows are bugs, at the same time they can represent real security threats. S5782 comes in addition to the one you may already be familiar with: S3519, "Memory access should be explicitly bounded to prevent buffer overflows". Together they cover most cases, with coverage of the remaining POSIX functions expected soon. S5782 is available in SonarCloud and in SonarQube commercial editions starting in version 8.3.