1 /*
2  * Copyright (c) 2015-2017, Intel Corporation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *  * Redistributions of source code must retain the above copyright notice,
8  *    this list of conditions and the following disclaimer.
9  *  * Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *  * Neither the name of Intel Corporation nor the names of its contributors
13  *    may be used to endorse or promote products derived from this software
14  *    without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "config.h"
30 
31 #include "gtest/gtest.h"
32 #include "hs.h"
33 #include "test_util.h"
34 
35 static char garbage[] = "TEST(HyperscanArgChecks, DatabaseSizeNoDatabase) {" \
36                         "    size_t sz = hs_database_size(0);" \
37                         "    ASSERT_EQ(0, sz);";
38 
39 static unsigned lastMatchId = 0;
40 static unsigned long long lastMatchFrom = 0;
41 static unsigned long long lastMatchTo = 0;
42 static unsigned lastMatchFlags = 0;
43 static void *lastMatchCtx = nullptr;
44 
45 // Single match callback: record all the details from a single match
46 static
singleHandler(unsigned id,unsigned long long from,unsigned long long to,unsigned flags,void * ctx)47 int singleHandler(unsigned id, unsigned long long from,
48                   unsigned long long to, unsigned flags, void *ctx) {
49     lastMatchId = id;
50     lastMatchFrom = from;
51     lastMatchTo = to;
52     lastMatchFlags = flags;
53     lastMatchCtx = ctx;
54     return 0;
55 }
56 
57 namespace /* anonymous */ {
58 
59 // Break the magic number of the given database.
breakDatabaseMagic(hs_database * db)60 void breakDatabaseMagic(hs_database *db) {
61     // database magic should be 0xdbdb at the start
62     ASSERT_TRUE(memcmp("\xdb\xdb", db, 2) == 0);
63     *(char *)db = 0xdc;
64 }
65 
66 // Break the version number of the given database.
breakDatabaseVersion(hs_database * db)67 void breakDatabaseVersion(hs_database *db) {
68     // database version is the second u32
69     *((char *)db + 4) += 1;
70 }
71 
72 // Break the platform data of the given database.
breakDatabasePlatform(hs_database * db)73 void breakDatabasePlatform(hs_database *db) {
74     // database platform is an aligned u64a 16 bytes in
75     memset((char *)db + 16, 0xff, 8);
76 }
77 
78 // Break the alignment of the bytecode for the given database.
breakDatabaseBytecode(hs_database * db)79 void breakDatabaseBytecode(hs_database *db) {
80     // bytecode ptr is a u32, 36 bytes in
81     unsigned int *bytecode = (unsigned int *)((char *)db + 36);
82     ASSERT_NE(0U, *bytecode);
83     ASSERT_EQ(0U, (size_t)((char *)db + *bytecode) % 16U);
84     *bytecode += 3;
85 }
86 
87 // Check that hs_valid_platform says we can run here
TEST(HyperscanArgChecks,ValidPlatform)88 TEST(HyperscanArgChecks, ValidPlatform) {
89     hs_error_t error = hs_valid_platform();
90     ASSERT_EQ(HS_SUCCESS, error) << "hs_valid_platform should return zero";
91 }
92 
93 // Check that hs_version gives us a reasonable string back
TEST(HyperscanArgChecks,Version)94 TEST(HyperscanArgChecks, Version) {
95     const char *version = hs_version();
96     ASSERT_TRUE(version != nullptr);
97     ASSERT_TRUE(version[0] >= '0' && version[0] <= '9') << "First byte should be a digit.";
98     ASSERT_EQ('.', version[1]) << "Second byte should be a dot.";
99 }
100 
101 // hs_compile: Compile a NULL pattern (block mode)
TEST(HyperscanArgChecks,SingleCompileBlockNoPattern)102 TEST(HyperscanArgChecks, SingleCompileBlockNoPattern) {
103     hs_database_t *db = nullptr;
104     hs_compile_error_t *compile_err = nullptr;
105     hs_error_t err = hs_compile(nullptr, 0, HS_MODE_NOSTREAM, nullptr, &db,
106                                 &compile_err);
107     EXPECT_EQ(HS_COMPILER_ERROR, err);
108     EXPECT_TRUE(db == nullptr);
109     EXPECT_TRUE(compile_err != nullptr);
110     hs_free_compile_error(compile_err);
111 }
112 
113 // hs_compile: Compile a NULL pattern (streaming mode)
TEST(HyperscanArgChecks,SingleCompileStreamingNoPattern)114 TEST(HyperscanArgChecks, SingleCompileStreamingNoPattern) {
115     hs_database_t *db = nullptr;
116     hs_compile_error_t *compile_err = nullptr;
117     hs_error_t err = hs_compile(nullptr, 0, HS_MODE_STREAM, nullptr, &db,
118                                 &compile_err);
119     EXPECT_EQ(HS_COMPILER_ERROR, err);
120     EXPECT_TRUE(db == nullptr);
121     EXPECT_TRUE(compile_err != nullptr);
122     hs_free_compile_error(compile_err);
123 }
124 
125 // hs_compile: Compile a pattern to a NULL database ptr (block mode)
TEST(HyperscanArgChecks,SingleCompileBlockNoDatabase)126 TEST(HyperscanArgChecks, SingleCompileBlockNoDatabase) {
127     hs_compile_error_t *compile_err = nullptr;
128     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, nullptr, nullptr,
129                                 &compile_err);
130     EXPECT_EQ(HS_COMPILER_ERROR, err);
131     EXPECT_TRUE(compile_err != nullptr);
132     hs_free_compile_error(compile_err);
133 }
134 
135 // hs_compile: Compile a pattern to a NULL database ptr (streaming mode)
TEST(HyperscanArgChecks,SingleCompileStreamingNoDatabase)136 TEST(HyperscanArgChecks, SingleCompileStreamingNoDatabase) {
137     hs_compile_error_t *compile_err = nullptr;
138     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, nullptr,
139                                 &compile_err);
140     EXPECT_EQ(HS_COMPILER_ERROR, err);
141     EXPECT_TRUE(compile_err != nullptr);
142     hs_free_compile_error(compile_err);
143 }
144 
145 // hs_compile: Compile a pattern with no mode set
TEST(HyperscanArgChecks,SingleCompileNoMode)146 TEST(HyperscanArgChecks, SingleCompileNoMode) {
147     hs_database_t *db = nullptr;
148     hs_compile_error_t *compile_err = nullptr;
149     hs_error_t err = hs_compile("foobar", 0, 0, nullptr, &db, &compile_err);
150     EXPECT_EQ(HS_COMPILER_ERROR, err);
151     EXPECT_TRUE(compile_err != nullptr);
152     hs_free_compile_error(compile_err);
153 }
154 
155 // hs_compile: Compile a pattern with several modes set
TEST(HyperscanArgChecks,SingleCompileSeveralModes1)156 TEST(HyperscanArgChecks, SingleCompileSeveralModes1) {
157     hs_database_t *db = nullptr;
158     hs_compile_error_t *compile_err = nullptr;
159     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM | HS_MODE_NOSTREAM,
160                                 nullptr, &db, &compile_err);
161     EXPECT_EQ(HS_COMPILER_ERROR, err);
162     EXPECT_TRUE(compile_err != nullptr);
163     hs_free_compile_error(compile_err);
164 }
165 
166 // hs_compile: Compile a pattern with bogus flags
TEST(HyperscanArgChecks,SingleCompileBogusFlags)167 TEST(HyperscanArgChecks, SingleCompileBogusFlags) {
168     hs_database_t *db = nullptr;
169     hs_compile_error_t *compile_err = nullptr;
170     hs_error_t err = hs_compile("foobar", 0xdeadbeef, HS_MODE_NOSTREAM,
171                                 nullptr, &db, &compile_err);
172     EXPECT_EQ(HS_COMPILER_ERROR, err);
173     EXPECT_TRUE(compile_err != nullptr);
174     EXPECT_STREQ("only HS_FLAG_QUIET and HS_FLAG_SINGLEMATCH "
175                  "are supported in combination "
176                  "with HS_FLAG_COMBINATION.", compile_err->message);
177 
178     hs_free_compile_error(compile_err);
179 }
180 
181 // hs_compile: Compile a pattern with bogus mode flags set.
TEST(HyperscanArgChecks,SingleCompileBogusMode1)182 TEST(HyperscanArgChecks, SingleCompileBogusMode1) {
183     hs_database_t *db = nullptr;
184     hs_compile_error_t *compile_err = nullptr;
185 
186     unsigned mode = HS_MODE_STREAM | (1U << 30);
187 
188     hs_error_t err = hs_compile("foobar", 0, mode, nullptr, &db, &compile_err);
189     EXPECT_EQ(HS_COMPILER_ERROR, err);
190     ASSERT_TRUE(compile_err != nullptr);
191     ASSERT_STREQ("Invalid parameter: unrecognised mode flags.",
192                  compile_err->message);
193     hs_free_compile_error(compile_err);
194 }
195 
TEST(HyperscanArgChecks,SingleCompileBadTune)196 TEST(HyperscanArgChecks, SingleCompileBadTune) {
197     hs_database_t *db = nullptr;
198     hs_compile_error_t *compile_err = nullptr;
199     hs_platform_info_t plat;
200     plat.cpu_features = 0;
201     plat.tune = 42;
202     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, &plat, &db,
203                                 &compile_err);
204     EXPECT_EQ(HS_COMPILER_ERROR, err);
205     EXPECT_TRUE(compile_err != nullptr);
206     EXPECT_STREQ("Invalid tuning value specified in the platform information.",
207                  compile_err->message);
208 
209     hs_free_compile_error(compile_err);
210 }
211 
TEST(HyperscanArgChecks,SingleCompileBadFeatures)212 TEST(HyperscanArgChecks, SingleCompileBadFeatures) {
213     hs_database_t *db = nullptr;
214     hs_compile_error_t *compile_err = nullptr;
215     hs_platform_info_t plat;
216     plat.cpu_features = 42;
217     plat.tune = 0;
218     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, &plat, &db,
219                                 &compile_err);
220     EXPECT_EQ(HS_COMPILER_ERROR, err);
221     EXPECT_TRUE(compile_err != nullptr);
222     EXPECT_STREQ("Invalid cpu features specified in the platform information.",
223                  compile_err->message);
224 
225     hs_free_compile_error(compile_err);
226 }
227 
228 // hs_compile: Check SOM flag validation.
TEST(HyperscanArgChecks,SingleCompileSOMFlag)229 TEST(HyperscanArgChecks, SingleCompileSOMFlag) {
230 
231     // try using the flags without a SOM mode.
232     hs_database_t *db = nullptr;
233     hs_compile_error_t *compile_err = nullptr;
234     hs_error_t err = hs_compile("foobar", HS_FLAG_SOM_LEFTMOST, HS_MODE_STREAM,
235                                 nullptr, &db, &compile_err);
236     ASSERT_EQ(HS_COMPILER_ERROR, err) << "should have failed with flag "
237                                       << HS_FLAG_SOM_LEFTMOST;
238     ASSERT_TRUE(compile_err != nullptr);
239     hs_free_compile_error(compile_err);
240 }
241 
242 // hs_compile: Check SOM mode validation.
TEST(HyperscanArgChecks,SingleCompileSOMModes)243 TEST(HyperscanArgChecks, SingleCompileSOMModes) {
244     static const unsigned som_modes[] = {
245             HS_MODE_SOM_HORIZON_LARGE,
246             HS_MODE_SOM_HORIZON_MEDIUM,
247             HS_MODE_SOM_HORIZON_SMALL
248     };
249     const size_t num_modes = sizeof(som_modes)/sizeof(som_modes[0]);
250 
251     // compilation of a trivial case with a single mode set should be fine.
252     for (size_t i = 0; i < num_modes; i++) {
253         hs_database_t *db = nullptr;
254         hs_compile_error_t *compile_err = nullptr;
255         hs_error_t err = hs_compile("foobar", HS_FLAG_SOM_LEFTMOST,
256                                     HS_MODE_STREAM | som_modes[i], nullptr, &db,
257                                     &compile_err);
258         ASSERT_EQ(HS_SUCCESS, err);
259         hs_free_database(db);
260     }
261 
262     // you can only use one of the SOM modes at a time.
263     for (size_t i = 0; i < num_modes; i++) {
264         for (size_t j = i + 1; j < num_modes; j++) {
265             hs_database_t *db = nullptr;
266             hs_compile_error_t *compile_err = nullptr;
267             unsigned int mode = som_modes[i] | som_modes[j];
268             hs_error_t err = hs_compile("foobar", HS_FLAG_SOM_LEFTMOST,
269                                         HS_MODE_STREAM | mode, nullptr, &db,
270                                         &compile_err);
271             ASSERT_EQ(HS_COMPILER_ERROR, err)
272                 << "should have failed with mode " << mode;
273             ASSERT_TRUE(compile_err != nullptr);
274             hs_free_compile_error(compile_err);
275         }
276     }
277 }
278 
279 // hs_compile_multi: Compile a NULL pattern set (block mode)
TEST(HyperscanArgChecks,MultiCompileBlockNoPattern)280 TEST(HyperscanArgChecks, MultiCompileBlockNoPattern) {
281     hs_database_t *db = nullptr;
282     hs_compile_error_t *compile_err = nullptr;
283     hs_error_t err = hs_compile_multi(nullptr, nullptr, nullptr, 1, HS_MODE_NOSTREAM,
284                                       nullptr, &db, &compile_err);
285     EXPECT_EQ(HS_COMPILER_ERROR, err);
286     EXPECT_TRUE(db == nullptr);
287     EXPECT_TRUE(compile_err != nullptr);
288     hs_free_compile_error(compile_err);
289 }
290 
291 // hs_compile_multi: Compile a NULL pattern set (streaming mode)
TEST(HyperscanArgChecks,MultiCompileStreamingNoPattern)292 TEST(HyperscanArgChecks, MultiCompileStreamingNoPattern) {
293     hs_database_t *db = nullptr;
294     hs_compile_error_t *compile_err = nullptr;
295     hs_error_t err = hs_compile_multi(nullptr, nullptr, nullptr, 1, HS_MODE_STREAM,
296                                       nullptr, &db, &compile_err);
297     EXPECT_EQ(HS_COMPILER_ERROR, err);
298     EXPECT_TRUE(db == nullptr);
299     EXPECT_TRUE(compile_err != nullptr);
300     hs_free_compile_error(compile_err);
301 }
302 
303 // hs_compile_multi: Compile a set of zero patterns
TEST(HyperscanArgChecks,MultiCompileZeroPatterns)304 TEST(HyperscanArgChecks, MultiCompileZeroPatterns) {
305     hs_database_t *db = nullptr;
306     hs_compile_error_t *compile_err = nullptr;
307     const char *expr[] = {"foobar"};
308     hs_error_t err = hs_compile_multi(expr, nullptr, nullptr, 0, HS_MODE_NOSTREAM,
309                                       nullptr, &db, &compile_err);
310     EXPECT_EQ(HS_COMPILER_ERROR, err);
311     EXPECT_TRUE(db == nullptr);
312     EXPECT_TRUE(compile_err != nullptr);
313     hs_free_compile_error(compile_err);
314 }
315 
316 // hs_compile_multi: Compile a pattern to a NULL database ptr (block mode)
TEST(HyperscanArgChecks,MultiCompileBlockNoDatabase)317 TEST(HyperscanArgChecks, MultiCompileBlockNoDatabase) {
318     hs_compile_error_t *compile_err = nullptr;
319     const char *expr[] = {"foobar"};
320     hs_error_t err = hs_compile_multi(expr, nullptr, nullptr, 1, HS_MODE_NOSTREAM,
321                                       nullptr, nullptr, &compile_err);
322     EXPECT_EQ(HS_COMPILER_ERROR, err);
323     EXPECT_TRUE(compile_err != nullptr);
324     hs_free_compile_error(compile_err);
325 }
326 
327 // hs_compile_multi: Compile a pattern to a NULL database ptr (streaming mode)
TEST(HyperscanArgChecks,MultiCompileStreamingNoDatabase)328 TEST(HyperscanArgChecks, MultiCompileStreamingNoDatabase) {
329     hs_compile_error_t *compile_err = nullptr;
330     const char *expr[] = {"foobar"};
331     hs_error_t err = hs_compile_multi(expr, nullptr, nullptr, 1, HS_MODE_STREAM,
332                                       nullptr, nullptr, &compile_err);
333     EXPECT_EQ(HS_COMPILER_ERROR, err);
334     EXPECT_TRUE(compile_err != nullptr);
335     hs_free_compile_error(compile_err);
336 }
337 
338 // hs_open_stream: Open a stream with a NULL database ptr
TEST(HyperscanArgChecks,OpenStreamNoDatabase)339 TEST(HyperscanArgChecks, OpenStreamNoDatabase) {
340     hs_stream_t *stream = nullptr;
341     hs_error_t err = hs_open_stream(nullptr, 0, &stream);
342     EXPECT_NE(HS_SUCCESS, err);
343     EXPECT_TRUE(stream == nullptr);
344 }
345 
346 // hs_open_stream: Open a stream with a NULL stream ptr
TEST(HyperscanArgChecks,OpenStreamNoStreamId)347 TEST(HyperscanArgChecks, OpenStreamNoStreamId) {
348     hs_database_t *db = nullptr;
349     hs_compile_error_t *compile_err = nullptr;
350     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
351                                 &compile_err);
352     ASSERT_EQ(HS_SUCCESS, err);
353 
354     err = hs_open_stream(db, 0, nullptr);
355     ASSERT_EQ(HS_INVALID, err);
356 
357     // teardown
358     hs_free_database(db);
359 }
360 
361 // hs_open_stream: Open a stream with a non-streaming database
TEST(HyperscanArgChecks,OpenStreamWithBlockDatabase)362 TEST(HyperscanArgChecks, OpenStreamWithBlockDatabase) {
363     hs_stream_t *stream = nullptr;
364     hs_database_t *db = nullptr;
365     hs_compile_error_t *compile_err = nullptr;
366     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, nullptr, &db,
367                                 &compile_err);
368     ASSERT_EQ(HS_SUCCESS, err);
369 
370     err = hs_open_stream(db, 0, &stream);
371     EXPECT_NE(HS_SUCCESS, err);
372     EXPECT_TRUE(stream == nullptr);
373 
374     // teardown
375     hs_free_database(db);
376 }
377 
378 // hs_open_stream: Open a stream with a broken database bytecode
TEST(HyperscanArgChecks,OpenStreamWithBrokenDatabaseBytecode)379 TEST(HyperscanArgChecks, OpenStreamWithBrokenDatabaseBytecode) {
380     hs_stream_t *stream = nullptr;
381     hs_database_t *db = nullptr;
382     hs_compile_error_t *compile_err = nullptr;
383     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
384                                 &compile_err);
385     ASSERT_EQ(HS_SUCCESS, err);
386 
387     breakDatabaseBytecode(db);
388 
389     err = hs_open_stream(db, 0, &stream);
390     EXPECT_NE(HS_SUCCESS, err);
391     EXPECT_TRUE(stream == nullptr);
392 
393     // teardown
394     hs_free_database(db);
395 }
396 
397 // hs_scan_stream: Call with no stream ID
TEST(HyperscanArgChecks,ScanStreamNoStreamID)398 TEST(HyperscanArgChecks, ScanStreamNoStreamID) {
399     hs_database_t *db = nullptr;
400     hs_compile_error_t *compile_err = nullptr;
401     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
402                                 &compile_err);
403     ASSERT_EQ(HS_SUCCESS, err);
404     ASSERT_TRUE(db != nullptr);
405     hs_scratch_t *scratch = nullptr;
406     err = hs_alloc_scratch(db, &scratch);
407     ASSERT_EQ(HS_SUCCESS, err);
408     ASSERT_TRUE(scratch != nullptr);
409 
410     err = hs_scan_stream(nullptr, "data", 4, 0, scratch, dummy_cb, nullptr);
411     EXPECT_NE(HS_SUCCESS, err);
412     EXPECT_NE(HS_SCAN_TERMINATED, err);
413 
414     // teardown
415     err = hs_free_scratch(scratch);
416     ASSERT_EQ(HS_SUCCESS, err);
417     hs_free_database(db);
418 }
419 
420 // hs_scan_stream: Call with no data
TEST(HyperscanArgChecks,ScanStreamNoData)421 TEST(HyperscanArgChecks, ScanStreamNoData) {
422     hs_database_t *db = nullptr;
423     hs_compile_error_t *compile_err = nullptr;
424     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
425                                 &compile_err);
426     ASSERT_EQ(HS_SUCCESS, err);
427     ASSERT_TRUE(db != nullptr);
428     hs_scratch_t *scratch = nullptr;
429     err = hs_alloc_scratch(db, &scratch);
430     ASSERT_EQ(HS_SUCCESS, err);
431     ASSERT_TRUE(scratch != nullptr);
432     hs_stream_t *stream = nullptr;
433     err = hs_open_stream(db, 0, &stream);
434     ASSERT_EQ(HS_SUCCESS, err);
435     ASSERT_TRUE(stream != nullptr);
436 
437     err = hs_scan_stream(stream, nullptr, 4, 0, scratch, dummy_cb, nullptr);
438     EXPECT_NE(HS_SUCCESS, err);
439     EXPECT_NE(HS_SCAN_TERMINATED, err);
440 
441     // teardown
442     err = hs_close_stream(stream, scratch, dummy_cb, nullptr);
443     ASSERT_EQ(HS_SUCCESS, err);
444     err = hs_free_scratch(scratch);
445     ASSERT_EQ(HS_SUCCESS, err);
446     hs_free_database(db);
447 }
448 
449 // hs_scan_stream: Call with no scratch
TEST(HyperscanArgChecks,ScanStreamNoScratch)450 TEST(HyperscanArgChecks, ScanStreamNoScratch) {
451     hs_database_t *db = nullptr;
452     hs_compile_error_t *compile_err = nullptr;
453     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
454                                 &compile_err);
455     ASSERT_EQ(HS_SUCCESS, err);
456     ASSERT_TRUE(db != nullptr);
457     hs_scratch_t *scratch = nullptr;
458     err = hs_alloc_scratch(db, &scratch);
459     ASSERT_EQ(HS_SUCCESS, err);
460     ASSERT_TRUE(scratch != nullptr);
461     hs_stream_t *stream = nullptr;
462     err = hs_open_stream(db, 0, &stream);
463     ASSERT_EQ(HS_SUCCESS, err);
464     ASSERT_TRUE(stream != nullptr);
465 
466     err = hs_scan_stream(stream, nullptr, 4, 0, scratch, dummy_cb, nullptr);
467     EXPECT_NE(HS_SUCCESS, err);
468     EXPECT_NE(HS_SCAN_TERMINATED, err);
469 
470     // teardown
471     err = hs_close_stream(stream, scratch, dummy_cb, nullptr);
472     ASSERT_EQ(HS_SUCCESS, err);
473     err = hs_free_scratch(scratch);
474     ASSERT_EQ(HS_SUCCESS, err);
475     hs_free_database(db);
476 }
477 
478 // hs_close_stream: Call with no stream
TEST(HyperscanArgChecks,CloseStreamNoStream)479 TEST(HyperscanArgChecks, CloseStreamNoStream) {
480     hs_database_t *db = nullptr;
481     hs_compile_error_t *compile_err = nullptr;
482     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
483                                 &compile_err);
484     ASSERT_EQ(HS_SUCCESS, err);
485     ASSERT_TRUE(db != nullptr);
486     hs_scratch_t *scratch = nullptr;
487     err = hs_alloc_scratch(db, &scratch);
488     ASSERT_EQ(HS_SUCCESS, err);
489     ASSERT_TRUE(scratch != nullptr);
490 
491     err = hs_close_stream(nullptr, scratch, dummy_cb, nullptr);
492     ASSERT_NE(HS_SUCCESS, err);
493 
494     // teardown
495     err = hs_free_scratch(scratch);
496     ASSERT_EQ(HS_SUCCESS, err);
497     hs_free_database(db);
498 }
499 
500 // hs_close_stream: Call with no scratch
TEST(HyperscanArgChecks,CloseStreamNoScratch)501 TEST(HyperscanArgChecks, CloseStreamNoScratch) {
502     hs_database_t *db = nullptr;
503     hs_compile_error_t *compile_err = nullptr;
504     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
505                                 &compile_err);
506     ASSERT_EQ(HS_SUCCESS, err);
507     ASSERT_TRUE(db != nullptr);
508     hs_stream_t *stream = nullptr;
509     err = hs_open_stream(db, 0, &stream);
510     ASSERT_EQ(HS_SUCCESS, err);
511     ASSERT_TRUE(stream != nullptr);
512 
513     err = hs_close_stream(stream, nullptr, dummy_cb, nullptr);
514     EXPECT_NE(HS_SUCCESS, err);
515 
516     // We happen to know we can free the stream here, and we do it so that
517     // this doesn't appear as a memory leak in valgrind
518     free(stream);
519 
520     // teardown
521     hs_free_database(db);
522 }
523 
524 // hs_close_stream: Call with no scratch and no callback (allowed)
TEST(HyperscanArgChecks,CloseStreamNoScratchNoCallback)525 TEST(HyperscanArgChecks, CloseStreamNoScratchNoCallback) {
526     hs_database_t *db = nullptr;
527     hs_compile_error_t *compile_err = nullptr;
528     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
529                                 &compile_err);
530     ASSERT_EQ(HS_SUCCESS, err);
531     ASSERT_TRUE(db != nullptr);
532     hs_stream_t *stream = nullptr;
533     err = hs_open_stream(db, 0, &stream);
534     ASSERT_EQ(HS_SUCCESS, err);
535     ASSERT_TRUE(stream != nullptr);
536 
537     err = hs_close_stream(stream, nullptr, nullptr, nullptr);
538     EXPECT_EQ(HS_SUCCESS, err);
539 
540     // teardown
541     hs_free_database(db);
542 }
543 
544 // hs_close_stream_nomatch: Call with no stream
TEST(HyperscanArgChecks,CloseStreamNoMatchNoStream)545 TEST(HyperscanArgChecks, CloseStreamNoMatchNoStream) {
546     hs_database_t *db = nullptr;
547     hs_compile_error_t *compile_err = nullptr;
548     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
549                                 &compile_err);
550     ASSERT_EQ(HS_SUCCESS, err);
551     ASSERT_TRUE(db != nullptr);
552 
553     hs_scratch_t *scratch = nullptr;
554     err = hs_alloc_scratch(db, &scratch);
555     ASSERT_EQ(HS_SUCCESS, err);
556 
557     err = hs_close_stream(nullptr, scratch, nullptr, nullptr);
558     ASSERT_NE(HS_SUCCESS, err);
559 
560     // teardown
561     err = hs_free_scratch(scratch);
562     ASSERT_EQ(HS_SUCCESS, err);
563     hs_free_database(db);
564 }
565 
566 // hs_set_stream_context: change context
TEST(HyperscanArgChecks,ChangeStreamContext)567 TEST(HyperscanArgChecks, ChangeStreamContext) {
568     const char *str = "foobar";
569     hs_database_t *db = nullptr;
570     hs_compile_error_t *compile_err = nullptr;
571     hs_error_t err = hs_compile(str, 0, HS_MODE_STREAM, nullptr, &db,
572                                 &compile_err);
573     ASSERT_EQ(HS_SUCCESS, err);
574     ASSERT_TRUE(db != nullptr);
575 
576     hs_scratch_t *scratch = nullptr;
577     err = hs_alloc_scratch(db, &scratch);
578     ASSERT_EQ(HS_SUCCESS, err);
579     ASSERT_TRUE(scratch != nullptr);
580 
581     // we'll start with the context pointer set to the scratch space ...
582     hs_stream_t *stream = nullptr;
583     err = hs_open_stream(db, 0, &stream);
584     ASSERT_EQ(HS_SUCCESS, err);
585     ASSERT_TRUE(stream != nullptr);
586     err = hs_scan_stream(stream, str, strlen(str), 0, scratch, singleHandler,
587                          (void *)scratch);
588     ASSERT_EQ(HS_SUCCESS, err);
589 
590     ASSERT_EQ(lastMatchTo, strlen(str));
591     ASSERT_EQ(lastMatchCtx, scratch);
592 
593     // ... and then change it to the stream ptr itself.
594     err = hs_scan_stream(stream, str, strlen(str), 0, scratch, singleHandler,
595                          (void *)stream);
596     ASSERT_EQ(HS_SUCCESS, err);
597 
598     ASSERT_EQ(lastMatchTo, 2*strlen(str));
599     ASSERT_EQ(lastMatchCtx, stream);
600 
601     err = hs_close_stream(stream, scratch, nullptr, nullptr);
602     ASSERT_EQ(HS_SUCCESS, err);
603 
604     // teardown
605     hs_free_database(db);
606     err = hs_free_scratch(scratch);
607     ASSERT_EQ(HS_SUCCESS, err);
608 }
609 
610 // hs_reset_stream: Call with no stream id
TEST(HyperscanArgChecks,ResetStreamNoId)611 TEST(HyperscanArgChecks, ResetStreamNoId) {
612     hs_database_t *db = nullptr;
613     hs_compile_error_t *compile_err = nullptr;
614     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
615                                 &compile_err);
616     ASSERT_EQ(HS_SUCCESS, err);
617     ASSERT_TRUE(db != nullptr);
618 
619     hs_scratch_t *scratch = nullptr;
620     err = hs_alloc_scratch(db, &scratch);
621     ASSERT_EQ(HS_SUCCESS, err);
622 
623     err = hs_reset_stream(nullptr, 0, scratch, dummy_cb, nullptr);
624     ASSERT_EQ(HS_INVALID, err);
625     err = hs_free_scratch(scratch);
626     ASSERT_EQ(HS_SUCCESS, err);
627     hs_free_database(db);
628 }
629 
630 // hs_reset_stream: Call with no scratch
TEST(HyperscanArgChecks,ResetStreamNoScratch)631 TEST(HyperscanArgChecks, ResetStreamNoScratch) {
632     hs_stream_t *stream = nullptr;
633     hs_database_t *db = nullptr;
634     hs_compile_error_t *compile_err = nullptr;
635     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
636                                 &compile_err);
637     ASSERT_EQ(HS_SUCCESS, err);
638     ASSERT_TRUE(db != nullptr);
639 
640     err = hs_open_stream(db, 0, &stream);
641     ASSERT_EQ(HS_SUCCESS, err);
642     ASSERT_TRUE(stream != nullptr);
643 
644     err = hs_reset_stream(stream, 0, nullptr, dummy_cb, nullptr);
645     ASSERT_EQ(HS_INVALID, err);
646 
647     hs_scratch_t *scratch = nullptr;
648     err = hs_alloc_scratch(db, &scratch);
649     ASSERT_EQ(HS_SUCCESS, err);
650 
651     hs_close_stream(stream, scratch, nullptr, nullptr);
652     err = hs_free_scratch(scratch);
653     ASSERT_EQ(HS_SUCCESS, err);
654     hs_free_database(db);
655 }
656 
657 // hs_copy_stream: Call with no from_id
TEST(HyperscanArgChecks,CopyStreamNoFromId)658 TEST(HyperscanArgChecks, CopyStreamNoFromId) {
659     hs_stream_t *to;
660     hs_error_t err = hs_copy_stream(&to, nullptr);
661     ASSERT_EQ(HS_INVALID, err);
662 }
663 
664 // hs_copy_stream: Call with no to_id
TEST(HyperscanArgChecks,CopyStreamNoToId)665 TEST(HyperscanArgChecks, CopyStreamNoToId) {
666     hs_stream_t *stream = nullptr;
667     hs_database_t *db = nullptr;
668     hs_compile_error_t *compile_err = nullptr;
669     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
670                                 &compile_err);
671     ASSERT_EQ(HS_SUCCESS, err);
672 
673     err = hs_open_stream(db, 0, &stream);
674     ASSERT_EQ(HS_SUCCESS, err);
675     ASSERT_TRUE(stream != nullptr);
676 
677     err = hs_copy_stream(nullptr, stream);
678     ASSERT_EQ(HS_INVALID, err);
679 
680     hs_scratch_t *scratch = nullptr;
681     err = hs_alloc_scratch(db, &scratch);
682     ASSERT_EQ(HS_SUCCESS, err);
683 
684     hs_close_stream(stream, scratch, nullptr, nullptr);
685     err = hs_free_scratch(scratch);
686     ASSERT_EQ(HS_SUCCESS, err);
687     hs_free_database(db);
688 }
689 
TEST(HyperscanArgChecks,ResetAndCopyStreamNoToId)690 TEST(HyperscanArgChecks, ResetAndCopyStreamNoToId) {
691     hs_stream_t *stream = nullptr;
692     hs_database_t *db = nullptr;
693     hs_compile_error_t *compile_err = nullptr;
694     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
695                                 &compile_err);
696     ASSERT_EQ(HS_SUCCESS, err);
697 
698     hs_scratch_t *scratch = nullptr;
699     err = hs_alloc_scratch(db, &scratch);
700     ASSERT_EQ(HS_SUCCESS, err);
701 
702     err = hs_open_stream(db, 0, &stream);
703     ASSERT_EQ(HS_SUCCESS, err);
704     ASSERT_TRUE(stream != nullptr);
705 
706     err = hs_reset_and_copy_stream(nullptr, stream, scratch, nullptr, nullptr);
707     ASSERT_EQ(HS_INVALID, err);
708 
709     err = hs_close_stream(stream, scratch, nullptr, nullptr);
710     ASSERT_EQ(HS_SUCCESS, err);
711     err = hs_free_scratch(scratch);
712     ASSERT_EQ(HS_SUCCESS, err);
713     hs_free_database(db);
714 }
715 
TEST(HyperscanArgChecks,ResetAndCopyStreamNoFromId)716 TEST(HyperscanArgChecks, ResetAndCopyStreamNoFromId) {
717     hs_stream_t *stream = nullptr;
718     hs_database_t *db = nullptr;
719     hs_compile_error_t *compile_err = nullptr;
720     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
721                                 &compile_err);
722     ASSERT_EQ(HS_SUCCESS, err);
723 
724     hs_scratch_t *scratch = nullptr;
725     err = hs_alloc_scratch(db, &scratch);
726     ASSERT_EQ(HS_SUCCESS, err);
727 
728     err = hs_open_stream(db, 0, &stream);
729     ASSERT_EQ(HS_SUCCESS, err);
730     ASSERT_TRUE(stream != nullptr);
731 
732     err = hs_reset_and_copy_stream(stream, nullptr, scratch, nullptr, nullptr);
733     ASSERT_EQ(HS_INVALID, err);
734 
735     err = hs_close_stream(stream, scratch, nullptr, nullptr);
736     ASSERT_EQ(HS_SUCCESS, err);
737     err = hs_free_scratch(scratch);
738     ASSERT_EQ(HS_SUCCESS, err);
739     hs_free_database(db);
740 }
741 
TEST(HyperscanArgChecks,ResetAndCopyStreamSameToId)742 TEST(HyperscanArgChecks, ResetAndCopyStreamSameToId) {
743     hs_stream_t *stream = nullptr;
744     hs_database_t *db = nullptr;
745     hs_compile_error_t *compile_err = nullptr;
746     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
747                                 &compile_err);
748     ASSERT_EQ(HS_SUCCESS, err);
749 
750     hs_scratch_t *scratch = nullptr;
751     err = hs_alloc_scratch(db, &scratch);
752     ASSERT_EQ(HS_SUCCESS, err);
753 
754     err = hs_open_stream(db, 0, &stream);
755     ASSERT_EQ(HS_SUCCESS, err);
756     ASSERT_TRUE(stream != nullptr);
757 
758     err = hs_reset_and_copy_stream(stream, stream, scratch, nullptr, nullptr);
759     ASSERT_EQ(HS_INVALID, err);
760 
761     err = hs_close_stream(stream, scratch, nullptr, nullptr);
762     ASSERT_EQ(HS_SUCCESS, err);
763     err = hs_free_scratch(scratch);
764     ASSERT_EQ(HS_SUCCESS, err);
765     hs_free_database(db);
766 }
767 
768 // hs_reset_and_copy_stream: You're allowed to reset and copy a stream with no
769 // scratch and no callback.
TEST(HyperscanArgChecks,ResetAndCopyStreamNoCallbackOrScratch)770 TEST(HyperscanArgChecks, ResetAndCopyStreamNoCallbackOrScratch) {
771     hs_stream_t *stream = nullptr;
772     hs_stream_t *stream_to = nullptr;
773     hs_database_t *db = nullptr;
774     hs_compile_error_t *compile_err = nullptr;
775     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
776                                 &compile_err);
777     ASSERT_EQ(HS_SUCCESS, err);
778 
779     hs_scratch_t *scratch = nullptr;
780     err = hs_alloc_scratch(db, &scratch);
781     ASSERT_EQ(HS_SUCCESS, err);
782 
783     err = hs_open_stream(db, 0, &stream);
784     ASSERT_EQ(HS_SUCCESS, err);
785 
786     err = hs_open_stream(db, 0, &stream_to);
787     ASSERT_EQ(HS_SUCCESS, err);
788 
789     err = hs_reset_and_copy_stream(stream_to, stream, nullptr, nullptr, nullptr);
790     ASSERT_EQ(HS_SUCCESS, err);
791 
792     err = hs_close_stream(stream_to, scratch, nullptr, nullptr);
793     ASSERT_EQ(HS_SUCCESS, err);
794     err = hs_close_stream(stream, scratch, nullptr, nullptr);
795     ASSERT_EQ(HS_SUCCESS, err);
796     err = hs_free_scratch(scratch);
797     ASSERT_EQ(HS_SUCCESS, err);
798     hs_free_database(db);
799 }
800 
801 // hs_reset_and_copy_stream: If you specify a callback, you must provide
802 // scratch.
TEST(HyperscanArgChecks,ResetAndCopyStreamNoScratch)803 TEST(HyperscanArgChecks, ResetAndCopyStreamNoScratch) {
804     hs_stream_t *stream = nullptr;
805     hs_stream_t *stream_to = nullptr;
806     hs_database_t *db = nullptr;
807     hs_compile_error_t *compile_err = nullptr;
808     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
809                                 &compile_err);
810     ASSERT_EQ(HS_SUCCESS, err);
811 
812     hs_scratch_t *scratch = nullptr;
813     err = hs_alloc_scratch(db, &scratch);
814     ASSERT_EQ(HS_SUCCESS, err);
815 
816     err = hs_open_stream(db, 0, &stream);
817     ASSERT_EQ(HS_SUCCESS, err);
818 
819     err = hs_open_stream(db, 0, &stream_to);
820     ASSERT_EQ(HS_SUCCESS, err);
821 
822     err = hs_reset_and_copy_stream(stream_to, stream, nullptr, dummy_cb,
823                                    nullptr);
824     ASSERT_EQ(HS_INVALID, err);
825 
826     err = hs_close_stream(stream_to, scratch, nullptr, nullptr);
827     ASSERT_EQ(HS_SUCCESS, err);
828     err = hs_close_stream(stream, scratch, nullptr, nullptr);
829     ASSERT_EQ(HS_SUCCESS, err);
830     err = hs_free_scratch(scratch);
831     ASSERT_EQ(HS_SUCCESS, err);
832     hs_free_database(db);
833 }
834 
TEST(HyperscanArgChecks,ResetAndCopyStreamDiffDb)835 TEST(HyperscanArgChecks, ResetAndCopyStreamDiffDb) {
836     hs_stream_t *stream = nullptr;
837     hs_stream_t *stream_to = nullptr;
838     hs_database_t *db = nullptr;
839     hs_database_t *db2 = nullptr;
840     hs_compile_error_t *compile_err = nullptr;
841     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
842                                 &compile_err);
843     ASSERT_EQ(HS_SUCCESS, err);
844 
845     err = hs_compile("barfoo", 0, HS_MODE_STREAM, nullptr, &db2, &compile_err);
846     ASSERT_EQ(HS_SUCCESS, err);
847 
848     hs_scratch_t *scratch = nullptr;
849     err = hs_alloc_scratch(db, &scratch);
850     ASSERT_EQ(HS_SUCCESS, err);
851     err = hs_alloc_scratch(db2, &scratch);
852     ASSERT_EQ(HS_SUCCESS, err);
853 
854     err = hs_open_stream(db, 0, &stream);
855     ASSERT_EQ(HS_SUCCESS, err);
856 
857     err = hs_open_stream(db2, 0, &stream_to);
858     ASSERT_EQ(HS_SUCCESS, err);
859 
860     err = hs_reset_and_copy_stream(stream_to, stream, scratch, nullptr,
861                                    nullptr);
862     ASSERT_EQ(HS_INVALID, err);
863 
864     err = hs_close_stream(stream_to, scratch, nullptr, nullptr);
865     ASSERT_EQ(HS_SUCCESS, err);
866     err = hs_close_stream(stream, scratch, nullptr, nullptr);
867     ASSERT_EQ(HS_SUCCESS, err);
868     err = hs_free_scratch(scratch);
869     ASSERT_EQ(HS_SUCCESS, err);
870     hs_free_database(db);
871     hs_free_database(db2);
872 }
873 
874 // hs_scan: Call with no database
TEST(HyperscanArgChecks,ScanBlockNoDatabase)875 TEST(HyperscanArgChecks, ScanBlockNoDatabase) {
876     hs_database_t *db = nullptr;
877     hs_compile_error_t *compile_err = nullptr;
878     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, nullptr, &db,
879                                 &compile_err);
880     ASSERT_EQ(HS_SUCCESS, err);
881     ASSERT_TRUE(db != nullptr);
882     hs_scratch_t *scratch = nullptr;
883     err = hs_alloc_scratch(db, &scratch);
884     ASSERT_EQ(HS_SUCCESS, err);
885     ASSERT_TRUE(scratch != nullptr);
886     err = hs_scan(nullptr, "data", 4, 0, scratch, dummy_cb, nullptr);
887     ASSERT_NE(HS_SUCCESS, err);
888     EXPECT_NE(HS_SCAN_TERMINATED, err);
889 
890     // teardown
891     err = hs_free_scratch(scratch);
892     ASSERT_EQ(HS_SUCCESS, err);
893     hs_free_database(db);
894 }
895 
896 // hs_scan: Call with a database with broken magic
TEST(HyperscanArgChecks,ScanBlockBrokenDatabaseMagic)897 TEST(HyperscanArgChecks, ScanBlockBrokenDatabaseMagic) {
898     hs_database_t *db = nullptr;
899     hs_compile_error_t *compile_err = nullptr;
900     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, nullptr, &db,
901                                 &compile_err);
902     ASSERT_EQ(HS_SUCCESS, err);
903     ASSERT_TRUE(db != nullptr);
904     hs_scratch_t *scratch = nullptr;
905     err = hs_alloc_scratch(db, &scratch);
906     ASSERT_EQ(HS_SUCCESS, err);
907     ASSERT_TRUE(scratch != nullptr);
908 
909     // break the database here, after scratch alloc
910     breakDatabaseMagic(db);
911 
912     err = hs_scan(db, "data", 4, 0, scratch, dummy_cb, nullptr);
913     ASSERT_EQ(HS_INVALID, err);
914 
915     // teardown
916     err = hs_free_scratch(scratch);
917     ASSERT_EQ(HS_SUCCESS, err);
918     free(db);
919 }
920 
921 // hs_scan: Call with a database with broken version
TEST(HyperscanArgChecks,ScanBlockBrokenDatabaseVersion)922 TEST(HyperscanArgChecks, ScanBlockBrokenDatabaseVersion) {
923     hs_database_t *db = nullptr;
924     hs_compile_error_t *compile_err = nullptr;
925     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, nullptr, &db,
926                                 &compile_err);
927     ASSERT_EQ(HS_SUCCESS, err);
928     ASSERT_TRUE(db != nullptr);
929     hs_scratch_t *scratch = nullptr;
930     err = hs_alloc_scratch(db, &scratch);
931     ASSERT_EQ(HS_SUCCESS, err);
932     ASSERT_TRUE(scratch != nullptr);
933 
934     // break the database here, after scratch alloc
935     breakDatabaseVersion(db);
936 
937     err = hs_scan(db, "data", 4, 0, scratch, dummy_cb, nullptr);
938     ASSERT_EQ(HS_DB_VERSION_ERROR, err);
939 
940     // teardown
941     err = hs_free_scratch(scratch);
942     ASSERT_EQ(HS_SUCCESS, err);
943     hs_free_database(db);
944 }
945 
946 // hs_scan: Call with a database with broken bytecode offset
TEST(HyperscanArgChecks,ScanBlockBrokenDatabaseBytecode)947 TEST(HyperscanArgChecks, ScanBlockBrokenDatabaseBytecode) {
948     hs_database_t *db = nullptr;
949     hs_compile_error_t *compile_err = nullptr;
950     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, nullptr, &db,
951                                 &compile_err);
952     ASSERT_EQ(HS_SUCCESS, err);
953     ASSERT_TRUE(db != nullptr);
954     hs_scratch_t *scratch = nullptr;
955     err = hs_alloc_scratch(db, &scratch);
956     ASSERT_EQ(HS_SUCCESS, err);
957     ASSERT_TRUE(scratch != nullptr);
958 
959     // break the database here, after scratch alloc
960     breakDatabaseBytecode(db);
961 
962     err = hs_scan(db, "data", 4, 0, scratch, dummy_cb, nullptr);
963     ASSERT_EQ(HS_INVALID, err);
964 
965     // teardown
966     err = hs_free_scratch(scratch);
967     ASSERT_EQ(HS_SUCCESS, err);
968     hs_free_database(db);
969 }
970 
971 // hs_scan: Call with a database built for streaming mode
TEST(HyperscanArgChecks,ScanBlockStreamingDatabase)972 TEST(HyperscanArgChecks, ScanBlockStreamingDatabase) {
973     hs_database_t *db = nullptr;
974     hs_compile_error_t *compile_err = nullptr;
975     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
976                                 &compile_err);
977     ASSERT_EQ(HS_SUCCESS, err);
978     ASSERT_TRUE(db != nullptr);
979     hs_scratch_t *scratch = nullptr;
980     err = hs_alloc_scratch(db, &scratch);
981     ASSERT_EQ(HS_SUCCESS, err);
982     ASSERT_TRUE(scratch != nullptr);
983 
984     err = hs_scan(db, "data", 4, 0, scratch, dummy_cb, nullptr);
985     ASSERT_EQ(HS_DB_MODE_ERROR, err);
986 
987     // teardown
988     err = hs_free_scratch(scratch);
989     ASSERT_EQ(HS_SUCCESS, err);
990     hs_free_database(db);
991 }
992 
TEST(HyperscanArgChecks,ScanBlockVectoredDatabase)993 TEST(HyperscanArgChecks, ScanBlockVectoredDatabase) {
994     hs_database_t *db = nullptr;
995     hs_compile_error_t *compile_err = nullptr;
996     hs_error_t err = hs_compile("foobar", 0, HS_MODE_VECTORED, nullptr, &db,
997                                 &compile_err);
998     ASSERT_EQ(HS_SUCCESS, err);
999     ASSERT_TRUE(db != nullptr);
1000     hs_scratch_t *scratch = nullptr;
1001     err = hs_alloc_scratch(db, &scratch);
1002     ASSERT_EQ(HS_SUCCESS, err);
1003     ASSERT_TRUE(scratch != nullptr);
1004 
1005     err = hs_scan(db, "data", 4, 0, scratch, dummy_cb, nullptr);
1006     ASSERT_EQ(HS_DB_MODE_ERROR, err);
1007 
1008     // teardown
1009     err = hs_free_scratch(scratch);
1010     ASSERT_EQ(HS_SUCCESS, err);
1011     hs_free_database(db);
1012 }
1013 
1014 
1015 // hs_scan: Call with no data
TEST(HyperscanArgChecks,ScanBlockNoData)1016 TEST(HyperscanArgChecks, ScanBlockNoData) {
1017     hs_database_t *db = nullptr;
1018     hs_compile_error_t *compile_err = nullptr;
1019     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, nullptr, &db,
1020                                 &compile_err);
1021     ASSERT_EQ(HS_SUCCESS, err);
1022     ASSERT_TRUE(db != nullptr);
1023     hs_scratch_t *scratch = nullptr;
1024     err = hs_alloc_scratch(db, &scratch);
1025     ASSERT_EQ(HS_SUCCESS, err);
1026     ASSERT_TRUE(scratch != nullptr);
1027     err = hs_scan(db, nullptr, 4, 0, scratch, dummy_cb, nullptr);
1028     ASSERT_NE(HS_SUCCESS, err);
1029     EXPECT_NE(HS_SCAN_TERMINATED, err);
1030 
1031     // teardown
1032     err = hs_free_scratch(scratch);
1033     ASSERT_EQ(HS_SUCCESS, err);
1034     hs_free_database(db);
1035 }
1036 
1037 // hs_scan: Call with no scratch
TEST(HyperscanArgChecks,ScanBlockNoScratch)1038 TEST(HyperscanArgChecks, ScanBlockNoScratch) {
1039     hs_database_t *db = nullptr;
1040     hs_compile_error_t *compile_err = nullptr;
1041     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, nullptr, &db,
1042                                 &compile_err);
1043     ASSERT_EQ(HS_SUCCESS, err);
1044     ASSERT_TRUE(db != nullptr);
1045     err = hs_scan(db, "data", 4, 0, nullptr, dummy_cb, nullptr);
1046     ASSERT_NE(HS_SUCCESS, err);
1047     EXPECT_NE(HS_SCAN_TERMINATED, err);
1048 
1049     // teardown
1050     hs_free_database(db);
1051 }
1052 
1053 // hs_scan: Call with no event handler
TEST(HyperscanArgChecks,ScanBlockNoHandler)1054 TEST(HyperscanArgChecks, ScanBlockNoHandler) {
1055     hs_database_t *db = nullptr;
1056     hs_compile_error_t *compile_err = nullptr;
1057     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, nullptr, &db,
1058                                 &compile_err);
1059     ASSERT_EQ(HS_SUCCESS, err);
1060     ASSERT_TRUE(db != nullptr);
1061     hs_scratch_t *scratch = nullptr;
1062     err = hs_alloc_scratch(db, &scratch);
1063     ASSERT_EQ(HS_SUCCESS, err);
1064     ASSERT_TRUE(scratch != nullptr);
1065     err = hs_scan(db, "data", 4, 0, scratch, nullptr, nullptr);
1066     ASSERT_EQ(HS_SUCCESS, err);
1067     EXPECT_NE(HS_SCAN_TERMINATED, err);
1068 
1069     // teardown
1070     err = hs_free_scratch(scratch);
1071     ASSERT_EQ(HS_SUCCESS, err);
1072     hs_free_database(db);
1073 }
1074 
1075 // hs_scan_vector: Call with no database
TEST(HyperscanArgChecks,ScanVectorNoDatabase)1076 TEST(HyperscanArgChecks, ScanVectorNoDatabase) {
1077     hs_database_t *db = nullptr;
1078     hs_compile_error_t *compile_err = nullptr;
1079     hs_error_t err = hs_compile("foobar", 0, HS_MODE_VECTORED, nullptr, &db,
1080                                 &compile_err);
1081     ASSERT_EQ(HS_SUCCESS, err);
1082     ASSERT_TRUE(db != nullptr);
1083     hs_scratch_t *scratch = nullptr;
1084     err = hs_alloc_scratch(db, &scratch);
1085     ASSERT_EQ(HS_SUCCESS, err);
1086     ASSERT_TRUE(scratch != nullptr);
1087     const char *data[] = {"data", "data"};
1088     unsigned int len[] = {4, 4};
1089     err = hs_scan_vector(nullptr, data, len, 2, 0, scratch, dummy_cb, nullptr);
1090     ASSERT_NE(HS_SUCCESS, err);
1091     EXPECT_NE(HS_SCAN_TERMINATED, err);
1092 
1093     // teardown
1094     err = hs_free_scratch(scratch);
1095     ASSERT_EQ(HS_SUCCESS, err);
1096     hs_free_database(db);
1097 }
1098 
1099 // hs_scan_vector: Call with a database with broken magic
TEST(HyperscanArgChecks,ScanVectorBrokenDatabaseMagic)1100 TEST(HyperscanArgChecks, ScanVectorBrokenDatabaseMagic) {
1101     hs_database_t *db = nullptr;
1102     hs_compile_error_t *compile_err = nullptr;
1103     hs_error_t err = hs_compile("foobar", 0, HS_MODE_VECTORED, nullptr, &db,
1104                                 &compile_err);
1105     ASSERT_EQ(HS_SUCCESS, err);
1106     ASSERT_TRUE(db != nullptr);
1107     hs_scratch_t *scratch = nullptr;
1108     err = hs_alloc_scratch(db, &scratch);
1109     ASSERT_EQ(HS_SUCCESS, err);
1110     ASSERT_TRUE(scratch != nullptr);
1111 
1112     // break the database here, after scratch alloc
1113     breakDatabaseMagic(db);
1114 
1115     const char *data[] = {"data", "data"};
1116     unsigned int len[] = {4, 4};
1117     err = hs_scan_vector(db, data, len, 2, 0, scratch, dummy_cb, nullptr);
1118     ASSERT_EQ(HS_INVALID, err);
1119 
1120     // teardown
1121     err = hs_free_scratch(scratch);
1122     ASSERT_EQ(HS_SUCCESS, err);
1123     free(db);
1124 }
1125 
1126 // hs_scan_vector: Call with a database with broken version
TEST(HyperscanArgChecks,ScanVectorBrokenDatabaseVersion)1127 TEST(HyperscanArgChecks, ScanVectorBrokenDatabaseVersion) {
1128     hs_database_t *db = nullptr;
1129     hs_compile_error_t *compile_err = nullptr;
1130     hs_error_t err = hs_compile("foobar", 0, HS_MODE_VECTORED, nullptr, &db,
1131                                 &compile_err);
1132     ASSERT_EQ(HS_SUCCESS, err);
1133     ASSERT_TRUE(db != nullptr);
1134     hs_scratch_t *scratch = nullptr;
1135     err = hs_alloc_scratch(db, &scratch);
1136     ASSERT_EQ(HS_SUCCESS, err);
1137     ASSERT_TRUE(scratch != nullptr);
1138 
1139     // break the database here, after scratch alloc
1140     breakDatabaseVersion(db);
1141 
1142     const char *data[] = {"data", "data"};
1143     unsigned int len[] = {4, 4};
1144     err = hs_scan_vector(db, data, len, 2, 0, scratch, dummy_cb, nullptr);
1145     ASSERT_EQ(HS_DB_VERSION_ERROR, err);
1146 
1147     // teardown
1148     err = hs_free_scratch(scratch);
1149     ASSERT_EQ(HS_SUCCESS, err);
1150     hs_free_database(db);
1151 }
1152 
1153 // hs_scan_vector: Call with a database with broken bytecode offset
TEST(HyperscanArgChecks,ScanVectorBrokenDatabaseBytecode)1154 TEST(HyperscanArgChecks, ScanVectorBrokenDatabaseBytecode) {
1155     hs_database_t *db = nullptr;
1156     hs_compile_error_t *compile_err = nullptr;
1157     hs_error_t err = hs_compile("foobar", 0, HS_MODE_VECTORED, nullptr, &db,
1158                                 &compile_err);
1159     ASSERT_EQ(HS_SUCCESS, err);
1160     ASSERT_TRUE(db != nullptr);
1161     hs_scratch_t *scratch = nullptr;
1162     err = hs_alloc_scratch(db, &scratch);
1163     ASSERT_EQ(HS_SUCCESS, err);
1164     ASSERT_TRUE(scratch != nullptr);
1165 
1166     // break the database here, after scratch alloc
1167     breakDatabaseBytecode(db);
1168 
1169     const char *data[] = {"data", "data"};
1170     unsigned int len[] = {4, 4};
1171     err = hs_scan_vector(db, data, len, 2, 0, scratch, dummy_cb, nullptr);
1172     ASSERT_EQ(HS_INVALID, err);
1173 
1174     // teardown
1175     err = hs_free_scratch(scratch);
1176     ASSERT_EQ(HS_SUCCESS, err);
1177     hs_free_database(db);
1178 }
1179 
1180 // hs_scan_vector: Call with a database built for streaming mode
TEST(HyperscanArgChecks,ScanVectorStreamingDatabase)1181 TEST(HyperscanArgChecks, ScanVectorStreamingDatabase) {
1182     hs_database_t *db = nullptr;
1183     hs_compile_error_t *compile_err = nullptr;
1184     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
1185                                 &compile_err);
1186     ASSERT_EQ(HS_SUCCESS, err);
1187     ASSERT_TRUE(db != nullptr);
1188     hs_scratch_t *scratch = nullptr;
1189     err = hs_alloc_scratch(db, &scratch);
1190     ASSERT_EQ(HS_SUCCESS, err);
1191     ASSERT_TRUE(scratch != nullptr);
1192 
1193     const char *data[] = {"data", "data"};
1194     unsigned int len[] = {4, 4};
1195     err = hs_scan_vector(db, data, len, 2, 0, scratch, dummy_cb, nullptr);
1196     ASSERT_EQ(HS_DB_MODE_ERROR, err);
1197 
1198     // teardown
1199     err = hs_free_scratch(scratch);
1200     ASSERT_EQ(HS_SUCCESS, err);
1201     hs_free_database(db);
1202 }
1203 
TEST(HyperscanArgChecks,ScanVectorBlockDatabase)1204 TEST(HyperscanArgChecks, ScanVectorBlockDatabase) {
1205     hs_database_t *db = nullptr;
1206     hs_compile_error_t *compile_err = nullptr;
1207     hs_error_t err = hs_compile("foobar", 0, HS_MODE_BLOCK, nullptr, &db,
1208                                 &compile_err);
1209     ASSERT_EQ(HS_SUCCESS, err);
1210     ASSERT_TRUE(db != nullptr);
1211     hs_scratch_t *scratch = nullptr;
1212     err = hs_alloc_scratch(db, &scratch);
1213     ASSERT_EQ(HS_SUCCESS, err);
1214     ASSERT_TRUE(scratch != nullptr);
1215 
1216     const char *data[] = {"data", "data"};
1217     unsigned int len[] = {4, 4};
1218     err = hs_scan_vector(db, data, len, 2, 0, scratch, dummy_cb, nullptr);
1219     ASSERT_EQ(HS_DB_MODE_ERROR, err);
1220 
1221     // teardown
1222     err = hs_free_scratch(scratch);
1223     ASSERT_EQ(HS_SUCCESS, err);
1224     hs_free_database(db);
1225 }
1226 
1227 // hs_scan_vector: Call with null data
TEST(HyperscanArgChecks,ScanVectorNoDataArray)1228 TEST(HyperscanArgChecks, ScanVectorNoDataArray) {
1229     hs_database_t *db = nullptr;
1230     hs_compile_error_t *compile_err = nullptr;
1231     hs_error_t err = hs_compile("foobar", 0, HS_MODE_VECTORED, nullptr, &db,
1232                                 &compile_err);
1233     ASSERT_EQ(HS_SUCCESS, err);
1234     ASSERT_TRUE(db != nullptr);
1235     hs_scratch_t *scratch = nullptr;
1236     err = hs_alloc_scratch(db, &scratch);
1237     ASSERT_EQ(HS_SUCCESS, err);
1238     ASSERT_TRUE(scratch != nullptr);
1239 
1240     unsigned int len[] = {4, 4};
1241     err = hs_scan_vector(db, nullptr, len, 2, 0, scratch, dummy_cb, nullptr);
1242     ASSERT_NE(HS_SUCCESS, err);
1243     EXPECT_NE(HS_SCAN_TERMINATED, err);
1244 
1245     // teardown
1246     err = hs_free_scratch(scratch);
1247     ASSERT_EQ(HS_SUCCESS, err);
1248     hs_free_database(db);
1249 }
1250 
TEST(HyperscanArgChecks,ScanVectorNoDataBlock)1251 TEST(HyperscanArgChecks, ScanVectorNoDataBlock) {
1252     hs_database_t *db = nullptr;
1253     hs_compile_error_t *compile_err = nullptr;
1254     hs_error_t err = hs_compile("foobar", 0, HS_MODE_VECTORED, nullptr, &db,
1255                                 &compile_err);
1256     ASSERT_EQ(HS_SUCCESS, err);
1257     ASSERT_TRUE(db != nullptr);
1258     hs_scratch_t *scratch = nullptr;
1259     err = hs_alloc_scratch(db, &scratch);
1260     ASSERT_EQ(HS_SUCCESS, err);
1261     ASSERT_TRUE(scratch != nullptr);
1262 
1263     const char *data[] = {"data", nullptr};
1264     unsigned int len[] = {4, 4};
1265     err = hs_scan_vector(db, data, len, 2, 0, scratch, dummy_cb, nullptr);
1266     ASSERT_NE(HS_SUCCESS, err);
1267     EXPECT_NE(HS_SCAN_TERMINATED, err);
1268 
1269     // teardown
1270     err = hs_free_scratch(scratch);
1271     ASSERT_EQ(HS_SUCCESS, err);
1272     hs_free_database(db);
1273 }
1274 
TEST(HyperscanArgChecks,ScanVectorNoLenArray)1275 TEST(HyperscanArgChecks, ScanVectorNoLenArray) {
1276     hs_database_t *db = nullptr;
1277     hs_compile_error_t *compile_err = nullptr;
1278     hs_error_t err = hs_compile("foobar", 0, HS_MODE_VECTORED, nullptr, &db,
1279                                 &compile_err);
1280     ASSERT_EQ(HS_SUCCESS, err);
1281     ASSERT_TRUE(db != nullptr);
1282     hs_scratch_t *scratch = nullptr;
1283     err = hs_alloc_scratch(db, &scratch);
1284     ASSERT_EQ(HS_SUCCESS, err);
1285     ASSERT_TRUE(scratch != nullptr);
1286 
1287     const char *data[] = {"data", "data"};
1288     err = hs_scan_vector(db, data, nullptr, 2, 0, scratch, dummy_cb, nullptr);
1289     ASSERT_NE(HS_SUCCESS, err);
1290     EXPECT_NE(HS_SCAN_TERMINATED, err);
1291 
1292     // teardown
1293     err = hs_free_scratch(scratch);
1294     ASSERT_EQ(HS_SUCCESS, err);
1295     hs_free_database(db);
1296 }
1297 
1298 // hs_scan_vector: Call with no scratch
TEST(HyperscanArgChecks,ScanVectorNoScratch)1299 TEST(HyperscanArgChecks, ScanVectorNoScratch) {
1300     hs_database_t *db = nullptr;
1301     hs_compile_error_t *compile_err = nullptr;
1302     hs_error_t err = hs_compile("foobar", 0, HS_MODE_VECTORED, nullptr, &db,
1303                                 &compile_err);
1304     ASSERT_EQ(HS_SUCCESS, err);
1305     ASSERT_TRUE(db != nullptr);
1306     const char *data[] = {"data", "data"};
1307     unsigned int len[] = {4, 4};
1308     err = hs_scan_vector(db, data, len, 2, 0, nullptr, dummy_cb, nullptr);
1309     ASSERT_NE(HS_SUCCESS, err);
1310     EXPECT_NE(HS_SCAN_TERMINATED, err);
1311 
1312     // teardown
1313     hs_free_database(db);
1314 }
1315 
1316 // hs_scan_vector: Call with no event handler
TEST(HyperscanArgChecks,ScanVectorNoHandler)1317 TEST(HyperscanArgChecks, ScanVectorNoHandler) {
1318     hs_database_t *db = nullptr;
1319     hs_compile_error_t *compile_err = nullptr;
1320     hs_error_t err = hs_compile("foobar", 0, HS_MODE_VECTORED, nullptr, &db,
1321                                 &compile_err);
1322     ASSERT_EQ(HS_SUCCESS, err);
1323     ASSERT_TRUE(db != nullptr);
1324     hs_scratch_t *scratch = nullptr;
1325     err = hs_alloc_scratch(db, &scratch);
1326     ASSERT_EQ(HS_SUCCESS, err);
1327     ASSERT_TRUE(scratch != nullptr);
1328     const char *data[] = {"data", "data"};
1329     unsigned int len[] = {4, 4};
1330     err = hs_scan_vector(db, data, len, 2, 0, scratch, nullptr, nullptr);
1331     ASSERT_EQ(HS_SUCCESS, err);
1332     EXPECT_NE(HS_SCAN_TERMINATED, err);
1333 
1334     // teardown
1335     err = hs_free_scratch(scratch);
1336     ASSERT_EQ(HS_SUCCESS, err);
1337     hs_free_database(db);
1338 }
1339 
1340 // hs_alloc_scratch: Call with no database
TEST(HyperscanArgChecks,AllocScratchNoDatabase)1341 TEST(HyperscanArgChecks, AllocScratchNoDatabase) {
1342     hs_scratch_t *scratch = nullptr;
1343     hs_error_t err = hs_alloc_scratch(nullptr, &scratch);
1344     EXPECT_NE(HS_SUCCESS, err);
1345     EXPECT_TRUE(scratch == nullptr);
1346 }
1347 
1348 // hs_alloc_scratch: Call with NULL ptr-to-scratch
TEST(HyperscanArgChecks,AllocScratchNullScratchPtr)1349 TEST(HyperscanArgChecks, AllocScratchNullScratchPtr) {
1350     hs_database_t *db = nullptr;
1351     hs_compile_error_t *compile_err = nullptr;
1352     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, nullptr, &db,
1353                                 &compile_err);
1354     ASSERT_EQ(HS_SUCCESS, err);
1355     ASSERT_TRUE(db != nullptr);
1356 
1357     err = hs_alloc_scratch(db, nullptr);
1358     ASSERT_EQ(HS_INVALID, err);
1359 
1360     // teardown
1361     hs_free_database(db);
1362 }
1363 
1364 // hs_alloc_scratch: Call with bogus scratch
TEST(HyperscanArgChecks,AllocScratchBogusScratch)1365 TEST(HyperscanArgChecks, AllocScratchBogusScratch) {
1366     hs_database_t *db = nullptr;
1367     hs_compile_error_t *compile_err = nullptr;
1368     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, nullptr, &db,
1369                                 &compile_err);
1370     ASSERT_EQ(HS_SUCCESS, err);
1371     ASSERT_TRUE(db != nullptr);
1372     hs_scratch_t *blah = (hs_scratch_t *)malloc(100);
1373     ASSERT_TRUE(blah != nullptr);
1374     memset(blah, 0xf0, 100);
1375     err = hs_alloc_scratch(db, &blah);
1376     ASSERT_EQ(HS_INVALID, err);
1377 
1378     // teardown
1379     free(blah);
1380     hs_free_database(db);
1381 }
1382 
1383 // hs_alloc_scratch: Call with broken database magic
TEST(HyperscanArgChecks,AllocScratchBadDatabaseMagic)1384 TEST(HyperscanArgChecks, AllocScratchBadDatabaseMagic) {
1385     hs_database_t *db = nullptr;
1386     hs_compile_error_t *compile_err = nullptr;
1387     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, nullptr, &db,
1388                                 &compile_err);
1389     ASSERT_EQ(HS_SUCCESS, err);
1390     ASSERT_TRUE(db != nullptr);
1391 
1392     breakDatabaseMagic(db);
1393 
1394     hs_scratch_t *scratch = nullptr;
1395     err = hs_alloc_scratch(db, &scratch);
1396     ASSERT_EQ(HS_INVALID, err);
1397 
1398     // teardown
1399     free(db);
1400 }
1401 
1402 // hs_alloc_scratch: Call with broken database version
TEST(HyperscanArgChecks,AllocScratchBadDatabaseVersion)1403 TEST(HyperscanArgChecks, AllocScratchBadDatabaseVersion) {
1404     hs_database_t *db = nullptr;
1405     hs_compile_error_t *compile_err = nullptr;
1406     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, nullptr, &db,
1407                                 &compile_err);
1408     ASSERT_EQ(HS_SUCCESS, err);
1409     ASSERT_TRUE(db != nullptr);
1410 
1411     breakDatabaseVersion(db);
1412 
1413     hs_scratch_t *scratch = nullptr;
1414     err = hs_alloc_scratch(db, &scratch);
1415     ASSERT_EQ(HS_DB_VERSION_ERROR, err);
1416 
1417     // teardown
1418     hs_free_database(db);
1419 }
1420 
1421 // hs_alloc_scratch: Call with broken database platform
TEST(HyperscanArgChecks,AllocScratchBadDatabasePlatform)1422 TEST(HyperscanArgChecks, AllocScratchBadDatabasePlatform) {
1423     hs_database_t *db = nullptr;
1424     hs_compile_error_t *compile_err = nullptr;
1425     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, nullptr, &db,
1426                                 &compile_err);
1427     ASSERT_EQ(HS_SUCCESS, err);
1428     ASSERT_TRUE(db != nullptr);
1429 
1430     breakDatabasePlatform(db);
1431 
1432     hs_scratch_t *scratch = nullptr;
1433     err = hs_alloc_scratch(db, &scratch);
1434     ASSERT_EQ(HS_DB_PLATFORM_ERROR, err);
1435 
1436     // teardown
1437     hs_free_database(db);
1438 }
1439 
1440 // hs_alloc_scratch: Call with broken database bytecode alignment
TEST(HyperscanArgChecks,AllocScratchBadDatabaseBytecode)1441 TEST(HyperscanArgChecks, AllocScratchBadDatabaseBytecode) {
1442     hs_database_t *db = nullptr;
1443     hs_compile_error_t *compile_err = nullptr;
1444     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, nullptr, &db,
1445                                 &compile_err);
1446     ASSERT_EQ(HS_SUCCESS, err);
1447     ASSERT_TRUE(db != nullptr);
1448 
1449     breakDatabaseBytecode(db);
1450 
1451     hs_scratch_t *scratch = nullptr;
1452     err = hs_alloc_scratch(db, &scratch);
1453     ASSERT_EQ(HS_INVALID, err);
1454 
1455     // teardown
1456     hs_free_database(db);
1457 }
1458 
1459 // hs_alloc_scratch: Call with broken database CRC
TEST(HyperscanArgChecks,AllocScratchBadDatabaseCRC)1460 TEST(HyperscanArgChecks, AllocScratchBadDatabaseCRC) {
1461     hs_database_t *db = nullptr;
1462     hs_compile_error_t *compile_err = nullptr;
1463     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, nullptr, &db,
1464                                 &compile_err);
1465     ASSERT_EQ(HS_SUCCESS, err);
1466     ASSERT_TRUE(db != nullptr);
1467 
1468     size_t len = 0;
1469     err = hs_database_size(db, &len);
1470     ASSERT_EQ(HS_SUCCESS, err);
1471     ASSERT_NE(0U, len);
1472 
1473     // ensure that we're able to alloc scratch for the unbroken db.
1474     hs_scratch_t *scratch = nullptr;
1475     err = hs_alloc_scratch(db, &scratch);
1476     ASSERT_EQ(HS_SUCCESS, err);
1477     err = hs_free_scratch(scratch);
1478     ASSERT_EQ(HS_SUCCESS, err);
1479 
1480     // for want of a better case, corrupt the "middle byte" of the database.
1481     char *mid = (char *)db + len/2;
1482     *mid += 17;
1483 
1484     scratch = nullptr;
1485     err = hs_alloc_scratch(db, &scratch);
1486     ASSERT_EQ(HS_INVALID, err);
1487 
1488     // teardown
1489     hs_free_database(db);
1490 }
1491 
1492 // hs_clone_scratch: Call with no source scratch
TEST(HyperscanArgChecks,CloneScratchNoSource)1493 TEST(HyperscanArgChecks, CloneScratchNoSource) {
1494     hs_scratch_t *scratch = nullptr, *scratch2 = nullptr;
1495     hs_error_t err = hs_clone_scratch(scratch, &scratch2);
1496     EXPECT_NE(HS_SUCCESS, err);
1497     EXPECT_TRUE(scratch2 == nullptr);
1498 }
1499 
1500 // hs_serialize_database: Call with no database
TEST(HyperscanArgChecks,SerializeNoDatabase)1501 TEST(HyperscanArgChecks, SerializeNoDatabase) {
1502     char *bytes = nullptr;
1503     size_t length = 0;
1504     hs_error_t err = hs_serialize_database(nullptr, &bytes, &length);
1505     EXPECT_NE(HS_SUCCESS, err);
1506     EXPECT_TRUE(bytes == nullptr);
1507 }
1508 
1509 // hs_serialize_database: Call with no bytes ptr
TEST(HyperscanArgChecks,SerializeNoBuffer)1510 TEST(HyperscanArgChecks, SerializeNoBuffer) {
1511     hs_database_t *db = nullptr;
1512     hs_compile_error_t *compile_err = nullptr;
1513     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, nullptr, &db,
1514                                 &compile_err);
1515     ASSERT_EQ(HS_SUCCESS, err);
1516     ASSERT_TRUE(db != nullptr);
1517 
1518     size_t length = 0;
1519     err = hs_serialize_database(db, nullptr, &length);
1520     EXPECT_NE(HS_SUCCESS, err);
1521     EXPECT_EQ(0U, length);
1522 
1523     // teardown
1524     hs_free_database(db);
1525 }
1526 
1527 // hs_serialize_database: Call with no bytes ptr
TEST(HyperscanArgChecks,SerializeNoLength)1528 TEST(HyperscanArgChecks, SerializeNoLength) {
1529     hs_database_t *db = nullptr;
1530     hs_compile_error_t *compile_err = nullptr;
1531     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, nullptr, &db,
1532                                 &compile_err);
1533     ASSERT_EQ(HS_SUCCESS, err);
1534     ASSERT_TRUE(db != nullptr);
1535 
1536     char *buf = nullptr;
1537     err = hs_serialize_database(db, &buf, nullptr);
1538     EXPECT_NE(HS_SUCCESS, err);
1539     EXPECT_TRUE(buf == nullptr);
1540 
1541     // teardown
1542     hs_free_database(db);
1543 }
1544 
1545 // hs_stream_size: Call with no database
TEST(HyperscanArgChecks,StreamSizeNoDatabase)1546 TEST(HyperscanArgChecks, StreamSizeNoDatabase) {
1547     size_t sz;
1548     hs_error_t err = hs_stream_size(nullptr, &sz);
1549     ASSERT_EQ(HS_INVALID, err);
1550 }
1551 
1552 // hs_stream_size: Call with invalid database
TEST(HyperscanArgChecks,StreamSizeBogusDatabase)1553 TEST(HyperscanArgChecks, StreamSizeBogusDatabase) {
1554     hs_database_t *db = nullptr;
1555     hs_compile_error_t *compile_err = nullptr;
1556     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, nullptr, &db,
1557                                 &compile_err);
1558     ASSERT_EQ(HS_SUCCESS, err);
1559     ASSERT_TRUE(db != nullptr);
1560     size_t len;
1561     err = hs_database_size(db, &len);
1562     ASSERT_EQ(HS_SUCCESS, err);
1563     ASSERT_LT(0U, len);
1564 
1565     memset(db, 0xf0, len);
1566 
1567     size_t sz;
1568     err = hs_stream_size(db, &sz);
1569     ASSERT_EQ(HS_INVALID, err);
1570 
1571     free(db);
1572 }
1573 
1574 // hs_stream_size: Call with a block-mode database
TEST(HyperscanArgChecks,StreamSizeBlockDatabase)1575 TEST(HyperscanArgChecks, StreamSizeBlockDatabase) {
1576     hs_database_t *db = nullptr;
1577     hs_compile_error_t *compile_err = nullptr;
1578     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, nullptr, &db,
1579                                 &compile_err);
1580     ASSERT_EQ(HS_SUCCESS, err);
1581     ASSERT_TRUE(db != nullptr);
1582 
1583     size_t sz;
1584     err = hs_stream_size(db, &sz);
1585     ASSERT_EQ(HS_DB_MODE_ERROR, err);
1586 
1587     hs_free_database(db);
1588 }
1589 
TEST(HyperscanArgChecks,StreamSizeVectoredDatabase)1590 TEST(HyperscanArgChecks, StreamSizeVectoredDatabase) {
1591     hs_database_t *db = nullptr;
1592     hs_compile_error_t *compile_err = nullptr;
1593     hs_error_t err = hs_compile("foobar", 0, HS_MODE_VECTORED, nullptr, &db,
1594                                 &compile_err);
1595     ASSERT_EQ(HS_SUCCESS, err);
1596     ASSERT_TRUE(db != nullptr);
1597 
1598     size_t sz;
1599     err = hs_stream_size(db, &sz);
1600     ASSERT_EQ(HS_DB_MODE_ERROR, err);
1601 
1602     hs_free_database(db);
1603 }
1604 
TEST(HyperscanArgChecks,OpenStreamBlockDatabase)1605 TEST(HyperscanArgChecks, OpenStreamBlockDatabase) {
1606     hs_database_t *db = nullptr;
1607     hs_compile_error_t *compile_err = nullptr;
1608     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, nullptr, &db,
1609                                 &compile_err);
1610     ASSERT_EQ(HS_SUCCESS, err);
1611     ASSERT_TRUE(db != nullptr);
1612 
1613     hs_stream_t *id;
1614     err = hs_open_stream(db, 0, &id);
1615     ASSERT_EQ(HS_DB_MODE_ERROR, err);
1616 
1617     hs_free_database(db);
1618 }
1619 
TEST(HyperscanArgChecks,OpenStreamVectoredDatabase)1620 TEST(HyperscanArgChecks, OpenStreamVectoredDatabase) {
1621     hs_database_t *db = nullptr;
1622     hs_compile_error_t *compile_err = nullptr;
1623     hs_error_t err = hs_compile("foobar", 0, HS_MODE_VECTORED, nullptr, &db,
1624                                 &compile_err);
1625     ASSERT_EQ(HS_SUCCESS, err);
1626     ASSERT_TRUE(db != nullptr);
1627 
1628     hs_stream_t *id;
1629     err = hs_open_stream(db, 0, &id);
1630     ASSERT_EQ(HS_DB_MODE_ERROR, err);
1631 
1632     hs_free_database(db);
1633 }
1634 
1635 
1636 // hs_stream_size: Call with a real database
TEST(HyperscanArgChecks,StreamSizeRealDatabase)1637 TEST(HyperscanArgChecks, StreamSizeRealDatabase) {
1638     hs_database_t *db = nullptr;
1639     hs_compile_error_t *compile_err = nullptr;
1640     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
1641                                 &compile_err);
1642     ASSERT_EQ(HS_SUCCESS, err);
1643     ASSERT_TRUE(db != nullptr);
1644 
1645     size_t sz;
1646     err = hs_stream_size(db, &sz);
1647     ASSERT_EQ(HS_SUCCESS, err);
1648     ASSERT_NE(0U, sz)
1649         << "Stream-mode database should have non-zero stream size";
1650 
1651     hs_free_database(db);
1652 }
1653 
TEST(HyperscanArgChecks,StreamSizeNoSize)1654 TEST(HyperscanArgChecks, StreamSizeNoSize) {
1655     hs_database_t *db = nullptr;
1656     hs_compile_error_t *compile_err = nullptr;
1657     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
1658                                 &compile_err);
1659     ASSERT_EQ(HS_SUCCESS, err);
1660     ASSERT_TRUE(db != nullptr);
1661 
1662     err = hs_stream_size(db, nullptr);
1663     ASSERT_EQ(HS_INVALID, err);
1664 
1665     hs_free_database(db);
1666 }
1667 
1668 // hs_database_size: Call with no database
TEST(HyperscanArgChecks,DatabaseSizeNoDatabase)1669 TEST(HyperscanArgChecks, DatabaseSizeNoDatabase) {
1670     size_t sz;
1671     hs_error_t err = hs_database_size(nullptr, &sz);
1672     ASSERT_EQ(HS_INVALID, err);
1673 }
1674 
TEST(HyperscanArgChecks,DatabaseSizeNoSize)1675 TEST(HyperscanArgChecks, DatabaseSizeNoSize) {
1676     hs_database_t *db = nullptr;
1677     hs_compile_error_t *compile_err = nullptr;
1678     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
1679                                 &compile_err);
1680     ASSERT_EQ(HS_SUCCESS, err);
1681     ASSERT_TRUE(db != nullptr);
1682 
1683     err = hs_database_size(db, nullptr);
1684     ASSERT_EQ(HS_INVALID, err);
1685 
1686     hs_free_database(db);
1687 }
1688 
TEST(HyperscanArgChecks,DatabaseSizeBadDb)1689 TEST(HyperscanArgChecks, DatabaseSizeBadDb) {
1690     hs_database_t *db = (hs_database_t *)garbage;
1691     size_t sz;
1692 
1693     hs_error_t err = hs_database_size(db, &sz);
1694     ASSERT_EQ(HS_INVALID, err);
1695 }
1696 
TEST(HyperscanArgChecks,DatabaseInfoBadDb)1697 TEST(HyperscanArgChecks, DatabaseInfoBadDb) {
1698     hs_database_t *db = (hs_database_t *)garbage;
1699     char *info = garbage;
1700     hs_error_t err = hs_database_info(db, &info);
1701     ASSERT_EQ(HS_INVALID, err);
1702     ASSERT_TRUE(nullptr == info);
1703 }
1704 
TEST(HyperscanArgChecks,DatabaseInfoNullDb)1705 TEST(HyperscanArgChecks, DatabaseInfoNullDb) {
1706     char *info = garbage;
1707     hs_error_t err = hs_database_info(nullptr, &info);
1708     ASSERT_EQ(HS_INVALID, err);
1709     ASSERT_TRUE(nullptr == info);
1710 }
1711 
TEST(HyperscanArgChecks,DatabaseInfoNullInfo)1712 TEST(HyperscanArgChecks, DatabaseInfoNullInfo) {
1713     hs_database_t *db;
1714     hs_compile_error_t *c_err;
1715     static const char *pattern = "hatstand.*(badgerbrush|teakettle)";
1716 
1717     hs_error_t err = hs_compile(pattern, 0, HS_MODE_NOSTREAM, nullptr, &db, &c_err);
1718     ASSERT_EQ(HS_SUCCESS, err);
1719     ASSERT_TRUE(db != nullptr);
1720 
1721     err = hs_database_info(db, nullptr);
1722     ASSERT_EQ(HS_INVALID, err);
1723 
1724     hs_free_database(db);
1725 }
1726 
TEST(HyperscanArgChecks,SerializedDatabaseSizeBadLen)1727 TEST(HyperscanArgChecks, SerializedDatabaseSizeBadLen) {
1728     hs_database_t *db;
1729     hs_compile_error_t *c_err;
1730     static const char *pattern = "hatstand.*(badgerbrush|teakettle)";
1731 
1732     hs_error_t err = hs_compile(pattern, 0, HS_MODE_NOSTREAM, nullptr, &db, &c_err);
1733     ASSERT_EQ(HS_SUCCESS, err);
1734     ASSERT_TRUE(db != nullptr);
1735 
1736     size_t db_len;
1737     err = hs_database_size(db, &db_len);
1738     ASSERT_EQ(HS_SUCCESS, err);
1739     ASSERT_NE(0, db_len);
1740 
1741     char *bytes = nullptr;
1742     size_t bytes_len = 0;
1743 
1744     err = hs_serialize_database(db, &bytes, &bytes_len);
1745     ASSERT_EQ(HS_SUCCESS, err);
1746     ASSERT_NE(0, bytes_len);
1747 
1748     hs_free_database(db);
1749 
1750     size_t ser_len;
1751     err = hs_serialized_database_size(bytes, 16, &ser_len);
1752     ASSERT_EQ(HS_INVALID, err);
1753 
1754    free(bytes);
1755 }
1756 
TEST(HyperscanArgChecks,SerializedDatabaseSizeNoSize)1757 TEST(HyperscanArgChecks, SerializedDatabaseSizeNoSize) {
1758     hs_database_t *db;
1759     hs_compile_error_t *c_err;
1760     static const char *pattern = "hatstand.*(badgerbrush|teakettle)";
1761 
1762     hs_error_t err = hs_compile(pattern, 0, HS_MODE_NOSTREAM, nullptr, &db, &c_err);
1763     ASSERT_EQ(HS_SUCCESS, err);
1764     ASSERT_TRUE(db != nullptr);
1765 
1766     size_t db_len;
1767     err = hs_database_size(db, &db_len);
1768     ASSERT_EQ(HS_SUCCESS, err);
1769     ASSERT_NE(0, db_len);
1770 
1771     char *bytes = nullptr;
1772     size_t bytes_len = 0;
1773 
1774     err = hs_serialize_database(db, &bytes, &bytes_len);
1775     ASSERT_EQ(HS_SUCCESS, err);
1776     ASSERT_NE(0, bytes_len);
1777 
1778     hs_free_database(db);
1779 
1780     err = hs_serialized_database_size(bytes, bytes_len, nullptr);
1781     ASSERT_EQ(HS_INVALID, err);
1782 
1783    free(bytes);
1784 }
1785 
TEST(HyperscanArgChecks,SerializedDatabaseSizeNoBytes)1786 TEST(HyperscanArgChecks, SerializedDatabaseSizeNoBytes) {
1787     size_t sz;
1788     hs_error_t err = hs_serialized_database_size(nullptr, 1024, &sz);
1789     ASSERT_EQ(HS_INVALID, err);
1790 }
1791 
TEST(HyperscanArgChecks,SerializedDatabaseInfoBadLen)1792 TEST(HyperscanArgChecks, SerializedDatabaseInfoBadLen) {
1793     hs_database_t *db;
1794     hs_compile_error_t *c_err;
1795     static const char *pattern = "hatstand.*(badgerbrush|teakettle)";
1796 
1797     hs_error_t err = hs_compile(pattern, 0, HS_MODE_NOSTREAM, nullptr, &db, &c_err);
1798     ASSERT_EQ(HS_SUCCESS, err);
1799     ASSERT_TRUE(db != nullptr);
1800 
1801     size_t db_len;
1802     err = hs_database_size(db, &db_len);
1803     ASSERT_EQ(HS_SUCCESS, err);
1804     ASSERT_NE(0, db_len);
1805 
1806     char *bytes = nullptr;
1807     size_t bytes_len = 0;
1808 
1809     err = hs_serialize_database(db, &bytes, &bytes_len);
1810     ASSERT_EQ(HS_SUCCESS, err);
1811     ASSERT_NE(0, bytes_len);
1812 
1813     hs_free_database(db);
1814 
1815     char *info = garbage;
1816     err = hs_serialized_database_info(bytes, 16, &info);
1817     ASSERT_EQ(HS_INVALID, err);
1818     ASSERT_TRUE(nullptr == info);
1819 
1820    free(bytes);
1821 }
1822 
TEST(HyperscanArgChecks,SerializedDatabaseInfoNoInfo)1823 TEST(HyperscanArgChecks, SerializedDatabaseInfoNoInfo) {
1824     hs_database_t *db;
1825     hs_compile_error_t *c_err;
1826     static const char *pattern = "hatstand.*(badgerbrush|teakettle)";
1827 
1828     hs_error_t err = hs_compile(pattern, 0, HS_MODE_NOSTREAM, nullptr, &db, &c_err);
1829     ASSERT_EQ(HS_SUCCESS, err);
1830     ASSERT_TRUE(db != nullptr);
1831 
1832     size_t db_len;
1833     err = hs_database_size(db, &db_len);
1834     ASSERT_EQ(HS_SUCCESS, err);
1835     ASSERT_NE(0, db_len);
1836 
1837     char *bytes = nullptr;
1838     size_t bytes_len = 0;
1839 
1840     err = hs_serialize_database(db, &bytes, &bytes_len);
1841     ASSERT_EQ(HS_SUCCESS, err);
1842     ASSERT_NE(0, bytes_len);
1843 
1844     hs_free_database(db);
1845 
1846     err = hs_serialized_database_info(bytes, bytes_len, nullptr);
1847     ASSERT_EQ(HS_INVALID, err);
1848 
1849    free(bytes);
1850 }
1851 
TEST(HyperscanArgChecks,SerializedDatabaseInfoNoBytes)1852 TEST(HyperscanArgChecks, SerializedDatabaseInfoNoBytes) {
1853     char *info = garbage;
1854     hs_error_t err = hs_serialized_database_info(nullptr, 1024, &info);
1855     ASSERT_EQ(HS_INVALID, err);
1856     ASSERT_TRUE(nullptr == info);
1857 }
1858 
TEST(HyperscanArgChecks,DeserializeDatabaseNoBytes)1859 TEST(HyperscanArgChecks, DeserializeDatabaseNoBytes) {
1860     hs_database_t *db = nullptr;
1861     hs_error_t err = hs_deserialize_database(nullptr, 2048, &db);
1862     ASSERT_EQ(HS_INVALID, err);
1863 }
1864 
TEST(HyperscanArgChecks,DeserializeDatabaseAtNoBytes)1865 TEST(HyperscanArgChecks, DeserializeDatabaseAtNoBytes) {
1866     hs_database_t *db = nullptr;
1867     hs_error_t err = hs_deserialize_database_at(nullptr, 2048, db);
1868     ASSERT_EQ(HS_INVALID, err);
1869 }
1870 
1871 static
makeSerializedDatabase(char ** bytes,size_t * length)1872 void makeSerializedDatabase(char **bytes, size_t *length) {
1873     hs_database_t *db = buildDB("(foo.*bar){3,}", 0, 0, HS_MODE_BLOCK);
1874     ASSERT_NE(nullptr, db);
1875     hs_error_t err = hs_serialize_database(db, bytes, length);
1876     ASSERT_EQ(HS_SUCCESS, err);
1877     hs_free_database(db);
1878 }
1879 
TEST(HyperscanArgChecks,DeserializeDatabaseNoDb)1880 TEST(HyperscanArgChecks, DeserializeDatabaseNoDb) {
1881     char *bytes = nullptr;
1882     size_t length = 0;
1883     makeSerializedDatabase(&bytes, &length);
1884     hs_error_t err = hs_deserialize_database(bytes, length, nullptr);
1885     ASSERT_EQ(HS_INVALID, err);
1886     free(bytes);
1887 }
1888 
TEST(HyperscanArgChecks,DeserializeDatabaseBadLen)1889 TEST(HyperscanArgChecks, DeserializeDatabaseBadLen) {
1890     char *bytes = nullptr;
1891     size_t length = 0;
1892     makeSerializedDatabase(&bytes, &length);
1893     hs_database_t *db = nullptr;
1894     hs_error_t err = hs_deserialize_database(bytes, length - 1, &db);
1895     ASSERT_EQ(HS_INVALID, err);
1896     free(bytes);
1897 }
1898 
TEST(HyperscanArgChecks,DeserializeDatabaseBadLen2)1899 TEST(HyperscanArgChecks, DeserializeDatabaseBadLen2) {
1900     char *bytes = nullptr;
1901     size_t length = 0;
1902     makeSerializedDatabase(&bytes, &length);
1903     hs_database_t *db = nullptr;
1904     hs_error_t err = hs_deserialize_database(bytes, length + 1, &db);
1905     ASSERT_EQ(HS_INVALID, err);
1906     free(bytes);
1907 }
1908 
TEST(HyperscanArgChecks,DeserializeDatabaseBadBytes)1909 TEST(HyperscanArgChecks, DeserializeDatabaseBadBytes) {
1910     char *bytes = nullptr;
1911     size_t length = 0;
1912     makeSerializedDatabase(&bytes, &length);
1913     memset(bytes, 0xff, length); // scribble
1914     hs_database_t *db = nullptr;
1915     hs_error_t err = hs_deserialize_database(bytes, length, &db);
1916     ASSERT_EQ(HS_INVALID, err);
1917     free(bytes);
1918 }
1919 
TEST(HyperscanArgChecks,DeserializeDatabaseBadBytes2)1920 TEST(HyperscanArgChecks, DeserializeDatabaseBadBytes2) {
1921     char *bytes = nullptr;
1922     size_t length = 0;
1923     makeSerializedDatabase(&bytes, &length);
1924     memset(bytes, 0, length); // scribble
1925     hs_database_t *db = nullptr;
1926     hs_error_t err = hs_deserialize_database(bytes, length, &db);
1927     ASSERT_EQ(HS_INVALID, err);
1928     free(bytes);
1929 }
1930 
TEST(HyperscanArgChecks,DeserializeDatabaseAtNoDb)1931 TEST(HyperscanArgChecks, DeserializeDatabaseAtNoDb) {
1932     char *bytes = nullptr;
1933     size_t length = 0;
1934     makeSerializedDatabase(&bytes, &length);
1935     hs_error_t err = hs_deserialize_database_at(bytes, length, nullptr);
1936     ASSERT_EQ(HS_INVALID, err);
1937     free(bytes);
1938 }
1939 
TEST(HyperscanArgChecks,DeserializeDatabaseAtBadLen)1940 TEST(HyperscanArgChecks, DeserializeDatabaseAtBadLen) {
1941     char *bytes = nullptr;
1942     size_t length = 0;
1943     makeSerializedDatabase(&bytes, &length);
1944     size_t db_length = 0;
1945     hs_error_t err = hs_serialized_database_size(bytes, length, &db_length);
1946     ASSERT_EQ(HS_SUCCESS, err);
1947     hs_database_t *db = (hs_database_t *)malloc(db_length);
1948     err = hs_deserialize_database_at(bytes, length - 1, db);
1949     ASSERT_EQ(HS_INVALID, err);
1950     free(bytes);
1951     free(db);
1952 }
1953 
TEST(HyperscanArgChecks,DeserializeDatabaseAtBadLen2)1954 TEST(HyperscanArgChecks, DeserializeDatabaseAtBadLen2) {
1955     char *bytes = nullptr;
1956     size_t length = 0;
1957     makeSerializedDatabase(&bytes, &length);
1958     size_t db_length = 0;
1959     hs_error_t err = hs_serialized_database_size(bytes, length, &db_length);
1960     ASSERT_EQ(HS_SUCCESS, err);
1961     hs_database_t *db = (hs_database_t *)malloc(db_length);
1962     err = hs_deserialize_database_at(bytes, length + 1, db);
1963     ASSERT_EQ(HS_INVALID, err);
1964     free(bytes);
1965     free(db);
1966 }
1967 
TEST(HyperscanArgChecks,DeserializeDatabaseAtBadBytes)1968 TEST(HyperscanArgChecks, DeserializeDatabaseAtBadBytes) {
1969     char *bytes = nullptr;
1970     size_t length = 0;
1971     makeSerializedDatabase(&bytes, &length);
1972     size_t db_length = 0;
1973     hs_error_t err = hs_serialized_database_size(bytes, length, &db_length);
1974     ASSERT_EQ(HS_SUCCESS, err);
1975     hs_database_t *db = (hs_database_t *)malloc(db_length);
1976     memset(bytes, 0xff, length); // scribble
1977     err = hs_deserialize_database_at(bytes, length, db);
1978     ASSERT_EQ(HS_INVALID, err);
1979     free(bytes);
1980     free(db);
1981 }
1982 
TEST(HyperscanArgChecks,DeserializeDatabaseAtBadBytes2)1983 TEST(HyperscanArgChecks, DeserializeDatabaseAtBadBytes2) {
1984     char *bytes = nullptr;
1985     size_t length = 0;
1986     makeSerializedDatabase(&bytes, &length);
1987     size_t db_length = 0;
1988     hs_error_t err = hs_serialized_database_size(bytes, length, &db_length);
1989     ASSERT_EQ(HS_SUCCESS, err);
1990     hs_database_t *db = (hs_database_t *)malloc(db_length);
1991     memset(bytes, 0, length); // scribble
1992     err = hs_deserialize_database_at(bytes, length, db);
1993     ASSERT_EQ(HS_INVALID, err);
1994     free(bytes);
1995     free(db);
1996 }
1997 
TEST(HyperscanArgChecks,ScratchSizeNoSize)1998 TEST(HyperscanArgChecks, ScratchSizeNoSize) {
1999     hs_error_t err;
2000 
2001     // build a database
2002     hs_database_t *db = nullptr;
2003     hs_compile_error_t *compile_err = nullptr;
2004     err = hs_compile("foo.*bar$", 0, HS_MODE_STREAM, nullptr, &db, &compile_err);
2005     ASSERT_EQ(HS_SUCCESS, err);
2006 
2007     // alloc some scratch
2008     hs_scratch_t *scratch = nullptr;
2009     err = hs_alloc_scratch(db, &scratch);
2010     ASSERT_EQ(HS_SUCCESS, err);
2011     EXPECT_TRUE(scratch != nullptr);
2012 
2013     err = hs_scratch_size(scratch, nullptr);
2014     ASSERT_EQ(HS_INVALID, err);
2015 
2016     err = hs_free_scratch(scratch);
2017     ASSERT_EQ(HS_SUCCESS, err);
2018     hs_free_database(db);
2019 }
2020 
TEST(HyperscanArgChecks,ScratchSizeNoScratch)2021 TEST(HyperscanArgChecks, ScratchSizeNoScratch) {
2022     size_t size;
2023     hs_error_t err = hs_scratch_size(nullptr, &size);
2024     ASSERT_EQ(HS_INVALID, err);
2025 }
2026 
TEST(HyperscanArgChecks,ScratchSizeBadScratch)2027 TEST(HyperscanArgChecks, ScratchSizeBadScratch) {
2028     hs_scratch_t *scratch = (hs_scratch_t *)garbage;
2029     size_t size;
2030     hs_error_t err = hs_scratch_size(scratch, &size);
2031     ASSERT_EQ(HS_INVALID, err);
2032 }
2033 
2034 // hs_clone_scratch: bad scratch arg
TEST(HyperscanArgChecks,CloneBadScratch)2035 TEST(HyperscanArgChecks, CloneBadScratch) {
2036     // Try cloning the scratch
2037     void *local_garbage = malloc(sizeof(garbage));
2038     ASSERT_TRUE(local_garbage != nullptr);
2039     memcpy(local_garbage, garbage, sizeof(garbage));
2040     hs_scratch_t *cloned = nullptr;
2041     hs_scratch_t *scratch = (hs_scratch_t *)local_garbage;
2042     hs_error_t err = hs_clone_scratch(scratch, &cloned);
2043     free(local_garbage);
2044     ASSERT_EQ(HS_INVALID, err);
2045 }
2046 
2047 // hs_scan: bad scratch arg
TEST(HyperscanArgChecks,ScanBadScratch)2048 TEST(HyperscanArgChecks, ScanBadScratch) {
2049     hs_database_t *db = nullptr;
2050     hs_compile_error_t *compile_err = nullptr;
2051     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, nullptr, &db,
2052                                 &compile_err);
2053     ASSERT_EQ(HS_SUCCESS, err);
2054     ASSERT_TRUE(db != nullptr);
2055 
2056     void *local_garbage = malloc(sizeof(garbage));
2057     ASSERT_TRUE(local_garbage != nullptr);
2058     memcpy(local_garbage, garbage, sizeof(garbage));
2059 
2060     hs_scratch_t *scratch = (hs_scratch_t *)local_garbage;
2061     err = hs_scan(db, "data", 4, 0, scratch, dummy_cb, nullptr);
2062     free(local_garbage);
2063     ASSERT_EQ(HS_INVALID, err);
2064 
2065     // teardown
2066     hs_free_database(db);
2067 }
2068 
2069 // hs_scan_stream: bad scratch arg
TEST(HyperscanArgChecks,ScanStreamBadScratch)2070 TEST(HyperscanArgChecks, ScanStreamBadScratch) {
2071     hs_database_t *db = nullptr;
2072     hs_compile_error_t *compile_err = nullptr;
2073     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
2074                                 &compile_err);
2075     ASSERT_EQ(HS_SUCCESS, err);
2076     ASSERT_TRUE(db != nullptr);
2077     void *local_garbage = malloc(sizeof(garbage));
2078     ASSERT_TRUE(local_garbage != nullptr);
2079     memcpy(local_garbage, garbage, sizeof(garbage));
2080     hs_scratch_t *scratch = (hs_scratch_t *)local_garbage;
2081 
2082     hs_stream_t *stream = nullptr;
2083     err = hs_open_stream(db, 0, &stream);
2084     ASSERT_EQ(HS_SUCCESS, err);
2085     ASSERT_TRUE(stream != nullptr);
2086 
2087     err = hs_scan_stream(stream, "data", 4, 0, scratch, nullptr, nullptr);
2088     EXPECT_NE(HS_SUCCESS, err);
2089     EXPECT_NE(HS_SCAN_TERMINATED, err);
2090 
2091     // teardown
2092     err = hs_close_stream(stream, scratch, dummy_cb, nullptr);
2093     EXPECT_EQ(HS_INVALID, err);
2094     scratch = nullptr;
2095     err = hs_alloc_scratch(db, &scratch);
2096     ASSERT_EQ(HS_SUCCESS, err);
2097     ASSERT_TRUE(scratch != nullptr);
2098     hs_close_stream(stream, scratch, nullptr, nullptr);
2099     hs_free_database(db);
2100     err = hs_free_scratch(scratch);
2101     ASSERT_EQ(HS_SUCCESS, err);
2102     free(local_garbage);
2103 }
2104 
2105 // hs_reset_stream: bad scratch arg
TEST(HyperscanArgChecks,ResetStreamBadScratch)2106 TEST(HyperscanArgChecks, ResetStreamBadScratch) {
2107     hs_database_t *db = nullptr;
2108     hs_compile_error_t *compile_err = nullptr;
2109     hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
2110                                 &compile_err);
2111     ASSERT_EQ(HS_SUCCESS, err);
2112     ASSERT_TRUE(db != nullptr);
2113     void *local_garbage = malloc(sizeof(garbage));
2114     ASSERT_TRUE(local_garbage != nullptr);
2115     memcpy(local_garbage, garbage, sizeof(garbage));
2116     hs_scratch_t *scratch = (hs_scratch_t *)local_garbage;
2117 
2118     hs_stream_t *stream = nullptr;
2119     err = hs_open_stream(db, 0, &stream);
2120     ASSERT_EQ(HS_SUCCESS, err);
2121     ASSERT_TRUE(stream != nullptr);
2122 
2123     err = hs_reset_stream(stream, 0, scratch, dummy_cb, nullptr);
2124     EXPECT_NE(HS_SUCCESS, err);
2125     EXPECT_NE(HS_SCAN_TERMINATED, err);
2126 
2127     // teardown
2128     err = hs_close_stream(stream, scratch, dummy_cb, nullptr);
2129     EXPECT_EQ(HS_INVALID, err);
2130     scratch = nullptr;
2131     err = hs_alloc_scratch(db, &scratch);
2132     ASSERT_EQ(HS_SUCCESS, err);
2133     ASSERT_TRUE(scratch != nullptr);
2134     hs_close_stream(stream, scratch, nullptr, nullptr);
2135     hs_free_database(db);
2136     err = hs_free_scratch(scratch);
2137     ASSERT_EQ(HS_SUCCESS, err);
2138     free(local_garbage);
2139 }
2140 
2141 // hs_scan_stream: bad scratch arg
TEST(HyperscanArgChecks,ScanVectorBadScratch)2142 TEST(HyperscanArgChecks, ScanVectorBadScratch) {
2143     hs_database_t *db = nullptr;
2144     hs_compile_error_t *compile_err = nullptr;
2145     hs_error_t err = hs_compile("foobar", 0, HS_MODE_VECTORED, nullptr, &db,
2146                                 &compile_err);
2147     ASSERT_EQ(HS_SUCCESS, err);
2148     ASSERT_TRUE(db != nullptr);
2149     void *local_garbage = malloc(sizeof(garbage));
2150     ASSERT_TRUE(local_garbage != nullptr);
2151     memcpy(local_garbage, garbage, sizeof(garbage));
2152     hs_scratch_t *scratch = (hs_scratch_t *)local_garbage;
2153 
2154     const char *data[] = { "data" };
2155     unsigned int len[] = { 4 };
2156 
2157     err = hs_scan_vector(db, data, len, 1, 0, scratch, dummy_cb, nullptr);
2158 
2159     EXPECT_NE(HS_SUCCESS, err);
2160     EXPECT_NE(HS_SCAN_TERMINATED, err);
2161 
2162     // teardown
2163     hs_free_database(db);
2164     free(local_garbage);
2165 }
2166 
2167 // hs_scan: bad (freed) scratch arg
2168 // disabled as, unsurprisingly, valgrind complains
2169 #ifdef TEST_FREED_MEM
TEST(HyperscanArgChecks,ScanFreedScratch)2170 TEST(HyperscanArgChecks, ScanFreedScratch) {
2171     hs_database_t *db = 0;
2172     hs_compile_error_t *compile_err = 0;
2173     hs_error_t err = hs_compile("foobar", 0, HS_MODE_NOSTREAM, NULL, &db,
2174                                 &compile_err);
2175     ASSERT_EQ(HS_SUCCESS, err);
2176     ASSERT_TRUE(db != NULL);
2177     hs_scratch_t *scratch = 0;
2178     err = hs_alloc_scratch(db, &scratch);
2179     ASSERT_EQ(HS_SUCCESS, err);
2180     ASSERT_TRUE(scratch != NULL);
2181     err = hs_free_scratch(scratch);
2182     ASSERT_EQ(HS_SUCCESS, err);
2183     err = hs_scan(db, "data", 4, 0, scratch, dummy_cb, 0);
2184     ASSERT_EQ(HS_INVALID, err);
2185     EXPECT_NE(HS_SCAN_TERMINATED, err);
2186 
2187     // teardown
2188     hs_free_database(db);
2189 }
2190 #endif // TEST_FREED_MEM
2191 
2192 // hs_expression_info: Compile a NULL pattern
TEST(HyperscanArgChecks,ExprInfoNullExpression)2193 TEST(HyperscanArgChecks, ExprInfoNullExpression) {
2194     hs_expr_info_t *info = nullptr;
2195     hs_compile_error_t *compile_err = nullptr;
2196     hs_error_t err = hs_expression_info(nullptr, 0, &info, &compile_err);
2197     EXPECT_EQ(HS_COMPILER_ERROR, err);
2198     EXPECT_TRUE(info == nullptr);
2199     EXPECT_TRUE(compile_err != nullptr);
2200     hs_free_compile_error(compile_err);
2201 }
2202 
2203 // hs_expression_info: NULL info block ptr
TEST(HyperscanArgChecks,ExprInfoNullInfoPtr)2204 TEST(HyperscanArgChecks, ExprInfoNullInfoPtr) {
2205     hs_compile_error_t *compile_err = nullptr;
2206     hs_error_t err = hs_expression_info("foobar", 0, nullptr, &compile_err);
2207     EXPECT_EQ(HS_COMPILER_ERROR, err);
2208     EXPECT_TRUE(compile_err != nullptr);
2209     hs_free_compile_error(compile_err);
2210 }
2211 
2212 // hs_expression_info: No compiler error block
TEST(HyperscanArgChecks,ExprInfoNullErrPtr)2213 TEST(HyperscanArgChecks, ExprInfoNullErrPtr) {
2214     hs_expr_info_t *info = nullptr;
2215     hs_error_t err = hs_expression_info("foobar", 0, &info, nullptr);
2216     EXPECT_EQ(HS_COMPILER_ERROR, err);
2217     EXPECT_TRUE(info == nullptr);
2218 }
2219 
2220 // hs_expression_ext_info: Compile a NULL pattern
TEST(HyperscanArgChecks,ExprExtInfoNullExpression)2221 TEST(HyperscanArgChecks, ExprExtInfoNullExpression) {
2222     hs_expr_info_t *info = nullptr;
2223     hs_compile_error_t *compile_err = nullptr;
2224     hs_error_t err =
2225         hs_expression_ext_info(nullptr, 0, nullptr, &info, &compile_err);
2226     EXPECT_EQ(HS_COMPILER_ERROR, err);
2227     EXPECT_TRUE(info == nullptr);
2228     EXPECT_TRUE(compile_err != nullptr);
2229     hs_free_compile_error(compile_err);
2230 }
2231 
2232 // hs_expression_ext_info: NULL info block ptr
TEST(HyperscanArgChecks,ExprExtInfoNullInfoPtr)2233 TEST(HyperscanArgChecks, ExprExtInfoNullInfoPtr) {
2234     hs_compile_error_t *compile_err = nullptr;
2235     hs_error_t err =
2236         hs_expression_ext_info("foobar", 0, nullptr, nullptr, &compile_err);
2237     EXPECT_EQ(HS_COMPILER_ERROR, err);
2238     EXPECT_TRUE(compile_err != nullptr);
2239     hs_free_compile_error(compile_err);
2240 }
2241 
2242 // hs_expression_ext_info: No compiler error block
TEST(HyperscanArgChecks,ExprExtInfoNullErrPtr)2243 TEST(HyperscanArgChecks, ExprExtInfoNullErrPtr) {
2244     hs_expr_info_t *info = nullptr;
2245     hs_error_t err =
2246         hs_expression_ext_info("foobar", 0, nullptr, &info, nullptr);
2247     EXPECT_EQ(HS_COMPILER_ERROR, err);
2248     EXPECT_TRUE(info == nullptr);
2249 }
2250 
TEST(HyperscanArgChecks,hs_free_database_null)2251 TEST(HyperscanArgChecks, hs_free_database_null) {
2252     hs_error_t err = hs_free_database(nullptr);
2253     ASSERT_EQ(HS_SUCCESS, err);
2254 }
2255 
TEST(HyperscanArgChecks,hs_free_database_garbage)2256 TEST(HyperscanArgChecks, hs_free_database_garbage) {
2257     hs_error_t err = hs_free_database((hs_database_t *)garbage);
2258     ASSERT_EQ(HS_INVALID, err);
2259 }
2260 
TEST(HyperscanArgChecks,hs_free_scratch_null)2261 TEST(HyperscanArgChecks, hs_free_scratch_null) {
2262     hs_error_t err = hs_free_scratch(nullptr);
2263     ASSERT_EQ(HS_SUCCESS, err);
2264 }
2265 
TEST(HyperscanArgChecks,hs_free_scratch_garbage)2266 TEST(HyperscanArgChecks, hs_free_scratch_garbage) {
2267     hs_error_t err = hs_free_scratch((hs_scratch_t *)garbage);
2268     ASSERT_EQ(HS_INVALID, err);
2269 }
2270 
TEST(HyperscanArgChecks,hs_free_compile_error_null)2271 TEST(HyperscanArgChecks, hs_free_compile_error_null) {
2272     hs_error_t err = hs_free_compile_error(nullptr);
2273     ASSERT_EQ(HS_SUCCESS, err);
2274 }
2275 
TEST(HyperscanArgChecks,multicompile_mix_highlander_1)2276 TEST(HyperscanArgChecks, multicompile_mix_highlander_1) {
2277     hs_database_t *db = nullptr;
2278     hs_compile_error_t *compile_err = nullptr;
2279     const char *expr[] = {"aoo[A-K]", "bar[L-Z]"};
2280     unsigned flags[] = {HS_FLAG_SINGLEMATCH, 0};
2281     unsigned ids[] = {30, 30};
2282     hs_error_t err = hs_compile_multi(expr, flags, ids, 2, HS_MODE_NOSTREAM,
2283                                       nullptr, &db, &compile_err);
2284     ASSERT_EQ(HS_COMPILER_ERROR, err);
2285     hs_free_compile_error(compile_err);
2286 }
2287 
TEST(HyperscanArgChecks,multicompile_mix_highlander_2)2288 TEST(HyperscanArgChecks, multicompile_mix_highlander_2) {
2289     hs_database_t *db = nullptr;
2290     hs_compile_error_t *compile_err = nullptr;
2291     const char *expr[] = {"aoo[A-K]", "bar[L-Z]"};
2292     unsigned flags[] = {0, HS_FLAG_SINGLEMATCH};
2293     unsigned ids[] = {30, 30};
2294     hs_error_t err = hs_compile_multi(expr, flags, ids, 2, HS_MODE_NOSTREAM,
2295                                       nullptr, &db, &compile_err);
2296     ASSERT_EQ(HS_COMPILER_ERROR, err);
2297     hs_free_compile_error(compile_err);
2298 }
2299 
TEST(HyperscanArgChecks,multicompile_nomix_highlander_1)2300 TEST(HyperscanArgChecks, multicompile_nomix_highlander_1) {
2301     hs_database_t *db = nullptr;
2302     hs_compile_error_t *compile_err = nullptr;
2303     const char *expr[] = {"aoo[A-K]", "bar[L-Z]"};
2304     unsigned flags[] = {HS_FLAG_SINGLEMATCH, HS_FLAG_SINGLEMATCH};
2305     unsigned ids[] = {30, 30};
2306     hs_error_t err = hs_compile_multi(expr, flags, ids, 2, HS_MODE_NOSTREAM,
2307                                       nullptr, &db, &compile_err);
2308     ASSERT_EQ(HS_SUCCESS, err);
2309     hs_free_database(db);
2310 }
2311 
TEST(HyperscanArgChecks,multicompile_nomix_highlander_2)2312 TEST(HyperscanArgChecks, multicompile_nomix_highlander_2) {
2313     hs_database_t *db = nullptr;
2314     hs_compile_error_t *compile_err = nullptr;
2315     const char *expr[] = {"aoo[A-K]", "bar[L-Z]"};
2316     unsigned flags[] = {0, 0};
2317     unsigned ids[] = {30, 30};
2318     hs_error_t err = hs_compile_multi(expr, flags, ids, 2, HS_MODE_NOSTREAM,
2319                                       nullptr, &db, &compile_err);
2320     ASSERT_EQ(HS_SUCCESS, err);
2321     hs_free_database(db);
2322 }
2323 
TEST(HyperscanArgChecks,hs_populate_platform_null)2324 TEST(HyperscanArgChecks, hs_populate_platform_null) {
2325     hs_error_t err = hs_populate_platform(nullptr);
2326     ASSERT_EQ(HS_INVALID, err);
2327 }
2328 
TEST(HyperscanArgChecks,CompressStreamNoStream)2329 TEST(HyperscanArgChecks, CompressStreamNoStream) {
2330     char buf[100];
2331     size_t used;
2332     hs_error_t err = hs_compress_stream(nullptr, buf, sizeof(buf), &used);
2333     ASSERT_EQ(HS_INVALID, err);
2334 }
2335 
TEST(HyperscanArgChecks,CompressStreamNoUsed)2336 TEST(HyperscanArgChecks, CompressStreamNoUsed) {
2337     hs_database_t *db = buildDB("(foo.*bar){3,}", 0, 0, HS_MODE_STREAM);
2338     ASSERT_NE(nullptr, db);
2339 
2340     hs_stream_t *stream;
2341     hs_error_t err = hs_open_stream(db, 0, &stream);
2342     ASSERT_EQ(HS_SUCCESS, err);
2343 
2344     char buf[100];
2345     err = hs_compress_stream(stream, buf, sizeof(buf), nullptr);
2346     ASSERT_EQ(HS_INVALID, err);
2347 
2348     err = hs_close_stream(stream, nullptr, nullptr, nullptr);
2349     ASSERT_EQ(HS_SUCCESS, err);
2350 
2351     err = hs_free_database(db);
2352     ASSERT_EQ(HS_SUCCESS, err);
2353 }
2354 
TEST(HyperscanArgChecks,CompressStreamNoBuf)2355 TEST(HyperscanArgChecks, CompressStreamNoBuf) {
2356     hs_database_t *db = buildDB("(foo.*bar){3,}", 0, 0, HS_MODE_STREAM);
2357     ASSERT_NE(nullptr, db);
2358 
2359     hs_stream_t *stream;
2360     hs_error_t err = hs_open_stream(db, 0, &stream);
2361     ASSERT_EQ(HS_SUCCESS, err);
2362 
2363     char buf[100];
2364     size_t used;
2365     err = hs_compress_stream(stream, nullptr, sizeof(buf), &used);
2366     ASSERT_EQ(HS_INVALID, err);
2367 
2368     err = hs_close_stream(stream, nullptr, nullptr, nullptr);
2369     ASSERT_EQ(HS_SUCCESS, err);
2370 
2371     err = hs_free_database(db);
2372     ASSERT_EQ(HS_SUCCESS, err);
2373 }
2374 
TEST(HyperscanArgChecks,CompressStreamSmallBuff)2375 TEST(HyperscanArgChecks, CompressStreamSmallBuff) {
2376     hs_database_t *db = buildDB("(foo.*bar){3,}", 0, 0, HS_MODE_STREAM);
2377     ASSERT_NE(nullptr, db);
2378 
2379     hs_stream_t *stream;
2380     hs_error_t err = hs_open_stream(db, 0, &stream);
2381     ASSERT_EQ(HS_SUCCESS, err);
2382 
2383     char buf[100];
2384     size_t used = 0;
2385     err = hs_compress_stream(stream, buf, 1, &used);
2386     ASSERT_EQ(HS_INSUFFICIENT_SPACE, err);
2387     ASSERT_LT(0, used);
2388 
2389     err = hs_close_stream(stream, nullptr, nullptr, nullptr);
2390     ASSERT_EQ(HS_SUCCESS, err);
2391 
2392     err = hs_free_database(db);
2393     ASSERT_EQ(HS_SUCCESS, err);
2394 }
2395 
TEST(HyperscanArgChecks,ExpandNoDb)2396 TEST(HyperscanArgChecks, ExpandNoDb) {
2397     hs_database_t *db = buildDB("(foo.*bar){3,}", 0, 0, HS_MODE_STREAM);
2398     ASSERT_NE(nullptr, db);
2399 
2400     hs_stream_t *stream1;
2401     hs_error_t err = hs_open_stream(db, 0, &stream1);
2402     ASSERT_EQ(HS_SUCCESS, err);
2403 
2404     char buf[2000];
2405     size_t used = 0;
2406     err = hs_compress_stream(stream1, buf, sizeof(buf), &used);
2407     ASSERT_EQ(HS_SUCCESS, err);
2408 
2409     hs_stream_t *stream2;
2410     err = hs_expand_stream(nullptr, &stream2, buf, used);
2411     ASSERT_EQ(HS_INVALID, err);
2412 
2413     err = hs_close_stream(stream1, nullptr, nullptr, nullptr);
2414     ASSERT_EQ(HS_SUCCESS, err);
2415 
2416     err = hs_free_database(db);
2417     ASSERT_EQ(HS_SUCCESS, err);
2418 }
2419 
TEST(HyperscanArgChecks,ExpandNoTo)2420 TEST(HyperscanArgChecks, ExpandNoTo) {
2421     hs_database_t *db = buildDB("(foo.*bar){3,}", 0, 0, HS_MODE_STREAM);
2422     ASSERT_NE(nullptr, db);
2423 
2424     hs_stream_t *stream1;
2425     hs_error_t err = hs_open_stream(db, 0, &stream1);
2426     ASSERT_EQ(HS_SUCCESS, err);
2427 
2428     char buf[2000];
2429     size_t used = 0;
2430     err = hs_compress_stream(stream1, buf, sizeof(buf), &used);
2431     ASSERT_EQ(HS_SUCCESS, err);
2432 
2433     hs_stream_t *stream2;
2434     err = hs_expand_stream(db, nullptr, buf, used);
2435     ASSERT_EQ(HS_INVALID, err);
2436 
2437     err = hs_close_stream(stream1, nullptr, nullptr, nullptr);
2438     ASSERT_EQ(HS_SUCCESS, err);
2439 
2440     err = hs_free_database(db);
2441     ASSERT_EQ(HS_SUCCESS, err);
2442 }
2443 
TEST(HyperscanArgChecks,ExpandNoBuf)2444 TEST(HyperscanArgChecks, ExpandNoBuf) {
2445     hs_database_t *db = buildDB("(foo.*bar){3,}", 0, 0, HS_MODE_STREAM);
2446     ASSERT_NE(nullptr, db);
2447 
2448     hs_stream_t *stream1;
2449     hs_error_t err = hs_open_stream(db, 0, &stream1);
2450     ASSERT_EQ(HS_SUCCESS, err);
2451 
2452     char buf[2000];
2453     size_t used = 0;
2454     err = hs_compress_stream(stream1, buf, sizeof(buf), &used);
2455     ASSERT_EQ(HS_SUCCESS, err);
2456 
2457     hs_stream_t *stream2;
2458     err = hs_expand_stream(db, &stream2, nullptr, used);
2459     ASSERT_EQ(HS_INVALID, err);
2460 
2461     err = hs_close_stream(stream1, nullptr, nullptr, nullptr);
2462     ASSERT_EQ(HS_SUCCESS, err);
2463 
2464     err = hs_free_database(db);
2465     ASSERT_EQ(HS_SUCCESS, err);
2466 }
2467 
TEST(HyperscanArgChecks,ExpandSmallBuf)2468 TEST(HyperscanArgChecks, ExpandSmallBuf) {
2469     hs_database_t *db = buildDB("(foo.*bar){3,}", 0, 0, HS_MODE_STREAM);
2470     ASSERT_NE(nullptr, db);
2471 
2472     hs_stream_t *stream1;
2473     hs_error_t err = hs_open_stream(db, 0, &stream1);
2474     ASSERT_EQ(HS_SUCCESS, err);
2475 
2476     char buf[2000];
2477     size_t used = 0;
2478     err = hs_compress_stream(stream1, buf, sizeof(buf), &used);
2479     ASSERT_EQ(HS_SUCCESS, err);
2480 
2481     hs_stream_t *stream2;
2482     err = hs_expand_stream(db, &stream2, buf, used / 2);
2483     ASSERT_EQ(HS_INVALID, err);
2484 
2485     err = hs_close_stream(stream1, nullptr, nullptr, nullptr);
2486     ASSERT_EQ(HS_SUCCESS, err);
2487 
2488     err = hs_free_database(db);
2489     ASSERT_EQ(HS_SUCCESS, err);
2490 }
2491 
TEST(HyperscanArgChecks,ResetAndExpandNoStream)2492 TEST(HyperscanArgChecks, ResetAndExpandNoStream) {
2493     hs_database_t *db = buildDB("(foo.*bar){3,}", 0, 0, HS_MODE_STREAM);
2494     ASSERT_NE(nullptr, db);
2495 
2496     hs_stream_t *stream1;
2497     hs_error_t err = hs_open_stream(db, 0, &stream1);
2498     ASSERT_EQ(HS_SUCCESS, err);
2499 
2500     char buf[2000];
2501     size_t used = 0;
2502     err = hs_compress_stream(stream1, buf, sizeof(buf), &used);
2503     ASSERT_EQ(HS_SUCCESS, err);
2504 
2505     err = hs_reset_and_expand_stream(nullptr, buf, used, nullptr, nullptr,
2506                                      nullptr);
2507     ASSERT_EQ(HS_INVALID, err);
2508 
2509     err = hs_close_stream(stream1, nullptr, nullptr, nullptr);
2510     ASSERT_EQ(HS_SUCCESS, err);
2511 
2512     err = hs_free_database(db);
2513     ASSERT_EQ(HS_SUCCESS, err);
2514 }
2515 
TEST(HyperscanArgChecks,ResetAndExpandNoBuf)2516 TEST(HyperscanArgChecks, ResetAndExpandNoBuf) {
2517     hs_database_t *db = buildDB("(foo.*bar){3,}", 0, 0, HS_MODE_STREAM);
2518     ASSERT_NE(nullptr, db);
2519 
2520     hs_stream_t *stream1;
2521     hs_error_t err = hs_open_stream(db, 0, &stream1);
2522     ASSERT_EQ(HS_SUCCESS, err);
2523 
2524     char buf[2000];
2525     size_t used = 0;
2526     err = hs_compress_stream(stream1, buf, sizeof(buf), &used);
2527     ASSERT_EQ(HS_SUCCESS, err);
2528 
2529     hs_stream_t *stream2;
2530     err = hs_open_stream(db, 0, &stream2);
2531     ASSERT_EQ(HS_SUCCESS, err);
2532 
2533     err = hs_reset_and_expand_stream(stream2, nullptr, used, nullptr, nullptr,
2534                                      nullptr);
2535     ASSERT_EQ(HS_INVALID, err);
2536 
2537     err = hs_close_stream(stream1, nullptr, nullptr, nullptr);
2538     ASSERT_EQ(HS_SUCCESS, err);
2539 
2540     err = hs_close_stream(stream2, nullptr, nullptr, nullptr);
2541     ASSERT_EQ(HS_SUCCESS, err);
2542 
2543     err = hs_free_database(db);
2544     ASSERT_EQ(HS_SUCCESS, err);
2545 }
2546 
2547 
TEST(HyperscanArgChecks,ResetAndExpandSmallBuf)2548 TEST(HyperscanArgChecks, ResetAndExpandSmallBuf) {
2549     hs_database_t *db = buildDB("(foo.*bar){3,}", 0, 0, HS_MODE_STREAM);
2550     ASSERT_NE(nullptr, db);
2551 
2552     hs_stream_t *stream1;
2553     hs_error_t err = hs_open_stream(db, 0, &stream1);
2554     ASSERT_EQ(HS_SUCCESS, err);
2555 
2556     char buf[2000];
2557     size_t used = 0;
2558     err = hs_compress_stream(stream1, buf, sizeof(buf), &used);
2559     ASSERT_EQ(HS_SUCCESS, err);
2560 
2561     hs_stream_t *stream2;
2562     err = hs_open_stream(db, 0, &stream2);
2563     ASSERT_EQ(HS_SUCCESS, err);
2564 
2565     err = hs_reset_and_expand_stream(stream2, buf, used / 2, nullptr, nullptr,
2566                                      nullptr);
2567     ASSERT_EQ(HS_INVALID, err);
2568 
2569     err = hs_close_stream(stream1, nullptr, nullptr, nullptr);
2570     ASSERT_EQ(HS_SUCCESS, err);
2571 
2572     err = hs_close_stream(stream2, nullptr, nullptr, nullptr);
2573     ASSERT_EQ(HS_SUCCESS, err);
2574 
2575     err = hs_free_database(db);
2576     ASSERT_EQ(HS_SUCCESS, err);
2577 }
2578 
TEST(HyperscanArgChecks,ResetAndExpandNoScratch)2579 TEST(HyperscanArgChecks, ResetAndExpandNoScratch) {
2580     hs_database_t *db = buildDB("(foo.*bar){3,}", 0, 0, HS_MODE_STREAM);
2581     ASSERT_NE(nullptr, db);
2582 
2583     hs_stream_t *stream1;
2584     hs_error_t err = hs_open_stream(db, 0, &stream1);
2585     ASSERT_EQ(HS_SUCCESS, err);
2586 
2587     char buf[2000];
2588     size_t used = 0;
2589     err = hs_compress_stream(stream1, buf, sizeof(buf), &used);
2590     ASSERT_EQ(HS_SUCCESS, err);
2591 
2592     hs_stream_t *stream2;
2593     err = hs_open_stream(db, 0, &stream2);
2594     ASSERT_EQ(HS_SUCCESS, err);
2595 
2596     int temp;
2597 
2598     err = hs_reset_and_expand_stream(stream2, buf, used, nullptr, singleHandler,
2599                                      &temp);
2600     ASSERT_EQ(HS_INVALID, err);
2601 
2602     err = hs_close_stream(stream1, nullptr, nullptr, nullptr);
2603     ASSERT_EQ(HS_SUCCESS, err);
2604 
2605     err = hs_close_stream(stream2, nullptr, nullptr, nullptr);
2606     ASSERT_EQ(HS_SUCCESS, err);
2607 
2608     err = hs_free_database(db);
2609     ASSERT_EQ(HS_SUCCESS, err);
2610 }
2611 
2612 class BadModeTest : public testing::TestWithParam<unsigned> {};
2613 
2614 // hs_compile: Compile a pattern with bogus mode flags set.
TEST_P(BadModeTest,FailCompile)2615 TEST_P(BadModeTest, FailCompile) {
2616     hs_database_t *db = nullptr;
2617     hs_compile_error_t *compile_err = nullptr;
2618 
2619     unsigned mode = GetParam();
2620     SCOPED_TRACE(mode);
2621 
2622     hs_error_t err = hs_compile("foo", 0, mode, nullptr, &db, &compile_err);
2623     ASSERT_EQ(HS_COMPILER_ERROR, err);
2624     ASSERT_TRUE(compile_err != nullptr);
2625     ASSERT_TRUE(compile_err->message != nullptr);
2626     hs_free_compile_error(compile_err);
2627 }
2628 
2629 static const unsigned badModeValues[] = {
2630     // Multiple modes at once.
2631     HS_MODE_BLOCK | HS_MODE_STREAM | HS_MODE_VECTORED,
2632     HS_MODE_BLOCK | HS_MODE_STREAM,
2633     HS_MODE_BLOCK | HS_MODE_VECTORED,
2634     HS_MODE_STREAM | HS_MODE_VECTORED,
2635     // SOM horizon modes are only accepted in streaming mode.
2636     HS_MODE_BLOCK | HS_MODE_SOM_HORIZON_LARGE,
2637     HS_MODE_BLOCK | HS_MODE_SOM_HORIZON_MEDIUM,
2638     HS_MODE_BLOCK | HS_MODE_SOM_HORIZON_SMALL,
2639     HS_MODE_VECTORED | HS_MODE_SOM_HORIZON_LARGE,
2640     HS_MODE_VECTORED | HS_MODE_SOM_HORIZON_MEDIUM,
2641     HS_MODE_VECTORED | HS_MODE_SOM_HORIZON_SMALL,
2642     // Can't specify more than one SOM horizon.
2643     HS_MODE_STREAM | HS_MODE_SOM_HORIZON_LARGE | HS_MODE_SOM_HORIZON_MEDIUM | HS_MODE_SOM_HORIZON_SMALL,
2644     HS_MODE_STREAM | HS_MODE_SOM_HORIZON_LARGE | HS_MODE_SOM_HORIZON_SMALL,
2645     HS_MODE_STREAM | HS_MODE_SOM_HORIZON_LARGE | HS_MODE_SOM_HORIZON_MEDIUM,
2646     HS_MODE_STREAM | HS_MODE_SOM_HORIZON_MEDIUM | HS_MODE_SOM_HORIZON_SMALL,
2647 };
2648 
2649 INSTANTIATE_TEST_CASE_P(HyperscanArgChecks, BadModeTest,
2650                         testing::ValuesIn(badModeValues));
2651 
2652 } // namespace
2653 
2654