summaryrefslogtreecommitdiff
path: root/tests/analysis/scan/fuzzing.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/analysis/scan/fuzzing.py')
-rw-r--r--tests/analysis/scan/fuzzing.py289
1 files changed, 289 insertions, 0 deletions
diff --git a/tests/analysis/scan/fuzzing.py b/tests/analysis/scan/fuzzing.py
new file mode 100644
index 0000000..1b9b25b
--- /dev/null
+++ b/tests/analysis/scan/fuzzing.py
@@ -0,0 +1,289 @@
+
+from common import RostTestClass
+from pychrysalide.analysis.contents import MemoryContent
+from pychrysalide.analysis.scan import ContentScanner
+from pychrysalide.analysis.scan import ScanOptions
+from pychrysalide.analysis.scan.patterns.backends import AcismBackend
+from pychrysalide.analysis.scan.patterns.backends import BitapBackend
+
+
+class TestRostFuzzingFixes(RostTestClass):
+ """TestCases to remember all the fixes for crashes identified by fuzzing."""
+
+ def testEmptyPatternListWithContent(self):
+ """Check no backend is run if there is no pattern to look for."""
+
+ content = MemoryContent(b'\n')
+
+ rule = '''
+'''
+
+ backends = [
+ AcismBackend, # This one was segfaulting
+ BitapBackend,
+ ]
+
+ for b in backends:
+
+ options = ScanOptions()
+ options.backend_for_data = b
+
+ scanner = ContentScanner(rule)
+ ctx = scanner.analyze(options, content)
+
+ self.assertIsNotNone(ctx)
+
+
+ def testMandatoryCondition(self):
+ """Ensure a condition section exists in a rule."""
+
+ rule = '''
+rule test {
+
+}
+'''
+
+ with self.assertRaisesRegex(ValueError, 'Unable to create content scanner'):
+
+ scanner = ContentScanner(rule)
+
+
+ def testNonExistingPattern(self):
+ """Avoid to count the matches of a non-existing pattern."""
+
+ rule = '''
+rule test {
+
+ condition:
+ #badid
+
+}
+'''
+
+ with self.assertRaisesRegex(ValueError, 'Unable to create content scanner'):
+
+ scanner = ContentScanner(rule)
+
+
+ def testNamespacesWithoutReductionCode(self):
+ """Clean the code for ROST namespaces."""
+
+ rule = '''
+rule test {
+
+ condition:
+ console
+
+}
+'''
+
+ self.check_rule_failure(rule)
+
+
+ def testCallOnNonCallable(self):
+ """Reject calls on non callable expressions softly."""
+
+ rule = '''
+rule test {
+
+ condition:
+ console.log().log()
+
+}
+'''
+
+ self.check_rule_failure(rule)
+
+
+ def testSelfReferencingRule(self):
+ """Reject any rule referencing itself as match condition."""
+
+ rule = '''
+rule test {
+
+ condition:
+ test
+
+}
+'''
+
+ self.check_rule_failure(rule)
+
+
+ def testSelfReferencingRule(self):
+ """Expect only one argument for the not operator, even in debug mode."""
+
+ rule = '''
+rule test {
+
+ condition:
+ not(0)
+
+}
+'''
+
+ self.check_rule_success(rule)
+
+
+ def testNoCommon(self):
+ """Handle the case where no common item is found from an empty set."""
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = "a"
+
+ condition:
+ maxcommon($a) == 0
+
+}
+'''
+
+ self.check_rule_success(rule)
+
+
+ def testAAsAcharacter(self):
+ """Consider the 'a' character as a valid lowercase character."""
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = "0000a0I0" nocase
+
+ condition:
+ $a
+
+}
+'''
+
+ self.check_rule_failure(rule)
+
+
+ def testAAsAcharacter(self):
+ """Do not expect initialized trackers when there is no real defined search pattern."""
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = {[0]}
+
+ condition:
+ $a
+
+}
+'''
+
+ with self.assertRaisesRegex(ValueError, 'Unable to create content scanner'):
+
+ scanner = ContentScanner(rule)
+
+
+ def testAllocations(self):
+ """Handle big alloctions for strings in conditions with regular expressions."""
+
+ rule = '''
+rule test {
+
+ condition:
+ "%s" == "%s"
+
+}
+''' % ("0" * (256 * 2 + 8), "0" * (256 * 2 + 8))
+
+ self.check_rule_success(rule)
+
+
+ def testFileFinalAccess(self):
+ """Ensure patterns found at the edges of scanned content do not crash the scanner."""
+
+ cnt = MemoryContent(bytes([ 0 for i in range(16) ]))
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = { 00 00 00 00 00 00 00 00 }
+
+ condition:
+ $a
+
+}
+'''
+
+ self.check_rule_success(rule, cnt)
+
+
+ def testValidHexRangeMerge(self):
+ """Merge valid hexadecimal ranges."""
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = { [0] ?? }
+
+ condition:
+ $a
+
+}
+'''
+
+ with self.assertRaisesRegex(ValueError, 'Unable to create content scanner'):
+
+ scanner = ContentScanner(rule)
+
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = { [2] ?? }
+
+ condition:
+ $a
+
+}
+'''
+
+ self.check_rule_failure(rule)
+
+
+ def testSmallBase64(self):
+ """Handle small base64 encodings which may produce few patterns."""
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = "0" base64
+
+ condition:
+ $a
+
+}
+'''
+
+ self.check_rule_failure(rule)
+
+
+ def testCountIndex(self):
+ """Ban pattern count indexes from the grammer."""
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = "1"
+
+ condition:
+ #*[0]
+
+}
+'''
+
+ with self.assertRaisesRegex(ValueError, 'Unable to create content scanner'):
+
+ scanner = ContentScanner(rule)