Back to Blog
critical SEVERITY7 min read

Critical Buffer Overflow in veejay packet.c: How Unchecked Network Packet Sizes Enable Remote Code Execution

A critical heap buffer overflow vulnerability was discovered in veejay's `packet.c` networking code, where `veejay_memcpy` operations used attacker-controlled size values from network packet headers without any boundary validation. This flaw could allow a remote attacker to send crafted packets that trigger heap corruption, potentially leading to arbitrary code execution. The fix adds proper buffer-length checks before any memory copy operations, ensuring that packet sizes are validated against

O
By Orbis AppSec
Published May 28, 2026Reviewed June 3, 2026

Answer Summary

This vulnerability is a critical heap buffer overflow (CWE-122) in veejay's C networking code (`packet.c`), caused by passing attacker-controlled size values from network packet headers directly into `veejay_memcpy` without validating them against the destination buffer's allocated size. The fix adds explicit boundary checks before each `veejay_memcpy` call, rejecting any packet whose declared size exceeds the allocated buffer length, which eliminates the heap corruption path and prevents remote code execution.

Vulnerability at a Glance

cweCWE-122
fixAdd buffer-length checks before all veejay_memcpy calls to reject packets whose declared size exceeds the allocated buffer
riskRemote attacker can corrupt heap memory and potentially execute arbitrary code by sending a crafted network packet
languageC
root causeAttacker-controlled packet header size fields passed directly to veejay_memcpy without bounds validation
vulnerabilityHeap Buffer Overflow

Critical Buffer Overflow in veejay packet.c: How Unchecked Network Packet Sizes Enable Remote Code Execution

Introduction

Buffer overflow vulnerabilities are among the oldest and most dangerous classes of security bugs in systems programming — and they're far from extinct. In 2024, a critical buffer overflow was identified and patched in veejay, an open-source real-time video performance tool widely used in live visual art and VJing communities.

The vulnerability lived in veejay-current/veejay-core/libvjnet/packet.c, a file responsible for handling network packet data. The root cause? Memory copy operations that blindly trusted size values supplied by incoming network packets — a classic CWE-120 (Buffer Copy Without Checking Size of Input) scenario.

If you write C or C++ code that handles network data, this post is essential reading. Even if you don't, understanding this class of vulnerability helps you appreciate why memory-safe languages and defensive coding practices matter so much.


The Vulnerability Explained

What Is a Heap Buffer Overflow?

When a program allocates a block of memory on the heap (e.g., via malloc) and then writes more data into that block than it can hold, the excess data spills into adjacent memory regions. This is a heap buffer overflow. Depending on what lives in that adjacent memory, an attacker can:

  • Corrupt heap metadata, causing crashes or undefined behavior
  • Overwrite function pointers or vtables, redirecting code execution
  • Achieve arbitrary code execution (RCE), the most severe outcome

The Vulnerable Code Pattern

In packet.c, the code performed veejay_memcpy operations using CHUNK_SIZE and len values that were derived directly from network packet headers:

// BEFORE (vulnerable pseudocode)
int len = read_packet_header_length(packet);   // attacker-controlled!
int chunk = read_packet_chunk_size(packet);    // attacker-controlled!

// No validation — len or chunk could be larger than dst buffer
veejay_memcpy(dst_buffer, src_data, len);
veejay_memcpy(chunk_buffer, chunk_data, chunk);

The critical flaw here is that len and chunk come from the network — meaning any remote peer can set them to arbitrary values. There is no check asking: "Does this size actually fit within the destination buffer?"

How Could an Attacker Exploit This?

The attack scenario is straightforward:

  1. Attacker identifies a veejay instance listening on the network (default multicast/unicast video streaming ports).
  2. Attacker crafts a malicious packet with an inflated len or CHUNK_SIZE value in the header — for example, claiming the payload is 1,000,000 bytes when the destination buffer is only 4,096 bytes.
  3. veejay processes the packet, calls veejay_memcpy with the attacker-supplied size, and writes far beyond the allocated buffer.
  4. Heap corruption occurs. With careful crafting, the attacker can overwrite adjacent heap objects, manipulate allocator metadata, or redirect execution flow.
  5. Remote code execution becomes possible — the attacker's payload runs with the privileges of the veejay process.

This is especially concerning in live performance environments where veejay instances may be exposed on local area networks, festival networks, or even the public internet.

Real-World Impact

Impact Area Details
Confidentiality Full system compromise possible
Integrity Arbitrary code execution
Availability Process crash / denial of service
Attack Vector Network (remote, no authentication required)
Severity CRITICAL

The vulnerability also affected mcastreceiver.c, the multicast receiver component, broadening the attack surface to multicast network scenarios.


The Fix

What Changed

The fix was applied to two files:
- veejay-current/veejay-core/libvjnet/packet.c
- veejay-current/veejay-core/libvjnet/mcastreceiver.c

The core change introduces explicit buffer-length validation before any veejay_memcpy call that uses network-supplied size values. The pattern looks like this:

// AFTER (fixed pseudocode)
int len = read_packet_header_length(packet);
int chunk = read_packet_chunk_size(packet);

// Validate BEFORE copying
if (len <= 0 || len > MAX_PACKET_SIZE || len > dst_buffer_size) {
    veejay_msg(VEEJAY_MSG_ERROR,
        "Packet length %d exceeds buffer boundary, dropping packet", len);
    return -1;
}

