]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Disallow the use of COLLATE clauses and the ASC and DESC keywords within
authordrh <drh@noemail.net>
Mon, 24 Aug 2015 15:39:42 +0000 (15:39 +0000)
committerdrh <drh@noemail.net>
Mon, 24 Aug 2015 15:39:42 +0000 (15:39 +0000)
foreign key constraints and in the argument list to common table expressions.

FossilOrigin-Name: 83cbc4d8761498647794affffa961a4fca311be7

manifest
manifest.uuid
src/build.c
src/expr.c
src/parse.y
src/sqliteInt.h
test/parser1.test [new file with mode: 0644]

index d46e10f6c8fb540a864c70579c6153279578d7f0..9b3d236121ebd598b54dc8a2efeef847042c379b 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Improvements\sto\sJSON\sstring\sdequoting.
-D 2015-08-24T12:42:41.080
+C Disallow\sthe\suse\sof\sCOLLATE\sclauses\sand\sthe\sASC\sand\sDESC\skeywords\swithin\nforeign\skey\sconstraints\sand\sin\sthe\sargument\slist\sto\scommon\stable\sexpressions.
+D 2015-08-24T15:39:42.405
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in e2218eb228374422969de7b1680eda6864affcef
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -282,14 +282,14 @@ F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
 F src/btree.c f48b3ef91676c06a90a8832987ecef6b94c931ee
 F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
 F src/btreeInt.h 8177c9ab90d772d6d2c6c517e05bed774b7c92c0
-F src/build.c 5eb5d055a1d1cdaaea25e01b12607aa894bc0911
+F src/build.c f49c55c1fba430c2d6af5039d0bf14de5ae6a427
 F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
 F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f
 F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b
 F src/date.c 8ec787fed4929d8ccdf6b1bc360fccc3e1d2ca58
 F src/dbstat.c f402e77e25089c6003d0c60b3233b9b3947d599a
 F src/delete.c 8857a6f27560718f65d43bdbec86c967ae1f8dfa
-F src/expr.c c34408e0ac1c57cf58ffa2003b339715ee9bda57
+F src/expr.c c05d67f1a03c097d5c29839d5a538cfde9c472ce
 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
 F src/fkey.c c9b63a217d86582c22121699a47f22f524608869
 F src/func.c 824bea430d3a2b7dbc62806ad54da8fdb8ed9e3f
@@ -326,7 +326,7 @@ F src/os_win.c 40b3af7a47eb1107d0d69e592bec345a3b7b798a
 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
 F src/pager.c aa916ca28606ccf4b6877dfc2b643ccbca86589f
 F src/pager.h 6d435f563b3f7fcae4b84433b76a6ac2730036e2
-F src/parse.y ad9af8552f6f340bd646577ca63356a6f82b6a7e
+F src/parse.y b5e0a5f8bb9ec33a58aa34850b6fae46aac51fdd
 F src/pcache.c cde06aa50962595e412d497e22fd2e07878ba1f0
 F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9
 F src/pcache1.c a3fe31b17e841ec70beee72a2c960e9c787a8857
@@ -342,7 +342,7 @@ F src/shell.c b1f91e60918df3a68efad1e3a11696b9a7e23d23
 F src/sqlite.h.in 378bebc8fe6a88bade25e5f23b7e6123fdc64b00
 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
 F src/sqlite3ext.h f700e6a9dd1fdcccc9951ab022b366fb66b9e413
-F src/sqliteInt.h 89e68539d645db597366a91411468b51e73c21a0
+F src/sqliteInt.h 1741691824491c330dda1e49f370920bfd3aa230
 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
 F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
 F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
@@ -910,6 +910,7 @@ F test/pagerfault2.test caf4c7facb914fd3b03a17b31ae2b180c8d6ca1f
 F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8
 F test/pageropt.test 6b8f6a123a5572c195ad4ae40f2987007923bbd6
 F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305
