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 "ue2common.h"
32 #include "hwlm/noodle_build.h"
33 #include "hwlm/noodle_engine.h"
34 #include "hwlm/hwlm.h"
35 #include "hwlm/hwlm_literal.h"
36 #include "scratch.h"
37 #include "util/alloc.h"
38 #include "util/ue2string.h"
39
40 #include <cstring>
41 #include <vector>
42 #include "gtest/gtest.h"
43
44 using std::unique_ptr;
45 using std::vector;
46 using namespace ue2;
47
48 struct hlmMatchEntry {
49 size_t to;
50 u32 id;
hlmMatchEntryhlmMatchEntry51 hlmMatchEntry(size_t end, u32 identifier) :
52 to(end), id(identifier) {}
53 };
54
55 vector<hlmMatchEntry> ctxt;
56
57 static
hlmSimpleCallback(size_t to,u32 id,UNUSED struct hs_scratch * scratch)58 hwlmcb_rv_t hlmSimpleCallback(size_t to, u32 id,
59 UNUSED struct hs_scratch *scratch) {
60 DEBUG_PRINTF("match @%zu = %u\n", to, id);
61
62 ctxt.push_back(hlmMatchEntry(to, id));
63
64 return HWLM_CONTINUE_MATCHING;
65 }
66
67 static
noodleMatch(const u8 * data,size_t data_len,const char * lit_str,size_t lit_len,char nocase,HWLMCallback cb)68 void noodleMatch(const u8 *data, size_t data_len, const char *lit_str,
69 size_t lit_len, char nocase, HWLMCallback cb) {
70 u32 id = 1000;
71 hwlmLiteral lit(std::string(lit_str, lit_len), nocase, id);
72 auto n = noodBuildTable(lit);
73 ASSERT_TRUE(n != nullptr);
74
75 hwlm_error_t rv;
76 struct hs_scratch scratch;
77 rv = noodExec(n.get(), data, data_len, 0, cb, &scratch);
78 ASSERT_EQ(HWLM_SUCCESS, rv);
79 }
80
TEST(Noodle,nood1)81 TEST(Noodle, nood1) {
82 const size_t data_len = 1024;
83 unsigned int i, j;
84 u8 data[data_len];
85
86 memset(data, 'a', data_len);
87
88 noodleMatch(data, data_len, "a", 1, 0, hlmSimpleCallback);
89 ASSERT_EQ(1024U, ctxt.size());
90 for (i = 0; i < 1024; i++) {
91 ASSERT_EQ(i, ctxt[i].to);
92 }
93
94 ctxt.clear();
95 noodleMatch(data, data_len, "A", 1, 0, hlmSimpleCallback);
96 ASSERT_EQ(0U, ctxt.size());
97
98 ctxt.clear();
99 noodleMatch(data, data_len, "A", 1, 1, hlmSimpleCallback);
100 ASSERT_EQ(1024U, ctxt.size());
101 for (i = 0; i < 1024; i++) {
102 ASSERT_EQ(i, ctxt[i].to);
103 }
104
105 for (j = 0; j < 16; j++) {
106 ctxt.clear();
107 noodleMatch(data + j, data_len - j, "A", 1, 1, hlmSimpleCallback);
108 ASSERT_EQ(1024 - j, ctxt.size());
109 for (i = 0; i < 1024 - j; i++) {
110 ASSERT_EQ(i, ctxt[i].to);
111 }
112
113 ctxt.clear();
114 noodleMatch(data, data_len - j, "A", 1, 1, hlmSimpleCallback);
115 ASSERT_EQ(1024 - j, ctxt.size());
116 for (i = 0; i < 1024 - j; i++) {
117 ASSERT_EQ(i, ctxt[i].to);
118 }
119 }
120 ctxt.clear();
121 }
122
TEST(Noodle,nood2)123 TEST(Noodle, nood2) {
124 const size_t data_len = 1024;
125 unsigned int i, j;
126 u8 data[data_len];
127
128 memset(data, 'a', data_len);
129
130 noodleMatch(data, data_len, "aa", 2, 0, hlmSimpleCallback);
131 ASSERT_EQ(1023U, ctxt.size());
132 for (i = 0; i < 1023; i++) {
133 ASSERT_EQ(i + 1, ctxt[i].to);
134 }
135
136 ctxt.clear();
137 noodleMatch(data, data_len, "aA", 2, 0, hlmSimpleCallback);
138 ASSERT_EQ(0U, ctxt.size());
139
140 ctxt.clear();
141 noodleMatch(data, data_len, "AA", 2, 0, hlmSimpleCallback);
142 ASSERT_EQ(0U, ctxt.size());
143
144 ctxt.clear();
145 noodleMatch(data, data_len, "aa", 2, 1, hlmSimpleCallback);
146 ASSERT_EQ(1023U, ctxt.size());
147 for (i = 0; i < 1023; i++) {
148 ASSERT_EQ(i + 1, ctxt[i].to);
149 }
150
151 ctxt.clear();
152 noodleMatch(data, data_len, "Aa", 2, 1, hlmSimpleCallback);
153 ASSERT_EQ(1023U, ctxt.size());
154 for (i = 0; i < 1023; i++) {
155 ASSERT_EQ(i + 1, ctxt[i].to);
156 }
157
158 ctxt.clear();
159 noodleMatch(data, data_len, "AA", 2, 1, hlmSimpleCallback);
160 ASSERT_EQ(1023U, ctxt.size());
161 for (i = 0; i < 1023; i++) {
162 ASSERT_EQ(i + 1, ctxt[i].to);
163 }
164
165 for (j = 0; j < 16; j++) {
166 ctxt.clear();
167 noodleMatch(data + j, data_len - j, "Aa", 2, 1, hlmSimpleCallback);
168 ASSERT_EQ(1023 - j, ctxt.size());
169 for (i = 0; i < 1023 - j; i++) {
170 ASSERT_EQ(i + 1, ctxt[i].to);
171 }
172
173 ctxt.clear();
174 noodleMatch(data, data_len - j, "aA", 2, 1, hlmSimpleCallback);
175 ASSERT_EQ(1023 - j, ctxt.size());
176 for (i = 0; i < 1023 - j; i++) {
177 ASSERT_EQ(i + 1, ctxt[i].to);
178 }
179 }
180 ctxt.clear();
181 }
182
TEST(Noodle,noodLong)183 TEST(Noodle, noodLong) {
184 const size_t data_len = 1024;
185 unsigned int i, j;
186 u8 data[data_len];
187
188 memset(data, 'a', data_len);
189
190 noodleMatch(data, data_len, "aaaa", 4, 0, hlmSimpleCallback);
191 ASSERT_EQ(1021U, ctxt.size());
192 for (i = 0; i < 1021; i++) {
193 ASSERT_EQ(i + 3, ctxt[i].to);
194 }
195
196 ctxt.clear();
197 noodleMatch(data, data_len, "aaAA", 4, 0, hlmSimpleCallback);
198 ASSERT_EQ(0U, ctxt.size());
199
200 ctxt.clear();
201 noodleMatch(data, data_len, "aaAA", 4, 1, hlmSimpleCallback);
202 ASSERT_EQ(1021U, ctxt.size());
203 for (i = 0; i < 1021; i++) {
204 ASSERT_EQ(i + 3, ctxt[i].to);
205 }
206
207 for (j = 0; j < 16; j++) {
208 ctxt.clear();
209 noodleMatch(data + j, data_len - j, "AAaa", 4, 1, hlmSimpleCallback);
210 ASSERT_EQ(1021 - j, ctxt.size());
211 for (i = 0; i < 1021 - j; i++) {
212 ASSERT_EQ(i + 3, ctxt[i].to);
213 }
214
215 ctxt.clear();
216 noodleMatch(data + j, data_len - j, "aaaA", 4, 1, hlmSimpleCallback);
217 ASSERT_EQ(1021 - j, ctxt.size());
218 for (i = 0; i < 1021 - j; i++) {
219 ASSERT_EQ(i + 3, ctxt[i].to);
220 }
221 }
222 ctxt.clear();
223 }
224
TEST(Noodle,noodCutoverSingle)225 TEST(Noodle, noodCutoverSingle) {
226 const size_t max_data_len = 128;
227 u8 data[max_data_len + 15];
228
229 memset(data, 'a', max_data_len + 15);
230
231 for (u32 align = 0; align < 16; align++) {
232 for (u32 len = 0; len < max_data_len; len++) {
233 ctxt.clear();
234 noodleMatch(data + align, len, "a", 1, 0, hlmSimpleCallback);
235 EXPECT_EQ(len, ctxt.size());
236 for (u32 i = 0; i < ctxt.size(); i++) {
237 ASSERT_EQ(i, ctxt[i].to);
238 }
239 }
240 }
241 ctxt.clear();
242 }
243
TEST(Noodle,noodCutoverDouble)244 TEST(Noodle, noodCutoverDouble) {
245 const size_t max_data_len = 128;
246 u8 data[max_data_len + 15];
247
248 memset(data, 'a', max_data_len + 15);
249
250 for (u32 align = 0; align < 16; align++) {
251 for (u32 len = 0; len < max_data_len; len++) {
252 ctxt.clear();
253 noodleMatch(data + align, len, "aa", 2, 0, hlmSimpleCallback);
254 EXPECT_EQ(len ? len - 1 : 0U, ctxt.size());
255 for (u32 i = 0; i < ctxt.size(); i++) {
256 ASSERT_EQ(i + 1, ctxt[i].to);
257 }
258 }
259 }
260 ctxt.clear();
261 }
262
263