fix(search): cap an expression at 256 atoms
The compiled SQL chains every atom into one expression, and SQLite rejects expressions deeper than 1000 levels. A query of about 1000 words parsed but then failed in SQL, outside the syntax-error handling, and crashed the app. The parser now rejects more than 256 atoms as a syntax error.
This commit is contained in:
1 parent
1d744ba504
commit
23f7806e2d
5 files changed
+79
-4
No files matched your search
@@ -248,6 +248,28 @@ public class SearchQueryParserTests
|
||||
Assert.IsNotNull(SearchQueryParser.Parse(groups));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AtomCountAtTheLimitParses()
|
||||
{
|
||||
Assert.IsNotNull(SearchQueryParser.Parse(string.Join(" ", Enumerable.Repeat("a", SearchQueryParser.MaxAtomCount))));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[DataRow(" ")]
|
||||
[DataRow(" OR ")]
|
||||
public void AtomCountBeyondTheLimitIsAnError(string separator)
|
||||
{
|
||||
AssertSyntaxError(string.Join(separator, Enumerable.Repeat("a", SearchQueryParser.MaxAtomCount + 1)));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void QualifiersAndPhrasesCountTowardsTheAtomLimit()
|
||||
{
|
||||
int half = SearchQueryParser.MaxAtomCount / 2;
|
||||
string text = string.Join(" ", Enumerable.Repeat("tag:\"a b\"", half).Concat(Enumerable.Repeat("\"c\"", half + 1)));
|
||||
AssertSyntaxError(text);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void VeryDeepNestingIsAnErrorRatherThanACrash()
|
||||
{
|
||||
|
||||
@@ -190,4 +190,20 @@ public class SearchSqlCompilerTests
|
||||
CollectionAssert.AreEqual(new[] { 5L }, fixture.Search("tag:äpfel"));
|
||||
CollectionAssert.AreEqual(new[] { 5L }, fixture.Search("column:érable"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void LargestAcceptedQueriesRunWithinTheSqliteExpressionDepth()
|
||||
{
|
||||
using var fixture = new SearchFixture();
|
||||
int count = SearchQueryParser.MaxAtomCount;
|
||||
int depth = SearchQueryParser.MaxNestingDepth;
|
||||
string nested = string.Concat(Enumerable.Repeat("(tag:x OR ", depth))
|
||||
+ string.Join(" ", Enumerable.Repeat("apple", count - depth))
|
||||
+ new string(')', depth);
|
||||
|
||||
CollectionAssert.AreEqual(new[] { 2L }, fixture.Search(string.Join(" ", Enumerable.Repeat("apple", count))));
|
||||
CollectionAssert.AreEqual(new[] { 2L }, fixture.Search(string.Join(" OR ", Enumerable.Repeat("apple", count))));
|
||||
CollectionAssert.AreEqual(new[] { 2L }, fixture.Search(string.Join(" ", Enumerable.Repeat("title:apple", count))));
|
||||
CollectionAssert.AreEqual(new[] { 2L }, fixture.Search(nested));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user