[Forensics-changes] [yara] 203/368: Port most of the the rule-related tests from yara-python

Hilko Bengen bengen at moszumanska.debian.org
Sat Jul 1 10:30:40 UTC 2017


This is an automated email from the git hooks/post-receive script.

bengen pushed a commit to annotated tag v3.5.0
in repository yara.

commit 485fce9b4474014a639a94477222a6f7b8ae20c1
Author: Hilko Bengen <bengen at hilluzination.de>
Date:   Sat Feb 27 18:42:26 2016 +0100

    Port most of the the rule-related tests from yara-python
    
    The test code for parsing and behavior of the rule engine belongs with
    Yara itself rather than the the Python bindings that have been split
    off. Now the tests can be run again when the library is built.
---
 Makefile.am        |   4 +-
 tests/blob.h       | 167 +++++++++++++++
 tests/test-rules.c | 602 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/util.c       | 112 ++++++++++
 tests/util.h       |  94 +++++++++
 5 files changed, 978 insertions(+), 1 deletion(-)

diff --git a/Makefile.am b/Makefile.am
index a479845..8901d58 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -15,8 +15,10 @@ yarac_SOURCES = args.c args.h yarac.c
 yarac_LDADD = libyara/.libs/libyara.a
 
 TESTS = $(check_PROGRAMS)
-check_PROGRAMS = test-alignment
+check_PROGRAMS = test-alignment test-rules
 test_alignment_SOURCES = tests/test-alignment.c
+test_rules_SOURCES = tests/test-rules.c tests/util.c
+test_rules_LDADD = libyara/.libs/libyara.a
 
 # man pages
 man1_MANS = yara.man yarac.man
