Back to Blog
medium SEVERITY7 min read

Integer Overflow in Packet Reassembly: How One Missing Check Enables Heap Corruption

A critical heap buffer overflow vulnerability was discovered in the network packet reassembly function of `net_channel_ex.c`, where an attacker-controlled `bodylen` field could be used to corrupt heap memory without any bounds validation. The fix introduces a simple yet effective integer overflow check before accumulating packet body lengths, preventing malformed packets from triggering memory corruption. This type of vulnerability is a stark reminder that even low-level arithmetic operations in

O
By orbisai0security
May 28, 2026

Integer Overflow in Packet Reassembly: How One Missing Check Enables Heap Corruption

Introduction

Network packet parsing is one of the most attack-exposed surfaces in any networked application. Every byte that arrives from the network is potentially attacker-controlled — and when your code trusts those bytes without validation, the consequences can be severe.

This post examines a critical heap buffer overflow vulnerability found in a network packet reassembly function written in C. The root cause is deceptively simple: an integer overflow in a length accumulation loop that goes unchecked before being passed to malloc(). The result? An attacker can send a single malformed packet and corrupt heap memory.

Whether you're a seasoned systems programmer or a developer just getting started with C networking code, this vulnerability illustrates a class of bugs that continues to haunt real-world software — and the fix is a masterclass in defensive programming.


The Vulnerability Explained

What Is Packet Reassembly?

In many network protocols, large messages are split across multiple packets. A reassembly function collects these fragments and stitches them back together into a single contiguous buffer. To do this, it typically:

  1. Iterates over a list of received packet fragments
  2. Sums up the total payload length
  3. Allocates a buffer of that total size
  4. Copies each fragment's payload into the buffer

This is exactly what merge_packet() does in net_channel_ex.c. And step 2 — summing the lengths — is where the vulnerability lives.

The Vulnerable Code

Here's the relevant portion of the original code:

static unsigned char* merge_packet(List_t* list, unsigned int* mergelen) {
    // ...
    unsigned int off = 0;

    for (cur = list->head; cur; cur = next) {
        packet = pod_container_of(cur, NetReactorPacket_t, _.node);
        next = cur->next;
        off += packet->_.bodylen;  // ← No overflow check!
    }

    ptr = (unsigned char*)malloc(off);  // ← Allocates potentially tiny buffer
    // ... then copies full data into ptr
}

The variable off is an unsigned int. Each iteration adds packet->_.bodylen — a value that comes directly from the packet header, meaning it is fully attacker-controlled.

The Integer Overflow

Here's the critical insight: unsigned integer arithmetic in C wraps around silently.

Imagine an attacker crafts two packets:
- Packet 1: bodylen = 0xFFFFFFF0 (4,294,967,280)
- Packet 2: bodylen = 0x00000020 (32)

When these are added:

0xFFFFFFF0 + 0x00000020 = 0x100000010

But since off is a 32-bit unsigned int, the result wraps around to:

0x00000010  (just 16 bytes!)

Now malloc(16) allocates a tiny 16-byte buffer, but the subsequent copy loop faithfully copies gigabytes of data into it — overflowing far beyond the allocated region and corrupting whatever lives next to it on the heap.

Real-World Impact

This vulnerability can be exploited by anyone who can send network packets to the target process. The impact includes:

  • Heap corruption: Overwriting adjacent heap metadata or application data
  • Remote Code Execution (RCE): With careful heap manipulation, an attacker may control what gets overwritten and redirect execution flow
  • Denial of Service (DoS): Even without achieving RCE, heap corruption typically causes a crash
  • No authentication required: A single malformed packet is sufficient — no session or login needed

This maps to CWE-190: Integer Overflow or Wraparound and CWE-122: Heap-Based Buffer Overflow, and is consistent with vulnerabilities scored at the highest severity levels under CVSS.

Attack Scenario

Attacker                          Server
   |                                 |
   |-- Packet 1 (bodylen=0xFFFFFFF0) -->|
   |-- Packet 2 (bodylen=0x00000020) -->|
   |                                 |
   |                    merge_packet() called
   |                    off = 0x10 (16 bytes, wrapped!)
   |                    malloc(16)  tiny buffer allocated
   |                    memcpy copies 4GB+ of data
   |                    HEAP CORRUPTED 💥
   |                                 |

