CWE Rule 704
Description
Rule Description
The software does not correctly convert an object, resource, or structure from one type to a different type.
Polyspace Implementation
The rule checker checks for these issues:
- Cast to pointer pointing to object of different type 
- Character value absorbed into EOF 
- Conversion between pointer and integer 
- Integer conversion overflow 
- Misuse of sign-extended character value 
- Precision loss in integer to float conversion 
- Qualifier removed in conversion 
- Reading memory reallocated from object of another type without reinitializing first 
- Sign change integer conversion overflow 
- Tainted sign change conversion 
- Unreliable cast of pointer 
- Unsafe conversion between pointer and integer 
- Unsigned integer conversion overflow 
- Wrong allocated object size for cast 
Examples
The issue occurs when you perform a cast between a pointer to an object type and a pointer to a different object type.
If a pointer to an object is cast into a pointer to a different object, the resulting pointer can be incorrectly aligned. The incorrect alignment causes undefined behavior.
Even if the conversion produces a pointer that is correctly aligned, the behavior can be undefined if the pointer is used to access an object.
Exception: You can convert a pointer to object type into a pointer to one of these types:
- char
- signed char
- unsigned char
signed   char *p1;
unsigned int *p2;
void foo(void){ 
  p2 = ( unsigned int * ) p1;     /* Non-compliant */				
}In this example, p1 can point to a signed
                        char object. However, p1 is cast to a pointer
                    that points to an object of wider type, unsigned int.
extern unsigned int read_value ( void );
extern void display ( unsigned int n );
void foo ( void ){
  unsigned int u = read_value ( );
  unsigned short *hi_p = ( unsigned short * ) &u;    /* Non-compliant  */	
  *hi_p = 0;                                         
  display ( u );                                     
}In this example, u is an unsigned int
                    variable. &u is cast to a pointer that points to an
                    object of narrower type, unsigned short.
On a big-endian machine, the statement *hi_p = 0 attempts
                    to clear the high bits of the memory location that &u
                    points to. But, from the result of display(u), you might find
                    that the high bits have not been cleared.
const short *p;
const volatile short *q;
void foo (void){
  q = ( const volatile short * ) p;  /* Compliant */								
}In this example, both p and q can point
                    to short objects. The cast between them adds a
                        volatile qualifier only and is therefore
                    compliant.
This issue occurs
when you perform a data type conversion that makes a valid character
value indistinguishable from EOF (End-of-File).
Bug Finder flags the defect in one of the following situations:
- End-of-File: You perform a data type conversion such as from - intto- charthat converts a non-EOF character value into- EOF.You then compare the result with EOF.- char ch = (char)getchar()The conversion can be explicit or implicit.- if((int)ch == EOF)
- Wide End-of-File: You perform a data type conversion that can convert a non-WEOF wide character value into WEOF, and then compare the result with WEOF. 
The data type char cannot hold the value EOF that
indicates the end of a file. Functions such as getchar have
return type int to accommodate EOF.
If you convert from int to char,
the values UCHAR_MAX (a valid character value)
and EOF get converted to the same value -1 and
become indistinguishable from each other. When you compare the result
of this conversion with EOF, the comparison can
lead to false detection of EOF. This rationale
also applies to wide character values and WEOF.
Perform the comparison with EOF or WEOF before
conversion.
#include <stdio.h>
#include <stdlib.h>
#define fatal_error() abort()
char func(void)
{
    char ch;
    ch = getchar();
    if (EOF == (int)ch) {  //Noncompliant
        fatal_error();
    }
    return ch;
}In this example, the return value of getchar is
implicitly converted to char. If getchar returns UCHAR_MAX,
it is converted to -1, which is indistinguishable from EOF. When you
compare with EOF later, it can lead to a false positive.
One possible correction is to first perform the comparison with
EOF, and then convert from int to char.
#include <stdio.h>
#include <stdlib.h>
#define fatal_error() abort()
char func(void)
{
    int i;               
    i = getchar();       
    if (EOF == i) {      
        fatal_error();
    }
    else {
        return (char)i;
    }
}
The issue occurs when you convert an integral type into a raw pointer type. Polyspace® reports the conversion as a violation of the rule regardless of the sizes of the integral and raw pointer types. For instance, if an integer originates from a pointer and then later, is cast into a pointer, Polyspace flags the conversion from integer to pointer. In this case, the integer and the pointer have the same size.
The mapping between pointers and integers is not always consistent with the addressing structure of the environment.
Converting from integers to pointers can create:
- Misaligned pointers or misaligned objects. 
- Invalid pointer addresses. 
Where possible, avoid integer-to-pointer conversions. If you want to convert a
                        void pointer to an integer, so that you do not change the
                    value, use types: 
