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
Published May 28, 2026Reviewed 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

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.

Frequently Asked Questions

What is an integer overflow leading to heap buffer overflow?

It occurs when an arithmetic operation on an integer (such as adding packet body lengths) exceeds the maximum value the integer type can hold, causing it to wrap around to a small or negative value, which is then used as a size for memory allocation or indexing — resulting in a buffer that is too small and subsequent writes that corrupt adjacent heap memory.

How do you prevent integer overflow in C packet reassembly?

Always validate that the sum of accumulated lengths cannot exceed a safe maximum before performing the addition. Use explicit checks like `if (total + bodylen > MAX_ALLOWED || total + bodylen < total)` before accumulating, or use safe integer arithmetic libraries.

What CWE is integer overflow leading to heap buffer overflow?

This vulnerability maps to CWE-190 (Integer Overflow or Wraparound) as the root cause, and CWE-122 (Heap-based Buffer Overflow) as the resulting impact. MITRE recognizes this chain as a common and dangerous pattern in C/C++ code.

Is input length validation enough to prevent this vulnerability?

Validating individual packet fields alone is not sufficient — you must also validate the *accumulated* total across all reassembled fragments. An attacker can send many packets each with a seemingly valid `bodylen`, but whose sum overflows the accumulator variable or exceeds the allocated buffer.

Can static analysis detect integer overflow in packet reassembly?

Yes. Static analysis tools such as Semgrep, Coverity, and CodeQL can detect patterns where integer values derived from external input are used in arithmetic without overflow checks. Orbis AppSec automatically detected this exact pattern and generated a fix.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #3

Related Articles

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

high

How insecure string copy functions happen in C and how to fix it

A high-severity buffer overflow vulnerability was discovered in `tools/claude-vscode-wrapper.c`, where an unbounded `strcpy()` call copied a file path into a fixed-size `MAX_PATH` buffer without any size validation. The fix replaces `strcpy()` with `snprintf()` and swaps `malloc()` for `calloc()`, ensuring both string operations and memory allocation are bounds-safe and zero-initialized.

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.

critical

How Stack Buffer Overflows Happen in C with sprintf() and How to Fix Them

A critical stack buffer overflow was discovered in `libuv/Learn-libuv/docs/code/tty-gravity/main.c` where `sprintf()` wrote ANSI escape sequences and user-controlled variables into a fixed 500-byte buffer without any bounds checking. An attacker controlling the `pos`, `width`, or `message` variables could overflow the stack, overwrite return addresses, and potentially achieve arbitrary code execution. The fix replaces `sprintf()` with `snprintf()` and adds explicit length validation to ensure wr

high

How insecure string copy functions happen in C and how to fix them

A high-severity buffer overflow risk was discovered in `login/main.c` where `strcpy()` was used to copy the `HOME` environment variable into a fixed-size 512-byte buffer without any bounds checking. An attacker controlling the `HOME` environment variable could overflow `pwd_file_name`, potentially corrupting memory or hijacking execution. The fix replaces the two-step `strcpy`/`strcat` pattern with a single, bounds-safe `snprintf` call.