Sign Conversion

From Guidance Share

Jump to: navigation, search

Contents

Description

A sign conversion error occurs when a primitive a signed primitive is used as an unsigned value or when an unsigned primitive is used as a signed value. This causes the most damage when the result is used as an indexer into a buffer or for pointer arithmetic. However, it can also cause logical errors when the calculation is used to drive control flow.

Applies To

  • Languages: C, C++, Fortran, Assembly
  • Operating platforms: All

Example

In the following example, it is possible to request that memcpy move a much larger segment of memory than assumed:

int returnChunkSize(void *) {
/* if chunk info is valid, return the size of usable memory, 
* else, return -1 to indicate an error
*/
.... 
}
int main() {
... 
memcpy(destBuf, srcBuf, (returnChunkSize(destBuf)-1));
...
}

If returnChunkSize() happens to encounter an error, and returns -1, memcpy will assume that the value is unsigned and therefore interpret it as MAXINT-1, therefore copying far more memory than is likely available in the destination buffer.

Impact

  • Availability: Incorrect sign conversions generally lead to undefined behavior, and therefore crashes.
  • Integrity: If a poor cast leads to a buffer underwrite, data integrity may be affected.
  • Access control (instruction processing): Sign conversions without proper checking can sometimes trigger buffer overflows which can result in the execution of arbitrary code. This is usually outside the scope of a program’s implicit security policy.

Vulnerabilities

  • Failure to check return codes for errors before they are used in calculations
  • Failure to check calculated values on signed data types before accessing, modifying, or allocating memory

Countermeasures

  • Requirements specification: The choice could be made to use a language that is not susceptible to these issues.
  • Design: Design object accessor functions to implicitly check values for valid sizes. Ensure that all functions return values which will be used as a size are checked for errors previous to use as a size. If the language permits, throw exceptions rather than using in-band errors.
  • Implementation: Error check the return values of all functions. Be aware of implicit casts made, and use unsigned variables for sizes if at all possible.
  • Build: Pay attention to compiler warnings which may alert you to improper type casting.

Vulnerability Patterns

How Tos

Personal tools