Safeguard
Application Security•

CWE-135 Incorrect Calculation of Multi-Byte String Length

Counting characters when you need bytes, or the reverse, sizes buffers wrong. See how wide and multi-byte strings cause overflows and how to avoid it.

Safeguard Security Team
3 min read

CWE-135 is the incorrect calculation of the length of strings that can contain wide or multi-byte characters. The root cause is a simple mismatch. One part of the code counts characters, another counts bytes, and the buffer is sized with the wrong one.

MITRE lists C and C++ as the affected languages. It matters for anything that handles Unicode, wide character APIs, or text in encodings like UTF-8 and UTF-16.

How it happens

In a single-byte encoding, one character is one byte, and strlen is the answer. With wide characters, one character may occupy two or four bytes. In UTF-8, one character takes between one and four bytes. The same text has different lengths depending on the unit.

// Vulnerable: wchar_t is 2 or 4 bytes, but the size counts characters
wchar_t *copy_wide(const wchar_t *src) {
    size_t n = wcslen(src);            // characters
    wchar_t *dst = malloc(n + 1);      // bytes, too small by a factor of 2 or 4
    wcscpy(dst, src);
    return dst;
}

The allocation is measured in bytes, but n + 1 is a count of characters. The copy then writes several times more data than the buffer holds.

// Fixed: multiply by the element size
wchar_t *copy_wide(const wchar_t *src) {
    size_t n = wcslen(src) + 1;
    if (n > SIZE_MAX / sizeof(wchar_t)) return NULL;
    wchar_t *dst = malloc(n * sizeof(wchar_t));
    if (!dst) return NULL;
    wmemcpy(dst, src, n);
    return dst;
}

The reverse mistake also happens: a bounds check made in characters but applied to a buffer measured in bytes, or a conversion from a wide string to UTF-8 where the output buffer was sized as if each character became one byte.

What an attacker gains

MITRE lists three consequences.

  • Code execution. The weakness may lead to a buffer overflow. Overflows can often be used to execute arbitrary code outside the product's implicit security policy.
  • Crashes and resource use. Out-of-bounds memory access can corrupt relevant memory, and perhaps instructions, possibly leading to a crash.
  • Memory disclosure. An out-of-bounds read can expose sensitive information, including details such as the current position of the buffer in memory, which helps craft further attacks.

How to find it

MITRE names automated static analysis, which can find some instances by analyzing source code without running it. Practical additions:

  • Test with non-ASCII input in every text field. Use two-byte, three-byte and four-byte UTF-8 sequences, not just accented Latin letters.
  • Search for allocations next to wcslen, mbstowcs and wcstombs and check that the units agree.
  • Run those tests with AddressSanitizer so a size mismatch fails the test.

How to fix it

The record lists no mitigations. These steps follow from the definition.

  1. Decide on a unit for every length variable and name it, for example len_bytes and len_chars.
  2. Multiply by sizeof the element type when allocating for wide strings.
  3. Use the conversion functions' size query mode to learn how many bytes the output needs before allocating.
  4. Prefer string types that manage their own size.
  5. Validate encoding on input so malformed sequences are rejected early.

Quick check

Why does ASCII-only testing miss this bug?

With ASCII, characters and bytes are the same count, so the two lengths agree. The mismatch only appears when input includes wide or multi-byte characters.

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.