Weakness reference
CWE-170

Improper Null Termination

Improper null termination occurs when a string is not correctly terminated with a null character or equivalent terminator, causing the software to read beyond…

01Summary

Improper null termination occurs when a string is not correctly terminated with a null character (or equivalent terminator), causing the software to read beyond the intended string boundary. This can lead to information disclosure, crashes, or unexpected behavior when functions expect a properly terminated string. It is particularly common in languages like C and C++ where null termination is not enforced by the language itself.

02How It Happens

Many string-handling functions in C and C++ rely on a null terminator (\0) to determine where a string ends. When a developer manually manages memory or copies data without ensuring proper null termination, the string becomes malformed. Functions like strlen(), strcpy(), or printf() will continue reading memory past the intended boundary until they encounter a null byte—potentially reading sensitive data from adjacent memory or causing a crash. This is especially problematic when copying user input into fixed-size buffers without accounting for the terminator.

03Real-World Impact

An attacker or unintended code path can read sensitive information from memory adjacent to the unterminated string, such as passwords, tokens, or other application data. In some cases, improper null termination can cause a denial of service by triggering a crash when the string is processed. The severity depends on what data lies in memory after the buffer and whether the application exposes that data to an attacker.

04Vulnerable & Fixed Patterns

Vulnerable pattern
import ctypes

# Simulating C-style string handling in Python
buffer = ctypes.create_string_buffer(10)
user_input = b"HelloWorld"  # 10 bytes, no room for null terminator

# Copying without null termination
ctypes.memmove(buffer, user_input, len(user_input))

# When passed to C functions expecting null termination, 
# they may read past the buffer boundary
print(ctypes.string_at(buffer))  # Undefined behavior

Why it's vulnerable:
The buffer is filled completely with user input, leaving no space for the null terminator. C functions that expect null-terminated strings will read past the buffer boundary.

Fixed pattern
import ctypes

buffer = ctypes.create_string_buffer(10)
user_input = b"HelloWorld"

# Ensure the input fits with room for null terminator
if len(user_input) < len(buffer):
    ctypes.memmove(buffer, user_input, len(user_input))
    buffer[len(user_input)] = 0  # Explicitly set null terminator
    print(ctypes.string_at(buffer))
else:
    raise ValueError("Input too long for buffer")
Vulnerable pattern
<?php
// Simulating low-level string handling (rare in modern PHP, but possible with FFI)
$buffer_size = 10;
$user_input = "HelloWorld";  // 10 characters

// Manually copying without null termination
$buffer = substr($user_input, 0, $buffer_size);

// If this buffer is passed to a C function via FFI expecting null termination,
// it may read beyond the intended boundary
echo $buffer;  // No null terminator appended
?>

Why it's vulnerable:
The string is truncated to fit the buffer size but no null terminator is explicitly added, which can cause issues if the buffer is passed to C functions or low-level operations.

Fixed pattern
<?php
$buffer_size = 10;
$user_input = "HelloWorld";

// Ensure input fits with room for null terminator
if (strlen($user_input) < $buffer_size) {
    $buffer = $user_input . "\0";  // Explicitly append null terminator
    echo $buffer;
} else {
    // Truncate and ensure null termination
    $buffer = substr($user_input, 0, $buffer_size - 1) . "\0";
    echo $buffer;
}
?>

05Prevention Checklist

Always allocate buffer space with room for a null terminator (size + 1 for the \0 byte).
Use safe string functions that enforce null termination: strncpy() with explicit termination, snprintf(), or language-native string types.
When copying user input, validate the length before copying and explicitly set the null terminator after the data.
Avoid manual memory management for strings; use standard library functions or language-native string types (e.g., std::string in C++, native strings in Python/PHP).
Test with inputs that are exactly the buffer size minus one to ensure the null terminator is always present.
Use static analysis tools to detect missing null terminators in string operations.

06Signs You May Already Be Affected

Look for crashes or unexpected behavior when processing strings, especially in logs showing segmentation faults or memory access violations. If you see information leakage in error messages or debug output that includes data beyond the expected string boundary, it may indicate improper null termination. Review code that manually manages buffers or uses low-level C functions; these are the most common sources of this weakness.

07Related Recent Vulnerabilities