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 Orbis AppSec
•Technically reviewed by Anupam Mediratta•Published May 28, 2026•Reviewed June 3, 2026

Answer Summary

This is a heap buffer overflow vulnerability (CWE-122) caused by an integer overflow in the packet reassembly logic of `net_channel_ex.c`, written in C. An attacker-controlled `bodylen` field could be accumulated across reassembled packets without any bounds validation, allowing the running total to wrap around or exceed the allocated buffer size. The fix adds a simple integer overflow check before each accumulation step, rejecting packets whose `bodylen` would cause the total to exceed safe limits. This prevents heap memory corruption from malformed or malicious network packets.

Vulnerability at a Glance

cweCWE-122 (Heap-based Buffer Overflow) / CWE-190 (Integer Overflow or Wraparound)
fixAdded an integer overflow check before accumulating `bodylen` values in the packet reassembly function in `net_channel_ex.c`
riskRemote attacker can corrupt heap memory by sending crafted network packets with malicious `bodylen` values
languageC
root causeThe `bodylen` field from attacker-controlled network packets was accumulated without any integer overflow or bounds validation
vulnerabilityInteger Overflow leading to Heap Buffer Overflow in packet reassembly

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

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.

Prevention and further reading

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #3

Related Articles

critical

Aardvark.Cef.Process.Core Shared Memory Handler: Unvalidated memcpy

The shared memory handler in Aardvark.Cef.Process.Core failed to validate that the `length` parameter passed from JavaScript did not exceed the destination buffer size before calling `memcpy`. This allowed a compromised Chromium renderer process to corrupt heap memory by supplying an oversized `handle->length` value to the `openMapping` function. The fix adds explicit bounds checking using `GetArrayBufferByteLength()` before the copy operation.

high

XShmGetImage Heap Corruption: Unvalidated Image Height in streamproxy

The `XShmGetImage` function in the X11 shared memory image path copies pixel data row-by-row using `memcpy` without validating that the source image height matches the destination buffer height. An attacker or compromised server could provide an oversized source image, causing writes beyond the allocated heap buffer and triggering heap corruption or code execution.

critical

SGX Enclave ecall_store_data memcpy Buffer Overflow in 256-Byte

The Intel SGX enclave's trusted bridge functions `ecall_store_data` and `ecall_retrieve_data` used `memcpy()` to move data into and out of a fixed 256-byte `secure_storage` buffer without validating that `data_len` fit within destination boundaries. An attacker providing oversized `data_len` values could corrupt enclave memory, breaking SGX's confidentiality guarantees.

critical

How Buffer Overflow via strcpy() Happens in C++ XML Parsers and How to Fix It

A critical buffer overflow vulnerability was discovered in `buildroot-external/package/libxmlparser/xmlParser.cpp`, where the `toXMLString` function used `_tcscpy()` to write XML escape sequences into a destination buffer without any bounds checking. An attacker supplying a crafted XML document could overflow the buffer and potentially execute arbitrary code. The fix replaces all five unsafe `_tcscpy()` calls with `memcpy()` calls that copy only the exact number of bytes required for each escape

critical

How Heap Buffer Overflows Happen in C++ ZIP Extraction and How to Fix Them

A critical heap buffer overflow vulnerability was discovered in `TKLiveSync/unzip.cpp`, where ZIP archive entry names were copied into a `PATH_MAX`-sized heap buffer using `strcpy()` without any length validation. Since the ZIP specification allows entry names up to 65,535 bytes — far exceeding typical `PATH_MAX` values of 1,024 to 4,096 bytes — a crafted archive could overflow the buffer and corrupt heap memory. The fix replaces the unsafe `strcpy`/`dirname` pattern with `std::string` operation

medium

How Integer Overflow happens in C++ image processing and how to fix it

A signed integer overflow in OpenCV's `bilateralFilter.cpp` allowed the buffer size calculation `cal_width * cal_height * cn` to wrap around to a small or negative value, causing `padding.resize()` to allocate far less memory than needed. Subsequent `memcpy` operations would then write beyond the allocated buffer, creating a heap corruption primitive. The fix is a single targeted cast to `size_t` that promotes the multiplication to unsigned 64-bit arithmetic before any overflow can occur.