Back to Blog
critical SEVERITY6 min read

How buffer overflow in strcpy() happens in C bin2coff tool and how to fix it

A critical buffer overflow vulnerability was discovered in `tools/bin2coff.c` where multiple `strcpy()` operations copied user-controlled label strings into fixed-size buffers without bounds checking. An attacker could provide maliciously long labels to overflow destination buffers and corrupt adjacent memory structures, potentially leading to arbitrary code execution. The fix replaced unsafe string operations with bounded alternatives like `strlcpy()` and `snprintf()`.

O
By Orbis AppSec
Published June 29, 2026Reviewed June 29, 2026

Answer Summary

This is a **CWE-120 buffer overflow** vulnerability in C code within the bin2coff tool. The vulnerability occurs when `strcpy()` copies user-controlled label strings into fixed-size buffers (like 8-byte ShortName fields) without length validation. An attacker providing labels longer than buffer capacity can overflow into adjacent memory, corrupting symbol table structures and potentially achieving code execution. The fix replaces `strcpy()` with bounded functions like `strlcpy()` and `snprintf()` that enforce maximum copy lengths, preventing buffer overruns regardless of input size.

Vulnerability at a Glance

cweCWE-120 (Buffer Copy without Checking Size of Input)
fixReplace strcpy() with strlcpy() and use snprintf() for bounded string operations
riskMemory corruption leading to potential arbitrary code execution when processing malicious binary labels
languageC
root causestrcpy() copies user-controlled strings into fixed 8-byte ShortName buffers without length validation
vulnerabilityBuffer overflow via unbounded strcpy() in COFF symbol table generation

Introduction

In a binary-to-COFF conversion tool at tools/bin2coff.c:393, we discovered a critical buffer overflow vulnerability that could allow attackers to corrupt memory and potentially execute arbitrary code. The vulnerability stemmed from using strcpy() to copy user-controlled label strings into fixed-size buffers within COFF symbol table structures—specifically the 8-byte ShortName field—without any bounds checking.

This isn't just a theoretical concern. The bin2coff tool processes binary files and generates COFF (Common Object File Format) object files, meaning any malicious input file with excessively long labels could trigger the overflow. Since this tool operates on user-provided input files, the attack surface is significant: an attacker simply needs to craft a binary file with labels exceeding buffer capacity to trigger memory corruption.

The vulnerability affects production code, not test files, making it a high-priority security issue that required immediate remediation.

The Vulnerability Explained

The core problem lies in how bin2coff.c handles string operations when building COFF symbol tables. Here's the vulnerable pattern:

// Vulnerable code in tools/bin2coff.c
struct syment {
    union {
        char ShortName[8];  // Fixed 8-byte buffer
        struct {
            uint32_t Zeroes;
            uint32_t Offset;
        } Name;
    } N;
    // ... other fields
};

// Somewhere in the code around line 393:
strcpy(symbol->N.ShortName, user_label);  // No bounds checking!

The ShortName field is exactly 8 bytes, but strcpy() will copy the entire source string regardless of destination capacity. When user_label contains more than 7 characters (leaving room for null terminator), the overflow begins.

Attack Scenario:

  1. An attacker creates a malicious binary file with an embedded label like "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" (40+ characters)
  2. The victim runs: bin2coff malicious.bin output.coff
  3. The tool calls strcpy(symbol->N.ShortName, "AAAA...")
  4. The 8-byte buffer overflows, overwriting adjacent memory in the symbol table structure
  5. Depending on what follows in memory (possibly function pointers, return addresses, or other critical data), the attacker could:
    - Corrupt the string table offset, causing crashes or information disclosure
    - Overwrite control flow data for code execution
    - Trigger undefined behavior leading to exploitable conditions

Real-World Impact:

For developers using bin2coff in build pipelines, this means:
- A malicious binary from an untrusted source could compromise the build system
- Automated toolchains processing user-submitted binaries become attack vectors
- Memory corruption could lead to non-deterministic build failures or worse—silent corruption of output files

The vulnerability was confirmed exploitable by the multi_agent_ai scanner using rule V-001, which specifically detects unbounded string copy operations with user-controlled input.

The Fix

The fix replaces all unsafe strcpy() calls with bounded alternatives that enforce maximum copy lengths. Here's what changed:

Before (Vulnerable):

strcpy(symbol->N.ShortName, label);

After (Secure):

strlcpy(symbol->N.ShortName, label, sizeof(symbol->N.ShortName));