- C99 — - intptr_tor- uintptr_t
- C90 — - size_tor- ssize_t
unsigned int* badintptrcast(void)
{
    int* ptr;
    unsigned long long int_same_as_ptr ;
    unsigned int int_smaller_than_ptr;
    unsigned int* ptr0 = (unsigned int*)0xdeadbeef; //Noncompliant
    
    /*int to ptr of same size*/
    ptr = (int*)int_same_as_ptr;  //Noncompliant
    
    /*int to ptr of different size*/
    ptr = (int*)int_smaller_than_ptr;  //Noncompliant
    return (unsigned int*)(ptr0 - (unsigned int*)ptr);  //Noncompliant
}In this example, Polyspace flags the conversions that might be unsafe. For instance:
- The conversion of - 0xdeadbeefto- unsigned int*causes alignment issues for the pointer. Polyspace flags the conversion.
- The conversion of the - int_same_as_ptrand- int_smaller_than_ptrto- int*pointers might result in invalid pointer address. Polyspace flags these conversion.
- The - returnstatement casts- ptrdiff_tto a pointer. This pointer might not point to an invalid address. Polyspace flags the conversion.
intptr_tOne possible correction is to use intptr_t types to store
                    addresses. When storing the result of subtracting two pointers, use the type
                        ptrdiff_t.
#include<stdint.h>
#include<stddef.h>
ptrdiff_t badintptrcast(void)
{
    intptr_t ptr;
    unsigned long long int_same_as_ptr ;
    unsigned int int_smaller_than_ptr;
    intptr_t ptr0 = (intptr_t)0xdeadbeef; //Compliant
    /*int to ptr of same size*/
    ptr = (intptr_t)int_same_as_ptr;  //Compliant
    
    /*int to ptr of different size*/
    ptr = (intptr_t)int_smaller_than_ptr;  //Compliant
    return (ptrdiff_t)ptr0;//Compliant
    
}This issue occurs when converting an integer to a
                    smaller integer type. If the variable does not have enough bytes to represent
                    the original value, the conversion overflows. For instance, if you perform a
                    comparison between implementation-defined type time_t and a
                    signed integer, Polyspace reports a violation because time_t might be
                    implemented as an unsigned integer.
The checker also detects comparison
The exact storage allocation for different floating point types depends on your
            processor. See Target processor type (-target).
Integer conversion overflows result in undefined behavior.
The fix depends on the root cause of the defect. Often the result details (or source code tooltips in Polyspace as You Code) show a sequence of events that led to the defect. You can implement the fix on any event in the sequence. If the result details do not show this event history, you can search for previous references of variables relevant to the defect using right-click options in the source code and find related events. See also Interpret Bug Finder Results in Polyspace Desktop User Interface or Interpret Bug Finder Results in Polyspace Access Web Interface (Polyspace Access).
You can fix the defect by:
- Using a bigger data type for the result of the conversion so that all values can be accommodated. 
- Checking for values that lead to the overflow and performing appropriate error handling. 
In general, avoid conversions to smaller integer types.
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:
- Address Results in Polyspace User Interface Through Bug Fixes or Justifications if you review results in the Polyspace user interface. 
- Address Results in Polyspace Access Through Bug Fixes or Justifications (Polyspace Access) if you review results in a web browser. 
- Annotate Code and Hide Known or Acceptable Results if you review results in an IDE. 
A default Bug Finder analysis might not raise this defect when the input values are unknown and only a subset of inputs cause an issue. To check for defects caused by specific system input values, run a stricter Bug Finder analysis. See Extend Bug Finder Checkers to Find Defects from Specific System Input Values.
char convert(void) {
    int num = 1000000;
    return (char)num;  //Noncompliant
}In the return statement, the integer variable num is
converted to a char. However, an 8-bit or 16-bit
character cannot represent 1000000 because it requires at least 20
bits. So the conversion operation overflows.
One possible correction is to convert to a different integer type that can represent the entire number.
long convert(void) {
    int num = 1000000;
    return (long)num;
}This issue occurs when you
            convert a signed or plain char variable containing possible negative
            values to a wider integer data type (or perform an arithmetic operation that does the
            conversion) and then use the resulting value in one of these ways:
- For comparison with - EOF(using- ==or- !=)
- As array index 
- As argument to a character-handling function in - ctype.h, for instance,- isalpha()or- isdigit()
If you convert a signed char variable with a negative value to a
            wider type such as int, the sign bit is preserved (sign extension).
            This can lead to specific problems even in situations where you think you have accounted
            for the sign bit.
