EQL: Forbid usage of ['] for string literals (#62458)

The usage of single quotes to wrap a string literal is forbidden
and an error encouraging the user to user double quotes is returned.

Tests are properly adjusted.

Relates to #61659
This commit is contained in:
Marios Trivyzas 2020-09-16 21:21:58 +02:00 committed by GitHub
parent e1882cd9cd
commit 8be400b773
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 324 additions and 322 deletions

View file

@ -178,7 +178,7 @@ public abstract class RestEqlUsageTestCase extends ESRestTestCase {
" [process where serial_event_id < 4] by exit_code" + " [process where serial_event_id < 4] by exit_code" +
" [process where opcode == 1] by user" + " [process where opcode == 1] by user" +
" [process where opcode == 2] by user" + " [process where opcode == 2] by user" +
" [file where parent_process_name == 'file_delete_event'] by exit_code" + " [file where parent_process_name == \\\"file_delete_event\\\"] by exit_code" +
" until [process where opcode=1] by ppid" + " until [process where opcode=1] by ppid" +
" | head 4" + " | head 4" +
" | tail 2"); " | tail 2");
@ -216,7 +216,7 @@ public abstract class RestEqlUsageTestCase extends ESRestTestCase {
runEql("sequence by user, ppid, exit_code with maxspan=1m" + runEql("sequence by user, ppid, exit_code with maxspan=1m" +
" [process where serial_event_id < 4]" + " [process where serial_event_id < 4]" +
" [process where opcode == 1]" + " [process where opcode == 1]" +
" [file where parent_process_name == 'file_delete_event']" + " [file where parent_process_name == \\\"file_delete_event\\\"]" +
" [process where serial_event_id < 4]" + " [process where serial_event_id < 4]" +
" [process where opcode == 1]" + " [process where opcode == 1]" +
"| tail 4"); "| tail 4");

View file

@ -62,7 +62,7 @@ network where cidrMatch(source_address, "0.0.0.0/0") == true
name = "concatEquals1" name = "concatEquals1"
description = "test string concatenation. update test to avoid case-sensitivity issues" description = "test string concatenation. update test to avoid case-sensitivity issues"
query = ''' query = '''
process where concat(serial_event_id, '::', process_name, '::', opcode) == '5::wininit.exe::3' process where concat(serial_event_id, "::", process_name, "::", opcode) == "5::wininit.exe::3"
''' '''
expected_event_ids = [5] expected_event_ids = [5]
@ -138,15 +138,15 @@ expected_event_ids = [98]
notes = "regexp doesn't support character classes" notes = "regexp doesn't support character classes"
query = ''' query = '''
// //
// ?'.*?net1\s+localgroup.*?') // ?".*?net1\s+localgroup.*?")
process where match(command_line, ?'.*?net1[ ]+localgroup.*?') process where match(command_line, ?".*?net1[ ]+localgroup.*?")
''' '''
[[queries]] [[queries]]
name = "matchLiteAdditional" name = "matchLiteAdditional"
expected_event_ids = [98] expected_event_ids = [98]
query = ''' query = '''
process where matchLite(command_line, ?'.*?net1.*?') process where matchLite(command_line, ?".*?net1.*?")
''' '''
[[queries]] [[queries]]
@ -154,8 +154,8 @@ name = "matchWithCharacterClasses2"
expected_event_ids = [98] expected_event_ids = [98]
notes = "regexp doesn't support predefined character classes (like \\s)" notes = "regexp doesn't support predefined character classes (like \\s)"
query = ''' query = '''
// ?'.*?net1\s+\w{4,15}\s+.*?' // ?".*?net1\s+\w{4,15}\s+.*?"
process where match(command_line, ?'.*?net1[ ]+[a-z]{4,15}[ ]+.*?') process where match(command_line, ?".*?net1[ ]+[a-z]{4,15}[ ]+.*?")
''' '''
@ -164,14 +164,14 @@ process where match(command_line, ?'.*?net1[ ]+[a-z]{4,15}[ ]+.*?')
name = "multiPatternMatch" name = "multiPatternMatch"
expected_event_ids = [50, 97, 98] expected_event_ids = [50, 97, 98]
query = ''' query = '''
process where match(command_line, '.*?net[1]? localgroup.*?', '.*? myappserver.py .*?') process where match(command_line, ".*?net[1]? localgroup.*?", ".*? myappserver.py .*?")
''' '''
[[queries]] [[queries]]
name = "matchWithSubstring" name = "matchWithSubstring"
expected_event_ids = [50, 98] expected_event_ids = [50, 98]
query = ''' query = '''
process where match(substring(command_line, 5), '.*?net[1]? localgroup.*?', '.*? myappserver.py .*?') process where match(substring(command_line, 5), ".*?net[1]? localgroup.*?", ".*? myappserver.py .*?")
''' '''
[[queries]] [[queries]]

View file

@ -762,7 +762,7 @@ expected_event_ids = [1, 2,
name = "sequencesOnDifferentEventTypes1" name = "sequencesOnDifferentEventTypes1"
query = ''' query = '''
sequence by unique_pid sequence by unique_pid
[process where opcode=1 and process_name == 'MSBuild.exe'] [process where opcode=1 and process_name == "MSBuild.exe"]
[network where true] [network where true]
''' '''
expected_event_ids = [75273, 75304] expected_event_ids = [75273, 75304]
@ -1322,7 +1322,7 @@ name = "arrayContainsCaseInsensitive1"
case_insensitive = true case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayContains(bytes_written_string_list, 'En-uS') registry where arrayContains(bytes_written_string_list, "En-uS")
''' '''
[[queries]] [[queries]]
@ -1330,7 +1330,7 @@ name = "arrayContainsCaseInsensitive2"
case_insensitive = true case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayContains(bytes_written_string_list, 'En') registry where arrayContains(bytes_written_string_list, "En")
''' '''
[[queries]] [[queries]]
@ -1338,7 +1338,7 @@ name = "lengthCaseInsensitive2"
case_insensitive = true case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where length(bytes_written_string_list) > 0 and bytes_written_string_list[0] == 'EN-us' registry where length(bytes_written_string_list) > 0 and bytes_written_string_list[0] == "EN-us"
''' '''
[[queries]] [[queries]]
@ -1346,7 +1346,7 @@ name = "arrayCaseInsensitive1"
case_insensitive = true case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where bytes_written_string_list[0] == 'EN-us' registry where bytes_written_string_list[0] == "EN-us"
''' '''
[[queries]] [[queries]]
@ -1354,7 +1354,7 @@ name = "arrayCaseInsensitive2"
case_insensitive = true case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where bytes_written_string_list[1] == 'EN' registry where bytes_written_string_list[1] == "EN"
''' '''
@ -1363,7 +1363,7 @@ name = "arrayContainsCaseInsensitive3"
case_insensitive = true case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayContains(bytes_written_string_list, 'en-US') registry where arrayContains(bytes_written_string_list, "en-US")
''' '''
[[queries]] [[queries]]
@ -1371,7 +1371,7 @@ name = "arrayContainsCaseInsensitive4"
case_insensitive = true case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayContains(bytes_written_string_list, 'en') registry where arrayContains(bytes_written_string_list, "en")
''' '''
[[queries]] [[queries]]
@ -1379,41 +1379,41 @@ name = "arrayCaseInsensitive3"
case_insensitive = true case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where length(bytes_written_string_list) > 0 and bytes_written_string_list[0] == 'en-US' registry where length(bytes_written_string_list) > 0 and bytes_written_string_list[0] == "en-US"
''' '''
[[queries]] [[queries]]
name = "arrayEquality1" name = "arrayEquality1"
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where bytes_written_string_list[0] == 'en-US' registry where bytes_written_string_list[0] == "en-US"
''' '''
[[queries]] [[queries]]
name = "arrayEquality2" name = "arrayEquality2"
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where bytes_written_string_list[1] == 'en' registry where bytes_written_string_list[1] == "en"
''' '''
[[queries]] [[queries]]
name = "matchLite1" name = "matchLite1"
query = ''' query = '''
process where matchLite(command_line, ?'.*?net1\s+localgroup\s+.*?') process where matchLite(command_line, ?".*?net1\s+localgroup\s+.*?")
''' '''
expected_event_ids = [98] expected_event_ids = [98]
[[queries]] [[queries]]
name = "matchLite2" name = "matchLite2"
query = ''' query = '''
process where matchLite(command_line, ?'.*?net1\s+\w+\s+.*?') process where matchLite(command_line, ?".*?net1\s+\w+\s+.*?")
''' '''
expected_event_ids = [98] expected_event_ids = [98]
[[queries]] [[queries]]
name = "matchLite3" name = "matchLite3"
query = ''' query = '''
process where matchLite(command_line, ?'.*?net1\s+\w{4,15}\s+.*?') process where matchLite(command_line, ?".*?net1\s+\w{4,15}\s+.*?")
''' '''
expected_event_ids = [98] expected_event_ids = [98]
@ -1421,13 +1421,13 @@ expected_event_ids = [98]
name = "match1" name = "match1"
expected_event_ids = [98] expected_event_ids = [98]
query = ''' query = '''
process where match(command_line, ?'.*?net1\s+\w{4,15}\s+.*?') process where match(command_line, ?".*?net1\s+\w{4,15}\s+.*?")
''' '''
[[queries]] [[queries]]
name = "matchLite4" name = "matchLite4"
query = ''' query = '''
process where matchLite(command_line, ?'.*?net1\s+[localgrup]{4,15}\s+.*?') process where matchLite(command_line, ?".*?net1\s+[localgrup]{4,15}\s+.*?")
''' '''
expected_event_ids = [98] expected_event_ids = [98]
@ -1435,7 +1435,7 @@ expected_event_ids = [98]
name = "stringEqualsCaseInsensitive1" name = "stringEqualsCaseInsensitive1"
case_insensitive = true case_insensitive = true
query = ''' query = '''
process where 'net.EXE' == original_file_name process where "net.EXE" == original_file_name
| filter process_name="net*.exe" | filter process_name="net*.exe"
''' '''
expected_event_ids = [97] expected_event_ids = [97]
@ -1445,7 +1445,7 @@ note = "check that case insensitive comparisons are performed even for lhs strin
name = "stringEqualsCaseInsensitive2" name = "stringEqualsCaseInsensitive2"
case_insensitive = true case_insensitive = true
query = ''' query = '''
process where process_name == original_file_name and process_name='net*.exe' process where process_name == original_file_name and process_name="net*.exe"
''' '''
expected_event_ids = [97, 98] expected_event_ids = [97, 98]
note = "check that case insensitive comparisons are performed for fields." note = "check that case insensitive comparisons are performed for fields."
@ -1463,7 +1463,7 @@ description = "check that case insensitive comparisons are performed for fields.
name = "startsWithCaseSensitive" name = "startsWithCaseSensitive"
case_sensitive = true case_sensitive = true
query = ''' query = '''
file where opcode=0 and startsWith(file_name, 'explorer.') file where opcode=0 and startsWith(file_name, "explorer.")
''' '''
expected_event_ids = [88] expected_event_ids = [88]
description = "check built-in string functions" description = "check built-in string functions"
@ -1473,7 +1473,7 @@ description = "check built-in string functions"
name = "startsWithCaseInsensitive1" name = "startsWithCaseInsensitive1"
case_insensitive = true case_insensitive = true
query = ''' query = '''
file where opcode=0 and startsWith(file_name, 'explorer.') file where opcode=0 and startsWith(file_name, "explorer.")
''' '''
expected_event_ids = [88, 92] expected_event_ids = [88, 92]
description = "check built-in string functions" description = "check built-in string functions"
@ -1483,7 +1483,7 @@ description = "check built-in string functions"
name = "startsWithCaseInsensitive2" name = "startsWithCaseInsensitive2"
case_insensitive = true case_insensitive = true
query = ''' query = '''
file where opcode=0 and startsWith(file_name, 'exploRER.') file where opcode=0 and startsWith(file_name, "exploRER.")
''' '''
expected_event_ids = [88, 92] expected_event_ids = [88, 92]
description = "check built-in string functions" description = "check built-in string functions"
@ -1492,7 +1492,7 @@ description = "check built-in string functions"
name = "startsWithCaseInsensitive3" name = "startsWithCaseInsensitive3"
case_insensitive = true case_insensitive = true
query = ''' query = '''
file where opcode=0 and startsWith(file_name, 'expLORER.exe') file where opcode=0 and startsWith(file_name, "expLORER.exe")
''' '''
expected_event_ids = [88, 92] expected_event_ids = [88, 92]
description = "check built-in string functions" description = "check built-in string functions"
@ -1500,7 +1500,7 @@ description = "check built-in string functions"
[[queries]] [[queries]]
name = "endsWith1" name = "endsWith1"
query = ''' query = '''
file where opcode=0 and endsWith(file_name, 'lorer.exe') file where opcode=0 and endsWith(file_name, "lorer.exe")
''' '''
expected_event_ids = [88] expected_event_ids = [88]
description = "check built-in string functions" description = "check built-in string functions"
@ -1510,7 +1510,7 @@ description = "check built-in string functions"
name = "endsWithCaseInsensitive" name = "endsWithCaseInsensitive"
case_insensitive = true case_insensitive = true
query = ''' query = '''
file where opcode=0 and endsWith(file_name, 'loREr.exe') file where opcode=0 and endsWith(file_name, "loREr.exe")
''' '''
expected_event_ids = [88] expected_event_ids = [88]
description = "check built-in string functions" description = "check built-in string functions"
@ -1518,7 +1518,7 @@ description = "check built-in string functions"
[[queries]] [[queries]]
name = "endsWith2" name = "endsWith2"
query = ''' query = '''
file where opcode=0 and startsWith('explorer.exeaaaaaaaa', file_name) file where opcode=0 and startsWith("explorer.exeaaaaaaaa", file_name)
''' '''
expected_event_ids = [88] expected_event_ids = [88]
description = "check built-in string functions" description = "check built-in string functions"
@ -1527,7 +1527,7 @@ description = "check built-in string functions"
name = "endsWithAndCondition" name = "endsWithAndCondition"
case_insensitive = true case_insensitive = true
query = ''' query = '''
file where opcode=0 and serial_event_id = 88 and startsWith('explorer.exeaAAAA', 'EXPLORER.exe') file where opcode=0 and serial_event_id = 88 and startsWith("explorer.exeaAAAA", "EXPLORER.exe")
''' '''
expected_event_ids = [88] expected_event_ids = [88]
description = "check built-in string functions" description = "check built-in string functions"
@ -1535,7 +1535,7 @@ description = "check built-in string functions"
[[queries]] [[queries]]
name = "stringContains2" name = "stringContains2"
query = ''' query = '''
file where opcode=0 and stringContains('ABCDEFGHIexplorer.exeJKLMNOP', file_name) file where opcode=0 and stringContains("ABCDEFGHIexplorer.exeJKLMNOP", file_name)
''' '''
expected_event_ids = [88] expected_event_ids = [88]
description = "check built-in string functions" description = "check built-in string functions"
@ -1544,7 +1544,7 @@ description = "check built-in string functions"
name = "indexOfCaseInsensitive" name = "indexOfCaseInsensitive"
case_insensitive = true case_insensitive = true
query = ''' query = '''
file where opcode=0 and indexOf(file_name, 'plore') == 2 and indexOf(file_name, '.pf') == null file where opcode=0 and indexOf(file_name, "plore") == 2 and indexOf(file_name, ".pf") == null
''' '''
expected_event_ids = [88] expected_event_ids = [88]
description = "check built-in string functions" description = "check built-in string functions"
@ -1552,7 +1552,7 @@ description = "check built-in string functions"
[[queries]] [[queries]]
name = "indexOf1" name = "indexOf1"
query = ''' query = '''
file where opcode=0 and indexOf(file_name, 'explorer.') > 0 and indexOf(file_name, 'plore', 100) > 0 file where opcode=0 and indexOf(file_name, "explorer.") > 0 and indexOf(file_name, "plore", 100) > 0
''' '''
expected_event_ids = [] expected_event_ids = []
description = "check built-in string functions" description = "check built-in string functions"
@ -1561,7 +1561,7 @@ description = "check built-in string functions"
name = "indexOf2" name = "indexOf2"
case_sensitive = true case_sensitive = true
query = ''' query = '''
file where opcode=0 and indexOf(file_name, 'plorer.', 0) == 2 file where opcode=0 and indexOf(file_name, "plorer.", 0) == 2
''' '''
expected_event_ids = [88] expected_event_ids = [88]
description = "check built-in string functions" description = "check built-in string functions"
@ -1570,7 +1570,7 @@ description = "check built-in string functions"
name = "indexOf3" name = "indexOf3"
case_insensitive = true case_insensitive = true
query = ''' query = '''
file where opcode=0 and indexOf(file_name, 'plorer.', 0) == 2 file where opcode=0 and indexOf(file_name, "plorer.", 0) == 2
''' '''
expected_event_ids = [88, 92] expected_event_ids = [88, 92]
description = "check built-in string functions" description = "check built-in string functions"
@ -1579,7 +1579,7 @@ description = "check built-in string functions"
name = "indexOf4" name = "indexOf4"
case_sensitive = true case_sensitive = true
query = ''' query = '''
file where opcode=0 and indexOf(file_name, 'plorer.', 2) != null file where opcode=0 and indexOf(file_name, "plorer.", 2) != null
''' '''
expected_event_ids = [88] expected_event_ids = [88]
description = "check built-in string functions" description = "check built-in string functions"
@ -1588,7 +1588,7 @@ description = "check built-in string functions"
name = "indexOf5" name = "indexOf5"
case_insensitive = true case_insensitive = true
query = ''' query = '''
file where opcode=0 and indexOf(file_name, 'plorer.', 2) != null file where opcode=0 and indexOf(file_name, "plorer.", 2) != null
''' '''
expected_event_ids = [88, 92] expected_event_ids = [88, 92]
description = "check built-in string functions" description = "check built-in string functions"
@ -1596,7 +1596,7 @@ description = "check built-in string functions"
[[queries]] [[queries]]
name = "indexOf6" name = "indexOf6"
query = ''' query = '''
file where opcode=0 and indexOf(file_name, 'plorer.', 4) != null file where opcode=0 and indexOf(file_name, "plorer.", 4) != null
''' '''
expected_event_ids = [] expected_event_ids = []
description = "check built-in string functions" description = "check built-in string functions"
@ -1604,7 +1604,7 @@ description = "check built-in string functions"
[[queries]] [[queries]]
name = "indexOf7" name = "indexOf7"
query = ''' query = '''
file where opcode=0 and indexOf(file_name, 'thing that never happened') != null file where opcode=0 and indexOf(file_name, "thing that never happened") != null
''' '''
expected_event_ids = [] expected_event_ids = []
description = "check built-in string functions" description = "check built-in string functions"
@ -1613,7 +1613,7 @@ description = "check built-in string functions"
name = "indexOf8" name = "indexOf8"
case_insensitive = true case_insensitive = true
query = ''' query = '''
file where opcode=0 and indexOf(file_name, 'plorer.', 2) == 2 file where opcode=0 and indexOf(file_name, "plorer.", 2) == 2
''' '''
expected_event_ids = [88, 92] expected_event_ids = [88, 92]
description = "check substring ranges" description = "check substring ranges"
@ -1622,7 +1622,7 @@ description = "check substring ranges"
name = "indexOf9" name = "indexOf9"
case_sensitive = true case_sensitive = true
query = ''' query = '''
file where opcode=0 and indexOf(file_name, 'plorer.', 2) == 2 file where opcode=0 and indexOf(file_name, "plorer.", 2) == 2
''' '''
expected_event_ids = [88] expected_event_ids = [88]
description = "check substring ranges" description = "check substring ranges"
@ -1631,7 +1631,7 @@ description = "check substring ranges"
name = "indexOf10" name = "indexOf10"
case_sensitive = true case_sensitive = true
query = ''' query = '''
file where opcode=0 and indexOf(file_name, 'explorer.', 0) == 0 file where opcode=0 and indexOf(file_name, "explorer.", 0) == 0
''' '''
expected_event_ids = [88] expected_event_ids = [88]
description = "check substring ranges" description = "check substring ranges"
@ -1640,7 +1640,7 @@ description = "check substring ranges"
name = "indexOf11" name = "indexOf11"
case_insensitive = true case_insensitive = true
query = ''' query = '''
file where opcode=0 and indexOf(file_name, 'explorer.', 0) == 0 file where opcode=0 and indexOf(file_name, "explorer.", 0) == 0
''' '''
expected_event_ids = [88, 92] expected_event_ids = [88, 92]
description = "check substring ranges" description = "check substring ranges"
@ -1649,7 +1649,7 @@ description = "check substring ranges"
name = "substring1" name = "substring1"
case_insensitive = true case_insensitive = true
query = ''' query = '''
file where serial_event_id=88 and substring(file_name, 0, 4) == 'expl' file where serial_event_id=88 and substring(file_name, 0, 4) == "expl"
''' '''
expected_event_ids = [88] expected_event_ids = [88]
description = "check substring ranges" description = "check substring ranges"
@ -1658,7 +1658,7 @@ description = "check substring ranges"
name = "substring2" name = "substring2"
case_sensitive = true case_sensitive = true
query = ''' query = '''
file where substring(file_name, 1, 3) == 'xp' file where substring(file_name, 1, 3) == "xp"
''' '''
expected_event_ids = [88, 91] expected_event_ids = [88, 91]
description = "check substring ranges" description = "check substring ranges"
@ -1667,7 +1667,7 @@ description = "check substring ranges"
name = "substring3" name = "substring3"
case_insensitive = true case_insensitive = true
query = ''' query = '''
file where substring(file_name, 1, 3) == 'xp' file where substring(file_name, 1, 3) == "xp"
''' '''
expected_event_ids = [88, 91, 92] expected_event_ids = [88, 91, 92]
description = "check substring ranges" description = "check substring ranges"
@ -1675,7 +1675,7 @@ description = "check substring ranges"
[[queries]] [[queries]]
name = "substring4" name = "substring4"
query = ''' query = '''
file where substring(file_name, -4) == '.exe' file where substring(file_name, -4) == ".exe"
''' '''
expected_event_ids = [55, 59, 61, 65, 67, 70, 72, 75, 76, 81, 83, 86, 88, 91] expected_event_ids = [55, 59, 61, 65, 67, 70, 72, 75, 76, 81, 83, 86, 88, 91]
description = "check substring ranges" description = "check substring ranges"
@ -1683,7 +1683,7 @@ description = "check substring ranges"
[[queries]] [[queries]]
name = "substring5" name = "substring5"
query = ''' query = '''
file where substring(file_name, -4, -1) == '.ex' file where substring(file_name, -4, -1) == ".ex"
''' '''
expected_event_ids = [55, 59, 61, 65, 67, 70, 72, 75, 76, 81, 83, 86, 88, 91] expected_event_ids = [55, 59, 61, 65, 67, 70, 72, 75, 76, 81, 83, 86, 88, 91]
description = "check substring ranges" description = "check substring ranges"
@ -1723,7 +1723,7 @@ description = "test built-in math functions"
[[queries]] [[queries]]
name = "stringNumberConversion1" name = "stringNumberConversion1"
query = ''' query = '''
process where serial_event_id == number('5') process where serial_event_id == number("5")
''' '''
expected_event_ids = [5] expected_event_ids = [5]
description = "test string/number conversions" description = "test string/number conversions"
@ -1733,7 +1733,7 @@ name = "stringNumberConversion2"
expected_event_ids = [50] expected_event_ids = [50]
description = "test string/number conversions" description = "test string/number conversions"
query = ''' query = '''
process where serial_event_id == number('0x32', 16) process where serial_event_id == number("0x32", 16)
''' '''
[[queries]] [[queries]]
@ -1741,13 +1741,13 @@ name = "stringNumberConversion3"
expected_event_ids = [50] expected_event_ids = [50]
description = "test string/number conversions" description = "test string/number conversions"
query = ''' query = '''
process where serial_event_id == number('32', 16) process where serial_event_id == number("32", 16)
''' '''
[[queries]] [[queries]]
name = "concat1" name = "concat1"
query = ''' query = '''
process where concat(serial_event_id, ':', process_name, opcode) == '5:wininit.exe3' process where concat(serial_event_id, ":", process_name, opcode) == "5:wininit.exe3"
''' '''
expected_event_ids = [5] expected_event_ids = [5]
description = "test string concatenation" description = "test string concatenation"
@ -1756,7 +1756,7 @@ description = "test string concatenation"
name = "concatCaseInsensitive" name = "concatCaseInsensitive"
case_insensitive = true case_insensitive = true
query = ''' query = '''
process where concat(serial_event_id, ':', process_name, opcode) == '5:winINIT.exe3' process where concat(serial_event_id, ":", process_name, opcode) == "5:winINIT.exe3"
''' '''
expected_event_ids = [5] expected_event_ids = [5]
description = "test string concatenation" description = "test string concatenation"
@ -1776,7 +1776,7 @@ name = "arraySearch1"
expected_event_ids = [57] expected_event_ids = [57]
description = "test arraySearch functionality for lists of strings, and lists of objects" description = "test arraySearch functionality for lists of strings, and lists of objects"
query = ''' query = '''
registry where arraySearch(bytes_written_string_list, a, a == 'en-US') registry where arraySearch(bytes_written_string_list, a, a == "en-US")
''' '''
[[queries]] [[queries]]
@ -1785,7 +1785,7 @@ case_sensitive = true
expected_event_ids = [] expected_event_ids = []
description = "test arraySearch functionality for lists of strings, and lists of objects" description = "test arraySearch functionality for lists of strings, and lists of objects"
query = ''' query = '''
registry where arraySearch(bytes_written_string_list, a, a == 'EN-US') registry where arraySearch(bytes_written_string_list, a, a == "EN-US")
''' '''
[[queries]] [[queries]]
@ -1794,7 +1794,7 @@ case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
description = "test arraySearch functionality for lists of strings, and lists of objects" description = "test arraySearch functionality for lists of strings, and lists of objects"
query = ''' query = '''
registry where arraySearch(bytes_written_string_list, a, a == 'en-us') registry where arraySearch(bytes_written_string_list, a, a == "en-us")
''' '''
[[queries]] [[queries]]
@ -1803,7 +1803,7 @@ case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
description = "test arraySearch functionality for lists of strings, and lists of objects" description = "test arraySearch functionality for lists of strings, and lists of objects"
query = ''' query = '''
registry where arraySearch(bytes_written_string_list, a, endsWith(a, '-us')) registry where arraySearch(bytes_written_string_list, a, endsWith(a, "-us"))
''' '''
[[queries]] [[queries]]
@ -1828,7 +1828,7 @@ name = "arraySearchWithMysteriousField3"
expected_event_ids = [75305] expected_event_ids = [75305]
description = "test arraySearch - conditional" description = "test arraySearch - conditional"
query = ''' query = '''
network where mysterious_field and arraySearch(mysterious_field.subarray, s, s.a == 's0-*') network where mysterious_field and arraySearch(mysterious_field.subarray, s, s.a == "s0-*")
''' '''
[[queries]] [[queries]]
@ -1836,7 +1836,7 @@ name = "arraySearchWithMysteriousField4"
expected_event_ids = [75305] expected_event_ids = [75305]
description = "test arraySearch - conditional" description = "test arraySearch - conditional"
query = ''' query = '''
network where mysterious_field and arraySearch(mysterious_field.subarray, s, s.a != 's0-*') network where mysterious_field and arraySearch(mysterious_field.subarray, s, s.a != "s0-*")
''' '''
[[queries]] [[queries]]
@ -1846,7 +1846,7 @@ description = "test arraySearch - nested"
query = ''' query = '''
network where mysterious_field network where mysterious_field
and arraySearch(mysterious_field.subarray, sub1, and arraySearch(mysterious_field.subarray, sub1,
arraySearch(sub1.c, nested, nested.x.y == '*')) arraySearch(sub1.c, nested, nested.x.y == "*"))
''' '''
[[queries]] [[queries]]
@ -1856,7 +1856,7 @@ description = "test arraySearch - nested with cross-check pass"
query = ''' query = '''
network where mysterious_field network where mysterious_field
and arraySearch(mysterious_field.subarray, sub1, and arraySearch(mysterious_field.subarray, sub1,
sub1.a == 's0-a' and arraySearch(sub1.c, nested, nested.z == 's0-c1-x-z')) sub1.a == "s0-a" and arraySearch(sub1.c, nested, nested.z == "s0-c1-x-z"))
''' '''
[[queries]] [[queries]]
@ -1866,7 +1866,7 @@ description = "test arraySearch - nested with cross-check pass"
query = ''' query = '''
network where mysterious_field network where mysterious_field
and arraySearch(mysterious_field.subarray, sub1, and arraySearch(mysterious_field.subarray, sub1,
sub1.a == 's0-a' and arraySearch(sub1.c, nested, nested.z == sub1.cross_match)) sub1.a == "s0-a" and arraySearch(sub1.c, nested, nested.z == sub1.cross_match))
''' '''
[[queries]] [[queries]]
@ -1891,7 +1891,7 @@ network where safe(divide(process_name, process_name))
name = "nestedSetComparisons" name = "nestedSetComparisons"
case_insensitive = true case_insensitive = true
query = ''' query = '''
file where serial_event_id == 82 and (true == (process_name in ('svchost.EXE', 'bad.exe', 'bad2.exe'))) file where serial_event_id == 82 and (true == (process_name in ("svchost.EXE", "bad.exe", "bad2.exe")))
''' '''
expected_event_ids = [82] expected_event_ids = [82]
description = "nested set comparisons" description = "nested set comparisons"
@ -1901,7 +1901,7 @@ name = "arrayCount1"
case_insensitive = true case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayCount(bytes_written_string_list, s, s == '*-us') == 1 registry where arrayCount(bytes_written_string_list, s, s == "*-us") == 1
''' '''
[[queries]] [[queries]]
@ -1909,7 +1909,7 @@ name = "arrayCount2"
case_insensitive = true case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayCount(bytes_written_string_list, s, s == '*en*') == 2 registry where arrayCount(bytes_written_string_list, s, s == "*en*") == 2
''' '''
[[queries]] [[queries]]
@ -2037,7 +2037,7 @@ name = "lengthCaseSensitive"
case_sensitive = true case_sensitive = true
expected_event_ids = [7, 14, 29, 44] expected_event_ids = [7, 14, 29, 44]
query = ''' query = '''
process where length(between(process_name, 'g', 'e')) > 0 process where length(between(process_name, "g", "e")) > 0
''' '''
[[queries]] [[queries]]
@ -2045,12 +2045,12 @@ name = "lengthCaseInsensitiveAndBetween"
case_insensitive = true case_insensitive = true
expected_event_ids = [7, 14, 22, 29, 44] expected_event_ids = [7, 14, 22, 29, 44]
query = ''' query = '''
process where length(between(process_name, 'g', 'e')) > 0 process where length(between(process_name, "g", "e")) > 0
''' '''
[[queries]] [[queries]]
name = "length1" name = "length1"
expected_event_ids = [] expected_event_ids = []
query = ''' query = '''
process where length(between(process_name, 'g', 'z')) > 0 process where length(between(process_name, "g", "z")) > 0
''' '''

View file

@ -719,7 +719,7 @@ name = "arrayContainsCaseInsensitive1"
case_insensitive = true case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayContains(bytes_written_string_list, 'En-uS') registry where arrayContains(bytes_written_string_list, "En-uS")
''' '''
[[queries]] [[queries]]
@ -727,7 +727,7 @@ name = "arrayContainsCaseInsensitive2"
case_insensitive = true case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayContains(bytes_written_string_list, 'En') registry where arrayContains(bytes_written_string_list, "En")
''' '''
[[queries]] [[queries]]
@ -735,7 +735,7 @@ name = "lengthCaseInsensitive"
case_insensitive = true case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where length(bytes_written_string_list) > 0 and bytes_written_string_list[0] == 'EN-us' registry where length(bytes_written_string_list) > 0 and bytes_written_string_list[0] == "EN-us"
''' '''
[[queries]] [[queries]]
@ -743,7 +743,7 @@ name = "arrayCaseInsensitive1"
case_insensitive = true case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where bytes_written_string_list[0] == 'EN-us' registry where bytes_written_string_list[0] == "EN-us"
''' '''
[[queries]] [[queries]]
@ -751,7 +751,7 @@ name = "arrayCaseInsensitive2"
case_insensitive = true case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where bytes_written_string_list[1] == 'EN' registry where bytes_written_string_list[1] == "EN"
''' '''
@ -760,7 +760,7 @@ name = "arrayContainsCaseInsensitive3"
case_insensitive = true case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayContains(bytes_written_string_list, 'en-US') registry where arrayContains(bytes_written_string_list, "en-US")
''' '''
[[queries]] [[queries]]
@ -768,7 +768,7 @@ name = "arrayContainsCaseInsensitive4"
case_insensitive = true case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayContains(bytes_written_string_list, 'en') registry where arrayContains(bytes_written_string_list, "en")
''' '''
[[queries]] [[queries]]
@ -776,42 +776,42 @@ name = "arrayCaseInsensitive3"
case_insensitive = true case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where length(bytes_written_string_list) > 0 and bytes_written_string_list[0] == 'en-US' registry where length(bytes_written_string_list) > 0 and bytes_written_string_list[0] == "en-US"
''' '''
[[queries]] [[queries]]
name = "arrayEquality1" name = "arrayEquality1"
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where bytes_written_string_list[0] == 'en-US' registry where bytes_written_string_list[0] == "en-US"
''' '''
[[queries]] [[queries]]
name = "arrayEquality2" name = "arrayEquality2"
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where bytes_written_string_list[1] == 'en' registry where bytes_written_string_list[1] == "en"
''' '''
# character classes aren't supported. custom tests made in test_queries_supported.toml # character classes aren't supported. custom tests made in test_queries_supported.toml
[[queries]] [[queries]]
name = "matchLite1" name = "matchLite1"
query = ''' query = '''
process where matchLite(command_line, ?'.*?net1\s+localgroup\s+.*?') process where matchLite(command_line, ?".*?net1\s+localgroup\s+.*?")
''' '''
expected_event_ids = [98] expected_event_ids = [98]
[[queries]] [[queries]]
name = "matchLite2" name = "matchLite2"
query = ''' query = '''
process where matchLite(command_line, ?'.*?net1\s+\w+\s+.*?') process where matchLite(command_line, ?".*?net1\s+\w+\s+.*?")
''' '''
expected_event_ids = [98] expected_event_ids = [98]
[[queries]] [[queries]]
name = "matchLite3" name = "matchLite3"
query = ''' query = '''
process where matchLite(command_line, ?'.*?net1\s+\w{4,15}\s+.*?') process where matchLite(command_line, ?".*?net1\s+\w{4,15}\s+.*?")
''' '''
expected_event_ids = [98] expected_event_ids = [98]
@ -819,13 +819,13 @@ expected_event_ids = [98]
name = "match1" name = "match1"
expected_event_ids = [98] expected_event_ids = [98]
query = ''' query = '''
process where match(command_line, ?'.*?net1\s+\w{4,15}\s+.*?') process where match(command_line, ?".*?net1\s+\w{4,15}\s+.*?")
''' '''
[[queries]] [[queries]]
name = "matchLite4" name = "matchLite4"
query = ''' query = '''
process where matchLite(command_line, ?'.*?net1\s+[localgrup]{4,15}\s+.*?') process where matchLite(command_line, ?".*?net1\s+[localgrup]{4,15}\s+.*?")
''' '''
expected_event_ids = [98] expected_event_ids = [98]
@ -833,7 +833,7 @@ expected_event_ids = [98]
name = "stringEqualsCaseInsensitive1" name = "stringEqualsCaseInsensitive1"
case_insensitive = true case_insensitive = true
query = ''' query = '''
process where 'net.EXE' == original_file_name process where "net.EXE" == original_file_name
| filter process_name="net*.exe" | filter process_name="net*.exe"
''' '''
expected_event_ids = [97] expected_event_ids = [97]
@ -843,7 +843,7 @@ note = "check that case insensitive comparisons are performed even for lhs strin
name = "stringEqualsCaseInsensitive2" name = "stringEqualsCaseInsensitive2"
case_insensitive = true case_insensitive = true
query = ''' query = '''
process where process_name == original_file_name and process_name='net*.exe' process where process_name == original_file_name and process_name="net*.exe"
''' '''
expected_event_ids = [97, 98] expected_event_ids = [97, 98]
note = "check that case insensitive comparisons are performed for fields." note = "check that case insensitive comparisons are performed for fields."
@ -861,7 +861,7 @@ description = "check that case insensitive comparisons are performed for fields.
name = "substring3" name = "substring3"
case_insensitive = true case_insensitive = true
query = ''' query = '''
file where substring(file_name, 1, 3) == 'xp' file where substring(file_name, 1, 3) == "xp"
''' '''
expected_event_ids = [88, 91, 92] expected_event_ids = [88, 91, 92]
description = "check substring ranges" description = "check substring ranges"
@ -878,7 +878,7 @@ description = "test built-in math functions"
name = "concatCaseInsensitive" name = "concatCaseInsensitive"
case_insensitive = true case_insensitive = true
query = ''' query = '''
process where concat(serial_event_id, ':', process_name, opcode) == '5:winINIT.exe3' process where concat(serial_event_id, ":", process_name, opcode) == "5:winINIT.exe3"
''' '''
expected_event_ids = [5] expected_event_ids = [5]
description = "test string concatenation" description = "test string concatenation"
@ -898,7 +898,7 @@ name = "arraySearch1"
expected_event_ids = [57] expected_event_ids = [57]
description = "test arraySearch functionality for lists of strings, and lists of objects" description = "test arraySearch functionality for lists of strings, and lists of objects"
query = ''' query = '''
registry where arraySearch(bytes_written_string_list, a, a == 'en-US') registry where arraySearch(bytes_written_string_list, a, a == "en-US")
''' '''
[[queries]] [[queries]]
@ -907,7 +907,7 @@ case_sensitive = true
expected_event_ids = [] expected_event_ids = []
description = "test arraySearch functionality for lists of strings, and lists of objects" description = "test arraySearch functionality for lists of strings, and lists of objects"
query = ''' query = '''
registry where arraySearch(bytes_written_string_list, a, a == 'EN-US') registry where arraySearch(bytes_written_string_list, a, a == "EN-US")
''' '''
[[queries]] [[queries]]
@ -916,7 +916,7 @@ case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
description = "test arraySearch functionality for lists of strings, and lists of objects" description = "test arraySearch functionality for lists of strings, and lists of objects"
query = ''' query = '''
registry where arraySearch(bytes_written_string_list, a, a == 'en-us') registry where arraySearch(bytes_written_string_list, a, a == "en-us")
''' '''
[[queries]] [[queries]]
@ -925,7 +925,7 @@ case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
description = "test arraySearch functionality for lists of strings, and lists of objects" description = "test arraySearch functionality for lists of strings, and lists of objects"
query = ''' query = '''
registry where arraySearch(bytes_written_string_list, a, endsWith(a, '-us')) registry where arraySearch(bytes_written_string_list, a, endsWith(a, "-us"))
''' '''
[[queries]] [[queries]]
@ -950,7 +950,7 @@ name = "arraySearchWithMysteriousField3"
expected_event_ids = [75305] expected_event_ids = [75305]
description = "test arraySearch - conditional" description = "test arraySearch - conditional"
query = ''' query = '''
network where mysterious_field and arraySearch(mysterious_field.subarray, s, s.a == 's0-*') network where mysterious_field and arraySearch(mysterious_field.subarray, s, s.a == "s0-*")
''' '''
[[queries]] [[queries]]
@ -958,7 +958,7 @@ name = "arraySearchWithMysteriousField4"
expected_event_ids = [75305] expected_event_ids = [75305]
description = "test arraySearch - conditional" description = "test arraySearch - conditional"
query = ''' query = '''
network where mysterious_field and arraySearch(mysterious_field.subarray, s, s.a != 's0-*') network where mysterious_field and arraySearch(mysterious_field.subarray, s, s.a != "s0-*")
''' '''
[[queries]] [[queries]]
@ -968,7 +968,7 @@ description = "test arraySearch - nested"
query = ''' query = '''
network where mysterious_field network where mysterious_field
and arraySearch(mysterious_field.subarray, sub1, and arraySearch(mysterious_field.subarray, sub1,
arraySearch(sub1.c, nested, nested.x.y == '*')) arraySearch(sub1.c, nested, nested.x.y == "*"))
''' '''
[[queries]] [[queries]]
@ -978,7 +978,7 @@ description = "test arraySearch - nested with cross-check pass"
query = ''' query = '''
network where mysterious_field network where mysterious_field
and arraySearch(mysterious_field.subarray, sub1, and arraySearch(mysterious_field.subarray, sub1,
sub1.a == 's0-a' and arraySearch(sub1.c, nested, nested.z == 's0-c1-x-z')) sub1.a == "s0-a" and arraySearch(sub1.c, nested, nested.z == "s0-c1-x-z"))
''' '''
[[queries]] [[queries]]
@ -988,7 +988,7 @@ description = "test arraySearch - nested with cross-check pass"
query = ''' query = '''
network where mysterious_field network where mysterious_field
and arraySearch(mysterious_field.subarray, sub1, and arraySearch(mysterious_field.subarray, sub1,
sub1.a == 's0-a' and arraySearch(sub1.c, nested, nested.z == sub1.cross_match)) sub1.a == "s0-a" and arraySearch(sub1.c, nested, nested.z == sub1.cross_match))
''' '''
[[queries]] [[queries]]
@ -1013,7 +1013,7 @@ network where safe(divide(process_name, process_name))
name = "nestedSetComparisons" name = "nestedSetComparisons"
case_insensitive = true case_insensitive = true
query = ''' query = '''
file where serial_event_id == 82 and (true == (process_name in ('svchost.EXE', 'bad.exe', 'bad2.exe'))) file where serial_event_id == 82 and (true == (process_name in ("svchost.EXE", "bad.exe", "bad2.exe")))
''' '''
expected_event_ids = [82] expected_event_ids = [82]
description = "nested set comparisons" description = "nested set comparisons"
@ -1023,7 +1023,7 @@ name = "arrayCount1"
case_insensitive = true case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayCount(bytes_written_string_list, s, s == '*-us') == 1 registry where arrayCount(bytes_written_string_list, s, s == "*-us") == 1
''' '''
[[queries]] [[queries]]
@ -1031,7 +1031,7 @@ name = "arrayCount2"
case_insensitive = true case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayCount(bytes_written_string_list, s, s == '*en*') == 2 registry where arrayCount(bytes_written_string_list, s, s == "*en*") == 2
''' '''
[[queries]] [[queries]]
@ -1081,7 +1081,7 @@ name = "lengthCaseSensitive"
case_sensitive = true case_sensitive = true
expected_event_ids = [7, 14, 29, 44] expected_event_ids = [7, 14, 29, 44]
query = ''' query = '''
process where length(between(process_name, 'g', 'e')) > 0 process where length(between(process_name, "g", "e")) > 0
''' '''
# TODO: add toggles to this function so it's not always insensitive # TODO: add toggles to this function so it's not always insensitive
@ -1090,6 +1090,6 @@ process where length(between(process_name, 'g', 'e')) > 0
#case_insensitive = true #case_insensitive = true
#expected_event_ids = [7, 14, 22, 29, 44] #expected_event_ids = [7, 14, 22, 29, 44]
#query = ''' #query = '''
#process where length(between(process_name, 'g', 'e')) > 0 #process where length(between(process_name, "g", "e")) > 0
#''' #'''

View file

@ -39,7 +39,7 @@ setup:
eql.search: eql.search:
index: eql_test index: eql_test
body: body:
query: "process where user = 'SYSTEM'" query: 'process where user = "SYSTEM"'
- match: {timed_out: false} - match: {timed_out: false}
- match: {hits.total.value: 3} - match: {hits.total.value: 3}
@ -55,7 +55,7 @@ setup:
eql.search: eql.search:
index: eql_test index: eql_test
body: body:
query: "sequence by user [process where user = 'SYSTEM'] [process where true]" query: 'sequence by user [process where user = "SYSTEM"] [process where true]'
- match: {timed_out: false} - match: {timed_out: false}
- match: {hits.total.value: 2} - match: {hits.total.value: 2}
- match: {hits.total.relation: "eq"} - match: {hits.total.relation: "eq"}
@ -72,7 +72,7 @@ setup:
eql.search: eql.search:
index: eql_test index: eql_test
body: body:
query: "sequence by id [process where user = 'SYSTEM'] [process where true]" query: 'sequence by id [process where user = "SYSTEM"] [process where true]'
- match: {timed_out: false} - match: {timed_out: false}
- match: {hits.total.value: 2} - match: {hits.total.value: 2}
- match: {hits.total.relation: "eq"} - match: {hits.total.relation: "eq"}
@ -89,7 +89,7 @@ setup:
eql.search: eql.search:
index: eql_test index: eql_test
body: body:
query: "sequence by valid [process where user = 'SYSTEM'] [process where true]" query: 'sequence by valid [process where user = "SYSTEM"] [process where true]'
- match: {timed_out: false} - match: {timed_out: false}
- match: {hits.total.value: 1} - match: {hits.total.value: 1}
- match: {hits.total.relation: "eq"} - match: {hits.total.relation: "eq"}
@ -105,7 +105,7 @@ setup:
wait_for_completion_timeout: "0ms" wait_for_completion_timeout: "0ms"
keep_on_completion: true keep_on_completion: true
body: body:
query: "process where user = 'SYSTEM'" query: 'process where user = "SYSTEM"'
- is_true: id - is_true: id
- set: {id: id} - set: {id: id}

View file

@ -115,26 +115,30 @@ abstract class AbstractBuilder extends EqlBaseBaseVisitor<Object> {
return node == null ? null : node.getText(); return node == null ? null : node.getText();
} }
public static String unquoteString(String text) { public static String unquoteString(Source source) {
// remove leading and trailing ' for strings and also eliminate escaped single quotes // remove leading and trailing ' for strings and also eliminate escaped single quotes
String text = source.text();
if (text == null) { if (text == null) {
return null; return null;
} }
// unescaped strings can be interpreted directly // unescaped strings can be interpreted directly
if (text.startsWith("?")) { if (text.startsWith("?")) {
checkForSingleQuotedString(source, text, 1);
return text.substring(2, text.length() - 1); return text.substring(2, text.length() - 1);
} }
checkForSingleQuotedString(source, text, 0);
text = text.substring(1, text.length() - 1); text = text.substring(1, text.length() - 1);
StringBuffer resultString = new StringBuffer(); StringBuffer resultString = new StringBuffer();
Matcher regexMatcher = slashPattern.matcher(text); Matcher regexMatcher = slashPattern.matcher(text);
while (regexMatcher.find()) { while (regexMatcher.find()) {
String source = regexMatcher.group(); String group = regexMatcher.group();
String replacement; String replacement;
switch (source) { switch (group) {
case "\\t": case "\\t":
replacement = "\t"; replacement = "\t";
break; break;
@ -162,7 +166,7 @@ abstract class AbstractBuilder extends EqlBaseBaseVisitor<Object> {
break; break;
default: default:
// unknown escape sequence, pass through as-is // unknown escape sequence, pass through as-is
replacement = source; replacement = group;
} }
regexMatcher.appendReplacement(resultString, replacement); regexMatcher.appendReplacement(resultString, replacement);
@ -173,6 +177,13 @@ abstract class AbstractBuilder extends EqlBaseBaseVisitor<Object> {
return resultString.toString(); return resultString.toString();
} }
private static void checkForSingleQuotedString(Source source, String text, int i) {
if (text.charAt(i) == '\'') {
throw new ParsingException(source,
"Use double quotes [\"] to define string literals, not single quotes [']");
}
}
@Override @Override
public Object visitTerminal(TerminalNode node) { public Object visitTerminal(TerminalNode node) {
Source source = source(node); Source source = source(node);

View file

@ -253,6 +253,7 @@ public class ExpressionBuilder extends IdentifierBuilder {
@Override @Override
public Literal visitString(EqlBaseParser.StringContext ctx) { public Literal visitString(EqlBaseParser.StringContext ctx) {
return new Literal(source(ctx), unquoteString(ctx.getText()), DataTypes.KEYWORD); Source source = source(ctx);
return new Literal(source, unquoteString(source), DataTypes.KEYWORD);
} }
} }

View file

@ -73,7 +73,7 @@ public class VerifierTests extends ESTestCase {
public void testQueryStartsWithNumber() { public void testQueryStartsWithNumber() {
assertEquals("1:1: no viable alternative at input '42'", errorParsing("42 where true")); assertEquals("1:1: no viable alternative at input '42'", errorParsing("42 where true"));
assertEquals("1:1: no viable alternative at input ''42''", errorParsing("'42' where true")); assertEquals("1:1: no viable alternative at input '\"42\"'", errorParsing("\"42\" where true"));
} }
public void testMissingColumn() { public void testMissingColumn() {
@ -100,7 +100,7 @@ public class VerifierTests extends ESTestCase {
// Some functions fail with "Unsupported" message at the parse stage // Some functions fail with "Unsupported" message at the parse stage
public void testArrayFunctionsUnsupported() { public void testArrayFunctionsUnsupported() {
assertEquals("1:16: Unknown function [arrayContains], did you mean [stringcontains]?", assertEquals("1:16: Unknown function [arrayContains], did you mean [stringcontains]?",
error("registry where arrayContains(bytes_written_string_list, 'En')")); error("registry where arrayContains(bytes_written_string_list, \"En\")"));
assertEquals("1:16: Unknown function [arraySearch]", assertEquals("1:16: Unknown function [arraySearch]",
error("registry where arraySearch(bytes_written_string_list, bytes_written_string, true)")); error("registry where arraySearch(bytes_written_string_list, bytes_written_string, true)"));
assertEquals("1:16: Unknown function [arrayCount]", assertEquals("1:16: Unknown function [arrayCount]",
@ -116,13 +116,13 @@ public class VerifierTests extends ESTestCase {
// Test unsupported array indexes // Test unsupported array indexes
public void testArrayIndexesUnsupported() { public void testArrayIndexesUnsupported() {
assertEquals("1:84: Array indexes are not supported", assertEquals("1:84: Array indexes are not supported",
errorParsing("registry where length(bytes_written_string_list) > 0 and bytes_written_string_list[0] == 'EN-us")); errorParsing("registry where length(bytes_written_string_list) > 0 and bytes_written_string_list[0] == \"EN-us"));
} }
// Test valid/supported queries // Test valid/supported queries
public void testQueryOk() { public void testQueryOk() {
// Mismatched type, still ok // Mismatched type, still ok
accept("process where serial_event_id = 'abcdef'"); accept("process where serial_event_id = \"abcdef\"");
// Equals condition // Equals condition
accept("process where serial_event_id = 1"); accept("process where serial_event_id = 1");
@ -143,7 +143,7 @@ public class VerifierTests extends ESTestCase {
" and serial_event_id in (58, 64, 69, 74, 80, 85, 90, 93, 94)"); " and serial_event_id in (58, 64, 69, 74, 80, 85, 90, 93, 94)");
// Combination // Combination
accept("file where serial_event_id == 82 and (true == (process_name in ('svchost.EXE', 'bad.exe', 'bad2.exe')))"); accept("file where serial_event_id == 82 and (true == (process_name in (\"svchost.EXE\", \"bad.exe\", \"bad2.exe\")))");
// String handling // String handling
accept("process where process_path == \"*\\\\MACHINE\\\\SAM\\\\SAM\\\\*\\\\Account\\\\Us*ers\\\\00*03E9\\\\F\""); accept("process where process_path == \"*\\\\MACHINE\\\\SAM\\\\SAM\\\\*\\\\Account\\\\Us*ers\\\\00*03E9\\\\F\"");
@ -156,7 +156,7 @@ public class VerifierTests extends ESTestCase {
accept("file where serial_event_id % 40 == 2"); accept("file where serial_event_id % 40 == 2");
} }
// Test mapping that doesn't have property event.category defined // Test mapping that doesn\"t have property event.category defined
public void testMissingEventCategory() { public void testMissingEventCategory() {
final IndexResolution idxr = loadIndexResolution("mapping-missing-event-category.json"); final IndexResolution idxr = loadIndexResolution("mapping-missing-event-category.json");
assertEquals("1:1: Unknown column [event.category]", error(idxr, "foo where true")); assertEquals("1:1: Unknown column [event.category]", error(idxr, "foo where true"));
@ -167,11 +167,11 @@ public class VerifierTests extends ESTestCase {
// Check unsupported // Check unsupported
assertEquals("1:11: Cannot use field [user_name_alias] with unsupported type [alias]", assertEquals("1:11: Cannot use field [user_name_alias] with unsupported type [alias]",
error(idxr, "foo where user_name_alias == 'bob'")); error(idxr, "foo where user_name_alias == \"bob\""));
// Check alias name typo // Check alias name typo
assertEquals("1:11: Unknown column [user_name_alia], did you mean any of [user_name, user_domain]?", assertEquals("1:11: Unknown column [user_name_alia], did you mean any of [user_name, user_domain]?",
error(idxr, "foo where user_name_alia == 'bob'")); error(idxr, "foo where user_name_alia == \"bob\""));
} }
// Test all elasticsearch numeric field types // Test all elasticsearch numeric field types
@ -193,45 +193,45 @@ public class VerifierTests extends ESTestCase {
public void testNoDoc() { public void testNoDoc() {
final IndexResolution idxr = loadIndexResolution("mapping-nodoc.json"); final IndexResolution idxr = loadIndexResolution("mapping-nodoc.json");
accept(idxr, "foo where description_nodoc == ''"); accept(idxr, "foo where description_nodoc == \"\"");
// TODO: add sort test on nodoc field once we have pipes support // TODO: add sort test on nodoc field once we have pipes support
} }
public void testDate() { public void testDate() {
final IndexResolution idxr = loadIndexResolution("mapping-date.json"); final IndexResolution idxr = loadIndexResolution("mapping-date.json");
accept(idxr, "foo where date == ''"); accept(idxr, "foo where date == \"\"");
accept(idxr, "foo where date == '2020-02-02'"); accept(idxr, "foo where date == \"2020-02-02\"");
accept(idxr, "foo where date == '2020-02-41'"); accept(idxr, "foo where date == \"2020-02-41\"");
accept(idxr, "foo where date == '20200241'"); accept(idxr, "foo where date == \"20200241\"");
accept(idxr, "foo where date_with_format == ''"); accept(idxr, "foo where date_with_format == \"\"");
accept(idxr, "foo where date_with_format == '2020-02-02'"); accept(idxr, "foo where date_with_format == \"2020-02-02\"");
accept(idxr, "foo where date_with_format == '2020-02-41'"); accept(idxr, "foo where date_with_format == \"2020-02-41\"");
accept(idxr, "foo where date_with_format == '20200241'"); accept(idxr, "foo where date_with_format == \"20200241\"");
accept(idxr, "foo where date_with_multi_format == ''"); accept(idxr, "foo where date_with_multi_format == \"\"");
accept(idxr, "foo where date_with_multi_format == '2020-02-02'"); accept(idxr, "foo where date_with_multi_format == \"2020-02-02\"");
accept(idxr, "foo where date_with_multi_format == '2020-02-41'"); accept(idxr, "foo where date_with_multi_format == \"2020-02-41\"");
accept(idxr, "foo where date_with_multi_format == '20200241'"); accept(idxr, "foo where date_with_multi_format == \"20200241\"");
accept(idxr, "foo where date_with_multi_format == '11:12:13'"); accept(idxr, "foo where date_with_multi_format == \"11:12:13\"");
// Test query against unsupported field type date_nanos // Test query against unsupported field type date_nanos
assertEquals("1:11: Cannot use field [date_nanos_field] with unsupported type [date_nanos]", assertEquals("1:11: Cannot use field [date_nanos_field] with unsupported type [date_nanos]",
error(idxr, "foo where date_nanos_field == ''")); error(idxr, "foo where date_nanos_field == \"\""));
} }
public void testBoolean() { public void testBoolean() {
final IndexResolution idxr = loadIndexResolution("mapping-boolean.json"); final IndexResolution idxr = loadIndexResolution("mapping-boolean.json");
accept(idxr, "foo where boolean_field == true"); accept(idxr, "foo where boolean_field == true");
accept(idxr, "foo where boolean_field == 'bar'"); accept(idxr, "foo where boolean_field == \"bar\"");
accept(idxr, "foo where boolean_field == 0"); accept(idxr, "foo where boolean_field == 0");
accept(idxr, "foo where boolean_field == 123456"); accept(idxr, "foo where boolean_field == 123456");
} }
public void testBinary() { public void testBinary() {
final IndexResolution idxr = loadIndexResolution("mapping-binary.json"); final IndexResolution idxr = loadIndexResolution("mapping-binary.json");
accept(idxr, "foo where blob == ''"); accept(idxr, "foo where blob == \"\"");
accept(idxr, "foo where blob == 'bar'"); accept(idxr, "foo where blob == \"bar\"");
accept(idxr, "foo where blob == 0"); accept(idxr, "foo where blob == 0");
accept(idxr, "foo where blob == 123456"); accept(idxr, "foo where blob == 123456");
} }
@ -239,23 +239,23 @@ public class VerifierTests extends ESTestCase {
public void testRange() { public void testRange() {
final IndexResolution idxr = loadIndexResolution("mapping-range.json"); final IndexResolution idxr = loadIndexResolution("mapping-range.json");
assertEquals("1:11: Cannot use field [integer_range_field] with unsupported type [integer_range]", assertEquals("1:11: Cannot use field [integer_range_field] with unsupported type [integer_range]",
error(idxr, "foo where integer_range_field == ''")); error(idxr, "foo where integer_range_field == \"\""));
assertEquals("1:11: Cannot use field [float_range_field] with unsupported type [float_range]", assertEquals("1:11: Cannot use field [float_range_field] with unsupported type [float_range]",
error(idxr, "foo where float_range_field == ''")); error(idxr, "foo where float_range_field == \"\""));
assertEquals("1:11: Cannot use field [long_range_field] with unsupported type [long_range]", assertEquals("1:11: Cannot use field [long_range_field] with unsupported type [long_range]",
error(idxr, "foo where long_range_field == ''")); error(idxr, "foo where long_range_field == \"\""));
assertEquals("1:11: Cannot use field [double_range_field] with unsupported type [double_range]", assertEquals("1:11: Cannot use field [double_range_field] with unsupported type [double_range]",
error(idxr, "foo where double_range_field == ''")); error(idxr, "foo where double_range_field == \"\""));
assertEquals("1:11: Cannot use field [date_range_field] with unsupported type [date_range]", assertEquals("1:11: Cannot use field [date_range_field] with unsupported type [date_range]",
error(idxr, "foo where date_range_field == ''")); error(idxr, "foo where date_range_field == \"\""));
assertEquals("1:11: Cannot use field [ip_range_field] with unsupported type [ip_range]", assertEquals("1:11: Cannot use field [ip_range_field] with unsupported type [ip_range]",
error(idxr, "foo where ip_range_field == ''")); error(idxr, "foo where ip_range_field == \"\""));
} }
public void testMixedSet() { public void testMixedSet() {
final IndexResolution idxr = loadIndexResolution("mapping-numeric.json"); final IndexResolution idxr = loadIndexResolution("mapping-numeric.json");
assertEquals("1:11: 2nd argument of [long_field in (1, 'string')] must be [long], found value ['string'] type [keyword]", assertEquals("1:11: 2nd argument of [long_field in (1, \"string\")] must be [long], found value [\"string\"] type [keyword]",
error(idxr, "foo where long_field in (1, 'string')")); error(idxr, "foo where long_field in (1, \"string\")"));
} }
public void testObject() { public void testObject() {
@ -297,32 +297,32 @@ public class VerifierTests extends ESTestCase {
public void testMultiField() { public void testMultiField() {
final IndexResolution idxr = loadIndexResolution("mapping-multi-field.json"); final IndexResolution idxr = loadIndexResolution("mapping-multi-field.json");
accept(idxr, "foo where multi_field.raw == 'bar'"); accept(idxr, "foo where multi_field.raw == \"bar\"");
assertEquals("1:11: [multi_field.english == 'bar'] cannot operate on first argument field of data type [text]: " + assertEquals("1:11: [multi_field.english == \"bar\"] cannot operate on first argument field of data type [text]: " +
"No keyword/multi-field defined exact matches for [english]; define one or use MATCH/QUERY instead", "No keyword/multi-field defined exact matches for [english]; define one or use MATCH/QUERY instead",
error(idxr, "foo where multi_field.english == 'bar'")); error(idxr, "foo where multi_field.english == \"bar\""));
accept(idxr, "foo where multi_field_options.raw == 'bar'"); accept(idxr, "foo where multi_field_options.raw == \"bar\"");
accept(idxr, "foo where multi_field_options.key == 'bar'"); accept(idxr, "foo where multi_field_options.key == \"bar\"");
accept(idxr, "foo where multi_field_ambiguous.one == 'bar'"); accept(idxr, "foo where multi_field_ambiguous.one == \"bar\"");
accept(idxr, "foo where multi_field_ambiguous.two == 'bar'"); accept(idxr, "foo where multi_field_ambiguous.two == \"bar\"");
assertEquals("1:11: [multi_field_ambiguous.normalized == 'bar'] cannot operate on first argument field of data type [keyword]: " + assertEquals("1:11: [multi_field_ambiguous.normalized == \"bar\"] cannot operate on first argument field of data type [keyword]: " +
"Normalized keyword field cannot be used for exact match operations", "Normalized keyword field cannot be used for exact match operations",
error(idxr, "foo where multi_field_ambiguous.normalized == 'bar'")); error(idxr, "foo where multi_field_ambiguous.normalized == \"bar\""));
assertEquals("1:11: Cannot use field [multi_field_nested.dep_name] type [text] with unsupported nested type in hierarchy " + assertEquals("1:11: Cannot use field [multi_field_nested.dep_name] type [text] with unsupported nested type in hierarchy " +
"(field [multi_field_nested])", "(field [multi_field_nested])",
error(idxr, "foo where multi_field_nested.dep_name == 'bar'")); error(idxr, "foo where multi_field_nested.dep_name == \"bar\""));
assertEquals("1:11: Cannot use field [multi_field_nested.dep_id.keyword] type [keyword] with unsupported nested type in " + assertEquals("1:11: Cannot use field [multi_field_nested.dep_id.keyword] type [keyword] with unsupported nested type in " +
"hierarchy (field [multi_field_nested])", "hierarchy (field [multi_field_nested])",
error(idxr, "foo where multi_field_nested.dep_id.keyword == 'bar'")); error(idxr, "foo where multi_field_nested.dep_id.keyword == \"bar\""));
assertEquals("1:11: Cannot use field [multi_field_nested.end_date] type [datetime] with unsupported nested type in " + assertEquals("1:11: Cannot use field [multi_field_nested.end_date] type [datetime] with unsupported nested type in " +
"hierarchy (field [multi_field_nested])", "hierarchy (field [multi_field_nested])",
error(idxr, "foo where multi_field_nested.end_date == ''")); error(idxr, "foo where multi_field_nested.end_date == \"\""));
assertEquals("1:11: Cannot use field [multi_field_nested.start_date] type [datetime] with unsupported nested type in " + assertEquals("1:11: Cannot use field [multi_field_nested.start_date] type [datetime] with unsupported nested type in " +
"hierarchy (field [multi_field_nested])", "hierarchy (field [multi_field_nested])",
error(idxr, "foo where multi_field_nested.start_date == 'bar'")); error(idxr, "foo where multi_field_nested.start_date == \"bar\""));
} }
public void testStringFunctionWithText() { public void testStringFunctionWithText() {
@ -330,6 +330,6 @@ public class VerifierTests extends ESTestCase {
assertEquals("1:15: [string(multi_field.english)] cannot operate on field " + assertEquals("1:15: [string(multi_field.english)] cannot operate on field " +
"of data type [text]: No keyword/multi-field defined exact matches for [english]; " + "of data type [text]: No keyword/multi-field defined exact matches for [english]; " +
"define one or use MATCH/QUERY instead", "define one or use MATCH/QUERY instead",
error(idxr, "process where string(multi_field.english) == 'foo'")); error(idxr, "process where string(multi_field.english) == \"foo\""));
} }
} }

View file

@ -135,8 +135,8 @@ public class OptimizerTests extends ESTestCase {
public void testEqualsWildcard() { public void testEqualsWildcard() {
List<String> tests = Arrays.asList( List<String> tests = Arrays.asList(
"foo where command_line == '* bar *'", "foo where command_line == \"* bar *\"",
"foo where '* bar *' == command_line" "foo where \"* bar *\" == command_line"
); );
for (String q : tests) { for (String q : tests) {
@ -157,8 +157,8 @@ public class OptimizerTests extends ESTestCase {
public void testNotEqualsWildcard() { public void testNotEqualsWildcard() {
List<String> tests = Arrays.asList( List<String> tests = Arrays.asList(
"foo where command_line != '* baz *'", "foo where command_line != \"* baz *\"",
"foo where '* baz *' != command_line" "foo where \"* baz *\" != command_line"
); );
for (String q : tests) { for (String q : tests) {
@ -180,7 +180,7 @@ public class OptimizerTests extends ESTestCase {
} }
public void testWildcardEscapes() { public void testWildcardEscapes() {
LogicalPlan plan = defaultPipes(accept("foo where command_line == '* %bar_ * \\\\ \\n \\r \\t'")); LogicalPlan plan = defaultPipes(accept("foo where command_line == \"* %bar_ * \\\\ \\n \\r \\t\""));
assertTrue(plan instanceof Filter); assertTrue(plan instanceof Filter);
Filter filter = (Filter) plan; Filter filter = (Filter) plan;

View file

@ -23,6 +23,7 @@ import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.In;
import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.LessThan; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.LessThan;
import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.LessThanOrEqual; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.LessThanOrEqual;
import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.NotEquals; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.NotEquals;
import org.elasticsearch.xpack.ql.tree.Source;
import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.ql.type.DataTypes;
import java.util.ArrayList; import java.util.ArrayList;
@ -40,6 +41,10 @@ public class ExpressionTests extends ESTestCase {
private final EqlParser parser = new EqlParser(); private final EqlParser parser = new EqlParser();
private static Source source(String text) {
return new Source(0, 0, text);
}
private Expression expr(String source) { private Expression expr(String source) {
return parser.createExpression(source); return parser.createExpression(source);
} }
@ -52,22 +57,21 @@ public class ExpressionTests extends ESTestCase {
return results; return results;
} }
public void testStrings() { public void testStrings() {
assertEquals("hello\"world", unquoteString("'hello\"world'")); assertEquals("hello\"world", unquoteString(source("\"hello\"world\"")));
assertEquals("hello'world", unquoteString("\"hello'world\"")); assertEquals("hello'world", unquoteString(source("\"hello'world\"")));
assertEquals("hello\nworld", unquoteString("'hello\\nworld'")); assertEquals("hello\nworld", unquoteString(source("\"hello\\nworld\"")));
assertEquals("hello\\\nworld", unquoteString("'hello\\\\\\nworld'")); assertEquals("hello\\\nworld", unquoteString(source("\"hello\\\\\\nworld\"")));
assertEquals("hello\\\"world", unquoteString("'hello\\\\\\\"world'")); assertEquals("hello\\\"world", unquoteString(source("\"hello\\\\\\\"world\"")));
// test for unescaped strings: ?"...." or ?'....' // test for unescaped strings: ?"...."
assertEquals("hello\"world", unquoteString("?'hello\"world'")); assertEquals("hello\"world", unquoteString(source("?\"hello\"world\"")));
assertEquals("hello\\\"world", unquoteString("?'hello\\\"world'")); assertEquals("hello\\\"world", unquoteString(source("?\"hello\\\"world\"")));
assertEquals("hello'world", unquoteString("?\"hello'world\"")); assertEquals("hello'world", unquoteString(source("?\"hello'world\"")));
assertEquals("hello\\nworld", unquoteString("?'hello\\nworld'")); assertEquals("hello\\nworld", unquoteString(source("?\"hello\\nworld\"")));
assertEquals("hello\\\\nworld", unquoteString("?'hello\\\\nworld'")); assertEquals("hello\\\\nworld", unquoteString(source("?\"hello\\\\nworld\"")));
assertEquals("hello\\\\\\nworld", unquoteString("?'hello\\\\\\nworld'")); assertEquals("hello\\\\\\nworld", unquoteString(source("?\"hello\\\\\\nworld\"")));
assertEquals("hello\\\\\\\"world", unquoteString("?'hello\\\\\\\"world'")); assertEquals("hello\\\\\\\"world", unquoteString(source("?\"hello\\\\\\\"world\"")));
} }
public void testLiterals() { public void testLiterals() {
@ -76,11 +80,13 @@ public class ExpressionTests extends ESTestCase {
assertEquals(Literal.NULL, expr("null")); assertEquals(Literal.NULL, expr("null"));
} }
public void testSingleQuotedString() { public void testSingleQuotedStringForbidden() {
// "hello \" world" ParsingException e = expectThrows(ParsingException.class, () -> expr("'hello world'"));
Expression parsed = expr("'hello \\' world!'"); assertEquals("line 1:2: Use double quotes [\"] to define string literals, not single quotes [']",
Expression expected = new Literal(null, "hello ' world!", DataTypes.KEYWORD); e.getMessage());
assertEquals(expected, parsed); e = expectThrows(ParsingException.class, () -> parser.createStatement("process where name='hello world'"));
assertEquals("line 1:21: Use double quotes [\"] to define string literals, not single quotes [']",
e.getMessage());
} }
public void testDoubleQuotedString() { public void testDoubleQuotedString() {
@ -90,11 +96,13 @@ public class ExpressionTests extends ESTestCase {
assertEquals(expected, parsed); assertEquals(expected, parsed);
} }
public void testSingleQuotedUnescapedString() { public void testSingleQuotedUnescapedStringForbidden() {
// "hello \" world" ParsingException e = expectThrows(ParsingException.class, () -> expr("?'hello world'"));
Expression parsed = expr("?'hello \\' world!'"); assertEquals("line 1:2: Use double quotes [\"] to define string literals, not single quotes [']",
Expression expected = new Literal(null, "hello \\' world!", DataTypes.KEYWORD); e.getMessage());
assertEquals(expected, parsed); e = expectThrows(ParsingException.class, () -> parser.createStatement("process where name=?'hello world'"));
assertEquals("line 1:21: Use double quotes [\"] to define string literals, not single quotes [']",
e.getMessage());
} }
public void testDoubleQuotedUnescapedString() { public void testDoubleQuotedUnescapedString() {
@ -135,7 +143,7 @@ public class ExpressionTests extends ESTestCase {
UnresolvedFunction.ResolutionType resolutionType = UnresolvedFunction.ResolutionType.STANDARD; UnresolvedFunction.ResolutionType resolutionType = UnresolvedFunction.ResolutionType.STANDARD;
Expression expected = new UnresolvedFunction(null, "concat", resolutionType, arguments); Expression expected = new UnresolvedFunction(null, "concat", resolutionType, arguments);
assertEquals(expected, expr("concat(some.field, 'test string')")); assertEquals(expected, expr("concat(some.field, \"test string\")"));
} }
public void testComparison() { public void testComparison() {
@ -154,8 +162,8 @@ public class ExpressionTests extends ESTestCase {
} }
public void testBoolean() { public void testBoolean() {
String leftText = "process_name == 'net.exe'"; String leftText = "process_name == \"net.exe\"";
String rightText = "command_line == '* localgroup*'"; String rightText = "command_line == \"* localgroup*\"";
Expression lhs = expr(leftText); Expression lhs = expr(leftText);
Expression rhs = expr(rightText); Expression rhs = expr(rightText);
@ -178,13 +186,13 @@ public class ExpressionTests extends ESTestCase {
new In(null, expr("name"), exprs("2", "1")) new In(null, expr("name"), exprs("2", "1"))
); );
assertEquals( assertEquals(
expr("name in ('net.exe')"), expr("name in (\"net.exe\")"),
new In(null, expr("name"), exprs("'net.exe'")) new In(null, expr("name"), exprs("\"net.exe\""))
); );
assertEquals( assertEquals(
expr("name in ('net.exe', 'whoami.exe', 'hostname.exe')"), expr("name in (\"net.exe\", \"whoami.exe\", \"hostname.exe\")"),
new In(null, expr("name"), exprs("'net.exe'", "'whoami.exe'", "'hostname.exe'")) new In(null, expr("name"), exprs("\"net.exe\"", "\"whoami.exe\"", "\"hostname.exe\""))
); );
} }
@ -195,17 +203,17 @@ public class ExpressionTests extends ESTestCase {
); );
assertEquals( assertEquals(
expr("name in ('net.exe', 'net.exe')"), expr("name in (\"net.exe\", \"net.exe\")"),
new In(null, expr("name"), exprs("'net.exe'", "'net.exe'")) new In(null, expr("name"), exprs("\"net.exe\"", "\"net.exe\""))
); );
} }
public void testNotInSet() { public void testNotInSet() {
assertEquals( assertEquals(
expr("name not in ('net.exe', 'whoami.exe', 'hostname.exe')"), expr("name not in (\"net.exe\", \"whoami.exe\", \"hostname.exe\")"),
new Not(null, new In(null, new Not(null, new In(null,
expr("name"), expr("name"),
exprs("'net.exe'", "'whoami.exe'", "'hostname.exe'"))) exprs("\"net.exe\"", "\"whoami.exe\"", "\"hostname.exe\"")))
); );
} }

View file

@ -53,23 +53,23 @@ public class LogicalPlanTests extends ESTestCase {
} }
public void testAnyQuery() { public void testAnyQuery() {
LogicalPlan fullQuery = parser.createStatement("any where process_name == 'net.exe'"); LogicalPlan fullQuery = parser.createStatement("any where process_name == \"net.exe\"");
Expression fullExpression = expr("process_name == 'net.exe'"); Expression fullExpression = expr("process_name == \"net.exe\"");
assertEquals(wrapFilter(fullExpression), fullQuery); assertEquals(wrapFilter(fullExpression), fullQuery);
} }
public void testEventQuery() { public void testEventQuery() {
LogicalPlan fullQuery = parser.createStatement("process where process_name == 'net.exe'"); LogicalPlan fullQuery = parser.createStatement("process where process_name == \"net.exe\"");
Expression fullExpression = expr("event.category == 'process' and process_name == 'net.exe'"); Expression fullExpression = expr("event.category == \"process\" and process_name == \"net.exe\"");
assertEquals(wrapFilter(fullExpression), fullQuery); assertEquals(wrapFilter(fullExpression), fullQuery);
} }
public void testParameterizedEventQuery() { public void testParameterizedEventQuery() {
ParserParams params = new ParserParams(UTC).fieldEventCategory("myCustomEvent"); ParserParams params = new ParserParams(UTC).fieldEventCategory("myCustomEvent");
LogicalPlan fullQuery = parser.createStatement("process where process_name == 'net.exe'", params); LogicalPlan fullQuery = parser.createStatement("process where process_name == \"net.exe\"", params);
Expression fullExpression = expr("myCustomEvent == 'process' and process_name == 'net.exe'"); Expression fullExpression = expr("myCustomEvent == \"process\" and process_name == \"net.exe\"");
assertEquals(wrapFilter(fullExpression), fullQuery); assertEquals(wrapFilter(fullExpression), fullQuery);
} }
@ -150,4 +150,4 @@ public class LogicalPlanTests extends ESTestCase {
assertTrue(plan instanceof OrderBy); assertTrue(plan instanceof OrderBy);
return ((OrderBy) plan).child(); return ((OrderBy) plan).child();
} }
} }

View file

@ -133,11 +133,11 @@ public class QueryFolderFailTests extends AbstractQueryFolderTestCase {
public void testMatchWithText() { public void testMatchWithText() {
VerificationException e = expectThrows(VerificationException.class, VerificationException e = expectThrows(VerificationException.class,
() -> plan("process where match(plain_text, 'foo.*')")); () -> plan("process where match(plain_text, \"foo.*\")"));
String msg = e.getMessage(); String msg = e.getMessage();
assertEquals("Found 1 problem\n" + assertEquals("Found 1 problem\n" +
"line 1:15: [match(plain_text, 'foo.*')] cannot operate on first argument field of data type [text]: No keyword/multi-field " + "line 1:15: [match(plain_text, \"foo.*\")] cannot operate on first argument field of data type [text]: " +
"defined exact matches for [plain_text]; define one or use MATCH/QUERY instead", msg); "No keyword/multi-field defined exact matches for [plain_text]; define one or use MATCH/QUERY instead", msg);
} }
public void testMatchWithNonString() { public void testMatchWithNonString() {
@ -253,9 +253,9 @@ public class QueryFolderFailTests extends AbstractQueryFolderTestCase {
public void testWildcardWithNumericField() { public void testWildcardWithNumericField() {
VerificationException e = expectThrows(VerificationException.class, VerificationException e = expectThrows(VerificationException.class,
() -> plan("process where wildcard(pid, '*.exe')")); () -> plan("process where wildcard(pid, \"*.exe\")"));
String msg = e.getMessage(); String msg = e.getMessage();
assertEquals("Found 1 problem\n" + assertEquals("Found 1 problem\n" +
"line 1:15: first argument of [wildcard(pid, '*.exe')] must be [string], found value [pid] type [long]", msg); "line 1:15: first argument of [wildcard(pid, \"*.exe\")] must be [string], found value [pid] type [long]", msg);
} }
} }

View file

@ -1,5 +1,5 @@
process where process_name == "svchost.exe" and command_line != "* -k *"; process where process_name == "svchost.exe" and command_line != "* -k *";
process where process_name in ('ipconfig.exe', 'netstat.exe', 'systeminfo.exe', 'route.exe'); process where process_name in ("ipconfig.exe", "netstat.exe", "systeminfo.exe", "route.exe");
process where subtype.create and wildcard(command_line, "*.ost *", "*.pst *") process where subtype.create and wildcard(command_line, "*.ost *", "*.pst *")
; ;
@ -178,66 +178,66 @@ process where command_line == "*%*%*" ;
process where command_line == "%*%*" ; process where command_line == "%*%*" ;
process where match(?'.*?net1\s+localgroup\s+.*?', command_line) process where match(?".*?net1\s+localgroup\s+.*?", command_line)
; ;
process where match(?'.*?net1\s+\w+\s+.*?', command_line) process where match(?".*?net1\s+\w+\s+.*?", command_line)
; ;
process where match(?'.*?net1\s+\w{4,15}\s+.*?', command_line) process where match(?".*?net1\s+\w{4,15}\s+.*?", command_line)
; ;
process where match(?'.*?net1\s+\w{4,15}\s+.*?', command_line) process where match(?".*?net1\s+\w{4,15}\s+.*?", command_line)
; ;
process where match(?'.*?net1\s+[localgrup]{4,15}\s+.*?', command_line) process where match(?".*?net1\s+[localgrup]{4,15}\s+.*?", command_line)
; ;
file where opcode=0 and startsWith(file_name, 'exploRER.') file where opcode=0 and startsWith(file_name, "exploRER.")
; ;
file where opcode=0 and startsWith(file_name, 'expLORER.exe') file where opcode=0 and startsWith(file_name, "expLORER.exe")
; ;
file where opcode=0 and endsWith(file_name, 'loREr.exe'); file where opcode=0 and endsWith(file_name, "loREr.exe");
file where opcode=0 and startsWith(file_name, 'explORER.EXE'); file where opcode=0 and startsWith(file_name, "explORER.EXE");
file where opcode=0 and startsWith('explorer.exeaaaaaaaa', file_name); file where opcode=0 and startsWith("explorer.exeaaaaaaaa", file_name);
file where opcode=0 and serial_event_id = 88 and startsWith('explorer.exeaAAAA', 'EXPLORER.exe'); file where opcode=0 and serial_event_id = 88 and startsWith("explorer.exeaAAAA", "EXPLORER.exe");
file where opcode=0 and stringContains('ABCDEFGHIexplorer.exeJKLMNOP', file_name) file where opcode=0 and stringContains("ABCDEFGHIexplorer.exeJKLMNOP", file_name)
; ;
file where opcode=0 and indexOf(file_name, 'plore') == 2 and not indexOf(file_name, '.pf') file where opcode=0 and indexOf(file_name, "plore") == 2 and not indexOf(file_name, ".pf")
; ;
file where opcode=0 and indexOf(file_name, 'explorer.') and indexOf(file_name, 'plore', 100) file where opcode=0 and indexOf(file_name, "explorer.") and indexOf(file_name, "plore", 100)
; ;
file where opcode=0 and indexOf(file_name, 'plorer.', 0) == 2; file where opcode=0 and indexOf(file_name, "plorer.", 0) == 2;
file where opcode=0 and indexOf(file_name, 'plorer.', 2); file where opcode=0 and indexOf(file_name, "plorer.", 2);
file where opcode=0 and indexOf(file_name, 'plorer.', 4); file where opcode=0 and indexOf(file_name, "plorer.", 4);
file where opcode=0 and indexOf(file_name, 'thing that never happened'); file where opcode=0 and indexOf(file_name, "thing that never happened");
file where opcode=0 and indexOf(file_name, 'plorer.', 2) == 2; file where opcode=0 and indexOf(file_name, "plorer.", 2) == 2;
file where opcode=0 and indexOf(file_name, 'explorer.', 0) == 0; file where opcode=0 and indexOf(file_name, "explorer.", 0) == 0;
file where serial_event_id=88 and substring(file_name, 0, 4) == 'expl' file where serial_event_id=88 and substring(file_name, 0, 4) == "expl"
; ;
file where serial_event_id=88 and substring(file_name, 1, 3) == 'xp' file where serial_event_id=88 and substring(file_name, 1, 3) == "xp"
; ;
file where serial_event_id=88 and substring(file_name, -4) == '.exe' file where serial_event_id=88 and substring(file_name, -4) == ".exe"
; ;
file where serial_event_id=88 and substring(file_name, -4, -1) == '.ex' file where serial_event_id=88 and substring(file_name, -4, -1) == ".ex"
; ;
process where add(serial_event_id, 0) == 1 and add(0, 1) == serial_event_id; process where add(serial_event_id, 0) == 1 and add(0, 1) == serial_event_id;
@ -248,15 +248,15 @@ process where multiply(6, serial_event_id) == 30 and divide(30, 4.0) == 7.5;
process where modulo(11, add(serial_event_id, 1)) == serial_event_id; process where modulo(11, add(serial_event_id, 1)) == serial_event_id;
process where serial_event_id == number('5'); process where serial_event_id == number("5");
process where serial_event_id == number('0x32', 16); process where serial_event_id == number("0x32", 16);
process where serial_event_id == number('32', 16); process where serial_event_id == number("32", 16);
process where number(serial_event_id) == number(5); process where number(serial_event_id) == number(5);
process where concat(serial_event_id, ':', process_name, opcode) == '5:winINIT.exe3' process where concat(serial_event_id, ":", process_name, opcode) == "5:winINIT.exe3"
; ;
@ -264,7 +264,7 @@ process where concat(serial_event_id, ':', process_name, opcode) == '5:winINIT.e
// network where safe(divide(process_name, process_name)) // network where safe(divide(process_name, process_name))
//; //;
file where serial_event_id == 82 and (true == (process_name in ('svchost.EXE', 'bad.exe', 'bad2.exe'))) file where serial_event_id == 82 and (true == (process_name in ("svchost.EXE", "bad.exe", "bad2.exe")))
; ;
@ -315,10 +315,10 @@ network where cidrMatch(source_address, "192.168.0.0/16", "10.6.48.157/8")
network where cidrMatch(source_address, "0.0.0.0/0") network where cidrMatch(source_address, "0.0.0.0/0")
; ;
process where length(between(process_name, 'g', 'e')) > 0 process where length(between(process_name, "g", "e")) > 0
; ;
process where length(between(process_name, 'g', 'z')) > 0 process where length(between(process_name, "g", "z")) > 0
; ;
@ -542,7 +542,7 @@ until [process where opcode=2] by ppid,process_path
; ;
sequence by unique_pid sequence by unique_pid
[process where opcode=1 and process_name == 'msbuild.exe'] [process where opcode=1 and process_name == "msbuild.exe"]
[network where true] [network where true]
; ;
@ -686,4 +686,4 @@ process where fake_field != "*"
| head 4; | head 4;
process where not (fake_field == "*") process where not (fake_field == "*")
| head 4; | head 4;

View file

@ -298,7 +298,7 @@ sequence
; ;
process where 'net.EXE' == original_file_name process where "net.EXE" == original_file_name
| filter process_name="net*.exe" | filter process_name="net*.exe"
; ;

View file

@ -103,14 +103,14 @@ process where cidrMatch(source_address, "10.0.0.0/8") != false
; ;
twoFunctionsEqualsBooleanLiterals-caseSensitive twoFunctionsEqualsBooleanLiterals-caseSensitive
process where endsWith(process_path, 'x') == true and endsWith(process_path, 'yx') == false process where endsWith(process_path, "x") == true and endsWith(process_path, "yx") == false
; ;
{"bool":{"must":[{"wildcard":{"process_path":{"wildcard":"*x","boost":1.0}}}, {"bool":{"must":[{"wildcard":{"process_path":{"wildcard":"*x","boost":1.0}}},
{"bool":{"must_not":[{"wildcard":{"process_path":{"wildcard":"*yx","boost":1.0}}}],"boost":1.0}}],"boost":1.0}} {"bool":{"must_not":[{"wildcard":{"process_path":{"wildcard":"*yx","boost":1.0}}}],"boost":1.0}}],"boost":1.0}}
; ;
twoFunctionsEqualsBooleanLiterals-caseInsensitive twoFunctionsEqualsBooleanLiterals-caseInsensitive
process where endsWith(process_path, 'x') == true and endsWith(process_path, 'yx') == false process where endsWith(process_path, "x") == true and endsWith(process_path, "yx") == false
; ;
"bool":{"must":[{"term":{"event.category":{"value":"process" "bool":{"must":[{"term":{"event.category":{"value":"process"
"must":[{"script":{"script":{"source":"InternalQlScriptUtils.nullSafeFilter( "must":[{"script":{"script":{"source":"InternalQlScriptUtils.nullSafeFilter(
@ -122,21 +122,21 @@ InternalEqlScriptUtils.endsWith(InternalQlScriptUtils.docValue(doc,params.v0),pa
; ;
endsWithKeywordFieldFunction-caseSensitive endsWithKeywordFieldFunction-caseSensitive
process where endsWith(user_name, 'c') process where endsWith(user_name, "c")
; ;
{"bool":{"must":[{"term":{"event.category":{"value":"process","boost":1.0}}}, {"bool":{"must":[{"term":{"event.category":{"value":"process","boost":1.0}}},
{"wildcard":{"user_name":{"wildcard":"*c","boost":1.0}}}],"boost":1.0}} {"wildcard":{"user_name":{"wildcard":"*c","boost":1.0}}}],"boost":1.0}}
; ;
endsWithWildcardSubFieldFunction-caseSensitive endsWithWildcardSubFieldFunction-caseSensitive
process where endsWith(hostname, 'c') process where endsWith(hostname, "c")
; ;
{"bool":{"must":[{"term":{"event.category":{"value":"process","boost":1.0}}}, {"bool":{"must":[{"term":{"event.category":{"value":"process","boost":1.0}}},
{"wildcard":{"hostname.keyword":{"wildcard":"*c","boost":1.0}}}],"boost":1.0}} {"wildcard":{"hostname.keyword":{"wildcard":"*c","boost":1.0}}}],"boost":1.0}}
; ;
endsWithFunction-caseInsensitive endsWithFunction-caseInsensitive
process where endsWith(user_name, 'c') process where endsWith(user_name, "c")
; ;
"script":{"source":"InternalQlScriptUtils.nullSafeFilter(InternalEqlScriptUtils.endsWith( "script":{"source":"InternalQlScriptUtils.nullSafeFilter(InternalEqlScriptUtils.endsWith(
InternalQlScriptUtils.docValue(doc,params.v0),params.v1,params.v2))", InternalQlScriptUtils.docValue(doc,params.v0),params.v1,params.v2))",
@ -168,7 +168,7 @@ InternalEqlScriptUtils.length(InternalQlScriptUtils.docValue(doc,params.v0)),par
; ;
startsWithFunction-caseInsensitive startsWithFunction-caseInsensitive
process where startsWith(user_name, 'A') process where startsWith(user_name, "A")
; ;
"script":{"source":"InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.startsWith( "script":{"source":"InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.startsWith(
InternalQlScriptUtils.docValue(doc,params.v0),params.v1,params.v2))", InternalQlScriptUtils.docValue(doc,params.v0),params.v1,params.v2))",
@ -176,14 +176,14 @@ InternalQlScriptUtils.docValue(doc,params.v0),params.v1,params.v2))",
; ;
startsWithFunctionSimple-caseSensitive startsWithFunctionSimple-caseSensitive
process where startsWith(user_name, 'A') process where startsWith(user_name, "A")
; ;
{"bool":{"must":[{"term":{"event.category":{"value":"process","boost":1.0}}}, {"bool":{"must":[{"term":{"event.category":{"value":"process","boost":1.0}}},
{"prefix":{"user_name":{"value":"A","boost":1.0}}}],"boost":1.0}} {"prefix":{"user_name":{"value":"A","boost":1.0}}}],"boost":1.0}}
; ;
startsWithFunctionWithCondition-caseSensitive startsWithFunctionWithCondition-caseSensitive
process where startsWith(user_name, 'A') or startsWith(user_name, 'B') process where startsWith(user_name, "A") or startsWith(user_name, "B")
; ;
{"bool":{"must":[{"term":{"event.category":{"value":"process","boost":1.0}}}, {"bool":{"must":[{"term":{"event.category":{"value":"process","boost":1.0}}},
{"bool":{"should":[{"prefix":{"user_name":{"value":"A","boost":1.0}}}, {"bool":{"should":[{"prefix":{"user_name":{"value":"A","boost":1.0}}},
@ -222,7 +222,7 @@ InternalEqlScriptUtils.string(InternalQlScriptUtils.docValue(doc,params.v0)),par
; ;
indexOfFunction-caseSensitive indexOfFunction-caseSensitive
process where indexOf(user_name, 'A', 2) > 0 process where indexOf(user_name, "A", 2) > 0
; ;
"script":{"source":"InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.gt( "script":{"source":"InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.gt(
InternalEqlScriptUtils.indexOf(InternalQlScriptUtils.docValue(doc,params.v0),params.v1,params.v2,params.v3),params.v4))", InternalEqlScriptUtils.indexOf(InternalQlScriptUtils.docValue(doc,params.v0),params.v1,params.v2,params.v3),params.v4))",
@ -230,7 +230,7 @@ InternalEqlScriptUtils.indexOf(InternalQlScriptUtils.docValue(doc,params.v0),par
; ;
indexOfFunction-caseInsensitive indexOfFunction-caseInsensitive
process where indexOf(user_name, 'A', 2) > 0 process where indexOf(user_name, "A", 2) > 0
; ;
"script":{"source":"InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.gt( "script":{"source":"InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.gt(
InternalEqlScriptUtils.indexOf(InternalQlScriptUtils.docValue(doc,params.v0),params.v1,params.v2,params.v3),params.v4))", InternalEqlScriptUtils.indexOf(InternalQlScriptUtils.docValue(doc,params.v0),params.v1,params.v2,params.v3),params.v4))",
@ -238,7 +238,7 @@ InternalEqlScriptUtils.indexOf(InternalQlScriptUtils.docValue(doc,params.v0),par
; ;
substringFunction substringFunction
process where substring(file_name, -4) == '.exe' process where substring(file_name, -4) == ".exe"
; ;
"script":{"source":"InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.eq( "script":{"source":"InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.eq(
InternalEqlScriptUtils.substring(InternalQlScriptUtils.docValue(doc,params.v0),params.v1,params.v2),params.v3))", InternalEqlScriptUtils.substring(InternalQlScriptUtils.docValue(doc,params.v0),params.v1,params.v2),params.v3))",

View file

@ -337,15 +337,15 @@ description = "Fold constant check in set"
expected = false expected = false
[[in_set.fold.tests]] [[in_set.fold.tests]]
expression = "'foo' not in ('foo', 'bar', 'baz')" expression = '"foo" not in ("foo", "bar", "baz")'
expected = false expected = false
[[in_set.fold.tests]] [[in_set.fold.tests]]
expression = "'foo' in ('foo', 'bar', 'baz')" expression = '"foo" in ("foo", "bar", "baz")'
expected = true expected = true
[[in_set.fold.tests]] [[in_set.fold.tests]]
expression = "'foo' in ('bar', 'baz')" expression = '"foo" in ("bar", "baz")'
expected = false expected = false
[or] [or]

View file

@ -94,11 +94,11 @@ description = "Test the `concat` function"
description = "Test the `endsWith` function with case matching" description = "Test the `endsWith` function with case matching"
[[endswith.fold.tests]] [[endswith.fold.tests]]
expression = "endsWith('FooBarBaz', 'Baz')" expression = 'endsWith("FooBarBaz", "Baz")'
expected = true expected = true
[[endswith.fold.tests]] [[endswith.fold.tests]]
expression = "endsWith('FooBarBaz', 'Foo')" expression = 'endsWith("FooBarBaz", "Foo")'
expected = false expected = false
@ -107,7 +107,7 @@ description = "Test the `endsWith` function with case insensitivity"
case_insensitive = true case_insensitive = true
[[endswith_insensitive.fold.tests]] [[endswith_insensitive.fold.tests]]
expression = "endsWith('FooBarBaz', 'baz')" expression = 'endsWith("FooBarBaz", "baz")'
expected = true expected = true
@ -116,7 +116,7 @@ description = "Test the `endsWith` function with case sensitivity"
case_sensitive = true case_sensitive = true
[[endswith_sensitive.fold.tests]] [[endswith_sensitive.fold.tests]]
expression = "endsWith('FooBarBaz', 'baz')" expression = 'endsWith("FooBarBaz", "baz")'
expected = false expected = false
@ -295,37 +295,37 @@ description = "Test the `startsWith` function"
expression = "startsWith()" expression = "startsWith()"
[[startswith.verifier.failures]] [[startswith.verifier.failures]]
expression = "startsWith(1, 'FOO')" expression = '''startsWith(1, "FOO")'''
[[startswith.verifier.failures]] [[startswith.verifier.failures]]
expression = "startsWith('FOO', 123)" expression = '''startsWith("FOO", 123)'''
[[startswith.fold.tests]] [[startswith.fold.tests]]
expression = "startsWith('FooBarBaz', null)" expression = '''startsWith("FooBarBaz", null)'''
# expected = null # expected = null
[[startswith.fold.tests]] [[startswith.fold.tests]]
expression = "startsWith(null, 'Foo')" expression = '''startsWith(null, "Foo")'''
# expected = null # expected = null
[[startswith.fold.tests]] [[startswith.fold.tests]]
expression = "startsWith('FooBarBaz', 'Foo')" expression = '''startsWith("FooBarBaz", "Foo")'''
expected = true expected = true
[[startswith.fold.tests]] [[startswith.fold.tests]]
expression = "startsWith('FooBarBaz', '')" expression = '''startsWith("FooBarBaz", "")'''
expected = true expected = true
[[startswith.fold.tests]] [[startswith.fold.tests]]
expression = "startsWith('FooBarBaz', 'FooBar')" expression = '''startsWith("FooBarBaz", "FooBar")'''
expected = true expected = true
[[startswith.fold.tests]] [[startswith.fold.tests]]
expression = "startsWith('FooBarBaz', 'Bar')" expression = '''startsWith("FooBarBaz", "Bar")'''
expected = false expected = false
[[startswith.fold.tests]] [[startswith.fold.tests]]
expression = "startsWith('FooBarBaz', 'Bar')" expression = '''startsWith("FooBarBaz", "Bar")'''
expected = false expected = false
@ -334,31 +334,32 @@ description = "Test the `startsWith` function with case-sensitive matching"
case_sensitive = true case_sensitive = true
[[startswith_case_sensitive.tests]] [[startswith_case_sensitive.tests]]
expression = "startsWith('FooBar', 'Foo')" expression = '''startsWith("FooBar", "Foo")'''
expected = true expected = true
[[startswith_case_sensitive.tests]] [[startswith_case_sensitive.tests]]
expression = "startsWith('FooBar', 'foo')" expression = '''startsWith("FooBar", "foo")'''
expected = false expected = false
[startswith_case_insensitive] [startswith_case_insensitive]
description = "Test the `startsWith` function with case-insensitive matching" description = "Test the `startsWith` function with case-insensitive matching"
case_insensitive = true
[[startswith_case_insensitive.fold.tests]] [[startswith_case_insensitive.fold.tests]]
expression = "startsWith('FooBar', 'Foo')" expression = '''startsWith("FooBar", "Foo")'''
expected = true expected = true
[[startswith_case_insensitive.fold.tests]] [[startswith_case_insensitive.fold.tests]]
expression = "startsWith('FooBar', 'FOO')" expression = '''startsWith("FooBar", "FOO")'''
expected = true expected = true
[[startswith_case_insensitive.fold.tests]] [[startswith_case_insensitive.fold.tests]]
expression = "startsWith('FooBar', 'foo')" expression = '''startsWith("FooBar", "foo")'''
expected = true expected = true
[[startswith_case_insensitive.fold.tests]] [[startswith_case_insensitive.fold.tests]]
expression = "startsWith('FooBar', 'Bar')" expression = '''startsWith("FooBar", "Bar")'''
expected = false expected = false
@ -382,7 +383,7 @@ description = "Test the `string` function"
expected = "2.1828" expected = "2.1828"
[[string.fold.tests]] [[string.fold.tests]]
expression = "string('hello')" expression = '''string("hello")'''
expected = "hello" expected = "hello"
[substring] [substring]
@ -397,55 +398,55 @@ description = "Test the `substring` function when the case already matches"
# expected = null # expected = null
[[substring.fold.tests]] [[substring.fold.tests]]
expression = "substring('hello world', null, null)" expression = '''substring("hello world", null, null)'''
expected = "hello world" expected = "hello world"
[[substring.fold.tests]] [[substring.fold.tests]]
expression = "substring('hello world', 6, null)" expression = '''substring("hello world", 6, null)'''
expected = "world" expected = "world"
[[substring.fold.tests]] [[substring.fold.tests]]
expression = "substring('hello world', null, 5)" expression = '''substring("hello world", null, 5)'''
expected = "hello" expected = "hello"
[[substring.fold.tests]] [[substring.fold.tests]]
expression = "substring('hello world', 0, 5)" expression = '''substring("hello world", 0, 5)'''
expected = "hello" expected = "hello"
[[substring.fold.tests]] [[substring.fold.tests]]
expression = "substring('hello world', 0, 500)" expression = '''substring("hello world", 0, 500)'''
expected = "hello world" expected = "hello world"
[[substring.fold.tests]] [[substring.fold.tests]]
expression = "substring('hello world', 5, -1)" expression = '''substring("hello world", 5, -1)'''
expected = " worl" expected = " worl"
[[substring.fold.tests]] [[substring.fold.tests]]
expression = "substring('hello world', 3, 9)" expression = '''substring("hello world", 3, 9)'''
expected = "lo wor" expected = "lo wor"
[[substring.fold.tests]] [[substring.fold.tests]]
expression = "substring('hello world', -5, null)" expression = '''substring("hello world", -5, null)'''
expected = "world" expected = "world"
[[substring.fold.tests]] [[substring.fold.tests]]
expression = "substring('hello world', -5, 11)" expression = '''substring("hello world", -5, 11)'''
expected = "world" expected = "world"
[[substring.fold.tests]] [[substring.fold.tests]]
expression = "substring('hello world', -5, 100)" expression = '''substring("hello world", -5, 100)'''
expected = "world" expected = "world"
[[substring.fold.tests]] [[substring.fold.tests]]
expression = "substring('hello world', -60, 5)" expression = '''substring("hello world", -60, 5)'''
expected = "hello" expected = "hello"
[[substring.fold.tests]] [[substring.fold.tests]]
expression = "substring('hello world', -5)" expression = '''substring("hello world", -5)'''
expected = "world" expected = "world"
[[substring.fold.tests]] [[substring.fold.tests]]
expression = "substring('hello world', -5, -1)" expression = '''substring("hello world", -5, -1)'''
expected = "worl" expected = "worl"
[wildcard] [wildcard]

View file

@ -127,27 +127,8 @@ case_insensitive = true
expected = false expected = false
[endswith_sensitive]
case_sensitive = true
[[endswith_sensitive.fold.tests]]
expression = "endsWith('FooBarBaz', 'baz')"
expected = false
[startswith_case_insensitive]
[[startswith_case_insensitive.fold.tests]]
expression = "startsWith('FooBar', 'FOO')"
expected = true
[[startswith_case_insensitive.fold.tests]]
expression = "startsWith('FooBar', 'foo')"
expected = true
[substring] [substring]
[[substring.fold.tests]] [[substring.fold.tests]]
expression = "substring('hello world', null, 5)" expression = '''substring("hello world", null, 5)'''
expected = "hello" expected = "hello"

View file

@ -516,7 +516,7 @@
eql.search: eql.search:
index: simple-data-stream1 index: simple-data-stream1
body: body:
query: "process where user = 'SYSTEM'" query: 'process where user = "SYSTEM"'
- match: {timed_out: false} - match: {timed_out: false}
- match: {hits.total.value: 1} - match: {hits.total.value: 1}
@ -527,7 +527,7 @@
eql.search: eql.search:
index: simple-data-s* index: simple-data-s*
body: body:
query: "process where user = 'SYSTEM'" query: 'process where user = "SYSTEM"'
- match: {timed_out: false} - match: {timed_out: false}
- match: {hits.total.value: 1} - match: {hits.total.value: 1}