The Fix

What Changed

The fix adds a single, surgical check inside the accumulation loop:

for (cur = list->head; cur; cur = next) {
    packet = pod_container_of(cur, NetReactorPacket_t, _.node);
    next = cur->next;
    if (off + packet->_.bodylen < off) {  // ← Overflow detection
        return NULL;
    }
    off += packet->_.bodylen;
}

Here's the full diff:

 for (cur = list->head; cur; cur = next) {
     packet = pod_container_of(cur, NetReactorPacket_t, _.node);
     next = cur->next;
+    if (off + packet->_.bodylen < off) {
+        return NULL;
+    }
     off += packet->_.bodylen;
 }

Why This Works

The check off + packet->_.bodylen < off exploits a fundamental property of unsigned integer arithmetic:

If adding a positive value to an unsigned integer produces a result smaller than the original, an overflow has occurred.

In standard C, unsigned integer overflow is well-defined (it wraps modulo 2^N), so this check is both portable and correct. If the addition would wrap, the function immediately returns NULL, signaling to the caller that the packet list is malformed.

This is a classic and idiomatic overflow guard in C, sometimes called a pre-addition overflow check. It's simple, has zero performance overhead, and is immediately understandable to any C developer.

Before vs. After

Scenario Before Fix After Fix
Normal packets ✅ Works correctly ✅ Works correctly
Single oversized bodylen ❌ Heap overflow ✅ Returns NULL safely
Multiple packets that overflow when summed ❌ Heap overflow ✅ Returns NULL safely
Attacker-crafted wraparound ❌ RCE possible ✅ Safely rejected

Prevention & Best Practices

1. Always Validate Attacker-Controlled Length Fields

Any length, size, or count value that originates from a network packet, file, or external input is untrusted by definition. Before using such values in arithmetic or memory allocation, validate them:

// Bad: trust the network
size_t total = header->length;
char* buf = malloc(total);

// Good: validate before use
if (header->length == 0 || header->length > MAX_ALLOWED_SIZE) {
    return ERROR_INVALID_LENGTH;
}
char* buf = malloc(header->length);

2. Use Safe Integer Arithmetic Helpers

For C/C++ projects, consider using helper functions or compiler built-ins for overflow-safe arithmetic:

// GCC/Clang built-in: returns true if overflow would occur
unsigned int result;
if (__builtin_uadd_overflow(off, bodylen, &result)) {
    return NULL;
}
off = result;

For C++, the <numeric> utilities or libraries like SafeInt provide robust overflow-safe operations.

3. Apply Defense in Depth with Maximum Size Limits

Even with overflow checks, it's wise to enforce an upper bound on total reassembled size:

#define MAX_REASSEMBLY_SIZE (64 * 1024 * 1024)  // 64 MB cap

if (off + packet->_.bodylen < off ||
    off + packet->_.bodylen > MAX_REASSEMBLY_SIZE) {
    return NULL;
}

This limits the blast radius even if a future bug bypasses the overflow check.

4. Prefer Memory-Safe Languages Where Possible

Languages like Rust make this class of bug impossible by default — integer overflows cause a panic in debug mode and use wrapping semantics in release mode, with explicit opt-in required for either behavior. For new network-facing code, consider whether Rust or another memory-safe language is appropriate.

5. Use Static Analysis and Fuzzing

  • Static analyzers like clang-tidy, Coverity, or CodeQL can flag unchecked arithmetic on attacker-controlled values
  • Fuzzers like AFL++ or libFuzzer are exceptionally good at finding this class of bug — feed them malformed packet streams and let them find the edge cases
  • AddressSanitizer (ASan) will catch the heap overflow at runtime during testing

6. Reference Security Standards

This vulnerability class is well-documented:


Conclusion

This vulnerability is a perfect example of how a single missing check in network-facing C code can open the door to remote code execution. The merge_packet() function trusted attacker-supplied length values, accumulated them without overflow protection, and passed the result directly to malloc() — a textbook recipe for heap corruption.

