Limit the number of nested NOT nodes in an fts5 expression to 256.
FossilOrigin-Name: 01219e69b430c8f5fea5ab6ce511ba8c9b4c9b32b6d2d36623dde99c3d3812c9
This commit is contained in:
commit
aeb064c069
@ -17,6 +17,10 @@
|
||||
#include "fts5Int.h"
|
||||
#include "fts5parse.h"
|
||||
|
||||
#ifndef SQLITE_FTS5_MAX_EXPR_DEPTH
|
||||
# define SQLITE_FTS5_MAX_EXPR_DEPTH 256
|
||||
#endif
|
||||
|
||||
/*
|
||||
** All token types in the generated fts5parse.h file are greater than 0.
|
||||
*/
|
||||
@ -57,11 +61,17 @@ struct Fts5Expr {
|
||||
** FTS5_NOT (nChild, apChild valid)
|
||||
** FTS5_STRING (pNear valid)
|
||||
** FTS5_TERM (pNear valid)
|
||||
**
|
||||
** iHeight:
|
||||
** Distance from this node to furthest leaf. This is always 0 for nodes
|
||||
** of type FTS5_STRING and FTS5_TERM. For all other nodes it is one
|
||||
** greater than the largest child value.
|
||||
*/
|
||||
struct Fts5ExprNode {
|
||||
int eType; /* Node type */
|
||||
int bEof; /* True at EOF */
|
||||
int bNomatch; /* True if entry is not a match */
|
||||
int iHeight; /* Distance to tree leaf nodes */
|
||||
|
||||
/* Next method for this node. */
|
||||
int (*xNext)(Fts5Expr*, Fts5ExprNode*, int, i64);
|
||||
@ -131,6 +141,31 @@ struct Fts5Parse {
|
||||
int bPhraseToAnd; /* Convert "a+b" to "a AND b" */
|
||||
};
|
||||
|
||||
/*
|
||||
** Check that the Fts5ExprNode.iHeight variables are set correctly in
|
||||
** the expression tree passed as the only argument.
|
||||
*/
|
||||
#ifndef NDEBUG
|
||||
static void assert_expr_depth_ok(int rc, Fts5ExprNode *p){
|
||||
if( rc==SQLITE_OK ){
|
||||
if( p->eType==FTS5_TERM || p->eType==FTS5_STRING || p->eType==0 ){
|
||||
assert( p->iHeight==0 );
|
||||
}else{
|
||||
int ii;
|
||||
int iMaxChild = 0;
|
||||
for(ii=0; ii<p->nChild; ii++){
|
||||
Fts5ExprNode *pChild = p->apChild[ii];
|
||||
iMaxChild = MAX(iMaxChild, pChild->iHeight);
|
||||
assert_expr_depth_ok(SQLITE_OK, pChild);
|
||||
}
|
||||
assert( p->iHeight==iMaxChild+1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define assert_expr_depth_ok(rc, p)
|
||||
#endif
|
||||
|
||||
void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...){
|
||||
va_list ap;
|
||||
va_start(ap, zFmt);
|
||||
@ -245,6 +280,8 @@ int sqlite3Fts5ExprNew(
|
||||
}while( sParse.rc==SQLITE_OK && t!=FTS5_EOF );
|
||||
sqlite3Fts5ParserFree(pEngine, fts5ParseFree);
|
||||
|
||||
assert_expr_depth_ok(sParse.rc, sParse.pExpr);
|
||||
|
||||
/* If the LHS of the MATCH expression was a user column, apply the
|
||||
** implicit column-filter. */
|
||||
if( iCol<pConfig->nCol && sParse.pExpr && sParse.rc==SQLITE_OK ){
|
||||
@ -2206,6 +2243,7 @@ static void fts5ExprAssignXNext(Fts5ExprNode *pNode){
|
||||
}
|
||||
|
||||
static void fts5ExprAddChildren(Fts5ExprNode *p, Fts5ExprNode *pSub){
|
||||
int ii = p->nChild;
|
||||
if( p->eType!=FTS5_NOT && pSub->eType==p->eType ){
|
||||
int nByte = sizeof(Fts5ExprNode*) * pSub->nChild;
|
||||
memcpy(&p->apChild[p->nChild], pSub->apChild, nByte);
|
||||
@ -2214,6 +2252,9 @@ static void fts5ExprAddChildren(Fts5ExprNode *p, Fts5ExprNode *pSub){
|
||||
}else{
|
||||
p->apChild[p->nChild++] = pSub;
|
||||
}
|
||||
for( ; ii<p->nChild; ii++){
|
||||
p->iHeight = MAX(p->iHeight, p->apChild[ii]->iHeight + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2244,6 +2285,7 @@ static Fts5ExprNode *fts5ParsePhraseToAnd(
|
||||
if( pRet ){
|
||||
pRet->eType = FTS5_AND;
|
||||
pRet->nChild = nTerm;
|
||||
pRet->iHeight = 1;
|
||||
fts5ExprAssignXNext(pRet);
|
||||
pParse->nPhrase--;
|
||||
for(ii=0; ii<nTerm; ii++){
|
||||
@ -2349,6 +2391,14 @@ Fts5ExprNode *sqlite3Fts5ParseNode(
|
||||
}else{
|
||||
fts5ExprAddChildren(pRet, pLeft);
|
||||
fts5ExprAddChildren(pRet, pRight);
|
||||
if( pRet->iHeight>SQLITE_FTS5_MAX_EXPR_DEPTH ){
|
||||
sqlite3Fts5ParseError(pParse,
|
||||
"fts5 expression tree is too large (maximum depth %d)",
|
||||
SQLITE_FTS5_MAX_EXPR_DEPTH
|
||||
);
|
||||
sqlite3_free(pRet);
|
||||
pRet = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -180,7 +180,11 @@ if {[detail_is_full]} {
|
||||
} {1 2}
|
||||
}
|
||||
|
||||
do_execsql_test 4.5 {
|
||||
do_execsql_test 4.5.1 {
|
||||
SELECT rowid FROM s1 WHERE s1 MATCH 'a AND x'
|
||||
} {1 2}
|
||||
|
||||
do_execsql_test 4.5.2 {
|
||||
SELECT rowid FROM s1 WHERE s1 MATCH 'a x'
|
||||
} {1 2}
|
||||
|
||||
|
47
ext/fts5/test/fts5limits.test
Normal file
47
ext/fts5/test/fts5limits.test
Normal file
@ -0,0 +1,47 @@
|
||||
# 2023 May 16
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#*************************************************************************
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5limits
|
||||
return_if_no_fts5
|
||||
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(x);
|
||||
}
|
||||
|
||||
# Default limit for expression depth is 256
|
||||
#
|
||||
foreach {tn nRepeat op bErr} {
|
||||
1 200 AND 0
|
||||
2 200 NOT 0
|
||||
3 200 OR 0
|
||||
|
||||
4 260 AND 0
|
||||
5 260 NOT 1
|
||||
6 260 OR 0
|
||||
} {
|
||||
set L [string repeat "abc " $nRepeat]
|
||||
set Q [join $L " $op "]
|
||||
|
||||
set res {0 {}}
|
||||
if {$bErr} {
|
||||
set res "1 {fts5 expression tree is too large (maximum depth 256)}"
|
||||
}
|
||||
|
||||
do_catchsql_test 1.$tn {
|
||||
SELECT * FROM ft($Q)
|
||||
} $res
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
17
manifest
17
manifest
@ -1,5 +1,5 @@
|
||||
C Increase\sthe\sstack\ssize\savailable\sto\sfuzzcheck\sto\s8MB\son\sWindows.
|
||||
D 2023-05-15T17:20:21.780
|
||||
C Limit\sthe\snumber\sof\snested\sNOT\snodes\sin\san\sfts5\sexpression\sto\s256.
|
||||
D 2023-05-15T17:24:48.160
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@ -90,7 +90,7 @@ F ext/fts5/fts5Int.h ed48a096418ff4a7c02ac9bd1e8d40c46de21b79a132b8b08d3f3223370
|
||||
F ext/fts5/fts5_aux.c 572d5ec92ba7301df2fea3258576332f2f4d2dfd66d8263afd157d9deceac480
|
||||
F ext/fts5/fts5_buffer.c 3001fbabb585d6de52947b44b455235072b741038391f830d6b729225eeaf6a5
|
||||
F ext/fts5/fts5_config.c 051056a9052f5d3a4d1c695f996fd364f920e341f136c60ab2c04aa7e267113f
|
||||
F ext/fts5/fts5_expr.c 7d298d76ea010c339b26ca47f6f69e9aef520ea46c083deaa4e83e87cf0e94b1
|
||||
F ext/fts5/fts5_expr.c 58fb8ceddfb1cefcd54510f9f2f33c220ef9d1b3fa77462111f5ae2a825ab7b1
|
||||
F ext/fts5/fts5_hash.c d4fb70940359f2120ccd1de7ffe64cc3efe65de9e8995b822cd536ff64c96982
|
||||
F ext/fts5/fts5_index.c de3cdae2e0056594aad97a728be5c43b6d7a6cdc7e9cc16f197892b2d8689c21
|
||||
F ext/fts5/fts5_main.c b4dba04a36aaf9b8e8cef0100b6dbb422cc74753eacc11d6401cac7a87c0f38d
|
||||
@ -106,7 +106,7 @@ F ext/fts5/fts5parse.y eb526940f892ade5693f22ffd6c4f2702543a9059942772526eac1fde
|
||||
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
|
||||
F ext/fts5/test/fts5_common.tcl a9de9c2209cc4e7ae3c753e783504e67206c6c1467d08f209cd0c5923d3e8d8b
|
||||
F ext/fts5/test/fts5aa.test 5bd43427b7d08ce2e19c488a26534be450538b9232d4d5305049e8de236e9aa9
|
||||
F ext/fts5/test/fts5ab.test 9205c839332c908aaad2b01ab8670ece8b161e8f2ec8a9fabf18ca9385880bb7
|
||||
F ext/fts5/test/fts5ab.test bd932720c748383277456b81f91bc00453de2174f9762cd05f95d0495dc50390
|
||||
F ext/fts5/test/fts5ac.test a7aa7e1fefc6e1918aa4d3111d5c44a09177168e962c5fd2cca9620de8a7ed6d
|
||||
F ext/fts5/test/fts5ad.test e8cf959dfcd57c8e46d6f5f25665686f3b6627130a9a981371dafdf6482790de
|
||||
F ext/fts5/test/fts5ae.test 1142d16d9cc193894dc13cc8f9c7a8a21411ac61b5567a878514df6f9f0d7bb7
|
||||
@ -166,6 +166,7 @@ F ext/fts5/test/fts5integrity.test 62147a1e85405b986691177e0312be5a64ec9e67b1799
|
||||
F ext/fts5/test/fts5interrupt.test 09613247b273a99889808ef852898177e671406fe71fdde7ea00e78ea283d227
|
||||
F ext/fts5/test/fts5lastrowid.test be98fe3e03235296585b72daad7aed5717ba0062bae5e5c18dd6e04e194c6b28
|
||||
F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc2782680740513c4d1fc114b43d4ad
|
||||
F ext/fts5/test/fts5limits.test 8ab67cf5d311c124b6ceb0062d0297767176df4572d955fce79fa43004dff01c
|
||||
F ext/fts5/test/fts5matchinfo.test 10c9a6f7fe61fb132299c4183c012770b10c4d5c2f2edb6df0b6607f683d737a
|
||||
F ext/fts5/test/fts5merge.test e92a8db28b45931e7a9c7b1bbd36101692759d00274df74d83fd29d25d53b3a6
|
||||
F ext/fts5/test/fts5merge2.test 3ebad1a59d6ad3fb66eff6523a09e95dc6367cbefb3cd73196801dea0425c8e2
|
||||
@ -2069,8 +2070,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 5a479a2c7637a018d1828d9d37973bf3d36a2fc4cd5b752bca61a41cd0920d39
|
||||
R e97269b0123587f5dfc34cc853ad1390
|
||||
U drh
|
||||
Z e688fa42e0abab382f3875162dadcd6f
|
||||
P 2290dc6876041bcc982f162f59fdc9fd98b0983e1058c0a33fd46937ecc4bd84 0e5c1ee40a146ef8b2b3c5f53d0a45e092bc8d8e933f3819805c995819d31bae
|
||||
R 87c6ce3630874e84944f0f7793d3558e
|
||||
U dan
|
||||
Z 904f5b174012101126ffaaf3b418be8e
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
@ -1 +1 @@
|
||||
2290dc6876041bcc982f162f59fdc9fd98b0983e1058c0a33fd46937ecc4bd84
|
||||
01219e69b430c8f5fea5ab6ce511ba8c9b4c9b32b6d2d36623dde99c3d3812c9
|
Loading…
Reference in New Issue
Block a user