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