/ Check-in [42670935]
Login

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

Overview
Comment:Fix a crash that could occur under certain circumstances if the vectors on either side of a comparison operator were of a different size.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | rowvalue
Files: files | file ages | folders
SHA1: 42670935aba152ba774c2a8bdcbe72b943309d68
User & Date: dan 2016-09-05 09:44:45
Context
2016-09-05
12:12
Do vector comparison size checking early - at name resolution time - to forestall future problems. check-in: ae127bcc user: drh tags: rowvalue
09:44
Fix a crash that could occur under certain circumstances if the vectors on either side of a comparison operator were of a different size. check-in: 42670935 user: dan tags: rowvalue
2016-09-03
19:52
Fix a problem causing the affinity of sub-select row-value elements to be ignored in some contextes. check-in: 7d9bd22c user: dan tags: rowvalue
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/expr.c.

517
518
519
520
521
522
523
524
525
526
527
528
529
530
531


532
533
534
535
536
537
538
....
2651
2652
2653
2654
2655
2656
2657























2658
2659
2660
2661
2662
2663
2664
  int dest,             /* Write results into this register */
  u8 op,                /* Comparison operator */
  u8 p5                 /* SQLITE_NULLEQ or zero */
){
  Vdbe *v = pParse->pVdbe;
  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 
................................................................................
      sqlite3ErrorMsg(pParse, "row value misused");
    }
    return 1;
  }
  return 0;
}
#endif
























#ifndef SQLITE_OMIT_SUBQUERY
/*
** Generate code for an IN expression.
**
**      x IN (SELECT ...)
**      x IN (value, value, ...)







<
<

<
<
<
<
<
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







517
518
519
520
521
522
523


524





525
526
527
528
529
530
531
532
533
....
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
  int dest,             /* Write results into this register */
  u8 op,                /* Comparison operator */
  u8 p5                 /* SQLITE_NULLEQ or zero */
){
  Vdbe *v = pParse->pVdbe;
  Expr *pLeft = pExpr->pLeft;
  Expr *pRight = pExpr->pRight;








  if( sqlite3ExprCheckComparison(pParse, pLeft, pRight)==0 ){
    int nLeft = sqlite3ExprVectorSize(pLeft);
    int i;
    int regLeft = 0;
    int regRight = 0;
    u8 opx = op;
    int addrDone = sqlite3VdbeMakeLabel(v);

    assert( pExpr->op==TK_EQ || pExpr->op==TK_NE 
................................................................................
      sqlite3ErrorMsg(pParse, "row value misused");
    }
    return 1;
  }
  return 0;
}
#endif

/*
** Expressions pLeft and pRight are the left and right sides of a comparison
** operator. If either pLeft or pRight is a vector and the other is not, or
** if they are both vectors but of a different size, leave an error message
** in the Parse object and return non-zero. Or, if there is no problem, 
** return 0.
*/
int sqlite3ExprCheckComparison(Parse *pParse, Expr *pLeft, Expr *pRight){
  int nLeft = sqlite3ExprVectorSize(pLeft);
  int nRight = sqlite3ExprVectorSize(pRight);
  if( nLeft!=nRight ){
    if( (pRight->flags & EP_xIsSelect) ){
      sqlite3SubselectError(pParse, nRight, nLeft);
    }else if( pLeft->flags & EP_xIsSelect ){
      sqlite3SubselectError(pParse, nLeft, nRight);
    }else{
      sqlite3ErrorMsg(pParse, "row value misused");
    }
    return 1;
  }
  return 0;
}

