Richard,
At 13:07 25/05/2011, you wrote:
>It turns out that the "expected" behavior does not happen in modern C
>compilers. Overflow of signed integers is undefined behavior in C. So if
>you have a signed integer overflow, it might wrap the result (the
>"expected"
>result) or it might segfault, or it might reformat your hard drive
>(probably
>not, but it could and still comply with the spec!) Recent compilers will
>take advantage of this undefined behavior to take shortcuts with signed
>integer arithmetic, meaning that different things happen on different
>compilers and with different optimization settings. On the other hand, we
>want SQLite to give the same answer regardless of how it is
>compiled. So as
>of version 3.7.6, SQLite is careful to avoid signed integer overflows. We
>now require that SQLite work even if compiled using the -fwrapv option in
>GCC.
You're certainly right about your point and I'm not going to argue
about the grounds of the C standard.
Nonetheless, the resulting behavior is surprising:
V:\Bin>sqlite3
SQLite version 3.7.6.3
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .load unifuzz.dll
sqlite> CREATE TABLE if not exists "overflow" (
...> "Test" INTEGER PRIMARY KEY AUTOINCREMENT,
...> "Operation" CHAR,
...> "IntValue" INTEGER,
...> "Type" CHAR,
...> "Hexa" CHAR);
sqlite>
sqlite> CREATE TRIGGER if not exists "trInsTest"
...> AFTER INSERT
...> ON "overflow"
...> BEGIN
...> update overflow set type = typeof(intvalue), hexa =
hexw(intvalue);
...> END;
sqlite> delete from overflow;
sqlite> insert into overflow (operation, intvalue) values ('initial
value MAX_INT', 9223372036854775807);
sqlite> insert into overflow (operation, intvalue) values ('- MAX_INT',
- (select intvalue from overflow where test = 1));
sqlite> insert into overflow (operation, intvalue) values ('MAX_INT +
1', (select intvalue from overflow where test = 1) + 1);
sqlite> insert into overflow (operation, intvalue) values ('- MAX_INT -
1', - (select intvalue from overflow where test = 1) - 1);
sqlite> select * from overflow;
1|initial value MAX_INT| 9223372036854775807|integer|7FFFFFFFFFFFFFFF
2|- MAX_INT |-9223372036854775807|integer|8000000000000001
3|MAX_INT + 1 |9.22337203685478e+18|real |8000000000000000
4|- MAX_INT - 1 |-9223372036854775808|integer|8000000000000000
The function hexw(x) is from the loaded extension and simply returns x
as an hex string, as you can see. It is just there to make the point
clearer: test 3 and test 4 produce the same content but distinct values
from distinct types. That can make some applications choke.
I decided to avoid any early conversion possibly made by the statement
parser and instead of typing literal values as 9223372036854775807 + 1,
I retrieved the value as a subselect.
Since integer overflow is a concern and given that no standard way of
dealing with it consistently is available over the millions of possible
targets, wouldn't it be more consistent to have a build-time option
ERR_ON_INT_OVERFLOW causing SQLite to return an error in case of
integer overflow?
_______________________________________________
sqlite-users mailing list
[email protected]
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users