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 |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
8858042fa1449516a2c7dbb991dca3eb |
User & Date: | dan 2010-03-05 16:32:12.000 |
Context
2010-03-05
| ||
17:27 | Fix a one byte buffer overread in fts3. (check-in: 6e3e014af9 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: 8858042fa1 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: 27413fc8dd user: drh tags: trunk) | |
Changes
Changes to src/expr.c.
︙ | ︙ | |||
244 245 246 247 248 249 250 | CollSeq *p4; p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight); p5 = binaryCompareP5(pLeft, pRight, jumpIfNull); addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1, (void*)p4, P4_COLLSEQ); sqlite3VdbeChangeP5(pParse->pVdbe, (u8)p5); | < < < < | 244 245 246 247 248 249 250 251 252 253 254 255 256 257 | CollSeq *p4; p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight); p5 = binaryCompareP5(pLeft, pRight, jumpIfNull); addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1, (void*)p4, P4_COLLSEQ); sqlite3VdbeChangeP5(pParse->pVdbe, (u8)p5); return addr; } #if SQLITE_MAX_EXPR_DEPTH>0 /* ** Check that argument nHeight is less than or equal to the maximum ** expression depth allowed. If it is not, leave an error message in |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
1046 1047 1048 1049 1050 1051 1052 | void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*) ){ int rc; char *zFunc8; sqlite3_mutex_enter(db->mutex); assert( !db->mallocFailed ); | | | 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 | void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*) ){ int rc; char *zFunc8; sqlite3_mutex_enter(db->mutex); assert( !db->mallocFailed ); zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1, SQLITE_UTF16NATIVE); rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xFunc, xStep, xFinal); sqlite3DbFree(db, zFunc8); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; } #endif |
︙ | ︙ | |||
1869 1870 1871 1872 1873 1874 1875 | void* pCtx, int(*xCompare)(void*,int,const void*,int,const void*) ){ int rc = SQLITE_OK; char *zName8; sqlite3_mutex_enter(db->mutex); assert( !db->mallocFailed ); | | | 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 | void* pCtx, int(*xCompare)(void*,int,const void*,int,const void*) ){ int rc = SQLITE_OK; char *zName8; sqlite3_mutex_enter(db->mutex); assert( !db->mallocFailed ); zName8 = sqlite3Utf16to8(db, zName, -1, SQLITE_UTF16NATIVE); if( zName8 ){ rc = createCollation(db, zName8, (u8)enc, SQLITE_COLL_USER, pCtx, xCompare, 0); sqlite3DbFree(db, zName8); } rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; |
︙ | ︙ |
Changes to src/prepare.c.
︙ | ︙ | |||
796 797 798 799 800 801 802 | assert( ppStmt ); *ppStmt = 0; if( !sqlite3SafetyCheckOk(db) ){ return SQLITE_MISUSE_BKPT; } sqlite3_mutex_enter(db->mutex); | | | 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 | assert( ppStmt ); *ppStmt = 0; if( !sqlite3SafetyCheckOk(db) ){ return SQLITE_MISUSE_BKPT; } sqlite3_mutex_enter(db->mutex); zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE); if( zSql8 ){ rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, 0, ppStmt, &zTail8); } if( zTail8 && pzTail ){ /* If sqlite3_prepare returns a tail pointer, we calculate the ** equivalent pointer into the UTF-16 string by counting the unicode |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
2854 2855 2856 2857 2858 2859 2860 | const void *sqlite3ValueText(sqlite3_value*, u8); int sqlite3ValueBytes(sqlite3_value*, u8); void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void(*)(void*)); void sqlite3ValueFree(sqlite3_value*); sqlite3_value *sqlite3ValueNew(sqlite3 *); | | | 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 | const void *sqlite3ValueText(sqlite3_value*, u8); int sqlite3ValueBytes(sqlite3_value*, u8); void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void(*)(void*)); void sqlite3ValueFree(sqlite3_value*); sqlite3_value *sqlite3ValueNew(sqlite3 *); char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8); #ifdef SQLITE_ENABLE_STAT2 char *sqlite3Utf8to16(sqlite3 *, u8, char *, int, int *); #endif int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **); void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8); #ifndef SQLITE_AMALGAMATION extern const unsigned char sqlite3OpcodeProperty[]; |
︙ | ︙ |
Changes to src/utf.c.
︙ | ︙ | |||
433 434 435 436 437 438 439 | /* ** Convert a UTF-16 string in the native encoding into a UTF-8 string. ** Memory to hold the UTF-8 string is obtained from sqlite3_malloc and must ** be freed by the calling function. ** ** NULL is returned if there is an allocation error. */ | | | | > > | 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 | /* ** Convert a UTF-16 string in the native encoding into a UTF-8 string. ** Memory to hold the UTF-8 string is obtained from sqlite3_malloc and must ** be freed by the calling function. ** ** NULL is returned if there is an allocation error. */ char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 enc){ Mem m; memset(&m, 0, sizeof(m)); m.db = db; sqlite3VdbeMemSetStr(&m, z, nByte, enc, SQLITE_STATIC); sqlite3VdbeChangeEncoding(&m, SQLITE_UTF8); if( db->mallocFailed ){ sqlite3VdbeMemRelease(&m); m.z = 0; } assert( (m.flags & MEM_Term)!=0 || db->mallocFailed ); assert( (m.flags & MEM_Str)!=0 || db->mallocFailed ); assert( (m.flags & MEM_Dyn)!=0 || db->mallocFailed ); assert( m.z || db->mallocFailed ); return m.z; } /* ** Convert a UTF-8 string to the UTF-16 encoding specified by parameter ** enc. A pointer to the new string is returned, and the value of *pnOut ** is set to the length of the returned string in bytes. The call should ** arrange to call sqlite3DbFree() on the returned pointer when it is |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
235 236 237 238 239 240 241 242 | ** do so without loss of information. In other words, if the string ** looks like a number, convert it into a number. If it does not ** look like a number, leave it alone. */ static void applyNumericAffinity(Mem *pRec){ if( (pRec->flags & (MEM_Real|MEM_Int))==0 ){ int realnum; sqlite3VdbeMemNulTerminate(pRec); | > | < > > | > > > > > | | > > > > > > | 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 | ** do so without loss of information. In other words, if the string ** looks like a number, convert it into a number. If it does not ** look like a number, leave it alone. */ static void applyNumericAffinity(Mem *pRec){ if( (pRec->flags & (MEM_Real|MEM_Int))==0 ){ int realnum; u8 enc = pRec->enc; sqlite3VdbeMemNulTerminate(pRec); if( (pRec->flags&MEM_Str) && sqlite3IsNumber(pRec->z, &realnum, enc) ){ i64 value; char *zUtf8 = pRec->z; #ifndef SQLITE_OMIT_UTF16 if( enc!=SQLITE_UTF8 ){ assert( pRec->db ); zUtf8 = sqlite3Utf16to8(pRec->db, pRec->z, pRec->n, enc); if( !zUtf8 ) return; } #endif if( !realnum && sqlite3Atoi64(zUtf8, &value) ){ pRec->u.i = value; MemSetTypeFlag(pRec, MEM_Int); }else{ sqlite3AtoF(zUtf8, &pRec->r); MemSetTypeFlag(pRec, MEM_Real); } #ifndef SQLITE_OMIT_UTF16 if( enc!=SQLITE_UTF8 ){ sqlite3DbFree(pRec->db, zUtf8); } #endif } } } /* ** Processing is determine by the affinity parameter: ** |
︙ | ︙ | |||
1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 | case OP_Ne: /* same as TK_NE, jump, in1, in3 */ case OP_Lt: /* same as TK_LT, jump, in1, in3 */ case OP_Le: /* same as TK_LE, jump, in1, in3 */ case OP_Gt: /* same as TK_GT, jump, in1, in3 */ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ int res; /* Result of the comparison of pIn1 against pIn3 */ char affinity; /* Affinity to use for comparison */ pIn1 = &aMem[pOp->p1]; pIn3 = &aMem[pOp->p3]; if( (pIn1->flags | pIn3->flags)&MEM_Null ){ /* One or both operands are NULL */ if( pOp->p5 & SQLITE_NULLEQ ){ /* If SQLITE_NULLEQ is set (which will only happen if the operator is ** OP_Eq or OP_Ne) then take the jump or not depending on whether ** or not both operands are null. */ | > > > > | 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 | case OP_Ne: /* same as TK_NE, jump, in1, in3 */ case OP_Lt: /* same as TK_LT, jump, in1, in3 */ case OP_Le: /* same as TK_LE, jump, in1, in3 */ case OP_Gt: /* same as TK_GT, jump, in1, in3 */ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ int res; /* Result of the comparison of pIn1 against pIn3 */ char affinity; /* Affinity to use for comparison */ u16 flags1; /* Copy of initial value of pIn1->flags */ u16 flags3; /* Copy of initial value of pIn3->flags */ pIn1 = &aMem[pOp->p1]; pIn3 = &aMem[pOp->p3]; flags1 = pIn1->flags; flags3 = pIn3->flags; if( (pIn1->flags | pIn3->flags)&MEM_Null ){ /* One or both operands are NULL */ if( pOp->p5 & SQLITE_NULLEQ ){ /* If SQLITE_NULLEQ is set (which will only happen if the operator is ** OP_Eq or OP_Ne) then take the jump or not depending on whether ** or not both operands are null. */ |
︙ | ︙ | |||
1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 | pOut = &aMem[pOp->p2]; MemSetTypeFlag(pOut, MEM_Int); pOut->u.i = res; REGISTER_TRACE(pOp->p2, pOut); }else if( res ){ pc = pOp->p2-1; } break; } /* Opcode: Permutation * * * P4 * ** ** Set the permutation used by the OP_Compare operator to be the array ** of integers in P4. | > > > > | 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 | pOut = &aMem[pOp->p2]; MemSetTypeFlag(pOut, MEM_Int); pOut->u.i = res; REGISTER_TRACE(pOp->p2, pOut); }else if( res ){ pc = pOp->p2-1; } /* Undo any changes made by applyAffinity() to the input registers. */ pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (flags1&MEM_TypeMask); pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (flags3&MEM_TypeMask); break; } /* Opcode: Permutation * * * P4 * ** ** Set the permutation used by the OP_Compare operator to be the array ** of integers in P4. |
︙ | ︙ |
Changes to test/select7.test.
︙ | ︙ | |||
151 152 153 154 155 156 157 158 159 | } [list 0 $result] append sql { UNION ALL SELECT 99999999} do_test select7-6.2 { catchsql $sql } {1 {too many terms in compound SELECT}} } } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | } [list 0 $result] append sql { UNION ALL SELECT 99999999} do_test select7-6.2 { catchsql $sql } {1 {too many terms in compound SELECT}} } } # This block of tests verifies that bug aa92c76cd4 is fixed. # do_test select7-7.1 { execsql { CREATE TABLE t3(a REAL); INSERT INTO t3 VALUES(44.0); INSERT INTO t3 VALUES(56.0); } } {} do_test select7-7.2 { execsql { pragma vdbe_trace = 0; SELECT (CASE WHEN a=0 THEN 0 ELSE (a + 25) / 50 END) AS categ, count(*) FROM t3 GROUP BY categ } } {1.38 1 1.62 1} do_test select7-7.3 { execsql { CREATE TABLE t4(a REAL); INSERT INTO t4 VALUES( 2.0 ); INSERT INTO t4 VALUES( 3.0 ); } } {} do_test select7-7.4 { execsql { SELECT (CASE WHEN a=0 THEN 'zero' ELSE a/2 END) AS t FROM t4 GROUP BY t; } } {1.0 1.5} do_test select7-7.5 { execsql { SELECT a=0, typeof(a) FROM t4 } } {0 real 0 real} do_test select7-7.6 { execsql { SELECT a=0, typeof(a) FROM t4 GROUP BY a } } {0 real 0 real} do_test select7-7.7 { execsql { CREATE TABLE t5(a TEXT, b INT); INSERT INTO t5 VALUES(123, 456); SELECT typeof(a), a FROM t5 GROUP BY a HAVING a<b; } } {text 123} finish_test |