1 /* radare - LGPL - Copyright 2010-2015 - pancake */
2
3 #include <r_search.h>
4
ignoreMask(const ut8 * bm,int len)5 static int ignoreMask(const ut8 *bm, int len) {
6 int i;
7 for (i=0; i<len; i++) {
8 if (bm[i] != 0xff) {
9 return 0;
10 }
11 }
12 return 1;
13 }
14
r_search_keyword_new(const ut8 * kwbuf,int kwlen,const ut8 * bmbuf,int bmlen,const char * data)15 R_API RSearchKeyword* r_search_keyword_new(const ut8 *kwbuf, int kwlen, const ut8 *bmbuf, int bmlen, const char *data) {
16 RSearchKeyword *kw;
17 if (kwlen < 1 || bmlen < 0) {
18 return NULL;
19 }
20 kw = R_NEW0 (RSearchKeyword);
21 if (!kw) {
22 return NULL;
23 }
24 kw->type = R_SEARCH_KEYWORD_TYPE_BINARY;
25 kw->data = (void *) data;
26 kw->keyword_length = kwlen;
27 kw->bin_keyword = malloc (kwlen);
28 if (!kw->bin_keyword) {
29 r_search_keyword_free (kw);
30 return NULL;
31 }
32 memcpy (kw->bin_keyword, kwbuf, kwlen);
33 if (bmbuf && bmlen > 0 && !ignoreMask (bmbuf, bmlen)) {
34 kw->bin_binmask = malloc (bmlen);
35 if (!kw->bin_binmask) {
36 r_search_keyword_free (kw);
37 return NULL;
38 }
39 memcpy (kw->bin_binmask, bmbuf, bmlen);
40 kw->binmask_length = bmlen;
41 } else {
42 kw->bin_binmask = NULL;
43 kw->binmask_length = 0;
44 }
45 return kw;
46 }
47
r_search_keyword_free(RSearchKeyword * kw)48 R_API void r_search_keyword_free (RSearchKeyword *kw) {
49 if (!kw) {
50 return;
51 }
52 free (kw->bin_binmask);
53 free (kw->bin_keyword);
54 free (kw);
55 }
56
r_search_keyword_new_str(const char * kwbuf,const char * bmstr,const char * data,int ignore_case)57 R_API RSearchKeyword* r_search_keyword_new_str(const char *kwbuf, const char *bmstr, const char *data, int ignore_case) {
58 RSearchKeyword *kw;
59 ut8 *bmbuf = NULL;
60 int bmlen = 0;
61
62 if (bmstr) {
63 bmbuf = malloc (strlen (bmstr)+1);
64 if (!bmbuf) {
65 return NULL;
66 }
67 bmlen = r_hex_str2bin (bmstr, bmbuf);
68 if (bmlen < 1) {
69 R_FREE (bmbuf);
70 }
71 }
72 kw = r_search_keyword_new ((ut8 *)kwbuf, strlen (kwbuf), bmbuf, bmlen, data);
73 if (kw) {
74 kw->icase = ignore_case;
75 kw->type = R_SEARCH_KEYWORD_TYPE_STRING;
76 }
77 free (bmbuf);
78 return kw;
79 }
80
r_search_keyword_new_wide(const char * kwbuf,const char * bmstr,const char * data,int ignore_case)81 R_API RSearchKeyword* r_search_keyword_new_wide(const char *kwbuf, const char *bmstr, const char *data, int ignore_case) {
82 RSearchKeyword *kw;
83 int len;
84 const char *p2;
85 char *p, *str;
86 ut8 *bmbuf = NULL;
87 int bmlen = 0;
88
89 if (bmstr) {
90 bmbuf = malloc (strlen (bmstr)+1);
91 if (!bmbuf) {
92 return NULL;
93 }
94 bmlen = r_hex_str2bin (bmstr, bmbuf);
95 if (bmlen < 1) {
96 R_FREE (bmbuf);
97 }
98 }
99
100 len = strlen(kwbuf);
101 str = malloc((len+1)*2);
102 for (p2=kwbuf, p=str; *p2; ) {
103 RRune ch;
104 int num_utf8_bytes = r_utf8_decode ((const ut8 *)p2, kwbuf + len - p2, &ch);
105 if (num_utf8_bytes < 1) {
106 eprintf ("WARNING: Malformed UTF8 at pos %td\n", p2 - kwbuf);
107 p[0] = *p2;
108 p[1] = 0;
109 p2++;
110 p += 2;
111 continue;
112 }
113 if (ignore_case && ch <= 0xff) {
114 ch = tolower (ch);
115 }
116 int num_wide_bytes = r_utf16le_encode ((ut8 *)p, ch);
117 r_warn_if_fail (num_wide_bytes != 0);
118 p2 += num_utf8_bytes;
119 p += num_wide_bytes;
120 }
121
122 kw = r_search_keyword_new ((ut8 *)str, p - str, bmbuf, bmlen, data);
123 free(str);
124 if (kw) {
125 kw->icase = ignore_case;
126 }
127 free(bmbuf);
128 return kw;
129 }
130
r_search_keyword_new_hex(const char * kwstr,const char * bmstr,const char * data)131 R_API RSearchKeyword* r_search_keyword_new_hex(const char *kwstr, const char *bmstr, const char *data) {
132 RSearchKeyword *kw;
133 ut8 *kwbuf, *bmbuf;
134 int kwlen, bmlen = 0;
135
136 if (!kwstr) {
137 return NULL;
138 }
139
140 kwbuf = malloc (strlen (kwstr)+1);
141 if (!kwbuf) {
142 return NULL;
143 }
144
145 kwlen = r_hex_str2bin (kwstr, kwbuf);
146 if (kwlen < 1) {
147 free (kwbuf);
148 return NULL;
149 }
150
151 bmbuf = NULL;
152 if (bmstr && *bmstr) {
153 bmbuf = malloc (strlen (bmstr)+1);
154 if (!bmbuf) {
155 free (kwbuf);
156 return NULL;
157 }
158 bmlen = r_hex_str2bin (bmstr, bmbuf);
159 if (bmlen < 1) {
160 free (bmbuf);
161 free (kwbuf);
162 return NULL;
163 }
164 }
165
166 kw = r_search_keyword_new (kwbuf, kwlen, bmbuf, bmlen, data);
167 free (kwbuf);
168 free (bmbuf);
169 return kw;
170 }
171
r_search_keyword_new_hexmask(const char * kwstr,const char * data)172 R_API RSearchKeyword* r_search_keyword_new_hexmask(const char *kwstr, const char *data) {
173 RSearchKeyword *ks = NULL;
174 ut8 *kw, *bm;
175 if (kwstr != NULL) {
176 int len = strlen (kwstr);
177 kw = malloc (len + 4);
178 bm = malloc (len + 4);
179 if (kw != NULL && bm != NULL) {
180 len = r_hex_str2binmask (kwstr, (ut8*)kw, (ut8*)bm);
181 if (len < 0) {
182 len = -len - 1;
183 }
184 if (len > 0) {
185 ks = r_search_keyword_new (kw, len, bm, len, data);
186 }
187 }
188 free (kw);
189 free (bm);
190 }
191 return ks;
192 }
193
194 /* Validate a regexp in the canonical format /<regexp>/<options> */
r_search_keyword_new_regexp(const char * str,const char * data)195 R_API RSearchKeyword *r_search_keyword_new_regexp (const char *str, const char *data) {
196 RSearchKeyword *kw;
197 int i = 0, start, length;
198
199 while (isspace ((const unsigned char)str[i])) {
200 i++;
201 }
202
203 if (str[i++] != '/') {
204 return NULL;
205 }
206
207 /* Find the fist non backslash-escaped slash */
208 int specials = 0;
209 for (start = i; str[i]; i++) {
210 if (str[i] == '/' && str[i - 1] != '\\') {
211 break;
212 } else if (str[i - 1] == '\\' && isalpha ((unsigned char)str[i])) {
213 specials++;
214 }
215 }
216
217 if (str[i++] != '/') {
218 return NULL;
219 }
220
221 length = i - start - 1;
222 if ((length > 128) || (length < 1)) {
223 return NULL;
224 }
225
226 kw = R_NEW0(RSearchKeyword);
227 if (!kw) {
228 return NULL;
229 }
230
231 kw->bin_keyword = malloc (length+1);
232 if (!kw->bin_keyword) {
233 r_search_keyword_free (kw);
234 return NULL;
235 }
236
237 kw->bin_keyword[length]=0;
238 memcpy(kw->bin_keyword, str + start, length);
239 kw->keyword_length = length - specials;
240 kw->type = R_SEARCH_KEYWORD_TYPE_STRING;
241 kw->data = (void *) data;
242
243 /* Parse the options */
244 for (; str[i]; i++) {
245 switch (str[i]) {
246 case 'i':
247 kw->icase = true;
248 break;
249 default:
250 r_search_keyword_free (kw);
251 return NULL;
252 }
253 }
254
255 return kw;
256 }
257