+F test/parser1.test 23867b6f2c4758c7774108826d9f17e9cd17bcde
 F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
 F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
@@ -1378,7 +1379,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P f0aba0e120074430cd7ad93291fcc97b8a25a054
-R 3625d17566ea8cc316dd4952d6bffb99
+P 196d66d34d9783622e6f2f79eafea1488fc6f5cf
+R 2a74528f51d8172b5387a3b7f110bb2b
 U drh
-Z 6090b9f6d755a9917a579931aff72e9d
+Z ffc4f8e604c67b08cae8ed1eda808a43
index bf64eaf064ba63f603d6d46e7f61b3a15db772cc..9ca8f1fa7585ec0bbe1fa798105c23e72f1a49ad 100644 (file)
@@ -1 +1 @@
-196d66d34d9783622e6f2f79eafea1488fc6f5cf
\ No newline at end of file
+83cbc4d8761498647794affffa961a4fca311be7
\ No newline at end of file
index e45908dc3b6c07d6adda7f8a730d3ba6ddbbcd35..0a816b398e4eebb3588adeceb06293e031ed72ab 100644 (file)
@@ -1321,7 +1321,7 @@ void sqlite3AddPrimaryKey(
   }
   if( nTerm==1
    && zType && sqlite3StrICmp(zType, "INTEGER")==0
-   && sortOrder==SQLITE_SO_ASC
+   && sortOrder!=SQLITE_SO_DESC
   ){
     pTab->iPKey = iCol;
     pTab->keyConf = (u8)onError;
@@ -2600,6 +2600,8 @@ void sqlite3CreateForeignKey(
 
   assert( pTo!=0 );
   if( p==0 || IN_DECLARE_VTAB ) goto fk_end;
+  sqlite3RestrictColumnListSyntax(pParse, pFromCol);
+  sqlite3RestrictColumnListSyntax(pParse, pToCol);
   if( pFromCol==0 ){
     int iCol = p->nCol-1;
     if( NEVER(iCol<0) ) goto fk_end;
@@ -3038,7 +3040,8 @@ Index *sqlite3CreateIndex(
     if( pList==0 ) goto exit_create_index;
     pList->a[0].zName = sqlite3DbStrDup(pParse->db,
                                         pTab->aCol[pTab->nCol-1].zName);
-    pList->a[0].sortOrder = (u8)sortOrder;
+    assert( pList->nExpr==1 );
+    sqlite3ExprListSetSortOrder(pList, sortOrder);
   }
 
   /* Figure out how many bytes of space are required to store explicitly
@@ -4283,6 +4286,32 @@ KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){
   return pKey;
 }
 
+/*
+** Generate a syntax error if the expression list provided contains
+** any COLLATE or ASC or DESC keywords.
+**
+** Some legacy versions of SQLite allowed constructs like:
+**
+**      CREATE TABLE x(..., FOREIGN KEY(x COLLATE binary DESC) REFERENCES...);
+**                                        ^^^^^^^^^^^^^^^^^^^
+**
+** The COLLATE and sort order terms were ignored.  To prevent compatibility
+** problems in case something like this appears in a legacy sqlite_master
+** table, only enforce the restriction on new SQL statements, not when
+** parsing the schema out of the sqlite_master table.
+*/
+void sqlite3RestrictColumnListSyntax(Parse *pParse, ExprList *p){
+  int i;
+  if( p==0 || pParse->db->init.busy ) return;
+  for(i=0; i<p->nExpr; i++){
+    if( p->a[i].pExpr!=0 || p->a[i].bDefinedSO ){
+      sqlite3ErrorMsg(pParse, "syntax error after column name \"%w\"",
+                      p->a[i].zName);
+      return;
+    }
+  }
+}
+
 #ifndef SQLITE_OMIT_CTE
 /* 
 ** This routine is invoked once per CTE by the parser while parsing a 
@@ -4299,6 +4328,8 @@ With *sqlite3WithAdd(
   With *pNew;
   char *zName;
 
+  sqlite3RestrictColumnListSyntax(pParse, pArglist);
+
   /* Check that the CTE name is unique within this WITH clause. If
   ** not, store an error in the Parse structure. */
   zName = sqlite3NameFromToken(pParse->db, pName);
index 04cd36ea79037049838b3cd47484e8ead3d4b34c..1c57ecc6fd6592c52b305b7704b732006f36c0ae 100644 (file)
@@ -1160,6 +1160,21 @@ no_mem:
   return 0;
 }
 
+/*
+** Set the sort order for the last element on the given ExprList.
+*/
+void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder){
+  if( p==0 ) return;
+  assert( SQLITE_SO_UNDEFINED<0 && SQLITE_SO_ASC>=0 && SQLITE_SO_DESC>0 );
+  assert( p->nExpr>0 );
+  if( iSortOrder<0 ){
+    assert( p->a[p->nExpr-1].sortOrder==SQLITE_SO_ASC );
+    return;
+  }
+  p->a[p->nExpr-1].sortOrder = (u8)iSortOrder;
+  p->a[p->nExpr-1].bDefinedSO = 1;
+}
+
 /*
 ** Set the ExprList.a[].zName element of the most recently added item
 ** on the expression list.
index 3d186b28aa62e126fea45d9495414aa17b43f18a..bc193ec1f20b31dc1a87dce9901e9f750fead865 100644 (file)
@@ -680,18 +680,18 @@ orderby_opt(A) ::= .                          {A = 0;}
 orderby_opt(A) ::= ORDER BY sortlist(X).      {A = X;}
 sortlist(A) ::= sortlist(X) COMMA expr(Y) sortorder(Z). {
   A = sqlite3ExprListAppend(pParse,X,Y.pExpr);
-  if( A ) A->a[A->nExpr-1].sortOrder = (u8)Z;
+  sqlite3ExprListSetSortOrder(A,Z);
 }
 sortlist(A) ::= expr(Y) sortorder(Z). {
   A = sqlite3ExprListAppend(pParse,0,Y.pExpr);
-  if( A && ALWAYS(A->a) ) A->a[0].sortOrder = (u8)Z;
+  sqlite3ExprListSetSortOrder(A,Z);
 }
 
 %type sortorder {int}
 
 sortorder(A) ::= ASC.           {A = SQLITE_SO_ASC;}
 sortorder(A) ::= DESC.          {A = SQLITE_SO_DESC;}
-sortorder(A) ::= .              {A = SQLITE_SO_ASC;}
+sortorder(A) ::= .              {A = SQLITE_SO_UNDEFINED;}
 
 %type groupby_opt {ExprList*}
 %destructor groupby_opt {sqlite3ExprListDelete(pParse->db, $$);}
@@ -1229,14 +1229,14 @@ idxlist(A) ::= idxlist(X) COMMA nm(Y) collate(C) sortorder(Z).  {
   A = sqlite3ExprListAppend(pParse,X, p);
   sqlite3ExprListSetName(pParse,A,&Y,1);
   sqlite3ExprListCheckLength(pParse, A, "index");
-  if( A ) A->a[A->nExpr-1].sortOrder = (u8)Z;
+  sqlite3ExprListSetSortOrder(A,Z);
 }
 idxlist(A) ::= nm(Y) collate(C) sortorder(Z). {
   Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &C, 1);
   A = sqlite3ExprListAppend(pParse,0, p);
   sqlite3ExprListSetName(pParse, A, &Y, 1);
   sqlite3ExprListCheckLength(pParse, A, "index");
-  if( A ) A->a[A->nExpr-1].sortOrder = (u8)Z;
+  sqlite3ExprListSetSortOrder(A,Z);
 }
 
 %type collate {Token}
index 96a7700210e525975ac2956d413a4b1a1dd6ae21..18a0fd705feaa16596a3990b767d84539eb822db 100644 (file)
@@ -1525,6 +1525,7 @@ struct CollSeq {
 */
 #define SQLITE_SO_ASC       0  /* Sort in ascending order */
 #define SQLITE_SO_DESC      1  /* Sort in ascending order */
+#define SQLITE_SO_UNDEFINED -1 /* No sort order specified */
 
 /*
 ** Column affinity types.
@@ -2189,6 +2190,7 @@ struct ExprList {
     unsigned done :1;       /* A flag to indicate when processing is finished */
     unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */
     unsigned reusable :1;   /* Constant expression is reusable */
+    unsigned bDefinedSO :1; /* True if either DESC or ASC keywords present */
     union {
       struct {
         u16 iOrderByCol;      /* For ORDER BY, column number in result set */
@@ -3244,6 +3246,7 @@ Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*);
 void sqlite3ExprAssignVarNumber(Parse*, Expr*);
 void sqlite3ExprDelete(sqlite3*, Expr*);
 ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
+void sqlite3ExprListSetSortOrder(ExprList*,int);
 void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
 void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*);
 void sqlite3ExprListDelete(sqlite3*, ExprList*);
@@ -3755,6 +3758,7 @@ const char *sqlite3JournalModename(int);
   int sqlite3Checkpoint(sqlite3*, int, int, int*, int*);
   int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
 #endif
+void sqlite3RestrictColumnListSyntax(Parse*,ExprList*);
 #ifndef SQLITE_OMIT_CTE
   With *sqlite3WithAdd(Parse*,With*,Token*,ExprList*,Select*);
   void sqlite3WithDelete(sqlite3*,With*);
diff --git a/test/parser1.test b/test/parser1.test
new file mode 100644 (file)
index 0000000..f4c3227
--- /dev/null
@@ -0,0 +1,58 @@
+# 2014-08-24
+#
+# 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 implements regression tests for SQLite library.
+# The focus of this script is testing details of the SQL language parser.
+# 
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+do_catchsql_test parser1-1.1 {
+  CREATE TABLE t1(
+    a TEXT PRIMARY KEY,
+    b TEXT,
+    FOREIGN KEY(b COLLATE nocase DESC) REFERENCES t1(a COLLATE binary ASC)
+  );
+} {1 {syntax error after column name "a"}}
+do_execsql_test parser1-1.2 {
+  CREATE TABLE t1(
+    a TEXT PRIMARY KEY,
+    b TEXT,
+    FOREIGN KEY(b) REFERENCES t1(a)
+  );
+  INSERT INTO t1 VALUES('abc',NULL),('xyz','abc');
+  PRAGMA writable_schema=on;
+  UPDATE sqlite_master SET sql='CREATE TABLE t1(
+    a TEXT PRIMARY KEY,
+    b TEXT,
+    FOREIGN KEY(b COLLATE nocase) REFERENCES t1(a)
+  )' WHERE name='t1';
+  SELECT name FROM sqlite_master WHERE sql LIKE '%collate%';
+} {t1}
+sqlite3 db2 test.db
+do_test parser1-1.3 {
+  sqlite3 db2 test.db
+  db2 eval {SELECT * FROM t1 ORDER BY 1}
+} {abc {} xyz abc}
+
+
+do_catchsql_test parser1-2.1 {
+  WITH RECURSIVE
+    c(x COLLATE binary) AS (VALUES(1) UNION SELECT x+1 FROM c WHERE x<5)
+  SELECT x FROM c;
+} {1 {syntax error after column name "x"}}
+do_catchsql_test parser1-2.2 {
+  WITH RECURSIVE
+    c(x ASC) AS (VALUES(1) UNION SELECT x+1 FROM c WHERE x<5)
+  SELECT x FROM c;
+} {1 {syntax error after column name "x"}}
+
+finish_test