diff options
author | drh <drh@noemail.net> | 2016-09-05 12:02:34 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2016-09-05 12:02:34 +0000 |
commit | b29e60c4487b6abc55acd8e0fe1694c590f18412 (patch) | |
tree | d3e367b64969b186e9002445d5f38cf432ba9811 | |
parent | 80aa545337b65289a0db4e73c97d763c357aad53 (diff) | |
download | sqlite-b29e60c4487b6abc55acd8e0fe1694c590f18412.tar.gz sqlite-b29e60c4487b6abc55acd8e0fe1694c590f18412.zip |
Catch vector size mismatch problems during name resolution to avoid later
problems.
FossilOrigin-Name: 56562a0346170cf7b72445976864b058437a8ac3
-rw-r--r-- | manifest | 27 | ||||
-rw-r--r-- | manifest.uuid | 2 | ||||
-rw-r--r-- | src/expr.c | 127 | ||||
-rw-r--r-- | src/resolve.c | 27 | ||||
-rw-r--r-- | src/whereexpr.c | 27 | ||||
-rw-r--r-- | test/rowvalue.test | 27 | ||||
-rw-r--r-- | test/rowvalue4.test | 2 | ||||
-rw-r--r-- | test/subselect.test | 2 |
8 files changed, 145 insertions, 96 deletions
@@ -1,5 +1,5 @@ -C Fix\sa\sproblem\scausing\sthe\saffinity\sof\ssub-select\srow-value\selements\sto\sbe\signored\sin\ssome\scontextes. -D 2016-09-03T19:52:12.432 +C Catch\svector\ssize\smismatch\sproblems\sduring\sname\sresolution\sto\savoid\slater\nproblems. +D 2016-09-05T12:02:34.649 F Makefile.in cfd8fb987cd7a6af046daa87daa146d5aad0e088 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 5017381e4853b1472e01d5bb926be1268eba429c @@ -338,7 +338,7 @@ F src/ctime.c e77f3dc297b4b65c96da78b4ae4272fdfae863d7 F src/date.c 95c9a8d00767e7221a8e9a31f4e913fc8029bf6b F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d F src/delete.c 76c084f0265f4a3cd1ecf17eee112a94f1ccbc05 -F src/expr.c 23b595cc6e2b609d53c72343b3fe16ce8b5e446d +F src/expr.c 942c417e84e835ce51c6b732afa0b4572110e1c1 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c e2be0968c1adc679c87e467aa5b4f167588f38a8 F src/func.c 29cc9acb170ec1387b9f63eb52cd85f8de96c771 @@ -383,7 +383,7 @@ F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c F src/prepare.c 0fcf16eaacc90c1059055519a76b75b516a59a88 F src/printf.c a5f0ca08ddede803c241266abb46356ec748ded1 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 -F src/resolve.c d67b9a5cc33339256e2088c5a722745fc2ff5219 +F src/resolve.c 24f40fd0c3475821d1ad762a3f2c3455cc839b42 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 38216d0b2d42a0f475abf86a84c3499e6421ba29 F src/shell.c 79dda477be6c96eba6e952a934957ad36f87acc7 @@ -468,7 +468,7 @@ F src/walker.c 2d2cc7fb0f320f7f415215d7247f3c584141ac09 F src/where.c 48d705e5196a0611a7be90698eade455ee238536 F src/whereInt.h 14dd243e13b81cbb0a66063d38b70f93a7d6e613 F src/wherecode.c 8a9a53cb52dd8a75e07c85e3bc12c1604c735954 -F src/whereexpr.c 7f9ada866d48d15d09754ae819c1c40efe3b2aff +F src/whereexpr.c c5ec87e234faf62ac2d4e7f7ce18fb1f4bd475ff F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -1020,10 +1020,10 @@ F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81 F test/rowid.test 5b7509f384f4f6fae1af3c8c104c8ca299fea18d -F test/rowvalue.test 7d8482dde9023973615eaaca65647f33d70c1f01 +F test/rowvalue.test 753eb744b7efeb5ac643d35d6e1e5066452ccf79 F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b F test/rowvalue3.test 01399b7bf150b0d41abce76c18072da777c2500c -F test/rowvalue4.test 9b40c9be9bdde30fc66cddbfdf6a5af37de4ccac +F test/rowvalue4.test 9b60544dcd0231a9fcbe1ec095edb16cdaa7ae13 F test/rowvalue5.test a440d490c8c0bf606034c09d5c6bbf7840b98f95 F test/rowvalue6.test d19b54feb604d5601f8614b15e214e0774c01087 F test/rowvalue7.test 5d06ff19d9e6969e574a2e662a531dd0c67801a8 @@ -1121,7 +1121,7 @@ F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1 F test/stmt.test 64844332db69cf1a735fcb3e11548557fc95392f F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f F test/subquery2.test 438f8a7da1457277b22e4176510f7659b286995f -F test/subselect.test ccec43f85d488c6c4b6f98ea2dfa95b6086871c0 +F test/subselect.test 0966aa8e720224dbd6a5e769a3ec2a723e332303 F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8 F test/superlock.test ec94f0556b6488d97f71c79f9061ae08d9ab8f12 @@ -1522,7 +1522,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P ed206048484667e4fe6aaeadd65882537d74bd35 -R ebdd3ea482059f46220cc36bb6b2e41e -U dan -Z 13aac770e03afb07d71bee955ff12a59 +P 7d9bd22c0715ede2592ee1fa7ebc215aded1ca1b +R 9a7c982f4a8ba0874174ff495f80018e +T *branch * early-vector-size-check +T *sym-early-vector-size-check * +T -sym-rowvalue * +U drh +Z 17a06585da7241edb65fdad418303946 diff --git a/manifest.uuid b/manifest.uuid index 7dd209be1..474117a10 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7d9bd22c0715ede2592ee1fa7ebc215aded1ca1b
\ No newline at end of file +56562a0346170cf7b72445976864b058437a8ac3
\ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 76f0d4908..f604ae4fe 100644 --- a/src/expr.c +++ b/src/expr.c @@ -522,75 +522,68 @@ static void codeVectorCompare( Expr *pLeft = pExpr->pLeft; Expr *pRight = pExpr->pRight; int nLeft = sqlite3ExprVectorSize(pLeft); - int nRight = sqlite3ExprVectorSize(pRight); - - /* Check that both sides of the comparison are vectors, and that - ** both are the same length. */ - if( nLeft!=nRight ){ - sqlite3ErrorMsg(pParse, "row value misused"); - }else{ - int i; - int regLeft = 0; - int regRight = 0; - u8 opx = op; - int addrDone = sqlite3VdbeMakeLabel(v); - - assert( pExpr->op==TK_EQ || pExpr->op==TK_NE - || pExpr->op==TK_IS || pExpr->op==TK_ISNOT - || pExpr->op==TK_LT || pExpr->op==TK_GT - || pExpr->op==TK_LE || pExpr->op==TK_GE - ); - assert( pExpr->op==op || (pExpr->op==TK_IS && op==TK_EQ) - || (pExpr->op==TK_ISNOT && op==TK_NE) ); - assert( p5==0 || pExpr->op!=op ); - assert( p5==SQLITE_NULLEQ || pExpr->op==op ); - - p5 |= SQLITE_STOREP2; - if( opx==TK_LE ) opx = TK_LT; - if( opx==TK_GE ) opx = TK_GT; - - regLeft = exprCodeSubselect(pParse, pLeft); - regRight = exprCodeSubselect(pParse, pRight); - - for(i=0; 1 /*Loop exits by "break"*/; i++){ - int regFree1 = 0, regFree2 = 0; - Expr *pL, *pR; - int r1, r2; - assert( i>=0 && i<nLeft ); - if( i>0 ) sqlite3ExprCachePush(pParse); - r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, ®Free1); - r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, ®Free2); - codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5); - testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); - testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); - testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); - testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); - testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); - testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); - sqlite3ReleaseTempReg(pParse, regFree1); - sqlite3ReleaseTempReg(pParse, regFree2); - if( i>0 ) sqlite3ExprCachePop(pParse); - if( i==nLeft-1 ){ - break; - } - if( opx==TK_EQ ){ - sqlite3VdbeAddOp2(v, OP_IfNot, dest, addrDone); VdbeCoverage(v); - p5 |= SQLITE_KEEPNULL; - }else if( opx==TK_NE ){ - sqlite3VdbeAddOp2(v, OP_If, dest, addrDone); VdbeCoverage(v); - p5 |= SQLITE_KEEPNULL; - }else{ - assert( op==TK_LT || op==TK_GT || op==TK_LE || op==TK_GE ); - sqlite3VdbeAddOp2(v, OP_ElseNotEq, 0, addrDone); - VdbeCoverageIf(v, op==TK_LT); - VdbeCoverageIf(v, op==TK_GT); - VdbeCoverageIf(v, op==TK_LE); - VdbeCoverageIf(v, op==TK_GE); - if( i==nLeft-2 ) opx = op; - } + int i; + int regLeft = 0; + int regRight = 0; + u8 opx = op; + int addrDone = sqlite3VdbeMakeLabel(v); + + assert( nLeft==sqlite3ExprVectorSize(pRight) ); + assert( pExpr->op==TK_EQ || pExpr->op==TK_NE + || pExpr->op==TK_IS || pExpr->op==TK_ISNOT + || pExpr->op==TK_LT || pExpr->op==TK_GT + || pExpr->op==TK_LE || pExpr->op==TK_GE + ); + assert( pExpr->op==op || (pExpr->op==TK_IS && op==TK_EQ) + || (pExpr->op==TK_ISNOT && op==TK_NE) ); + assert( p5==0 || pExpr->op!=op ); + assert( p5==SQLITE_NULLEQ || pExpr->op==op ); + + p5 |= SQLITE_STOREP2; + if( opx==TK_LE ) opx = TK_LT; + if( opx==TK_GE ) opx = TK_GT; + + regLeft = exprCodeSubselect(pParse, pLeft); + regRight = exprCodeSubselect(pParse, pRight); + + for(i=0; 1 /*Loop exits by "break"*/; i++){ + int regFree1 = 0, regFree2 = 0; + Expr *pL, *pR; + int r1, r2; + assert( i>=0 && i<nLeft ); + if( i>0 ) sqlite3ExprCachePush(pParse); + r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, ®Free1); + r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, ®Free2); + codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5); + testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); + testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); + testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); + testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); + testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); + testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); + sqlite3ReleaseTempReg(pParse, regFree1); + sqlite3ReleaseTempReg(pParse, regFree2); + if( i>0 ) sqlite3ExprCachePop(pParse); + if( i==nLeft-1 ){ + break; + } + if( opx==TK_EQ ){ + sqlite3VdbeAddOp2(v, OP_IfNot, dest, addrDone); VdbeCoverage(v); + p5 |= SQLITE_KEEPNULL; + }else if( opx==TK_NE ){ + sqlite3VdbeAddOp2(v, OP_If, dest, addrDone); VdbeCoverage(v); + p5 |= SQLITE_KEEPNULL; + }else{ + assert( op==TK_LT || op==TK_GT || op==TK_LE || op==TK_GE ); + sqlite3VdbeAddOp2(v, OP_ElseNotEq, 0, addrDone); + VdbeCoverageIf(v, op==TK_LT); + VdbeCoverageIf(v, op==TK_GT); + VdbeCoverageIf(v, op==TK_LE); + VdbeCoverageIf(v, op==TK_GE); + if( i==nLeft-2 ) opx = op; } - sqlite3VdbeResolveLabel(v, addrDone); } + sqlite3VdbeResolveLabel(v, addrDone); } #if SQLITE_MAX_EXPR_DEPTH>0 diff --git a/src/resolve.c b/src/resolve.c index 206015fcf..a5cc06b91 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -776,6 +776,33 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ notValid(pParse, pNC, "parameters", NC_IsCheck|NC_PartIdx|NC_IdxExpr); break; } + case TK_EQ: + case TK_NE: + case TK_LT: + case TK_LE: + case TK_GT: + case TK_GE: + case TK_IS: + case TK_ISNOT: { + int nLeft, nRight; + if( pParse->db->mallocFailed ) break; + assert( pExpr->pRight!=0 ); + assert( pExpr->pLeft!=0 ); + nLeft = sqlite3ExprVectorSize(pExpr->pLeft); + nRight = sqlite3ExprVectorSize(pExpr->pRight); + if( nLeft!=nRight ){ + testcase( pExpr->op==TK_EQ ); + testcase( pExpr->op==TK_NE ); + testcase( pExpr->op==TK_LT ); + testcase( pExpr->op==TK_LE ); + testcase( pExpr->op==TK_GT ); + testcase( pExpr->op==TK_GE ); + testcase( pExpr->op==TK_IS ); + testcase( pExpr->op==TK_ISNOT ); + sqlite3ErrorMsg(pParse, "row value misused"); + } + break; + } } return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue; } diff --git a/src/whereexpr.c b/src/whereexpr.c index 00328989e..92aed29bb 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -1188,22 +1188,21 @@ static void exprAnalyze( || (pExpr->pRight->flags & EP_xIsSelect)==0 )){ int nLeft = sqlite3ExprVectorSize(pExpr->pLeft); - if( nLeft==sqlite3ExprVectorSize(pExpr->pRight) ){ - int i; - for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){ - int idxNew; - Expr *pNew; - Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i); - Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i); + int i; + assert( nLeft==sqlite3ExprVectorSize(pExpr->pRight) ); + for(i=0; i<nLeft; i++){ + int idxNew; + Expr *pNew; + Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i); + Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i); - pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight, 0); - idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC); - exprAnalyze(pSrc, pWC, idxNew); - } - pTerm = &pWC->a[idxTerm]; - pTerm->wtFlags = TERM_CODED|TERM_VIRTUAL; /* Disable the original */ - pTerm->eOperator = 0; + pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight, 0); + idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC); + exprAnalyze(pSrc, pWC, idxNew); } + pTerm = &pWC->a[idxTerm]; + pTerm->wtFlags = TERM_CODED|TERM_VIRTUAL; /* Disable the original */ + pTerm->eOperator = 0; } /* If there is a vector IN term - e.g. "(a, b) IN (SELECT ...)" - create diff --git a/test/rowvalue.test b/test/rowvalue.test index f716c26c8..f53d5328c 100644 --- a/test/rowvalue.test +++ b/test/rowvalue.test @@ -229,4 +229,31 @@ do_execsql_test 10.0 { AND (a,b,e) IN (SELECT 'a','b','d' FROM dual); } +do_catchsql_test 11.1 { + CREATE TABLE t11(a); + SELECT * FROM t11 WHERE (a,a)<=1; +} {1 {row value misused}} +do_catchsql_test 11.2 { + SELECT * FROM t11 WHERE (a,a)<1; +} {1 {row value misused}} +do_catchsql_test 11.3 { + SELECT * FROM t11 WHERE (a,a)>=1; +} {1 {row value misused}} +do_catchsql_test 11.4 { + SELECT * FROM t11 WHERE (a,a)>1; +} {1 {row value misused}} +do_catchsql_test 11.5 { + SELECT * FROM t11 WHERE (a,a)==1; +} {1 {row value misused}} +do_catchsql_test 11.6 { + SELECT * FROM t11 WHERE (a,a)<>1; +} {1 {row value misused}} +do_catchsql_test 11.7 { + SELECT * FROM t11 WHERE (a,a) IS 1; +} {1 {row value misused}} +do_catchsql_test 11.8 { + SELECT * FROM t11 WHERE (a,a) IS NOT 1; +} {1 {row value misused}} + + finish_test diff --git a/test/rowvalue4.test b/test/rowvalue4.test index a30edcc26..d3d5e46c7 100644 --- a/test/rowvalue4.test +++ b/test/rowvalue4.test @@ -306,6 +306,6 @@ do_catchsql_test 8.2 { SELECT * FROM c2 CROSS JOIN c3 WHERE ( (a, b) == (SELECT x, y FROM c1) AND c3.d = c ) OR ( c == (SELECT x, y FROM c1) AND c3.d = c ) -} {1 {sub-select returns 2 columns - expected 1}} +} {1 {row value misused}} finish_test diff --git a/test/subselect.test b/test/subselect.test index fc1c10308..4d0efde47 100644 --- a/test/subselect.test +++ b/test/subselect.test @@ -40,7 +40,7 @@ do_test subselect-1.1 { do_test subselect-1.2 { set v [catch {execsql {SELECT * FROM t1 WHERE a = (SELECT * FROM t1)}} msg] lappend v $msg -} {1 {sub-select returns 2 columns - expected 1}} +} {1 {row value misused}} # A subselect without an aggregate. # |