2 * Copyright (C) 2014 Oracle.
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.
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.
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
24 static void match_assign(struct expression
*expr
)
26 struct symbol
*left_type
, *right_type
;
27 struct expression
*size_expr
;
30 left_type
= get_type(expr
->left
);
31 if (!left_type
|| left_type
->type
!= SYM_PTR
)
33 left_type
= get_real_base_type(left_type
);
34 if (!left_type
|| left_type
->type
!= SYM_STRUCT
)
37 right_type
= get_type(expr
->right
);
38 if (!right_type
|| right_type
->type
!= SYM_PTR
)
40 right_type
= get_real_base_type(right_type
);
43 if (right_type
!= &void_ctype
&& type_bits(right_type
) != 8)
46 size_expr
= get_size_variable(expr
->right
);
50 get_absolute_min(size_expr
, &min_size
);
51 if (min_size
.value
>= type_bytes(left_type
))
54 set_state_expr(my_id
, expr
->left
, &too_small
);
57 static void match_dereferences(struct expression
*expr
)
59 struct symbol
*left_type
;
60 struct expression
*right
;
61 struct smatch_state
*state
;
63 struct expression
*size_expr
;
66 if (expr
->type
!= EXPR_PREOP
)
69 expr
= strip_expr(expr
->unop
);
70 state
= get_state_expr(my_id
, expr
);
71 if (state
!= &too_small
)
74 left_type
= get_type(expr
);
75 if (!left_type
|| left_type
->type
!= SYM_PTR
)
77 left_type
= get_real_base_type(left_type
);
78 if (!left_type
|| left_type
->type
!= SYM_STRUCT
)
81 right
= get_assigned_expr(expr
);
82 size_expr
= get_size_variable(right
);
86 get_absolute_min(size_expr
, &min_size
);
87 if (min_size
.value
>= type_bytes(left_type
))
90 name
= expr_to_str(right
);
91 sm_msg("warn: is '%s' large enough for 'struct %s'? %s", name
, left_type
->ident
? left_type
->ident
->name
: "<anon>", sval_to_str(min_size
));
93 set_state_expr(my_id
, expr
, &undefined
);
96 void check_buffer_too_small_for_struct(int id
)
100 add_hook(&match_assign
, ASSIGNMENT_HOOK
);
101 add_hook(&match_dereferences
, DEREF_HOOK
);