For instance, the signed char value of -1 can represent the
            character EOF (end-of-file), which is an invalid character. Suppose a
                char variable var acquires this value. If you
            treat var as a char variable, you might want to
            write special code to account for this invalid character value. However, if you perform
            an operation such as var++ (involving integer promotion), it leads to
            the value 0, which represents a valid value '\0' by accident. You
            transitioned from an invalid to a valid value through the arithmetic operation.
Even for negative values other than -1, a conversion from signed
                char to signed int can lead to other issues.
            For instance, the signed char value -126 is equivalent to the
                unsigned char value 130 (corresponding to an extended character
                '\202'). If you convert the value from char to
                int, the sign bit is preserved. If you then cast the resulting
            value to unsigned int, you get an unexpectedly large value,
            4294967170 (assuming 32-bit int). If your code expects the
                unsigned char value of 130 in the final unsigned
                int variable, you can see unexpected results.
The underlying cause of this issue is the sign extension during conversion to a wider type. Most architectures use two's complement representation for storing values. In this representation, the most significant bit indicates the sign of the value. When converted to a wider type, the conversion is done by copying this sign bit to all the leading bits of the wider type, so that the sign is preserved. For instance, the char
                    value of -3 is represented as 11111101 (assuming 8-bit char). When converted to int, the representation is:
11111111 11111111 11111111  11111101int. However, when converted to unsigned int, the value (4294967293) is no longer the same as the unsigned char
                    equivalent of the original char value. If you are not aware of this issue, you can see unexpected results in your code.In the following cases, Bug Finder flags use of variables after a conversion from
                    char to a wider data type or an arithmetic operation that
                implicitly converts the variable to a wider data type:
- If you compare the variable value with EOF: - A - charvalue of -1 can represent the invalid character- EOFor the valid extended character value- '\377'(corresponding to the- unsigned charequivalent, 255). After a- charvariable is cast to a wider type such as- int, because of sign extension, the- charvalue -1, representing one of- EOFor- '\377'becomes the- intvalue -1, representing only- EOF. The- unsigned charvalue 255 can no longer be recovered from the- intvariable. Bug Finder flags this situation so that you can cast the variable to- unsigned charfirst (or avoid the- char-to-- intconversion or converting operation before comparison with- EOF). Only then, a comparison with- EOFis meaningful. See Sign-Extended Character Value Compared with EOF.
- If you use the variable value as an array index: - After a - charvariable is cast to a wider type such as- int, because of sign extension, all negative values retain their sign. If you use the negative values directly to access an array, you cause buffer overflow/underflow. Even when you account for the negative values, the way you account for them might result in incorrect elements being read from the array. See Sign-Extended Character Value Used as Array Index.
- If you pass the variable value as argument to a character-handling function: - According to the C11 standard (Section 7.4), if you supply an integer argument that cannot be represented as - unsigned charor- EOF, the resulting behavior is undefined. Bug Finder flags this situation because negative- charvalues after conversion can no longer be represented as- unsigned charor- EOF. For instance, the signed- charvalue -126 is equivalent to the- unsigned charvalue 130, but the signed- intvalue -126 cannot be represented as- unsigned charor- EOF.
Before conversion to a wider integer data type, cast the signed or plain
                    char value explicitly to unsigned
                char.
If you use the char data type to not represent characters but
                simply as a smaller data type to save memory, your use of sign-extended
                    char values might avoid the risks mentioned earlier. If so,
                add comments to your result or code to avoid another review. See: 
- Address Results in Polyspace User Interface Through Bug Fixes or Justifications if you review results in the Polyspace user interface. 
- Address Results in Polyspace Access Through Bug Fixes or Justifications (Polyspace Access) if you review results in a web browser. 
- Annotate Code and Hide Known or Acceptable Results if you review results in an IDE. 
#include <stdio.h>
#include <stdlib.h>
#define fatal_error() abort()
extern char parsed_token_buffer[20];
static int parser(char *buf)
{
    int c = EOF;
    if (buf && *buf) {
        c = *buf++;    
    }
    return c;
}
void func()
{
    if (parser(parsed_token_buffer) == EOF) { //Noncompliant
        /* Handle error */
        fatal_error();
    }
}In this example, the function
            parser can traverse a string input buf. If a
        character in the string has the value -1, it can represent either EOF or
        the valid character value '\377' (corresponding to the unsigned
            char equivalent 255). When converted to the int variable
            c, its value becomes the integer value -1, which is always
            EOF. The later comparison with EOF will not detect
        if the value returned from parser is actually
        EOF.
