CVE-2019-19646: Improper Check for Unusual or Exceptional Conditions (CWE-754)
value: pragma.c in SQLite through 3.30.1 mishandles NOT NULL in an integrity_check PRAGMA command in certain cases of generated columns.
CWE description: The product does not check or incorrectly checks for unusual or exceptional conditions that are not expected to occur frequently during day to day operation of the product.
CVSS v3 base score: 9.8
Published: 2019-12-09T19:15Z
Repository: https://github.com/sqlite/sqlite
Language: Other
Files changed: manifest, manifest.uuid, src/pragma.c, test/gencol1.test
Commit date: 2019-12-09 15:52:07 +0000
Commit message: Fix the NOT NULL verification logic in PRAGMA integrity_check so that it
works for generated columns whose value is the result of a comparison operator.
Ticket [bd8c280671ba44a7]

FossilOrigin-Name: f3b39c71b88cb6721f443de56cdce4c08252453a5e340b00a2bd88dc10c42400
Diff: diff --git a/manifest b/manifest
index 6bd9a3ad38..a5efb52608 100644
--- a/manifest
+++ b/manifest
@@ -1,7 +1,7 @@
-C Fix\sa\sgramfuzz\sfind.\s\sIf\sa\spartial\sindex\sthat\sdoes\snot\sreference\sany\scolumn\nof\sits\stable\sis\sused\sby\san\sUPDATE\sstatement\sin\sone-pass\smode,\sthen\savoid\sthe\nuse\sof\sOP_DeferredSeek\ssince\sthe\sseek\smight\snot\sbe\sresolved\sprior\sto\sthe\nOP_Delete\sand\sOP_Insert\sthat\simplement\sthe\sUPDATE.
-D 2019-12-09T14:34:37.171
+C Fix\sthe\sNOT\sNULL\sverification\slogic\sin\sPRAGMA\sintegrity_check\sso\sthat\sit\nworks\sfor\sgenerated\scolumns\swhose\svalue\sis\sthe\sresult\sof\sa\scomparison\soperator.\nTicket\s[bd8c280671ba44a7]
+D 2019-12-09T15:52:07.194
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
 F Makefile.in d3a862c9742f5a08230a3b295c0a47fd3067f19356dc39935280135f90474b04
 F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
@@ -518,11 +518,11 @@ F src/pager.c 30f20d2263d3717f41a0d9a40f7a3d0f48ce1cfab461b875c6187ead9d6ad1c7
 F src/pager.h 217921e81eb5fe455caa5cda96061959706bcdd29ddb57166198645ef7822ac3
 F src/parse.y 17c1ae265e1b92cb1f3f1661b020e3eb31f2d8b9588322d2b6f2b22f25b674c9
 F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177
 F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
 F src/pcache1.c 62714cbd1b7299a6e6a27a587b66b4fd3a836a84e1181e7f96f5c34a50917848
-F src/pragma.c 36c367a62a9d3415fd3d15523e794cccc2cb74e6d806662b0185b8c686f06acb
+F src/pragma.c 26e9ee514138b9697d4be6d8f9ca84655053026390cf10de838862238aa4aba9
 F src/pragma.h ec3b31eac9b1df040f1cc8cb3d89bc06605c3b4cb3d76f833de8d6d6c3f77f04
 F src/prepare.c 6049beb71385f017af6fc320d2c75a4e50b75e280c54232442b785fbb83df057
 F src/printf.c 9be6945837c839ba57837b4bc3af349eba630920fa5532aa518816defe42a7d4
 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
 F src/resolve.c 618bf4f57fa0617cd5295117fea5f25955b76d278303405a8551c4204593011e
@@ -1020,11 +1020,11 @@ F test/fuzzdata7.db e7a86fd83dda151d160445d542e32e5c6019c541b3a74c2a525b6ac64063
 F test/fuzzdata8.db b45368bbe9f86d40d30603e8f780ac29807cbcc951a18d7a7fd9d0c0e904706e
 F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
 F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
 F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
 F test/gcfault.test dd28c228a38976d6336a3fc42d7e5f1ad060cb8c
-F test/gencol1.test 037c5c26dddd984ba7ea11bd16996377f72523a4126804b1bbecafc833fccb47
+F test/gencol1.test 96d669ccb82d4140df6b38bfc110b98f94ac4cf8d32af42bae6349941b3eb92c
 F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
 F test/having.test e4098a4b8962f9596035c3b87a8928a10648acc509f1bb8d6f96413bbf79a1b3
 F test/hexlit.test 4a6a5f46e3c65c4bf1fa06f5dd5a9507a5627751
 F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
 F test/hook.test 1604b3b2f5931430087540404555c1b6be3618600b81558657c66b533ed70b13
@@ -1850,9 +1850,9 @@ F vsixtest/pch.h 9cab7980f2ac4baa40807d8b5e52af32a21cf78c
 F vsixtest/vsixtest.sln 77cadbe4e96c1fe1bf51cd77de9e9b0a12ada547
 F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 1d2e53a39b87e364685e21de137655b6eee725e4c6d27fc90865072d7c5892b5
-R 73f9d074ffb019cac59a96d55cf2c0bc
+P e3398c5ffb060b2b26334b8598e2c63953741e2d6f5124dbd6bdfc8e94742539
+R 214fd6f511022e08e69f40b8ca4a69e8
 U drh
