/src/yara/libyara/sizedstr.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | Copyright (c) 2014. The YARA Authors. All Rights Reserved. |
3 | | |
4 | | Redistribution and use in source and binary forms, with or without modification, |
5 | | are permitted provided that the following conditions are met: |
6 | | |
7 | | 1. Redistributions of source code must retain the above copyright notice, this |
8 | | list of conditions and the following disclaimer. |
9 | | |
10 | | 2. Redistributions in binary form must reproduce the above copyright notice, |
11 | | this list of conditions and the following disclaimer in the documentation and/or |
12 | | other materials provided with the distribution. |
13 | | |
14 | | 3. Neither the name of the copyright holder nor the names of its contributors |
15 | | may be used to endorse or promote products derived from this software without |
16 | | specific prior written permission. |
17 | | |
18 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
19 | | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
20 | | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
21 | | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR |
22 | | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
23 | | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
24 | | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
25 | | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
26 | | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
27 | | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | | */ |
29 | | |
30 | | #include <ctype.h> |
31 | | #include <string.h> |
32 | | #include <yara/globals.h> |
33 | | #include <yara/mem.h> |
34 | | #include <yara/sizedstr.h> |
35 | | #include <yara/strutils.h> |
36 | | #include <yara/types.h> |
37 | | |
38 | | //////////////////////////////////////////////////////////////////////////////// |
39 | | // ss_compare returns: |
40 | | // 0 if s1 == s2 |
41 | | // -1 if s1 < s2 |
42 | | // 1 if s1 > s2 |
43 | | // |
44 | | int ss_compare(SIZED_STRING* s1, SIZED_STRING* s2) |
45 | 0 | { |
46 | 0 | size_t i = 0; |
47 | |
|
48 | 0 | while (s1->length > i && s2->length > i && s1->c_string[i] == s2->c_string[i]) |
49 | 0 | { |
50 | 0 | i++; |
51 | 0 | } |
52 | |
|
53 | 0 | if (i == s1->length && i == s2->length) |
54 | 0 | return 0; |
55 | 0 | else if (i == s1->length) |
56 | 0 | return -1; |
57 | 0 | else if (i == s2->length) |
58 | 0 | return 1; |
59 | 0 | else if (s1->c_string[i] < s2->c_string[i]) |
60 | 0 | return -1; |
61 | 0 | else |
62 | 0 | return 1; |
63 | 0 | } |
64 | | |
65 | | //////////////////////////////////////////////////////////////////////////////// |
66 | | // ss_icompare is the case-insensitive version of ss_compare. |
67 | | // |
68 | | int ss_icompare(SIZED_STRING* s1, SIZED_STRING* s2) |
69 | 0 | { |
70 | 0 | size_t i = 0; |
71 | |
|
72 | 0 | while (s1->length > i && s2->length > i && |
73 | 0 | yr_lowercase[(uint8_t) s1->c_string[i]] == |
74 | 0 | yr_lowercase[(uint8_t) s2->c_string[i]]) |
75 | 0 | { |
76 | 0 | i++; |
77 | 0 | } |
78 | |
|
79 | 0 | if (i == s1->length && i == s2->length) |
80 | 0 | return 0; |
81 | 0 | else if (i == s1->length) |
82 | 0 | return -1; |
83 | 0 | else if (i == s2->length) |
84 | 0 | return 1; |
85 | 0 | else if (s1->c_string[i] < s2->c_string[i]) |
86 | 0 | return -1; |
87 | 0 | else |
88 | 0 | return 1; |
89 | 0 | } |
90 | | |
91 | | //////////////////////////////////////////////////////////////////////////////// |
92 | | // ss_contains returns true if the sized string s1 contains s2. |
93 | | // |
94 | | bool ss_contains(SIZED_STRING* s1, SIZED_STRING* s2) |
95 | 0 | { |
96 | 0 | return memmem(s1->c_string, s1->length, s2->c_string, s2->length) != NULL; |
97 | 0 | } |
98 | | |
99 | | //////////////////////////////////////////////////////////////////////////////// |
100 | | // ss_icontains is the case-insensitive version of ss_contains. |
101 | | // |
102 | | bool ss_icontains(SIZED_STRING* s1, SIZED_STRING* s2) |
103 | 0 | { |
104 | 0 | if (s1->length < s2->length) |
105 | 0 | return false; |
106 | | |
107 | 0 | for (uint32_t i = 0; i < s1->length - s2->length + 1; i++) |
108 | 0 | { |
109 | 0 | uint32_t j = 0; |
110 | |
|
111 | 0 | for (j = 0; j < s2->length; j++) |
112 | 0 | if (yr_lowercase[(uint8_t) s1->c_string[i + j]] != |
113 | 0 | yr_lowercase[(uint8_t) s2->c_string[j]]) |
114 | 0 | break; |
115 | |
|
116 | 0 | if (j == s2->length) |
117 | 0 | return true; |
118 | 0 | } |
119 | | |
120 | 0 | return false; |
121 | 0 | } |
122 | | |
123 | | //////////////////////////////////////////////////////////////////////////////// |
124 | | // ss_startswith returns true if the sized string s1 starts with s2. |
125 | | // |
126 | | bool ss_startswith(SIZED_STRING* s1, SIZED_STRING* s2) |
127 | 0 | { |
128 | 0 | if (s1->length < s2->length) |
129 | 0 | return false; |
130 | | |
131 | 0 | for (uint32_t i = 0; i < s2->length; i++) |
132 | 0 | { |
133 | 0 | if (s1->c_string[i] != s2->c_string[i]) |
134 | 0 | return false; |
135 | 0 | } |
136 | | |
137 | 0 | return true; |
138 | 0 | } |
139 | | |
140 | | //////////////////////////////////////////////////////////////////////////////// |
141 | | // ss_istartswith is the case-insensitive version of ss_startswith. |
142 | | // |
143 | | bool ss_istartswith(SIZED_STRING* s1, SIZED_STRING* s2) |
144 | 0 | { |
145 | 0 | if (s1->length < s2->length) |
146 | 0 | return false; |
147 | | |
148 | 0 | for (uint32_t i = 0; i < s2->length; i++) |
149 | 0 | { |
150 | 0 | if (yr_lowercase[(uint8_t) s1->c_string[i]] != |
151 | 0 | yr_lowercase[(uint8_t) s2->c_string[i]]) |
152 | 0 | return false; |
153 | 0 | } |
154 | | |
155 | 0 | return true; |
156 | 0 | } |
157 | | |
158 | | //////////////////////////////////////////////////////////////////////////////// |
159 | | // ss_endswith returns true if the sized string s1 ends with s2. |
160 | | // |
161 | | bool ss_endswith(SIZED_STRING* s1, SIZED_STRING* s2) |
162 | 0 | { |
163 | 0 | if (s1->length < s2->length) |
164 | 0 | return false; |
165 | | |
166 | 0 | for (uint32_t i = 0; i < s2->length; i++) |
167 | 0 | { |
168 | 0 | if (s1->c_string[s1->length - s2->length + i] != s2->c_string[i]) |
169 | 0 | return false; |
170 | 0 | } |
171 | | |
172 | 0 | return true; |
173 | 0 | } |
174 | | |
175 | | //////////////////////////////////////////////////////////////////////////////// |
176 | | // ss_iendswith is the case-insensitive version of ss_endswith. |
177 | | // |
178 | | bool ss_iendswith(SIZED_STRING* s1, SIZED_STRING* s2) |
179 | 0 | { |
180 | 0 | if (s1->length < s2->length) |
181 | 0 | return false; |
182 | | |
183 | 0 | for (uint32_t i = 0; i < s2->length; i++) |
184 | 0 | { |
185 | 0 | if (yr_lowercase[(uint8_t) s1->c_string[s1->length - s2->length + i]] != |
186 | 0 | yr_lowercase[(uint8_t) s2->c_string[i]]) |
187 | 0 | return false; |
188 | 0 | } |
189 | | |
190 | 0 | return true; |
191 | 0 | } |
192 | | |
193 | | //////////////////////////////////////////////////////////////////////////////// |
194 | | // ss_dup creates a new copy of a given SIZED_STRING. |
195 | | // |
196 | | SIZED_STRING* ss_dup(SIZED_STRING* s) |
197 | 0 | { |
198 | 0 | SIZED_STRING* result = (SIZED_STRING*) yr_malloc( |
199 | 0 | sizeof(SIZED_STRING) + s->length); |
200 | |
|
201 | 0 | if (result == NULL) |
202 | 0 | return NULL; |
203 | | |
204 | 0 | result->length = s->length; |
205 | 0 | result->flags = s->flags; |
206 | |
|
207 | 0 | memcpy(result->c_string, s->c_string, s->length + 1); |
208 | |
|
209 | 0 | return result; |
210 | 0 | } |
211 | | |
212 | | //////////////////////////////////////////////////////////////////////////////// |
213 | | // ss_new creates a SIZED_STRING from a C string. |
214 | | // |
215 | | SIZED_STRING* ss_new(const char* s) |
216 | 0 | { |
217 | 0 | SIZED_STRING* result; |
218 | |
|
219 | 0 | size_t length = strlen(s); |
220 | |
|
221 | 0 | result = (SIZED_STRING*) yr_malloc(sizeof(SIZED_STRING) + length); |
222 | |
|
223 | 0 | if (result == NULL) |
224 | 0 | return NULL; |
225 | | |
226 | 0 | result->length = (uint32_t) length; |
227 | 0 | result->flags = 0; |
228 | | |
229 | | // Copy the string and the null terminator. |
230 | 0 | strcpy(result->c_string, s); |
231 | |
|
232 | 0 | return result; |
233 | 0 | } |
234 | | |
235 | | //////////////////////////////////////////////////////////////////////////////// |
236 | | // Convert a SIZED_STRING to a wide version. It is up to the caller to free |
237 | | // the returned string. |
238 | | // |
239 | | SIZED_STRING* ss_convert_to_wide(SIZED_STRING* s) |
240 | 0 | { |
241 | 0 | SIZED_STRING* wide = (SIZED_STRING*) yr_malloc( |
242 | 0 | sizeof(SIZED_STRING) + s->length * 2); |
243 | |
|
244 | 0 | if (wide == NULL) |
245 | 0 | return NULL; |
246 | | |
247 | 0 | for (size_t i = 0; i < s->length; i++) |
248 | 0 | { |
249 | 0 | wide->c_string[i * 2] = s->c_string[i]; |
250 | 0 | wide->c_string[i * 2 + 1] = '\x00'; |
251 | 0 | } |
252 | |
|
253 | 0 | wide->length = s->length * 2; |
254 | 0 | wide->flags = s->flags | STRING_FLAGS_WIDE; |
255 | |
|
256 | 0 | return wide; |
257 | 0 | } |