SQLite User Forum

Bug Report: Overflow in `ROUND(X,Y)` function
Login

Bug Report: Overflow in `ROUND(X,Y)` function

(1) By QueryHouse on 2024-12-18 17:47:03 [source]

Hi,

We've identified an issue with the ROUND(X,Y) function in SQLite version 3.48.0.

According to the official documentation, ROUND(X,Y) returns a floating-point value X rounded to Y digits to the right of the decimal point. If Y is negative or omitted, it is taken to be 0.

Here's the relevant part of the documentation:

https://www.sqlite.org/lang_corefunc.html#round

However, we've obeserved a signed integer overflow occurs when a large value is passed as Y, causing incorrect results.

Steps to Reproduce:

The following queries demonstrate the issue:

sqlite> SELECT ROUND(123.456, 2147483647); -- 0x7fffffff
123.456
sqlite> SELECT ROUND(123.456, 2147483648); -- 0x80000000 => -2147483648
123.0
sqlite> SELECT ROUND(123.456, 2147483649); -- 0x80000001 => -2147483647
123.0
...
sqlite> SELECT ROUND(123.456, 4294967295); -- 0xffffffff => -1
123.0
sqlite> SELECT ROUND(123.456, 4294967296); -- 0x1`00000000 => 0
123.0
sqlite> SELECT ROUND(123.456, 4294967297); -- 0x1`00000001 => 1
123.5
sqlite> SELECT ROUND(123.456, 4294967298); -- 0x1`00000002 => 2
123.46
sqlite> SELECT ROUND(123.456, 4294967299); -- 0x1`00000003 => 3
123.456
...
sqlite> SELECT ROUND(123.456, 6442450943); -- 0x1'7fffffff => 2147483647
123.456
sqlite> SELECT ROUND(123.456, 6442450944); -- 0x1'80000000 => -2147483648
123.0
sqlite> SELECT ROUND(123.456, 6442450945); -- 0x1'80000001 => -2147483647
123.0
...
sqlite> SELECT ROUND(123.456, 8589934591); -- 0x1'ffffffff => -1
123.0
sqlite> SELECT ROUND(123.456, 8589934592); -- 0x2'00000000 => 0
123.0
sqlite> SELECT ROUND(123.456, 8589934593); -- 0x2'00000001 => 1
123.5
sqlite> SELECT ROUND(123.456, 8589934594); -- 0x2'00000002 => 2
123.46
sqlite> SELECT ROUND(123.456, 8589934595); -- 0x2'00000003 => 3
123.456
...

Expected Result:

The ROUND(123.456, Y) function should return the correct rounded value for any valid positive integer Y, even when large.

Actual Behavior (in version 3.48.0):

As shown, the value of Y appears to be truncated to its lower 32 bits, causing unexpected behavior for large Y values.

Any Y with the 32nd bit set results in ROUND() returning an incorrect value (e.g., 123.0 instead of 123.456), as if it's negative and treated as 0, per the policy of ROUND() mentioned above. Additionally, any Y postfixed with 0x00000001 works as 1, 0x00000002 as 2, and so on.

We suggest updating SQLite to correctly handle large values for Y or to return an overflow error for out-of-range values, with the supported range specified in the documentation.

Thank you for your time and attention to this matter.

We look forward to your response.

Best regards.

(2) By Stephan Beal (stephan) on 2024-12-19 05:23:45 in reply to 1 [link] [source]

We look forward to your response.

That was fixed in src:a9759fc78d6cb0df. Thank you for the report!