suricata
detect-engine-content-inspection.c
Go to the documentation of this file.
1/* Copyright (C) 2007-2017 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18/**
19 * \file
20 *
21 * \author Victor Julien <victor@inliniac.net>
22 *
23 * Tests for the content inspection engine.
24 */
25
26#include "../suricata-common.h"
27#include "../decode.h"
28#include "../flow.h"
29#include "../detect.h"
30#include "detect-engine-build.h"
31
32extern thread_local uint32_t ut_inspection_recursion_counter;
33
34#define TEST_HEADER \
35 ThreadVars tv; \
36 memset(&tv, 0, sizeof(tv)); \
37 Flow f; \
38 memset(&f, 0, sizeof(f));
39
40#define TEST_RUN(buf, buflen, sig, match, steps) \
41 { \
42 DetectEngineCtx *de_ctx = DetectEngineCtxInit(); \
43 FAIL_IF_NULL(de_ctx); \
44 DetectEngineThreadCtx *det_ctx = NULL; \
45 char rule[2048]; \
46 snprintf(rule, sizeof(rule), "alert tcp any any -> any any (%s sid:1; rev:1;)", (sig)); \
47 Signature *s = DetectEngineAppendSig(de_ctx, rule); \
48 FAIL_IF_NULL(s); \
49 SigGroupBuild(de_ctx); \
50 DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); \
51 FAIL_IF_NULL(det_ctx); \
52 int r = DetectEngineContentInspection(de_ctx, det_ctx, s, \
53 s->sm_arrays[DETECT_SM_LIST_PMATCH], NULL, &f, (uint8_t *)(buf), (buflen), 0, \
54 DETECT_CI_FLAGS_SINGLE, DETECT_ENGINE_CONTENT_INSPECTION_MODE_PAYLOAD); \
55 FAIL_IF_NOT(r == (match)); \
56 FAIL_IF_NOT(ut_inspection_recursion_counter == (steps)); \
57 DetectEngineThreadCtxDeinit(&tv, det_ctx); \
58 DetectEngineCtxFree(de_ctx); \
59 }
60#define TEST_FOOTER \
61 PASS
62
63/** \test simple match with distance */
64static int DetectEngineContentInspectionTest01(void) {
66 TEST_RUN("ab", 2, "content:\"a\"; content:\"b\";", true, 2);
67 TEST_RUN("ab", 2, "content:\"a\"; content:\"b\"; distance:0; ", true, 2);
68 TEST_RUN("ba", 2, "content:\"a\"; content:\"b\"; distance:0; ", false, 2);
70}
71
72/** \test simple match with pcre/R */
73static int DetectEngineContentInspectionTest02(void) {
75 TEST_RUN("ab", 2, "content:\"a\"; pcre:\"/b/\";", true, 2);
76 TEST_RUN("ab", 2, "content:\"a\"; pcre:\"/b/R\";", true, 2);
77 TEST_RUN("ba", 2, "content:\"a\"; pcre:\"/b/R\";", false, 2);
79}
80
81/** \test simple recursion logic */
82static int DetectEngineContentInspectionTest03(void) {
84 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; content:\"c\";", true, 3);
85 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; content:\"d\";", false, 3);
86
87 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; content:\"c\"; distance:0;", true, 3);
88 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; content:\"d\"; distance:0;", false, 3);
89
90 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"d\"; distance:0; within:1;", false, 5);
91
92 // 5 steps: (1) a, (2) 1st b, (3) c not found, (4) 2nd b, (5) c found
93 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"c\"; distance:0; within:1;", true, 5);
94 // 6 steps: (1) a, (2) 1st b, (3) c not found, (4) 2nd b, (5) c found, (6) bab
95 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"c\"; distance:0; within:1; content:\"bab\";", true, 6);
96 // 6 steps: (1) a, (2) 1st b, (3) c not found, (4) 2nd b, (5) c found, (6) no not found
97 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"c\"; distance:0; within:1; content:\"no\";", false, 6);
98
99 // 5 steps: (1) a, (2) 1st b, (3) c not found, (4) 2nd b, (5) c found
100 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; pcre:\"/^c$/R\";", true, 5);
101 // 6 steps: (1) a, (2) 1st b, (3) c not found, (4) 2nd b, (5) c found, (6) bab
102 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; pcre:\"/^c$/R\"; content:\"bab\";", true, 6);
103 // 6 steps: (1) a, (2) 1st b, (3) c not found, (4) 2nd b, (5) c found, (6) no not found
104 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; pcre:\"/^c$/R\"; content:\"no\";", false, 6);
105
107}
108
109/** \test pcre recursion logic */
110static int DetectEngineContentInspectionTest04(void) {
112 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; content:\"c\";", true, 3);
113 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; content:\"d\";", false, 3);
114
115 // simple chain of pcre
116 TEST_RUN("ababc", 5, "pcre:\"/^a/\"; pcre:\"/^b/R\"; pcre:\"/c/R\"; ", true, 3);
117 TEST_RUN("ababc", 5, "pcre:\"/a/\"; pcre:\"/^b/R\"; pcre:\"/^c/R\"; ", true, 5);
118 TEST_RUN("ababc", 5, "pcre:\"/^a/\"; pcre:\"/^b/R\"; pcre:\"/d/R\"; ", false, 3);
119 TEST_RUN("ababc", 5, "pcre:\"/^a/\"; pcre:\"/^b/R\"; pcre:\"/c/R\"; pcre:\"/d/\"; ", false, 4);
120
122}
123
124/** \test multiple independent blocks recursion logic */
125static int DetectEngineContentInspectionTest05(void) {
127 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; content:\"c\";", true, 3);
128 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; content:\"d\";", false, 3);
129
130 // first block 2: (1) a, (2) b
131 // second block 3: (1) b, (2) c not found, (x) b continues within loop, (3) c found
132 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"b\"; content:\"c\"; distance:0; within:1;", true, 5);
133
135}
136
137/** \test isdataat recursion logic */
138static int DetectEngineContentInspectionTest06(void) {
140 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; content:\"c\";", true, 3);
141 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; content:\"d\";", false, 3);
142
143 // 6 steps: (1) a, (2) 1st b, (3) c not found, (4) 2nd b, (5) c found, isdataat
144 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"c\"; distance:0; within:1; isdataat:!1,relative;", true, 5);
145 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"c\"; distance:0; within:1; isdataat:1,relative;", false, 6);
146 TEST_RUN("abcabc", 6,
147 "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"c\"; distance:0; "
148 "within:1; isdataat:10,relative;",
149 false, 4);
150
151 TEST_RUN("ababcabc", 8, "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"c\"; distance:0; within:1; isdataat:!1,relative;", true, 7);
152 TEST_RUN("ababcabc", 8, "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"c\"; distance:0; within:1; isdataat:1,relative;", true, 6);
153
154 TEST_RUN("abcXYZ", 6, "content:\"abc\"; content:\"XYZ\"; distance:0; within:3; isdataat:!1,relative;", true, 2);
155 TEST_RUN("abcXYZ", 6, "content:\"XYZ\"; distance:3; within:3; isdataat:!1,relative;", true, 1);
156 TEST_RUN("abcXYZ", 6, "content:\"cXY\"; distance:2; within:3; isdataat:!1,relative;", false, 1);
157
158 TEST_RUN("xxxxxxxxxxxxxxxxxyYYYYYYYYYYYYYYYY", 34, "content:\"yYYYYYYYYYYYYYYYY\"; distance:9; within:29; isdataat:!1,relative;", true, 1);
160}
161
162/** \test extreme recursion */
163static int DetectEngineContentInspectionTest07(void) {
165 TEST_RUN("abcabcabcabcabcabcabcabcabcabcd", 31, "content:\"a\"; content:\"b\"; within:1; distance:0; content:\"c\"; distance:0; within:1; content:\"d\";", true, 4);
166 TEST_RUN("abcabcabcabcabcabcabcabcabcabcd", 31, "content:\"a\"; content:\"b\"; within:1; distance:0; content:\"c\"; distance:0; within:1; content:\"d\"; within:1; distance:0; ", true, 31);
167 TEST_RUN("abcabcabcabcabcabcabcabcabcabcx", 31, "content:\"a\"; content:\"b\"; within:1; distance:0; content:\"c\"; distance:0; within:1; content:\"d\"; within:1; distance:0; ", false, 31);
168
169 TEST_RUN("abcabcabcabcabcabcabcabcabcabcx", 31, "content:\"a\"; content:\"b\"; distance:0; content:\"c\"; distance:0; content:\"d\"; distance:0; ", false, 4);
170 TEST_RUN("abcabcabcabcabcabcabcabcabcabcx", 31, "content:\"a\"; content:\"b\"; distance:0; content:\"c\"; distance:0; pcre:\"/^d/R\"; ", false, 13);
171 TEST_RUN("abcabcabcabcabcabcabcabcabcabcx", 31, "content:\"a\"; content:\"b\"; distance:0; content:\"c\"; distance:0; isdataat:!1,relative; ", false, 3);
172 TEST_RUN("abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdx", 41,
173 "content:\"a\"; content:\"b\"; distance:0; content:\"c\"; distance:0; content:\"d\"; distance:0; content:\"e\"; distance:0; ", false, 5);
174 TEST_RUN("abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdx", 41,
175 "content:\"a\"; content:\"b\"; distance:0; content:\"c\"; distance:0; content:\"d\"; distance:0; pcre:\"/^e/R\"; ", false, 14); // TODO should be 5?
176 TEST_RUN("abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdx", 41,
177 "content:\"a\"; content:\"b\"; distance:0; content:\"c\"; distance:0; content:\"d\"; distance:0; isdataat:!1,relative; ", false, 4);
178
179 TEST_RUN("abcabcabcabcabcabcabcabcabcabcd", 31, "content:\"a\"; content:\"b\"; within:1; distance:0; content:\"c\"; distance:0; within:1; pcre:\"/d/\";", true, 4);
180 TEST_RUN("abcabcabcabcabcabcabcabcabcabcd", 31, "content:\"a\"; content:\"b\"; within:1; distance:0; content:\"c\"; distance:0; within:1; pcre:\"/d/R\";", true, 4);
181 TEST_RUN("abcabcabcabcabcabcabcabcabcabcd", 31, "content:\"a\"; content:\"b\"; within:1; distance:0; content:\"c\"; distance:0; within:1; pcre:\"/^d/R\";", true, 31);
182
183 TEST_RUN("abcabcabcabcabcabcabcabcabcabcx", 31, "content:\"a\"; content:\"b\"; within:1; distance:0; content:\"c\"; distance:0; within:1; pcre:\"/d/\";", false, 4);
184 TEST_RUN("abcabcabcabcabcabcabcabcabcabcx", 31, "content:\"a\"; content:\"b\"; within:1; distance:0; content:\"c\"; distance:0; within:1; pcre:\"/d/R\";", false, 31);
185 TEST_RUN("abcabcabcabcabcabcabcabcabcabcx", 31, "content:\"a\"; content:\"b\"; within:1; distance:0; content:\"c\"; distance:0; within:1; pcre:\"/^d/R\";", false, 31);
187}
188
189/** \test mix in negation */
190static int DetectEngineContentInspectionTest08(void) {
192 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; content:!\"d\";", true, 3);
193 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; content:!\"c\";", false, 3);
194
195 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; content:!\"a\"; distance:0; within:1;", true, 5);
196 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; content:!\"a\"; distance:0; ", true, 5);
197
198 TEST_RUN("abcdefghy", 9, "content:\"a\"; content:!\"x\"; content:\"c\"; distance:0; within:2; ",
199 true, 3);
200 TEST_RUN("abcdefghx", 9, "content:\"a\"; content:!\"x\"; content:\"c\"; distance:0; within:2; ",
201 false, 2);
202 TEST_RUN("abcdefghy", 9,
203 "content:\"a\"; content:!\"x\"; content:!\"c\"; distance:2; within:1; ", true, 3);
204
205 TEST_RUN("aaabbbccc", 9, "content:\"ccc\"; endswith; content:!\"bccc\"; endswith; ", false, 2);
206 TEST_RUN("aaabbbccc", 9, "content:\"ccc\"; endswith; content:!\"accc\"; endswith; ", true, 2);
207 TEST_RUN("aaabbbccc", 9, "content:\"ccc\"; endswith; content:!\"bccc\"; endswith; depth:4; ",
208 true, 2);
209 TEST_RUN("aaabbbccc", 9, "content:\"ccc\"; endswith; content:!\"bccc\"; endswith; depth:9; ",
210 false, 2);
212}
213
214/** \test mix in byte_jump */
215static int DetectEngineContentInspectionTest09(void) {
217 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; content:!\"d\";", true, 3);
218 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; content:!\"c\";", false, 3);
219
220 TEST_RUN("abc03abcxyz", 11, "content:\"abc\"; byte_jump:2,0,relative,string,dec; content:\"xyz\"; within:3;", true, 3);
221 TEST_RUN("abc03abc03abcxyz", 16, "content:\"abc\"; byte_jump:2,0,relative,string,dec; content:\"xyz\"; within:3;", true, 5);
222 TEST_RUN("abc03abc03abcxyz", 16, "content:\"abc\"; byte_jump:2,0,relative,string,dec; content:\"xyz\"; within:3; isdataat:!1,relative;", true, 5);
223 TEST_RUN("abc03abc03abcxyz", 16, "content:\"abc\"; byte_jump:2,0,relative,string,dec; content:\"xyz\"; within:3; pcre:\"/klm$/R\";", false, 7);
224 TEST_RUN("abc03abc03abcxyzklm", 19, "content:\"abc\"; byte_jump:2,0,relative,string,dec; content:\"xyz\"; within:3; pcre:\"/klm$/R\";", true, 6);
225 TEST_RUN("abc03abc03abcxyzklx", 19, "content:\"abc\"; byte_jump:2,0,relative,string,dec; content:\"xyz\"; within:3; pcre:\"/^klm$/R\";", false, 7);
226 TEST_RUN("abc03abc03abc03abcxyzklm", 24, "content:\"abc\"; byte_jump:2,0,relative,string,dec; content:\"xyz\"; within:3; pcre:\"/^klm$/R\";", true, 8);
227
229}
230
231/** \test mix in byte_extract */
232static int DetectEngineContentInspectionTest10(void) {
234 /* extract first byte as length field and check with isdataat */
235 TEST_RUN("9abcdefghi", 10, "byte_extract:1,0,data_size,string; isdataat:data_size;", true, 2);
236 TEST_RUN("9abcdefgh", 9, "byte_extract:1,0,data_size,string; isdataat:!data_size;", true, 2);
237 /* anchor len field to pattern 'x' to test recursion */
238 TEST_RUN("x9x9abcdefghi", 13, "content:\"x\"; byte_extract:1,0,data_size,string,relative; isdataat:data_size,relative;", true, 3);
239 TEST_RUN("x9x9abcdefgh", 12, "content:\"x\"; byte_extract:1,0,data_size,string,relative; isdataat:!data_size,relative;", true, 5);
240 TEST_RUN("x9x9abcdefgh", 12, "content:\"x\"; depth:1; byte_extract:1,0,data_size,string,relative; isdataat:!data_size,relative;", false, 3);
241 /* first isdataat should fail, second succeed */
242 TEST_RUN("x9x5abcdef", 10,
243 "content:\"x\"; byte_extract:1,0,data_size,string,relative; "
244 "isdataat:data_size,relative;",
245 true, 5);
246 /* check for super high extracted values */
247 TEST_RUN("100000000abcdefghi", 18, "byte_extract:0,0,data_size,string; isdataat:data_size;", false, 2);
248 TEST_RUN("100000000abcdefghi", 18, "byte_extract:0,0,data_size,string; isdataat:!data_size;", true, 2);
250}
251
252static int DetectEngineContentInspectionTest11(void) {
254 TEST_RUN("ab", 2, "content:\"a\"; startswith; content:\"b\";", true, 2);
255 TEST_RUN("ab", 2, "content:\"a\"; startswith; content:\"b\"; within:1; distance:0;", true, 2);
256 TEST_RUN("ab", 2, "content:\"ab\"; startswith;", true, 1);
257 TEST_RUN("ab", 2, "content:\"a\"; startswith;", true, 1);
258 TEST_RUN("ab", 2, "content:\"b\"; startswith;", false, 1);
260}
261
262/** \test endswith (isdataat) recursion logic
263 * based on DetectEngineContentInspectionTest06 */
264static int DetectEngineContentInspectionTest12(void) {
266 // 6 steps: (1) a, (2) 1st b, (3) c not found, (4) 2nd b, (5) c found, endswith
267 TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"c\"; distance:0; within:1; endswith;", true, 5);
268
269 TEST_RUN("ababcabc", 8, "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"c\"; distance:0; within:1; endswith;", true, 7);
270
271 TEST_RUN("abcXYZ", 6, "content:\"abc\"; content:\"XYZ\"; distance:0; within:3; endswith;", true, 2);
272 TEST_RUN("abcXYZ", 6, "content:\"XYZ\"; distance:3; within:3; endswith;", true, 1);
273 TEST_RUN("abcXYZ", 6, "content:\"cXY\"; distance:2; within:3; endswith;", false, 1);
274 TEST_RUN("abcXYZ", 6, "content:!\"cXY\"; endswith;", true, 1);
275 TEST_RUN("abcXYZ", 6, "content:!\"XYZ\"; endswith;", false, 1);
276
277 TEST_RUN("xxxxxxxxxxxxxxxxxyYYYYYYYYYYYYYYYY", 34, "content:\"yYYYYYYYYYYYYYYYY\"; distance:9; within:29; endswith;", true, 1);
279}
280
281static int DetectEngineContentInspectionTest13(void) {
283 TEST_RUN("ab", 2, "content:\"a\"; startswith; content:\"b\"; endswith;", true, 2);
284 TEST_RUN("ab", 2, "content:\"a\"; startswith; content:\"b\"; within:1; distance:0; endswith;", true, 2);
285 TEST_RUN("ab", 2, "content:\"ab\"; startswith; endswith;", true, 1);
286 TEST_RUN("ab", 2, "content:\"a\"; startswith; endswith;", false, 1);
287 TEST_RUN("ab", 2, "content:\"b\"; startswith;", false, 1);
288 TEST_RUN("ab", 2, "content:\"b\"; startswith; endswith;", false, 1);
290}
291
292static int DetectEngineContentInspectionTest14(void)
293{
295 TEST_RUN("XYZ_klm_1234abcd_XYZ_klm_5678abcd", 33,
296 "content:\"XYZ\"; content:\"_klm_\"; distance:0; content:\"abcd\"; distance:4; "
297 "byte_test:4,=,1234,-8,relative,string;",
298 true, 4);
299 TEST_RUN("XYZ_klm_1234abcd_XYZ_klm_5678abcd", 33,
300 "content:\"XYZ\"; content:\"_klm_\"; distance:0; content:\"abcd\"; distance:4; "
301 "byte_test:4,=,5678,-8,relative,string;",
302 true, 5);
304}
305
306/** \brief negative distance */
307static int DetectEngineContentInspectionTest17(void)
308{
310 TEST_RUN("aaabbbcccdddee", 14,
311 "content:\"aaa\"; content:\"ee\"; within:2; distance:9; content:\"bbb\"; within:3; "
312 "distance:-11; content:\"ccc\"; within:3; distance:0;",
313 true, 4);
315}
316
318{
319 UtRegisterTest("DetectEngineContentInspectionTest01",
320 DetectEngineContentInspectionTest01);
321 UtRegisterTest("DetectEngineContentInspectionTest02",
322 DetectEngineContentInspectionTest02);
323 UtRegisterTest("DetectEngineContentInspectionTest03",
324 DetectEngineContentInspectionTest03);
325 UtRegisterTest("DetectEngineContentInspectionTest04",
326 DetectEngineContentInspectionTest04);
327 UtRegisterTest("DetectEngineContentInspectionTest05",
328 DetectEngineContentInspectionTest05);
329 UtRegisterTest("DetectEngineContentInspectionTest06",
330 DetectEngineContentInspectionTest06);
331 UtRegisterTest("DetectEngineContentInspectionTest07",
332 DetectEngineContentInspectionTest07);
333 UtRegisterTest("DetectEngineContentInspectionTest08",
334 DetectEngineContentInspectionTest08);
335 UtRegisterTest("DetectEngineContentInspectionTest09",
336 DetectEngineContentInspectionTest09);
337 UtRegisterTest("DetectEngineContentInspectionTest10",
338 DetectEngineContentInspectionTest10);
339 UtRegisterTest("DetectEngineContentInspectionTest11 startswith",
340 DetectEngineContentInspectionTest11);
341 UtRegisterTest("DetectEngineContentInspectionTest12 endswith",
342 DetectEngineContentInspectionTest12);
343 UtRegisterTest("DetectEngineContentInspectionTest13 mix startswith/endswith",
344 DetectEngineContentInspectionTest13);
345 UtRegisterTest("DetectEngineContentInspectionTest14 byte_test negative offset",
346 DetectEngineContentInspectionTest14);
347 UtRegisterTest("DetectEngineContentInspectionTest17 negative distance",
348 DetectEngineContentInspectionTest17);
349}
350
351#undef TEST_HEADER
352#undef TEST_RUN
353#undef TEST_FOOTER
thread_local uint32_t ut_inspection_recursion_counter
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
void DetectEngineContentInspectionRegisterTests(void)
#define TEST_RUN(buf, buflen, sig, match, steps)