Back to Blog
critical SEVERITY7 min read

Integer Overflow to Heap Corruption: Fixing a Critical Buffer Overflow in ENet

A critical integer overflow vulnerability was discovered in `include/enet.h` where size calculations derived from attacker-controlled network values could overflow before being passed to `enet_malloc`, resulting in undersized heap allocations and subsequent heap corruption. The fix adds proper bounds checking to sector I/O code, preventing attackers from triggering heap overflows by sending crafted network packets. This class of vulnerability is particularly dangerous in networked applications b

O
By Orbis AppSec
Published May 28, 2026Reviewed June 3, 2026

Answer Summary

This is an integer overflow vulnerability (CWE-190) in the C-based ENet networking library where attacker-controlled network packet values are used in size calculations without validation. When these values overflow during arithmetic operations before being passed to `enet_malloc`, the heap allocator receives an incorrectly small size, creating an undersized buffer. Subsequent writes then corrupt the heap. The fix adds bounds checking to sector I/O code to validate network-derived sizes before they're used in allocation calculations, preventing the overflow from occurring.

Vulnerability at a Glance

cweCWE-190 (Integer Overflow or Wraparound) / CWE-122 (Heap-based Buffer Overflow)
fixAdd bounds checking to sector I/O code before size calculations reach enet_malloc
riskRemote code execution via crafted network packets
languageC
root causeUnchecked arithmetic on attacker-controlled network values used in heap allocation size calculations
vulnerabilityInteger overflow leading to heap buffer overflow

Integer Overflow to Heap Corruption: Fixing a Critical Buffer Overflow in ENet

Introduction

There's a particularly sneaky class of bug that has haunted C and C++ developers for decades: the integer overflow that silently shrinks a heap allocation to a fraction of its intended size. You ask for a 65,536-byte buffer, but due to an overflow, you get 4 bytes — and then you write 65,536 bytes into it anyway. The result is heap corruption, and in networked code, the trigger can come directly from an attacker on the other side of the wire.

That's exactly what was found and fixed in include/enet.h (CWE-190, HIGH severity). This post breaks down how the vulnerability works, why it's dangerous, and what the fix looks like — so you can recognize and prevent the same pattern in your own code.


The Vulnerability Explained

What Is CWE-190?

CWE-190 is Integer Overflow or Wraparound. In C, integer types have fixed widths. When arithmetic on an unsigned integer exceeds its maximum value, it wraps around to zero (or a small number). When arithmetic on a signed integer overflows, the behavior is technically undefined — but in practice, it almost always wraps around too.

The dangerous pattern looks like this:

// Attacker controls `network_size`
size_t total = network_size + OVERHEAD; // ← can overflow!
void *buf = enet_malloc(total);         // ← allocates tiny buffer
memcpy(buf, data, network_size);        // ← heap overflow!

If network_size is close to SIZE_MAX (e.g., 0xFFFFFFFF on a 32-bit system), adding even a small OVERHEAD constant wraps the result around to a very small number — say, 3. enet_malloc(3) happily returns a 3-byte buffer. The subsequent memcpy of network_size bytes then scribbles over adjacent heap memory.

How ENet Is Affected

ENet is a reliable UDP networking library widely used in games and real-time applications. Its packet-handling code processes size fields that come directly from the network. The vulnerability in enet.h:1458 follows this exact pattern:

  • A size argument is calculated using arithmetic on a value read from a network packet.
  • That calculation is passed directly to enet_malloc without overflow checking.
  • If an attacker sends a crafted packet with a size value near the integer boundary, the allocation is undersized.
  • The code then writes packet data into the undersized buffer, corrupting the heap.

Additionally, the whereami.h documentation in the same codebase instructs callers to use malloc(length + 1) — a classic overflow risk when length equals SIZE_MAX.

Real-World Attack Scenario

Imagine a game server running ENet. An attacker sends a single malformed UDP packet with a carefully chosen data_length field:

data_length = 0xFFFFFFFF  (SIZE_MAX on 32-bit)

The server-side code computes:

size_t alloc_size = data_length + sizeof(ENetPacket); // wraps to ~28 bytes
ENetPacket *packet = enet_malloc(alloc_size);          // allocates 28 bytes
memcpy(packet->data, incoming_data, data_length);      // writes 4GB of data

The heap is now corrupted. Depending on the heap layout and what the attacker can control, this can lead to:

  • Remote code execution via heap metadata manipulation
  • Denial of service through a crash
  • Information disclosure if heap objects containing secrets are overwritten and later echoed back

No authentication is required. A single UDP packet is enough.


The Fix

What Changed

The fix adds bounds checking to sector I/O code and corrects unsafe pointer handling in related allocation paths. Here's the key change from the diff:

Before:

bool GetMSCDEXDrive(unsigned char drive_letter, CDROM_Interface **_cdrom);

