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

high

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

A high-severity buffer overflow vulnerability was discovered in `src/calculations.c` at line 37, where a two-step `strncpy` + manual null-termination pattern left the door open for subtle memory safety bugs when copying string data into the `entry->type` field. The fix replaces both lines with a single `snprintf` call that handles bounds and null-termination atomically, eliminating the risk entirely. This is a common C pitfall that affects production CLI tools and can be exploited when attacker-

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.

high

How buffer overflow via sprintf() happens in C networking code and how to fix it

A high-severity buffer overflow vulnerability was discovered in `profile.c` where `sprintf()` was used to format server addresses without any bounds checking. An attacker who could influence the `SERVER_BASE_PORT` value or trigger integer overflow in the port calculation could write beyond the `server_address` buffer. The fix replaces `sprintf()` with `snprintf()` using explicit buffer size limits at both call sites (lines 99 and 220).

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.

high

How insecure string copy functions happen in C (cyw43.c) and how to fix it

Three unsafe string copy calls in `src/cyw43.c` — including a bare `strcpy()` and two `strncpy()` calls — created buffer overflow risks in a CYW43 Wi-Fi driver emulation layer. The fix replaces all three with `snprintf()`, which enforces buffer size limits and guarantees null-termination in a single, consistent operation. Left unaddressed, these vulnerabilities could allow an attacker controlling input like a TAP interface name or SSID to corrupt adjacent memory and potentially execute arbitrary