xref: /illumos-gate/usr/src/tools/smatch/src/smatch_buf_size.c (revision efe51d0cc2398b9ac179568b63a44e4bf295b8e2)
1 /*
2  * Copyright (C) 2010 Dan Carpenter.
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 #include <stdlib.h>
19 #include <errno.h>
20 #include "parse.h"
21 #include "smatch.h"
22 #include "smatch_slist.h"
23 #include "smatch_extra.h"
24 #include "smatch_function_hashtable.h"
25 
26 #define UNKNOWN_SIZE (-1)
27 
28 static int my_size_id;
29 
30 static DEFINE_HASHTABLE_INSERT(insert_func, char, int);
31 static DEFINE_HASHTABLE_SEARCH(search_func, char, int);
32 static struct hashtable *allocation_funcs;
33 
34 static char *get_fn_name(struct expression *expr)
35 {
36 	if (expr->type != EXPR_CALL)
37 		return NULL;
38 	if (expr->fn->type != EXPR_SYMBOL)
39 		return NULL;
40 	return expr_to_var(expr->fn);
41 }
42 
43 static int is_allocation_function(struct expression *expr)
44 {
45 	char *func;
46 	int ret = 0;
47 
48 	func = get_fn_name(expr);
49 	if (!func)
50 		return 0;
51 	if (search_func(allocation_funcs, func))
52 		ret = 1;
53 	free_string(func);
54 	return ret;
55 }
56 
57 static void add_allocation_function(const char *func, void *call_back, int param)
58 {
59 	insert_func(allocation_funcs, (char *)func, (int *)1);
60 	add_function_assign_hook(func, call_back, INT_PTR(param));
61 }
62 
63 static int estate_to_size(struct smatch_state *state)
64 {
65 	sval_t sval;
66 
67 	if (!state || !estate_rl(state))
68 		return 0;
69 	sval = estate_max(state);
70 	return sval.value;
71 }
72 
73 static struct smatch_state *size_to_estate(int size)
74 {
75 	sval_t sval;
76 
77 	sval.type = &int_ctype;
78 	sval.value = size;
79 
80 	return alloc_estate_sval(sval);
81 }
82 
83 static struct range_list *size_to_rl(int size)
84 {
85 	sval_t sval;
86 
87 	sval.type = &int_ctype;
88 	sval.value = size;
89 
90 	return alloc_rl(sval, sval);
91 }
92 
93 static struct smatch_state *unmatched_size_state(struct sm_state *sm)
94 {
95 	return size_to_estate(UNKNOWN_SIZE);
96 }
97 
98 static void set_size_undefined(struct sm_state *sm, struct expression *mod_expr)
99 {
100 	set_state(sm->owner, sm->name, sm->sym, size_to_estate(UNKNOWN_SIZE));
101 }
102 
103 static struct smatch_state *merge_size_func(struct smatch_state *s1, struct smatch_state *s2)
104 {
105 	return merge_estates(s1, s2);
106 }
107 
108 void set_param_buf_size(const char *name, struct symbol *sym, char *key, char *value)
109 {
110 	struct range_list *rl = NULL;
111 	struct smatch_state *state;
112 	char fullname[256];
113 
114 	if (strncmp(key, "$", 1) != 0)
115 		return;
116 
117 	snprintf(fullname, 256, "%s%s", name, key + 1);
118 
119 	str_to_rl(&int_ctype, value, &rl);
120 	if (!rl || is_whole_rl(rl))
121 		return;
122 	state = alloc_estate_rl(rl);
123 	set_state(my_size_id, fullname, sym, state);
124 }
125 
126 static int bytes_per_element(struct expression *expr)
127 {
128 	struct symbol *type;
129 
130 	if (!expr)
131 		return 0;
132 	if (expr->type == EXPR_STRING)
133 		return 1;
134 	if (expr->type == EXPR_PREOP && expr->op == '&') {
135 		type = get_type(expr->unop);
136 		if (type && type->type == SYM_ARRAY)
137 			expr = expr->unop;
138 	}
139 	type = get_type(expr);
140 	if (!type)
141 		return 0;
142 
143 	if (type->type != SYM_PTR && type->type != SYM_ARRAY)
144 		return 0;
145 
146 	type = get_base_type(type);
147 	return type_bytes(type);
148 }
149 
150 static int bytes_to_elements(struct expression *expr, int bytes)
151 {
152 	int bpe;
153 
154 	bpe = bytes_per_element(expr);
155 	if (bpe == 0)
156 		return 0;
157 	return bytes / bpe;
158 }
159 
160 static int elements_to_bytes(struct expression *expr, int elements)
161 {
162 	int bpe;
163 
164 	bpe = bytes_per_element(expr);
165 	return elements * bpe;
166 }
167 
168 static int get_initializer_size(struct expression *expr)
169 {
170 	switch (expr->type) {
171 	case EXPR_STRING:
172 		return expr->string->length;
173 	case EXPR_INITIALIZER: {
174 		struct expression *tmp;
175 		int i = 0;
176 
177 		FOR_EACH_PTR(expr->expr_list, tmp) {
178 			if (tmp->type == EXPR_INDEX) {
179 				if (tmp->idx_to >= i)
180 					i = tmp->idx_to;
181 				else
182 					continue;
183 			}
184 
185 			i++;
186 		} END_FOR_EACH_PTR(tmp);
187 		return i;
188 	}
189 	case EXPR_SYMBOL:
190 		return get_array_size(expr);
191 	}
192 	return 0;
193 }
194 
195 static struct range_list *db_size_rl;
196 static int db_size_callback(void *unused, int argc, char **argv, char **azColName)
197 {
198 	struct range_list *tmp = NULL;
199 
200 	if (!db_size_rl) {
201 		str_to_rl(&int_ctype, argv[0], &db_size_rl);
202 	} else {
203 		str_to_rl(&int_ctype, argv[0], &tmp);
204 		db_size_rl = rl_union(db_size_rl, tmp);
205 	}
206 	return 0;
207 }
208 
209 static struct range_list *size_from_db_type(struct expression *expr)
210 {
211 	int this_file_only = 0;
212 	char *name;
213 
214 	name = get_member_name(expr);
215 	if (!name && is_static(expr)) {
216 		name = expr_to_var(expr);
217 		this_file_only = 1;
218 	}
219 	if (!name)
220 		return NULL;
221 
222 	if (this_file_only) {
223 		db_size_rl = NULL;
224 		run_sql(db_size_callback, NULL,
225 			"select size from function_type_size where type = '%s' and file = '%s';",
226 			name, get_filename());
227 		if (db_size_rl)
228 			return db_size_rl;
229 		return NULL;
230 	}
231 
232 	db_size_rl = NULL;
233 	run_sql(db_size_callback, NULL,
234 		"select size from type_size where type = '%s';",
235 		name);
236 	return db_size_rl;
237 }
238 
239 static struct range_list *size_from_db_symbol(struct expression *expr)
240 {
241 	struct symbol *sym;
242 
243 	if (expr->type != EXPR_SYMBOL)
244 		return NULL;
245 	sym = expr->symbol;
246 	if (!sym || !sym->ident ||
247 	    !(sym->ctype.modifiers & MOD_TOPLEVEL) ||
248 	    sym->ctype.modifiers & MOD_STATIC)
249 		return NULL;
250 
251 	db_size_rl = NULL;
252 	run_sql(db_size_callback, NULL,
253 		"select value from data_info where file = 'extern' and data = '%s' and type = %d;",
254 		sym->ident->name, BUF_SIZE);
255 	return db_size_rl;
256 }
257 
258 static struct range_list *size_from_db(struct expression *expr)
259 {
260 	struct range_list *rl;
261 
262 	rl = size_from_db_symbol(expr);
263 	if (rl)
264 		return rl;
265 	return size_from_db_type(expr);
266 }
267 
268 static void db_returns_buf_size(struct expression *expr, int param, char *unused, char *math)
269 {
270 	struct expression *call;
271 	struct range_list *rl;
272 
273 	if (expr->type != EXPR_ASSIGNMENT)
274 		return;
275 	call = strip_expr(expr->right);
276 
277 	if (!parse_call_math_rl(call, math, &rl))
278 		return;
279 	rl = cast_rl(&int_ctype, rl);
280 	set_state_expr(my_size_id, expr->left, alloc_estate_rl(rl));
281 }
282 
283 static int get_real_array_size_from_type(struct symbol *type)
284 {
285 	sval_t sval;
286 
287 	if (!type)
288 		return 0;
289 	if (!type || type->type != SYM_ARRAY)
290 		return 0;
291 
292 	if (!get_implied_value(type->array_size, &sval))
293 		return 0;
294 
295 	return sval.value;
296 }
297 
298 int get_real_array_size(struct expression *expr)
299 {
300 	if (!expr)
301 		return 0;
302 	if (expr->type == EXPR_PREOP && expr->op == '&')
303 		expr = expr->unop;
304 	if (expr->type == EXPR_BINOP) /* array elements foo[5] */
305 		return 0;
306 	return get_real_array_size_from_type(get_type(expr));
307 }
308 
309 static int get_size_from_initializer(struct expression *expr)
310 {
311 	if (expr->type != EXPR_SYMBOL || !expr->symbol || !expr->symbol->initializer)
312 		return 0;
313 	if (expr->symbol->initializer == expr) /* int a = a; */
314 		return 0;
315 	return get_initializer_size(expr->symbol->initializer);
316 }
317 
318 static struct range_list *get_stored_size_bytes(struct expression *expr)
319 {
320 	struct smatch_state *state;
321 
322 	state = get_state_expr(my_size_id, expr);
323 	if (!state)
324 		return NULL;
325 	return estate_rl(state);
326 }
327 
328 static int get_bytes_from_address(struct expression *expr)
329 {
330 	struct symbol *type;
331 	int ret;
332 
333 	if (expr->type != EXPR_PREOP || expr->op != '&')
334 		return 0;
335 	type = get_type(expr);
336 	if (!type)
337 		return 0;
338 
339 	if (type->type == SYM_PTR)
340 		type = get_base_type(type);
341 
342 	ret = type_bytes(type);
343 	if (ret == 1)
344 		return 0;  /* ignore char pointers */
345 
346 	return ret;
347 }
348 
349 static struct expression *remove_addr_fluff(struct expression *expr)
350 {
351 	struct expression *tmp;
352 	sval_t sval;
353 
354 	expr = strip_expr(expr);
355 
356 	/* remove '&' and '*' operations that cancel */
357 	while (expr && expr->type == EXPR_PREOP && expr->op == '&') {
358 		tmp = strip_expr(expr->unop);
359 		if (tmp->type != EXPR_PREOP)
360 			break;
361 		if (tmp->op != '*')
362 			break;
363 		expr = strip_expr(tmp->unop);
364 	}
365 
366 	if (!expr)
367 		return NULL;
368 
369 	/* "foo + 0" is just "foo" */
370 	if (expr->type == EXPR_BINOP && expr->op == '+' &&
371 	    get_value(expr->right, &sval) && sval.value == 0)
372 		return expr->left;
373 
374 	return expr;
375 }
376 
377 static int is_last_member_of_struct(struct symbol *sym, struct ident *member)
378 {
379 	struct symbol *tmp;
380 	int i;
381 
382 	i = 0;
383 	FOR_EACH_PTR_REVERSE(sym->symbol_list, tmp) {
384 		if (i++ || !tmp->ident)
385 			return 0;
386 		if (tmp->ident == member)
387 			return 1;
388 		return 0;
389 	} END_FOR_EACH_PTR_REVERSE(tmp);
390 
391 	return 0;
392 }
393 
394 int last_member_is_resizable(struct symbol *sym)
395 {
396 	struct symbol *last_member;
397 	struct symbol *type;
398 	sval_t sval;
399 
400 	if (!sym || sym->type != SYM_STRUCT)
401 		return 0;
402 
403 	last_member = last_ptr_list((struct ptr_list *)sym->symbol_list);
404 	if (!last_member || !last_member->ident)
405 		return 0;
406 
407 	type = get_real_base_type(last_member);
408 	if (type->type == SYM_STRUCT)
409 		return last_member_is_resizable(type);
410 	if (type->type != SYM_ARRAY)
411 		return 0;
412 
413 	if (!get_implied_value(type->array_size, &sval))
414 		return 0;
415 
416 	if (sval.value != 0 && sval.value != 1)
417 		return 0;
418 
419 	return 1;
420 }
421 
422 static int get_stored_size_end_struct_bytes(struct expression *expr)
423 {
424 	struct symbol *sym;
425 	struct symbol *base_sym;
426 	struct smatch_state *state;
427 
428 	if (expr->type == EXPR_BINOP) /* array elements foo[5] */
429 		return 0;
430 
431 	if (expr->type == EXPR_PREOP && expr->op == '&')
432 		expr = strip_parens(expr->unop);
433 
434 	sym = expr_to_sym(expr);
435 	if (!sym || !sym->ident)
436 		return 0;
437 	if (!type_bytes(sym))
438 		return 0;
439 	if (sym->type != SYM_NODE)
440 		return 0;
441 
442 	base_sym = get_real_base_type(sym);
443 	if (!base_sym || base_sym->type != SYM_PTR)
444 		return 0;
445 	base_sym = get_real_base_type(base_sym);
446 	if (!base_sym || base_sym->type != SYM_STRUCT)
447 		return 0;
448 
449 	if (!is_last_member_of_struct(base_sym, expr->member))
450 		return 0;
451 	if (!last_member_is_resizable(base_sym))
452 		return 0;
453 
454 	state = get_state(my_size_id, sym->ident->name, sym);
455 	if (!estate_to_size(state))
456 		return 0;
457 
458 	return estate_to_size(state) - type_bytes(base_sym) + type_bytes(get_type(expr));
459 }
460 
461 static struct range_list *alloc_int_rl(int value)
462 {
463 	sval_t sval = {
464 		.type = &int_ctype,
465 		{.value = value},
466 	};
467 
468 	return alloc_rl(sval, sval);
469 }
470 
471 struct range_list *get_array_size_bytes_rl(struct expression *expr)
472 {
473 	struct range_list *ret = NULL;
474 	int size;
475 
476 	expr = remove_addr_fluff(expr);
477 	if (!expr)
478 		return NULL;
479 
480 	/* "BAR" */
481 	if (expr->type == EXPR_STRING)
482 		return alloc_int_rl(expr->string->length);
483 
484 	if (expr->type == EXPR_BINOP && expr->op == '+') {
485 		sval_t offset;
486 		struct symbol *type;
487 		int bytes;
488 
489 		if (!get_implied_value(expr->right, &offset))
490 			return NULL;
491 		type = get_type(expr->left);
492 		if (!type)
493 			return NULL;
494 		if (type->type != SYM_ARRAY && type->type != SYM_PTR)
495 			return NULL;
496 		type = get_real_base_type(type);
497 		bytes = type_bytes(type);
498 		if (bytes == 0)
499 			return NULL;
500 		offset.value *= bytes;
501 		size = get_array_size_bytes(expr->left);
502 		if (size <= 0)
503 			return NULL;
504 		return alloc_int_rl(size - offset.value);
505 	}
506 
507 	size = get_stored_size_end_struct_bytes(expr);
508 	if (size)
509 		return alloc_int_rl(size);
510 
511 	/* buf[4] */
512 	size = get_real_array_size(expr);
513 	if (size)
514 		return alloc_int_rl(elements_to_bytes(expr, size));
515 
516 	/* buf = malloc(1024); */
517 	ret = get_stored_size_bytes(expr);
518 	if (ret)
519 		return ret;
520 
521 	/* char *foo = "BAR" */
522 	size = get_size_from_initializer(expr);
523 	if (size)
524 		return alloc_int_rl(elements_to_bytes(expr, size));
525 
526 	size = get_bytes_from_address(expr);
527 	if (size)
528 		return alloc_int_rl(size);
529 
530 	ret = size_from_db(expr);
531 	if (ret)
532 		return ret;
533 
534 	return NULL;
535 }
536 
537 int get_array_size_bytes(struct expression *expr)
538 {
539 	struct range_list *rl;
540 	sval_t sval;
541 
542 	rl = get_array_size_bytes_rl(expr);
543 	if (!rl_to_sval(rl, &sval))
544 		return 0;
545 	if (sval.uvalue >= INT_MAX)
546 		return 0;
547 	return sval.value;
548 }
549 
550 int get_array_size_bytes_max(struct expression *expr)
551 {
552 	struct range_list *rl;
553 	sval_t bytes;
554 
555 	rl = get_array_size_bytes_rl(expr);
556 	if (!rl)
557 		return 0;
558 	bytes = rl_min(rl);
559 	if (bytes.value < 0)
560 		return 0;
561 	bytes = rl_max(rl);
562 	if (bytes.uvalue >= INT_MAX)
563 		return 0;
564 	return bytes.value;
565 }
566 
567 int get_array_size_bytes_min(struct expression *expr)
568 {
569 	struct range_list *rl;
570 	struct data_range *range;
571 
572 	rl = get_array_size_bytes_rl(expr);
573 	if (!rl)
574 		return 0;
575 
576 	FOR_EACH_PTR(rl, range) {
577 		if (range->min.value <= 0)
578 			return 0;
579 		if (range->max.value <= 0)
580 			return 0;
581 		if (range->min.uvalue >= INT_MAX)
582 			return 0;
583 		return range->min.value;
584 	} END_FOR_EACH_PTR(range);
585 
586 	return 0;
587 }
588 
589 int get_array_size(struct expression *expr)
590 {
591 	if (!expr)
592 		return 0;
593 	return bytes_to_elements(expr, get_array_size_bytes_max(expr));
594 }
595 
596 static struct expression *strip_ampersands(struct expression *expr)
597 {
598 	struct symbol *type;
599 
600 	if (expr->type != EXPR_PREOP)
601 		return expr;
602 	if (expr->op != '&')
603 		return expr;
604 	type = get_type(expr->unop);
605 	if (!type || type->type != SYM_ARRAY)
606 		return expr;
607 	return expr->unop;
608 }
609 
610 static void info_record_alloction(struct expression *buffer, struct range_list *rl)
611 {
612 	char *name;
613 
614 	if (!option_info)
615 		return;
616 
617 	name = get_member_name(buffer);
618 	if (!name && is_static(buffer))
619 		name = expr_to_var(buffer);
620 	if (!name)
621 		return;
622 	if (rl && !is_whole_rl(rl))
623 		sql_insert_function_type_size(name, show_rl(rl));
624 	else
625 		sql_insert_function_type_size(name, "(-1)");
626 
627 	free_string(name);
628 }
629 
630 static void store_alloc(struct expression *expr, struct range_list *rl)
631 {
632 	struct symbol *type;
633 
634 	rl = clone_rl(rl); // FIXME!!!
635 	set_state_expr(my_size_id, expr, alloc_estate_rl(rl));
636 
637 	type = get_type(expr);
638 	if (!type)
639 		return;
640 	if (type->type != SYM_PTR)
641 		return;
642 	type = get_real_base_type(type);
643 	if (!type)
644 		return;
645 	if (type == &void_ctype)
646 		return;
647 	if (type->type != SYM_BASETYPE && type->type != SYM_PTR)
648 		return;
649 
650 	info_record_alloction(expr, rl);
651 }
652 
653 static void match_array_assignment(struct expression *expr)
654 {
655 	struct expression *left;
656 	struct expression *right;
657 	char *left_member, *right_member;
658 	struct range_list *rl;
659 	sval_t sval;
660 
661 	if (expr->op != '=')
662 		return;
663 	left = strip_expr(expr->left);
664 	right = strip_expr(expr->right);
665 	right = strip_ampersands(right);
666 
667 	if (!is_pointer(left))
668 		return;
669 	if (is_allocation_function(right))
670 		return;
671 
672 	left_member = get_member_name(left);
673 	right_member = get_member_name(right);
674 	if (left_member && right_member && strcmp(left_member, right_member) == 0) {
675 		free_string(left_member);
676 		free_string(right_member);
677 		return;
678 	}
679 	free_string(left_member);
680 	free_string(right_member);
681 
682 	if (get_implied_value(right, &sval) && sval.value == 0) {
683 		rl = alloc_int_rl(0);
684 		goto store;
685 	}
686 
687 	rl = get_array_size_bytes_rl(right);
688 	if (!rl && __in_fake_assign)
689 		return;
690 
691 store:
692 	store_alloc(left, rl);
693 }
694 
695 static void match_alloc(const char *fn, struct expression *expr, void *_size_arg)
696 {
697 	int size_arg = PTR_INT(_size_arg);
698 	struct expression *right;
699 	struct expression *arg;
700 	struct range_list *rl;
701 
702 	right = strip_expr(expr->right);
703 	arg = get_argument_from_call_expr(right->args, size_arg);
704 	get_absolute_rl(arg, &rl);
705 	rl = cast_rl(&int_ctype, rl);
706 	store_alloc(expr->left, rl);
707 }
708 
709 static void match_calloc(const char *fn, struct expression *expr, void *unused)
710 {
711 	struct expression *right;
712 	struct expression *size, *nr, *mult;
713 	struct range_list *rl;
714 
715 	right = strip_expr(expr->right);
716 	nr = get_argument_from_call_expr(right->args, 0);
717 	size = get_argument_from_call_expr(right->args, 1);
718 	mult = binop_expression(nr, '*', size);
719 	if (get_implied_rl(mult, &rl))
720 		store_alloc(expr->left, rl);
721 	else
722 		store_alloc(expr->left, size_to_rl(-1));
723 }
724 
725 static void match_page(const char *fn, struct expression *expr, void *_unused)
726 {
727 	sval_t page_size = {
728 		.type = &int_ctype,
729 		{.value = 4096},
730 	};
731 
732 	store_alloc(expr->left, alloc_rl(page_size, page_size));
733 }
734 
735 static void match_strndup(const char *fn, struct expression *expr, void *unused)
736 {
737 	struct expression *fn_expr;
738 	struct expression *size_expr;
739 	sval_t size;
740 
741 	fn_expr = strip_expr(expr->right);
742 	size_expr = get_argument_from_call_expr(fn_expr->args, 1);
743 	if (get_implied_max(size_expr, &size)) {
744 		size.value++;
745 		store_alloc(expr->left, size_to_rl(size.value));
746 	} else {
747 		store_alloc(expr->left, size_to_rl(-1));
748 	}
749 
750 }
751 
752 static void match_alloc_pages(const char *fn, struct expression *expr, void *_order_arg)
753 {
754 	int order_arg = PTR_INT(_order_arg);
755 	struct expression *right;
756 	struct expression *arg;
757 	sval_t sval;
758 
759 	right = strip_expr(expr->right);
760 	arg = get_argument_from_call_expr(right->args, order_arg);
761 	if (!get_implied_value(arg, &sval))
762 		return;
763 	if (sval.value < 0 || sval.value > 10)
764 		return;
765 
766 	sval.type = &int_ctype;
767 	sval.value = 1 << sval.value;
768 	sval.value *= 4096;
769 
770 	store_alloc(expr->left, alloc_rl(sval, sval));
771 }
772 
773 static int is_type_bytes(struct range_list *rl, struct expression *arg)
774 {
775 	struct symbol *type;
776 	sval_t sval;
777 
778 	if (!rl_to_sval(rl, &sval))
779 		return 0;
780 
781 	type = get_type(arg);
782 	if (!type)
783 		return 0;
784 	if (type->type != SYM_PTR)
785 		return 0;
786 	type = get_real_base_type(type);
787 	if (type->type != SYM_STRUCT &&
788 	    type->type != SYM_UNION)
789 		return 0;
790 	if (sval.value != type_bytes(type))
791 		return 0;
792 	return 1;
793 }
794 
795 static void match_call(struct expression *expr)
796 {
797 	struct expression *arg;
798 	struct symbol *type;
799 	struct range_list *rl;
800 	int i;
801 
802 	i = -1;
803 	FOR_EACH_PTR(expr->args, arg) {
804 		i++;
805 		type = get_type(arg);
806 		if (!type || (type->type != SYM_PTR && type->type != SYM_ARRAY))
807 			continue;
808 		rl = get_array_size_bytes_rl(arg);
809 		if (!rl)
810 			continue;
811 		if (is_whole_rl(rl))
812 			continue;
813 		if (is_type_bytes(rl, arg))
814 			continue;
815 		sql_insert_caller_info(expr, BUF_SIZE, i, "$", show_rl(rl));
816 	} END_FOR_EACH_PTR(arg);
817 }
818 
819 static void struct_member_callback(struct expression *call, int param, char *printed_name, struct sm_state *sm)
820 {
821 	if (sm->state == &merged ||
822 	    strcmp(sm->state->name, "(-1)") == 0 ||
823 	    strcmp(sm->state->name, "empty") == 0 ||
824 	    strcmp(sm->state->name, "0") == 0)
825 		return;
826 	sql_insert_caller_info(call, BUF_SIZE, param, printed_name, sm->state->name);
827 }
828 
829 /*
830  * This is slightly (very) weird because half of this stuff is handled in
831  * smatch_parse_call_math.c which is poorly named.  But anyway, add some buf
832  * sizes here.
833  *
834  */
835 static void print_returned_allocations(int return_id, char *return_ranges, struct expression *expr)
836 {
837 	char buf[16];
838 	int size;
839 
840 	size = get_array_size_bytes(expr);
841 	if (!size)
842 		return;
843 
844 	snprintf(buf, sizeof(buf), "%d", size);
845 	sql_insert_return_states(return_id, return_ranges, BUF_SIZE, -1, "", buf);
846 }
847 
848 static void record_global_size(struct symbol *sym)
849 {
850 	int bytes;
851 	char buf[16];
852 
853 	if (!sym->ident)
854 		return;
855 
856 	if (!(sym->ctype.modifiers & MOD_TOPLEVEL) ||
857 	    sym->ctype.modifiers & MOD_STATIC)
858 		return;
859 
860 	bytes = get_array_size_bytes(symbol_expression(sym));
861 	if (bytes <= 1)
862 		return;
863 
864 	snprintf(buf, sizeof(buf), "%d", bytes);
865 	sql_insert_data_info_var_sym(sym->ident->name, sym, BUF_SIZE, buf);
866 }
867 
868 void register_buf_size(int id)
869 {
870 	my_size_id = id;
871 
872 	set_dynamic_states(my_size_id);
873 
874 	add_unmatched_state_hook(my_size_id, &unmatched_size_state);
875 
876 	select_caller_info_hook(set_param_buf_size, BUF_SIZE);
877 	select_return_states_hook(BUF_SIZE, &db_returns_buf_size);
878 	add_split_return_callback(print_returned_allocations);
879 
880 	allocation_funcs = create_function_hashtable(100);
881 	add_allocation_function("malloc", &match_alloc, 0);
882 	add_allocation_function("calloc", &match_calloc, 0);
883 	add_allocation_function("memdup", &match_alloc, 1);
884 	add_allocation_function("realloc", &match_alloc, 1);
885 	if (option_project == PROJ_KERNEL) {
886 		add_allocation_function("kmalloc", &match_alloc, 0);
887 		add_allocation_function("kmalloc_node", &match_alloc, 0);
888 		add_allocation_function("kzalloc", &match_alloc, 0);
889 		add_allocation_function("kzalloc_node", &match_alloc, 0);
890 		add_allocation_function("vmalloc", &match_alloc, 0);
891 		add_allocation_function("__vmalloc", &match_alloc, 0);
892 		add_allocation_function("kcalloc", &match_calloc, 0);
893 		add_allocation_function("kmalloc_array", &match_calloc, 0);
894 		add_allocation_function("drm_malloc_ab", &match_calloc, 0);
895 		add_allocation_function("drm_calloc_large", &match_calloc, 0);
896 		add_allocation_function("sock_kmalloc", &match_alloc, 1);
897 		add_allocation_function("kmemdup", &match_alloc, 1);
898 		add_allocation_function("kmemdup_user", &match_alloc, 1);
899 		add_allocation_function("dma_alloc_attrs", &match_alloc, 1);
900 		add_allocation_function("pci_alloc_consistent", &match_alloc, 1);
901 		add_allocation_function("pci_alloc_coherent", &match_alloc, 1);
902 		add_allocation_function("devm_kmalloc", &match_alloc, 1);
903 		add_allocation_function("devm_kzalloc", &match_alloc, 1);
904 		add_allocation_function("krealloc", &match_alloc, 1);
905 		add_allocation_function("__alloc_bootmem", &match_alloc, 0);
906 		add_allocation_function("alloc_bootmem", &match_alloc, 0);
907 		add_allocation_function("kmap", &match_page, 0);
908 		add_allocation_function("get_zeroed_page", &match_page, 0);
909 		add_allocation_function("alloc_page", &match_page, 0);
910 		add_allocation_function("page_address", &match_page, 0);
911 		add_allocation_function("lowmem_page_address", &match_page, 0);
912 		add_allocation_function("alloc_pages", &match_alloc_pages, 1);
913 		add_allocation_function("alloc_pages_current", &match_alloc_pages, 1);
914 		add_allocation_function("__get_free_pages", &match_alloc_pages, 1);
915 	}
916 
917 	add_allocation_function("strndup", match_strndup, 0);
918 	if (option_project == PROJ_KERNEL)
919 		add_allocation_function("kstrndup", match_strndup, 0);
920 
921 	add_modification_hook(my_size_id, &set_size_undefined);
922 
923 	add_merge_hook(my_size_id, &merge_size_func);
924 
925 	if (option_info)
926 		add_hook(record_global_size, BASE_HOOK);
927 }
928 
929 void register_buf_size_late(int id)
930 {
931 	/* has to happen after match_alloc() */
932 	add_hook(&match_array_assignment, ASSIGNMENT_HOOK);
933 
934 	add_hook(&match_call, FUNCTION_CALL_HOOK);
935 	add_member_info_callback(my_size_id, struct_member_callback);
936 }
937