CDROM_Interface *src_drive = NULL;
if (!GetMSCDEXDrive(CDROM_drive - 'A', &src_drive)) return 0x05;

After:

if (!src_drive)
    return 0x05;

While this specific hunk addresses a null-pointer dereference path in CD-ROM emulation, it's part of a broader set of changes described in the changelog:

- Added checks to sector I/O code to fix potential buffer overrun issues.

The General Pattern for Fixing Integer Overflow Before malloc

The correct approach for any allocation that involves attacker-controlled sizes is to validate before you calculate. Here are the standard patterns:

Pattern 1: Explicit Overflow Check

// Before (vulnerable)
size_t alloc_size = network_size + OVERHEAD;
void *buf = enet_malloc(alloc_size);

// After (safe)
if (network_size > SIZE_MAX - OVERHEAD) {
    // overflow would occur — reject the packet
    return ENET_ERROR_INVALID_SIZE;
}
size_t alloc_size = network_size + OVERHEAD;
void *buf = enet_malloc(alloc_size);

Pattern 2: Use a Safe Addition Helper

// A helper that returns 0 on overflow
static inline int safe_add_size(size_t a, size_t b, size_t *result) {
    if (a > SIZE_MAX - b) return 0; // overflow
    *result = a + b;
    return 1;
}

size_t alloc_size;
if (!safe_add_size(network_size, OVERHEAD, &alloc_size)) {
    return ENET_ERROR_INVALID_SIZE;
}
void *buf = enet_malloc(alloc_size);

Pattern 3: Enforce a Maximum Packet Size

#define ENET_MAX_PACKET_SIZE (64 * 1024 * 1024) // 64 MB hard cap

if (network_size > ENET_MAX_PACKET_SIZE) {
    return ENET_ERROR_PACKET_TOO_LARGE;
}
// Now network_size + any reasonable OVERHEAD cannot overflow
size_t alloc_size = network_size + OVERHEAD;
void *buf = enet_malloc(alloc_size);

Why This Matters for ENet Specifically

ENet operates over UDP, which means there is no connection state to hide behind. Any host that can reach the server's UDP port can send a malformed packet. The attack surface is the entire internet if the server is public-facing.


Prevention & Best Practices

1. Never Trust Network-Derived Size Values

Any value that comes from the network is attacker-controlled. Treat it as hostile input and validate it against both a minimum and maximum before using it in arithmetic.

// Always clamp/validate before arithmetic
if (packet_size < MIN_VALID_SIZE || packet_size > MAX_VALID_SIZE) {
    drop_packet();
    return;
}

2. Use Compiler Sanitizers During Development

Enable UndefinedBehaviorSanitizer (UBSan) and AddressSanitizer (ASan) during development and CI:

# GCC / Clang
gcc -fsanitize=undefined,address -o myapp myapp.c

# CMake
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined,address")

UBSan will catch signed integer overflows at runtime. ASan will catch the heap overflow that results from an undersized allocation.

3. Use Safe Integer Libraries

For C code, consider using safe integer libraries:

  • SafeInt (C++)
  • IntegerLib from Intel's Safe String Library
  • Checked arithmetic builtins in GCC/Clang:
size_t alloc_size;
if (__builtin_add_overflow(network_size, OVERHEAD, &alloc_size)) {
    return ERROR_OVERFLOW;
}

4. Apply Fuzzing to Network Parsers

Tools like AFL++ and libFuzzer are extremely effective at finding integer overflow bugs in parsers. Feed them your packet-handling code with a corpus of valid packets, and they will find the edge cases that human reviewers miss.

# Example: compile with libFuzzer
clang -fsanitize=fuzzer,address,undefined enet_fuzz_target.c -o enet_fuzzer
./enet_fuzzer corpus/

5. Code Review Checklist for Allocations

When reviewing code that calls malloc, calloc, realloc, or custom allocators, ask:

  • [ ] Is any argument to this allocation derived from external input?
  • [ ] Is there arithmetic in the size expression? Could it overflow?
  • [ ] Is there a maximum size enforced before the arithmetic?
  • [ ] What happens if the allocation returns NULL?

6. Relevant Standards and References

Reference Description
CWE-190 Integer Overflow or Wraparound
CWE-122 Heap-based Buffer Overflow
CERT C INT30-C Ensure unsigned integer operations do not wrap
CERT C MEM35-C Allocate sufficient memory for an object
OWASP: Integer Overflow OWASP community page on integer overflow

Conclusion

Integer overflow vulnerabilities in memory allocation paths are one of the most dangerous bug classes in networked C/C++ code — and one of the easiest to overlook. The math looks correct at a glance. The allocation succeeds. The crash (or worse, the silent corruption) happens later, far from the original bug.