-Z 9b8f81a17115c4850191512c3ac99432
+Z 7b3cdd64628ae3e72f321ced6b81d514
diff --git a/manifest.uuid b/manifest.uuid
index 146af5fbe7..fdfe085d85 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-e3398c5ffb060b2b26334b8598e2c63953741e2d6f5124dbd6bdfc8e94742539
\ No newline at end of file
+f3b39c71b88cb6721f443de56cdce4c08252453a5e340b00a2bd88dc10c42400
\ No newline at end of file
diff --git a/src/pragma.c b/src/pragma.c
index 8878e7353e..9b83807c61 100644
--- a/src/pragma.c
+++ b/src/pragma.c
@@ -1594,11 +1594,13 @@ void sqlite3Pragma(
           char *zErr;
           int jmp2;
           if( j==pTab->iPKey ) continue;
           if( pTab->aCol[j].notNull==0 ) continue;
           sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
-          sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
+          if( sqlite3VdbeGetOp(v,-1)->opcode==OP_Column ){
+            sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
+          }
           jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
           zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
                               pTab->aCol[j].zName);
           sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
           integrityCheckResultRow(v);
diff --git a/test/gencol1.test b/test/gencol1.test
index 75016d590a..80769222a9 100644
--- a/test/gencol1.test
+++ b/test/gencol1.test
@@ -326,6 +326,20 @@ do_execsql_test gencol1-11.70 {
 }
 do_catchsql_test gencol1-11.80 {
   INSERT OR REPLACE INTO t0(c0, c1) VALUES (2, 1), (1, 0)
 } {1 {FOREIGN KEY constraint failed}}
 
+# 2019-12-09 ticket bd8c280671ba44a7
+# With generated columns, the sqlite3ExprGetColumnOfTable() routine might
+# generate a code sequence that does not end with OP_Column.  So check to
+# make sure that the last instruction generated is an OP_column prior to
+# applying the OPFLAG_TYPEOFARG optimization to NOT NULL checks in the
+# PRAGMA integrity_check code.
+#
+sqlite3 db :memory:
+do_execsql_test gencol1-12.10 {
+  CREATE TABLE t0 (c0, c1 NOT NULL AS (c0==0));
+  INSERT INTO t0(c0) VALUES (0);
+  PRAGMA integrity_check;
+} {ok}
+
 finish_test

Vulnerable code: C Fix\sa\sgramfuzz\sfind.\s\sIf\sa\spartial\sindex\sthat\sdoes\snot\sreference\sany\scolumn\nof\sits\stable\sis\sused\sby\san\sUPDATE\sstatement\sin\sone-pass\smode,\sthen\savoid\sthe\nuse\sof\sOP_DeferredSeek\ssince\sthe\sseek\smight\snot\sbe\sresolved\sprior\sto\sthe\nOP_Delete\sand\sOP_Insert\sthat\simplement\sthe\sUPDATE.
D 2019-12-09T14:34:37.171
F src/pragma.c 36c367a62a9d3415fd3d15523e794cccc2cb74e6d806662b0185b8c686f06acb
F test/gencol1.test 037c5c26dddd984ba7ea11bd16996377f72523a4126804b1bbecafc833fccb47
P 1d2e53a39b87e364685e21de137655b6eee725e4c6d27fc90865072d7c5892b5
R 73f9d074ffb019cac59a96d55cf2c0bc
Z 9b8f81a17115c4850191512c3ac99432
e3398c5ffb060b2b26334b8598e2c63953741e2d6f5124dbd6bdfc8e94742539
          sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
Fixed code: C Fix\sthe\sNOT\sNULL\sverification\slogic\sin\sPRAGMA\sintegrity_check\sso\sthat\sit\nworks\sfor\sgenerated\scolumns\swhose\svalue\sis\sthe\sresult\sof\sa\scomparison\soperator.\nTicket\s[bd8c280671ba44a7]
D 2019-12-09T15:52:07.194
F src/pragma.c 26e9ee514138b9697d4be6d8f9ca84655053026390cf10de838862238aa4aba9
F test/gencol1.test 96d669ccb82d4140df6b38bfc110b98f94ac4cf8d32af42bae6349941b3eb92c
P e3398c5ffb060b2b26334b8598e2c63953741e2d6f5124dbd6bdfc8e94742539
R 214fd6f511022e08e69f40b8ca4a69e8
Z 7b3cdd64628ae3e72f321ced6b81d514
f3b39c71b88cb6721f443de56cdce4c08252453a5e340b00a2bd88dc10c42400
          if( sqlite3VdbeGetOp(v,-1)->opcode==OP_Column ){
            sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
          }
# 2019-12-09 ticket bd8c280671ba44a7
# With generated columns, the sqlite3ExprGetColumnOfTable() routine might
# generate a code sequence that does not end with OP_Column.  So check to
# make sure that the last instruction generated is an OP_column prior to
# applying the OPFLAG_TYPEOFARG optimization to NOT NULL checks in the
# PRAGMA integrity_check code.
#
sqlite3 db :memory:
do_execsql_test gencol1-12.10 {
  CREATE TABLE t0 (c0, c1 NOT NULL AS (c0==0));
  INSERT INTO t0(c0) VALUES (0);
  PRAGMA integrity_check;
} {ok}