diff --git a/tests/blob.h b/tests/blob.h
new file mode 100644
index 0000000..0014126
--- /dev/null
+++ b/tests/blob.h
@@ -0,0 +1,167 @@
+/*
+Copyright (c) 2016. The YARA Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+uint8_t PE32_FILE[] = {
+  0x4d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+  0x50, 0x45, 0x00, 0x00, 0x4c, 0x01, 0x01, 0x00,
+  0x5d, 0xbe, 0x45, 0x45, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03, 0x01,
+  0x0b, 0x01, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x60, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00,
+  0x64, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x64, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04,
+  0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00,
+  0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x2e, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x60,
+  0x6a, 0x2a, 0x58, 0xc3,
+};
+
+uint8_t ELF32_FILE[] = {
+  0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x60, 0x80, 0x04, 0x08, 0x34, 0x00, 0x00, 0x00,
+  0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x34, 0x00, 0x20, 0x00, 0x01, 0x00, 0x28, 0x00,
+  0x04, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x08,
+  0x00, 0x80, 0x04, 0x08, 0x6c, 0x00, 0x00, 0x00,
+  0x6c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xb8, 0x01, 0x00, 0x00, 0x00, 0xbb, 0x2a, 0x00,
+  0x00, 0x00, 0xcd, 0x80, 0x00, 0x54, 0x68, 0x65,
+  0x20, 0x4e, 0x65, 0x74, 0x77, 0x69, 0x64, 0x65,
+  0x20, 0x41, 0x73, 0x73, 0x65, 0x6d, 0x62, 0x6c,
+  0x65, 0x72, 0x20, 0x32, 0x2e, 0x30, 0x35, 0x2e,
+  0x30, 0x31, 0x00, 0x00, 0x2e, 0x73, 0x68, 0x73,
+  0x74, 0x72, 0x74, 0x61, 0x62, 0x00, 0x2e, 0x74,
+  0x65, 0x78, 0x74, 0x00, 0x2e, 0x63, 0x6f, 0x6d,
+  0x6d, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x60, 0x80, 0x04, 0x08,
+  0x60, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x6c, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x8b, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+uint8_t ELF64_FILE[] = {
+  0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00,
+  0x01, 0x00, 0x40, 0x00, 0x04, 0x00, 0x03, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xb8, 0x01, 0x00, 0x00, 0x00, 0xbb, 0x2a, 0x00,
+  0x00, 0x00, 0xcd, 0x80, 0x00, 0x54, 0x68, 0x65,
+  0x20, 0x4e, 0x65, 0x74, 0x77, 0x69, 0x64, 0x65,
+  0x20, 0x41, 0x73, 0x73, 0x65, 0x6d, 0x62, 0x6c,
+  0x65, 0x72, 0x20, 0x32, 0x2e, 0x30, 0x35, 0x2e,
+  0x30, 0x31, 0x00, 0x00, 0x2e, 0x73, 0x68, 0x73,
+  0x74, 0x72, 0x74, 0x61, 0x62, 0x00, 0x2e, 0x74,
+  0x65, 0x78, 0x74, 0x00, 0x2e, 0x63, 0x6f, 0x6d,
+  0x6d, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
diff --git a/tests/test-rules.c b/tests/test-rules.c
new file mode 100644
index 0000000..a5653c4
--- /dev/null
+++ b/tests/test-rules.c
@@ -0,0 +1,602 @@
+/*
+Copyright (c) 2016. The YARA Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include <yara.h>
+#include "blob.h"
+#include "util.h"
+
+static void test_boolean_operators() {
+  assert_true_rule("rule test { condition: true }", NULL);
+  assert_true_rule("rule test { condition: true or false }", NULL);
+  assert_true_rule("rule test { condition: true and true }", NULL);
+  assert_true_rule("rule test { condition: 0x1 and 0x2}", NULL);
+
+  assert_false_rule("rule test { condition: false }", NULL);
+  assert_false_rule("rule test { condition: true and false }", NULL);
+  assert_false_rule("rule test { condition: false or false }", NULL);
+}
+
+static void test_comparison_operators() {
+  assert_true_rule("rule test { condition: 2 > 1 }", NULL);
+  assert_true_rule("rule test { condition: 1 < 2 }", NULL);
+  assert_true_rule("rule test { condition: 2 >= 1 }", NULL);
+  assert_true_rule("rule test { condition: 1 <= 1 }", NULL);
+  assert_true_rule("rule test { condition: 1 == 1 }", NULL);
+  assert_true_rule("rule test { condition: 1.5 == 1.5}", NULL);
+  assert_true_rule("rule test { condition: 1.0 == 1}", NULL);
+  assert_true_rule("rule test { condition: 1.5 >= 1.0}", NULL);
+  assert_true_rule("rule test { condition: 1.5 >= 1}", NULL);
+  assert_true_rule("rule test { condition: 1.0 >= 1}", NULL);
+  assert_true_rule("rule test { condition: 0.5 < 1}", NULL);
+  assert_true_rule("rule test { condition: 0.5 <= 1}", NULL);
+  assert_true_rule("rule rest { condition: 1.0 <= 1}", NULL);
+  assert_true_rule("rule rest { condition: \"abc\" == \"abc\"}", NULL);
+  assert_true_rule("rule rest { condition: \"abc\" <= \"abc\"}", NULL);
+  assert_true_rule("rule rest { condition: \"abc\" >= \"abc\"}", NULL);
+  assert_true_rule("rule rest { condition: \"ab\" < \"abc\"}", NULL);
+  assert_true_rule("rule rest { condition: \"abc\" > \"ab\"}", NULL);
+  assert_true_rule("rule rest { condition: \"abc\" < \"abd\"}", NULL);
+  assert_true_rule("rule rest { condition: \"abd\" > \"abc\"}", NULL);
+
+  assert_false_rule("rule test { condition: 1 != 1}", NULL);
+  assert_false_rule("rule test { condition: 1 != 1.0}", NULL);
+  assert_false_rule("rule test { condition: 2 > 3}", NULL);
+  assert_false_rule("rule test { condition: 2.1 < 2}", NULL);
+  assert_false_rule("rule test { condition: \"abc\" != \"abc\"}", NULL);
+  assert_false_rule("rule test { condition: \"abc\" > \"abc\"}", NULL);
+  assert_false_rule("rule test { condition: \"abc\" < \"abc\"}", NULL);
+}
+
+static void test_arithmetic_operators() {
+  assert_true_rule("rule test { condition: (1 + 1) * 2 == (9 - 1) \\ 2 }", NULL);
+  assert_true_rule("rule test { condition: 5 % 2 == 1 }", NULL);
+  assert_true_rule("rule test { condition: 1.5 + 1.5 == 3}", NULL);
+  assert_true_rule("rule test { condition: 3 \\ 2 == 1}", NULL);
+  assert_true_rule("rule test { condition: 3.0 \\ 2 == 1.5}", NULL);
+  assert_true_rule("rule test { condition: 1 + -1 == 0}", NULL);
+  assert_true_rule("rule test { condition: -1 + -1 == -2}", NULL);
+  assert_true_rule("rule test { condition: 4 --2 * 2 == 8}", NULL);
+  assert_true_rule("rule test { condition: -1.0 * 1 == -1.0}", NULL);
+  assert_true_rule("rule test { condition: 1-1 == 0}", NULL);
+  assert_true_rule("rule test { condition: -2.0-3.0 == -5}", NULL);
+  assert_true_rule("rule test { condition: --1 == 1}", NULL);
+  assert_true_rule("rule test { condition: 1--1 == 2}", NULL);
+  assert_true_rule("rule test { condition: -0x01 == -1}", NULL);
+}
+
+static void test_bitwise_operators() {
+  assert_true_rule("rule test { condition: 0x55 | 0xAA == 0xFF }", NULL);
+  assert_true_rule("rule test { condition: ~0xAA ^ 0x5A & 0xFF == (~0xAA) ^ (0x5A & 0xFF) }", NULL);
+  assert_true_rule("rule test { condition: ~0x55 & 0xFF == 0xAA }", NULL);
+  assert_true_rule("rule test { condition: 8 >> 2 == 2 }", NULL);
+  assert_true_rule("rule test { condition: 1 << 3 == 8 }", NULL);
+  assert_true_rule("rule test { condition: 1 | 3 ^ 3 == 1 | (3 ^ 3) }", NULL);
+
+  assert_false_rule("rule test { condition: ~0xAA ^ 0x5A & 0xFF == 0x0F }", NULL);
+  assert_false_rule("rule test { condition: 1 | 3 ^ 3 == (1 | 3) ^ 3}", NULL);
+}
+
+static void test_syntax() {
+  assert_syntax_error("rule test { strings: $a = \"a\" $a = \"a\" condition: all of them }");
+}
+
+static void test_anonymous_strings() {
+  assert_true_rule("rule test { strings: $ = \"a\" $ = \"b\" condition: all of them }", "ab");
+}
+
+static void test_strings() {
+  char* str = "---- abc ---- xyz";
+  assert_true_rule("rule test { strings: $a = \"a\" condition: $a }", str);
+  assert_true_rule("rule test { strings: $a = \"ab\" condition: $a }", str);
+  assert_true_rule("rule test { strings: $a = \"abc\" condition: $a }", str);
+  assert_true_rule("rule test { strings: $a = \"xyz\" condition: $a }", str);
+  assert_true_rule("rule test { strings: $a = \"abc\" nocase fullword condition: $a }", str);
+  assert_true_rule("rule test { strings: $a = \"aBc\" nocase  condition: $a }", str);
+  assert_true_rule("rule test { strings: $a = \"abc\" fullword condition: $a }", str);
+
+  assert_false_rule("rule test { strings: $a = \"a\" fullword condition: $a }", str);
+  assert_false_rule("rule test { strings: $a = \"ab\" fullword condition: $a }", str);
+  assert_false_rule("rule test { strings: $a = \"abc\" wide fullword condition: $a }", str);
+
+  uint8_t blob[] = "---- a\000b\000c\000 -\000-\000-\000-\000x\000y\000z\000";
+  size_t blob_len = sizeof(blob);
+  assert_true_rule_blob("rule test { strings: $a = \"a\" wide condition: $a }", blob, blob_len);
+  assert_true_rule_blob("rule test { strings: $a = \"a\" wide ascii condition: $a }", blob, blob_len);
+  assert_true_rule_blob("rule test { strings: $a = \"ab\" wide condition: $a }", blob, blob_len);
+  assert_true_rule_blob("rule test { strings: $a = \"ab\" wide ascii condition: $a }", blob, blob_len);
+  assert_true_rule_blob("rule test { strings: $a = \"abc\" wide condition: $a }", blob, blob_len);
+  assert_true_rule_blob("rule test { strings: $a = \"abc\" wide nocase fullword condition: $a }", blob, blob_len);
+  assert_true_rule_blob("rule test { strings: $a = \"aBc\" wide nocase condition: $a }", blob, blob_len);
+  assert_true_rule_blob("rule test { strings: $a = \"aBc\" wide ascii nocase condition: $a }", blob, blob_len);
+  assert_true_rule_blob("rule test { strings: $a = \"---xyz\" wide nocase condition: $a }", blob, blob_len);
+
+  assert_true_rule("rule test { strings: $a = \"abc\" fullword condition: $a }", "abc");
+
+  assert_false_rule("rule test { strings: $a = \"abc\" fullword condition: $a }", "xabcx");
+
+  assert_false_rule("rule test { strings: $a = \"abc\" fullword condition: $a }", "xabc");
+
+  assert_false_rule("rule test { strings: $a = \"abc\" fullword condition: $a }", "abcx");
+
+  assert_false_rule("rule test { strings: $a = \"abc\" ascii wide fullword condition: $a }", "abcx");
+
+  assert_true_rule_blob("rule test { strings: $a = \"abc\" ascii wide fullword condition: $a }",
+                        (uint8_t*)"a\000abc", 5);
+
+  assert_true_rule_blob("rule test { strings: $a = \"abc\" wide fullword condition: $a }",
+                        (uint8_t*)"a\000b\000c\000", 6);
+
+  assert_false_rule_blob("rule test { strings: $a = \"abc\" wide fullword condition: $a }",
+                         (uint8_t*)"x\000a\000b\000c\000x\000", 10);
+
+  assert_false_rule_blob("rule test { strings: $a = \"ab\" wide fullword condition: $a }",
+                         (uint8_t*)"x\000a\000b\000", 6);
+
+  assert_false_rule_blob("rule test { strings: $a = \"abc\" wide fullword condition: $a }",
+                         (uint8_t*)"x\000a\000b\000c\000", 8);
+
+  assert_true_rule_blob("rule test { strings: $a = \"abc\" wide fullword condition: $a }",
+                        (uint8_t*)"x\001a\000b\000c\000", 8);
+
+  assert_true_rule("rule test {\n\
+                       strings:\n\
+                           $a = \"abcdef\"\n\
+                           $b = \"cdef\"\n\
+                           $c = \"ef\"\n\
+                       condition:\n\
+                           all of them\n\
+                     }", "abcdef");
+}
+
+static void test_wildcard_strings() {
+  uint8_t blob[] = "---- abc ---- A\x00""B\x00""C\x00 ---- xyz";
+  size_t blob_len = sizeof(blob);
+  assert_true_rule_blob("rule test {\n\
+                           strings:\n\
+                               $s1 = \"abc\"\n\
+                               $s2 = \"xyz\"\n\
+                           condition:\n\
+                               for all of ($*) : ($)\n\
+                        }", blob, blob_len);
+  
+}
+
+static void test_hex_strings() {
+  assert_true_rule_blob("rule test { strings: $a = { 64 01 00 00 60 01 } condition: $a }",
+                        PE32_FILE, sizeof(PE32_FILE));
+  assert_true_rule_blob("rule test { strings: $a = { 64 0? 00 00 ?0 01 } condition: $a }",
+                        PE32_FILE, sizeof(PE32_FILE));
+  assert_true_rule_blob("rule test { strings: $a = { 6? 01 00 00 60 0? } condition: $a }",
+                        PE32_FILE, sizeof(PE32_FILE));
+  assert_true_rule_blob("rule test { strings: $a = { 64 01 [1-3] 60 01 } condition: $a }",
+                        PE32_FILE, sizeof(PE32_FILE));
+  assert_true_rule_blob("rule test { strings: $a = { 64 01 [1-3] (60|61) 01 } condition: $a }",
+                        PE32_FILE, sizeof(PE32_FILE));
+  assert_true_rule_blob("rule test { strings: $a = { 4D 5A [-] 6A 2A [-] 58 C3} condition: $a }",
+                        PE32_FILE, sizeof(PE32_FILE));
+  assert_true_rule_blob("rule test { strings: $a = { 4D 5A [300-] 6A 2A [-] 58 C3} condition: $a }",
+                        PE32_FILE, sizeof(PE32_FILE));
+  assert_true_rule_blob("rule test { strings: $a = { 2e 7? (65 | ?""?"") 78 } condition: $a }",
+                        PE32_FILE, sizeof(PE32_FILE));
+
+  assert_false_rule_blob("rule test { strings: $a = { 4D 5A [0-300] 6A 2A } condition: $a }",
+                         PE32_FILE, sizeof(PE32_FILE));
+  assert_false_rule_blob("rule test { strings: $a = { 4D 5A [0-128] 45 [0-128] 01 [0-128]  C3 } condition: $a }",
+                         PE32_FILE, sizeof(PE32_FILE));
+
+  assert_true_rule("rule test { strings: $a = { 31 32 [-] 38 39 } condition: $a }", "1234567890");
+  assert_true_rule("rule test { strings: $a = { 31 32 [-] 33 34 [-] 38 39 } condition: $a }", "1234567890");
+  assert_true_rule("rule test { strings: $a = { 31 32 [1] 34 35 [2] 38 39 } condition: $a }", "1234567890");
+  assert_true_rule("rule test { strings: $a = { 31 32 [1-] 34 35 [1-] 38 39 } condition: $a }", "1234567890");
+  assert_true_rule("rule test { strings: $a = { 31 32 [0-3] 34 35 [1-] 38 39 } condition: $a }", "1234567890");
+  assert_true_rule("rule test { strings: $a = { 31 32 [0-2] 35 [1-] 37 38 39 } condition: $a }", "1234567890");
+
+  assert_true_rule("rule test { strings: $a = { 31 32 [-] 38 39 } condition: all of them }", "1234567890");
+
+  assert_false_rule("rule test { strings: $a = { 31 32 [-] 32 33 } condition: $a }", "1234567890");
+  assert_false_rule("rule test { strings: $a = { 35 36 [-] 31 32 } condition: $a }", "1234567890");
+  assert_false_rule("rule test { strings: $a = { 31 32 [2-] 34 35 } condition: $a }", "1234567890");
+  assert_false_rule("rule test { strings: $a = { 31 32 [0-3] 37 38 } condition: $a }", "1234567890");
+
+  assert_syntax_error("rule test { strings: $a = { 01 [0] 02 } condition: $a }");
+  assert_syntax_error("rule test { strings: $a = { [-] 01 02 } condition: $a }");
+  assert_syntax_error("rule test { strings: $a = { 01 02 [-] } condition: $a }");
+  assert_syntax_error("rule test { strings: $a = { 01 02 ([-] 03 | 04) } condition: $a }");
+  assert_syntax_error("rule test { strings: $a = { 01 02 (03 [-] | 04) } condition: $a }");
+  assert_syntax_error("rule test { strings: $a = { 01 02 (03 | 04 [-]) } condition: $a ");
+
+  /* TODO: tests.py:551 ff. */
+}
+
+static void test_count() {
+  assert_true_rule("rule test { strings: $a = \"ssi\" condition: #a == 2 }", "mississippi");
+}
+
+static void test_at() {
+  assert_true_rule("rule test { strings: $a = \"ssi\" condition: $a at 2 and $a at 5 }", "mississippi");
+  assert_true_rule("rule test { strings: $a = \"mis\" condition: $a at ~0xFF & 0xFF }", "mississippi");
+
+  assert_true_rule_blob("rule test { strings: $a = { 00 00 00 00 ?? 74 65 78 74 } condition: $a at 308}",
+                        PE32_FILE, sizeof(PE32_FILE));
+}
+
+static void test_in() {
+  assert_true_rule_blob("import \"pe\" rule test { strings: $a = { 6a 2a 58 c3 } condition: $a in (pe.entry_point .. pe.entry_point + 1) }",
+                        PE32_FILE, sizeof(PE32_FILE));
+}
+
+static void test_offset() {
+  assert_true_rule("rule test { strings: $a = \"ssi\" condition: @a == 2 }", "mississippi");
+  assert_true_rule("rule test { strings: $a = \"ssi\" condition: @a == @a[1] }", "mississippi");
+  assert_true_rule("rule test { strings: $a = \"ssi\" condition: @a[2] == 5 }", "mississippi");
+}
+
+static void test_length() {
+  assert_true_rule("rule test { strings: $a = /m.*?ssi/ condition: !a == 5 }", "mississippi");
+  assert_true_rule("rule test { strings: $a = /m.*?ssi/ condition: !a[1] == 5 }", "mississippi");
+  assert_true_rule("rule test { strings: $a = /m.*ssi/ condition: !a == 8 }", "mississippi");
+  assert_true_rule("rule test { strings: $a = /m.*ssi/ condition: !a[1] == 8 }", "mississippi");
+  assert_true_rule("rule test { strings: $a = /ssi.*ppi/ condition: !a[1] == 9 }", "mississippi");
+  assert_true_rule("rule test { strings: $a = /ssi.*ppi/ condition: !a[2] == 6 }", "mississippi");
+  assert_true_rule("rule test { strings: $a = { 6D [1-3] 73 73 69 } condition: !a == 5}", "mississippi");
+  assert_true_rule("rule test { strings: $a = { 6D [-] 73 73 69 } condition: !a == 5}", "mississippi");
+  assert_true_rule("rule test { strings: $a = { 6D [-] 70 70 69 } condition: !a == 11}", "mississippi");
+  assert_true_rule("rule test { strings: $a = { 6D 69 73 73 [-] 70 69 } condition: !a == 11}", "mississippi");
+}
+
+static void test_of() {
+  assert_true_rule("rule test { strings: $a = \"ssi\" $b = \"mis\" $c = \"oops\" condition: any of them }", "mississippi");
+  assert_true_rule("rule test { strings: $a = \"ssi\" $b = \"mis\" $c = \"oops\" condition: 1 of them }", "mississippi");
+  assert_true_rule("rule test { strings: $a = \"ssi\" $b = \"mis\" $c = \"oops\" condition: 2 of them }", "mississippi");
+  assert_true_rule("rule test { strings: $a1 = \"dummy1\" $b1 = \"dummy1\" $b2 = \"ssi\" condition: any of ($a*, $b*) }", "mississippi");
+
+  assert_true_rule_blob("rule test\n\
+                         {\n\
+                           strings:\n\
+                             $ = /abc/\n\
+                             $ = /def/\n\
+                             $ = /ghi/\n\
+                           condition:\n\
+                             for any of ($*) : ( for any i in (1..#): (uint8(@[i] - 1) == 0x00) )\n\
+                         }", (uint8_t*)"abc\000def\000ghi", 11);
+  assert_false_rule("rule test { strings: $a = \"ssi\" $b = \"mis\" $c = \"oops\" condition: all of them }", "mississippi");
+
+  assert_syntax_error("rule test { condition: all of ($a*) }");
+  assert_syntax_error("rule test { condition: all of them }");
+}
+
+void test_for() {
+  assert_true_rule("rule test { strings: $a = \"ssi\" condition: for all i in (1..#a) : (@a[i] >= 2 and @a[i] <= 5) }", "mississippi");
+  assert_true_rule("rule test { strings: $a = \"ssi\" $b = \"mi\" condition: for all i in (1..#a) : ( for all j in (1..#b) : (@a[i] >= @b[j])) }", "mississippi");
+  
+  assert_false_rule("rule test { strings: $a = \"ssi\" condition: for all i in (1..#a) : (@a[i] == 5) }", "mississippi");
+}
+
+void test_re() {
+  assert_true_rule("rule test { strings: $a = /ssi/ condition: $a }",
+                   "mississippi\tmississippi.mississippi\nmississippi");
+  assert_true_rule("rule test { strings: $a = /ssi(s|p)/ condition: $a }",
+                   "mississippi\tmississippi.mississippi\nmississippi");
+  assert_true_rule("rule test { strings: $a = /ssim*/ condition: $a }",
+                   "mississippi\tmississippi.mississippi\nmississippi");
+  assert_true_rule("rule test { strings: $a = /ssa?/ condition: $a }",
+                   "mississippi\tmississippi.mississippi\nmississippi");
+  assert_true_rule("rule test { strings: $a = /Miss/ nocase condition: $a }",
+                   "mississippi\tmississippi.mississippi\nmississippi");
+  assert_true_rule("rule test { strings: $a = /(M|N)iss/ nocase condition: $a }",
+                   "mississippi\tmississippi.mississippi\nmississippi");
+  assert_true_rule("rule test { strings: $a = /[M-N]iss/ nocase condition: $a }",
+                   "mississippi\tmississippi.mississippi\nmississippi");
+  assert_true_rule("rule test { strings: $a = /(Mi|ssi)ssippi/ nocase condition: $a }",
+                   "mississippi\tmississippi.mississippi\nmississippi");
+  assert_true_rule("rule test { strings: $a = /ppi\\tmi/ condition: $a }",
+                   "mississippi\tmississippi.mississippi\nmississippi");
+  assert_true_rule("rule test { strings: $a = /ppi\\.mi/ condition: $a }",
+                   "mississippi\tmississippi.mississippi\nmississippi");
+  assert_true_rule("rule test { strings: $a = /^mississippi/ fullword condition: $a }",
+                   "mississippi\tmississippi.mississippi\nmississippi");
+  assert_true_rule("rule test { strings: $a = /mississippi.*mississippi$/s condition: $a }",
+                   "mississippi\tmississippi.mississippi\nmississippi");
+
+  assert_false_rule("rule test { strings: $a = /^ssi/ condition: $a }", "mississippi");
+  assert_false_rule("rule test { strings: $a = /ssi$/ condition: $a }", "mississippi");
+  assert_false_rule("rule test { strings: $a = /ssissi/ fullword condition: $a }", "mississippi");
+  assert_false_rule("rule test { strings: $a = /^[isp]+/ condition: $a }", "mississippi");
+
+  /* tests.py:670 ff. */
+  assert_regexp_syntax_error(")");
+  assert_true_regexp("abc", "abc", "abc");
+  assert_false_regexp("abc", "xbc");
+  assert_false_regexp("abc", "axc");
+  assert_false_regexp("abc", "abx");
+  assert_true_regexp("abc", "xabcx", "abc");
+  assert_true_regexp("abc", "ababc", "abc");
+  assert_true_regexp("a.c", "abc", "abc");
+  assert_false_regexp("a.b", "a\nb");
+  assert_false_regexp("a.*b", "acc\nccb");
+  assert_false_regexp("a.{4,5}b", "acc\nccb");
+  assert_true_regexp("a.b", "a\rb", "a\rb");
+  assert_true_regexp("ab*c", "abc", "abc");
+  assert_true_regexp("ab*c", "ac", "ac");
+  assert_true_regexp("ab*bc", "abc", "abc");
+  assert_true_regexp("ab*bc", "abbc", "abbc");
+  assert_true_regexp("a.*bb", "abbbb", "abbbb");
+  assert_true_regexp("a.*?bbb", "abbbbbb", "abbb");
+  assert_true_regexp("a.*c", "ac", "ac");
+  assert_true_regexp("a.*c", "axyzc", "axyzc");
+  assert_true_regexp("ab+c", "abbc", "abbc");
+  assert_false_regexp("ab+c", "ac");
+  assert_true_regexp("ab+", "abbbb", "abbbb");
+  assert_true_regexp("ab+?", "abbbb", "ab");
+  assert_false_regexp("ab+bc", "abc");
+  assert_false_regexp("ab+bc", "abq");
+  assert_true_regexp("a+b+c", "aabbabc", "abc");
+  assert_false_regexp("ab?bc", "abbbbc");
+  assert_true_regexp("ab?c", "abc", "abc");
+  assert_true_regexp("ab*?", "abbb", "a");
+  assert_true_regexp("ab?c", "abc", "abc");
+  assert_true_regexp("ab??", "ab", "a");
+  assert_true_regexp("a(b|x)c", "abc", "abc");
+  assert_true_regexp("a(b|x)c", "axc", "axc");
+  assert_true_regexp("a(b|.)c", "axc", "axc");
+  assert_true_regexp("a(b|x|y)c", "ayc", "ayc");
+  assert_true_regexp("(a+|b)*", "ab", "ab");
+  assert_true_regexp("a|b|c|d|e", "e", "e");
+  assert_true_regexp("(a|b|c|d|e)f", "ef", "ef");
+  assert_true_regexp(".b{2}", "abb", "abb");
+  assert_true_regexp("ab{1}c", "abc", "abc");
+  assert_true_regexp("ab{1,2}c", "abbc", "abbc");
+  assert_true_regexp("ab{1,}c", "abbbc", "abbbc");
+  assert_false_regexp("ab{1,}b", "ab");
+  assert_false_regexp("ab{1}c", "abbc");
+  assert_true_regexp("ab{0,}c", "ac", "ac");
+  assert_true_regexp("ab{0,}c", "abbbc", "abbbc");
+  assert_true_regexp("ab{,3}c", "abbbc", "abbbc");
+  assert_false_regexp("ab{,2}c", "abbbc");
+  assert_false_regexp("ab{4,5}bc", "abbbbc");
+  assert_true_regexp("ab{2,3}?", "abbbbb", "abb");
+  assert_true_regexp("ab{.*}", "ab{c}", "ab{c}");
+  assert_true_regexp(".(aa){1,2}", "aaaaaaaaaa", "aaaaa");
+  assert_true_regexp("a.(bc.){2}", "aabcabca", "aabcabca");
+  assert_true_regexp("(ab{1,2}c){1,3}", "abbcabc", "abbcabc");
+  assert_true_regexp("ab(c|cc){1,3}d", "abccccccd", "abccccccd");
+  assert_true_regexp("a[bx]c", "abc", "abc");
+  assert_true_regexp("a[bx]c", "axc", "axc");
+  assert_true_regexp("a[0-9]*b", "ab", "ab");
+  assert_true_regexp("a[0-9]*b", "a0123456789b", "a0123456789b");
+  assert_true_regexp("[0-9a-f]+", "0123456789abcdef", "0123456789abcdef");
+  assert_true_regexp("[0-9a-f]+", "xyz0123456789xyz", "0123456789");
+  assert_true_regexp("a[\\s\\S]b", "a b", "a b");
+  assert_true_regexp("a[\\d\\D]b", "a1b", "a1b");
+  assert_false_regexp("[x-z]+", "abc");
+  assert_true_regexp("a[-]?c", "ac", "ac");
+  assert_true_regexp("a[-b]", "a-", "a-");
+  assert_true_regexp("a[-b]", "ab", "ab");
+  assert_true_regexp("a[b-]", "a-", "a-");
+  assert_true_regexp("a[b-]", "ab", "ab");
+  assert_true_regexp("[a-c-e]", "b", "b");
+  assert_true_regexp("[a-c-e]", "-", "-");
+  assert_false_regexp("[a-c-e]", "d");
+  assert_regexp_syntax_error("[b-a]");
+  assert_regexp_syntax_error("(abc");
+  assert_regexp_syntax_error("abc)");
+  assert_regexp_syntax_error("a[]b");
+  assert_regexp_syntax_error("a\\");
+  assert_true_regexp("a[\\-b]", "a-", "a-");
+  assert_true_regexp("a[\\-b]", "ab", "ab");
+  assert_regexp_syntax_error("a[\\");
+  assert_true_regexp("a]", "a]", "a]");
+  assert_true_regexp("a[]]b", "a]b", "a]b");
+  assert_true_regexp("a[\\]]b", "a]b", "a]b");
+  assert_true_regexp("a[^bc]d", "aed", "aed");
+  assert_false_regexp("a[^bc]d", "abd");
+  assert_true_regexp("a[^-b]c", "adc", "adc");
+  assert_false_regexp("a[^-b]c", "a-c");
+  assert_false_regexp("a[^]b]c", "a]c");
+  assert_true_regexp("a[^]b]c", "adc", "adc");
+  assert_true_regexp("[^ab]*", "cde", "cde");
+  assert_regexp_syntax_error(")(");
+  assert_true_regexp("a\\sb", "a b", "a b");
+  assert_true_regexp("a\\sb", "a\tb", "a\tb");
+  assert_true_regexp("a\\sb", "a\rb", "a\rb");
+  assert_true_regexp("a\\sb", "a\nb", "a\nb");
+  assert_true_regexp("a\\sb", "a\vb", "a\vb");
+  assert_true_regexp("a\\sb", "a\fb", "a\fb");
+  assert_false_regexp("a\\Sb", "a b");
+  assert_false_regexp("a\\Sb", "a\tb");
+  assert_false_regexp("a\\Sb", "a\rb");
+  assert_false_regexp("a\\Sb", "a\nb");
+  assert_false_regexp("a\\Sb", "a\vb");
+  assert_false_regexp("a\\Sb", "a\fb");
+  assert_true_regexp("\\n\\r\\t\\f\\a", "\n\r\t\f\a", "\n\r\t\f\a");
+  assert_true_regexp("[\\n][\\r][\\t][\\f][\\a]", "\n\r\t\f\a", "\n\r\t\f\a");
+  assert_true_regexp("\\x01\\x02\\x03", "\x01\x02\x03", "\x01\x02\x03");
+  assert_true_regexp("[\\x01-\\x03]+", "\x01\x02\x03", "\x01\x02\x03");
+  assert_false_regexp("[\\x00-\\x02]+", "\x03\x04\x05");
+  assert_true_regexp("[\\x5D]", "]", "]");
+  assert_true_regexp("[\\0x5A-\\x5D]", "\x5B", "\x5B");
+  assert_true_regexp("[\\x5D-\\x5F]", "\x5E", "\x5E");
+  assert_true_regexp("[\\x5C-\\x5F]", "\x5E", "\x5E");
+  assert_true_regexp("[\\x5D-\\x5F]", "\x5E", "\x5E");
+  assert_true_regexp("a\\wc", "abc", "abc");
+  assert_true_regexp("a\\wc", "a_c", "a_c");
+  assert_true_regexp("a\\wc", "a0c", "a0c");
+  assert_false_regexp("a\\wc", "a*c");
+  assert_true_regexp("\\w+", "--ab_cd0123--", "ab_cd0123");
+  assert_true_regexp("[\\w]+", "--ab_cd0123--", "ab_cd0123");
+  assert_true_regexp("\\D+", "1234abc5678", "abc");
+  assert_true_regexp("[\\d]+", "0123456789", "0123456789");
+  assert_true_regexp("[\\D]+", "1234abc5678", "abc");
+  assert_true_regexp("[\\da-fA-F]+", "123abc", "123abc");
+  assert_false_regexp("^(ab|cd)e", "abcde");
+  assert_true_regexp("(abc|)ef", "abcdef", "ef");
+  assert_true_regexp("(abc|)ef", "abcef", "abcef");
+  assert_true_regexp("\\babc", "abc", "abc");
+  assert_true_regexp("abc\\b", "abc", "abc");
+  assert_false_regexp("\\babc", "1abc");
+  assert_false_regexp("abc\\b", "abc1");
+  assert_true_regexp("abc\\s\\b", "abc x", "abc ");
+  assert_false_regexp("abc\\s\\b", "abc  ");
+  assert_true_regexp("\\babc\\b", " abc ", "abc");
+  assert_true_regexp("\\b\\w\\w\\w\\b", " abc ", "abc");
+  assert_true_regexp("\\w\\w\\w\\b", "abcd", "bcd");
+  assert_true_regexp("\\b\\w\\w\\w", "abcd", "abc");
+  assert_false_regexp("\\b\\w\\w\\w\\b", "abcd");
+  assert_false_regexp("\\Babc", "abc");
+  assert_false_regexp("abc\\B", "abc");
+  assert_true_regexp("\\Babc", "1abc", "abc");
+  assert_true_regexp("abc\\B", "abc1", "abc");
+  assert_false_regexp("abc\\s\\B", "abc x");
+  assert_true_regexp("abc\\s\\B", "abc  ", "abc ");
+  assert_true_regexp("\\w\\w\\w\\B", "abcd", "abc");
+  assert_true_regexp("\\B\\w\\w\\w", "abcd", "bcd");
+  assert_false_regexp("\\B\\w\\w\\w\\B", "abcd");
+
+  /* This is allowed in most regexp engines but in order to keep the
+     grammar free of shift/reduce conflicts I've decided not supporting
+     it. Users can use the (abc|) form instead. */
+  assert_regexp_syntax_error("(|abc)ef");
+
+  assert_true_regexp("((a)(b)c)(d)", "abcd", "abcd");
+  assert_true_regexp("(a|b)c*d", "abcd", "bcd");
+  assert_true_regexp("(ab|ab*)bc", "abc", "abc");
+  assert_true_regexp("a([bc]*)c*", "abc", "abc");
+  assert_true_regexp("a([bc]*)c*", "ac", "ac");
+  assert_true_regexp("a([bc]*)c*", "a", "a");
+  assert_true_regexp("a([bc]*)(c*d)", "abcd", "abcd");
+  assert_true_regexp("a([bc]+)(c*d)", "abcd", "abcd");
+  assert_true_regexp("a([bc]*)(c+d)", "abcd", "abcd");
+  assert_true_regexp("a[bcd]*dcdcde", "adcdcde", "adcdcde");
+  assert_false_regexp("a[bcd]+dcdcde", "adcdcde");
+  assert_true_regexp("\\((.*), (.*)\\)", "(a, b)", "(a, b)");
+  assert_true_regexp("abc|123$", "abcx", "abc");
+  assert_false_regexp("abc|123$", "123x");
+  assert_true_regexp("abc|^123", "123", "123");
+  assert_false_regexp("abc|^123", "x123");
+  assert_true_regexp("^abc$", "abc", "abc");
+  assert_false_regexp("^abc$", "abcc");
+  assert_true_regexp("^abc", "abcc", "abc");
+  assert_false_regexp("^abc$", "aabc");
+  assert_true_regexp("abc$", "aabc", "abc");
+  assert_true_regexp("^a(bc+|b[eh])g|.h$", "abhg", "abhg");
+  assert_true_regexp("(bc+d$|ef*g.|h?i(j|k))", "effgz", "effgz");
+  assert_true_regexp("(bc+d$|ef*g.|h?i(j|k))", "ij", "ij");
+  assert_false_regexp("(bc+d$|ef*g.|h?i(j|k))", "effg");
+  assert_false_regexp("(bc+d$|ef*g.|h?i(j|k))", "bcdd");
+  assert_true_regexp("(bc+d$|ef*g.|h?i(j|k))", "reffgz", "effgz");
+
+  /* Test case for issue #324 */
+  assert_true_regexp("whatever|   x.   x", "   xy   x", "   xy   x");
+}
+
+static void test_entrypoint() {
+  assert_true_rule_blob("rule test { strings: $a = { 6a 2a 58 c3 } condition: $a at entrypoint }",
+                        PE32_FILE, sizeof(PE32_FILE));
+
+  assert_true_rule_blob("rule test { strings: $a = { b8 01 00 00 00 bb 2a } condition: $a at entrypoint }",
+                        ELF32_FILE, sizeof(ELF32_FILE));
+
+  assert_true_rule_blob("rule test { strings: $a = { b8 01 00 00 00 bb 2a } condition: $a at entrypoint }",
+                        ELF64_FILE, sizeof(ELF64_FILE));
+
+  assert_false_rule("rule test { condition: entrypoint >= 0 }", NULL);
+}
+
+static void test_filesize() {
+  char rule[80];
+  snprintf(rule, sizeof(rule), "rule test { condition: filesize == %zd }", sizeof(PE32_FILE));
+  assert_true_rule_blob(rule, PE32_FILE, sizeof(PE32_FILE));
+}
+
+static void test_comments() {
+  assert_true_rule("rule test {\n\
+                       condition:\n\
+                           //  this is a comment\n\
+                           /*** this is a comment ***/\n\
+                           /* /* /*\n\
+                               this is a comment\n\
+                           */\n\
+                           true\n\
+                   }", NULL);
+}
+
+static void test_modules() {
+  assert_true_rule("import \"tests\" rule test { condition: tests.constants.one + 1 == tests.constants.two }", NULL);
+  assert_true_rule("import \"tests\" rule test { condition: tests.constants.foo == \"foo\" }", NULL);
+  assert_true_rule("import \"tests\" rule test { condition: tests.constants.empty == \"\" }", NULL);
+  assert_true_rule("import \"tests\" rule test { condition: tests.empty() == \"\" }", NULL);
+  assert_true_rule("import \"tests\" rule test { condition: tests.struct_array[1].i == 1 }", NULL);
+  assert_true_rule("import \"tests\" rule test { condition: tests.struct_array[0].i == 1 or true}", NULL);
+  assert_true_rule("import \"tests\" rule test { condition: tests.integer_array[0] == 0}", NULL);
+  assert_true_rule("import \"tests\" rule test { condition: tests.integer_array[1] == 1}", NULL);
+  assert_true_rule("import \"tests\" rule test { condition: tests.string_array[0] == \"foo\"}", NULL);
+  assert_true_rule("import \"tests\" rule test { condition: tests.string_array[2] == \"baz\"}", NULL);
+  assert_true_rule("import \"tests\" rule test { condition: tests.string_dict[\"foo\"] == \"foo\"}", NULL);
+  assert_true_rule("import \"tests\" rule test { condition: tests.string_dict[\"bar\"] == \"bar\"}", NULL);
+  assert_true_rule("import \"tests\" rule test { condition: tests.isum(1,2) == 3}", NULL);
+  assert_true_rule("import \"tests\" rule test { condition: tests.isum(1,2,3) == 6}", NULL);
+  assert_true_rule("import \"tests\" rule test { condition: tests.fsum(1.0,2.0) == 3.0}", NULL);
+  assert_true_rule("import \"tests\" rule test { condition: tests.fsum(1.0,2.0,3.0) == 6.0}", NULL);
+  assert_true_rule("import \"tests\" rule test { condition: tests.length(\"dummy\") == 5}", NULL);
+
+  assert_false_rule("import \"tests\" rule test { condition: tests.struct_array[0].i == 1 }", NULL);
+  assert_false_rule("import \"tests\" rule test { condition: tests.isum(1,1) == 3}", NULL);
+  assert_false_rule("import \"tests\" rule test { condition: tests.fsum(1.0,1.0) == 3.0}", NULL);
+}
+
+void test_integer_functions() {
+  assert_true_rule("rule test { condition: uint8(0) == 0xAA}", "\xaa\xbb\xcc\xdd");
+  assert_true_rule("rule test { condition: uint16(0) == 0xBBAA}", "\xaa\xbb\xcc\xdd");
+  assert_true_rule("rule test { condition: uint32(0) == 0xDDCCBBAA}", "\xaa\xbb\xcc\xdd");
+  assert_true_rule("rule test { condition: uint8be(0) == 0xAA}", "\xaa\xbb\xcc\xdd");
+  assert_true_rule("rule test { condition: uint16be(0) == 0xAABB}", "\xaa\xbb\xcc\xdd");
+  assert_true_rule("rule test { condition: uint32be(0) == 0xAABBCCDD}", "\xaa\xbb\xcc\xdd");
+}
+
+int main(int argc, char** argv)
+{
+  yr_initialize();
+  test_boolean_operators();
+  test_comparison_operators();
+  test_arithmetic_operators();
+  test_bitwise_operators();
+  test_syntax();
+  test_anonymous_strings();
+  test_strings();
+  test_wildcard_strings();
+  test_hex_strings();
+  test_count();
+  test_at();
+  test_in();
+  test_offset();
+  test_length();
+  test_of();
+  test_for();
+  test_re();
+  test_entrypoint();
+  test_filesize();
+  // test_compile_file();
+  // test_compile_files();
+  // test_include_files();
+  // test_externals();
+  // test_callback();
+  // test_compare();
+  test_comments();
+  test_modules();
+  test_integer_functions();
+  // test_string_io();
+  return 0;
+}
diff --git a/tests/util.c b/tests/util.c
new file mode 100644
index 0000000..77e7d5a
--- /dev/null
+++ b/tests/util.c
@@ -0,0 +1,112 @@
+/*
+Copyright (c) 2016. The YARA Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include <stdio.h>
+#include <error.h>
+#include <unistd.h>
+
+#include <yara.h>
+
+YR_RULES* rule_of_string(char* string) {
+  YR_COMPILER* compiler = NULL;
+  YR_RULES* rules = NULL;
+  if (yr_compiler_create(&compiler) != ERROR_SUCCESS) {
+    perror("yr_compiler_create");
+    goto out;
+  }
+  if (yr_compiler_add_string(compiler, string, NULL) != 0) {
+    goto out;
+  }
+  if (yr_compiler_get_rules(compiler, &rules) != ERROR_SUCCESS) {
+    goto out;
+  }
+ out:
+  yr_compiler_destroy(compiler);
+  return rules;
+}
+
+static int count_matches(int message, void* message_data, void* user_data) {
+  if (message == CALLBACK_MSG_RULE_MATCHING) {
+    (*(int*)user_data)++;
+  }
+  return CALLBACK_CONTINUE;
+}
+
+int matches_blob(char* rule, uint8_t* blob, size_t len) {
+  if (blob == NULL) {
+    blob = (uint8_t*)"dummy";
+    len = 5;
+  }
+  YR_RULES* rules = rule_of_string(rule);
+  if (rules == NULL) {
+    fprintf(stderr, "failed to compile rule << %s >>\n", rule);
+    exit(EXIT_FAILURE);
+  }
+  int matches = 0;
+  if (yr_rules_scan_mem(rules, blob, len, 0, count_matches, &matches, 0) != ERROR_SUCCESS) {
+    fprintf(stderr, "yr_rules_scan_mem: error\n");
+    exit(EXIT_FAILURE);
+  }
+  yr_rules_destroy(rules);
+  return matches;
+}
+
+int matches_string(char* rule, char* string) {
+  size_t len = 0;
+  if (string != NULL) {
+    len = strlen(string);
+  }
+  return matches_blob(rule, (uint8_t*)string, len);
+}
+
+typedef struct {
+  char* expected;
+  int found;
+} find_string_t;
+
+static int capture_matches(int message, void* message_data, void* user_data) {
+  if (message == CALLBACK_MSG_RULE_MATCHING) {
+    find_string_t* f = (find_string_t*)user_data;
+    YR_RULE* rule = (YR_RULE*)message_data;
+    YR_STRING* string;
+    yr_rule_strings_foreach(rule, string) {
+      YR_MATCH* match;
+      yr_string_matches_foreach(string, match) {
+        if (strncmp(f->expected, (char*)(match->data), match->length) == 0) {
+          f->found++;
+        }
+      }
+    }
+  }
+  return CALLBACK_CONTINUE;
+}
+
+int capture_string(char* rule, char* string, char* expected_string) {
+  YR_RULES* rules = rule_of_string(rule);
+  if (rules == NULL) {
+    fprintf(stderr, "failed to compile rule << %s >>\n", rule);
+    exit(EXIT_FAILURE);
+  }
+  find_string_t f;
+  f.found = 0;
+  f.expected = expected_string;
+  if (yr_rules_scan_mem(rules, (uint8_t*)string, strlen(string), 0,
+                        capture_matches, &f, 0) != ERROR_SUCCESS) {
+    fprintf(stderr, "yr_rules_scan_mem: error\n");
+    exit(EXIT_FAILURE);
+  }
+  return f.found;
+}
diff --git a/tests/util.h b/tests/util.h
new file mode 100644
index 0000000..3e5c315
--- /dev/null
+++ b/tests/util.h
@@ -0,0 +1,94 @@
+/*
+Copyright (c) 2016. The YARA Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#ifndef _UTIL_H
+#define _UTIL_H
+
+YR_RULES* rule_of_string(char* string);
+int matches_blob(char* rule, uint8_t* blob, size_t len);
+int matches_string(char* rule, char* string);
+int capture_string(char* rule, char* string, char* expected_string);
+
+#define assert_true_rule(rule,string)                                   \
+  do {                                                                  \
+    if (!matches_string(rule, string)) {                                \
+      fprintf(stderr, "%s:%d: rule does not match (but should)\n",      \
+              __FILE__, __LINE__ );                                     \
+      exit(EXIT_FAILURE);                                               \
+    }                                                                   \
+  } while (0);
+
+#define assert_true_rule_blob(rule,blob,len)                            \
+  do {                                                                  \
+    if (!matches_blob(rule, blob, len)) {                               \
+      fprintf(stderr, "%s:%d: rule does not match (but should)\n",      \
+              __FILE__, __LINE__ );                                     \
+      exit(EXIT_FAILURE);                                               \
+    }                                                                   \
+  } while (0);
+
+#define assert_false_rule(rule,string)                                  \
+  do {                                                                  \
+    if (matches_string(rule, string)) {                                 \
+      fprintf(stderr, "%s:%d: rule matches (but shouldn't)\n",          \
+              __FILE__, __LINE__ );                                     \
+      exit(EXIT_FAILURE);                                               \
+    }                                                                   \
+  } while (0);
+
+#define assert_false_rule_blob(rule,blob,len)                           \
+  do {                                                                  \
+    if (matches_blob(rule, blob, len)) {                                \
+      fprintf(stderr, "%s:%d: rule matches (but shouldn't)\n",          \
+              __FILE__, __LINE__ );                                     \
+      exit(EXIT_FAILURE);                                               \
+    }                                                                   \
+  } while (0);
+
+#define assert_syntax_correct(rule) do {                                \
+    if (rule_of_string(rule) == NULL) {                                 \
+      fprintf(stderr, "%s:%d: rule can't be compiled (but should)\n",   \
+              __FILE__, __LINE__);                                      \
+      exit(EXIT_FAILURE);                                               \
+    }                                                                   \
+  } while(0);
+
+#define assert_syntax_error(rule) do {                                  \
+    if (rule_of_string(rule) != NULL) {                                 \
+      fprintf(stderr, "%s:%d: rule can be compiled (but shouldn't)\n",  \
+              __FILE__, __LINE__);                                      \
+      exit(EXIT_FAILURE);                                               \
+    }                                                                   \
+  } while(0);
+
+#define assert_true_regexp(regexp,string,expected) do {                 \
+    if (!capture_string("rule test { strings: $a = /" regexp            \
+                        "/ condition: $a }", string, expected)) {       \
+      fprintf(stderr, "%s:%d: regexp does not match\n",                 \
+              __FILE__, __LINE__);                                      \
+      exit(EXIT_FAILURE);                                               \
+    }                                                                   \
+} while (0);
+
+#define assert_false_regexp(regexp,string)                              \
+  assert_false_rule("rule test { strings: $a = /" regexp                \
+                    "/ condition: $a }", string)
+
+#define assert_regexp_syntax_error(regexp)                      \
+  assert_syntax_error("rule test { strings: $a = /" regexp      \
+                      "/ condition: $a }")
+
+#endif /* _UTIL_H */

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/forensics/yara.git



More information about the forensics-changes mailing list