Main Content

CWE Rule 135

Incorrect Calculation of Multi-Byte String Length

Since R2023a

Description

Rule Description

The software does not correctly calculate the length of strings that can contain wide or multi-byte characters.

Polyspace Implementation

The rule checker checks for these issues:

  • Destination buffer overflow in string manipulation

  • Misuse of narrow or wide character string

  • Unreliable cast of pointer

Examples

expand all

Issue

This issue occurs when certain string manipulation functions write to their destination buffer argument at an offset greater than the buffer size.

For instance, when calling the function sprintf(char* buffer, const char* format), you use a constant string format of greater size than buffer.

Risk

Buffer overflow can cause unexpected behavior such as memory corruption or stopping your system. Buffer overflow also introduces the risk of code injection.

Fix

One possible solution is to use alternative functions to constrain the number of characters written. For instance:

  • If you use sprintf to write formatted data to a string, use snprintf, _snprintf or sprintf_s instead to enforce length control. Alternatively, use asprintf to automatically allocate the memory required for the destination buffer.

  • If you use vsprintf to write formatted data from a variable argument list to a string, use vsnprintf or vsprintf_s instead to enforce length control.

  • If you use wcscpy to copy a wide string, use wcsncpy, wcslcpy, or wcscpy_s instead to enforce length control.

Another possible solution is to increase the buffer size.

Example — Buffer Overflow in sprintf Use
#include <stdio.h>

void func(void) {
    char buffer[20];
    char *fmt_string = "This is a very long string, it does not fit in the buffer";

    sprintf(buffer, fmt_string);  //Noncompliant
}

In this example, buffer can contain 20 char elements but fmt_string has a greater size.

Correction — Use snprintf Instead of sprintf

One possible correction is to use the snprintf function to enforce length control.

#include <stdio.h>

void func(void) {
    char buffer[20];
    char *fmt_string = "This is a very long string, it does not fit in the buffer";

    snprintf(buffer, 20, fmt_string);
}
Issue

This issue occurs when you pass a narrow character string to a wide string function, or a wide character string to a narrow string function.

Misuse of narrow or wide character string raises no defect on operating systems where narrow and wide character strings have the same size.

Risk

Using a narrow character string with a wide string function, or vice versa, can result in unexpected or undefined behavior.

If you pass a wide character string to a narrow string function, you can encounter these issues:

  • Data truncation. If the string contains null bytes, a copy operation using strncpy() can terminate early.

  • Incorrect string length. strlen() returns the number of characters of a string up to the first null byte. A wide string can have additional characters after its first null byte.

If you pass a narrow character string to a wide string function, you can encounter this issue:

  • Buffer overflow. In a copy operation using wcsncpy(), the destination string might have insufficient memory to store the result of the copy.

Fix

Use the narrow string functions with narrow character strings. Use the wide string functions with wide character strings.

Example — Passing Wide Character Strings to strncpy()
#include <string.h>
#include <wchar.h>

void func(void)
{
    wchar_t wide_str1[]  = L"0123456789";
    wchar_t wide_str2[] =  L"0000000000";
    strncpy(wide_str2, wide_str1, 10); //Noncompliant 
}

In this example, strncpy() copies 10 wide characters from wide_strt1 to wide_str2. If wide_str1 contains null bytes, the copy operation can end prematurely and truncate the wide character string.

Correction — Use wcsncpy() to Copy Wide Character Strings

One possible correction is to use wcsncpy() to copy wide_str1 to wide_str2.

#include <string.h>
#include <wchar.h>

void func(void)
{
    wchar_t wide_str1[]  = L"0123456789";
    wchar_t wide_str2[] =  L"0000000000";
    wcsncpy(wide_str2, wide_str1, 10);
}
Issue

This issue occurs when a pointer is implicitly cast to a data type different from its declaration type. Such an implicit casting can take place, for instance, when a pointer to data type char is assigned the address of an integer.

This defect applies only if the code language for the project is C.

Risk

Casting a pointer to data type different from its declaration type can result in issues such as buffer overflow. If the cast is implicit, it can indicate a coding error.

Fix

Avoid implicit cast of a pointer to a data type different from its declaration type.

See examples of fixes below.

If you do not want to fix the issue, add comments to your result or code to avoid another review. See:

Example — Unreliable cast of pointer error
 #include <string.h>
 
 void Copy_Integer_To_String()
 {
  int src[]={1,2,3,4,5,6,7,8,9,10};
  char buffer[]="Buffer_Text";
  strcpy(buffer,src);  //Noncompliant
  /* Defect: Implicit cast of (int*) to (char*) */
 }

src is declared as an int* pointer. The strcpy statement, while copying to buffer, implicitly casts src to char*. In C++, such a cast fails to compile.

Correction — Avoid Pointer Cast

One possible correction is to declare the pointer src with the same data type as buffer.

 #include <string.h>
  void Copy_Integer_To_String()
 {
  /* Fix: Declare src with same type as buffer */
  char *src[10]={"1","2","3","4","5","6","7","8","9","10"};  
  char *buffer[10];

  for(int i=0;i<10;i++)
    buffer[i]="Buffer_Text";

  for(int i=0;i<10;i++)
    buffer[i]= src[i];
  }

Check Information

Category: String Errors

Version History

Introduced in R2023a