if (chunk <= 0 || chunk > CHUNK_SIZE || chunk > chunk_buffer_size) {
    veejay_msg(VEEJAY_MSG_ERROR,
        "Chunk size %d exceeds buffer boundary, dropping packet", chunk);
    return -1;
}

// Safe to copy — sizes have been validated
veejay_memcpy(dst_buffer, src_data, len);
veejay_memcpy(chunk_buffer, chunk_data, chunk);

Why This Fix Works

The fix enforces a fundamental security principle: never trust input from the network. By checking that:

  1. The size is positive (prevents integer underflow tricks)
  2. The size does not exceed a known maximum (MAX_PACKET_SIZE)
  3. The size does not exceed the actual destination buffer size

...the code ensures that veejay_memcpy can never write beyond the allocated region, regardless of what values an attacker provides in the packet header.

Malformed or oversized packets are now silently dropped with an error log, rather than blindly processed. This is the correct behavior for a network application receiving untrusted data.

Defense in Depth

Beyond the direct fix, a well-hardened version of this code would also benefit from:

// Using safer bounded copy as additional layer
// Instead of: veejay_memcpy(dst, src, attacker_len)
// Prefer:      memcpy(dst, src, MIN(attacker_len, sizeof(dst)))

This "belt and suspenders" approach means even if a future developer accidentally removes the explicit check, the bounded copy limits damage.


Prevention & Best Practices

1. Never Trust Network-Supplied Lengths

Any size, offset, or count value that arrives from the network must be treated as hostile input. Always validate against known-safe bounds before using the value in a memory operation.

// Dangerous pattern
memcpy(buffer, data, network_supplied_length);

// Safe pattern
if (network_supplied_length > sizeof(buffer)) {
    handle_error();
    return;
}
memcpy(buffer, data, network_supplied_length);

2. Use Compiler and OS Mitigations

Modern toolchains offer several protections that raise the bar for exploiting buffer overflows:

Mitigation How to Enable What It Does
Stack Canaries -fstack-protector-strong Detects stack smashing
ASLR OS-level (default on Linux) Randomizes memory layout
PIE -fPIE -pie Position-independent executable
RELRO -Wl,-z,relro,-z,now Hardens GOT/PLT
FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 Adds runtime buffer checks

These don't replace proper input validation, but they significantly increase exploit complexity.

3. Use Static Analysis Tools

Several tools can catch CWE-120 class vulnerabilities automatically:

Integrating these into your CI/CD pipeline means issues like this get caught before they reach production.

4. Adopt Fuzzing for Network Code

Network parsers are prime candidates for fuzz testing. Tools like AFL++ and libFuzzer automatically generate malformed inputs and monitor for crashes — exactly the kind of testing that would have surfaced this vulnerability early.

# Example: running AFL++ against a network parser
afl-fuzz -i inputs/ -o findings/ -- ./veejay_packet_parser @@

5. Prefer Memory-Safe Languages Where Possible

For new networking code, languages like Rust provide memory safety guarantees at compile time, making entire classes of buffer overflow vulnerabilities impossible by construction. If rewriting existing C code isn't feasible, consider wrapping the most dangerous parsing logic in a Rust or Go component.

Security Standards Reference


Conclusion

This vulnerability in veejay's packet.c is a textbook example of why input validation is non-negotiable in network code. A few missing bounds checks turned a routine memory copy into a potential remote code execution vector — the most severe outcome in the security threat model.

The key takeaways from this incident:

Always validate network-supplied sizes before using them in memory operations

Treat every byte from the network as hostile until proven otherwise

Layer your defenses: input validation + compiler mitigations + runtime sanitizers

Automate security scanning in CI/CD to catch issues early and cheaply

Fuzz your network parsers — automated tools find what human review misses

Buffer overflows have been exploited since the Morris Worm of 1988. Decades later, they remain one of the most impactful vulnerability classes in systems software. The good news: with the right tools, practices, and mindset, they are entirely preventable.

If you maintain C or C++ code that processes network data, take this as a prompt to audit your own packet parsing logic. The fix is often just a few lines — but the protection it provides is invaluable.


This vulnerability was identified and patched as part of an automated security review. The fix was verified by build testing and scanner re-scan confirmation.

Have a vulnerability you'd like explained? Reach out to the Fenny Security team.

Frequently Asked Questions

What is a heap buffer overflow?

A heap buffer overflow occurs when a program writes more data into a heap-allocated buffer than the buffer can hold, corrupting adjacent memory. In C, this often happens when a size value is not validated before being used in a memory copy operation.

How do you prevent heap buffer overflow in C networking code?

Always validate attacker-supplied length fields from network packets against the actual size of the destination buffer before performing any memory copy. Use safe copy functions and enforce strict upper bounds on all size parameters derived from external input.

What CWE is heap buffer overflow?

Heap buffer overflow is classified as CWE-122 (Heap-based Buffer Overflow), a subset of CWE-119 (Improper Restriction of Operations within the Bounds of a Memory Buffer).

Is using veejay_memcpy instead of memcpy enough to prevent buffer overflow?

No. A wrapper like veejay_memcpy only changes the copy mechanism; if the size argument passed to it is attacker-controlled and not validated against the destination buffer's capacity, a heap overflow can still occur regardless of which copy function is used.

Can static analysis detect heap buffer overflow from network input?

Yes. Static analysis tools such as Semgrep, Coverity, and CodeQL can trace tainted data from network input sources to memory copy sinks and flag cases where size arguments are not validated, which is precisely how this vulnerability was detected.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #383

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