summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/sqlite/patches/0003-Fix-ASSERT-memIsValid-hit.patch
blob: d6a8184c5e5bdf86353e5d40e6accca46ccfcf0e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
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
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
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, &regFree1));
+        exprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
         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, &regFree1));
-  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, &regFree1));
+    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