/ Check-in [b8381d9f]
Login

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

Overview
Comment:Fix problem in the code generator were incorrect code was being created if the SQL source contained a negative integer that was too large to fit in a 32-bit signed integer variable. Ticket #552. (CVS 1157)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: b8381d9fe99273507e8626638110646801afef06
User & Date: drh 2004-01-06 01:13:46
Context
2004-01-06
01:27
Increase the version number and update the change log prior to the next release. (CVS 1158) check-in: b99b68d0 user: drh tags: trunk
01:13
Fix problem in the code generator were incorrect code was being created if the SQL source contained a negative integer that was too large to fit in a 32-bit signed integer variable. Ticket #552. (CVS 1157) check-in: b8381d9f user: drh tags: trunk
00:44
Add the sqlite_current_time variable for testing purposes. (CVS 1156) check-in: 23fa407d user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/expr.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains routines used for analyzing expressions and
    13     13   ** for generating VDBE code that evaluates expressions in SQLite.
    14     14   **
    15         -** $Id: expr.c,v 1.102 2003/12/10 03:13:44 drh Exp $
           15  +** $Id: expr.c,v 1.103 2004/01/06 01:13:46 drh Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   #include <ctype.h>
    19     19   
    20     20   /*
    21     21   ** Construct a new expression node and return a pointer to it.  Memory
    22     22   ** for this node is obtained from sqliteMalloc().  The calling function
................................................................................
   324    324         return p->pLeft!=0 || p->pRight!=0 || (p->pList && p->pList->nExpr>0);
   325    325       }
   326    326     }
   327    327     return 0;
   328    328   }
   329    329   
   330    330   /*
   331         -** If the given expression codes a constant integer, return 1 and put
   332         -** the value of the integer in *pValue.  If the expression is not an
   333         -** integer, return 0 and leave *pValue unchanged.
          331  +** If the given expression codes a constant integer that is small enough
          332  +** to fit in a 32-bit integer, return 1 and put the value of the integer
          333  +** in *pValue.  If the expression is not an integer or if it is too big
          334  +** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
   334    335   */
   335    336   int sqliteExprIsInteger(Expr *p, int *pValue){
   336    337     switch( p->op ){
   337    338       case TK_INTEGER: {
   338         -      *pValue = atoi(p->token.z);
   339         -      return 1;
          339  +      if( sqliteFitsIn32Bits(p->token.z) ){
          340  +        *pValue = atoi(p->token.z);
          341  +        return 1;
          342  +      }
          343  +      break;
   340    344       }
   341    345       case TK_STRING: {
   342    346         const char *z = p->token.z;
   343    347         int n = p->token.n;
   344    348         if( n>0 && z[0]=='-' ){ z++; n--; }
   345    349         while( n>0 && *z && isdigit(*z) ){ z++; n--; }
   346         -      if( n==0 ){
          350  +      if( n==0 && sqliteFitsIn32Bits(p->token.z) ){
   347    351           *pValue = atoi(p->token.z);
   348    352           return 1;
   349    353         }
   350    354         break;
   351    355       }
   352    356       case TK_UPLUS: {
   353    357         return sqliteExprIsInteger(p->pLeft, pValue);
................................................................................
   965    969       default:
   966    970         assert( p->op==TK_ABORT );  /* Can't Happen */
   967    971         break;
   968    972     }
   969    973     return SQLITE_SO_NUM;
   970    974   }
   971    975   
          976  +/*
          977  +** Run
          978  +
   972    979   /*
   973    980   ** Generate code into the current Vdbe to evaluate the given
   974    981   ** expression and leave the result on the top of stack.
   975    982   */
   976    983   void sqliteExprCode(Parse *pParse, Expr *pExpr){
   977    984     Vdbe *v = pParse->pVdbe;
   978    985     int op;
................................................................................
  1010   1017           sqliteVdbeAddOp(v, OP_Column, pExpr->iTable, pExpr->iColumn);
  1011   1018         }else{
  1012   1019           sqliteVdbeAddOp(v, OP_Recno, pExpr->iTable, 0);
  1013   1020         }
  1014   1021         break;
  1015   1022       }
  1016   1023       case TK_INTEGER: {
  1017         -      int iVal = atoi(pExpr->token.z);
  1018         -      char zBuf[30];
  1019         -      sprintf(zBuf,"%d",iVal);
  1020         -      if( strlen(zBuf)!=pExpr->token.n 
  1021         -            || strncmp(pExpr->token.z,zBuf,pExpr->token.n)!=0 ){
  1022         -        /* If the integer value cannot be represented exactly in 32 bits,
  1023         -        ** then code it as a string instead. */
         1024  +      if( !sqliteFitsIn32Bits(pExpr->token.z) ){
  1024   1025           sqliteVdbeAddOp(v, OP_String, 0, 0);
  1025   1026         }else{
  1026         -        sqliteVdbeAddOp(v, OP_Integer, iVal, 0);
         1027  +        sqliteVdbeAddOp(v, OP_Integer, atoi(pExpr->token.z), 0);
  1027   1028         }
  1028   1029         sqliteVdbeChangeP3(v, -1, pExpr->token.z, pExpr->token.n);
  1029   1030         break;
  1030   1031       }
  1031   1032       case TK_FLOAT: {
  1032   1033         sqliteVdbeAddOp(v, OP_String, 0, 0);
  1033   1034         assert( pExpr->token.z );
................................................................................
  1086   1087         sqliteExprCode(pParse, pExpr->pRight);
  1087   1088         sqliteVdbeAddOp(v, OP_Concat, 2, 0);
  1088   1089         break;
  1089   1090       }
  1090   1091       case TK_UPLUS: {
  1091   1092         Expr *pLeft = pExpr->pLeft;
  1092   1093         if( pLeft && pLeft->op==TK_INTEGER ){
  1093         -        sqliteVdbeAddOp(v, OP_Integer, atoi(pLeft->token.z), 0);
         1094  +        if( sqliteFitsIn32Bits(pLeft->token.z) ){
         1095  +          sqliteVdbeAddOp(v, OP_Integer, atoi(pLeft->token.z), 0);
         1096  +        }else{
         1097  +          sqliteVdbeAddOp(v, OP_String, 0, 0);
         1098  +        }
  1094   1099           sqliteVdbeChangeP3(v, -1, pLeft->token.z, pLeft->token.n);
  1095   1100         }else if( pLeft && pLeft->op==TK_FLOAT ){
  1096   1101           sqliteVdbeAddOp(v, OP_String, 0, 0);
  1097   1102           sqliteVdbeChangeP3(v, -1, pLeft->token.z, pLeft->token.n);
  1098   1103         }else{
  1099   1104           sqliteExprCode(pParse, pExpr->pLeft);
  1100   1105         }
................................................................................
  1102   1107       }
  1103   1108       case TK_UMINUS: {
  1104   1109         assert( pExpr->pLeft );
  1105   1110         if( pExpr->pLeft->op==TK_FLOAT || pExpr->pLeft->op==TK_INTEGER ){
  1106   1111           Token *p = &pExpr->pLeft->token;
  1107   1112           char *z = sqliteMalloc( p->n + 2 );
  1108   1113           sprintf(z, "-%.*s", p->n, p->z);
  1109         -        if( pExpr->pLeft->op==TK_INTEGER ){
         1114  +        if( pExpr->pLeft->op==TK_INTEGER && sqliteFitsIn32Bits(z) ){
  1110   1115             sqliteVdbeAddOp(v, OP_Integer, atoi(z), 0);
  1111   1116           }else{
  1112   1117             sqliteVdbeAddOp(v, OP_String, 0, 0);
  1113   1118           }
  1114   1119           sqliteVdbeChangeP3(v, -1, z, p->n+1);
  1115   1120           sqliteFree(z);
  1116   1121           break;

Changes to src/sqliteInt.h.

     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Internal interface definitions for SQLite.
    13     13   **
    14         -** @(#) $Id: sqliteInt.h,v 1.205 2003/12/23 02:17:35 drh Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.206 2004/01/06 01:13:47 drh Exp $
    15     15   */
    16     16   #include "config.h"
    17     17   #include "sqlite.h"
    18     18   #include "hash.h"
    19     19   #include "vdbe.h"
    20     20   #include "parse.h"
    21     21   #include "btree.h"
................................................................................
  1201   1201   int sqliteFixSrcList(DbFixer*, SrcList*);
  1202   1202   int sqliteFixSelect(DbFixer*, Select*);
  1203   1203   int sqliteFixExpr(DbFixer*, Expr*);
  1204   1204   int sqliteFixExprList(DbFixer*, ExprList*);
  1205   1205   int sqliteFixTriggerStep(DbFixer*, TriggerStep*);
  1206   1206   double sqliteAtoF(const char *z);
  1207   1207   int sqlite_snprintf(int,char*,const char*,...);
         1208  +int sqliteFitsIn32Bits(const char *);

Changes to src/util.c.

    10     10   **
    11     11   *************************************************************************
    12     12   ** Utility functions used throughout sqlite.
    13     13   **
    14     14   ** This file contains functions for allocating memory, comparing
    15     15   ** strings, and stuff like that.
    16     16   **
    17         -** $Id: util.c,v 1.69 2003/12/23 02:17:35 drh Exp $
           17  +** $Id: util.c,v 1.70 2004/01/06 01:13:47 drh Exp $
    18     18   */
    19     19   #include "sqliteInt.h"
    20     20   #include <stdarg.h>
    21     21   #include <ctype.h>
    22     22   
    23     23   /*
    24     24   ** If malloc() ever fails, this global variable gets set to 1.
................................................................................
   708    708         v1 /= scale;
   709    709       }else{
   710    710         v1 *= scale;
   711    711       }
   712    712     }
   713    713     return sign<0 ? -v1 : v1;
   714    714   }
          715  +
          716  +/*
          717  +** The string zNum represents an integer.  There might be some other
          718  +** information following the integer too, but that part is ignored.
          719  +** If the integer that the prefix of zNum represents will fit in a
          720  +** 32-bit signed integer, return TRUE.  Otherwise return FALSE.
          721  +**
          722  +** This routine returns FALSE for the string -2147483648 even that
          723  +** that number will, in theory fit in a 32-bit integer.  But positive
          724  +** 2147483648 will not fit in 32 bits.  So it seems safer to return
          725  +** false.
          726  +*/
          727  +int sqliteFitsIn32Bits(const char *zNum){
          728  +  int i, c;
          729  +  if( *zNum=='-' || *zNum=='+' ) zNum++;
          730  +  for(i=0; (c=zNum[i])>='0' && c<='9'; i++){}
          731  +  return i<10 || (i==10 && memcmp(zNum,"2147483647",10)<=0);
          732  +}
   715    733   
   716    734   /* This comparison routine is what we use for comparison operations
   717    735   ** between numeric values in an SQL expression.  "Numeric" is a little
   718    736   ** bit misleading here.  What we mean is that the strings have a
   719    737   ** type of "numeric" from the point of view of SQL.  The strings
   720    738   ** do not necessarily contain numbers.  They could contain text.
   721    739   **

Changes to test/misc3.test.

     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.
    12     12   #
    13     13   # This file implements tests for miscellanous features that were
    14     14   # left out of other test files.
    15     15   #
    16         -# $Id: misc3.test,v 1.2 2003/12/23 02:17:35 drh Exp $
           16  +# $Id: misc3.test,v 1.3 2004/01/06 01:13:47 drh Exp $
    17     17   
    18     18   set testdir [file dirname $argv0]
    19     19   source $testdir/tester.tcl
    20     20   
    21     21   # Ticket #529.  Make sure an ABORT does not damage the in-memory cache
    22     22   # that will be used by subsequent statements in the same transaction.
    23     23   #
................................................................................
    94     94   do_test misc3-2.8 {
    95     95     execsql {SELECT 2.0e-27 * '+0.5e+127'}
    96     96   } 1e+100
    97     97   do_test misc3-2.9 {
    98     98     execsql {SELECT 2.0e-27 * '+0.000005e+132'}
    99     99   } 1e+100
   100    100   
          101  +# Ticket #522.  Make sure integer overflow is handled properly in
          102  +# indices.
          103  +#
          104  +do_test misc3-3.1 {
          105  +  execsql {PRAGMA integrity_check}
          106  +} ok
          107  +do_test misc3-3.2 {
          108  +  execsql {
          109  +    CREATE TABLE t2(a INT UNIQUE);
          110  +    PRAGMA integrity_check;
          111  +  }
          112  +} ok
          113  +do_test misc3-3.3 {
          114  +  execsql {
          115  +    INSERT INTO t2 VALUES(2147483648);
          116  +    PRAGMA integrity_check;
          117  +  }
          118  +} ok
          119  +do_test misc3-3.4 {
          120  +  execsql {
          121  +    INSERT INTO t2 VALUES(-2147483649);
          122  +    PRAGMA integrity_check;
          123  +  }
          124  +} ok
   101    125   
   102    126   finish_test