| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| From: Darwin Huang <huangdarwin@chromium.org> |
| Date: Wed, 17 Jul 2019 15:22:41 -0700 |
| Subject: [PATCH 3/6] Fix ASSERT memIsValid hit |
| |
| Backports https://www.sqlite.org/src/info/7ef7b23cbb1b9ace |
| |
| Bug: 984699 |
| --- |
| third_party/sqlite/patched/src/expr.c | 75 ++++++++++--------- |
| third_party/sqlite/patched/test/check.test | 29 +++++++ |
| .../sqlite/patched/test/checkfault.test | 41 ++++++++++ |
| 3 files changed, 108 insertions(+), 37 deletions(-) |
| create mode 100644 third_party/sqlite/patched/test/checkfault.test |
| |
| diff --git a/third_party/sqlite/patched/src/expr.c b/third_party/sqlite/patched/src/expr.c |
| index e958c88a6523..88e5baec85ef 100644 |
| --- a/third_party/sqlite/patched/src/expr.c |
| +++ b/third_party/sqlite/patched/src/expr.c |
| @@ -1083,16 +1083,6 @@ static int exprStructSize(Expr *p){ |
| return EXPR_FULLSIZE; |
| } |
| |
| -/* |
| -** Copy the complete content of an Expr node, taking care not to read |
| -** past the end of the structure for a reduced-size version of the source |
| -** Expr. |
| -*/ |
| -static void exprNodeCopy(Expr *pDest, Expr *pSrc){ |
| - memset(pDest, 0, sizeof(Expr)); |
| - memcpy(pDest, pSrc, exprStructSize(pSrc)); |
| -} |
| - |
| /* |
| ** The dupedExpr*Size() routines each return the number of bytes required |
| ** to store a copy of an expression or expression tree. They differ in |
| @@ -4044,6 +4034,8 @@ expr_code_doover: |
| Expr opCompare; /* The X==Ei expression */ |
| Expr *pX; /* The X expression */ |
| Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */ |
| + Expr *pDel = 0; |
| + sqlite3 *db = pParse->db; |
| |
| assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList ); |
| assert(pExpr->x.pList->nExpr > 0); |
| @@ -4052,13 +4044,17 @@ expr_code_doover: |
| nExpr = pEList->nExpr; |
| endLabel = sqlite3VdbeMakeLabel(pParse); |
| if( (pX = pExpr->pLeft)!=0 ){ |
| - exprNodeCopy(&tempX, pX); |
| + pDel = sqlite3ExprDup(db, pX, 0); |
| + if( db->mallocFailed ){ |
| + sqlite3ExprDelete(db, pDel); |
| + break; |
| + } |
| testcase( pX->op==TK_COLUMN ); |
| - exprToRegister(&tempX, exprCodeVector(pParse, &tempX, ®Free1)); |
| + exprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1)); |
| testcase( regFree1==0 ); |
| memset(&opCompare, 0, sizeof(opCompare)); |
| opCompare.op = TK_EQ; |
| - opCompare.pLeft = &tempX; |
| + opCompare.pLeft = pDel; |
| pTest = &opCompare; |
| /* Ticket b351d95f9cd5ef17e9d9dbae18f5ca8611190001: |
| ** The value in regFree1 might get SCopy-ed into the file result. |
| @@ -4086,6 +4082,7 @@ expr_code_doover: |
| }else{ |
| sqlite3VdbeAddOp2(v, OP_Null, 0, target); |
| } |
| + sqlite3ExprDelete(db, pDel); |
| sqlite3VdbeResolveLabel(v, endLabel); |
| break; |
| } |
| @@ -4367,40 +4364,44 @@ static void exprCodeBetween( |
| void (*xJump)(Parse*,Expr*,int,int), /* Action to take */ |
| int jumpIfNull /* Take the jump if the BETWEEN is NULL */ |
| ){ |
| - Expr exprAnd; /* The AND operator in x>=y AND x<=z */ |
| + Expr exprAnd; /* The AND operator in x>=y AND x<=z */ |
| Expr compLeft; /* The x>=y term */ |
| Expr compRight; /* The x<=z term */ |
| - Expr exprX; /* The x subexpression */ |
| int regFree1 = 0; /* Temporary use register */ |
| + Expr *pDel = 0; |
| + sqlite3 *db = pParse->db; |
| |
| memset(&compLeft, 0, sizeof(Expr)); |
| memset(&compRight, 0, sizeof(Expr)); |
| memset(&exprAnd, 0, sizeof(Expr)); |
| |
| assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); |
| - exprNodeCopy(&exprX, pExpr->pLeft); |
| - exprAnd.op = TK_AND; |
| - exprAnd.pLeft = &compLeft; |
| - exprAnd.pRight = &compRight; |
| - compLeft.op = TK_GE; |
| - compLeft.pLeft = &exprX; |
| - compLeft.pRight = pExpr->x.pList->a[0].pExpr; |
| - compRight.op = TK_LE; |
| - compRight.pLeft = &exprX; |
| - compRight.pRight = pExpr->x.pList->a[1].pExpr; |
| - exprToRegister(&exprX, exprCodeVector(pParse, &exprX, ®Free1)); |
| - if( xJump ){ |
| - xJump(pParse, &exprAnd, dest, jumpIfNull); |
| - }else{ |
| - /* Mark the expression is being from the ON or USING clause of a join |
| - ** so that the sqlite3ExprCodeTarget() routine will not attempt to move |
| - ** it into the Parse.pConstExpr list. We should use a new bit for this, |
| - ** for clarity, but we are out of bits in the Expr.flags field so we |
| - ** have to reuse the EP_FromJoin bit. Bummer. */ |
| - exprX.flags |= EP_FromJoin; |
| - sqlite3ExprCodeTarget(pParse, &exprAnd, dest); |
| + pDel = sqlite3ExprDup(db, pExpr->pLeft, 0); |
| + if( db->mallocFailed==0 ){ |
| + exprAnd.op = TK_AND; |
| + exprAnd.pLeft = &compLeft; |
| + exprAnd.pRight = &compRight; |
| + compLeft.op = TK_GE; |
| + compLeft.pLeft = pDel; |
| + compLeft.pRight = pExpr->x.pList->a[0].pExpr; |
| + compRight.op = TK_LE; |
| + compRight.pLeft = pDel; |
| + compRight.pRight = pExpr->x.pList->a[1].pExpr; |
| + exprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1)); |
| + if( xJump ){ |
| + xJump(pParse, &exprAnd, dest, jumpIfNull); |
| + }else{ |
| + /* Mark the expression is being from the ON or USING clause of a join |
| + ** so that the sqlite3ExprCodeTarget() routine will not attempt to move |
| + ** it into the Parse.pConstExpr list. We should use a new bit for this, |
| + ** for clarity, but we are out of bits in the Expr.flags field so we |
| + ** have to reuse the EP_FromJoin bit. Bummer. */ |
| + pDel->flags |= EP_FromJoin; |
| + sqlite3ExprCodeTarget(pParse, &exprAnd, dest); |
| + } |
| + sqlite3ReleaseTempReg(pParse, regFree1); |
| } |
| - sqlite3ReleaseTempReg(pParse, regFree1); |
| + sqlite3ExprDelete(db, pDel); |
| |
| /* Ensure adequate test coverage */ |
| testcase( xJump==sqlite3ExprIfTrue && jumpIfNull==0 && regFree1==0 ); |
| diff --git a/third_party/sqlite/patched/test/check.test b/third_party/sqlite/patched/test/check.test |
| index 4042b6d96ed8..a0ab615fa76e 100644 |
| --- a/third_party/sqlite/patched/test/check.test |
| +++ b/third_party/sqlite/patched/test/check.test |
| @@ -495,4 +495,33 @@ do_execsql_test 10.1 { |
| PRAGMA integrity_check; |
| } {ok} |
| |
| +#------------------------------------------------------------------------- |
| +reset_db |
| +do_execsql_test 11.0 { |
| + CREATE TABLE t1 (Col0 CHECK(1 COLLATE BINARY BETWEEN 1 AND 1) ) ; |
| +} |
| +do_execsql_test 11.1 { |
| + INSERT INTO t1 VALUES (NULL); |
| +} |
| +do_execsql_test 11.2 { |
| + INSERT INTO t1 VALUES (NULL); |
| +} |
| + |
| +do_execsql_test 11.3 { |
| + CREATE TABLE t2(b, a CHECK( |
| + CASE 'abc' COLLATE nocase WHEN a THEN 1 ELSE 0 END) |
| + ); |
| +} |
| +do_execsql_test 11.4 { |
| + INSERT INTO t2(a) VALUES('abc'); |
| +} |
| +do_execsql_test 11.5 { |
| + INSERT INTO t2(b, a) VALUES(1, 'abc'||''); |
| +} |
| +do_execsql_test 11.6 { |
| + INSERT INTO t2(b, a) VALUES(2, 'abc'); |
| +} |
| + |
| +finish_test |
| + |
| finish_test |
| diff --git a/third_party/sqlite/patched/test/checkfault.test b/third_party/sqlite/patched/test/checkfault.test |
| new file mode 100644 |
| index 000000000000..126e68751b28 |
| --- /dev/null |
| +++ b/third_party/sqlite/patched/test/checkfault.test |
| @@ -0,0 +1,41 @@ |
| +# 2019 July 17 |
| +# |
| +# The author disclaims copyright to this source code. In place of |
| +# a legal notice, here is a blessing: |
| +# |
| +# May you do good and not evil. |
| +# May you find forgiveness for yourself and forgive others. |
| +# May you share freely, never taking more than you give. |
| +# |
| +#*********************************************************************** |
| +# |
| +# This file contains fault-injection test cases for the |
| +# sqlite3_db_cacheflush API. |
| +# |
| + |
| +set testdir [file dirname $argv0] |
| +source $testdir/tester.tcl |
| +set testprefix cffault |
| +source $testdir/malloc_common.tcl |
| + |
| +do_execsql_test 1.0 { |
| + CREATE TABLE t1 (Col0 CHECK(1 COLLATE BINARY BETWEEN 1 AND 1) ) ; |
| + CREATE TABLE t2(b, a CHECK( |
| + CASE 'abc' COLLATE nocase WHEN a THEN 1 ELSE 0 END) |
| + ); |
| +} |
| + |
| +do_faultsim_test 1.1 -faults oom* -body { |
| + execsql { INSERT INTO t1 VALUES ('ABCDEFG') } |
| +} -test { |
| + faultsim_test_result {0 {}} |
| +} |
| + |
| +do_faultsim_test 1.2 -faults oom* -body { |
| + execsql { INSERT INTO t2(a) VALUES('abc') } |
| +} -test { |
| + faultsim_test_result {0 {}} |
| +} |
| + |
| + |
| +finish_test |
| \ No newline at end of file |
| -- |
| 2.23.0.351.gc4317032e6-goog |
| |