unsigned char Before ConversionOne possible correction is to cast the plain char value to
                unsigned char before conversion to the wider
                int type. Only then can you test if the return value of
                parser is really EOF.
#include <stdio.h>
#include <stdlib.h>
#define fatal_error() abort()
extern char parsed_token_buffer[20];
static int parser(char *buf)
{
    int c = EOF;
    if (buf && *buf) {
        c = (unsigned char)*buf++;    
    }
    return c;
}
void func()
{
    if (parser(parsed_token_buffer) == EOF) { 
        /* Handle error */
        fatal_error();
    }
}#include <limits.h>
#include <stddef.h>
#include <stdio.h>
#define NUL '\0'
#define SOH 1    /* start of heading */
#define STX 2    /* start of text */
#define ETX 3    /* end of text */
#define EOT 4    /* end of transmission */
#define ENQ 5    /* enquiry */
#define ACK 6    /* acknowledge */
static const int ascii_table[UCHAR_MAX + 1] =
{
      [0]=NUL,[1]=SOH, [2]=STX, [3]=ETX, [4]=EOT, [5]=ENQ,[6]=ACK,
      /* ... */
      [126] = '~',
      /* ... */
      [130/*-126*/]='\202',
      /* ... */
      [255 /*-1*/]='\377'
};
int lookup_ascii_table(char c)
{
    int i;
    i = (c < 0 ? -c : c);
    return ascii_table[i];  //Noncompliant
}
In this example, the char variable c is converted to
        the int variable i. If c has
        negative values, they are converted to positive values before assignment to
            i. However, this conversion can lead to unexpected values when
            i is used as array index. For instance:
- If - chas the value -1 representing the invalid character- EOF, you want to probably treat this value separately. However, in this example, a value of- cequal to -1 leads to a value of- iequal to 1. The function- lookup_ascii_tablereturns the value- ascii_table[1](or- SOH) without the invalid character value- EOFbeing accounted for.- If you use the - chardata type to not represent characters but simply as a smaller data type to save memory, you need not worry about this issue.
- If - chas a negative value, when assigned to- i, its sign is reversed. However, if you access the elements of- ascii_tablethrough- i, this sign reversal can result in unexpected values being read.- For instance, if - chas the value -126,- ihas the value 126. The function- lookup_ascii_tablereturns the value- ascii_table[126](or- '~') but you probably expected the value- ascii_table[130](or- '\202').
Note that the example uses designated initializers for array initialization and does not compile in C++. You can adapt the example appropriately for C++ compilation.
unsigned charTo correct the issues, avoid the conversion from char to
                int. First, check c for the value
                EOF. Then, cast the value of the char variable
                c to unsigned char and use the result as array
            index.
#include <limits.h>
#include <stddef.h>
#include <stdio.h>
#define NUL '\0'
#define SOH 1    /* start of heading */
#define STX 2    /* start of text */
#define ETX 3    /* end of text */
#define EOT 4    /* end of transmission */
#define ENQ 5    /* enquiry */
#define ACK 6    /* acknowledge */
static const int ascii_table[UCHAR_MAX + 1] =
{
      [0]=NUL,[1]=SOH, [2]=STX, [3]=ETX, [4]=EOT, [5]=ENQ,[6]=ACK,
      /* ... */
      [126] = '~',
      /* ... */
      [130/*-126*/]='\202',
      /* ... */
      [255 /*-1*/]='\377'
};
int lookup_ascii_table(char c)
{
    int r = EOF;
    if (c != EOF) /* specific handling EOF, invalid character */
        r = ascii_table[(unsigned char)c]; /* cast to 'unsigned char' */
    return r;
}
This issue occurs when you cast an integer value to a floating-point type that cannot represent the original integer value.
For instance, the long int value
                        1234567890L is too large for a variable of type
                        float.
If the floating-point type cannot represent the integer value, the behavior is undefined (see C11 standard, 6.3.1.4, paragraph 2). For instance, least significant bits of the variable value can be dropped leading to unexpected results.
Convert to a floating-point type that can represent the integer value.
For instance, if the float data type cannot represent the integer
        value, use the double data type instead.
When writing a function that converts an integer to floating point type, before the conversion, check if the integer value can be represented in the floating-point type. For instance, DBL_MANT_DIG * log2(FLT_RADIX) represents the number of base-2 digits in the type double. Before conversion to the type double, check if this number is greater than or equal to the precision of the integer
                    that you are converting. To determine the precision of an integer num, use this code:
 size_t precision = 0;
 while (num != 0) {
    if (num % 2 == 1) {
      precision++;
    }
    num >>= 1;
 }Some implementations provide a builtin function to determine the precision of an
        integer. For instance, GCC provides the function
        __builtin_popcount.