The key improvements:

  1. strlcpy() enforces bounds: The third parameter sizeof(symbol->N.ShortName) (8 bytes) ensures no more than 7 characters are copied, always leaving room for null termination
  2. Guaranteed null-termination: Unlike strncpy(), strlcpy() always null-terminates the destination, preventing string handling bugs downstream
  3. Truncation handling: If the source exceeds capacity, strlcpy() truncates safely rather than overflowing

For cases involving formatted strings, the fix uses snprintf():

Before:

sprintf(buffer, "_%s", label);

After:

snprintf(buffer, sizeof(buffer), "_%s", label);

This ensures formatted output respects buffer boundaries regardless of input length.

Why This Works:

The bounded functions create a security invariant: "Label length must not exceed destination buffer capacity." This property holds even under adversarial input. The regression test included in the PR validates this by testing:
- Short valid input: "A" (1 char)
- Boundary case: 40 characters
- Exploit payload: 256 characters

After the fix, all cases complete without memory corruption signals (SIGSEGV/SIGABRT), confirming the security boundary is maintained.

Prevention & Best Practices

1. Ban Unsafe String Functions

Add compiler warnings or static analysis rules to flag:
- strcpy() → use strlcpy() or strncpy() with manual null termination
- strcat() → use strlcat() or strncat()
- sprintf() → use snprintf()
- gets() → use fgets()

Enable -Wstringop-overflow and -Wformat-overflow in GCC/Clang to catch these at compile time.

2. Always Validate Buffer Sizes

Before any copy operation:

if (strlen(source) >= sizeof(dest)) {
    // Handle error: truncate, reject, or allocate larger buffer
}
strlcpy(dest, source, sizeof(dest));

3. Use Static Analysis

Tools like Semgrep can detect this pattern:

rules:
  - id: unsafe-strcpy
    pattern: strcpy($DEST, $SRC)
    message: "Use strlcpy() or strncpy() instead of strcpy()"
    severity: ERROR

4. Enable Memory Safety Protections

Compile with:
- Stack canaries (-fstack-protector-strong)
- ASLR (Address Space Layout Randomization)
- DEP/NX (non-executable stack)
- FORTIFY_SOURCE (-D_FORTIFY_SOURCE=2)

These won't prevent buffer overflows but make exploitation harder.

5. Adopt Secure Coding Standards

Follow CERT C guidelines:
- STR31-C: Guarantee sufficient storage for strings
- STR38-C: Use bounded string functions

6. Test with Adversarial Input

The regression test demonstrates best practices:
- Test valid input (1 char)
- Test boundary conditions (exactly at limit)
- Test exploit payloads (far exceeding limit)
- Assert no crashes or memory corruption signals

Key Takeaways

  • Never use strcpy() with user-controlled input in production code—the bin2coff tool processed user-provided binary files, making every label a potential attack vector
  • The 8-byte ShortName field in COFF symbol tables requires special handling—always use strlcpy(dest, src, 8) when populating this structure
  • Bounded functions like strlcpy() and snprintf() are not just best practices—they're essential security controls that prevent an entire class of memory corruption vulnerabilities
  • Static analysis tools can catch these issues before they reach production—the multi_agent_ai scanner flagged this with rule V-001, enabling automated detection
  • Security-focused regression tests validate invariants under adversarial input—the included test ensures the fix prevents crashes even with 256-character payloads

How Orbis AppSec Detected This

  • Source: User-controlled label strings from input binary files processed by the bin2coff tool
  • Sink: strcpy() call at tools/bin2coff.c:393 copying into fixed 8-byte ShortName buffer in COFF symbol table structure
  • Missing control: No bounds checking or length validation before string copy operation
  • CWE: CWE-120 (Buffer Copy without Checking Size of Input)
  • Fix: Replaced strcpy() with strlcpy() and sprintf() with snprintf(), enforcing buffer size limits via sizeof() parameters

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Conclusion

This buffer overflow in bin2coff.c demonstrates why C's legacy string functions remain one of the most persistent sources of security vulnerabilities. By replacing unbounded strcpy() operations with bounded alternatives like strlcpy() and snprintf(), we eliminate an entire class of memory corruption bugs.

The fix is straightforward—change one function call—but the security impact is profound. Memory safety isn't just about preventing crashes; it's about maintaining the integrity of your program's control flow and data structures under adversarial conditions.

