views:

331

answers:

6

Is there a way to find potential numeric overflows in Java code, using the Eclipse IDE? For example...

long aLong = X * Y * Z;

... where X, Y, and Z are ints and the result may overflow Integer.MAX_VALUE. (Note that, perhaps counter-intuitively, if the result in this example overflows Integer.MAX_VALUE, aLong will be assigned the erroneous overflowed value).

I've looked in Eclipse's Warnings settings, PMD rules, and FindBugs rules and I can't find any setting to help with this. A co-worker notes that IntelliJ will warn about this... and I'd hate to have to admit that I can't do the same with Eclipse. ;-)


Clarification 1: I'm not looking for something that gives 0 false positives... just warnings that "you may have an overflow problem here".,

Clarification 2: This is desired at "development time"... meaning, at the same stage that Eclipse is looking for unused imports, PMD is checking its rules, etc.

A: 

may be you could do your calculation with java.math.BigInteger and compare the result with

new java.math.BigInteger(String.valueOf(Long.MAX_VALUE))
Pierre
That is a way to do the calculation without errors, but not to detect if a calculation is subject to a particular type of error, which is what the question is asking.
Carl
A: 

You want this at compile time? Haven't seen a setting to do this.

If you really want it, the best bet is most likely to write a new ruleset for PMD?

Thorbjørn Ravn Andersen
A: 

What would be the expected result for this?

 long testMethod () {
     long aLong =  Integer.MAX_VALUE + doesMethodContainAnOverflow ( "testMethod" ) ? 0 : 1;

     return aLong;
 }

it has an overflow only if there is no overflow in it.

There's a potential overflow for any fixed representation integer operation; determining whether there's an actual overflow is trivially convertible to the halting problem. Which doesn't mean that IntelliJ doesn't have some heuristic to warn you in some cases - you could, for example, track the upper and lower bounds of any numeric operation through a program and get a worst-case answer, but writing an accurate rule would be neither trivial nor decidable.

Pete Kirkham
The question is for *potential* overflows, which is the worst-case answer, which as you point out, is decidable.The feature isn't about deciding overflows anyways, it's more like calling attention to things the programmer might not have recognized as potential overflow points, though the noise is probably pretty high (simple addition of variable integers should set it off, for example).
Carl
Someone's been reading GEB
Jherico
A: 

This would either require a deep analisys of an algorithm or just give you a warning for every arithmetic operation that involves variables.

EDIT: Oh, do you mean that if X, Y and Z are integers, then the multiplication would be on integers and only then assigned to aLong? IntelliJ Idea will show it as a warning but the inspection is off by default.

tulskiy
Yes, your EDIT is correct. I'm just looking for a warning similar to what IntelliJ Idea does.
dirtyvagabond
You can write a PMD of FindBugs rule, but I don't think it worth it.
tulskiy
A: 

In FindBugs the FindPuzzlers detector's description contains

ICAST_INTEGER_MULTIPLY_CAST_TO_LONG (ICAST, STYLE): Result of integer multiplication cast to long

but somehow I can't make this detect the problem in the following code:

    final int x = 10000;
    final int y = 10000;
    final int z = 10000;
    final long aLong = x * y * z;
    System.out.println(aLong);
starblue
+1  A: 

If you do not know what X could be, it could be the worst case. So, what is the worst case:

 int X = Integer.MAX_VALUE;
 long aLong = X + 1;

Conclusion: You don't want Eclipse to warn you about everything.

If you want to fix integer overflow of

 long aLong = X * Y * Z; //you could write
 long aLong = (long)X * Y * Z;

Conclusion: This would not fix long overflow problems. If you want to fix them you should write code like:

 BigInteger tmp = BigInteger.valueOf(X).multiply(BigInteger.valueOf(Y)).multiply(BigInteger.valueOf(Z));
 if(BigInteger.valueOf(Long.MAX_VALUE).compareTo(tmp)>=0){
  long aLong = tmp.longValue();
 }else{
  System.out.println("Overflow");
 }

But this will only check if resulting value could fit in long. But you are asking, if during calculation "Overflow" happened. This would mean after every calculation you would need to check for this.

If you want to write a tool for eclipse that parses whole source file to find this, then i am not stopping you. But it would be just whole lot easier to remember following values:

 /*11111111111111111111111111111111*/int Y = -1; //-1
 /*11111111111111111111111111111111*/int QRY = (Y >> 1); //-1
 /*11111111111111111111111111111110*/int QLY = (Y << 1); //-2
 /*11111111111111111111111111111110*/int QLX = (X << 1); //-2
 /*11000000000000000000000000000000*/int QRZ = (Z >> 1); //-1073741824
 /*10000000000000000000000000000000*/int Z = Integer.MIN_VALUE; //-2147483648
 /*01111111111111111111111111111111*/int X = Integer.MAX_VALUE; // 2147483647
 /*00111111111111111111111111111111*/int QRX = (X >> 1); // 1073741823
 /*00000000000000000000000000000000*/int QLZ = (Z << 1); // 0
Margus