1 /* radare - LGPL - Copyright 2009-2020 - pancake, nibble */
2 
3 #include <r_anal.h>
4 #include <r_sign.h>
5 #include <r_search.h>
6 #include <r_core.h>
7 
8 R_LIB_VERSION (r_sign);
9 
10 #define SIGN_DIFF_MATCH_BYTES_THRESHOLD 1.0
11 #define SIGN_DIFF_MATCH_GRAPH_THRESHOLD 1.0
12 
getRealRef(RCore * core,ut64 off)13 const char *getRealRef(RCore *core, ut64 off) {
14 	RFlagItem *item;
15 	RListIter *iter;
16 
17 	const RList *list = r_flag_get_list (core->flags, off);
18 	if (!list) {
19 		return NULL;
20 	}
21 
22 	r_list_foreach (list, iter, item) {
23 		if (!item->name) {
24 			continue;
25 		}
26 		if (strncmp (item->name, "sym.", 4)) {
27 			continue;
28 		}
29 		return item->name;
30 	}
31 
32 	return NULL;
33 }
34 
r_sign_fcn_vars(RAnal * a,RAnalFunction * fcn)35 R_API RList *r_sign_fcn_vars(RAnal *a, RAnalFunction *fcn) {
36 	r_return_val_if_fail (a && fcn, NULL);
37 
38 	RCore *core = a->coreb.core;
39 
40 	if (!core) {
41 		return NULL;
42 	}
43 
44 	RListIter *iter;
45 	RAnalVar *var;
46 	RList *ret = r_list_newf ((RListFree) free);
47 	if (!ret) {
48 		return NULL;
49 	}
50 	RList *reg_vars = r_anal_var_list (core->anal, fcn, R_ANAL_VAR_KIND_REG);
51 	RList *spv_vars = r_anal_var_list (core->anal, fcn, R_ANAL_VAR_KIND_SPV);
52 	RList *bpv_vars = r_anal_var_list (core->anal, fcn, R_ANAL_VAR_KIND_BPV);
53 	r_list_foreach (bpv_vars, iter, var) {
54 		r_list_append (ret, r_str_newf ("b%d", var->delta));
55 	}
56 	r_list_foreach (spv_vars, iter, var) {
57 		r_list_append (ret, r_str_newf ("s%d", var->delta));
58 	}
59 	r_list_foreach (reg_vars, iter, var) {
60 		r_list_append (ret, r_str_newf ("r%d", var->delta));
61 	}
62 	r_list_free (reg_vars);
63 	r_list_free (bpv_vars);
64 	r_list_free (spv_vars);
65 	return ret;
66 }
67 
r_sign_fcn_types(RAnal * a,RAnalFunction * fcn)68 R_API RList *r_sign_fcn_types(RAnal *a, RAnalFunction *fcn) {
69 
70 	// From anal/types/*:
71 	// Get key-value types from sdb matching "func.%s", fcn->name
72 	// Get func.%s.args (number of args)
73 	// Get type,name pairs
74 	// Put everything in RList following the next format:
75 	// types: main.ret=%type%, main.args=%num%, main.arg.0="int,argc", ...
76 
77 	r_return_val_if_fail (a && fcn, NULL);
78 
79 	RList *ret = r_list_newf ((RListFree) free);
80 	if (!ret) {
81 		return NULL;
82 	}
83 
84 	char *scratch = r_str_newf ("func.%s.args", fcn->name);
85 	if (!scratch) {
86 		return NULL;
87 	}
88 	const char *fcntypes = sdb_const_get (a->sdb_types, scratch, 0);
89 	free (scratch);
90 
91 	scratch = r_str_newf ("func.%s.ret", fcn->name);
92 	if (!scratch) {
93 		return NULL;
94 	}
95 	const char *ret_type = sdb_const_get (a->sdb_types, scratch, 0);
96 	free (scratch);
97 
98 	if (fcntypes) {
99 		if (ret_type) {
100 			r_list_append (ret, r_str_newf ("func.%s.ret=%s", fcn->name, ret_type));
101 		}
102 		int argc = atoi (fcntypes);
103 		r_list_append (ret, r_str_newf ("func.%s.args=%d", fcn->name, argc));
104 		int i;
105 		for (i = 0; i < argc; i++) {
106 			const char *arg = sdb_const_get (a->sdb_types, r_str_newf ("func.%s.arg.%d", fcn->name, i), 0);
107 			r_list_append (ret, r_str_newf ("func.%s.arg.%d=\"%s\"", fcn->name, i, arg));
108 		}
109 	}
110 
111 	return ret;
112 }
113 
r_sign_fcn_xrefs(RAnal * a,RAnalFunction * fcn)114 R_API RList *r_sign_fcn_xrefs(RAnal *a, RAnalFunction *fcn) {
115 	RListIter *iter = NULL;
116 	RAnalRef *refi = NULL;
117 
118 	r_return_val_if_fail (a && fcn, NULL);
119 
120 	RCore *core = a->coreb.core;
121 
122 	if (!core) {
123 		return NULL;
124 	}
125 
126 	RList *ret = r_list_newf ((RListFree) free);
127 	RList *xrefs = r_anal_function_get_xrefs (fcn);
128 	r_list_foreach (xrefs, iter, refi) {
129 		if (refi->type == R_ANAL_REF_TYPE_CODE || refi->type == R_ANAL_REF_TYPE_CALL) {
130 			const char *flag = getRealRef (core, refi->addr);
131 			if (flag) {
132 				r_list_append (ret, r_str_new (flag));
133 			}
134 		}
135 	}
136 	r_list_free (xrefs);
137 	return ret;
138 }
139 
r_sign_fcn_refs(RAnal * a,RAnalFunction * fcn)140 R_API RList *r_sign_fcn_refs(RAnal *a, RAnalFunction *fcn) {
141 	RListIter *iter = NULL;
142 	RAnalRef *refi = NULL;
143 
144 	r_return_val_if_fail (a && fcn, NULL);
145 
146 	RCore *core = a->coreb.core;
147 
148 	if (!core) {
149 		return NULL;
150 	}
151 
152 	RList *ret = r_list_newf ((RListFree) free);
153 	RList *refs = r_anal_function_get_refs (fcn);
154 	r_list_foreach (refs, iter, refi) {
155 		if (refi->type == R_ANAL_REF_TYPE_CODE || refi->type == R_ANAL_REF_TYPE_CALL) {
156 			const char *flag = getRealRef (core, refi->addr);
157 			if (flag) {
158 				r_list_append (ret, r_str_new (flag));
159 			}
160 		}
161 	}
162 	r_list_free (refs);
163 	return ret;
164 }
165 
zign_types_to_list(RAnal * a,const char * types)166 static RList *zign_types_to_list(RAnal *a, const char *types) {
167 	RList *ret = r_list_newf ((RListFree)free);
168 	if (!ret) {
169 		return NULL;
170 	}
171 
172 	unsigned int i = 0, prev = 0, len = strlen (types);
173 	bool quoted = false;
174 	char *token = NULL;
175 	for (i = 0; i <= len; i++) {
176 		if (types[i] == '"') {
177 			quoted = !quoted;
178 		} else if ((types[i] == ',' && !quoted) || types[i] == '\0') {
179 			token = r_str_ndup (types + prev, i - prev);
180 			if (token) {
181 				prev = i + 1;
182 				r_list_append (ret, token);
183 				token = NULL;
184 			}
185 		}
186 	}
187 
188 	return ret;
189 }
190 
do_reflike_sig(const char * token)191 static RList *do_reflike_sig(const char *token) {
192 	RList *list = NULL;
193 	char *scratch = r_str_new (token);
194 	int cnt = r_str_split (scratch, ',');
195 	if (cnt > 0 && (list = r_list_newf ((RListFree)free))) {
196 		int i;
197 		for (i = 0; i < cnt; i++) {
198 			r_list_append (list, r_str_new (r_str_word_get0 (scratch, i)));
199 		}
200 	}
201 	free (scratch);
202 	return list;
203 }
204 
205 #define DBL_VAL_FAIL(x,y) \
206 	if (x) { \
207 		eprintf ("Warning: Skipping signature with multiple %c signatures (%s)\n", y, k); \
208 		success = false; \
209 		goto out; \
210 	}
r_sign_deserialize(RAnal * a,RSignItem * it,const char * k,const char * v)211 R_API bool r_sign_deserialize(RAnal *a, RSignItem *it, const char *k, const char *v) {
212 	r_return_val_if_fail (a && it && k && v, false);
213 
214 	bool success = true;
215 	char *k2 = r_str_new (k);
216 	char *v2 = r_str_new (v);
217 	if (!k2 || !v2) {
218 		success = false;
219 		goto out;
220 	}
221 
222 	// Deserialize key: zign|space|name
223 	int n = r_str_split (k2, '|');
224 	if (n != 3) {
225 		eprintf ("Warning: Skipping signature with invalid key (%s)\n", k);
226 		success = false;
227 		goto out;
228 	}
229 	if (strcmp (r_str_word_get0 (k2, 0), "zign")) {
230 		eprintf ("Warning: Skipping signature with invalid value (%s)\n", k);
231 		success = false;
232 		goto out;
233 	}
234 
235 	it->space = r_spaces_add (&a->zign_spaces, r_str_word_get0 (k2, 1));
236 	it->name = r_str_new (r_str_word_get0 (k2, 2));
237 
238 	// remove newline at end
239 	strtok (v2, "\n");
240 	// Deserialize value: |k:v|k:v|k:v|...
241 	n = r_str_split (v2, '|');
242 	const char *token = NULL;
243 	int w, size;
244 	for (w = 0; w < n; w++) {
245 		const char *word = r_str_word_get0 (v2, w);
246 		if (!word) {
247 			break;
248 		}
249 		if (!*word) {
250 			continue;
251 		}
252 		token = word + 2;
253 		if (!strcmp (word, "*")) {
254 			continue;
255 		}
256 		if (strlen (word) < 3 || word[1] != ':') {
257 			eprintf ("Warning: Skipping signature with corrupted serialization (%s:%s)\n", k, word);
258 			success = false;
259 			goto out;
260 		}
261 		RSignType st = (RSignType)*word;
262 		switch (st) {
263 		case R_SIGN_ANAL:
264 			eprintf ("Unsupported\n");
265 			break;
266 		case R_SIGN_NAME:
267 			DBL_VAL_FAIL (it->realname, R_SIGN_NAME);
268 			it->realname = strdup (token);
269 			break;
270 		case R_SIGN_COMMENT:
271 			DBL_VAL_FAIL (it->comment, R_SIGN_COMMENT);
272 			it->comment = strdup (token);
273 			break;
274 		case R_SIGN_GRAPH:
275 			DBL_VAL_FAIL (it->graph, R_SIGN_GRAPH);
276 			if (strlen (token) == 2 * sizeof (RSignGraph)) {
277 				it->graph = R_NEW0 (RSignGraph);
278 				if (it->graph) {
279 					r_hex_str2bin (token, (ut8 *)it->graph);
280 				}
281 			}
282 			break;
283 		case R_SIGN_OFFSET:
284 			DBL_VAL_FAIL ((it->addr != UT64_MAX), R_SIGN_OFFSET);
285 			it->addr = atoll (token);
286 			break;
287 		case R_SIGN_REFS:
288 			DBL_VAL_FAIL (it->refs, R_SIGN_REFS);
289 			if (!(it->refs = do_reflike_sig (token))) {
290 				success = false;
291 				goto out;
292 			}
293 			break;
294 		case R_SIGN_XREFS:
295 			DBL_VAL_FAIL (it->xrefs, R_SIGN_XREFS);
296 			if (!(it->xrefs = do_reflike_sig (token))) {
297 				success = false;
298 				goto out;
299 			}
300 			break;
301 		case R_SIGN_VARS:
302 			DBL_VAL_FAIL (it->vars, R_SIGN_VARS);
303 			if (!(it->vars = do_reflike_sig (token))) {
304 				success = false;
305 				goto out;
306 			}
307 			break;
308 		case R_SIGN_TYPES:
309 			DBL_VAL_FAIL (it->types, R_SIGN_TYPES);
310 			it->types = zign_types_to_list (a, token);
311 			break;
312 		case R_SIGN_BBHASH:
313 			DBL_VAL_FAIL (it->hash, R_SIGN_BBHASH);
314 			if (token[0] != 0) {
315 				it->hash = R_NEW0 (RSignHash);
316 				if (it->hash) {
317 					it->hash->bbhash = r_str_new (token);
318 				}
319 			}
320 			break;
321 		case R_SIGN_BYTES:
322 			// following two errors are not due to double entries
323 			if (!it->bytes) {
324 				eprintf ("Warning: Skipping signature with no bytes size (%s)\n", k);
325 				success = false;
326 				goto out;
327 			}
328 			if (strlen (token) != 2 * it->bytes->size) {
329 				eprintf ("Warning: Skipping signature with invalid size (%s)\n", k);
330 				success = false;
331 				goto out;
332 			}
333 			DBL_VAL_FAIL (it->bytes->bytes, R_SIGN_BYTES);
334 			it->bytes->bytes = malloc (it->bytes->size);
335 			if (it->bytes->bytes) {
336 				r_hex_str2bin (token, it->bytes->bytes);
337 			}
338 			break;
339 		case R_SIGN_BYTES_MASK:
340 			// following two errors are not due to double entries
341 			if (!it->bytes) {
342 				eprintf ("Warning: Skipping signature with no mask size (%s)\n", k);
343 				success = false;
344 				goto out;
345 			}
346 			if (strlen (token) != 2 * it->bytes->size) {
347 				eprintf ("Warning: Skipping signature invalid mask size (%s)\n", k);
348 				success = false;
349 				goto out;
350 			}
351 			DBL_VAL_FAIL (it->bytes->mask, R_SIGN_BYTES);
352 			it->bytes->mask = malloc (it->bytes->size);
353 			if (!it->bytes->mask) {
354 				goto out;
355 			}
356 			r_hex_str2bin (token, it->bytes->mask);
357 			break;
358 		case R_SIGN_BYTES_SIZE:
359 			// allocate
360 			size = atoi (token);
361 			if (size > 0) {
362 				DBL_VAL_FAIL (it->bytes, R_SIGN_BYTES_SIZE);
363 				it->bytes = R_NEW0 (RSignBytes);
364 				if (!it->bytes) {
365 					goto out;
366 				}
367 				it->bytes->size = size;
368 			}
369 			break;
370 		default:
371 			eprintf ("Unsupported (%s)\n", word);
372 			break;
373 		}
374 	}
375 out:
376 	free (k2);
377 	free (v2);
378 	return success;
379 }
380 #undef DBL_VAL_FAIL
381 
serializeKey(RAnal * a,const RSpace * space,const char * name,char * k)382 static void serializeKey(RAnal *a, const RSpace *space, const char* name, char *k) {
383 	snprintf (k, R_SIGN_KEY_MAXSZ, "zign|%s|%s", space? space->name: "*", name);
384 }
385 
serializeKeySpaceStr(RAnal * a,const char * space,const char * name,char * k)386 static void serializeKeySpaceStr(RAnal *a, const char *space, const char* name, char *k) {
387 	snprintf (k, R_SIGN_KEY_MAXSZ, "zign|%s|%s", space, name);
388 }
389 
serialize(RAnal * a,RSignItem * it,char * k,char * v)390 static void serialize(RAnal *a, RSignItem *it, char *k, char *v) {
391 	RListIter *iter = NULL;
392 	char *hexbytes = NULL, *hexmask = NULL, *hexgraph = NULL;
393 	char *refs = NULL, *xrefs = NULL, *ref = NULL, *var, *vars = NULL;
394 	char *type, *types = NULL;
395 	int i = 0, len = 0;
396 	RSignBytes *bytes = it->bytes;
397 	RSignGraph *graph = it->graph;
398 	RSignHash *hash = it->hash;
399 
400 	if (k) {
401 		serializeKey (a, it->space, it->name, k);
402 	}
403 	if (v) {
404 		if (bytes) {
405 			len = bytes->size * 2 + 1;
406 			hexbytes = calloc (1, len);
407 			hexmask = calloc (1, len);
408 			if (!hexbytes || !hexmask) {
409 				free (hexbytes);
410 				free (hexmask);
411 				return;
412 			}
413 			if (!bytes->bytes) {
414 				bytes->bytes = malloc ((bytes->size + 1) * 3);
415 			}
416 			r_hex_bin2str (bytes->bytes, bytes->size, hexbytes);
417 			if (!bytes->mask) {
418 				bytes->mask = malloc ((bytes->size + 1) * 3);
419 			}
420 			r_hex_bin2str (bytes->mask, bytes->size, hexmask);
421 		}
422 		if (graph) {
423 			hexgraph = calloc (1, sizeof (RSignGraph) * 2 + 1);
424 			if (hexgraph) {
425 				r_hex_bin2str ((ut8 *) graph, sizeof (RSignGraph), hexgraph);
426 			}
427 		}
428 		i = 0;
429 		r_list_foreach (it->refs, iter, ref) {
430 			if (i > 0) {
431 				refs = r_str_appendch (refs, ',');
432 			}
433 			refs = r_str_append (refs, ref);
434 			i++;
435 		}
436 		i = 0;
437 		r_list_foreach (it->xrefs, iter, ref) {
438 			if (i > 0) {
439 				xrefs = r_str_appendch (xrefs, ',');
440 			}
441 			xrefs = r_str_append (xrefs, ref);
442 			i++;
443 		}
444 		i = 0;
445 		r_list_foreach (it->vars, iter, var) {
446 			if (i > 0) {
447 				vars = r_str_appendch (vars, ',');
448 			}
449 			vars = r_str_append (vars, var);
450 			i++;
451 		}
452 		i = 0;
453 		r_list_foreach (it->types, iter, type) {
454 			if (i > 0) {
455 				types = r_str_appendch (types, ',');
456 			}
457 			types = r_str_append (types, type);
458 			i++;
459 		}
460 		RStrBuf *sb = r_strbuf_new ("");
461 		if (bytes) {
462 			// TODO: do not hardcoded s,b,m here, use RSignType enum
463 			r_strbuf_appendf (sb, "|s:%d|b:%s|m:%s", bytes->size, hexbytes, hexmask);
464 		}
465 		if (it->addr != UT64_MAX) {
466 			r_strbuf_appendf (sb, "|%c:%"PFMT64d, R_SIGN_OFFSET, it->addr);
467 		}
468 		if (graph) {
469 			r_strbuf_appendf (sb, "|%c:%s", R_SIGN_GRAPH, hexgraph);
470 		}
471 		if (refs) {
472 			r_strbuf_appendf (sb, "|%c:%s", R_SIGN_REFS, refs);
473 		}
474 		if (xrefs) {
475 			r_strbuf_appendf (sb, "|%c:%s", R_SIGN_XREFS, xrefs);
476 		}
477 		if (vars) {
478 			r_strbuf_appendf (sb, "|%c:%s", R_SIGN_VARS, vars);
479 		}
480 		if (types) {
481 			r_strbuf_appendf (sb, "|%c:%s", R_SIGN_TYPES, types);
482 		}
483 		if (it->comment) {
484 			// b64 encoded
485 			r_strbuf_appendf (sb, "|%c:%s", R_SIGN_COMMENT, it->comment);
486 		}
487 		if (it->realname) {
488 			// b64 encoded
489 			r_strbuf_appendf (sb, "|%c:%s", R_SIGN_NAME, it->realname);
490 		}
491 		if (hash && hash->bbhash) {
492 			r_strbuf_appendf (sb, "|%c:%s", R_SIGN_BBHASH, hash->bbhash);
493 		}
494 		if (r_strbuf_length (sb) >= R_SIGN_VAL_MAXSZ) {
495 			eprintf ("Signature limit reached for 0x%08"PFMT64x" (%s)\n", it->addr, it->name);
496 		}
497 		char *res = r_strbuf_drain (sb);
498 		if (res) {
499 			strncpy (v, res, R_SIGN_VAL_MAXSZ);
500 			free (res);
501 		}
502 
503 		free (hexbytes);
504 		free (hexmask);
505 		free (hexgraph);
506 		free (refs);
507 		free (vars);
508 		free (xrefs);
509 		free (types);
510 	}
511 }
512 
deserialize_sign_space(RAnal * a,RSpace * space)513 static RList *deserialize_sign_space(RAnal *a, RSpace *space) {
514 	r_return_val_if_fail (a && space, NULL);
515 
516 	char k[R_SIGN_KEY_MAXSZ];
517 	serializeKey (a, space, "", k);
518 	SdbList *zigns = sdb_foreach_match (a->sdb_zigns, k, false);
519 
520 	SdbListIter *iter;
521 	SdbKv *kv;
522 	RList *ret = r_list_newf ((RListFree)r_sign_item_free);
523 	if (!ret) {
524 		goto beach;
525 	}
526 	ls_foreach (zigns, iter, kv) {
527 		RSignItem *it = r_sign_item_new ();
528 		if (!it) {
529 			goto beach;
530 		}
531 		if (r_sign_deserialize (a, it, kv->base.key, kv->base.value)) {
532 			r_list_append (ret, it);
533 		} else {
534 			r_sign_item_free (it);
535 		}
536 	}
537 
538 	ls_free (zigns);
539 	return ret;
540 
541 beach:
542 	ls_free (zigns);
543 	r_list_free (ret);
544 	return NULL;
545 }
546 
mergeItem(RSignItem * dst,RSignItem * src)547 static void mergeItem(RSignItem *dst, RSignItem *src) {
548 	RListIter *iter = NULL;
549 	char *ref, *var, *type;
550 
551 	if (src->bytes) {
552 		r_sign_bytes_free (dst->bytes);
553 		dst->bytes = R_NEW0 (RSignBytes);
554 		if (!dst->bytes) {
555 			return;
556 		}
557 		dst->space = src->space;
558 		dst->bytes->size = src->bytes->size;
559 		dst->bytes->bytes = malloc (src->bytes->size);
560 		if (!dst->bytes->bytes) {
561 			r_sign_bytes_free (dst->bytes);
562 			return;
563 		}
564 		memcpy (dst->bytes->bytes, src->bytes->bytes, src->bytes->size);
565 		dst->bytes->mask = malloc (src->bytes->size);
566 		if (!dst->bytes->mask) {
567 			r_sign_bytes_free (dst->bytes);
568 			return;
569 		}
570 		memcpy (dst->bytes->mask, src->bytes->mask, src->bytes->size);
571 	}
572 
573 	if (src->graph) {
574 		free (dst->graph);
575 		dst->graph = R_NEW0 (RSignGraph);
576 		if (!dst->graph) {
577 			return;
578 		}
579 		*dst->graph = *src->graph;
580 	}
581 
582 	if (src->comment) {
583 		dst->comment = strdup (src->comment);
584 	}
585 
586 	if (src->realname) {
587 		dst->realname = strdup (src->realname);
588 	}
589 
590 	if (src->addr != UT64_MAX) {
591 		dst->addr = src->addr;
592 	}
593 
594 	if (src->refs) {
595 		r_list_free (dst->refs);
596 
597 		dst->refs = r_list_newf ((RListFree)free);
598 		r_list_foreach (src->refs, iter, ref) {
599 			r_list_append (dst->refs, r_str_new (ref));
600 		}
601 	}
602 
603 	if (src->vars) {
604 		r_list_free (dst->vars);
605 
606 		dst->vars = r_list_newf ((RListFree)free);
607 		r_list_foreach (src->vars, iter, var) {
608 			r_list_append (dst->vars, r_str_new (var));
609 		}
610 	}
611 
612 	if (src->types) {
613 		r_list_free (dst->types);
614 
615 		dst->types = r_list_newf ((RListFree)free);
616 		r_list_foreach (src->types, iter, type) {
617 			r_list_append (dst->types, r_str_new (type));
618 		}
619 	}
620 
621 	if (src->hash) {
622 		if (!dst->hash) {
623 			dst->hash = R_NEW0 (RSignHash);
624 			if (!dst->hash) {
625 				return;
626 			}
627 		}
628 		if (src->hash->bbhash) {
629 			dst->hash->bbhash = strdup (src->hash->bbhash);
630 		}
631 	}
632 }
633 
r_sign_get_item(RAnal * a,const char * name)634 R_API RSignItem *r_sign_get_item(RAnal *a, const char *name) {
635 	char k[R_SIGN_KEY_MAXSZ];
636 	serializeKey (a, r_spaces_current (&a->zign_spaces), name, k);
637 
638 	const char *v = sdb_const_get (a->sdb_zigns, k, 0);
639 	if (!v) {
640 		return NULL;
641 	}
642 	RSignItem *it = r_sign_item_new ();
643 	if (!it) {
644 		return NULL;
645 	}
646 	if (!r_sign_deserialize (a, it, k, v)) {
647 		r_sign_item_free (it);
648 		return NULL;
649 	}
650 	return it;
651 }
652 
r_sign_add_item(RAnal * a,RSignItem * it)653 R_API bool r_sign_add_item(RAnal *a, RSignItem *it) {
654 	char key[R_SIGN_KEY_MAXSZ], val[R_SIGN_VAL_MAXSZ];
655 	const char *curval = NULL;
656 	bool retval = true;
657 	RSignItem *curit = r_sign_item_new ();
658 	if (!curit) {
659 		return false;
660 	}
661 
662 	serialize (a, it, key, val);
663 	curval = sdb_const_get (a->sdb_zigns, key, 0);
664 	if (curval) {
665 		if (!r_sign_deserialize (a, curit, key, curval)) {
666 			eprintf ("error: cannot deserialize zign\n");
667 			retval = false;
668 			goto out;
669 		}
670 		mergeItem (curit, it);
671 		serialize (a, curit, key, val);
672 	}
673 	sdb_set (a->sdb_zigns, key, val, 0);
674 
675 out:
676 	r_sign_item_free (curit);
677 
678 	return retval;
679 }
680 
addHash(RAnal * a,const char * name,int type,const char * val)681 static bool addHash(RAnal *a, const char *name, int type, const char *val) {
682 	RSignItem *it = r_sign_item_new ();
683 	if (!it) {
684 		r_sign_item_free (it);
685 		return false;
686 	}
687 	it->name = r_str_new (name);
688 	if (!it->name) {
689 		r_sign_item_free (it);
690 		return false;
691 	}
692 	it->hash = R_NEW0 (RSignHash);
693 	if (!it->hash) {
694 		r_sign_item_free (it);
695 		return false;
696 	}
697 	it->space = r_spaces_current (&a->zign_spaces);
698 
699 	bool retval = false;
700 	switch (type) {
701 	case R_SIGN_BBHASH:
702 		it->hash->bbhash = strdup (val);
703 		retval = r_sign_add_item (a, it);
704 		r_sign_item_free (it);
705 		break;
706 	}
707 
708 	return retval;
709 }
710 
addBBHash(RAnal * a,RAnalFunction * fcn,const char * name)711 static bool addBBHash(RAnal *a, RAnalFunction *fcn, const char *name) {
712 	bool retval = false;
713 	RSignItem *it = r_sign_item_new ();
714 	if (!it) {
715 		goto beach;
716 	}
717 	it->name = r_str_new (name);
718 	if (!it->name) {
719 		goto beach;
720 	}
721 	it->space = r_spaces_current (&a->zign_spaces);
722 
723 	if (r_sign_addto_item (a, it, fcn, R_SIGN_BBHASH)) {
724 		retval = r_sign_add_item (a, it);
725 	}
726 beach:
727 	r_sign_item_free (it);
728 	return retval;
729 }
730 
addBytes(RAnal * a,const char * name,ut64 size,const ut8 * bytes,const ut8 * mask)731 static bool addBytes(RAnal *a, const char *name, ut64 size, const ut8 *bytes, const ut8 *mask) {
732 	bool retval = true;
733 
734 	if (r_mem_is_zero (mask, size)) {
735 		eprintf ("error: zero mask\n");
736 		return false;
737 	}
738 
739 	RSignItem *it = r_sign_item_new ();
740 	if (!it) {
741 		return false;
742 	}
743 
744 	it->name = r_str_new (name);
745 	if (!it->name) {
746 		free (it);
747 		return false;
748 	}
749 	it->space = r_spaces_current (&a->zign_spaces);
750 	it->bytes = R_NEW0 (RSignBytes);
751 	if (!it->bytes) {
752 		goto fail;
753 	}
754 	it->bytes->size = size;
755 	it->bytes->bytes = malloc (size);
756 	if (!it->bytes->bytes) {
757 		goto fail;
758 	}
759 	memcpy (it->bytes->bytes, bytes, size);
760 	it->bytes->mask = malloc (size);
761 	if (!it->bytes->mask) {
762 		goto fail;
763 	}
764 	memcpy (it->bytes->mask, mask, size);
765 	retval = r_sign_add_item (a, it);
766 	r_sign_item_free (it);
767 	return retval;
768 fail:
769 	if (it) {
770 		free (it->name);
771 		r_sign_bytes_free (it->bytes);
772 	}
773 	free (it);
774 	return false;
775 }
776 
r_sign_add_hash(RAnal * a,const char * name,int type,const char * val,int len)777 R_API bool r_sign_add_hash(RAnal *a, const char *name, int type, const char *val, int len) {
778 	r_return_val_if_fail (a && name && type && val && len > 0, false);
779 	if (type != R_SIGN_BBHASH) {
780 		eprintf ("error: hash type unknown");
781 		return false;
782 	}
783 	int digestsize = r_hash_size (R_ZIGN_HASH) * 2;
784 	if (len != digestsize) {
785 		eprintf ("error: invalid hash size: %d (%s digest size is %d)\n", len, ZIGN_HASH, digestsize);
786 		return false;
787 	}
788 	return addHash (a, name, type, val);
789 }
790 
r_sign_add_bb_hash(RAnal * a,RAnalFunction * fcn,const char * name)791 R_API bool r_sign_add_bb_hash(RAnal *a, RAnalFunction *fcn, const char *name) {
792 	r_return_val_if_fail (a && fcn && name, false);
793 	return addBBHash (a, fcn, name);
794 }
795 
r_sign_add_bytes(RAnal * a,const char * name,ut64 size,const ut8 * bytes,const ut8 * mask)796 R_API bool r_sign_add_bytes(RAnal *a, const char *name, ut64 size, const ut8 *bytes, const ut8 *mask) {
797 	r_return_val_if_fail (a && name && size > 0 && bytes && mask, false);
798 	return addBytes (a, name, size, bytes, mask);
799 }
800 
r_sign_add_anal(RAnal * a,const char * name,ut64 size,const ut8 * bytes,ut64 at)801 R_API bool r_sign_add_anal(RAnal *a, const char *name, ut64 size, const ut8 *bytes, ut64 at) {
802 	bool retval = false;
803 	r_return_val_if_fail (a && name && size > 0 && bytes, false);
804 	ut8 *mask = r_anal_mask (a, size, bytes, at);
805 	if (mask) {
806 		retval = addBytes (a, name, size, bytes, mask);
807 		free (mask);
808 	}
809 	return retval;
810 }
811 
r_sign_fcn_graph(RAnalFunction * fcn)812 static RSignGraph *r_sign_fcn_graph(RAnalFunction *fcn) {
813 	r_return_val_if_fail (fcn, false);
814 	RSignGraph *graph = R_NEW0 (RSignGraph);
815 	if (graph) {
816 		graph->cc = r_anal_function_complexity (fcn),
817 		graph->nbbs = r_list_length (fcn->bbs);
818 		graph->edges = r_anal_function_count_edges (fcn, &graph->ebbs);
819 		graph->bbsum = r_anal_function_realsize (fcn);
820 	}
821 	return graph;
822 }
823 
bb_sort_by_addr(const void * x,const void * y)824 static int bb_sort_by_addr(const void *x, const void *y) {
825 	RAnalBlock *a = (RAnalBlock *)x;
826 	RAnalBlock *b = (RAnalBlock *)y;
827 	if (a->addr > b->addr) {
828 		return 1;
829 	}
830 	if (a->addr < b->addr) {
831 		return -1;
832 	}
833 	return 0;
834 }
835 
r_sign_fcn_bytes(RAnal * a,RAnalFunction * fcn)836 static RSignBytes *r_sign_fcn_bytes(RAnal *a, RAnalFunction *fcn) {
837 	r_return_val_if_fail (a && fcn && fcn->bbs && fcn->bbs->head, false);
838 
839 	// get size
840 	RCore *core = a->coreb.core;
841 	int maxsz = a->coreb.cfggeti (core, "zign.maxsz");
842 	r_list_sort (fcn->bbs, &bb_sort_by_addr);
843 	ut64 ea = fcn->addr;
844 	RAnalBlock *bb = (RAnalBlock *)fcn->bbs->tail->data;
845 	int size = R_MIN (bb->addr + bb->size - ea, maxsz);
846 
847 	// alloc space for signature
848 	RSignBytes *sig = R_NEW0 (RSignBytes);
849 	if (!sig) {
850 		goto bytes_failed;
851 	}
852 	if (!(sig->bytes = malloc (size))) {
853 		goto bytes_failed;
854 	}
855 	if (!(sig->mask = malloc (size))) {
856 		goto bytes_failed;
857 	}
858 	memset (sig->mask, 0, size);
859 	sig->size = size;
860 
861 	// fill in bytes
862 	if (!a->iob.read_at (a->iob.io, ea, sig->bytes, size)) {
863 		eprintf ("error: failed to read at 0x%08" PFMT64x "\n", ea);
864 		goto bytes_failed;
865 	}
866 
867 	ut8 *tmpmask = NULL;
868 	RListIter *iter;
869 	r_list_foreach (fcn->bbs, iter, bb) {
870 		if (bb->addr >= ea) {
871 			size_t delta = bb->addr - ea;
872 			size_t rsize = bb->size;
873 
874 			// bounds check
875 			if (delta > size) {
876 				break;
877 			}
878 			if (size - delta < rsize) {
879 				rsize = size - delta;
880 			}
881 
882 			// get mask for block
883 			if (!(tmpmask = r_anal_mask (a, rsize, sig->bytes + delta, ea))) {
884 				goto bytes_failed;
885 			}
886 			if (rsize > 0) {
887 				memcpy (sig->mask + delta, tmpmask, rsize);
888 			}
889 			free (tmpmask);
890 		}
891 	}
892 
893 	return sig;
894 bytes_failed:
895 	r_sign_bytes_free (sig);
896 	return NULL;
897 }
898 
r_sign_fcn_bbhash(RAnal * a,RAnalFunction * fcn)899 static RSignHash *r_sign_fcn_bbhash(RAnal *a, RAnalFunction *fcn) {
900 	r_return_val_if_fail (a && fcn, NULL);
901 	RSignHash *hash = R_NEW0 (RSignHash);
902 	if (!hash) {
903 		return NULL;
904 	}
905 
906 	char *digest_hex = r_sign_calc_bbhash (a, fcn);
907 	if (!digest_hex) {
908 		free (hash);
909 		return NULL;
910 	}
911 	hash->bbhash = digest_hex;
912 	return hash;
913 }
914 
r_sign_addto_item(RAnal * a,RSignItem * it,RAnalFunction * fcn,RSignType type)915 R_API bool r_sign_addto_item(RAnal *a, RSignItem *it, RAnalFunction *fcn, RSignType type) {
916 	r_return_val_if_fail (a && it && fcn, false);
917 	switch (type) {
918 	case R_SIGN_GRAPH:
919 		return !it->graph && (it->graph = r_sign_fcn_graph (fcn));
920 	case R_SIGN_BYTES:
921 		return !it->bytes && (it->bytes = r_sign_fcn_bytes (a, fcn));
922 	case R_SIGN_XREFS:
923 		return !it->xrefs && (it->xrefs = r_sign_fcn_xrefs (a, fcn));
924 	case R_SIGN_REFS:
925 		return !it->refs && (it->refs = r_sign_fcn_refs (a, fcn));
926 	case R_SIGN_VARS:
927 		return !it->vars && (it->vars = r_sign_fcn_vars (a, fcn));
928 	case R_SIGN_TYPES:
929 		return !it->types && (it->types = r_sign_fcn_types (a, fcn));
930 	case R_SIGN_BBHASH:
931 		return !it->hash && (it->hash = r_sign_fcn_bbhash (a, fcn));
932 	case R_SIGN_OFFSET:
933 		it->addr = fcn->addr;
934 		return true;
935 	case R_SIGN_NAME:
936 		if (!it->realname && it->name) {
937 			if (strcmp (it->name, fcn->name)) {
938 				it->realname = strdup (fcn->name);
939 			}
940 			return true;
941 		}
942 		break;
943 	default:
944 		eprintf ("Error: %s Can not handle type %c\n", __FUNCTION__, type);
945 	}
946 
947 	return false;
948 }
949 
r_sign_add_graph(RAnal * a,const char * name,RSignGraph graph)950 R_API bool r_sign_add_graph(RAnal *a, const char *name, RSignGraph graph) {
951 	r_return_val_if_fail (a && !R_STR_ISEMPTY (name), false);
952 	bool retval = true;
953 	RSignItem *it = r_sign_item_new ();
954 	if (!it) {
955 		return false;
956 	}
957 	it->name = r_str_new (name);
958 	if (!it->name) {
959 		free (it);
960 		return false;
961 	}
962 	it->space = r_spaces_current (&a->zign_spaces);
963 	it->graph = R_NEW0 (RSignGraph);
964 	if (!it->graph) {
965 		free (it->name);
966 		free (it);
967 		return false;
968 	}
969 	*it->graph = graph;
970 	retval = r_sign_add_item (a, it);
971 	r_sign_item_free (it);
972 
973 	return retval;
974 }
975 
r_sign_add_comment(RAnal * a,const char * name,const char * comment)976 R_API bool r_sign_add_comment(RAnal *a, const char *name, const char *comment) {
977 	r_return_val_if_fail (a && name && comment, false);
978 
979 	RSignItem *it = r_sign_item_new ();
980 	if (!it) {
981 		return false;
982 	}
983 	it->name = r_str_new (name);
984 	it->space = r_spaces_current (&a->zign_spaces);
985 	it->comment = strdup (comment);
986 	bool retval = r_sign_add_item (a, it);
987 	r_sign_item_free (it);
988 	return retval;
989 }
990 
r_sign_add_name(RAnal * a,const char * name,const char * realname)991 R_API bool r_sign_add_name(RAnal *a, const char *name, const char *realname) {
992 	r_return_val_if_fail (a && name && realname, false);
993 	RSignItem *it = r_sign_item_new ();
994 	if (it) {
995 		it->name = r_str_new (name);
996 		it->realname = strdup (realname);
997 		it->space = r_spaces_current (&a->zign_spaces);
998 		bool retval = r_sign_add_item (a, it);
999 		r_sign_item_free (it);
1000 		return retval;
1001 	}
1002 	return false;
1003 }
1004 
r_sign_add_addr(RAnal * a,const char * name,ut64 addr)1005 R_API bool r_sign_add_addr(RAnal *a, const char *name, ut64 addr) {
1006 	r_return_val_if_fail (a && name && addr != UT64_MAX, false);
1007 
1008 	RSignItem *it = r_sign_item_new ();
1009 	if (!it) {
1010 		return NULL;
1011 	}
1012 	it->name = r_str_new (name);
1013 	it->space = r_spaces_current (&a->zign_spaces);
1014 	it->addr = addr;
1015 
1016 	bool retval = r_sign_add_item (a, it);
1017 
1018 	r_sign_item_free (it);
1019 
1020 	return retval;
1021 }
1022 
r_sign_add_vars(RAnal * a,const char * name,RList * vars)1023 R_API bool r_sign_add_vars(RAnal *a, const char *name, RList *vars) {
1024 	r_return_val_if_fail (a && name && vars, false);
1025 
1026 	RListIter *iter;
1027 	char *var;
1028 
1029 	RSignItem *it = r_sign_item_new ();
1030 	if (!it) {
1031 		return false;
1032 	}
1033 	it->name = r_str_new (name);
1034 	if (!it->name) {
1035 		r_sign_item_free (it);
1036 		return false;
1037 	}
1038 	it->space = r_spaces_current (&a->zign_spaces);
1039 	it->vars = r_list_newf ((RListFree)free);
1040 	r_list_foreach (vars, iter, var) {
1041 		r_list_append (it->vars, strdup (var));
1042 	}
1043 	bool retval = r_sign_add_item (a, it);
1044 	r_sign_item_free (it);
1045 
1046 	return retval;
1047 }
1048 
r_sign_add_types(RAnal * a,const char * name,RList * types)1049 R_API bool r_sign_add_types(RAnal *a, const char *name, RList *types) {
1050 	r_return_val_if_fail (a && name && types, false);
1051 
1052 	RListIter *iter;
1053 	char *type;
1054 
1055 	RSignItem *it = r_sign_item_new ();
1056 	if (!it) {
1057 		return false;
1058 	}
1059 	it->name = r_str_new (name);
1060 	if (!it->name) {
1061 		r_sign_item_free (it);
1062 		return false;
1063 	}
1064 	it->space = r_spaces_current (&a->zign_spaces);
1065 	it->types = r_list_newf ((RListFree) free);
1066 	r_list_foreach (types, iter, type) {
1067 		r_list_append (it->types, strdup (type));
1068 	}
1069 	bool retval = r_sign_add_item (a, it);
1070 	r_sign_item_free (it);
1071 
1072 	return retval;
1073 }
1074 
r_sign_add_refs(RAnal * a,const char * name,RList * refs)1075 R_API bool r_sign_add_refs(RAnal *a, const char *name, RList *refs) {
1076 	r_return_val_if_fail (a && name && refs, false);
1077 
1078 	char *ref;
1079 	RListIter *iter;
1080 	RSignItem *it = r_sign_item_new ();
1081 	if (!it) {
1082 		return false;
1083 	}
1084 	it->name = r_str_new (name);
1085 	if (!it->name) {
1086 		free (it);
1087 		return false;
1088 	}
1089 	it->space = r_spaces_current (&a->zign_spaces);
1090 	it->refs = r_list_newf ((RListFree) free);
1091 	r_list_foreach (refs, iter, ref) {
1092 		r_list_append (it->refs, strdup (ref));
1093 	}
1094 	bool retval = r_sign_add_item (a, it);
1095 	r_sign_item_free (it);
1096 
1097 	return retval;
1098 }
1099 
r_sign_add_xrefs(RAnal * a,const char * name,RList * xrefs)1100 R_API bool r_sign_add_xrefs(RAnal *a, const char *name, RList *xrefs) {
1101 	r_return_val_if_fail (a && name && xrefs, false);
1102 
1103 	RListIter *iter = NULL;
1104 	char *ref = NULL;
1105 	RSignItem *it = r_sign_item_new ();
1106 	if (!it) {
1107 		return false;
1108 	}
1109 	it->name = r_str_new (name);
1110 	if (!it->name) {
1111 		free (it);
1112 		return false;
1113 	}
1114 	it->space = r_spaces_current (&a->zign_spaces);
1115 	it->xrefs = r_list_newf ((RListFree) free);
1116 	r_list_foreach (xrefs, iter, ref) {
1117 		r_list_append (it->xrefs, strdup (ref));
1118 	}
1119 	bool retval = r_sign_add_item (a, it);
1120 	r_sign_item_free (it);
1121 
1122 	return retval;
1123 }
1124 
1125 struct ctxDeleteCB {
1126 	RAnal *anal;
1127 	char buf[R_SIGN_KEY_MAXSZ];
1128 };
1129 
deleteBySpaceCB(void * user,const char * k,const char * v)1130 static bool deleteBySpaceCB(void *user, const char *k, const char *v) {
1131 	struct ctxDeleteCB *ctx = (struct ctxDeleteCB *) user;
1132 	if (!strncmp (k, ctx->buf, strlen (ctx->buf))) {
1133 		sdb_remove (ctx->anal->sdb_zigns, k, 0);
1134 	}
1135 	return true;
1136 }
1137 
r_sign_delete(RAnal * a,const char * name)1138 R_API bool r_sign_delete(RAnal *a, const char *name) {
1139 	struct ctxDeleteCB ctx = {0};
1140 	char k[R_SIGN_KEY_MAXSZ];
1141 
1142 	if (!a || !name) {
1143 		return false;
1144 	}
1145 	// Remove all zigns
1146 	if (*name == '*') {
1147 		if (!r_spaces_current (&a->zign_spaces)) {
1148 			sdb_reset (a->sdb_zigns);
1149 			return true;
1150 		}
1151 		ctx.anal = a;
1152 		serializeKey (a, r_spaces_current (&a->zign_spaces), "", ctx.buf);
1153 		sdb_foreach (a->sdb_zigns, deleteBySpaceCB, &ctx);
1154 		return true;
1155 	}
1156 	// Remove specific zign
1157 	serializeKey (a, r_spaces_current (&a->zign_spaces), name, k);
1158 	return sdb_remove (a->sdb_zigns, k, 0);
1159 }
1160 
build_combined_bytes(RSignBytes * bsig)1161 static ut8 * build_combined_bytes(RSignBytes *bsig) {
1162 	r_return_val_if_fail (bsig && bsig->bytes && bsig->mask, NULL);
1163 	ut8 *buf = (ut8 *)malloc (bsig->size);
1164 	if (buf) {
1165 		size_t i;
1166 		for (i = 0; i < bsig->size; i++) {
1167 			buf[i] = bsig->bytes[i] & bsig->mask[i];
1168 		}
1169 	}
1170 	return buf;
1171 }
1172 
cmp_bytesig_to_buff(RSignBytes * sig,ut8 * buf,int len)1173 static double cmp_bytesig_to_buff(RSignBytes *sig, ut8 *buf, int len) {
1174 	r_return_val_if_fail (sig && buf && len >= 0, (double)-1.0);
1175 	ut8 *sigbuf = build_combined_bytes (sig);
1176 	double sim = -1.0;
1177 	if (sigbuf) {
1178 		r_diff_buffers_distance (NULL, sigbuf, sig->size, buf, len, NULL, &sim);
1179 		free (sigbuf);
1180 	}
1181 	return sim;
1182 }
1183 
matchBytes(RSignItem * a,RSignItem * b)1184 static double matchBytes(RSignItem *a, RSignItem *b) {
1185 	double result = 0.0;
1186 
1187 	if (!a->bytes || !b->bytes) {
1188 		return result;
1189 	}
1190 
1191 	size_t min_size = R_MIN ((size_t)a->bytes->size, (size_t)b->bytes->size);
1192 	if (!min_size) {
1193 		return result;
1194 	}
1195 
1196 	ut8 *combined_mask = NULL;
1197 	if (a->bytes->mask || b->bytes->mask) {
1198 		combined_mask = (ut8*)malloc (min_size);
1199 		if (!combined_mask) {
1200 			return result;
1201 		}
1202 		memcpy (combined_mask, a->bytes->mask, min_size);
1203 		if (b->bytes->mask) {
1204 			int i;
1205 			for (i = 0; i != min_size; i++) {
1206 				combined_mask[i] &= b->bytes->mask[i];
1207 			}
1208 		}
1209 	}
1210 
1211 	if ((combined_mask && !r_mem_cmp_mask (a->bytes->bytes, b->bytes->bytes, combined_mask, min_size)) ||
1212 		(!combined_mask && !memcmp (a->bytes->bytes, b->bytes->bytes, min_size))) {
1213 		result = (double)min_size / (double)R_MAX (a->bytes->size, b->bytes->size);
1214 	}
1215 
1216 	free (combined_mask);
1217 
1218 	return result;
1219 }
1220 
1221 #define SIMILARITY(a, b) \
1222 	((a) == (b)? 1.0: (R_MAX ((a), (b)) == 0.0? 0.0: (double)R_MIN ((a), (b)) / (double)R_MAX ((a), (b))))
1223 
matchGraph(RSignItem * a,RSignItem * b)1224 static double matchGraph(RSignItem *a, RSignItem *b) {
1225 	if (!a->graph || !b->graph) {
1226 		return 0.0;
1227 	}
1228 
1229 	double total = 0.0;
1230 
1231 	total += SIMILARITY (a->graph->cc, b->graph->cc);
1232 	total += SIMILARITY (a->graph->nbbs, b->graph->nbbs);
1233 	total += SIMILARITY (a->graph->ebbs, b->graph->ebbs);
1234 	total += SIMILARITY (a->graph->edges, b->graph->edges);
1235 	total += SIMILARITY (a->graph->bbsum, b->graph->bbsum);
1236 
1237 	return total / 5.0;
1238 }
1239 
score_cmpr(const void * a,const void * b)1240 static int score_cmpr(const void *a, const void *b) {
1241 	double sa = ((RSignCloseMatch *)a)->score;
1242 	double sb = ((RSignCloseMatch *)b)->score;
1243 
1244 	if (sa < sb) {
1245 		return 1;
1246 	}
1247 	if (sa > sb) {
1248 		return -1;
1249 	}
1250 	return 0;
1251 }
1252 
1253 typedef struct {
1254 	RSignItem *test;
1255 	RList *output;
1256 	size_t count;
1257 	double score_threshold;
1258 	ut8 *bytes_combined;
1259 
1260 	// greatest lower bound. Thanks lattice theory for helping name variables
1261 	double infimum;
1262 } ClosestMatchData;
1263 
closest_match_update(ClosestMatchData * data,RSignItem * it)1264 static bool closest_match_update(ClosestMatchData *data, RSignItem *it) {
1265 	// quantify how close the signature matches
1266 	int div = 0;
1267 	double score = 0.0;
1268 	double gscore = -1.0;
1269 	if (it->graph && data->test->graph) {
1270 		gscore = matchGraph (it, data->test);
1271 		score += gscore;
1272 		div++;
1273 	}
1274 	double bscore = -1.0;
1275 	bool list_full = (r_list_length (data->output) == data->count);
1276 
1277 	// value to beat to enter the list
1278 	double pivot = data->score_threshold;
1279 	if (list_full) {
1280 		pivot = R_MAX (pivot, data->infimum);
1281 	}
1282 
1283 	if (it->bytes && data->bytes_combined) {
1284 		int sizea = it->bytes->size;
1285 		int sizeb = data->test->bytes->size;
1286 		if (pivot > 0.0) {
1287 			// bytes distance is slow. To avoid it, we can do quick maths to
1288 			// see if the highest possible score would be good enough to change
1289 			// results
1290 			double maxscore = R_MIN (sizea, sizeb) / R_MAX (sizea, sizeb);
1291 			if (div > 0) {
1292 				maxscore = (maxscore + score) / div;
1293 			}
1294 			if (maxscore < pivot) {
1295 				r_sign_item_free (it);
1296 				return true;
1297 			}
1298 		}
1299 
1300 		// get true byte score
1301 		bscore = cmp_bytesig_to_buff (it->bytes, data->bytes_combined, sizeb);
1302 		score += bscore;
1303 		div++;
1304 	}
1305 	if (div == 0) {
1306 		r_sign_item_free (it);
1307 		return true;
1308 	}
1309 	score /= div;
1310 
1311 	// score is too low, don't bother doing any more work
1312 	if (score < pivot) {
1313 		r_sign_item_free (it);
1314 		return true;
1315 	}
1316 
1317 	// add new element
1318 	RSignCloseMatch *row = R_NEW (RSignCloseMatch);
1319 	if (!row) {
1320 		r_sign_item_free (it);
1321 		return false;
1322 	}
1323 	row->score = score;
1324 	row->gscore = gscore;
1325 	row->bscore = bscore;
1326 	row->item = it;
1327 	r_list_add_sorted (data->output, (void *)row, &score_cmpr);
1328 
1329 	if (list_full) {
1330 		// remove smallest element
1331 		r_sign_close_match_free (r_list_pop (data->output));
1332 
1333 		// get new infimum
1334 		row = r_list_get_top (data->output);
1335 		data->infimum = row->score;
1336 	}
1337 	return true;
1338 }
1339 
closest_match_callback(void * a,const char * name,const char * value)1340 static bool closest_match_callback(void *a, const char *name, const char *value) {
1341 	ClosestMatchData *data = (ClosestMatchData *)a;
1342 
1343 	// get signature in usable format
1344 	RSignItem *it = r_sign_item_new ();
1345 	if (!it) {
1346 		return false;
1347 	}
1348 	if (!r_sign_deserialize (a, it, name, value)) {
1349 		r_sign_item_free (it);
1350 		return false;
1351 	}
1352 
1353 	return closest_match_update (data, it);
1354 }
1355 
r_sign_close_match_free(RSignCloseMatch * match)1356 R_API void r_sign_close_match_free(RSignCloseMatch *match) {
1357 	if (match) {
1358 		r_sign_item_free (match->item);
1359 		free (match);
1360 	}
1361 }
1362 
r_sign_find_closest_sig(RAnal * a,RSignItem * it,int count,double score_threshold)1363 R_API RList *r_sign_find_closest_sig(RAnal *a, RSignItem *it, int count, double score_threshold) {
1364 	r_return_val_if_fail (a && it && count > 0 && score_threshold >= 0 && score_threshold <= 1, NULL);
1365 
1366 	// need at least one acceptable signature type
1367 	r_return_val_if_fail (it->bytes || it->graph, NULL);
1368 
1369 	ClosestMatchData data;
1370 	RList *output = r_list_newf ((RListFree)r_sign_close_match_free);
1371 	if (!output) {
1372 		return NULL;
1373 	}
1374 
1375 	data.output = output;
1376 	data.count = count;
1377 	data.score_threshold = score_threshold;
1378 	data.infimum = 0.0;
1379 	data.test = it;
1380 	if (it->bytes) {
1381 		data.bytes_combined = build_combined_bytes (it->bytes);
1382 	} else {
1383 		data.bytes_combined = NULL;
1384 	}
1385 
1386 	// TODO: handle sign spaces
1387 	if (!sdb_foreach (a->sdb_zigns, &closest_match_callback, (void *)&data)) {
1388 		r_list_free (output);
1389 		output = NULL;
1390 	}
1391 
1392 	free (data.bytes_combined);
1393 	return output;
1394 }
1395 
r_sign_find_closest_fcn(RAnal * a,RSignItem * it,int count,double score_threshold)1396 R_API RList *r_sign_find_closest_fcn(RAnal *a, RSignItem *it, int count, double score_threshold) {
1397 	r_return_val_if_fail (a && it && count > 0 && score_threshold >= 0 && score_threshold <= 1, NULL);
1398 	r_return_val_if_fail (it->bytes || it->graph, NULL);
1399 
1400 	RList *output = r_list_newf ((RListFree)r_sign_close_match_free);
1401 	if (!output) {
1402 		return NULL;
1403 	}
1404 
1405 	ClosestMatchData data;
1406 	data.output = output;
1407 	data.count = count;
1408 	data.score_threshold = score_threshold;
1409 	data.infimum = 0.0;
1410 	data.test = it;
1411 	if (it->bytes) {
1412 		data.bytes_combined = build_combined_bytes (it->bytes);
1413 	} else {
1414 		data.bytes_combined = NULL;
1415 	}
1416 
1417 	RAnalFunction *fcn;
1418 	RListIter *iter;
1419 	r_list_foreach (a->fcns, iter, fcn) {
1420 		// turn function into signature item
1421 		RSignItem *fsig = r_sign_item_new ();
1422 		if (!fsig) {
1423 			r_list_free (output);
1424 			return NULL;
1425 		}
1426 		if (data.bytes_combined) {
1427 			r_sign_addto_item (a, fsig, fcn, R_SIGN_BYTES);
1428 		}
1429 		if (it->graph) {
1430 			r_sign_addto_item (a, fsig, fcn, R_SIGN_GRAPH);
1431 		}
1432 		r_sign_addto_item (a, fsig, fcn, R_SIGN_OFFSET);
1433 		fsig->name = r_str_new (fcn->name);
1434 
1435 		// maybe add signature item to output list
1436 		closest_match_update (&data, fsig);
1437 	}
1438 	free (data.bytes_combined);
1439 	return output;
1440 }
1441 
r_sign_diff(RAnal * a,RSignOptions * options,const char * other_space_name)1442 R_API bool r_sign_diff(RAnal *a, RSignOptions *options, const char *other_space_name) {
1443 	r_return_val_if_fail (a && other_space_name, false);
1444 
1445 	RSpace *current_space = r_spaces_current (&a->zign_spaces);
1446 	if (!current_space) {
1447 		return false;
1448 	}
1449 	RSpace *other_space = r_spaces_get (&a->zign_spaces, other_space_name);
1450 	if (!other_space) {
1451 		return false;
1452 	}
1453 
1454 	RList *la = deserialize_sign_space (a, current_space);
1455 	if (!la) {
1456 		return false;
1457 	}
1458 	RList *lb = deserialize_sign_space (a, other_space);
1459 	if (!lb) {
1460 		r_list_free (la);
1461 		return false;
1462 	}
1463 
1464 	eprintf ("Diff %d %d\n", (int)ls_length (la), (int)ls_length (lb));
1465 
1466 	RListIter *itr;
1467 	RListIter *itr2;
1468 	RSignItem *si;
1469 	RSignItem *si2;
1470 
1471 	// do the sign diff here
1472 	r_list_foreach (la, itr, si) {
1473 		if (strstr (si->name, "imp.")) {
1474 			continue;
1475 		}
1476 		r_list_foreach (lb, itr2, si2) {
1477 			if (strstr (si2->name, "imp.")) {
1478 				continue;
1479 			}
1480 			double bytesScore = matchBytes (si, si2);
1481 			double graphScore = matchGraph (si, si2);
1482 			bool bytesMatch = bytesScore >= (options ? options->bytes_diff_threshold : SIGN_DIFF_MATCH_BYTES_THRESHOLD);
1483 			bool graphMatch = graphScore >= (options ? options->graph_diff_threshold : SIGN_DIFF_MATCH_GRAPH_THRESHOLD);
1484 
1485 			if (bytesMatch) {
1486 				a->cb_printf ("0x%08" PFMT64x " 0x%08"PFMT64x " %02.5lf B %s\n", si->addr, si2->addr, bytesScore, si->name);
1487 			}
1488 
1489 			if (graphMatch) {
1490 				a->cb_printf ("0x%08" PFMT64x " 0x%08"PFMT64x" %02.5lf G %s\n", si->addr, si2->addr, graphScore, si->name);
1491 			}
1492 		}
1493 	}
1494 
1495 	r_list_free (la);
1496 	r_list_free (lb);
1497 	return true;
1498 }
1499 
r_sign_diff_by_name(RAnal * a,RSignOptions * options,const char * other_space_name,bool not_matching)1500 R_API bool r_sign_diff_by_name(RAnal *a, RSignOptions *options, const char *other_space_name, bool not_matching) {
1501 	r_return_val_if_fail (a && other_space_name, false);
1502 
1503 	RSpace *current_space = r_spaces_current (&a->zign_spaces);
1504 	if (!current_space) {
1505 		return false;
1506 	}
1507 	RSpace *other_space = r_spaces_get (&a->zign_spaces, other_space_name);
1508 	if (!other_space) {
1509 		return false;
1510 	}
1511 
1512 	RList *la = deserialize_sign_space (a, current_space);
1513 	if (!la) {
1514 		return false;
1515 	}
1516 	RList *lb = deserialize_sign_space (a, other_space);
1517 	if (!lb) {
1518 		return false;
1519 	}
1520 
1521 	eprintf ("Diff by name %d %d (%s)\n", (int)ls_length (la), (int)ls_length (lb), not_matching? "not matching" : "matching");
1522 
1523 	RListIter *itr;
1524 	RListIter *itr2;
1525 	RSignItem *si;
1526 	RSignItem *si2;
1527 	size_t current_space_name_len = strlen (current_space->name);
1528 	size_t other_space_name_len = strlen (other_space->name);
1529 
1530 	r_list_foreach (la, itr, si) {
1531 		if (strstr (si->name, "imp.")) {
1532 			continue;
1533 		}
1534 		r_list_foreach (lb, itr2, si2) {
1535 			if (strcmp (si->name + current_space_name_len + 1, si2->name + other_space_name_len + 1)) {
1536 				continue;
1537 			}
1538 			// TODO: add config variable for threshold
1539 			double bytesScore = matchBytes (si, si2);
1540 			double graphScore = matchGraph (si, si2);
1541 			bool bytesMatch = bytesScore >= (options ? options->bytes_diff_threshold : SIGN_DIFF_MATCH_BYTES_THRESHOLD);
1542 			bool graphMatch = graphScore >= (options ? options->graph_diff_threshold : SIGN_DIFF_MATCH_GRAPH_THRESHOLD);
1543 			if ((bytesMatch && !not_matching) || (!bytesMatch && not_matching)) {
1544 				a->cb_printf ("0x%08"PFMT64x" 0x%08"PFMT64x" %02.5f B %s\n", si->addr, si2->addr, bytesScore, si->name);
1545 			}
1546 			if ((graphMatch && !not_matching) || (!graphMatch && not_matching)) {
1547 				a->cb_printf ("0x%08"PFMT64x" 0x%08"PFMT64x" %02.5f G %s\n", si->addr, si2->addr, graphScore, si->name);
1548 			}
1549 		}
1550 	}
1551 
1552 	r_list_free (la);
1553 	r_list_free (lb);
1554 
1555 	return true;
1556 }
1557 
1558 struct ctxListCB {
1559 	RAnal *anal;
1560 	int idx;
1561 	int format;
1562 	PJ *pj;
1563 };
1564 
1565 struct ctxGetListCB {
1566 	RAnal *anal;
1567 	RList *list;
1568 };
1569 
listBytes(RAnal * a,RSignItem * it,PJ * pj,int format)1570 static void listBytes(RAnal *a, RSignItem *it, PJ *pj, int format) {
1571 	RSignBytes *bytes = it->bytes;
1572 
1573 	if (!bytes->bytes) {
1574 		return;
1575 	}
1576 
1577 	int masked = 0, i = 0;
1578 	for (i = 0; i < bytes->size; i++) {
1579 		masked += bytes->mask[i] == 0xff;
1580 	}
1581 
1582 	char * strbytes = r_hex_bin2strdup (bytes->bytes, bytes->size);
1583 	if (!strbytes) {
1584 		return;
1585 	}
1586 	char * strmask = r_hex_bin2strdup (bytes->mask, bytes->size);
1587 	if (!strmask) {
1588 		free (strbytes);
1589 		return;
1590 	}
1591 
1592 	if (format == '*') {
1593 		if (masked == bytes->size) {
1594 			a->cb_printf ("za %s b %s\n", it->name, strbytes);
1595 		} else {
1596 			a->cb_printf ("za %s b %s:%s\n", it->name, strbytes, strmask);
1597 		}
1598 	} else if (format == 'q') {
1599 		a->cb_printf (" b(%d/%d)", masked, bytes->size);
1600 	} else if (format == 'j') {
1601 		pj_ks (pj, "bytes", strbytes);
1602 		pj_ks (pj, "mask", strmask);
1603 	} else {
1604 		a->cb_printf ("  bytes: %s\n", strbytes);
1605 		a->cb_printf ("  mask: %s\n", strmask);
1606 	}
1607 
1608 	free (strbytes);
1609 	free (strmask);
1610 }
1611 
listGraph(RAnal * a,RSignItem * it,PJ * pj,int format)1612 static void listGraph(RAnal *a, RSignItem *it, PJ *pj, int format) {
1613 	RSignGraph *graph = it->graph;
1614 
1615 	if (format == 'q') {
1616 		a->cb_printf (" g(cc=%d,nb=%d,e=%d,eb=%d,h=%d)",
1617 			graph->cc, graph->nbbs, graph->edges, graph->ebbs, graph->bbsum);
1618 	} else if (format == '*') {
1619 		a->cb_printf ("za %s g cc=%d nbbs=%d edges=%d ebbs=%d bbsum=%d\n",
1620 			it->name, graph->cc, graph->nbbs, graph->edges, graph->ebbs, graph->bbsum);
1621 	} else if (format == 'j') {
1622 		pj_ko (pj, "graph");
1623 		pj_kN (pj, "cc", graph->cc);
1624 		pj_kN (pj, "nbbs", graph->nbbs);
1625 		pj_kN (pj, "edges", graph->edges);
1626 		pj_kN (pj, "ebbs", graph->ebbs);
1627 		pj_kN (pj, "bbsum", graph->bbsum);
1628 		pj_end (pj);
1629 	} else {
1630 		a->cb_printf ("  graph: cc=%d nbbs=%d edges=%d ebbs=%d bbsum=%d\n",
1631 			graph->cc, graph->nbbs, graph->edges, graph->ebbs, graph->bbsum);
1632 	}
1633 }
1634 
listComment(RAnal * a,RSignItem * it,PJ * pj,int format)1635 static void listComment(RAnal *a, RSignItem *it, PJ *pj, int format) {
1636 	if (it->comment) {
1637 		if (format == 'q') {
1638 			//	a->cb_printf (" addr(0x%08"PFMT64x")", it->addr);
1639 			a->cb_printf ("\n ; %s\n", it->comment);
1640 		} else if (format == '*') {
1641 			a->cb_printf ("%s\n", it->comment); // comment injection via CCu..
1642 		} else if (format == 'j') {
1643 			pj_ks (pj, "comments", it->comment);
1644 		} else {
1645 			a->cb_printf ("  comment: 0x%08" PFMT64x "\n", it->addr);
1646 		}
1647 	}
1648 }
1649 
listRealname(RAnal * a,RSignItem * it,PJ * pj,int format)1650 static void listRealname(RAnal *a, RSignItem *it, PJ *pj, int format) {
1651 	if (it->realname) {
1652 		if (format == 'q') {
1653 			//	a->cb_printf (" addr(0x%08"PFMT64x")", it->addr);
1654 		} else if (format == '*') {
1655 			a->cb_printf ("za %s n %s\n", it->name, it->realname);
1656 			a->cb_printf ("afn %s @ 0x%08"PFMT64x"\n", it->realname, it->addr);
1657 		} else if (format == 'j') {
1658 			pj_ks (pj, "realname", it->realname);
1659 		} else {
1660 			a->cb_printf ("  realname: %s\n", it->realname);
1661 		}
1662 	}
1663 }
1664 
listOffset(RAnal * a,RSignItem * it,PJ * pj,int format)1665 static void listOffset(RAnal *a, RSignItem *it, PJ *pj, int format) {
1666 	if (format == 'q') {
1667 		//	a->cb_printf (" addr(0x%08"PFMT64x")", it->addr);
1668 	} else if (format == '*') {
1669 		a->cb_printf ("za %s o 0x%08"PFMT64x"\n", it->name, it->addr);
1670 	} else if (format == 'j') {
1671 		pj_kN (pj, "addr", it->addr);
1672 	} else {
1673 		a->cb_printf ("  addr: 0x%08"PFMT64x"\n", it->addr);
1674 	}
1675 }
1676 
listVars(RAnal * a,RSignItem * it,PJ * pj,int format)1677 static void listVars(RAnal *a, RSignItem *it, PJ *pj, int format) {
1678 	RListIter *iter = NULL;
1679 	char *var = NULL;
1680 	int i = 0;
1681 
1682 	if (format == '*') {
1683 		a->cb_printf ("za %s v ", it->name);
1684 	} else if (format == 'q') {
1685 		a->cb_printf (" vars(%d)", r_list_length (it->vars));
1686 		return;
1687 	} else if (format == 'j') {
1688 		pj_ka (pj, "vars");
1689 	} else {
1690 		a->cb_printf ("  vars: ");
1691 	}
1692 
1693 	r_list_foreach (it->vars, iter, var) {
1694 		if (i > 0) {
1695 			if (format == '*') {
1696 				a->cb_printf (" ");
1697 			} else if (format != 'j') {
1698 				a->cb_printf (", ");
1699 			}
1700 		}
1701 		if (format == 'j') {
1702 			pj_s (pj, var);
1703 		} else {
1704 			a->cb_printf ("%s", var);
1705 		}
1706 		i++;
1707 	}
1708 
1709 	if (format == 'j') {
1710 		pj_end (pj);
1711 	} else {
1712 		a->cb_printf ("\n");
1713 	}
1714 }
1715 
print_list_type_header(RAnal * a,RSignItem * it,PJ * pj,int format)1716 static void print_list_type_header(RAnal *a, RSignItem *it, PJ *pj, int format) {
1717 	if (format == '*') {
1718 		a->cb_printf ("za %s t ", it->name);
1719 	} else if (format == 'q') {
1720 		a->cb_printf (" types(%d)", r_list_length (it->types));
1721 		return;
1722 	} else if (format == 'j') {
1723 		pj_ka (pj, "types");
1724 	} else {
1725 		a->cb_printf ("  types: ");
1726 	}
1727 }
1728 
print_function_args_json(RAnal * a,PJ * pj,char * arg_type)1729 static void print_function_args_json(RAnal *a, PJ *pj, char *arg_type) {
1730 	char *arg_name = strchr (arg_type, ',');
1731 
1732 	if (arg_name == NULL) {
1733 		return;
1734 	}
1735 
1736 	*arg_name = '\0';
1737 	++arg_name;
1738 
1739 	size_t len_arg_name = strlen (arg_name);
1740 	arg_name[len_arg_name - 1] = '\0';
1741 
1742 	pj_o (pj);
1743 	pj_ks (pj, "name", arg_name);
1744 	pj_ks (pj, "type", arg_type + 1);
1745 	pj_end (pj);
1746 }
1747 
print_type_json(RAnal * a,char * type,PJ * pj,size_t pos)1748 static void print_type_json(RAnal *a, char *type, PJ *pj, size_t pos) {
1749 	if (pos == 0) {
1750 		return;
1751 	}
1752 
1753 	char *str_type = strchr (type, '=');
1754 
1755 	if (str_type == NULL) {
1756 		return;
1757 	}
1758 
1759 	*str_type = '\0';
1760 	++str_type;
1761 
1762 	print_function_args_json (a, pj, str_type);
1763 }
1764 
print_list_separator(RAnal * a,RSignItem * it,PJ * pj,int format,int pos)1765 static void print_list_separator(RAnal *a, RSignItem *it, PJ *pj, int format, int pos) {
1766 	if (pos == 0 || format == 'j') {
1767 		return;
1768 	}
1769 	if (format == '*') {
1770 		a->cb_printf (" ");
1771 	} else {
1772 		a->cb_printf (", ");
1773 	}
1774 }
1775 
print_list_type_body(RAnal * a,RSignItem * it,PJ * pj,int format)1776 static void print_list_type_body(RAnal *a, RSignItem *it, PJ *pj, int format) {
1777 	int i = 0;
1778 	char *type = NULL;
1779 	RListIter *iter = NULL;
1780 
1781 	r_list_foreach (it->types, iter, type) {
1782 		print_list_separator (a, it, pj, format, i);
1783 
1784 		if (format == 'j') {
1785 			char *t = strdup (type);
1786 			print_type_json (a, t, pj, i);
1787 			free (t);
1788 		} else {
1789 			a->cb_printf ("%s", type);
1790 		}
1791 		i++;
1792 	}
1793 }
1794 
listTypes(RAnal * a,RSignItem * it,PJ * pj,int format)1795 static void listTypes(RAnal *a, RSignItem *it, PJ *pj, int format) {
1796 	print_list_type_header (a, it, pj, format);
1797 	print_list_type_body (a, it, pj, format);
1798 
1799 	if (format == 'j') {
1800 		pj_end (pj);
1801 	} else {
1802 		a->cb_printf ("\n");
1803 	}
1804 }
1805 
listXRefs(RAnal * a,RSignItem * it,PJ * pj,int format)1806 static void listXRefs(RAnal *a, RSignItem *it, PJ *pj, int format) {
1807 	RListIter *iter = NULL;
1808 	char *ref = NULL;
1809 	int i = 0;
1810 
1811 	if (format == '*') {
1812 		a->cb_printf ("za %s x ", it->name);
1813 	} else if (format == 'q') {
1814 		a->cb_printf (" xrefs(%d)", r_list_length (it->xrefs));
1815 		return;
1816 	} else if (format == 'j') {
1817 		pj_ka (pj, "xrefs");
1818 	} else {
1819 		if (it->xrefs && !r_list_empty (it->xrefs)) {
1820 			a->cb_printf ("  xrefs: ");
1821 		}
1822 	}
1823 
1824 	r_list_foreach (it->xrefs, iter, ref) {
1825 		if (i > 0) {
1826 			if (format == '*') {
1827 				a->cb_printf (" ");
1828 			} else if (format != 'j') {
1829 				a->cb_printf (", ");
1830 			}
1831 		}
1832 		if (format == 'j') {
1833 			pj_s (pj, ref);
1834 		} else {
1835 			a->cb_printf ("%s", ref);
1836 		}
1837 		i++;
1838 	}
1839 
1840 	if (format == 'j') {
1841 		pj_end (pj);
1842 	} else {
1843 		a->cb_printf ("\n");
1844 	}
1845 }
1846 
listRefs(RAnal * a,RSignItem * it,PJ * pj,int format)1847 static void listRefs(RAnal *a, RSignItem *it, PJ *pj, int format) {
1848 	RListIter *iter = NULL;
1849 	char *ref = NULL;
1850 	int i = 0;
1851 
1852 	if (format == '*') {
1853 		a->cb_printf ("za %s r ", it->name);
1854 	} else if (format == 'q') {
1855 		a->cb_printf (" refs(%d)", r_list_length (it->refs));
1856 		return;
1857 	} else if (format == 'j') {
1858 		pj_ka (pj, "refs");
1859 	} else {
1860 		if (it->refs && !r_list_empty (it->refs)) {
1861 			a->cb_printf ("  refs: ");
1862 		}
1863 	}
1864 
1865 	r_list_foreach (it->refs, iter, ref) {
1866 		if (i > 0) {
1867 			if (format == '*') {
1868 				a->cb_printf (" ");
1869 			} else if (format != 'j') {
1870 				a->cb_printf (", ");
1871 			}
1872 		}
1873 		if (format == 'j') {
1874 			pj_s (pj, ref);
1875 		} else {
1876 			a->cb_printf ("%s", ref);
1877 		}
1878 		i++;
1879 	}
1880 
1881 	if (format == 'j') {
1882 		pj_end (pj);
1883 	} else {
1884 		a->cb_printf ("\n");
1885 	}
1886 }
1887 
listHash(RAnal * a,RSignItem * it,PJ * pj,int format)1888 static void listHash(RAnal *a, RSignItem *it, PJ *pj, int format) {
1889 	if (!it->hash) {
1890 		return;
1891 	}
1892 	switch (format) {
1893 	case 'q':
1894 		if (it->hash->bbhash) {
1895 			a->cb_printf (" h(%08x)", r_str_hash (it->hash->bbhash));
1896 		}
1897 		break;
1898 	case '*':
1899 		if (it->hash->bbhash) {
1900 			a->cb_printf ("za %s h %s\n", it->name, it->hash->bbhash);
1901 		}
1902 		break;
1903 	case 'j':
1904 		pj_ko (pj, "hash");
1905 		if (it->hash->bbhash) {
1906 			pj_ks (pj, "bbhash", it->hash->bbhash);
1907 		}
1908 		pj_end (pj);
1909 		break;
1910 	default:
1911 		if (it->hash->bbhash) {
1912 			a->cb_printf ("  bbhash: %s\n", it->hash->bbhash);
1913 		}
1914 		break;
1915 	}
1916 }
1917 
listCB(void * user,const char * k,const char * v)1918 static bool listCB(void *user, const char *k, const char *v) {
1919 	struct ctxListCB *ctx = (struct ctxListCB *)user;
1920 	RSignItem *it = r_sign_item_new ();
1921 	RAnal *a = ctx->anal;
1922 
1923 	if (!r_sign_deserialize (a, it, k, v)) {
1924 		eprintf ("error: cannot deserialize zign\n");
1925 		goto out;
1926 	}
1927 
1928 	RSpace *cur = r_spaces_current (&a->zign_spaces);
1929 	if (cur != it->space && cur) {
1930 		goto out;
1931 	}
1932 
1933 	// Start item
1934 	if (ctx->format == 'j') {
1935 		pj_o (ctx->pj);
1936 	}
1937 
1938 	// Zignspace and name (except for radare format)
1939 	if (ctx->format == '*') {
1940 		if (it->space) {
1941 			a->cb_printf ("zs %s\n", it->space->name);
1942 		} else {
1943 			a->cb_printf ("zs *\n");
1944 		}
1945 	} else if (ctx->format == 'q') {
1946 		a->cb_printf ("0x%08" PFMT64x " ", it->addr);
1947 		const char *pad = r_str_pad (' ', 30 - strlen (it->name));
1948 		a->cb_printf ("%s:%s", it->name, pad);
1949 	} else if (ctx->format == 'j') {
1950 		if (it->space) {
1951 			pj_ks (ctx->pj, "zignspace", it->space->name);
1952 		}
1953 		pj_ks (ctx->pj, "name", it->name);
1954 	} else {
1955 		if (!r_spaces_current (&a->zign_spaces) && it->space) {
1956 			a->cb_printf ("(%s) ", it->space->name);
1957 		}
1958 		a->cb_printf ("%s:\n", it->name);
1959 	}
1960 
1961 	// Bytes pattern
1962 	if (it->bytes) {
1963 		listBytes (a, it, ctx->pj, ctx->format);
1964 	} else if (ctx->format == 'j') {
1965 		pj_ks (ctx->pj, "bytes", "");
1966 	}
1967 
1968 	// Graph metrics
1969 	if (it->graph) {
1970 		listGraph (a, it, ctx->pj, ctx->format);
1971 	} else if (ctx->format == 'j') {
1972 		pj_ko (ctx->pj, "graph");
1973 		pj_end (ctx->pj);
1974 	}
1975 
1976 	// Offset
1977 	if (it->addr != UT64_MAX) {
1978 		listOffset (a, it, ctx->pj, ctx->format);
1979 	} else if (ctx->format == 'j') {
1980 		pj_kN (ctx->pj, "addr", -1);
1981 	}
1982 	// Name
1983 	if (it->realname) {
1984 		listRealname (a, it, ctx->pj, ctx->format);
1985 	}
1986 	if (it->comment) {
1987 		listComment (a, it, ctx->pj, ctx->format);
1988 	}
1989 	// References
1990 	if (it->refs) {
1991 		listRefs (a, it, ctx->pj, ctx->format);
1992 	} else if (ctx->format == 'j') {
1993 		pj_ka (ctx->pj, "refs");
1994 		pj_end (ctx->pj);
1995 	}
1996 	// XReferences
1997 	if (it->xrefs) {
1998 		listXRefs (a, it, ctx->pj, ctx->format);
1999 	} else if (ctx->format == 'j') {
2000 		pj_ka (ctx->pj, "xrefs");
2001 		pj_end (ctx->pj);
2002 	}
2003 	// Vars
2004 	if (it->vars) {
2005 		listVars (a, it, ctx->pj, ctx->format);
2006 	} else if (ctx->format == 'j') {
2007 		pj_ka (ctx->pj, "vars");
2008 		pj_end (ctx->pj);
2009 	}
2010 	if (it->types) {
2011 		listTypes (a, it, ctx->pj, ctx->format);
2012 	} else if (ctx->format == 'j') {
2013 		pj_ka (ctx->pj, "types");
2014 		pj_end (ctx->pj);
2015 	}
2016 	// Hash
2017 	if (it->hash) {
2018 		listHash (a, it, ctx->pj, ctx->format);
2019 	} else if (ctx->format == 'j') {
2020 		pj_ko (ctx->pj, "hash");
2021 		pj_end (ctx->pj);
2022 	}
2023 
2024 	// End item
2025 	if (ctx->format == 'j') {
2026 		pj_end (ctx->pj);
2027 	}
2028 	if (ctx->format == 'q') {
2029 		a->cb_printf ("\n");
2030 	}
2031 
2032 	ctx->idx++;
2033 
2034 out:
2035 	r_sign_item_free (it);
2036 
2037 	return true;
2038 }
2039 
r_sign_list(RAnal * a,int format)2040 R_API void r_sign_list(RAnal *a, int format) {
2041 	r_return_if_fail (a);
2042 	PJ *pj = NULL;
2043 
2044 	if (format == 'j') {
2045 		pj = a->coreb.pjWithEncoding (a->coreb.core);
2046 		pj_a (pj);
2047 	}
2048 
2049 	struct ctxListCB ctx = { a, 0, format, pj };
2050 	sdb_foreach (a->sdb_zigns, listCB, &ctx);
2051 
2052 	if (format == 'j') {
2053 		pj_end (pj);
2054 		a->cb_printf ("%s\n", pj_string (pj));
2055 		pj_free (pj);
2056 	}
2057 }
2058 
listGetCB(void * user,const char * key,const char * val)2059 static bool listGetCB(void *user, const char *key, const char *val) {
2060 	struct ctxGetListCB *ctx = user;
2061 	RSignItem *item = r_sign_item_new ();
2062 	if (!item) {
2063 		return false;
2064 	}
2065 	if (!r_sign_deserialize (ctx->anal, item, key, val)) {
2066 		r_sign_item_free (item);
2067 		return false;
2068 	}
2069 	r_list_append (ctx->list, item);
2070 	return true;
2071 }
2072 
r_sign_get_list(RAnal * a)2073 R_API RList *r_sign_get_list(RAnal *a) {
2074 	r_return_val_if_fail (a, NULL);
2075 	struct ctxGetListCB ctx = { a, r_list_newf ((RListFree)r_sign_item_free) };
2076 	sdb_foreach (a->sdb_zigns, listGetCB, &ctx);
2077 	return ctx.list;
2078 }
2079 
cmpaddr(const void * _a,const void * _b)2080 static int cmpaddr(const void *_a, const void *_b) {
2081 	const RAnalBlock *a = _a, *b = _b;
2082 	return (a->addr - b->addr);
2083 }
2084 
r_sign_calc_bbhash(RAnal * a,RAnalFunction * fcn)2085 R_API char *r_sign_calc_bbhash(RAnal *a, RAnalFunction *fcn) {
2086 	RListIter *iter = NULL;
2087 	RAnalBlock *bbi = NULL;
2088 	char *digest_hex = NULL;
2089 	RHash *ctx = r_hash_new (true, R_ZIGN_HASH);
2090 	if (!ctx) {
2091 		goto beach;
2092 	}
2093 	r_list_sort (fcn->bbs, &cmpaddr);
2094 	r_hash_do_begin (ctx, R_ZIGN_HASH);
2095 	r_list_foreach (fcn->bbs, iter, bbi) {
2096 		ut8 *buf = malloc (bbi->size);
2097 		if (!buf) {
2098 			goto beach;
2099 		}
2100 		if (!a->iob.read_at (a->iob.io, bbi->addr, buf, bbi->size)) {
2101 			goto beach;
2102 		}
2103 		if (!r_hash_do_sha256 (ctx, buf, bbi->size)) {
2104 			goto beach;
2105 		}
2106 		free (buf);
2107 	}
2108 	r_hash_do_end (ctx, R_ZIGN_HASH);
2109 
2110 	digest_hex = r_hex_bin2strdup (ctx->digest, r_hash_size (R_ZIGN_HASH));
2111 beach:
2112 	free (ctx);
2113 	return digest_hex;
2114 }
2115 
2116 struct ctxCountForCB {
2117 	RAnal *anal;
2118 	const RSpace *space;
2119 	int count;
2120 };
2121 
countForCB(void * user,const char * k,const char * v)2122 static bool countForCB(void *user, const char *k, const char *v) {
2123 	struct ctxCountForCB *ctx = (struct ctxCountForCB *) user;
2124 	RSignItem *it = r_sign_item_new ();
2125 
2126 	if (r_sign_deserialize (ctx->anal, it, k, v)) {
2127 		if (it->space == ctx->space) {
2128 			ctx->count++;
2129 		}
2130 	} else {
2131 		eprintf ("error: cannot deserialize zign\n");
2132 	}
2133 	r_sign_item_free (it);
2134 
2135 	return true;
2136 }
2137 
r_sign_space_count_for(RAnal * a,const RSpace * space)2138 R_API int r_sign_space_count_for(RAnal *a, const RSpace *space) {
2139 	struct ctxCountForCB ctx = { a, space, 0 };
2140 	r_return_val_if_fail (a, 0);
2141 	sdb_foreach (a->sdb_zigns, countForCB, &ctx);
2142 	return ctx.count;
2143 }
2144 
2145 struct ctxUnsetForCB {
2146 	RAnal *anal;
2147 	const RSpace *space;
2148 };
2149 
unsetForCB(void * user,const char * k,const char * v)2150 static bool unsetForCB(void *user, const char *k, const char *v) {
2151 	struct ctxUnsetForCB *ctx = (struct ctxUnsetForCB *) user;
2152 	char nk[R_SIGN_KEY_MAXSZ], nv[R_SIGN_VAL_MAXSZ];
2153 	RSignItem *it = r_sign_item_new ();
2154 	Sdb *db = ctx->anal->sdb_zigns;
2155 	if (r_sign_deserialize (ctx->anal, it, k, v)) {
2156 		if (it->space && it->space == ctx->space) {
2157 			it->space = NULL;
2158 			serialize (ctx->anal, it, nk, nv);
2159 			sdb_remove (db, k, 0);
2160 			sdb_set (db, nk, nv, 0);
2161 		}
2162 	} else {
2163 		eprintf ("error: cannot deserialize zign\n");
2164 	}
2165 	r_sign_item_free (it);
2166 	return true;
2167 }
2168 
r_sign_space_unset_for(RAnal * a,const RSpace * space)2169 R_API void r_sign_space_unset_for(RAnal *a, const RSpace *space) {
2170 	r_return_if_fail (a);
2171 	struct ctxUnsetForCB ctx = { a, space };
2172 	sdb_foreach (a->sdb_zigns, unsetForCB, &ctx);
2173 }
2174 
2175 struct ctxRenameForCB {
2176 	RAnal *anal;
2177 	char oprefix[R_SIGN_KEY_MAXSZ];
2178 	char nprefix[R_SIGN_KEY_MAXSZ];
2179 };
2180 
renameForCB(void * user,const char * k,const char * v)2181 static bool renameForCB(void *user, const char *k, const char *v) {
2182 	struct ctxRenameForCB *ctx = (struct ctxRenameForCB *) user;
2183 	char nk[R_SIGN_KEY_MAXSZ], nv[R_SIGN_VAL_MAXSZ];
2184 	const char *zigname = NULL;
2185 	Sdb *db = ctx->anal->sdb_zigns;
2186 
2187 	if (!strncmp (k, ctx->oprefix, strlen (ctx->oprefix))) {
2188 		zigname = k + strlen (ctx->oprefix);
2189 		snprintf (nk, R_SIGN_KEY_MAXSZ, "%s%s", ctx->nprefix, zigname);
2190 		snprintf (nv, R_SIGN_VAL_MAXSZ, "%s", v);
2191 		sdb_remove (db, k, 0);
2192 		sdb_set (db, nk, nv, 0);
2193 	}
2194 	return true;
2195 }
2196 
r_sign_space_rename_for(RAnal * a,const RSpace * space,const char * oname,const char * nname)2197 R_API void r_sign_space_rename_for(RAnal *a, const RSpace *space, const char *oname, const char *nname) {
2198 	r_return_if_fail (a && space && oname && nname);
2199 	struct ctxRenameForCB ctx = {.anal = a};
2200 	serializeKeySpaceStr (a, oname, "", ctx.oprefix);
2201 	serializeKeySpaceStr (a, nname, "", ctx.nprefix);
2202 	sdb_foreach (a->sdb_zigns, renameForCB, &ctx);
2203 }
2204 
2205 struct ctxForeachCB {
2206 	RAnal *anal;
2207 	RSignForeachCallback cb;
2208 	bool freeit;
2209 	void *user;
2210 };
2211 
foreachCB(void * user,const char * k,const char * v)2212 static bool foreachCB(void *user, const char *k, const char *v) {
2213 	struct ctxForeachCB *ctx = (struct ctxForeachCB *) user;
2214 	RSignItem *it = r_sign_item_new ();
2215 	RAnal *a = ctx->anal;
2216 
2217 	if (r_sign_deserialize (a, it, k, v)) {
2218 		RSpace *cur = r_spaces_current (&a->zign_spaces);
2219 		if (ctx->cb && cur == it->space) {
2220 			ctx->cb (it, ctx->user);
2221 		}
2222 	} else {
2223 		eprintf ("error: cannot deserialize zign\n");
2224 	}
2225 	if (ctx->freeit) {
2226 		r_sign_item_free (it);
2227 	}
2228 	return true;
2229 }
2230 
r_sign_foreach_nofree(RAnal * a,RSignForeachCallback cb,void * user)2231 static bool r_sign_foreach_nofree(RAnal *a, RSignForeachCallback cb, void *user) {
2232 	r_return_val_if_fail (a && cb, false);
2233 	struct ctxForeachCB ctx = { a, cb, false, user };
2234 	return sdb_foreach (a->sdb_zigns, foreachCB, &ctx);
2235 }
2236 
r_sign_foreach(RAnal * a,RSignForeachCallback cb,void * user)2237 R_API bool r_sign_foreach(RAnal *a, RSignForeachCallback cb, void *user) {
2238 	r_return_val_if_fail (a && cb, false);
2239 	struct ctxForeachCB ctx = { a, cb, true, user };
2240 	return sdb_foreach (a->sdb_zigns, foreachCB, &ctx);
2241 }
2242 
r_sign_search_new(void)2243 R_API RSignSearch *r_sign_search_new(void) {
2244 	RSignSearch *ret = R_NEW0 (RSignSearch);
2245 	if (ret) {
2246 		ret->search = r_search_new (R_SEARCH_KEYWORD);
2247 		ret->items = r_list_newf ((RListFree) r_sign_item_free);
2248 	}
2249 	return ret;
2250 }
2251 
r_sign_search_free(RSignSearch * ss)2252 R_API void r_sign_search_free(RSignSearch *ss) {
2253 	if (!ss) {
2254 		return;
2255 	}
2256 	r_search_free (ss->search);
2257 	r_list_free (ss->items);
2258 	free (ss);
2259 }
2260 
searchHitCB(RSearchKeyword * kw,void * user,ut64 addr)2261 static int searchHitCB(RSearchKeyword *kw, void *user, ut64 addr) {
2262 	RSignSearch *ss = (RSignSearch *) user;
2263 	return ss->cb? ss->cb ((RSignItem *) kw->data, kw, addr, ss->user): 1;
2264 }
2265 
2266 struct ctxAddSearchKwCB {
2267 	RSignSearch *ss;
2268 	int minsz;
2269 };
2270 
addSearchKwCB(RSignItem * it,void * user)2271 static int addSearchKwCB(RSignItem *it, void *user) {
2272 	struct ctxAddSearchKwCB *ctx = (struct ctxAddSearchKwCB *) user;
2273 	RSignSearch *ss = ctx->ss;
2274 	RSignBytes *bytes = it->bytes;
2275 
2276 	if (!bytes) {
2277 		eprintf ("Cannot find bytes for this signature: %s\n", it->name);
2278 		return 1;
2279 	}
2280 
2281 	if (ctx->minsz && bytes->size < ctx->minsz) {
2282 		return 1;
2283 	}
2284 	r_list_append (ss->items, it);
2285 	// TODO(nibble): change arg data in r_search_keyword_new to void*
2286 	RSearchKeyword *kw = r_search_keyword_new (bytes->bytes, bytes->size, bytes->mask, bytes->size, (const char *)it);
2287 	r_search_kw_add (ss->search, kw);
2288 	return 1;
2289 }
2290 
r_sign_search_init(RAnal * a,RSignSearch * ss,int minsz,RSignSearchCallback cb,void * user)2291 R_API void r_sign_search_init(RAnal *a, RSignSearch *ss, int minsz, RSignSearchCallback cb, void *user) {
2292 	struct ctxAddSearchKwCB ctx = { ss, minsz };
2293 	r_return_if_fail (a && ss && cb);
2294 	ss->cb = cb;
2295 	ss->user = user;
2296 	r_list_purge (ss->items);
2297 	r_search_reset (ss->search, R_SEARCH_KEYWORD);
2298 	r_sign_foreach_nofree (a, addSearchKwCB, &ctx);
2299 	r_search_begin (ss->search);
2300 	r_search_set_callback (ss->search, searchHitCB, ss);
2301 }
2302 
r_sign_search_update(RAnal * a,RSignSearch * ss,ut64 * at,const ut8 * buf,int len)2303 R_API int r_sign_search_update(RAnal *a, RSignSearch *ss, ut64 *at, const ut8 *buf, int len) {
2304 	r_return_val_if_fail (a && ss && buf && len > 0, 0);
2305 	return r_search_update (ss->search, *at, buf, len);
2306 }
2307 
2308 // allow ~10% of margin error
matchCount(int a,int b)2309 static int matchCount(int a, int b) {
2310 	int c = a - b;
2311 	int m = a / 10;
2312 	return R_ABS (c) < m;
2313 }
2314 
fcnMetricsCmp(RSignItem * it,RAnalFunction * fcn)2315 static bool fcnMetricsCmp(RSignItem *it, RAnalFunction *fcn) {
2316 	RSignGraph *graph = it->graph;
2317 	int ebbs = -1;
2318 
2319 	if (graph->cc != -1 && graph->cc != r_anal_function_complexity (fcn)) {
2320 		return false;
2321 	}
2322 	if (graph->nbbs != -1 && graph->nbbs != r_list_length (fcn->bbs)) {
2323 		return false;
2324 	}
2325 	if (graph->edges != -1 && graph->edges != r_anal_function_count_edges (fcn, &ebbs)) {
2326 		return false;
2327 	}
2328 	if (graph->ebbs != -1 && graph->ebbs != ebbs) {
2329 		return false;
2330 	}
2331 	if (graph->bbsum > 0 && matchCount (graph->bbsum, r_anal_function_linear_size (fcn))) {
2332 		return false;
2333 	}
2334 	return true;
2335 }
2336 
graph_match(RSignItem * it,RSignSearchMetrics * sm)2337 static bool graph_match(RSignItem *it, RSignSearchMetrics *sm) {
2338 	RSignGraph *graph = it->graph;
2339 
2340 	if (!graph) {
2341 		return false;
2342 	}
2343 
2344 	if (graph->cc < sm->mincc) {
2345 		return false;
2346 	}
2347 
2348 	if (!fcnMetricsCmp (it, sm->fcn)) {
2349 		return false;
2350 	}
2351 
2352 	return true;
2353 }
2354 
addr_match(RSignItem * it,RSignSearchMetrics * sm)2355 static bool addr_match(RSignItem *it, RSignSearchMetrics *sm) {
2356 	if (it->addr != sm->fcn->addr || it->addr == UT64_MAX) {
2357 		return false;
2358 	}
2359 	return true;
2360 }
2361 
hash_match(RSignItem * it,char ** digest_hex,RSignSearchMetrics * sm)2362 static bool hash_match(RSignItem *it, char **digest_hex, RSignSearchMetrics *sm) {
2363 	RSignHash *hash = it->hash;
2364 	if (!hash || !hash->bbhash || hash->bbhash[0] == 0) {
2365 		return false;
2366 	}
2367 
2368 	if (!*digest_hex) {
2369 		*digest_hex = r_sign_calc_bbhash (sm->anal, sm->fcn);
2370 	}
2371 	if (strcmp (hash->bbhash, *digest_hex)) {
2372 		return false;
2373 	}
2374 	return true;
2375 }
2376 
str_list_equals(RList * la,RList * lb)2377 static bool str_list_equals(RList *la, RList *lb) {
2378 	r_return_val_if_fail (la && lb, false);
2379 	size_t len = r_list_length (la);
2380 	if (len != r_list_length (lb)) {
2381 		return false;
2382 	}
2383 	size_t i;
2384 	for (i = 0; i < len; i++) {
2385 		const char *a = r_list_get_n (la, i);
2386 		const char *b = r_list_get_n (lb, i);
2387 		if (strcmp (a, b)) {
2388 			return false;
2389 		}
2390 	}
2391 	return true;
2392 }
2393 
vars_match(RSignItem * it,RList ** vars,RSignSearchMetrics * sm)2394 static bool vars_match(RSignItem *it, RList **vars, RSignSearchMetrics *sm) {
2395 	r_return_val_if_fail (vars && sm, false);
2396 	if (!it->vars) {
2397 		return false;
2398 	}
2399 
2400 	if (!*vars) {
2401 		*vars = r_sign_fcn_vars (sm->anal, sm->fcn);
2402 		if (!*vars) {
2403 			return false;
2404 		}
2405 	}
2406 
2407 	if (str_list_equals (*vars, it->vars)) {
2408 		return true;
2409 	}
2410 	return false;
2411 }
2412 
refs_match(RSignItem * it,RList ** refs,RSignSearchMetrics * sm)2413 static bool refs_match(RSignItem *it, RList **refs, RSignSearchMetrics *sm) {
2414 	r_return_val_if_fail (refs && sm, false);
2415 	if (!it->refs) {
2416 		return false;
2417 	}
2418 
2419 	if (!*refs) {
2420 		*refs = r_sign_fcn_refs (sm->anal, sm->fcn);
2421 		if (!*refs) {
2422 			return false;
2423 		}
2424 	}
2425 
2426 	if (str_list_equals (*refs, it->refs)) {
2427 		return true;
2428 	}
2429 	return false;
2430 }
2431 
types_match(RSignItem * it,RList ** types,RSignSearchMetrics * sm)2432 static bool types_match(RSignItem *it, RList **types, RSignSearchMetrics *sm) {
2433 	r_return_val_if_fail (types && sm, false);
2434 	if (!it->types) {
2435 		return false;
2436 	}
2437 
2438 	if (!*types) {
2439 		*types = r_sign_fcn_types (sm->anal, sm->fcn);
2440 		if (!*types) {
2441 			return false;
2442 		}
2443 	}
2444 
2445 	if (str_list_equals (*types, it->types)) {
2446 		return true;
2447 	}
2448 	return false;
2449 }
2450 
2451 struct metric_ctx {
2452 	int matched;
2453 	RSignSearchMetrics *sm;
2454 	RList *refs;
2455 	RList *types;
2456 	RList *vars;
2457 	char *digest_hex;
2458 };
2459 
match_metrics(RSignItem * it,void * user)2460 static int match_metrics(RSignItem *it, void *user) {
2461 	struct metric_ctx *ctx = (struct metric_ctx *)user;
2462 	RSignSearchMetrics *sm = ctx->sm;
2463 	RSignType type;
2464 	int count = 0;
2465 	int i = 0;
2466 	while ((type = sm->types[i++])) {
2467 		bool found = false;
2468 		switch (type) {
2469 		case R_SIGN_GRAPH:
2470 			found = graph_match (it, sm);
2471 			break;
2472 		case R_SIGN_OFFSET:
2473 			found = addr_match (it, sm);
2474 			break;
2475 		case R_SIGN_BBHASH:
2476 			found = hash_match (it, &ctx->digest_hex, sm);
2477 			break;
2478 		case R_SIGN_REFS:
2479 			found = refs_match (it, &ctx->refs, sm);
2480 			break;
2481 		case R_SIGN_TYPES:
2482 			found = vars_match (it, &ctx->vars, sm);
2483 			break;
2484 		case R_SIGN_VARS:
2485 			found = types_match (it, &ctx->types, sm);
2486 			break;
2487 		default:
2488 			eprintf ("Invalid type: %c\n", type);
2489 		}
2490 		if (found) {
2491 			sm->cb (it, sm->fcn, type, (count > 1), sm->user);
2492 			count++;
2493 		}
2494 	}
2495 	ctx->matched += count;
2496 	return count? 0: 1;
2497 }
2498 
r_sign_fcn_match_metrics(RSignSearchMetrics * sm)2499 R_API int r_sign_fcn_match_metrics(RSignSearchMetrics *sm) {
2500 	r_return_val_if_fail (sm && sm->mincc >= 0 && sm->anal && sm->fcn, false);
2501 	struct metric_ctx ctx = { 0, sm, NULL, NULL, NULL, NULL };
2502 	r_sign_foreach (sm->anal, match_metrics, (void *)&ctx);
2503 	r_list_free (ctx.refs);
2504 	r_list_free (ctx.types);
2505 	r_list_free (ctx.vars);
2506 	free (ctx.digest_hex);
2507 	return ctx.matched;
2508 }
2509 
r_sign_item_new(void)2510 R_API RSignItem *r_sign_item_new(void) {
2511 	RSignItem *ret = R_NEW0 (RSignItem);
2512 	if (ret) {
2513 		ret->addr = UT64_MAX;
2514 		ret->space = NULL;
2515 	}
2516 	return ret;
2517 }
2518 
r_sign_item_free(RSignItem * item)2519 R_API void r_sign_item_free(RSignItem *item) {
2520 	if (!item) {
2521 		return;
2522 	}
2523 	free (item->name);
2524 	r_sign_bytes_free (item->bytes);
2525 	if (item->hash) {
2526 		free (item->hash->bbhash);
2527 		free (item->hash);
2528 	}
2529 	r_sign_graph_free (item->graph);
2530 	free (item->comment);
2531 	free (item->realname);
2532 	r_list_free (item->refs);
2533 	r_list_free (item->vars);
2534 	r_list_free (item->xrefs);
2535 	r_list_free (item->types);
2536 	free (item);
2537 }
2538 
r_sign_graph_free(RSignGraph * graph)2539 R_API void r_sign_graph_free(RSignGraph *graph) {
2540 	free (graph);
2541 }
2542 
r_sign_bytes_free(RSignBytes * bytes)2543 R_API void r_sign_bytes_free(RSignBytes *bytes) {
2544 	if (bytes) {
2545 		free (bytes->bytes);
2546 		free (bytes->mask);
2547 		free (bytes);
2548 	}
2549 }
2550 
loadCB(void * user,const char * k,const char * v)2551 static bool loadCB(void *user, const char *k, const char *v) {
2552 	RAnal *a = (RAnal *) user;
2553 	char nk[R_SIGN_KEY_MAXSZ], nv[R_SIGN_VAL_MAXSZ];
2554 	RSignItem *it = r_sign_item_new ();
2555 	if (it && r_sign_deserialize (a, it, k, v)) {
2556 		serialize (a, it, nk, nv);
2557 		sdb_set (a->sdb_zigns, nk, nv, 0);
2558 	} else {
2559 		eprintf ("error: cannot deserialize zign\n");
2560 	}
2561 	r_sign_item_free (it);
2562 	return true;
2563 }
2564 
r_sign_path(RAnal * a,const char * file)2565 R_API char *r_sign_path(RAnal *a, const char *file) {
2566 	char *abs = r_file_abspath (file);
2567 	if (abs) {
2568 		if (r_file_is_regular (abs)) {
2569 			return abs;
2570 		}
2571 		free (abs);
2572 	}
2573 
2574 	if (a->zign_path) {
2575 		char *path = r_str_newf ("%s%s%s", a->zign_path, R_SYS_DIR, file);
2576 		abs = r_file_abspath (path);
2577 		free (path);
2578 		if (r_file_is_regular (abs)) {
2579 			return abs;
2580 		}
2581 		free (abs);
2582 	} else {
2583 		char *home = r_str_home (R2_HOME_ZIGNS);
2584 		abs = r_str_newf ("%s%s%s", home, R_SYS_DIR, file);
2585 		free (home);
2586 		if (r_file_is_regular (abs)) {
2587 			return abs;
2588 		}
2589 		free (abs);
2590 	}
2591 
2592 	abs = r_str_newf (R_JOIN_3_PATHS ("%s", R2_ZIGNS, "%s"), r_sys_prefix (NULL), file);
2593 	if (r_file_is_regular (abs)) {
2594 		return abs;
2595 	}
2596 	free (abs);
2597 
2598 	return NULL;
2599 }
2600 
r_sign_load(RAnal * a,const char * file)2601 R_API bool r_sign_load(RAnal *a, const char *file) {
2602 	if (!a || !file) {
2603 		return false;
2604 	}
2605 	char *path = r_sign_path (a, file);
2606 	if (!r_file_exists (path)) {
2607 		eprintf ("error: file %s does not exist\n", file);
2608 		free (path);
2609 		return false;
2610 	}
2611 	Sdb *db = sdb_new (NULL, path, 0);
2612 	if (!db) {
2613 		free (path);
2614 		return false;
2615 	}
2616 	sdb_foreach (db, loadCB, a);
2617 	sdb_close (db);
2618 	sdb_free (db);
2619 	free (path);
2620 	return true;
2621 }
2622 
r_sign_load_gz(RAnal * a,const char * filename)2623 R_API bool r_sign_load_gz(RAnal *a, const char *filename) {
2624 	ut8 *buf = NULL;
2625 	int size = 0;
2626 	char *tmpfile = NULL;
2627 	bool retval = true;
2628 
2629 	char *path = r_sign_path (a, filename);
2630 	if (!r_file_exists (path)) {
2631 		eprintf ("error: file %s does not exist\n", filename);
2632 		retval = false;
2633 		goto out;
2634 	}
2635 
2636 	if (!(buf = r_file_gzslurp (path, &size, 0))) {
2637 		eprintf ("error: cannot decompress file\n");
2638 		retval = false;
2639 		goto out;
2640 	}
2641 
2642 	if (!(tmpfile = r_file_temp ("r2zign"))) {
2643 		eprintf ("error: cannot create temp file\n");
2644 		retval = false;
2645 		goto out;
2646 	}
2647 
2648 	if (!r_file_dump (tmpfile, buf, size, 0)) {
2649 		eprintf ("error: cannot dump file\n");
2650 		retval = false;
2651 		goto out;
2652 	}
2653 
2654 	if (!r_sign_load (a, tmpfile)) {
2655 		eprintf ("error: cannot load file\n");
2656 		retval = false;
2657 		goto out;
2658 	}
2659 
2660 	if (!r_file_rm (tmpfile)) {
2661 		eprintf ("error: cannot delete temp file\n");
2662 		retval = false;
2663 		goto out;
2664 	}
2665 
2666 out:
2667 	free (buf);
2668 	free (tmpfile);
2669 	free (path);
2670 
2671 	return retval;
2672 }
2673 
r_sign_save(RAnal * a,const char * file)2674 R_API bool r_sign_save(RAnal *a, const char *file) {
2675 	r_return_val_if_fail (a && file, false);
2676 
2677 	if (sdb_isempty (a->sdb_zigns)) {
2678 		eprintf ("WARNING: no zignatures to save\n");
2679 		return false;
2680 	}
2681 
2682 	Sdb *db = sdb_new (NULL, file, 0);
2683 	if (!db) {
2684 		return false;
2685 	}
2686 	sdb_merge (db, a->sdb_zigns);
2687 	bool retval = sdb_sync (db);
2688 	sdb_close (db);
2689 	sdb_free (db);
2690 
2691 	return retval;
2692 }
2693 
r_sign_options_new(const char * bytes_thresh,const char * graph_thresh)2694 R_API RSignOptions *r_sign_options_new(const char *bytes_thresh, const char *graph_thresh) {
2695 	RSignOptions *options = R_NEW0 (RSignOptions);
2696 	if (!options) {
2697 		return NULL;
2698 	}
2699 
2700 	options->bytes_diff_threshold = r_num_get_float (NULL, bytes_thresh);
2701 	options->graph_diff_threshold = r_num_get_float (NULL, graph_thresh);
2702 
2703 	if (options->bytes_diff_threshold > 1.0) {
2704 		options->bytes_diff_threshold = 1.0;
2705 	}
2706 	if (options->bytes_diff_threshold < 0) {
2707 		options->bytes_diff_threshold = 0.0;
2708 	}
2709 	if (options->graph_diff_threshold > 1.0) {
2710 		options->graph_diff_threshold = 1.0;
2711 	}
2712 	if (options->graph_diff_threshold < 0) {
2713 		options->graph_diff_threshold = 0.0;
2714 	}
2715 
2716 	return options;
2717 }
2718 
r_sign_options_free(RSignOptions * options)2719 R_API void r_sign_options_free(RSignOptions *options) {
2720 	R_FREE (options);
2721 }
2722