#ifndef SQLITE_OMIT_SUBQUERY
/*
** Generate code for an IN expression.
**
**      x IN (SELECT ...)
**      x IN (value, value, ...)

Changes to src/sqliteInt.h.

4005
4006
4007
4008
4009
4010
4011

4012
4013
4014
4015
4016
4017
4018
void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *);

#ifndef SQLITE_OMIT_SUBQUERY
int sqlite3ExprCheckIN(Parse*, Expr*);
#else
# define sqlite3ExprCheckIN(x,y) SQLITE_OK
#endif


#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
void sqlite3AnalyzeFunctions(void);
int sqlite3Stat4ProbeSetValue(
    Parse*,Index*,UnpackedRecord**,Expr*,int,int,int*);
int sqlite3Stat4ValueFromExpr(Parse*, Expr*, u8, sqlite3_value**);
void sqlite3Stat4ProbeFree(UnpackedRecord*);







>







4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *);

#ifndef SQLITE_OMIT_SUBQUERY
int sqlite3ExprCheckIN(Parse*, Expr*);
#else
# define sqlite3ExprCheckIN(x,y) SQLITE_OK
#endif
int sqlite3ExprCheckComparison(Parse*, Expr*, Expr*);

#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
void sqlite3AnalyzeFunctions(void);
int sqlite3Stat4ProbeSetValue(
    Parse*,Index*,UnpackedRecord**,Expr*,int,int,int*);
int sqlite3Stat4ValueFromExpr(Parse*, Expr*, u8, sqlite3_value**);
void sqlite3Stat4ProbeFree(UnpackedRecord*);

Changes to src/whereexpr.c.

947
948
949
950
951
952
953




954
955
956
957
958
959
960
  pTerm->iParent = -1;
  pTerm->eOperator = 0;
  if( allowedOp(op) ){
    int iCur, iColumn;
    Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
    Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
    u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;





    if( pTerm->iField>0 ){
      assert( op==TK_IN );
      assert( pLeft->op==TK_VECTOR );
      pLeft = pLeft->x.pList->a[pTerm->iField-1].pExpr;
    }








>
>
>
>







947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
  pTerm->iParent = -1;
  pTerm->eOperator = 0;
  if( allowedOp(op) ){
    int iCur, iColumn;
    Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
    Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
    u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;

    if( pRight && sqlite3ExprCheckComparison(pParse, pLeft, pRight) ){
      return;
    }

    if( pTerm->iField>0 ){
      assert( op==TK_IN );
      assert( pLeft->op==TK_VECTOR );
      pLeft = pLeft->x.pList->a[pTerm->iField-1].pExpr;
    }

Changes to test/rowvalue4.test.

43
44
45
46
47
48
49


50
51
52
53
54
55
56
  3 "SELECT * FROM t1 WHERE NOT (b = (1, 2))" {row value misused}
  4 "SELECT * FROM t1 LIMIT (1, 2)"           {row value misused}
  5 "SELECT (a, b) IN (SELECT * FROM t1) FROM t1" 
                             {sub-select returns 3 columns - expected 2}

  6 "SELECT * FROM t1 WHERE (a, b) IN (SELECT * FROM t1)" 
                             {sub-select returns 3 columns - expected 2}


} {
  do_catchsql_test 2.$tn "$s" [list 1 $error]
}

#-------------------------------------------------------------------------
do_execsql_test 2.0 {
  CREATE TABLE t2(a, b, c, d);







>
>







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  3 "SELECT * FROM t1 WHERE NOT (b = (1, 2))" {row value misused}
  4 "SELECT * FROM t1 LIMIT (1, 2)"           {row value misused}
  5 "SELECT (a, b) IN (SELECT * FROM t1) FROM t1" 
                             {sub-select returns 3 columns - expected 2}

  6 "SELECT * FROM t1 WHERE (a, b) IN (SELECT * FROM t1)" 
                             {sub-select returns 3 columns - expected 2}
  7 "SELECT * FROM t1 WHERE (c, c) <= 1" {row value misused}
  8 "SELECT * FROM t1 WHERE (b, b) <= 1" {row value misused}
} {
  do_catchsql_test 2.$tn "$s" [list 1 $error]
}

#-------------------------------------------------------------------------
do_execsql_test 2.0 {
  CREATE TABLE t2(a, b, c, d);