I had a bug that caused an integer overflow, resulting in wrong (negative) timestamps being written to the database. The code is fixed already, but I want to fix the wrong data, too.
I thought, I could just take the wrong results and add Integer.MAX_VALUE, but that didn’t seem to work, it left me with to high values. I have the offset value in the code snippet below, but the input values are not stored.
The following code reproduces the bug:
@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);
}
How to fix the bug in your database
To fix the bug in your database you can do the following addition to all the buggy data:
The constant number was found like this:
resultvalueresultvalue be?resultvalue to find the correct `result.But this is only possible if you have saved
sampleandoffsetin your database or somewhere else.Otherwise, it depends on the number of wraps that occured during the original calculation:
If the numbers in your database are close enough to your sample value, this means, you can do the above, using 305 as the number of wraps.
Explanation of the bug (for future readers)
The operation here:
is computed using
intand notlong. But the result is “too big” to be saved on anintvariable. That’s why you have an overflow.Change it to:
So now the
+and*operations will be done usinglongvalues, and the result will be alongvalue which won’t overflow.