As developers, we must treat every string operation as a potential security boundary. Use bounded functions, validate input lengths, enable compiler warnings, and test with adversarial payloads. These practices transform security from a reactive measure into a proactive engineering discipline.

References

Frequently Asked Questions

What is buffer overflow in strcpy()?

Buffer overflow via strcpy() occurs when this C function copies a source string to a destination buffer without checking if the source exceeds the destination's capacity, allowing data to overwrite adjacent memory regions and corrupt program state.

How do you prevent buffer overflow in C?

Use bounded string functions like strncpy(), strlcpy(), or snprintf() that accept maximum length parameters. Always validate input lengths before copying, allocate sufficient buffer space, and enable compiler protections like stack canaries and ASLR.

What CWE is buffer overflow?

Buffer overflow is classified as CWE-120 (Buffer Copy without Checking Size of Input) or CWE-121 (Stack-based Buffer Overflow) depending on memory location. It's part of the broader CWE-119 (Improper Restriction of Operations within Memory Bounds) category.

Is using strncpy() enough to prevent buffer overflow?

Not always. While strncpy() limits copy length, it doesn't guarantee null-termination if the source fills the buffer completely. Use strlcpy() when available (guarantees null-termination) or manually add a null terminator after strncpy(). Also validate that destination size accounts for the null terminator.

Can static analysis detect buffer overflow?

Yes, modern static analysis tools can detect many buffer overflow patterns by tracking buffer sizes and string operation bounds. Tools like Coverity, CodeQL, Semgrep, and compiler warnings (-Wstringop-overflow) flag unsafe strcpy() usage and recommend bounded alternatives.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #7

Related Articles

high

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

A high-severity buffer overflow vulnerability was discovered in `src/apps/common/apputils.c`, where `strncpy()` was used without guaranteed null-termination across four call sites — including the `sock_bind_to_device()` and `getdomainname()` functions. The fix replaces all unsafe `strncpy()` calls with `snprintf()`, which enforces both length bounds and automatic null-termination. Left unpatched, these flaws could allow an attacker to corrupt memory, crash the process, or potentially execute arb

critical

How integer overflow in buffer size calculation happens in C++ and how to fix it

A critical integer overflow vulnerability was discovered in OpenCV's HAL filter implementation where multiplying image dimensions without overflow protection could allocate dangerously undersized buffers. An attacker supplying crafted image dimensions (e.g., 65536×65536) could trigger heap corruption through out-of-bounds writes. The fix promotes the calculation to 64-bit arithmetic with a single cast.

critical

How buffer overflow via strcpy() happens in C zlib and how to fix it

A critical buffer overflow vulnerability was discovered in `general/libzlib/gzlib.c` where multiple `strcpy()` and `strcat()` calls operated without bounds checking. An attacker controlling file paths or error messages could overflow destination buffers, potentially achieving arbitrary code execution. The fix replaces these unsafe string operations with bounded `memcpy()` calls that respect pre-calculated buffer lengths.

critical

How buffer overflow in rcdevice.c request parser happens in C and how to fix it

A critical buffer overflow vulnerability was discovered in `src/main/io/rcdevice.c` at line 489, where the RC device request parser wrote incoming data into a fixed-size buffer without validating against the hard-coded maximum capacity `RCDEVICE_PROTOCOL_MAX_DATA_SIZE`. An attacker controlling the device's I/O data stream could overflow the buffer by sending a payload longer than `expectedDataLength`, potentially achieving arbitrary code execution. The fix adds a second bounds check against the

critical

How buffer overflow via unchecked memcpy offset happens in C++ PCL point cloud parsing and how to fix it

A critical out-of-bounds read vulnerability was discovered in `pcpatch_pcl.cpp` where the `readFloat` lambda performed a `memcpy` operation using an untrusted offset value without validating buffer boundaries. An attacker could craft malicious PCD point cloud files with large offset values to read memory outside allocated buffers, potentially leaking sensitive data or causing crashes. The fix adds a bounds check ensuring `f->offset + sizeof(float)` stays within the row buffer before any memory c

critical

How buffer overflow in stb_image.h memcpy happens in C image parsing and how to fix it

A critical buffer overflow vulnerability was discovered in stb_image.h at line 4823, where a memcpy operation copied image data without validating buffer bounds. The multiplication of width (x) and channel count (img_n) could overflow or exceed allocated memory, allowing attackers to corrupt memory through malicious PNG files. The fix adds an explicit size_t cast to prevent integer overflow during the buffer size calculation.