#include <stdio.h>
int main(void) {
  long int big = 1234567890L;
  float approx = big;  //Noncompliant
  printf("%ld\n", (big - (long int)approx));
  return 0;
}In this C code, the long int
    variable big is converted to float.
One possible correction is to convert to the double data type
          instead of float.
#include <stdio.h>
int main(void) {
  long int big = 1234567890L;
  double approx = big;
  printf("%ld\n", (big - (long int)approx));
  return 0;
}This checker is deactivated in a default Polyspace as You Code analysis. See Checkers Deactivated in Polyspace as You Code Analysis (Polyspace Access).
This issue occurs during a pointer
            conversion when one pointer has a qualifier and the other does not. For example, when
            converting from a const int* to an int*, the
            conversion removes the const qualifier.
This defect applies only for projects in C.
Qualifiers such as const or volatile in a pointer declaration:
const int* ptr;const or volatile. These qualifiers act as instructions to the compiler. For instance, a const object is not supposed to be modified in the code and a
                        volatile object is not supposed to be optimized away by the compiler.If a second pointer points to the same object but does not use the same qualifier,
                the qualifier on the first pointer is no longer valid. For instance, if a
                    const int* pointer and an int* pointer
                point to the same object, you can modify the object through the second pointer and
                violate the contract implied by the const qualifier in the first
                pointer.
If you intend to convert from one pointer to another, declare both pointers with the same qualifiers.
void implicit_cast(void) {
    const char  cc, *pcc = &cc;
    char * quo;
    quo = &cc;  //Noncompliant
    quo = pcc;  //Noncompliant
    read(quo);
}During the assignment to the character q,
the variables, cc and pcc, are
converted from const char to char.
The const qualifier is removed during the conversion
causing a defect.
One possible correction is to add the same
qualifiers to the new variables. In this example, changing q to
a const char fixes the defect.
void implicit_cast(void) {
    const char  cc, *pcc = &cc;
    const char * quo;
    quo = &cc;
    quo = pcc;
    read(quo);
}One possible correction is to remove the qualifiers
in the converted variable. In this example, removing the const qualifier
from the cc and pcc initialization
fixes the defect.
void implicit_basic_cast(void) {
    char  cc, *pcc = &cc;
    char * quo;
    quo = &cc;
    quo = pcc;
    read(quo);
}This issue occurs when you do the following in sequence:
- Reallocate memory to an object with a type that is different from the original allocation. - For instance, in this code snippet, a memory originally allocated to a pointer with type - struct A*is reallocated to a pointer with type- struct B*:- struct A; struct B; struct A *Aptr = (struct A*) malloc(sizeof(struct A)); struct B *Bptr = (struct B*) realloc(Aptr, sizeof(struct B));
- Read from this reallocated memory without reinitializing the memory first. - Read accesses on the pointer to the reallocated memory can happen through pointer dereference or array indexing. Passing the pointer to a function that takes a pointer to a - const-qualified object as the corresponding parameter also counts as a read access.
Reading from reallocated memory that has not been reinitialized leads to undefined behavior.
Reinitialize memory after reallocation and before the first read access.
The checker considers any write access on the pointer to the reallocated
                    memory as satisfying the reinitialization requirement (even if the object might
                    only be partially reinitialized). Write accesses on the pointer to the
                    reallocated memory can happen through pointer dereference or array indexing.
                    Passing the pointer to a function that takes a pointer to a
                        non-const-qualified object as the corresponding parameter
                    also counts as a write access.
#include<stdlib.h>
struct group {
    char *groupFirst;
    int groupSize;
};
struct groupWithID {
    int groupID;
    char *groupFirst;
    int groupSize;
};
char* readName();
int readSize();
void createGroup(int nextAvailableID) {
    struct group *aGroup;
    struct groupWithID *aGroupWithID;
    
    aGroup = (struct group*) malloc(sizeof(struct group));
    
    if(!aGroup) {
        /*Handle error*/
    }
    
    aGroup->groupFirst = readName();
    aGroup->groupSize  = readSize();
    
    /* Reassign to group with ID */
    aGroupWithID = 
        (struct groupWithID*) realloc(aGroup, sizeof(struct groupWithID)); //Noncompliant
    if(!aGroupWithID) {
        free(aGroup);
        /*Handle error*/
    }
    
    if(aGroupWithID -> groupSize > 0) { /* Noncompliant */
        /* ... */
    }
    
    /* ...*/
    free(aGroupWithID);
}
In this example, the memory allocated to a group* pointer
                    using the malloc function is reallocated to a
                        groupWithID* pointer using the realloc
                    function. There is a read access on the reallocated memory before the memory is
                    reinitialized, causing a violation. The reallocation operation allocates memory
                    the size of which is not a multiple of the destination type, causing a violation
                    because of the issue Wrong allocated object size for
                        cast.
