/src/suricata7/src/util-spm-bs2bm.c
Line | Count | Source |
1 | | /* Copyright (C) 2007-2010 Open Information Security Foundation |
2 | | * |
3 | | * You can copy, redistribute or modify this Program under the terms of |
4 | | * the GNU General Public License version 2 as published by the Free |
5 | | * Software Foundation. |
6 | | * |
7 | | * This program is distributed in the hope that it will be useful, |
8 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | | * GNU General Public License for more details. |
11 | | * |
12 | | * You should have received a copy of the GNU General Public License |
13 | | * version 2 along with this program; if not, write to the Free Software |
14 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
15 | | * 02110-1301, USA. |
16 | | */ |
17 | | |
18 | | /** |
19 | | * \file |
20 | | * |
21 | | * \author Pablo Rincon Crespo <pablo.rincon.crespo@gmail.com> |
22 | | * |
23 | | * Bs2Bm use a simple context array to determine the characters |
24 | | * that are not present on the pattern. This way on partial matches |
25 | | * broken by a char not present, we can skip to the next character |
26 | | * making less checks |
27 | | */ |
28 | | |
29 | | #include "suricata-common.h" |
30 | | #include "suricata.h" |
31 | | |
32 | | #include "util-spm-bs2bm.h" |
33 | | |
34 | | /** |
35 | | * \brief Array setup function for Bs2Bm of bad characters index (not found at the needle) |
36 | | * |
37 | | * \param needle pointer to the pattern we ar searching for |
38 | | * \param needle_len length limit of the needle |
39 | | * \param badchars pointer to an empty array of bachars. The array prepared contains |
40 | | * characters that can't be inside the needle_len. So the skips can be |
41 | | * faster |
42 | | */ |
43 | | void Bs2BmBadchars(const uint8_t *needle, uint16_t needle_len, uint8_t *badchars) |
44 | 104k | { |
45 | 104k | uint32_t i; |
46 | 26.7M | for (i = 0; i < ALPHABET_SIZE; i++) |
47 | 26.6M | badchars[i] = 1; |
48 | | |
49 | | /* set to 0 the values where index as ascii is present |
50 | | * because they are not badchars |
51 | | */ |
52 | 968k | for (i = 0; i < needle_len; i++) |
53 | 864k | badchars[needle[i]] = 0; |
54 | 104k | } |
55 | | |
56 | | /** |
57 | | * \brief Array setup function for Bs2BmNocase of bad characters index (not found at the needle) |
58 | | * |
59 | | * \param needle pointer to the pattern we ar searching for |
60 | | * \param needle_len length limit of the needle |
61 | | * \param badchars pointer to an empty array of bachars. The array prepared contains |
62 | | * characters that can't be inside the needle_len. So the skips can be |
63 | | * faster |
64 | | */ |
65 | | void Bs2BmBadcharsNocase(const uint8_t *needle, uint16_t needle_len, uint8_t *badchars) |
66 | 0 | { |
67 | 0 | uint32_t i; |
68 | 0 | for (i = 0; i < ALPHABET_SIZE; i++) |
69 | 0 | badchars[i] = 1; |
70 | | |
71 | | /* set to 0 the values where index as ascii is present |
72 | | * because they are not badchars |
73 | | */ |
74 | 0 | for (i = 0; i < needle_len; i++) { |
75 | 0 | badchars[u8_tolower(needle[i])] = 0; |
76 | 0 | } |
77 | 0 | } |
78 | | |
79 | | /** |
80 | | * \brief Basic search with a bad characters array. The array badchars contains |
81 | | * flags at character's ascii index that can't be inside the needle. So the skips can be |
82 | | * faster |
83 | | * |
84 | | * \param haystack pointer to the buffer to search in |
85 | | * \param haystack_len length limit of the buffer |
86 | | * \param needle pointer to the pattern we ar searching for |
87 | | * \param needle_len length limit of the needle |
88 | | * \param badchars pointer to an array of bachars prepared by Bs2BmBadchars() |
89 | | * |
90 | | * \retval ptr to start of the match; NULL if no match |
91 | | */ |
92 | | uint8_t *Bs2Bm(const uint8_t *haystack, uint32_t haystack_len, const uint8_t *needle, |
93 | | uint16_t needle_len, const uint8_t badchars[]) |
94 | 104k | { |
95 | 104k | const uint8_t *h, *n; |
96 | 104k | const uint8_t *hmax = haystack + haystack_len; |
97 | 104k | const uint8_t *nmax = needle + needle_len; |
98 | | |
99 | 104k | if (needle_len == 0 || needle_len > haystack_len) |
100 | 3.29k | return NULL; |
101 | | |
102 | 8.85M | for (n = needle; nmax - n <= hmax - haystack; haystack++) { |
103 | 8.82M | if (*haystack != *n) { |
104 | 8.52M | continue; |
105 | 8.52M | } |
106 | | /* one byte needles */ |
107 | 302k | if (needle_len == 1) |
108 | 0 | return (uint8_t *)haystack; |
109 | | |
110 | 1.39M | for (h = haystack+1, n++; nmax - n <= hmax - haystack; h++, n++) { |
111 | 1.39M | if (*h != *n) { |
112 | 235k | if (badchars[*h] == 1) { |
113 | | /* skip it! */ |
114 | 168k | haystack = h; |
115 | 168k | } |
116 | 235k | break; |
117 | 235k | } |
118 | | /* if we run out of needle we fully matched */ |
119 | 1.15M | if (n == nmax - 1 ) { |
120 | 67.4k | return (uint8_t *)haystack; |
121 | 67.4k | } |
122 | 1.15M | } |
123 | 235k | n = needle; |
124 | 235k | } |
125 | | |
126 | 33.4k | return NULL; |
127 | 100k | } |
128 | | |
129 | | /** |
130 | | * \brief Basic search case less with a bad characters array. The array badchars contains |
131 | | * flags at character's ascii index that can't be inside the needle. So the skips can be |
132 | | * faster |
133 | | * |
134 | | * \param haystack pointer to the buffer to search in |
135 | | * \param haystack_len length limit of the buffer |
136 | | * \param needle pointer to the pattern we ar searching for |
137 | | * \param needle_len length limit of the needle |
138 | | * \param badchars pointer to an array of bachars prepared by Bs2BmBadchars() |
139 | | * |
140 | | * \retval ptr to start of the match; NULL if no match |
141 | | */ |
142 | | uint8_t *Bs2BmNocase(const uint8_t *haystack, uint32_t haystack_len, const uint8_t *needle, |
143 | | uint16_t needle_len, const uint8_t badchars[]) |
144 | 0 | { |
145 | 0 | const uint8_t *h, *n; |
146 | 0 | const uint8_t *hmax = haystack + haystack_len; |
147 | 0 | const uint8_t *nmax = needle + needle_len; |
148 | |
|
149 | 0 | if (needle_len == 0 || needle_len > haystack_len) |
150 | 0 | return NULL; |
151 | | |
152 | 0 | for (n = needle; nmax - n <= hmax - haystack; haystack++) { |
153 | 0 | if (u8_tolower(*haystack) != u8_tolower(*n)) { |
154 | 0 | continue; |
155 | 0 | } |
156 | | /* one byte needles */ |
157 | 0 | if (needle_len == 1) |
158 | 0 | return (uint8_t *)haystack; |
159 | | |
160 | 0 | for (h = haystack+1, n++; nmax - n <= hmax - haystack; h++, n++) { |
161 | 0 | if (u8_tolower(*h) != u8_tolower(*n)) { |
162 | 0 | if (badchars[u8_tolower(*h)] == 1) { |
163 | | /* skip it! */ |
164 | 0 | haystack = h; |
165 | 0 | } |
166 | 0 | break; |
167 | 0 | } |
168 | | /* if we run out of needle we fully matched */ |
169 | 0 | if (n == nmax - 1) { |
170 | 0 | return (uint8_t *)haystack; |
171 | 0 | } |
172 | 0 | } |
173 | 0 | n = needle; |
174 | 0 | } |
175 | | |
176 | 0 | return NULL; |
177 | 0 | } |