/ Check-in [8858042f]
Login

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

Overview
Comment:Modify the vdbe so that the comparison operator opcodes do not modify the data type of operands. Fix for [aa92c76cd4].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 8858042fa1449516a2c7dbb991dca3eb6c5794cb
User & Date: dan 2010-03-05 16:32:12
Context
2010-03-05
17:27
Fix a one byte buffer overread in fts3. check-in: 6e3e014a user: dan tags: trunk
16:32
Modify the vdbe so that the comparison operator opcodes do not modify the data type of operands. Fix for [aa92c76cd4]. check-in: 8858042f user: dan tags: trunk
13:53
Adjustments to #ifdefs so that the #include of <sys/mount.h> is not included twice, because that confuses the amalgamation builder. check-in: 27413fc8 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/expr.c.

   244    244     CollSeq *p4;
   245    245   
   246    246     p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
   247    247     p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);
   248    248     addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
   249    249                              (void*)p4, P4_COLLSEQ);
   250    250     sqlite3VdbeChangeP5(pParse->pVdbe, (u8)p5);
   251         -  if( (p5 & SQLITE_AFF_MASK)!=SQLITE_AFF_NONE ){
   252         -    sqlite3ExprCacheAffinityChange(pParse, in1, 1);
   253         -    sqlite3ExprCacheAffinityChange(pParse, in2, 1);
   254         -  }
   255    251     return addr;
   256    252   }
   257    253   
   258    254   #if SQLITE_MAX_EXPR_DEPTH>0
   259    255   /*
   260    256   ** Check that argument nHeight is less than or equal to the maximum
   261    257   ** expression depth allowed. If it is not, leave an error message in

Changes to src/main.c.

  1046   1046     void (*xStep)(sqlite3_context*,int,sqlite3_value**),
  1047   1047     void (*xFinal)(sqlite3_context*)
  1048   1048   ){
  1049   1049     int rc;
  1050   1050     char *zFunc8;
  1051   1051     sqlite3_mutex_enter(db->mutex);
  1052   1052     assert( !db->mallocFailed );
  1053         -  zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1);
         1053  +  zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1, SQLITE_UTF16NATIVE);
  1054   1054     rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xFunc, xStep, xFinal);
  1055   1055     sqlite3DbFree(db, zFunc8);
  1056   1056     rc = sqlite3ApiExit(db, rc);
  1057   1057     sqlite3_mutex_leave(db->mutex);
  1058   1058     return rc;
  1059   1059   }
  1060   1060   #endif
................................................................................
  1869   1869     void* pCtx,
  1870   1870     int(*xCompare)(void*,int,const void*,int,const void*)
  1871   1871   ){
  1872   1872     int rc = SQLITE_OK;
  1873   1873     char *zName8;
  1874   1874     sqlite3_mutex_enter(db->mutex);
  1875   1875     assert( !db->mallocFailed );
  1876         -  zName8 = sqlite3Utf16to8(db, zName, -1);
         1876  +  zName8 = sqlite3Utf16to8(db, zName, -1, SQLITE_UTF16NATIVE);
  1877   1877     if( zName8 ){
  1878   1878       rc = createCollation(db, zName8, (u8)enc, SQLITE_COLL_USER, pCtx, xCompare, 0);
  1879   1879       sqlite3DbFree(db, zName8);
  1880   1880     }
  1881   1881     rc = sqlite3ApiExit(db, rc);
  1882   1882     sqlite3_mutex_leave(db->mutex);
  1883   1883     return rc;

Changes to src/prepare.c.

   796    796   
   797    797     assert( ppStmt );
   798    798     *ppStmt = 0;
   799    799     if( !sqlite3SafetyCheckOk(db) ){
   800    800       return SQLITE_MISUSE_BKPT;
   801    801     }
   802    802     sqlite3_mutex_enter(db->mutex);
   803         -  zSql8 = sqlite3Utf16to8(db, zSql, nBytes);
          803  +  zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE);
   804    804     if( zSql8 ){
   805    805       rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, 0, ppStmt, &zTail8);
   806    806     }
   807    807   
   808    808     if( zTail8 && pzTail ){
   809    809       /* If sqlite3_prepare returns a tail pointer, we calculate the
   810    810       ** equivalent pointer into the UTF-16 string by counting the unicode

Changes to src/sqliteInt.h.

  2854   2854   
  2855   2855   const void *sqlite3ValueText(sqlite3_value*, u8);
  2856   2856   int sqlite3ValueBytes(sqlite3_value*, u8);
  2857   2857   void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, 
  2858   2858                           void(*)(void*));
  2859   2859   void sqlite3ValueFree(sqlite3_value*);
  2860   2860   sqlite3_value *sqlite3ValueNew(sqlite3 *);
  2861         -char *sqlite3Utf16to8(sqlite3 *, const void*, int);
         2861  +char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8);
  2862   2862   #ifdef SQLITE_ENABLE_STAT2
  2863   2863   char *sqlite3Utf8to16(sqlite3 *, u8, char *, int, int *);
  2864   2864   #endif
  2865   2865   int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
  2866   2866   void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
  2867   2867   #ifndef SQLITE_AMALGAMATION
  2868   2868   extern const unsigned char sqlite3OpcodeProperty[];

Changes to src/utf.c.

   433    433   /*
   434    434   ** Convert a UTF-16 string in the native encoding into a UTF-8 string.
   435    435   ** Memory to hold the UTF-8 string is obtained from sqlite3_malloc and must
   436    436   ** be freed by the calling function.
   437    437   **
   438    438   ** NULL is returned if there is an allocation error.
   439    439   */
   440         -char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte){
          440  +char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 enc){
   441    441     Mem m;
   442    442     memset(&m, 0, sizeof(m));
   443    443     m.db = db;
   444         -  sqlite3VdbeMemSetStr(&m, z, nByte, SQLITE_UTF16NATIVE, SQLITE_STATIC);
          444  +  sqlite3VdbeMemSetStr(&m, z, nByte, enc, SQLITE_STATIC);
   445    445     sqlite3VdbeChangeEncoding(&m, SQLITE_UTF8);
   446    446     if( db->mallocFailed ){
   447    447       sqlite3VdbeMemRelease(&m);
   448    448       m.z = 0;
   449    449     }
   450    450     assert( (m.flags & MEM_Term)!=0 || db->mallocFailed );
   451    451     assert( (m.flags & MEM_Str)!=0 || db->mallocFailed );
   452         -  return (m.flags & MEM_Dyn)!=0 ? m.z : sqlite3DbStrDup(db, m.z);
          452  +  assert( (m.flags & MEM_Dyn)!=0 || db->mallocFailed );
          453  +  assert( m.z || db->mallocFailed );
          454  +  return m.z;
   453    455   }
   454    456   
   455    457   /*
   456    458   ** Convert a UTF-8 string to the UTF-16 encoding specified by parameter
   457    459   ** enc. A pointer to the new string is returned, and the value of *pnOut
   458    460   ** is set to the length of the returned string in bytes. The call should
   459    461   ** arrange to call sqlite3DbFree() on the returned pointer when it is

Changes to src/vdbe.c.

   235    235   ** do so without loss of information.  In other words, if the string
   236    236   ** looks like a number, convert it into a number.  If it does not
   237    237   ** look like a number, leave it alone.
   238    238   */
   239    239   static void applyNumericAffinity(Mem *pRec){
   240    240     if( (pRec->flags & (MEM_Real|MEM_Int))==0 ){
   241    241       int realnum;
          242  +    u8 enc = pRec->enc;
   242    243       sqlite3VdbeMemNulTerminate(pRec);
   243         -    if( (pRec->flags&MEM_Str)
   244         -         && sqlite3IsNumber(pRec->z, &realnum, pRec->enc) ){
          244  +    if( (pRec->flags&MEM_Str) && sqlite3IsNumber(pRec->z, &realnum, enc) ){
   245    245         i64 value;
   246         -      sqlite3VdbeChangeEncoding(pRec, SQLITE_UTF8);
   247         -      if( !realnum && sqlite3Atoi64(pRec->z, &value) ){
          246  +      char *zUtf8 = pRec->z;
          247  +#ifndef SQLITE_OMIT_UTF16
          248  +      if( enc!=SQLITE_UTF8 ){
          249  +        assert( pRec->db );
          250  +        zUtf8 = sqlite3Utf16to8(pRec->db, pRec->z, pRec->n, enc);
          251  +        if( !zUtf8 ) return;
          252  +      }
          253  +#endif
          254  +      if( !realnum && sqlite3Atoi64(zUtf8, &value) ){
   248    255           pRec->u.i = value;
   249    256           MemSetTypeFlag(pRec, MEM_Int);
   250    257         }else{
   251         -        sqlite3VdbeMemRealify(pRec);
          258  +        sqlite3AtoF(zUtf8, &pRec->r);
          259  +        MemSetTypeFlag(pRec, MEM_Real);
   252    260         }
          261  +#ifndef SQLITE_OMIT_UTF16
          262  +      if( enc!=SQLITE_UTF8 ){
          263  +        sqlite3DbFree(pRec->db, zUtf8);
          264  +      }
          265  +#endif
   253    266       }
   254    267     }
   255    268   }
   256    269   
   257    270   /*
   258    271   ** Processing is determine by the affinity parameter:
   259    272   **
................................................................................
  1727   1740   case OP_Ne:               /* same as TK_NE, jump, in1, in3 */
  1728   1741   case OP_Lt:               /* same as TK_LT, jump, in1, in3 */
  1729   1742   case OP_Le:               /* same as TK_LE, jump, in1, in3 */
  1730   1743   case OP_Gt:               /* same as TK_GT, jump, in1, in3 */
  1731   1744   case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
  1732   1745     int res;            /* Result of the comparison of pIn1 against pIn3 */
  1733   1746     char affinity;      /* Affinity to use for comparison */
         1747  +  u16 flags1;         /* Copy of initial value of pIn1->flags */
         1748  +  u16 flags3;         /* Copy of initial value of pIn3->flags */
  1734   1749   
  1735   1750     pIn1 = &aMem[pOp->p1];
  1736   1751     pIn3 = &aMem[pOp->p3];
         1752  +  flags1 = pIn1->flags;
         1753  +  flags3 = pIn3->flags;
  1737   1754     if( (pIn1->flags | pIn3->flags)&MEM_Null ){
  1738   1755       /* One or both operands are NULL */
  1739   1756       if( pOp->p5 & SQLITE_NULLEQ ){
  1740   1757         /* If SQLITE_NULLEQ is set (which will only happen if the operator is
  1741   1758         ** OP_Eq or OP_Ne) then take the jump or not depending on whether
  1742   1759         ** or not both operands are null.
  1743   1760         */
................................................................................
  1784   1801       pOut = &aMem[pOp->p2];
  1785   1802       MemSetTypeFlag(pOut, MEM_Int);
  1786   1803       pOut->u.i = res;
  1787   1804       REGISTER_TRACE(pOp->p2, pOut);
  1788   1805     }else if( res ){
  1789   1806       pc = pOp->p2-1;
  1790   1807     }
         1808  +
         1809  +  /* Undo any changes made by applyAffinity() to the input registers. */
         1810  +  pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (flags1&MEM_TypeMask);
         1811  +  pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (flags3&MEM_TypeMask);
  1791   1812     break;
  1792   1813   }
  1793   1814   
  1794   1815   /* Opcode: Permutation * * * P4 *
  1795   1816   **
  1796   1817   ** Set the permutation used by the OP_Compare operator to be the array
  1797   1818   ** of integers in P4.

Changes to test/select7.test.

   151    151       } [list 0 $result]
   152    152       append sql { UNION ALL SELECT 99999999}
   153    153       do_test select7-6.2 {
   154    154         catchsql $sql
   155    155       } {1 {too many terms in compound SELECT}}
   156    156     }
   157    157   }
          158  +
          159  +# This block of tests verifies that bug aa92c76cd4 is fixed.
          160  +#
          161  +do_test select7-7.1 {
          162  +  execsql {
          163  +    CREATE TABLE t3(a REAL);
          164  +    INSERT INTO t3 VALUES(44.0);
          165  +    INSERT INTO t3 VALUES(56.0);
          166  +  }
          167  +} {}
          168  +do_test select7-7.2 {
          169  +  execsql {
          170  +    pragma vdbe_trace = 0;
          171  +    SELECT (CASE WHEN a=0 THEN 0 ELSE (a + 25) / 50 END) AS categ, count(*)
          172  +    FROM t3 GROUP BY categ
          173  +  }
          174  +} {1.38 1 1.62 1}
          175  +do_test select7-7.3 {
          176  +  execsql {
          177  +    CREATE TABLE t4(a REAL);
          178  +    INSERT INTO t4 VALUES( 2.0 );
          179  +    INSERT INTO t4 VALUES( 3.0 );
          180  +  }
          181  +} {}
          182  +do_test select7-7.4 {
          183  +  execsql {
          184  +    SELECT (CASE WHEN a=0 THEN 'zero' ELSE a/2 END) AS t FROM t4 GROUP BY t;
          185  +  }
          186  +} {1.0 1.5}
          187  +do_test select7-7.5 {
          188  +  execsql { SELECT a=0, typeof(a) FROM t4 }
          189  +} {0 real 0 real}
          190  +do_test select7-7.6 {
          191  +  execsql { SELECT a=0, typeof(a) FROM t4 GROUP BY a }
          192  +} {0 real 0 real}
          193  +
          194  +do_test select7-7.7 {
          195  +  execsql {
          196  +    CREATE TABLE t5(a TEXT, b INT);
          197  +    INSERT INTO t5 VALUES(123, 456);
          198  +    SELECT typeof(a), a FROM t5 GROUP BY a HAVING a<b;
          199  +  }
          200  +} {text 123}
   158    201   
   159    202   finish_test