PORTING.SIGNED.CHARUse of 'char' without explicitly specifying signednessThe PORTING checkers identify code that might rely on specific implementation details in different compilers. The PORTING.SIGNED.CHAR checker detects situations in C code, in which 'char' is used without an explicitly specified sign. (This checker applies only to C, since these signedness issues are picked up by C++ compilers.) Vulnerability and riskThe 'char' data type isn't precisely defined in the C standard, so an instance may or may not be considered to be signed. Some compilers allow the sign of 'char' to be switched using compiler options, but best practice is for developers to write unambiguous code at all times to avoid problems in porting code. Mitigation and preventionAlways specify the sign of the 'char' type. This is best done by a using a typedef or #define definition that is then rigorously used everywhere. Vulnerable code example1 static char *s = "Hello, \xABWorld\xBB!\n"; 2 /* return next char, or -1 upon end of stream */ 3 int get_next_char() { 4 return *s ? *s++ : -1; 5 } 6 int main() { 7 int ch; 8 while ((ch = get_next_char()) > 0) { 9 putchar(ch); 10 } 11 return 0; 12 } When char is unsigned in this example, it works as expected, and the string is printed on standard output with 'World' enclosed in angle quotes (in Latin-1 encoding): Hello, «World»! When char is signed, the code prints only part of the string, up to the opening angle quote: Hello, Fixed code example1 typedef unsigned char UCHAR; 2 static UCHAR *s = "Hello, \xABWorld\xBB!\n"; 3 /* return next char, or -1 upon end of stream */ 4 int get_next_char() { 5 return *s ? *s++ : -1; 6 } 7 int main() { 8 int ch; 9 while ((ch = get_next_char()) > 0) { 10 putchar(ch); 11 } 12 return 0; 13 } In the fixed code, unsigned char is used instead of char. Changing the condition of the while loop to (ch = get_next_char()) != -1) wouldn't fix the problem, as the stream would be terminated on the '\xFF' character anyway. |