1/*
2 * Copyright (C) 2012 Oracle.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
16 */
17
18/*
19 * The point here is to store that a buffer has x bytes even if we don't know
20 * the value of x.
21 *
22 */
23
24#include "smatch.h"
25#include "smatch_extra.h"
26#include "smatch_slist.h"
27
28static int size_id;
29static int link_id;
30
31/*
32 * There is a bunch of code which does this:
33 *
34 *     if (size)
35 *         foo = malloc(size);
36 *
37 * So if "size" is non-zero then the size of "foo" is size.  But really it's
38 * also true if size is zero.  It's just better to assume to not trample over
39 * the data that we have by merging &undefined states.
40 *
41 */
42static struct smatch_state *unmatched_state(struct sm_state *sm)
43{
44	return sm->state;
45}
46
47static struct smatch_state *merge_links(struct smatch_state *s1, struct smatch_state *s2)
48{
49	struct expression *expr1, *expr2;
50
51	expr1 = s1->data;
52	expr2 = s2->data;
53
54	if (expr1 && expr2 && expr_equiv(expr1, expr2))
55		return s1;
56	return &merged;
57}
58
59static void match_link_modify(struct sm_state *sm, struct expression *mod_expr)
60{
61	struct expression *expr;
62	struct sm_state *tmp;
63
64	expr = sm->state->data;
65	if (expr) {
66		set_state_expr(size_id, expr, &undefined);
67		set_state(link_id, sm->name, sm->sym, &undefined);
68		return;
69	}
70
71	FOR_EACH_PTR(sm->possible, tmp) {
72		expr = tmp->state->data;
73		if (expr)
74			set_state_expr(size_id, expr, &undefined);
75	} END_FOR_EACH_PTR(tmp);
76	set_state(link_id, sm->name, sm->sym, &undefined);
77}
78
79static const char *limit_map[] = {
80	"byte_count",
81	"elem_count",
82	"elem_last",
83	"used_count",
84	"used_last",
85};
86
87int state_to_limit(struct smatch_state *state)
88{
89	int i;
90
91	if (!state || !state->data)
92		return -1;
93
94	for (i = 0; i < ARRAY_SIZE(limit_map); i++) {
95		if (strncmp(state->name, limit_map[i], strlen(limit_map[i])) == 0)
96			return i + BYTE_COUNT;
97	}
98
99	return -1;
100}
101
102const char *limit_type_str(unsigned int limit_type)
103{
104	if (limit_type - BYTE_COUNT >= ARRAY_SIZE(limit_map)) {
105		sm_msg("internal: wrong size type %u", limit_type);
106		return "unknown";
107	}
108
109	return limit_map[limit_type - BYTE_COUNT];
110}
111
112static struct smatch_state *alloc_compare_size(int limit_type, struct expression *expr)
113{
114	struct smatch_state *state;
115	char *name;
116	char buf[256];
117
118	state = __alloc_smatch_state(0);
119	expr = strip_expr(expr);
120	name = expr_to_str(expr);
121	snprintf(buf, sizeof(buf), "%s %s", limit_type_str(limit_type), name);
122	state->name = alloc_sname(buf);
123	free_string(name);
124	state->data = expr;
125	return state;
126}
127
128static int bytes_per_element(struct expression *expr)
129{
130	struct symbol *type;
131
132	type = get_type(expr);
133	if (!type)
134		return 0;
135
136	if (type->type != SYM_PTR && type->type != SYM_ARRAY)
137		return 0;
138
139	type = get_base_type(type);
140	return type_bytes(type);
141}
142
143static void db_save_type_links(struct expression *array, int type_limit, struct expression *size)
144{
145	const char *array_name;
146
147	array_name = get_data_info_name(array);
148	if (!array_name)
149		array_name = "";
150	sql_insert_data_info(size, type_limit, array_name);
151}
152
153static void match_alloc_helper(struct expression *pointer, struct expression *size)
154{
155	struct expression *tmp;
156	struct sm_state *sm;
157	int limit_type = ELEM_COUNT;
158	sval_t sval;
159	int cnt = 0;
160
161	pointer = strip_expr(pointer);
162	size = strip_expr(size);
163	if (!size || !pointer)
164		return;
165
166	while ((tmp = get_assigned_expr(size))) {
167		size = strip_expr(tmp);
168		if (cnt++ > 5)
169			break;
170	}
171
172	if (size->type == EXPR_BINOP && size->op == '*') {
173		struct expression *mult_left, *mult_right;
174
175		mult_left = strip_expr(size->left);
176		mult_right = strip_expr(size->right);
177
178		if (get_implied_value(mult_left, &sval) &&
179		    sval.value == bytes_per_element(pointer))
180			size = mult_right;
181		else if (get_implied_value(mult_right, &sval) &&
182		    sval.value == bytes_per_element(pointer))
183			size = mult_left;
184		else
185			return;
186	}
187
188	/* Only save links to variables, not fixed sizes */
189	if (get_value(size, &sval))
190		return;
191
192	if (size->type == EXPR_BINOP && size->op == '+' &&
193	    get_value(size->right, &sval) && sval.value == 1) {
194		size = size->left;
195		limit_type = ELEM_LAST;
196	}
197
198	db_save_type_links(pointer, limit_type, size);
199	sm = set_state_expr(size_id, pointer, alloc_compare_size(limit_type, size));
200	if (!sm)
201		return;
202	set_state_expr(link_id, size, alloc_state_expr(pointer));
203}
204
205static void match_alloc(const char *fn, struct expression *expr, void *_size_arg)
206{
207	int size_arg = PTR_INT(_size_arg);
208	struct expression *pointer, *call, *arg;
209
210	pointer = strip_expr(expr->left);
211	call = strip_expr(expr->right);
212	arg = get_argument_from_call_expr(call->args, size_arg);
213	match_alloc_helper(pointer, arg);
214}
215
216static void match_calloc(const char *fn, struct expression *expr, void *_start_arg)
217{
218	int start_arg = PTR_INT(_start_arg);
219	struct expression *pointer, *call, *arg;
220	struct sm_state *tmp;
221	int limit_type = ELEM_COUNT;
222	sval_t sval;
223
224	pointer = strip_expr(expr->left);
225	call = strip_expr(expr->right);
226	arg = get_argument_from_call_expr(call->args, start_arg);
227	if (get_implied_value(arg, &sval) &&
228	    sval.value == bytes_per_element(pointer))
229		arg = get_argument_from_call_expr(call->args, start_arg + 1);
230
231	if (arg->type == EXPR_BINOP && arg->op == '+' &&
232	    get_value(arg->right, &sval) && sval.value == 1) {
233		arg = arg->left;
234		limit_type = ELEM_LAST;
235	}
236
237	db_save_type_links(pointer, limit_type, arg);
238	tmp = set_state_expr(size_id, pointer, alloc_compare_size(limit_type, arg));
239	if (!tmp)
240		return;
241	set_state_expr(link_id, arg, alloc_state_expr(pointer));
242}
243
244struct expression *get_size_variable(struct expression *buf, int *limit_type)
245{
246	struct smatch_state *state;
247
248	state = get_state_expr(size_id, buf);
249	if (!state)
250		return NULL;
251	*limit_type = state_to_limit(state);
252	return state->data;
253}
254
255struct expression *get_array_variable(struct expression *size)
256{
257	struct smatch_state *state;
258
259	state = get_state_expr(link_id, size);
260	if (state)
261		return state->data;
262	return NULL;
263}
264
265static void array_check(struct expression *expr)
266{
267	struct expression *array;
268	struct expression *size;
269	struct expression *offset;
270	char *array_str, *offset_str;
271	int limit_type;
272
273	expr = strip_expr(expr);
274	if (!is_array(expr))
275		return;
276
277	array = get_array_base(expr);
278	size = get_size_variable(array, &limit_type);
279	if (!size)
280		return;
281	if (limit_type != ELEM_COUNT)
282		return;
283	offset = get_array_offset(expr);
284	if (!possible_comparison(size, SPECIAL_EQUAL, offset))
285		return;
286
287	array_str = expr_to_str(array);
288	offset_str = expr_to_str(offset);
289	sm_warning("potentially one past the end of array '%s[%s]'", array_str, offset_str);
290	free_string(array_str);
291	free_string(offset_str);
292}
293
294struct db_info {
295	char *name;
296	int ret;
297};
298
299static int db_limitter_callback(void *_info, int argc, char **argv, char **azColName)
300{
301	struct db_info *info = _info;
302
303	/*
304	 * If possible the limitters are tied to the struct they limit.  If we
305	 * aren't sure which struct they limit then we use them as limitters for
306	 * everything.
307	 */
308	if (!info->name || argv[0][0] == '\0' || strcmp(info->name, argv[0]) == 0)
309		info->ret = 1;
310	return 0;
311}
312
313static char *vsl_to_data_info_name(const char *name, struct var_sym_list *vsl)
314{
315	struct var_sym *vs;
316	struct symbol *type;
317	static char buf[80];
318	const char *p;
319
320	if (ptr_list_size((struct ptr_list *)vsl) != 1)
321		return NULL;
322	vs = first_ptr_list((struct ptr_list *)vsl);
323
324	type = get_real_base_type(vs->sym);
325	if (!type || type->type != SYM_PTR)
326		goto top_level_name;
327	type = get_real_base_type(type);
328	if (!type || type->type != SYM_STRUCT)
329		goto top_level_name;
330	if (!type->ident)
331		goto top_level_name;
332
333	p = name;
334	while ((name = strstr(p, "->")))
335		p = name + 2;
336
337	snprintf(buf, sizeof(buf),"(struct %s)->%s", type->ident->name, p);
338	return alloc_sname(buf);
339
340top_level_name:
341	if (!(vs->sym->ctype.modifiers & MOD_TOPLEVEL))
342		return NULL;
343	if (vs->sym->ctype.modifiers & MOD_STATIC)
344		snprintf(buf, sizeof(buf),"static %s", name);
345	else
346		snprintf(buf, sizeof(buf),"global %s", name);
347	return alloc_sname(buf);
348}
349
350int db_var_is_array_limit(struct expression *array, const char *name, struct var_sym_list *vsl)
351{
352	char *size_name;
353	char *array_name = get_data_info_name(array);
354	struct db_info db_info = {.name = array_name,};
355
356	size_name = vsl_to_data_info_name(name, vsl);
357	if (!size_name)
358		return 0;
359
360	run_sql(db_limitter_callback, &db_info,
361		"select value from data_info where type = %d and data = '%s';",
362		ARRAY_LEN, size_name);
363
364	return db_info.ret;
365}
366
367int buf_comparison_index_ok(struct expression *expr)
368{
369	struct expression *array;
370	struct expression *size;
371	struct expression *offset;
372	int limit_type;
373	int comparison;
374
375	array = get_array_base(expr);
376	size = get_size_variable(array, &limit_type);
377	if (!size)
378		return 0;
379	offset = get_array_offset(expr);
380	comparison = get_comparison(offset, size);
381	if (!comparison)
382		return 0;
383
384	if ((limit_type == ELEM_COUNT || limit_type == ELEM_LAST) &&
385	    (comparison == '<' || comparison == SPECIAL_UNSIGNED_LT))
386		return 1;
387	if (limit_type == ELEM_LAST &&
388	    (comparison == SPECIAL_LTE ||
389	     comparison == SPECIAL_UNSIGNED_LTE ||
390	     comparison == SPECIAL_EQUAL))
391		return 1;
392
393	return 0;
394}
395
396static int known_access_ok_numbers(struct expression *expr)
397{
398	struct expression *array;
399	struct expression *offset;
400	sval_t max;
401	int size;
402
403	array = get_array_base(expr);
404	offset = get_array_offset(expr);
405
406	size = get_array_size(array);
407	if (size <= 0)
408		return 0;
409
410	get_absolute_max(offset, &max);
411	if (max.uvalue < size)
412		return 1;
413	return 0;
414}
415
416static void array_check_data_info(struct expression *expr)
417{
418	struct expression *array;
419	struct expression *offset;
420	struct state_list *slist;
421	struct sm_state *sm;
422	struct compare_data *comp;
423	char *offset_name;
424	const char *equal_name = NULL;
425
426	expr = strip_expr(expr);
427	if (!is_array(expr))
428		return;
429
430	if (known_access_ok_numbers(expr))
431		return;
432	if (buf_comparison_index_ok(expr))
433		return;
434
435	array = get_array_base(expr);
436	offset = get_array_offset(expr);
437	offset_name = expr_to_var(offset);
438	if (!offset_name)
439		return;
440	slist = get_all_possible_equal_comparisons(offset);
441	if (!slist)
442		goto free;
443
444	FOR_EACH_PTR(slist, sm) {
445		comp = sm->state->data;
446		if (strcmp(comp->left_var, offset_name) == 0) {
447			if (db_var_is_array_limit(array, comp->right_var, comp->right_vsl)) {
448				equal_name = comp->right_var;
449				break;
450			}
451		} else if (strcmp(comp->right_var, offset_name) == 0) {
452			if (db_var_is_array_limit(array, comp->left_var, comp->left_vsl)) {
453				equal_name = comp->left_var;
454				break;
455			}
456		}
457	} END_FOR_EACH_PTR(sm);
458
459	if (equal_name) {
460		char *array_name = expr_to_str(array);
461
462		sm_warning("potential off by one '%s[]' limit '%s'", array_name, equal_name);
463		free_string(array_name);
464	}
465
466free:
467	free_slist(&slist);
468	free_string(offset_name);
469}
470
471static void add_allocation_function(const char *func, void *call_back, int param)
472{
473	add_function_assign_hook(func, call_back, INT_PTR(param));
474}
475
476static int is_sizeof(struct expression *expr)
477{
478	const char *name;
479
480	if (expr->type == EXPR_SIZEOF)
481		return 1;
482	name = pos_ident(expr->pos);
483	if (name && strcmp(name, "sizeof") == 0)
484		return 1;
485	return 0;
486}
487
488static int match_size_binop(struct expression *size, struct expression *expr, int *limit_type)
489{
490	int orig_type = *limit_type;
491	struct expression *left;
492	sval_t sval;
493
494	left = expr->left;
495	if (!expr_equiv(size, left))
496		return 0;
497
498	if (expr->op == '-' &&
499	    get_value(expr->right, &sval) &&
500	    sval.value == 1 &&
501	    orig_type == ELEM_COUNT) {
502		*limit_type = ELEM_LAST;
503		return 1;
504	}
505
506	if (expr->op == '+' &&
507	    get_value(expr->right, &sval) &&
508	    sval.value == 1 &&
509	    orig_type == ELEM_LAST) {
510		*limit_type = ELEM_COUNT;
511		return 1;
512	}
513
514	if (expr->op == '*' &&
515	    is_sizeof(expr->right) &&
516	    orig_type == ELEM_COUNT) {
517		*limit_type = BYTE_COUNT;
518		return 1;
519	}
520
521	if (expr->op == '/' &&
522	    is_sizeof(expr->right) &&
523	    orig_type == BYTE_COUNT) {
524		*limit_type = ELEM_COUNT;
525		return 1;
526	}
527
528	return 0;
529}
530
531static char *buf_size_param_comparison(struct expression *array, struct expression_list *args, int *limit_type)
532{
533	struct expression *tmp, *arg;
534	struct expression *size;
535	static char buf[32];
536	int i;
537
538	size = get_size_variable(array, limit_type);
539	if (!size)
540		return NULL;
541
542	if (*limit_type == USED_LAST)
543		*limit_type = ELEM_LAST;
544	if (*limit_type == USED_COUNT)
545		*limit_type = ELEM_COUNT;
546
547	i = -1;
548	FOR_EACH_PTR(args, tmp) {
549		i++;
550		arg = tmp;
551		if (arg == array)
552			continue;
553		if (expr_equiv(arg, size) ||
554		    (arg->type == EXPR_BINOP &&
555		     match_size_binop(size, arg, limit_type))) {
556			snprintf(buf, sizeof(buf), "==$%d", i);
557			return buf;
558		}
559	} END_FOR_EACH_PTR(tmp);
560
561	return NULL;
562}
563
564static void match_call(struct expression *call)
565{
566	struct expression *arg;
567	char *compare;
568	int param;
569	char buf[5];
570	int limit_type;
571
572	param = -1;
573	FOR_EACH_PTR(call->args, arg) {
574		param++;
575		if (!is_pointer(arg))
576			continue;
577		compare = buf_size_param_comparison(arg, call->args, &limit_type);
578		if (!compare)
579			continue;
580		snprintf(buf, sizeof(buf), "%d", limit_type);
581		sql_insert_caller_info(call, limit_type, param, compare, buf);
582	} END_FOR_EACH_PTR(arg);
583}
584
585static int get_param(int param, char **name, struct symbol **sym)
586{
587	struct symbol *arg;
588	int i;
589
590	i = 0;
591	FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
592		/*
593		 * this is a temporary hack to work around a bug (I think in sparse?)
594		 * 2.6.37-rc1:fs/reiserfs/journal.o
595		 * If there is a function definition without parameter name found
596		 * after a function implementation then it causes a crash.
597		 * int foo() {}
598		 * int bar(char *);
599		 */
600		if (arg->ident->name < (char *)100)
601			continue;
602		if (i == param) {
603			*name = arg->ident->name;
604			*sym = arg;
605			return TRUE;
606		}
607		i++;
608	} END_FOR_EACH_PTR(arg);
609
610	return FALSE;
611}
612
613static void set_param_compare(const char *array_name, struct symbol *array_sym, char *key, char *value)
614{
615	struct expression *array_expr;
616	struct expression *size_expr;
617	struct symbol *size_sym;
618	char *size_name;
619	long param;
620	struct sm_state *tmp;
621	int limit_type;
622
623	if (strncmp(key, "==$", 3) != 0)
624		return;
625	param = strtol(key + 3, NULL, 10);
626	if (!get_param(param, &size_name, &size_sym))
627		return;
628	array_expr = symbol_expression(array_sym);
629	size_expr = symbol_expression(size_sym);
630	limit_type = strtol(value, NULL, 10);
631
632	tmp = set_state_expr(size_id, array_expr, alloc_compare_size(limit_type, size_expr));
633	if (!tmp)
634		return;
635	set_state_expr(link_id, size_expr, alloc_state_expr(array_expr));
636}
637
638static void set_implied(struct expression *call, struct expression *array_expr, char *key, char *value)
639{
640	struct expression *size_expr;
641	struct symbol *size_sym;
642	char *size_name;
643	long param;
644	struct sm_state *tmp;
645	int limit_type;
646
647	if (strncmp(key, "==$", 3) != 0)
648		return;
649	param = strtol(key + 3, NULL, 10);
650	if (!get_param(param, &size_name, &size_sym))
651		return;
652	size_expr = symbol_expression(size_sym);
653
654	limit_type = strtol(value, NULL, 10);
655	tmp = set_state_expr(size_id, array_expr, alloc_compare_size(limit_type, size_expr));
656	if (!tmp)
657		return;
658	set_state_expr(link_id, size_expr, alloc_state_expr(array_expr));
659}
660
661static void munge_start_states(struct statement *stmt)
662{
663	struct state_list *slist = NULL;
664	struct sm_state *sm;
665	struct sm_state *poss;
666
667	FOR_EACH_MY_SM(size_id, __get_cur_stree(), sm) {
668		if (sm->state != &merged)
669			continue;
670		/*
671		 * screw it.  let's just assume that if one caller passes the
672		 * size then they all do.
673		 */
674		FOR_EACH_PTR(sm->possible, poss) {
675			if (poss->state != &merged &&
676			    poss->state != &undefined) {
677				add_ptr_list(&slist, poss);
678				break;
679			}
680		} END_FOR_EACH_PTR(poss);
681	} END_FOR_EACH_SM(sm);
682
683	FOR_EACH_PTR(slist, sm) {
684		set_state(size_id, sm->name, sm->sym, sm->state);
685	} END_FOR_EACH_PTR(sm);
686
687	free_slist(&slist);
688}
689
690static void set_used(struct expression *expr)
691{
692	struct expression *parent;
693	struct expression *array;
694	struct expression *offset;
695	struct sm_state *tmp;
696	int limit_type;
697
698	if (expr->op != SPECIAL_INCREMENT)
699		return;
700
701	limit_type = USED_LAST;
702	if (expr->type == EXPR_POSTOP)
703		limit_type = USED_COUNT;
704
705	parent = expr_get_parent_expr(expr);
706	if (!parent || parent->type != EXPR_BINOP)
707		return;
708	parent = expr_get_parent_expr(parent);
709	if (!parent || !is_array(parent))
710		return;
711
712	array = get_array_base(parent);
713	offset = get_array_offset(parent);
714	if (offset != expr)
715		return;
716
717	tmp = set_state_expr(size_id, array, alloc_compare_size(limit_type, offset->unop));
718	if (!tmp)
719		return;
720	set_state_expr(link_id, offset->unop, alloc_state_expr(array));
721}
722
723static int match_assign_array(struct expression *expr)
724{
725	// FIXME: implement
726	return 0;
727}
728
729static int match_assign_size(struct expression *expr)
730{
731	struct expression *right, *size, *array;
732	struct smatch_state *state;
733	struct sm_state *tmp;
734	int limit_type;
735
736	right = expr->right;
737	size = right;
738	if (size->type == EXPR_BINOP)
739		size = size->left;
740
741	array = get_array_variable(size);
742	if (!array)
743		return 0;
744	state = get_state_expr(size_id, array);
745	if (!state || !state->data)
746		return 0;
747
748	limit_type = state_to_limit(state);
749	if (limit_type < 0)
750		return 0;
751
752	if (right->type == EXPR_BINOP && !match_size_binop(size, right, &limit_type))
753		return 0;
754
755	tmp = set_state_expr(size_id, array, alloc_compare_size(limit_type, expr->left));
756	if (!tmp)
757		return 0;
758	set_state_expr(link_id, expr->left, alloc_state_expr(array));
759	return 1;
760}
761
762static void match_assign(struct expression *expr)
763{
764	if (expr->op != '=')
765		return;
766
767	if (match_assign_array(expr))
768		return;
769	match_assign_size(expr);
770}
771
772static void match_copy(const char *fn, struct expression *expr, void *unused)
773{
774	struct expression *src, *size;
775	int src_param, size_param;
776
777	src = get_argument_from_call_expr(expr->args, 1);
778	size = get_argument_from_call_expr(expr->args, 2);
779	src = strip_expr(src);
780	size = strip_expr(size);
781	if (!src || !size)
782		return;
783	if (src->type != EXPR_SYMBOL || size->type != EXPR_SYMBOL)
784		return;
785
786	src_param = get_param_num_from_sym(src->symbol);
787	size_param = get_param_num_from_sym(size->symbol);
788	if (src_param < 0 || size_param < 0)
789		return;
790
791	sql_insert_cache(call_implies, "'%s', '%s', 0, %d, %d, %d, '==$%d', '%d'",
792			 get_base_file(), get_function(), fn_static(),
793			 BYTE_COUNT, src_param, size_param, BYTE_COUNT);
794}
795
796void register_buf_comparison(int id)
797{
798	int i;
799
800	size_id = id;
801
802	set_dynamic_states(size_id);
803
804	add_unmatched_state_hook(size_id, &unmatched_state);
805
806	add_allocation_function("malloc", &match_alloc, 0);
807	add_allocation_function("memdup", &match_alloc, 1);
808	add_allocation_function("realloc", &match_alloc, 1);
809	if (option_project == PROJ_KERNEL) {
810		add_allocation_function("kmalloc", &match_alloc, 0);
811		add_allocation_function("kzalloc", &match_alloc, 0);
812		add_allocation_function("vmalloc", &match_alloc, 0);
813		add_allocation_function("__vmalloc", &match_alloc, 0);
814		add_allocation_function("sock_kmalloc", &match_alloc, 1);
815		add_allocation_function("kmemdup", &match_alloc, 1);
816		add_allocation_function("kmemdup_user", &match_alloc, 1);
817		add_allocation_function("dma_alloc_attrs", &match_alloc, 1);
818		add_allocation_function("pci_alloc_consistent", &match_alloc, 1);
819		add_allocation_function("pci_alloc_coherent", &match_alloc, 1);
820		add_allocation_function("devm_kmalloc", &match_alloc, 1);
821		add_allocation_function("devm_kzalloc", &match_alloc, 1);
822		add_allocation_function("kcalloc", &match_calloc, 0);
823		add_allocation_function("devm_kcalloc", &match_calloc, 1);
824		add_allocation_function("kmalloc_array", &match_calloc, 0);
825		add_allocation_function("krealloc", &match_alloc, 1);
826
827		add_function_hook("copy_from_user", &match_copy, NULL);
828		add_function_hook("__copy_from_user", &match_copy, NULL);
829	}
830
831	add_hook(&array_check, OP_HOOK);
832	add_hook(&array_check_data_info, OP_HOOK);
833	add_hook(&set_used, OP_HOOK);
834
835	add_hook(&match_call, FUNCTION_CALL_HOOK);
836	add_hook(&munge_start_states, AFTER_DEF_HOOK);
837
838	add_hook(&match_assign, ASSIGNMENT_HOOK);
839
840	for (i = BYTE_COUNT; i <= USED_COUNT; i++) {
841		select_call_implies_hook(i, &set_implied);
842		select_caller_info_hook(set_param_compare, i);
843		select_return_implies_hook(i, &set_implied);
844	}
845}
846
847void register_buf_comparison_links(int id)
848{
849	link_id = id;
850	set_dynamic_states(link_id);
851	add_merge_hook(link_id, &merge_links);
852	add_modification_hook(link_id, &match_link_modify);
853}
854