/ Check-in [c6dfd9e4]
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 | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: c6dfd9e43449b0b3528281d9e2e4971c6ba86ab5
User & Date: danielk1977 2007-06-26 11:13:26
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: be2570c0 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: c6dfd9e4 user: danielk1977 tags: trunk
10:56
Remove the unused EXTSRC variable from the non-configure makefile. (CVS 4129) check-in: bbdcf372 user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
....
1149
1150
1151
1152
1153
1154
1155








1156
1157
1158
1159
1160

1161
1162
1163
1164
1165
1166
1167
....
1180
1181
1182
1183
1184
1185
1186

1187
1188
1189
1190
1191
1192
1193
**
** 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"

................................................................................
    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);
................................................................................
        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;
    }







|







 







>
>
>
>
>
>
>
>





>







 







>







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
....
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
....
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
**
** 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"

................................................................................
    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);
................................................................................
        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.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
134
135
136
137
138
139
140



141
142
143
144
145
146
147
#    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)}
................................................................................
# 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







|







 







>
>
>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#    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)}
................................................................................
# 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