From 954733b3864f2659ae839dc5009a5e66469bae2c Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 27 Jul 2018 23:33:16 +0000 Subject: [PATCH] Improvements to the parser to increase coverage. Fix the parser so that at least one expresssion is required after PARTITION BY and within the list of expressions on VALUES(). FossilOrigin-Name: 02204f8b246c868846f39bd44f2e3bc0fab0275aa09ef3a0e5a8e3d58f484ca8 --- manifest | 19 +++++++++---------- manifest.uuid | 2 +- src/expr.c | 11 ++++++++++- src/parse.y | 32 ++++++++++---------------------- src/sqliteInt.h | 2 +- src/window.c | 5 ++++- 6 files changed, 35 insertions(+), 36 deletions(-) diff --git a/manifest b/manifest index d470799eab..1eeed1854b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C When\sdoing\sa\sDROP\sVIEW\sdo\snot\stry\sto\sdelete\sentries\sfrom\sthe\ssqlite_stat1\ntable\sas\sthere\sare\snone. -D 2018-07-27T22:55:58.128 +C Improvements\sto\sthe\sparser\sto\sincrease\scoverage.\s\sFix\sthe\sparser\sso\sthat\nat\sleast\sone\sexpresssion\sis\srequired\safter\sPARTITION\sBY\sand\swithin\sthe\nlist\sof\sexpressions\son\sVALUES(). +D 2018-07-27T23:33:16.472 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -450,7 +450,7 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/dbpage.c 4aa7f26198934dbd002e69418220eae3dbc71b010bbac32bd78faf86b52ce6c3 F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91 F src/delete.c 4c8c7604277a2041647f96b78f4b9a47858e9217e4fb333d35e7b5ab32c5b57f -F src/expr.c 5b5e7b571f377ca76fc76eec0a684384483e0bf6525f6b561a09db09d81600eb +F src/expr.c 907d7de6cac23e55e32f22133a4fa8ca1558d7fe7c9a37e01feebb1106416fe7 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c f59253c0be4b1e9dfcb073b6d6d6ab83090ae50c08b5c113b76013c4b157cd6a F src/func.c 7c288b4ce309b5a8b8473514b88e1f8e69a80134509a8c0db8e39c858e367e7f @@ -487,7 +487,7 @@ F src/os_win.c 070cdbb400097c6cda54aa005356095afdc2f3ee691d17192c54724ef146a971 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 76d29b8a960dcb8b67210f095899d91e4a90673a6674ea58cfd1115b705a7fb9 F src/pager.h c571b064df842ec8f2e90855dead9acf4cbe0d1b2c05afe0ef0d0145f7fd0388 -F src/parse.y a3020c881f558dea6dc1138c58a2a657c26c792120e019792d3e72801da0bf90 +F src/parse.y 704c94624d41d7d46a5467574130e55aa8029a563f4df538f0121475eae46e34 F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170 F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880 @@ -503,7 +503,7 @@ F src/shell.c.in f6ebd05c461805a7c708333cd645e74e0a93560d2118f5adb73a75d8c9cf6b0 F src/sqlite.h.in c6451bb876adced3aba5b1682c6317d215c5eceaba21a6ce979e71a0b8d0bf95 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7 -F src/sqliteInt.h fafe020e6fa39964ffff8ff1b48e2a7f0b394e03c722a746629751d2d31721ae +F src/sqliteInt.h de37aae03c6a4e4f1e1eff15c04292153dbba015ad8e0dc0dffe82ea0fe76d5e F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -587,7 +587,7 @@ F src/where.c fae13835da8cd457bbc50a8530b1f4bfe6eb173dec0687cf1572fc02a7aec415 F src/whereInt.h b90ef9b9707ef750eab2a7a080c48fb4900315033274689def32d0cf5a81ebe4 F src/wherecode.c 2c552dfe50d06e0916dbd49a180e4bf0accfce6d17d46a2dfeea8f75d2b5861b F src/whereexpr.c dc34f0df69418dedb4619f7ad61b7d31f447971223540b957a1b836a62c0ce7b -F src/window.c c61434ce7e35b7d76b3321dec39e10e79061c10eed1e3d7976c87dbdd77aefb5 +F src/window.c 4b503da928dace3e845b891381a4d98eeb8c5744313ae3643df8d8d21fdcca65 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d @@ -1753,8 +1753,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P cfd1b00592bd550e444dfc7b6a6a93c77c07b835729c6cc69a4b6361038964ba 523ff77925f1da361cf31e3fc82bcb1708ed356a2391430ab14ef620c9bf2327 -R a2c24e054b9c8d4fae68977faa296b2b -T +closed 523ff77925f1da361cf31e3fc82bcb1708ed356a2391430ab14ef620c9bf2327 +P 7efdba2bbc8547ee9292a1bbd1e61d38b40d7aabc0860ceba188bdec539f5114 +R 471a9deda4100ce593be82a25e7c7930 U drh -Z 442a0ea187fa6114275630f524fa214c +Z 49ba2c803564fb9ad5a228c53691471f diff --git a/manifest.uuid b/manifest.uuid index cc7468b358..fbf370f762 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7efdba2bbc8547ee9292a1bbd1e61d38b40d7aabc0860ceba188bdec539f5114 \ No newline at end of file +02204f8b246c868846f39bd44f2e3bc0fab0275aa09ef3a0e5a8e3d58f484ca8 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 7767061050..986b4f9aa9 100644 --- a/src/expr.c +++ b/src/expr.c @@ -941,7 +941,12 @@ Expr *sqlite3ExprAnd(sqlite3 *db, Expr *pLeft, Expr *pRight){ ** Construct a new expression node for a function with multiple ** arguments. */ -Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){ +Expr *sqlite3ExprFunction( + Parse *pParse, /* Parsing context */ + ExprList *pList, /* Argument list */ + Token *pToken, /* Name of the function */ + int eDistinct /* SF_Distinct or SF_ALL or 0 */ +){ Expr *pNew; sqlite3 *db = pParse->db; assert( pToken ); @@ -950,10 +955,14 @@ Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){ sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */ return 0; } + if( pList && pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ + sqlite3ErrorMsg(pParse, "too many arguments on function %T", pToken); + } pNew->x.pList = pList; ExprSetProperty(pNew, EP_HasFunc); assert( !ExprHasProperty(pNew, EP_xIsSelect) ); sqlite3ExprSetHeightAndFlags(pParse, pNew); + if( eDistinct==SF_Distinct ) ExprSetProperty(pNew, EP_Distinct); return pNew; } diff --git a/src/parse.y b/src/parse.y index f8757df6ba..ea20529340 100644 --- a/src/parse.y +++ b/src/parse.y @@ -558,7 +558,7 @@ oneselect(A) ::= values(A). values(A) ::= VALUES LP nexprlist(X) RP. { A = sqlite3SelectNew(pParse,X,0,0,0,0,0,SF_Values,0); } -values(A) ::= values(A) COMMA LP exprlist(Y) RP. { +values(A) ::= values(A) COMMA LP nexprlist(Y) RP. { Select *pRight, *pLeft = A; pRight = sqlite3SelectNew(pParse,Y,0,0,0,0,0,SF_Values|SF_MultiValue,0); if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue; @@ -1001,37 +1001,25 @@ expr(A) ::= CAST LP expr(E) AS typetoken(T) RP. { expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP. { - if( Y && Y->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ - sqlite3ErrorMsg(pParse, "too many arguments on function %T", &X); - } - A = sqlite3ExprFunction(pParse, Y, &X); - if( D==SF_Distinct && A ){ - A->flags |= EP_Distinct; - } + A = sqlite3ExprFunction(pParse, Y, &X, D); } expr(A) ::= id(X) LP STAR RP. { - A = sqlite3ExprFunction(pParse, 0, &X); + A = sqlite3ExprFunction(pParse, 0, &X, 0); } %ifndef SQLITE_OMIT_WINDOWFUNC expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP over_clause(Z). { - if( Y && Y->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ - sqlite3ErrorMsg(pParse, "too many arguments on function %T", &X); - } - A = sqlite3ExprFunction(pParse, Y, &X); - if( D==SF_Distinct && A ){ - A->flags |= EP_Distinct; - } + A = sqlite3ExprFunction(pParse, Y, &X, D); sqlite3WindowAttach(pParse, A, Z); } expr(A) ::= id(X) LP STAR RP over_clause(Z). { - A = sqlite3ExprFunction(pParse, 0, &X); + A = sqlite3ExprFunction(pParse, 0, &X, 0); sqlite3WindowAttach(pParse, A, Z); } %endif term(A) ::= CTIME_KW(OP). { - A = sqlite3ExprFunction(pParse, 0, &OP); + A = sqlite3ExprFunction(pParse, 0, &OP, 0); } expr(A) ::= LP nexprlist(X) COMMA expr(Y) RP. { @@ -1065,7 +1053,7 @@ expr(A) ::= expr(A) likeop(OP) expr(Y). [LIKE_KW] { OP.n &= 0x7fffffff; pList = sqlite3ExprListAppend(pParse,0, Y); pList = sqlite3ExprListAppend(pParse,pList, A); - A = sqlite3ExprFunction(pParse, pList, &OP); + A = sqlite3ExprFunction(pParse, pList, &OP, 0); if( bNot ) A = sqlite3PExpr(pParse, TK_NOT, A, 0); if( A ) A->flags |= EP_InfixFunc; } @@ -1076,7 +1064,7 @@ expr(A) ::= expr(A) likeop(OP) expr(Y) ESCAPE expr(E). [LIKE_KW] { pList = sqlite3ExprListAppend(pParse,0, Y); pList = sqlite3ExprListAppend(pParse,pList, A); pList = sqlite3ExprListAppend(pParse,pList, E); - A = sqlite3ExprFunction(pParse, pList, &OP); + A = sqlite3ExprFunction(pParse, pList, &OP, 0); if( bNot ) A = sqlite3PExpr(pParse, TK_NOT, A, 0); if( A ) A->flags |= EP_InfixFunc; } @@ -1640,8 +1628,8 @@ window(A) ::= LP part_opt(X) orderby_opt(Y) frame_opt(Z) RP. { } } -part_opt(A) ::= PARTITION BY exprlist(X). { A = X; } -part_opt(A) ::= . { A = 0; } +part_opt(A) ::= PARTITION BY nexprlist(X). { A = X; } +part_opt(A) ::= . { A = 0; } frame_opt(A) ::= . { A = sqlite3WindowAlloc(pParse, TK_RANGE, TK_UNBOUNDED, 0, TK_CURRENT, 0); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 7c4d46a40a..5d66df4c08 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3792,7 +3792,7 @@ void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*); Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*); void sqlite3PExprAddSelect(Parse*, Expr*, Select*); Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*); -Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*); +Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int); void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32); void sqlite3ExprDelete(sqlite3*, Expr*); ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); diff --git a/src/window.c b/src/window.c index ce85c44608..ce51de790f 100644 --- a/src/window.c +++ b/src/window.c @@ -959,7 +959,10 @@ windowAllocErr: */ void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){ if( p ){ - if( pWin ){ + /* This routine is only called for the parser. If pWin was not + ** allocated due to an OOM, then the parser would fail before ever + ** invoking this routine */ + if( ALWAYS(pWin) ){ p->pWin = pWin; pWin->pOwner = p; if( p->flags & EP_Distinct ){ -- 2.47.2