C/C++ Patterns

45+ vulnerability patterns for C and C++ applications including buffer overflows, memory corruption, and format string vulnerabilities.

Memory Safety Critical

C/C++ require careful memory management. These patterns represent the most common sources of security vulnerabilities in native code.

Overview

Bloodhound provides comprehensive analysis for C and C++ code, detecting memory safety issues, undefined behavior, and common vulnerability patterns.

15
Critical
14
High
10
Medium
6
Low

Buffer Overflow

Critical

Stack Buffer Overflow

Writing beyond stack buffer bounds enables code execution.

Vulnerable
C
1// Vulnerable: No bounds checking
2void greet(char *name) {
3 char buffer[64];
4 strcpy(buffer, name); // No size limit!
5 printf("Hello, %s\n", buffer);
6}
Secure
C
1// Secure: Use strncpy with size limit
2void greet(char *name) {
3 char buffer[64];
4 strncpy(buffer, name, sizeof(buffer) - 1);
5 buffer[sizeof(buffer) - 1] = '\0';
6 printf("Hello, %s\n", buffer);
7}
Critical

Heap Buffer Overflow

Overflowing heap buffers can corrupt heap metadata.

Vulnerable
C
1// Vulnerable: Insufficient allocation
2char *copy_input(const char *input) {
3 char *buf = malloc(strlen(input)); // Missing +1 for null
4 strcpy(buf, input);
5 return buf;
6}
Secure
C
1// Secure: Include null terminator
2char *copy_input(const char *input) {
3 size_t len = strlen(input) + 1;
4 char *buf = malloc(len);
5 if (buf) memcpy(buf, input, len);
6 return buf;
7}

Memory Corruption

Critical

Use After Free

Accessing memory after deallocation leads to undefined behavior.

Vulnerable
C
1// Vulnerable: Use after free
2void process() {
3 char *data = malloc(100);
4 free(data);
5 strcpy(data, "test"); // Use after free!
6}
Secure
C
1// Secure: Nullify pointer after free
2void process() {
3 char *data = malloc(100);
4 // ... use data ...
5 free(data);
6 data = NULL; // Prevent accidental use
7}
Critical

Double Free

Freeing the same memory twice corrupts heap metadata.

Vulnerable
C
1// Vulnerable: Double free
2void cleanup(char *ptr) {
3 free(ptr);
4}
5void process() {
6 char *data = malloc(100);
7 cleanup(data);
8 free(data); // Double free!
9}
Secure
C
1// Secure: Track ownership, use smart pointers in C++
2void cleanup(char **ptr) {
3 if (*ptr) {
4 free(*ptr);
5 *ptr = NULL;
6 }
7}
High

Null Pointer Dereference

Dereferencing NULL causes crashes or security issues.

Vulnerable
C
1// Vulnerable: No NULL check
2void process(struct data *d) {
3 printf("%s\n", d->name); // Crashes if d is NULL
4}
Secure
C
1// Secure: Validate pointers
2void process(struct data *d) {
3 if (d == NULL || d->name == NULL) return;
4 printf("%s\n", d->name);
5}

Format String

Critical

Format String Vulnerability

User-controlled format strings enable memory read/write.

Vulnerable
C
1// Vulnerable: User input as format string
2void log_message(char *user_input) {
3 printf(user_input); // User can read stack with %x
4}
Secure
C
1// Secure: Use format specifier
2void log_message(char *user_input) {
3 printf("%s", user_input);
4}

Integer Vulnerabilities

High

Integer Overflow

Arithmetic overflow wraps around, causing unexpected behavior.

Vulnerable
C
1// Vulnerable: Overflow in size calculation
2void *alloc(size_t count, size_t size) {
3 size_t total = count * size; // Can overflow!
4 return malloc(total);
5}
Secure
C
1// Secure: Check for overflow
2void *alloc(size_t count, size_t size) {
3 if (count > SIZE_MAX / size) return NULL;
4 return malloc(count * size);
5}
Medium

Signed/Unsigned Mismatch

Mixing signed and unsigned types causes unexpected comparisons.

Vulnerable
C
1// Vulnerable: Signed used as size
2void process(int size) {
3 if (size > MAX_SIZE) return; // Negative bypasses check
4 char *buf = malloc(size); // Huge allocation!
5}
Secure
C
1// Secure: Use size_t for sizes
2void process(size_t size) {
3 if (size > MAX_SIZE) return;
4 char *buf = malloc(size);
5}

Modern C++ Practices

Prefer smart pointers (unique_ptr, shared_ptr), std::string, std::vector, and RAII patterns over raw pointers and manual memory management.