The fix is just three lines, but those three lines close a critical attack vector entirely. This is the essence of secure coding in C: every arithmetic operation on untrusted data is a potential vulnerability, and the cost of a guard check is always worth the security guarantee it provides.

Key Takeaways

  • 🔢 Unsigned integer overflow is silent and well-defined in C — it wraps, and attackers know how to exploit that
  • 📦 Packet header fields are attacker-controlled — never trust them without validation
  • 🛡️ Pre-addition overflow checks (if (a + b < a)) are idiomatic, correct, and cheap
  • 🔍 Fuzz your packet parsers — this is exactly the kind of bug that fuzzers find quickly
  • 📏 Enforce maximum sizes as a second layer of defense

Security is built one careful check at a time. The next time you write a loop that accumulates lengths from external data, remember this bug — and add the guard.


This vulnerability was identified and fixed automatically by OrbisAI Security. Automated security scanning helps catch these issues before they reach production.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #3

Related Articles

critical

Heap Buffer Overflow in Audio Ring Buffer: How a Missing Bounds Check Could Crash Your App

A critical heap buffer overflow vulnerability was discovered in `audio_backend.c`, where the audio ring buffer's `memcpy` operations lacked bounds validation before writing PCM data. Without checking that incoming data sizes fell within the allocated buffer's capacity, a maliciously crafted audio file could corrupt adjacent heap memory, potentially enabling arbitrary code execution. The fix adds a concise pre-flight validation guard that rejects out-of-range write requests before any memory oper

critical

Critical Heap Buffer Overflow in SSDP Control Point: How Unbounded String Operations Put Networks at Risk

A critical heap buffer overflow vulnerability was discovered and patched in the SSDP control point implementation (`ssdp_ctrlpt.c`), where multiple unbounded `strcpy` and `strcat` operations constructed HTTP request buffers without any length validation. Network-received SSDP response fields — including service type strings and location URLs — could be crafted by an attacker to exceed buffer boundaries, potentially enabling arbitrary code execution or denial of service. The fix replaces the unsa

critical

Heap Buffer Overflow in OPDS Parser: How a Misplaced Variable Nearly Opened the Door to Remote Code Execution

A critical heap buffer overflow vulnerability was discovered in `lib/OpdsParser/OpdsParser.cpp`, where the buffer allocation size was calculated *after* a fixed chunk size was used to allocate memory, meaning the actual bytes read could exceed the allocated buffer. On embedded devices parsing untrusted OPDS catalog data from the network, this flaw could allow a remote attacker to corrupt heap memory and potentially achieve arbitrary code execution. The fix was elegantly simple: move the `toRead`

critical

Heap Buffer Overflow in BLE MIDI: How a Missing Bounds Check Opens the Door to Remote Exploitation

A critical heap buffer overflow vulnerability was discovered in the BLE MIDI packet assembly code of `blemidi.c`, where attacker-controlled packet length values could trigger writes beyond allocated heap memory. The fix adds an integer overflow guard before the `malloc` call, ensuring that maliciously crafted BLE MIDI packets can no longer corrupt heap memory. This vulnerability is particularly dangerous because it is remotely exploitable by any nearby Bluetooth device — no physical access requi

critical

Heap Overflow in TOML Parser: How Integer Overflow Leads to Memory Corruption

A critical heap buffer overflow vulnerability was discovered and patched in the centitoml TOML parser, where missing integer overflow validation on a `MALLOC(len+1)` call could allow an attacker to trigger memory corruption via a crafted TOML configuration file. The vulnerability (CWE-190) is reachable through community-distributed mod or map files that the game loads from its `config/` directory, making it a realistic attack vector for remote code execution. A targeted one-line guard now preven

critical

Heap Corruption via Unchecked memcpy: How Integer Overflow Bugs Corrupt Memory in Windows File Operations

A critical buffer overflow vulnerability was discovered in `phlib/nativefile.c`, where multiple `memcpy` calls copied filename and extended-attribute data into fixed-size structures without verifying that source lengths didn't exceed destination buffer boundaries. An attacker supplying an oversized filename or EA name could corrupt adjacent heap memory, potentially enabling arbitrary code execution. The fix replaces unchecked arithmetic with Windows' safe integer helpers (`RtlULongAdd`, `RtlULon