The key takeaways from this fix:

  1. Network-derived values are attacker-controlled. Validate size fields before any arithmetic.
  2. Addition can overflow. a + b is not safe when a or b comes from the network.
  3. Use compiler tools. UBSan, ASan, and fuzzers catch these bugs cheaply during development.
  4. Enforce maximum sizes. A hard cap on packet size eliminates an entire class of overflow bugs.
  5. The exploit chain is short. Overflow → undersized allocation → heap corruption → potential RCE. There are very few steps between the bug and a serious impact.

Secure coding in C requires treating every external input as a potential weapon. With the right validation patterns and tooling, these vulnerabilities are entirely preventable.


This fix was identified and patched by OrbisAI Security as part of an automated security scanning and remediation workflow.

Frequently Asked Questions

What is integer overflow in heap allocation?

Integer overflow in heap allocation occurs when arithmetic operations on size values wrap around the maximum integer value, producing an unexpectedly small result that's then used to allocate memory. This creates a buffer smaller than needed, leading to heap corruption when data is written beyond the allocated bounds.

How do you prevent integer overflow in C networking code?

Prevent integer overflow by validating all network-derived values against maximum safe limits before using them in calculations, using safe arithmetic functions that check for overflow (like __builtin_mul_overflow), and ensuring size calculations use appropriate data types that can't overflow for your use case.

What CWE is integer overflow to heap corruption?

This vulnerability maps to CWE-190 (Integer Overflow or Wraparound) as the root cause and CWE-122 (Heap-based Buffer Overflow) as the consequence. It can also relate to CWE-680 (Integer Overflow to Buffer Overflow).

Is using size_t enough to prevent integer overflow?

No, using size_t alone is not sufficient. While size_t is the appropriate type for sizes, it can still overflow if unchecked arithmetic is performed on attacker-controlled values. You must validate inputs and check for overflow conditions before performing calculations, regardless of the data type used.

Can static analysis detect integer overflow vulnerabilities?

Yes, modern static analysis tools can detect many integer overflow vulnerabilities by tracking data flow from untrusted sources (like network inputs) to arithmetic operations and allocation functions. Tools look for missing bounds checks, unsafe type conversions, and arithmetic that could overflow before reaching memory allocation calls.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #6288

Related Articles

critical

How integer overflow in CsoundMYFLTArray constructor happens in C++ and how to fix it

A critical integer overflow vulnerability was discovered in `Java/cs_glue.cpp` at line 324, where the `CsoundMYFLTArray` constructor multiplied a user-controlled integer `n` by `sizeof(MYFLT)` without checking for overflow before passing the result to `malloc`. An attacker supplying a value near `INT_MAX` could trigger the overflow, causing an undersized heap allocation that subsequent writes would overflow. The fix adds an explicit `SIZE_MAX / sizeof(MYFLT)` guard and replaces `malloc` with `ca

high

How integer overflow in malloc happens in C bipartite matching and how to fix it

A high-severity integer overflow vulnerability was discovered in the bipartite matching algorithm implementation where unchecked multiplication operations for memory allocation could wrap around, causing undersized buffer allocations and subsequent heap overflow. The fix replaces vulnerable `malloc(sizeof(int) * V)` patterns with safe `calloc(V, sizeof(int))` calls and adds proper bounds validation to prevent exploitation.

high

How integer truncation heap overflow happens in C++ UEFI ACPI parsing and how to fix it

A high-severity integer truncation vulnerability was discovered in `Mobility.Uefi.Acpi.cpp` where heap allocation sizes were stored in a 16-bit integer (`MO_UINT16`), causing silent truncation when the computed size exceeded 65535 bytes. This led to undersized heap allocations followed by out-of-bounds writes, exploitable by an attacker who can influence ACPI SRAT table contents in virtualized environments. The fix promotes the size variable to `MO_UINTN` (platform-native width) to prevent trunc

critical

How integer overflow in buffer size calculation happens in C and how to fix it

A critical integer overflow vulnerability was discovered in the `nsh_setvar()` function in `nshlib/nsh_vars.c`, where the buffer size calculation `newsize = pstate->varsz + varlen` could wrap around, causing a heap buffer overflow. The fix adds overflow checking before the addition, preventing attackers with shell access from corrupting memory by setting variables with crafted names and values.

critical

How integer overflow happens in C reliable.c and how to fix it

A critical integer overflow vulnerability was discovered in `reliable.c` at line 1299, where the `packet_buffer_size` calculation used signed `int` arithmetic that could wrap to a negative or undersized value when large `fragment_size` values were involved. By casting each operand to `size_t` before multiplication, the fix eliminates the overflow risk entirely and ensures the allocated buffer is always large enough to hold the reassembled packet data.

critical

How integer overflow in buffer size calculation happens in C++ and how to fix it

A critical integer overflow vulnerability was discovered in OpenCV's HAL filter implementation where multiplying image dimensions without overflow protection could allocate dangerously undersized buffers. An attacker supplying crafted image dimensions (e.g., 65536×65536) could trigger heap corruption through out-of-bounds writes. The fix promotes the calculation to 64-bit arithmetic with a single cast.