SQLite

Check-in [c6dfd9e434]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix for #2444: Avoid SIGFPE on 64-bit platforms when evaluating expressions like ((1<<63)/-1). (CVS 4130)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: c6dfd9e43449b0b3528281d9e2e4971c6ba86ab5
User & Date: danielk1977 2007-06-26 11:13:26.000
Context
2007-06-26
12:52
Use (((i64)1)<<63) instead of just (1<<63) to compute the most negative 64-bit integer. (CVS 4131) (check-in: be2570c061 user: danielk1977 tags: trunk)
11:13
Fix for #2444: Avoid SIGFPE on 64-bit platforms when evaluating expressions like ((1<<63)/-1). (CVS 4130) (check-in: c6dfd9e434 user: danielk1977 tags: trunk)
10:56
Remove the unused EXTSRC variable from the non-configure makefile. (CVS 4129) (check-in: bbdcf372c6 user: danielk1977 tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/vdbe.c.
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.632 2007/06/26 00:37:28 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include <math.h>
#include "vdbeInt.h"








|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.633 2007/06/26 11:13:26 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include <math.h>
#include "vdbeInt.h"

1149
1150
1151
1152
1153
1154
1155








1156
1157
1158
1159
1160

1161
1162
1163
1164
1165
1166
1167
    b = pNos->u.i;
    switch( pOp->opcode ){
      case OP_Add:         b += a;       break;
      case OP_Subtract:    b -= a;       break;
      case OP_Multiply:    b *= a;       break;
      case OP_Divide: {
        if( a==0 ) goto divide_by_zero;








        b /= a;
        break;
      }
      default: {
        if( a==0 ) goto divide_by_zero;

        b %= a;
        break;
      }
    }
    Release(pTos);
    pTos--;
    Release(pTos);







>
>
>
>
>
>
>
>





>







1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
    b = pNos->u.i;
    switch( pOp->opcode ){
      case OP_Add:         b += a;       break;
      case OP_Subtract:    b -= a;       break;
      case OP_Multiply:    b *= a;       break;
      case OP_Divide: {
        if( a==0 ) goto divide_by_zero;
        /* Dividing the largest possible negative 64-bit integer (1<<63) by 
        ** -1 returns an integer to large to store in a 64-bit data-type. On
        ** some architectures, the value overflows to (1<<63). On others,
        ** a SIGFPE is issued. The following statement normalizes this
        ** behaviour so that all architectures behave as if integer 
        ** overflow occured.
        */
        if( a==-1 && b==(1<<63) ) a = 1;
        b /= a;
        break;
      }
      default: {
        if( a==0 ) goto divide_by_zero;
        if( a==-1 ) a = 1;
        b %= a;
        break;
      }
    }
    Release(pTos);
    pTos--;
    Release(pTos);
1180
1181
1182
1183
1184
1185
1186

1187
1188
1189
1190
1191
1192
1193
        b /= a;
        break;
      }
      default: {
        i64 ia = (i64)a;
        i64 ib = (i64)b;
        if( ia==0 ) goto divide_by_zero;

        b = ib % ia;
        break;
      }
    }
    if( sqlite3_isnan(b) ){
      goto divide_by_zero;
    }







>







1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
        b /= a;
        break;
      }
      default: {
        i64 ia = (i64)a;
        i64 ib = (i64)b;
        if( ia==0 ) goto divide_by_zero;
        if( ia==-1 ) ia = 1;
        b = ib % ia;
        break;
      }
    }
    if( sqlite3_isnan(b) ){
      goto divide_by_zero;
    }
Changes to test/expr.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing expressions.
#
# $Id: expr.test,v 1.56 2007/06/25 17:28:02 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table to work with.
#
execsql {CREATE TABLE test1(i1 int, i2 int, r1 real, r2 real, t1 text, t2 text)}













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing expressions.
#
# $Id: expr.test,v 1.57 2007/06/26 11:13:27 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table to work with.
#
execsql {CREATE TABLE test1(i1 int, i2 int, r1 real, r2 real, t1 text, t2 text)}
134
135
136
137
138
139
140



141
142
143
144
145
146
147
# Check for proper handling of 64-bit integer values.
#
test_expr expr-1.102 {i1=40, i2=1} {i2<<i1} 1099511627776

test_expr expr-1.103 {i1=0} {(-2147483648.0 % -1)} 0.0
test_expr expr-1.104 {i1=0} {(-9223372036854775808.0 % -1)} 0.0
test_expr expr-1.105 {i1=0} {(-9223372036854775808.0 / -1)>1} 1




test_expr expr-2.1 {r1=1.23, r2=2.34} {r1+r2} 3.57
test_expr expr-2.2 {r1=1.23, r2=2.34} {r1-r2} -1.11
test_expr expr-2.3 {r1=1.23, r2=2.34} {r1*r2} 2.8782
set tcl_precision 15
test_expr expr-2.4 {r1=1.23, r2=2.34} {r1/r2} 0.525641025641026
test_expr expr-2.5 {r1=1.23, r2=2.34} {r2/r1} 1.90243902439024







>
>
>







134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# Check for proper handling of 64-bit integer values.
#
test_expr expr-1.102 {i1=40, i2=1} {i2<<i1} 1099511627776

test_expr expr-1.103 {i1=0} {(-2147483648.0 % -1)} 0.0
test_expr expr-1.104 {i1=0} {(-9223372036854775808.0 % -1)} 0.0
test_expr expr-1.105 {i1=0} {(-9223372036854775808.0 / -1)>1} 1

test_expr expr-1.106 {i1=0} {(1<<63)/-1} -9223372036854775808
test_expr expr-1.107 {i1=0} {(1<<63)%-1} 0

test_expr expr-2.1 {r1=1.23, r2=2.34} {r1+r2} 3.57
test_expr expr-2.2 {r1=1.23, r2=2.34} {r1-r2} -1.11
test_expr expr-2.3 {r1=1.23, r2=2.34} {r1*r2} 2.8782
set tcl_precision 15
test_expr expr-2.4 {r1=1.23, r2=2.34} {r1/r2} 0.525641025641026
test_expr expr-2.5 {r1=1.23, r2=2.34} {r2/r1} 1.90243902439024