...
The only integer type conversions that are guaranteed to be safe for all data values and all possible conforming implementations are conversions of an integral value to a wider type of the same signedness. Section Subclause 6.3.1.3 of the C Standard [ISO/IEC 9899:2011] says,
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <limits.h> void func(void) { unsigned long int u_a = ULONG_MAX; signed char sc; sc = (signed char)u_a; /* cast eliminates warning */ /* ... */ } |
Compliant Solution (Unsigned to Signed)
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <limits.h> void func(void) { unsigned long int u_a = ULONG_MAX; signed char sc; if (u_a <= SCHAR_MAX) { sc = (signed char)u_a; /* use cast to eliminate warning */ } else { /* handle error condition */ } } |
Noncompliant Code Example (Signed to Unsigned)
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <limits.h> void func(void) { signed int si = INT_MIN; unsigned int ui = (unsigned int)si; /* cast eliminates warning */ /* ... */ } |
Compliant Solution (Signed to Unsigned)
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <limits.h> void func(void) { signed int si = INT_MIN; unsigned int ui; if (si < 0) { /* handle error condition */ } else { ui = (unsigned int)si; /* cast eliminates warning */ } /* ... */ } |
NOTE: Although unsigned types can usually represent all positive values of the corresponding signed type, this relationship is not guaranteed by the C Standard.
...
A loss of data (truncation) can occur when converting from a signed type to a signed type with less precision. The following code can result in truncation:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <limits.h> void func(void) { signed long int s_a = LONG_MAX; signed char sc = (signed char)s_a; /* cast eliminates warning */ /* ... */ } |
Compliant Solution (Signed, Loss of Precision)
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <limits.h> void func(void) { signed long int s_a = LONG_MAX; signed char sc; if ( (s_a < SCHAR_MIN) || (s_a > SCHAR_MAX) ) { /* handle error condition */ } else { sc = (signed char)s_a; /* use cast to eliminate warning */ } /* ... */ } |
Conversions from signed types with greater precision to signed types with lesser precision require both the upper and lower bounds to be checked.
...
A loss of data (truncation) can occur when converting from an unsigned type to an unsigned type with less precision. The following code results in a truncation error on most implementations:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <limits.h> void func(void) { unsigned long int u_a = ULONG_MAX; unsigned char uc = (unsigned char)u_a; /* cast eliminates warning */ /* ... */ } |
Compliant Solution (Unsigned, Loss of Precision)
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <limits.h> void func(void) { unsigned long int u_a = ULONG_MAX; unsigned char uc; if (u_a > UCHAR_MAX) ) { /* handle error condition */ } else { uc = (unsigned char)u_a; /* use cast to eliminate warning */ } /* ... */ } |
Conversions from unsigned types with greater precision to unsigned types with lesser precision require only the upper bounds to be checked.
...
[Dowd 2006] | Chapter 6, "C Language Issues" ("Type Conversions," pp. 223–270) |
[ISO/IEC 9899:2011] | Section Subclause 6.3.1.3, "Signed and Unsigned Integers" |
[Seacord 2013] | Chapter 5, "Integer Security" |
[Viega 2005] | Section 5.2.9, "Truncation Error" Section 5.2.10, "Sign Extension Error" Section 5.2.11, "Signed to Unsigned Conversion Error" Section 5.2.12, "Unsigned to Signed Conversion Error" |
[Warren 2002] | Chapter 2, "Basics" |
[xorl 2009] | "CVE-2009-1376: Pidgin MSN SLP Integer Truncation" |
...