Reinitialize the memory assigned to the groupWithID*
                    pointer before the first read access. All bits of the memory can be
                    reinitialized using the memset function.
#include<stdlib.h>
#include<string.h>
struct group {
    char *groupFirst;
    int groupSize;
};
struct groupWithID {
    int groupID;
    char *groupFirst;
    int groupSize;
};
char* readName();
int readSize();
void createGroup(int nextAvailableID) {
    struct group *aGroup;
    struct groupWithID *aGroupWithID;
    
    aGroup = (struct group*) malloc(sizeof(struct group));
    
    if(!aGroup) {
        /*Handle error*/
    }
    
    aGroup->groupFirst = readName();
    aGroup->groupSize  = readSize();
    
    /* Reassign to group with ID */
    aGroupWithID = 
        (struct groupWithID*) realloc(aGroup, sizeof(struct groupWithID)); //Compliant
    if(!aGroupWithID) {
        free(aGroup);
        /*Handle error*/
    }
    
    memset(aGroupWithID, 0 , sizeof(struct groupWithID));
    /* Reinitialize group */
    if(aGroupWithID -> groupSize > 0) { 
        /* ... */
    }
    
    /* ...*/
    free(aGroupWithID);
}
The violation because of the issue Wrong allocated object size for cast remains in this corrected code.
This issue occurs when converting an unsigned integer to a signed integer. If the variable does not have enough bytes to represent both the original constant and the sign bit, the conversion overflows.
The exact storage allocation for different floating point types depends on your
            processor. See Target processor type (-target).
The fix depends on the root cause of the defect. Often the result details (or source code tooltips in Polyspace as You Code) show a sequence of events that led to the defect. You can implement the fix on any event in the sequence. If the result details do not show this event history, you can search for previous references of variables relevant to the defect using right-click options in the source code and find related events. See also Interpret Bug Finder Results in Polyspace Desktop User Interface or Interpret Bug Finder Results in Polyspace Access Web Interface (Polyspace Access).
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:
- Address Results in Polyspace User Interface Through Bug Fixes or Justifications if you review results in the Polyspace user interface. 
- Address Results in Polyspace Access Through Bug Fixes or Justifications (Polyspace Access) if you review results in a web browser. 
- Annotate Code and Hide Known or Acceptable Results if you review results in an IDE. 
A default Bug Finder analysis might not raise this defect when the input values are unknown and only a subset of inputs cause an issue. To check for defects caused by specific system input values, run a stricter Bug Finder analysis. See Extend Bug Finder Checkers to Find Defects from Specific System Input Values.
char sign_change(void) {
    unsigned char count = 255;
    return (char)count;  //Noncompliant
}In the return statement, the unsigned character
variable count is converted to a signed character.
However, char has 8 bits, 1 for the sign of the
constant and 7 to represent the number. The conversion operation overflows
because 255 uses 8 bits.
One possible correction is using a larger integer
type. By using an int, there are enough bits to
represent the sign and the number value.
int sign_change(void) {
    unsigned char count = 255;
    return (int)count;
}This issue occurs when values from unsecure sources are converted, implicitly or explicitly, from signed to unsigned values.
For example, functions that use size_t as arguments implicitly convert the argument to an unsigned integer. Some functions that implicitly convert size_t are:
bcmp
memcpy
memmove
strncmp
strncpy
calloc
malloc
memalignIf you convert a small negative number to unsigned, the result is a large positive number. The large positive number can create security vulnerabilities. For example, if you use the unsigned value in:
- Memory size routines — causes allocating memory issues. 
- String manipulation routines — causes buffer overflow. 
- Loop boundaries — causes infinite loops. 
To avoid converting unsigned negative values, check that the value being converted is within an acceptable range. For example, if the value represents a size, validate that the value is not negative and less than the maximum value size.
By default, Polyspace assumes that data from external sources are tainted. See Sources of Tainting in a Polyspace Analysis. To consider
                any data that does not originate in the current scope of Polyspace analysis as
                tainted, use the command line option -consider-analysis-perimeter-as-trust-boundary.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
