Integer Error – “You Can’t Count that High” – CS2

 

Background

Summary:

Integer values that are too large or too small may fall outside the allowable bounds for their data type, leading to unpredictable problems that can both reduce the robustness of your code and lead to potential security problems.

Can't Sleep

Source: Can’t Sleep http://xkcd.com/571/

Description:

Declaring a variable as type int allocates a fixed amount of space in memory. Most languages include several integer types, including short, int, long, etc., to allow for less or more storage. The amount of space allocated limits the range of values that can be stored. For example, a 32-bit int variable can hold values from -231 through 231-1. Operations that result in values outside of this range can lead to a variety of problems, which apply to all data types that store integer variables, including int, short, and long.

  • Integer Overflow/Underflow: Mathematical operations can increase integer values above the maximum or decrease them below the minimum allowed values.  For instance, if  i = Integer.MAX_VALUE, the increment operator i++ will cause an overflow and the resulting value will be the smallest possible integer value Integer.MIN_VALUE.  Addition, subtraction, multiplication, and even division can cause overflow/underflow problems.
  • Truncation: If an integer is converted from a larger type to a smaller type (say, from a long to a short), the value will be truncated if it is outside the range of the smaller type; data that can’t fit will simply be thrown out. For example, if you have a long variable that has a value that is greater than the largest value that can be stored in a short (long l=32800), assigning the long to a short (short s = (short)l;) will cause a truncation error (s=-32736).

Risk – How can it happen?

Integer variables are often used to indicate a number of items that must be stored in an array or other fixed-size buffer. If a variable with an overflow is used for this purpose, the resulting buffer might be too small for the data that will be copied into it. This can cause your Java program to throw an exception. Programs written in other languages might throw exceptions, crash, lead to incorrect behavior, or open security vulnerabilities.

Examples of Occurrence:

Many Unix operating systems store time values in 32-bit signed (positive or negative) integers, counting the number of seconds since midnight on January 1, 1970. On Tuesday, January 19, 2038, this value will overflow, becoming a negative number. Although the impact of this problem in 2038 is not yet known, there are concerns that software that projects out to future dates – including tools for mortgage payment and retirement fund distribution – might face problems long before then. Source: Year 2038 Problem” http://en.wikipedia.org/wiki/Year_2038_problem

Code Responsibly – How Can I Avoid an Integer Error?

  1. Know your limits: Familiarize yourself with the ranges available for each data type. Since the size of data types may be compiler and machine dependent, it is a good idea to run this sample program to show you the limits of each variable type.
  2. Choose your data types carefully: If there’s any doubt at all as to whether the variable will have values that are too large for a short, use an int. If an int might be too small, use a long.
  3. Validate your input: Check input for ranges and reasonableness before conducting operations (more on this in future modules).
  4. Check for possible overflows: Always check results of arithmetic operations or parsing of strings to integers, to be sure that an overflow has not occurred. The result of multiplying two positive integers should be at least as big as both of those integers. If you find a result that overflows, you can take appropriate action before the result is used. Imagine you were adding two positive integers. Instead of writing:
     int sum = someInteger + someOtherInteger;

    You might try this instead:

    	if   (((someInteger >0) && (someOtherInteger >0) &&
                 (someInteger> (Integer.MAX_VALUE-someOther Integer))) ||
                ((someInteger <0) && (someOtherInteger <0) &&
    			(someInteger < (Integer.MIN_VALUE - someOtherInteger)))) {
      		// throw an exception to handle the problem }
    	else 	//  no exception, so no overflow.
    		int sum = someInteger+someOtherInteger;
    

    This won’t completely solve the problem – you’ll need to recover from the exception. As these tests can become fairly complex [1], you should be careful when relying upon manual checks for preventing integer overflow.

  5. Use compiler checks: Many compilers include options that can be used to check for possible integer overflows. Read the documentation for your compiler and use these functions whenever possible.
  6. Use libraries that will help you avoid errors: C++ programmers might use the SafeInt class, which tests for errors before conducting operations. Java programmers can use the BigInteger class to conduct arbitrary-precision integer operations that might go beyond the bounds of long integers.

[1] See https://www.securecoding.cert.org/confluence/display/java/NUM00-J.+Detect+or+prevent+integer+overflow for examples of solutions for other operations.

Laboratory Assignment

The program below projects the growth of student  population over the next 10 years.

import java.util.Scanner;
public class PopCheck {
  public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);
    System.out.print("What is the current population? ");
    short pop = scan.nextShort();
    System.out.print("What is the rate of growth? (e.g., for 10% enter 10)");
    short growth = scan.nextShort(); //note that growth is an integer

    float growthRate = growth/100f;    //convert the growth rate to a float
    System.out.println("Year\tGrowth\tNew Population");
    for (int i = 1; i <= 10; i++)  {
      // calculate increase and new population
      // Force them both to be shorts
      short increase = (short) (pop * growthRate);
      short newpop = (short) (pop+increase);
      System.out.println(i+"\t"+increase+"\t"+newpop);
      pop = newpop;
    }
    System.err.println("Final population is "+pop);
  }
}

Lab Questions:

  1. Type* the program and compile. What happens if you start with a population of 10,000 and a 10% growth rate? How about 20,000 with a 10% growth rate? Find two combinations of starting populations and growth rates that lead to overflows, and two that do not.
  2. Does a short seem like a good choice of data type for this program? Why or why not?
  3. Complete the security checklist for the program. Submit marked program and completed checklist.
  4. Write a corrected version of this program that uses appropriate data types that will make this program run correctly for calculating population growths for any university and any country in the world.

*Copying and pasting programs may result in syntax errors and other inconsistencies. It is recommended you type each program.

Security Checklist

For each underlined variable:

Security Checklist

Vulnerability: Integer Errors Course: CS2  
Check each line of code Completed
1. Underline each occurrence of an integer variable.  
For each underlined variable:
2. Mark with a V any input operations that assign values to the variable.  
3. Mark with a V any mathematical operations involving the variable.  
4. Mark with a V any assignments made to the variable.  
Shaded areas indicate vulnerabilities!  
   

If this group reaches 4,294,967,296

Discussion Questions

  1. Click on the image to the right and explain the concept behind this group. Do you think it is likely that the group might cause an overflow?
  2. What dangers do integer overflows present?
  3. One of the main implications of integer errors is when an array index overflows or underflows. Why do you think this is a problem?
  4. Explore how division might cause integer overflows (hint: you should look at sources on the web for the answer).

Further Work (optional – check with your instructor if you need to answer the following questions)

  1. Write a version of program 1 that still uses short variables to store results,  and uses appropriate error and result handling to respond to errors. You may use the technique of storing values in temporary variables before assigning them to the short variables.
  2. Name three things you might do in your next program to prevent an integer error from occurring.
 
Copyright © Towson University