SQLite

Check-in [392559465d]
Login

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

Overview
Comment:Use caution to avoid integer overflow when doing real to integer affinity operations. Ticket #3922. (CVS 6776)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 392559465d499f491907ef7f42d37a1a6c699511
User & Date: drh 2009-06-17 16:20:04.000
Context
2009-06-17
21:42
Fix a problem in vdbe.c that could cause a double-free of memory if the SQLITE_LIMIT_LENGTH is changed after a statement is prepared but before it is run. Also remove debugging statements from tkt3841.test. (CVS 6777) (check-in: 3d7327fd6a user: drh tags: trunk)
16:20
Use caution to avoid integer overflow when doing real to integer affinity operations. Ticket #3922. (CVS 6776) (check-in: 392559465d user: drh tags: trunk)
13:57
Fix a potential segfault following database corruption. Problem made visible by check-in (6772). (CVS 6775) (check-in: 69eb0ff817 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/util.c.
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
**
*************************************************************************
** Utility functions used throughout sqlite.
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.259 2009/06/10 11:07:01 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
#ifdef SQLITE_HAVE_ISNAN
# include <math.h>
#endif








|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
**
*************************************************************************
** Utility functions used throughout sqlite.
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.260 2009/06/17 16:20:04 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
#ifdef SQLITE_HAVE_ISNAN
# include <math.h>
#endif

388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
**
**      compare2pow63("9223372036854775800")
**
** will return -8.
*/
static int compare2pow63(const char *zNum){
  int c;
  c = memcmp(zNum,"922337203685477580",18);
  if( c==0 ){
    c = zNum[18] - '8';
  }
  return c;
}









|







388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
**
**      compare2pow63("9223372036854775800")
**
** will return -8.
*/
static int compare2pow63(const char *zNum){
  int c;
  c = memcmp(zNum,"922337203685477580",18)*10;
  if( c==0 ){
    c = zNum[18] - '8';
  }
  return c;
}


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.851 2009/06/15 20:45:35 drh Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes.  The test







|







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.852 2009/06/17 16:20:04 drh Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes.  The test
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
** if we run out of memory.
*/
static VdbeCursor *allocateCursor(
  Vdbe *p,              /* The virtual machine */
  int iCur,             /* Index of the new VdbeCursor */
  int nField,           /* Number of fields in the table or index */
  int iDb,              /* When database the cursor belongs to, or -1 */
  int isBtreeCursor     /* */
){
  /* Find the memory cell that will be used to store the blob of memory
  ** required for this VdbeCursor structure. It is convenient to use a 
  ** vdbe memory cell to manage the memory allocation required for a
  ** VdbeCursor structure for the following reasons:
  **
  **   * Sometimes cursor numbers are used for a couple of different







|







185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
** if we run out of memory.
*/
static VdbeCursor *allocateCursor(
  Vdbe *p,              /* The virtual machine */
  int iCur,             /* Index of the new VdbeCursor */
  int nField,           /* Number of fields in the table or index */
  int iDb,              /* When database the cursor belongs to, or -1 */
  int isBtreeCursor     /* True for B-Tree vs. pseudo-table or vtab */
){
  /* Find the memory cell that will be used to store the blob of memory
  ** required for this VdbeCursor structure. It is convenient to use a 
  ** vdbe memory cell to manage the memory allocation required for a
  ** VdbeCursor structure for the following reasons:
  **
  **   * Sometimes cursor numbers are used for a couple of different
Changes to src/vdbemem.c.
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
*************************************************************************
**
** This file contains code use to manipulate "Mem" structure.  A "Mem"
** stores a single value in the VDBE.  Mem is an opaque structure visible
** only within the VDBE.  Interface routines refer to a Mem using the
** name sqlite_value
**
** $Id: vdbemem.c,v 1.147 2009/05/28 11:05:57 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"

/*
** Call sqlite3VdbeMemExpandBlob() on the supplied value (type Mem*)
** P if required.







|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
*************************************************************************
**
** This file contains code use to manipulate "Mem" structure.  A "Mem"
** stores a single value in the VDBE.  Mem is an opaque structure visible
** only within the VDBE.  Interface routines refer to a Mem using the
** name sqlite_value
**
** $Id: vdbemem.c,v 1.148 2009/06/17 16:20:04 drh Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"

/*
** Call sqlite3VdbeMemExpandBlob() on the supplied value (type Mem*)
** P if required.
407
408
409
410
411
412
413











414
415
416
417
418
419
420
421
void sqlite3VdbeIntegerAffinity(Mem *pMem){
  assert( pMem->flags & MEM_Real );
  assert( (pMem->flags & MEM_RowSet)==0 );
  assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
  assert( EIGHT_BYTE_ALIGNMENT(pMem) );

  pMem->u.i = doubleToInt64(pMem->r);











  if( pMem->r==(double)pMem->u.i ){
    pMem->flags |= MEM_Int;
  }
}

/*
** Convert pMem to type integer.  Invalidate any prior representations.
*/







>
>
>
>
>
>
>
>
>
>
>
|







407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
void sqlite3VdbeIntegerAffinity(Mem *pMem){
  assert( pMem->flags & MEM_Real );
  assert( (pMem->flags & MEM_RowSet)==0 );
  assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
  assert( EIGHT_BYTE_ALIGNMENT(pMem) );

  pMem->u.i = doubleToInt64(pMem->r);

  /* Only mark the value as an integer if
  **
  **    (1) the round-trip conversion real->int->real is a no-op, and
  **    (2) The integer is neither the largest nor the smallest
  **        possible integer (ticket #3922)
  **
  ** The second term in the following conditional enforces the second
  ** condition under the assumption that additional overflow causes
  ** values to wrap around.
  */
  if( pMem->r==(double)pMem->u.i && (pMem->u.i-1) < (pMem->u.i+1) ){
    pMem->flags |= MEM_Int;
  }
}

/*
** Convert pMem to type integer.  Invalidate any prior representations.
*/
Added test/tkt3922.test.
























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# 2009 June 17
#
# 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.
#
#***********************************************************************
#
# $Id: tkt3922.test,v 1.1 2009/06/17 16:20:04 drh Exp $

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

do_test tkt3922.1 {
  execsql {
    CREATE TABLE t1(a NUMBER);
    INSERT INTO t1 VALUES('-9223372036854775808');
    SELECT a, typeof(a) FROM t1;
  }
} {-9223372036854775808 integer}
do_test tkt3922.2 {
  execsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES('-9223372036854775809');
    SELECT a, typeof(a) FROM t1;
  }
} {-9.22337203685478e+18 real}
do_test tkt3922.3 {
  execsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES('-9223372036854776832');
    SELECT a, typeof(a) FROM t1;
  }
} {-9.22337203685478e+18 real}
do_test tkt3922.4 {
  execsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES('-9223372036854776833');
    SELECT a, typeof(a) FROM t1;
  }
} {-9.22337203685478e+18 real}
do_test tkt3922.5 {
  execsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES('9223372036854775807');
    SELECT a, typeof(a) FROM t1;
  }
} {9223372036854775807 integer}
do_test tkt3922.6 {
  execsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES('9223372036854775808');
    SELECT a, typeof(a) FROM t1;
  }
} {9.22337203685478e+18 real}

finish_test