enum {
    SIZE10  =  10,
    SIZE100 = 100,
    SIZE128 = 128
};
void bug_taintedsignchange(void) {
    int size;
    scanf("%d",&size);
    char str[SIZE128] = "";
    if (size<SIZE128) {
        memset(str, 'c', size); //Noncompliant
    }
}
In this example, a char buffer is created
and filled using memset. The size argument to memset is
an input argument to the function. 
The call to memset implicitly converts size to
unsigned integer. If size is a large negative number,
the absolute value could be too large to represent as an integer,
causing a buffer overflow. 
sizeOne possible correction is to check if size is
inside the valid range. This correction checks if size is
greater than zero and less than the buffer size before calling memset.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
enum {
    SIZE10  =  10,
    SIZE100 = 100,
    SIZE128 = 128
};
void corrected_taintedsignchange(void) {
    int size;
    scanf("%d",&size);
    char str[SIZE128] = "";
    if (size>0 && size<SIZE128) {
        memset(str, 'c', size);  
    }
}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.
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.
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:
- Address Results in Polyspace User Interface Through Bug Fixes or Justifications if you review results in the Polyspace user interface. 
- Address Results in Polyspace Access Through Bug Fixes or Justifications (Polyspace Access) if you review results in a web browser. 
- Annotate Code and Hide Known or Acceptable Results if you review results in an IDE. 
 #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*.
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];
  }This issue occurs when you convert between a pointer type, such as
                                                  intptr_t, or
                                                  uintprt_t, and an integer type,
                                                such as enum,
                                                  ptrdiff_t, or
                                                  pid_t, or vice versa.
The mapping between pointers and integers is not always consistent with the addressing structure of the environment.
Converting from pointers to integers can create:
- Truncated or out of range integer values. 
- Invalid integer types. 
Converting from integers to pointers can create:
- Misaligned pointers or misaligned objects. 
- Invalid pointer addresses. 
Where possible, avoid pointer-to-integer or integer-to-pointer
conversions. If you want to convert a void pointer
to an integer, so that you do not change the value, use types: 
- C99 — - intptr_tor- uintptr_t
- C90 — - size_tor- ssize_t
 unsigned int *badintptrcast(void)
{
    unsigned int *ptr0 = (unsigned int *)0xdeadbeef;  //Noncompliant
    char *ptr1 = (char *)0xdeadbeef;
    unsigned int *explicit_ptr = reinterpret_cast<unsigned int*>(0xdeadbeef);  //Noncompliant
    return (unsigned int *)(ptr0 - (unsigned int *)ptr1); //Noncompliant
}In this example, there are four conversions, three unsafe conversions and one safe conversion.
- The conversion of - 0xdeadbeefto an- unsigned int*causes alignment issues for the pointer. Polyspace flags this conversion.
- The conversion of - 0xdeadbeefto a- char *is not flagged because there are no alignment issues for- char.
- The explicit - reinterpret_castof- 0xdeadbeefto an- unsigned int*causes alignment issues for the pointer. Polyspace flags this conversion.
- The conversion in the return casts - ptrdiff_tto a pointer. This pointer might point to an invalid address. Polyspace flags this conversion.
intptr_tOne possible correction is to use intptr_t types to store the pointer address 0xdeadbeef. 
#include <stdint.h>
unsigned int *badintptrcast(void)
{
    intptr_t iptr0 = (intptr_t)0xdeadbeef;
    return (unsigned int *)iptr0;
}This issue occurs when converting an unsigned integer to a smaller unsigned integer type. If the variable does not have enough bytes to represent the original constant, the conversion overflows.
The exact storage allocation for different floating point types depends on your
            processor. See Target processor type (-target).
