How to fix incorrect numbers caused by integer overflow?

I had an error that caused the overflow of integers, as a result of which erroneous (negative) timestamps were written to the database. The code has already been fixed, but I also want to fix the incorrect data .

I thought I could just accept the wrong results and add Integer.MAX_VALUE, but that didn't seem to work, it left me with high values. I have an offset value in the code snippet below, but the input values ​​are not saved.

The following code reproduces the error:

 @Test public void testArexxConversion() { // The input values represent seconds since midnight, Jan 1, 2000 UTC final int sample = 361450072; // A sample input value drawn from production // I use the offset from the UNIX epoch to convert the vakue to UNIX seconds final int offset = 946684800; // midnight, Jan 01 2000 UTC in UNIX seconds // This was the buggy line in my code, the assertion will fail long result = (sample + offset) * 1000; // Prints 'Result is negative: -1830153280' Assert.assertTrue(result > 0, String.format("Result is negative: %d", result)); // This is for comparison Date dt = new Date(offset * 1000); Assert.assertEquals(dt.getTime() + sample * 1000, result); } 
+6
source share
3 answers

How to fix an error in your database

To fix the error in your database, you can make the following addition to all errors:

 long new_result = old_buggy_result + 1309965025280L; 

A constant number was found as follows:

  • Check the value of the buggy result
  • Indicate what should be in the correct value of result ?
  • Add a buggy result value to find the correct result.

But this is only possible if you saved sample and offset in your database or somewhere else.

Otherwise, it depends on the number of wrappers that occurred during the initial calculation:

 long size_of_int = (long)Math.pow(2, 32); int number_of_wraps = 305 // Only correct in your example! // You can't deduct the number of wraps from // the wrong value alone, because that information // is lost in the modulo (the "wrap") long correct_number = wrong_number + size_of_int * number_of_wraps; 

If the numbers in your database are close enough to your sample, that means you can do higher using 305 as the number of wrappers.

Error explanation (for future readers)

Operation here:

  (sample + offset) * 1000; 

computed using int , not long . But the result is "too large" to be stored in the int variable. That's why you have an overflow.

Change it to:

  ((long) sample + offset) * 1000L; 

So, now the + and * operations will be performed using long values, and the result will have a long value that will not overflow.

+4
source

It will be like this:

 long result = ... ; // bad negative from database long new_result = (long)((int)result - Integer.MAX_VALUE) + Integer.MAX_VALUE; 
+1
source

Replace this line.

 long result = (long)(sample + offset) * 1000L; 
0
source

Source: https://habr.com/ru/post/890596/


All Articles