Safeguard
Application Security•

CWE-124 Buffer Underwrite: Writing Before the Start of a Buffer

A buffer underwrite writes to memory before a buffer begins. Learn the typical causes, impact and fixes, with a short C example and detection steps.

Safeguard Security Team
3 min read

CWE-124, Buffer Underwrite or Buffer Underflow, is the mirror image of the usual overflow. The product writes to a buffer using an index or pointer that references a memory location prior to the beginning of the buffer. Instead of running off the end, the code steps off the front.

It affects memory-unsafe code, C and C++ according to MITRE. Anything that walks backwards through data, trims whitespace, parses from the right or uses a computed index can hit it.

How it happens

Underwrites come from indexes and pointers that go below zero, or below the start of the buffer. MITRE's observed examples show three common routes.

  • A counter decremented too far. CVE-2007-1584 is a buffer underflow from an all-whitespace string, which causes a counter to be decremented before the buffer while looking for a non-whitespace character.
  • Inconsistent length values. CVE-2007-4580 is an underflow from a small size value with a large buffer, a length parameter inconsistency.
  • Unchecked lengths from the network. CVE-2002-2227 is an unchecked length of an SSLv2 challenge value leading to an underflow.

MITRE also lists CVE-2021-24018, a buffer underwrite in a firmware verification routine that allows code execution via a crafted firmware image.

Here is the trimming bug in its simplest form.

// Vulnerable: if s is all spaces, end goes below s
void rtrim(char *s) {
    char *end = s + strlen(s) - 1;
    while (*end == ' ') {
        end--;               // can step before the start of s
    }
    end[1] = '\0';
}

For an empty or all-space string, end moves before s, and the final write lands outside the buffer. The fix is to check the lower bound in the loop.

// Fixed: never go below the start
void rtrim(char *s) {
    size_t n = strlen(s);
    while (n > 0 && s[n - 1] == ' ') {
        n--;
    }
    s[n] = '\0';
}

What an attacker gains

MITRE lists these consequences.

  • Crashes. Out-of-bounds memory access very likely corrupts relevant memory, and perhaps instructions, which can crash the program.
  • Code execution. If the corrupted memory can be effectively controlled, it may be possible to execute arbitrary code. If the corrupted memory is data rather than instructions, the program may keep running with improper values.
  • Subverting protections. Code execution can often be used to subvert any other security service.

How to find it

  • Static analysis. SAST can find some instances by analyzing source code or binaries.
  • Runtime checks. AddressSanitizer inserts memory safety checks at compile time and flags writes before the buffer start.
  • Edge case tests. Feed empty strings, all-whitespace strings, zero lengths and negative values. Underflows live at the edges.

How to fix it

The record lists no mitigations, so these come from the causes above.

  1. Check the lower bound everywhere you decrement an index or pointer.
  2. Prefer index variables that are unsigned and checked against zero before decrementing, or use signed types with explicit range checks.
  3. Validate length fields from untrusted sources, including very small ones.
  4. Use library string and container functions instead of hand-rolled backwards loops.
  5. Add edge case inputs to unit tests and fuzz corpora.

Quick check

How is an underwrite different from an overflow?

An overflow writes after the end of the buffer. An underwrite writes before the beginning. The impact is similar: memory corruption, crashes and possible code execution.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.