Integer conversion overflows result in undefined behavior.
The fix depends on the root cause of the defect. Often the result details (or source code tooltips in Polyspace as You Code) show a sequence of events that led to the defect. You can implement the fix on any event in the sequence. If the result details do not show this event history, you can search for previous references of variables relevant to the defect using right-click options in the source code and find related events. See also Interpret Bug Finder Results in Polyspace Desktop User Interface or Interpret Bug Finder Results in Polyspace Access Web Interface (Polyspace Access).
You can fix the defect by:
- Using a bigger data type for the result of the conversion so that all values can be accommodated. 
- Checking for values that lead to the overflow and performing appropriate error handling. 
In general, avoid conversions to smaller integer types.
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:
- Address Results in Polyspace User Interface Through Bug Fixes or Justifications if you review results in the Polyspace user interface. 
- Address Results in Polyspace Access Through Bug Fixes or Justifications (Polyspace Access) if you review results in a web browser. 
- Annotate Code and Hide Known or Acceptable Results if you review results in an IDE. 
A default Bug Finder analysis might not raise this defect when the input values are unknown and only a subset of inputs cause an issue. To check for defects caused by specific system input values, run a stricter Bug Finder analysis. See Extend Bug Finder Checkers to Find Defects from Specific System Input Values.
unsigned char convert(void) {
    unsigned int unum = 1000000U;
    return (unsigned char)unum;  //Noncompliant
}In the return statement, the unsigned integer
variable unum is converted to an unsigned character
type. However, the conversion overflows because 1000000 requires at
least 20 bits. The C programming language standard does not view unsigned
overflow as an error because the program automatically reduces the
result by modulo the maximum value plus 1. In this example, unum is
reduced by modulo 2^8 because a character data
type can only represent 2^8-1. 
One possible correction is to convert to a different integer
type that can represent the entire number. For example, long.
unsigned long convert(void) {
    unsigned int unum = 1000000U;
    return (unsigned long)unum;  
}This issue occurs during pointer conversion when the pointer’s address is misaligned. If a pointer is converted to a different pointer type, the size of the allocated memory must be a multiple of the size of the destination pointer.
Dereferencing a misaligned pointer has undefined behavior and can cause your program to crash.
Suppose you convert a pointer ptr1 to ptr2.
                If ptr1 points to a buffer of N bytes and
                    ptr2 is a type
                    *sizeof( is
                    type)n bytes, make sure that N is an integer
                multiple of n.
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:
- Address Results in Polyspace User Interface Through Bug Fixes or Justifications if you review results in the Polyspace user interface. 
- Address Results in Polyspace Access Through Bug Fixes or Justifications (Polyspace Access) if you review results in a web browser. 
- Annotate Code and Hide Known or Acceptable Results if you review results in an IDE. 
#include <stdlib.h>
void dyn_non_align(void){
    void *ptr = malloc(13);
    long *dest;
    dest = (long*)ptr; //Noncompliant
}In this example, the software raises a defect on the
        conversion of ptr to a long*. The dynamically
        allocated memory of ptr, 13 bytes, is not a multiple of the size of
            dest, 4 bytes. This misalignment causes the Wrong allocated object size for cast defect.
One possible correction is to use a pointer size that is a multiple of the destination size. In this example, resolve the defect by changing the allocated memory to 12 instead of 13.
#include <stdlib.h>
void dyn_non_align(void){
    void *ptr = malloc(12);
    long *dest;
    dest = (long*)ptr;
}#include <stdlib.h>
void *my_alloc(unsigned int size) { 
    void *ptr_func = malloc(size); 
    if(ptr_func == NULL) exit(-1); 
    return ptr_func; 
}
void fun_non_align(void){
    int *dest1;
    char *dest2;
    dest1 = (int*)my_alloc(13);  //Noncompliant
    dest2 = (char*)my_alloc(13); //Compliant
}In this example, the software raises a defect on the conversion
of the pointer returned by my_alloc(13) to an int* in
line 11. my_alloc(13) returns a pointer with a
dynamically allocated size of 13 bytes. The size of dest1 is
4 bytes, which is not a divisor of 13. This misalignment causes the Wrong allocated object size for cast defect.
In line 12, the same function call, my_alloc(13),
does not call a defect for the conversion to dest2 because
the size of char*, 1 byte, a divisor of 13.
One possible correction is to use a pointer size that is a multiple
of the destination size. In this example, resolve the defect by changing
the argument for my_alloc to a multiple of 4.
#include <stdlib.h>
void *my_alloc(unsigned int size) { 
    void *ptr_func = malloc(size); 
    if(ptr_func == NULL) exit(-1); 
    return ptr_func; 
}
void fun_non_align(void){
    int *dest1;
    char *dest2;
    dest1 = (int*)my_alloc(12); 
    dest2 = (char*)my_alloc(13); 
}Check Information
| Category: Others | 
Version History
Introduced in R2023aPolyspace does not report a violation if you call a function inside of a lambda expression where the function contains an argument captured by the lambda expression. For example:
#include <iostream>
#include <functional>
void greet(const std::string& name) {
    std::cout << "Hello, " << name << "!" << std::endl;
}
int main() {
    std::string name = "Alice";
    auto lambda = [name]() {
        greet(name);			//Compliant
    };
    
    lambda(); 
    
    return 0;
}Polyspace does not report a violation if you convert pointers to nonqualified object type into a pointer to one of the following types:
- char
- signed char
- unsigned char
                Polyspace reports a violation if you convert pointers to qualified objects even
                if the destination type is one of char*, signed
                    char*, or unsigned char*.
See Also
External Websites
MATLAB Command
You clicked a link that corresponds to this MATLAB command:
Run the command by entering it in the MATLAB Command Window. Web browsers do not support MATLAB commands.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)