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
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to