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 happens in C tar header parsing and how to fix it

A critical buffer overflow vulnerability was discovered in `microtar/microtar.c` where the `raw_to_header()` and `header_to_raw()` functions used unbounded `strcpy()` and `sprintf()` calls to copy tar header fields. Malicious tar files with non-null-terminated name fields could overflow destination buffers, potentially leading to code execution. The fix replaces all unsafe string operations with bounded alternatives: `memcpy()` with explicit null-termination and `snprintf()` instead of `sprintf(

critical

How buffer overflow happens in C ieee80211_input() and how to fix it

A critical buffer overflow vulnerability was discovered in `src/firmware/src/net/ieee80211.c` at line 1584, where the `ieee80211_input()` function processed raw 802.11 data frames without verifying that the incoming frame was large enough to contain a valid `ieee80211_frame` header. An attacker within wireless range could craft undersized or malformed frames to trigger memory corruption, potentially leading to remote code execution on the firmware. The fix adds a single, targeted bounds check th

high

How buffer overflow from unsafe string copy functions happens in C network interface code and how to fix it

A high-severity buffer overflow vulnerability was discovered in `generic/eth-impl.c`, where unsafe `strncpy()` and `sprintf()` calls could write beyond buffer boundaries when handling network interface names and device filenames. The fix replaced these dangerous functions with bounded `snprintf()` calls that guarantee null-termination and prevent memory corruption.

critical

How buffer overflow in FuzzIxml.c sprintf() happens in C and how to fix it

A critical buffer overflow vulnerability was discovered in `fuzzer/FuzzIxml.c` where `sprintf()` wrote a PID-formatted filename into a fixed 256-byte stack buffer without any bounds checking. The fix replaces `sprintf()` with `snprintf()`, explicitly passing the buffer size to prevent any overflow. While exploitation in this specific fuzzer context requires local access, the pattern is a textbook example of CWE-120 that developers should recognize and eliminate everywhere it appears.

critical

How buffer overflow happens in C HTML parsing and how to fix it

A critical buffer overflow vulnerability in `include/html_parse.h` allowed attackers to overflow buffers by providing malicious HTML input exceeding buffer capacity. The fix adds proper bounds checking before memcpy() operations to prevent memory corruption and potential code execution.

critical

How buffer overflow in memcpy() happens in Node.js N-API bindings and how to fix it

A critical buffer overflow vulnerability was discovered in the GetBufferAsVector() function in examples_nodejs/src/zupt_napi.cpp, where memcpy() copied data from JavaScript Uint8Array buffers without proper bounds validation. This vulnerability could allow attackers to trigger memory corruption by providing maliciously crafted input arrays to the native Node.js module, potentially leading to crashes or arbitrary code execution.