Main Content

CWE Rule 464

Addition of Data Structure Sentinel

Since R2026a

Description

The accidental addition of a data-structure sentinel can cause serious programming logic problems.

Polyspace Implementation

The rule checker checks for:

  • Unsafe conversion from string to numeric value

  • Input string not null-terminated

Examples

expand all

Issue

This issue occurs when you perform conversions from strings to integer or floating-point values and your conversion method does not include robust error handling.

Risk

Converting a string to numerical value can cause data loss or misinterpretation. Without validation of the conversion or error handling, your program continues with invalid values.

Fix

To fix the use, do one of the following:

  • Add additional checks to validate the numerical value.

  • Use a more robust string-to-numeric conversion function such as strtol, strtoll, strtoul, or strtoull.

Example — Conversion With atoi

In this example, argv1 is converted to an integer with atoi. atoi does not provide errors for an invalid integer string. The conversion can fail unexpectedly.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static int demo_check_string_not_empty(char *s)
{
    if (s != NULL)
        return strlen(s) > 0; /* check string null-terminated and not empty */
    else
        return 0;
}

int unsafestrtonumeric(char* argv1)
{
    int s = 0;
    if (demo_check_string_not_empty(argv1))
    {
        s = atoi(argv1); // Noncompliant
    }
    return s;
}
Correction — Use strtol Instead

One possible correction is to use strtol to validate the input string and the converted integer.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>

static int demo_check_string_not_empty(char *s)
{
    if (s != NULL)
        return strlen(s) > 0; /* check string null-terminated and not empty */
    else
        return 0;
}

int unsafestrtonumeric(char *argv1)
{
    char *c_str = argv1;
    char *end;
    long sl;

    if (demo_check_string_not_empty(c_str))
    {
        errno = 0; /* set errno for error check */
        sl = strtol(c_str, &end, 10);
        if (end == c_str)
        {
            (void)fprintf(stderr, "%s: not a decimal number\n", c_str);
        }
        else if ('\0' != *end)
        {
            (void)fprintf(stderr, "%s: extra characters: %s\n", c_str, end);
        }
        else if ((LONG_MIN == sl || LONG_MAX == sl) && ERANGE == errno)
        {
            (void)fprintf(stderr, "%s out of range of type long\n", c_str);
        }
        else if (sl > INT_MAX)
        {
            (void)fprintf(stderr, "%ld greater than INT_MAX\n", sl);
        }
        else if (sl < INT_MIN)
        {
            (void)fprintf(stderr, "%ld less than INT_MIN\n", sl);
        }
        else
        {
            return (int)sl;
        }
    }
    return 0;
}
Issue

This issue occurs when both of these conditions are true:

  • You obtain a string from an input function that does not necessarily terminates the string by a null character.

  • You use the input string that does not have the terminating null character in places where a null-terminated string is expected.

For example, in this code, the constructor of std::string expects a string terminated by a null character, but str is not null-terminated.

    char str[10];
    scanf("%10c", str);
    std::string S(str);//Null-terminated string expected 
Polyspace® reports a violation of this rule.

Risk

Functions in the C++ library assume that a valid string is terminated by a null character and apply this assumption string algorithms. Using these functions and algorithms with a string that lacks a terminating null character results in undefined behavior.

Fix

The fix for this issue depends on the context:

  • You can fix this issue by terminating raw input strings by a null. For example, this code declares str with 11 elements. After filling the first 10 elements with the raw input, assign the last element the value '\0'. After manually terminating the input string with a null character, you can use the input string with standard template library (STL) string functions without violating this rule.

        char str[11];
        scanf("%10c", str);
        str[10] = '\0';
        std::string S(str);//Valid string

  • Some C++ functions accepts character pointers or substrings as input. These functions can correctly handle a raw character array without a terminating null character. For instance, This code constructs the std::string object S by using a nondefault constructor. This constructor allows the use of str, which lacks a terminating null character. Such uses do not violate this rule.

        char str[10];
        scanf("%10c", str);
        std::string S(str,sizeof(str));//Valid use of substring

Example — Print Input String Without Terminating Null Character

In this example, the read function accepts an array of characters, which is then stored in the char array buffer. Because bufferdoes not have a terminating null character, using buffer with the function printf() results in undefined behavior. Polyspace reports a violation of this rule.

#include <iostream>
#include <string>
#include <fstream>
#include <cstdio>
void echo_instream(std::istream& instream) {
    //...
    char buffer[10];
    instream.read(buffer,sizeof(buffer));
	//...
    printf("%s", buffer); //Noncompliant
	//...
}

Correction — Terminate Input String with '\0'

To fix this issue, manually add the terminating null character at the end of buffer.

#include <iostream>
#include <string>
#include <fstream>
#include <cstdio>
void echo_instream(std::istream& instream) {
    //...
    char buffer[10];
    instream.read(buffer,sizeof(buffer)-1);
    buffer[9] = '\0';
	//...
    printf("%s", buffer); //Compliant
	//...
}

Check Information

Category: Data Neutralization Issues
PQL Name: std.cwe_native.R464

Version History

Introduced in R2026a