Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: exception

Signed character data must be converted to unsigned char before being assigned or converted to a larger signed type. Because compilers have the latitude to define char This rule applies to both signed char and (plain) char characters on implementations where char is defined to have the same range, representation, and behavior behaviors as either signed char or unsigned char.

However, this rule should be applied to both signed char and (plain) char characters.This rule is applicable only in only in cases where the character data may contain values that can be interpreted misinterpreted as negative valuesnumbers. For example, if the char type is represented by a two's complement 8-bit value, any character value greater than +127 is interpreted as a negative value.

This rule is a generalization of STR37-C. Arguments to character-handling functions must be representable as an unsigned char.

Noncompliant Code Example

...

Code Block
bgColor#FFcccc
langc
static int yy_string_get(void) {
  register char *c_str;
  register int c;

  c_str = bash_input.location.string;
  c = EOF;

  /* If the string doesn't exist or is empty, EOF found */
  if (c_str && *c_str) {
    c = *c_str++;
    bash_input.location.string = c_str;
  }
  return (c);
}

The c_str variable is used to traverse the character string containing the command line to be parsed. As characters are retrieved from this pointer, they are stored in a variable of type int. For compilers implementations in which the char type defaults to is defined to have the same range, representation, and behavior as signed char, this value is sign-extended when assigned to the int variable. For character code 255 decimal (−1 in two's complement form), this sign extension results in the value −1 being assigned to the integer, which is indistinguishable from EOF.

Noncompliant Code Example

This problem was can be repaired by explicitly declaring the c_str variable as unsigned char.:

Code Block
bgColor#FFcccc
langc
static int yy_string_get(void) {
  register unsigned char *c_str;
  register int c;

  c_str = bash_input.location.string;
  c = EOF;

  /* If the string doesn't exist or is empty, EOF found */
  if (c_str && *c_str) {
    c = *c_str++;
    bash_input.location.string = c_str;
  }
  return (c);
}

...

In this compliant solution, the result of the expression *c_str++ is cast to (unsigned char) before assignment to the int variable c:

Code Block
bgColor#ccccff
langc
static int yy_string_get(void) {
  register char *c_str;
  register int c;

  c_str = bash_input.location.string;
  c = EOF;

  /* If the string doesn't exist or is empty, EOF found */
  if (c_str && *c_str) {
    /* Cast to unsigned type */
    c = (unsigned char)*c_str++;

    bash_input.location.string = c_str;
  }
  return (c);
}

Noncompliant Code Example

In this noncompliant code example, the cast of *s to unsigned int may can result in a value in excess of UCHAR_MAX because of integer promotions, consequently causing the function to violate a violation of ARR30-C. Do not form or use out-of-bounds pointers or array subscripts, leading to undefined behavior:

Code Block
bgColor#ffcccc
langc
#include <limits.h>
#include <stddef.h>
 
static const char table[UCHAR_MAX + 1] = { 'a' /* ... */ };

ptrdiff_t first_not_in_table(const char *c_str) {
  for (const char *s = c_str; *s; ++s) {
    if (table[(unsigned int)*s] != *s) {
      return s - c_str;
    }
  }
  return -1;
}

...

This compliant solution casts the value of type char value to unsigned char before allowing it to be implicitly promoted the implicit promotion to a larger unsigned type:

Code Block
bgColor#ccccff
langc
#include <limits.h>
#include <stddef.h>
 
static const char table[UCHAR_MAX + 1] = { 'a' /* ... */ };

ptrdiff_t first_not_in_table(const char *c_str) {
  for (const char *s = c_str; *s; ++s) {
    if (table[(unsigned char)*s] != *s) {
      return s - c_str;
    }
  }
  return -1;
}

Risk Assessment

Exceptions

STR34-C-EX1: This rule only applies to characters that are to be treated as unsigned chars for some purpose, such as being passed to the isdigit() function. Characters that hold small integer values for mathematical purposes need not comply with this rule.

Risk Assessment

Conversion of character data resulting in a value in excess of UCHAR_MAX is an often-missed error that can result This is a subtle error that results in a disturbingly broad range of potentially severe vulnerabilities.

Rule

Severity

Likelihood

Remediation Cost

Detectable

Repairable

Priority

Level

STR34-C

Medium

Probable

Yes

Medium

No

P8

L2

Automated Detection

Tool

Version

Checker

Description

Astrée
Include Page
Astrée_V
Astrée_V
char-sign-conversionFully checked
Axivion Bauhaus Suite

Include Page
Axivion Bauhaus Suite_V
Axivion Bauhaus Suite_V

CertC-STR34Fully implemented
CodeSonar
Include Page
CodeSonar_V
CodeSonar_V
MISC.NEGCHARNegative Character Value
Compass/ROSE
  


Can detect violations of this rule when checking for violations of INT07-C. Use only explicitly signed or unsigned char type for numeric values

Coverity
Include Page
Coverity_V
Coverity_V

MISRA C 2012 Rule 10.1

MISRA C 2012 Rule 10.2

MISRA C 2012 Rule 10.3

MISRA C 2012 Rule 10.4

Implemented

Essential type checkers

Cppcheck Premium

Include Page
Cppcheck Premium_V
Cppcheck Premium_V

premium-cert-str34-c

ECLAIR

Include Page
ECLAIR_V
ECLAIR_V

CC2.STR34

Fully implemented
Fortify SCA

5.0

 

Can detect violations of this rule with CERT C Rule Pack

GCC

2.95 and later

-Wchar-subscripts

Detects objects of type char used as array indices

Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C2140, C2141, C2143, C2144, C2145, C2147, C2148, C2149, C2151, C2152, C2153, C2155

C++3051


Klocwork
Include Page
Klocwork_V
Klocwork_V
CXX.CAST.SIGNED_CHAR_TO_INTEGER


LDRA tool suite
Include Page
LDRA_V
LDRA_V

434 S

Fully implementedPRQA QA-C Include PagePRQA_VPRQA_V3704
Partially implemented
Parasoft C/C++test
Include Page
Parasoft_V
Parasoft_V

CERT_C-STR34-b
CERT_C-STR34-c
CERT_C-STR34-d

Cast characters to unsigned char before assignment to larger integer sizes
An expressions of the 'signed char' type should not be used as an array index
Cast characters to unsigned char before converting to larger integer sizes

PC-lint Plus

Include Page
PC-lint Plus_V
PC-lint Plus_V

571

Partially supported

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C: Rule STR34-CChecks for misuse of sign-extended character value (rule fully covered)
RuleChecker

Include Page
RuleChecker_V
RuleChecker_V

char-sign-conversionFully checked
TrustInSoft Analyzer

Include Page
TrustInSoft Analyzer_V
TrustInSoft Analyzer_V

out of bounds readPartially verified (exhaustively detects undefined behavior).
Fully implemented

Related Vulnerabilities

CVE-2009-0887 results from a violation of this rule. In Linux PAM (up to version 1.0.3), the libpam implementation of strtok() casts a (potentially signed) character to an integer for use as an index to an array. An attacker can exploit this vulnerability by inputting a string with non-ASCII characters, causing the cast to result in a negative index and accessing memory outside of the array [xorl 2009].

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Related Guidelines

Bibliography

...


...

Image Modified Image Modified Image Modified