Ejemplo n.º 1
0
static void match_dma_func(const char *fn, struct expression *expr, void *param)
{
	struct expression *arg;
	struct symbol *sym;
	char *name;

	arg = get_argument_from_call_expr(expr->args, PTR_INT(param));
	arg = strip_expr(arg);
	if (!arg)
		return;
	if (arg->type == EXPR_PREOP && arg->op == '&') {
		if (arg->unop->type != EXPR_SYMBOL)
			return;
		name = expr_to_str(arg);
		sm_msg("error: doing dma on the stack (%s)", name);
		free_string(name);
		return;
	}
	if (arg->type != EXPR_SYMBOL)
		return;
	sym = get_type(arg);
	if (!sym || sym->type != SYM_ARRAY)
		return;
	name = expr_to_var(arg);
	sm_msg("error: doing dma on the stack (%s)", name);
	free_string(name);
}
Ejemplo n.º 2
0
static void match_return(struct expression *ret_value)
{
	struct expression *expr;
	char *macro;

	if (!ret_value)
		return;
	expr = ret_value;
	if (ret_value->type != EXPR_PREOP || ret_value->op != '-')
		return;

	macro = get_macro_name(expr->unop->pos);
	if (macro && !strcmp(macro, "PTR_ERR")) {
		sm_msg("warn: returning -%s()", macro);
		return;
	}

	if (!option_spammy)
		return;

	expr = get_assigned_expr(ret_value->unop);
	if (!expr)
		return;
	if (expr->type != EXPR_CALL)
		return;

	sm_msg("warn: should this return really be negated?");
}
Ejemplo n.º 3
0
static void match_loop(struct statement *stmt)
{
	struct expression *iterator;
	char *iter_set;
	char *iter_tested;

	if (get_macro_name(stmt->pos))
		return;

	iterator = get_iterator_set(stmt->iterator_pre_statement);
	iter_set = expr_to_var(iterator);
	iterator = get_iterator_tested(stmt->iterator_pre_condition);
	iter_tested = expr_to_var(iterator);
	if (!iter_set || !iter_tested)
		goto free;
	if (strcmp(iter_set, iter_tested))
		goto free;

	/* smatch doesn't handle loops correctly so this silences some
	 * false positives.
	 */
	if (right_side_changes(stmt->iterator_pre_condition))
		goto free;

	if (implied_condition_false(stmt->iterator_pre_condition))
		sm_msg("warn: we never enter this loop");

free:
	free_string(iter_set);
	free_string(iter_tested);
}
Ejemplo n.º 4
0
static void print_missing_break(struct expression *expr)
{
	char *name;

	if (get_switch_expr() == last_print_expr)
		return;
	last_print_expr = get_switch_expr();

	name = expr_to_var(expr);
	sm_msg("warn: missing break? reassigning '%s'", name);
	free_string(name);
}
Ejemplo n.º 5
0
static void check_size_matches(int data_size, struct expression *size_expr)
{
	sval_t sval;

	if (data_size == 1)  /* this is generic a buffer */
		return;

	if (!get_implied_value(size_expr, &sval))
		return;
	if (sval_cmp_val(sval, data_size) != 0)
		sm_msg("warn: double check that we're allocating correct size: %d vs %s", data_size, sval_to_str(sval));
}
Ejemplo n.º 6
0
static void verify_size_expr(struct expression *expr)
{
	if (expr->type != EXPR_BINOP)
		return;
	if (expr->op != '-')
		return;
	if (is_probably_ok(expr->left))
		return;
	if (is_probably_ok(expr->right))
		return;
	sm_msg("warn: consider using resource_size() here");
}
Ejemplo n.º 7
0
static void match_strcpy(const char *fn, struct expression *expr, void *unused)
{
	struct expression *dest;
	struct expression *data;
	char *dest_name = NULL;
	char *data_name = NULL;
	int dest_size;
	int data_size;

	dest = get_argument_from_call_expr(expr->args, 0);
	data = get_argument_from_call_expr(expr->args, 1);
	dest_size = get_array_size_bytes(dest);
	if (!dest_size)
		return;

	data_size = get_size_from_strlen(data);
	if (!data_size)
		data_size = get_array_size_bytes(data);

	/* If the size of both arrays is known and the destination
	 * buffer is larger than the source buffer, we're okay.
	 */
	if (data_size && dest_size >= data_size)
		return;

	dest_name = expr_to_str(dest);
	data_name = expr_to_str(data);

	if (data_size)
		sm_msg("error: %s() '%s' too large for '%s' (%d vs %d)",
			fn, data_name, dest_name, data_size, dest_size);
	else if (option_spammy)
		sm_msg("warn: %s() '%s' of unknown size might be too large for '%s'",
			fn, data_name, dest_name);

	free_string(dest_name);
	free_string(data_name);
}
Ejemplo n.º 8
0
static void match_condition(struct expression *expr)
{
	if (expr->type == EXPR_ASSIGNMENT)
		match_condition(expr->left);

	if (get_state_expr(my_id, expr) == &filehandle) {
		char *name;

		name = expr_to_var(expr);
		sm_msg("error: comparing a filehandle against zero '%s'", name);
		set_state_expr(my_id, expr, &oktocheck);
		free_string(name);
	}
}
Ejemplo n.º 9
0
static void check_for_held(void)
{
	struct state_list *slist;
	struct sm_state *tmp;

	slist = get_all_states(my_id);
	FOR_EACH_PTR(slist, tmp) {
		if (slist_has_state(tmp->possible, &held)) {
			sm_msg("warn: '%s' held on error path.",
				tmp->name);
		}
	} END_FOR_EACH_PTR(tmp);
	free_slist(&slist);
}
Ejemplo n.º 10
0
static void match_binop(struct expression *expr)
{
	sval_t left, right, sval;

	if (expr->op != '&')
		return;
	if (!get_value(expr, &sval) || sval.value != 0)
		return;
	if (get_macro_name(expr->pos))
		return;
	if (!get_value(expr->left, &left) || !get_value(expr->right, &right))
		return;
	sm_msg("warn: odd binop '0x%llx & 0x%llx'", left.uvalue, right.uvalue);
}
Ejemplo n.º 11
0
static void check_expr(struct expression *expr)
{
	struct sm_state *sm;
	sval_t max;
	sval_t sval;
	char *name;
	int overflow = 0;
	int underflow = 0;

	sm = get_sm_state_expr(my_max_id, expr);
	if (sm && slist_has_state(sm->possible, &user_data)) {
		if (!get_absolute_max(expr, &max) || sval_cmp_val(max, 20000) > 0)
			overflow = 1;
	}

	sm = get_sm_state_expr(my_min_id, expr);
	if (sm && slist_has_state(sm->possible, &user_data)) {
		if (!get_absolute_min(expr, &sval) ||
		    (sval_is_negative(sval) && sval_cmp_val(sval, -20000) < 0))
			underflow = 1;
	}

	if (!overflow && !underflow)
		return;

	name = expr_to_var_sym(expr, NULL);
	if (overflow && underflow)
		sm_msg("warn: check for integer over/underflow '%s'", name);
	else if (underflow)
		sm_msg("warn: check for integer underflow '%s'", name);
	else
		sm_msg("warn: check for integer overflow '%s'", name);
	free_string(name);

	set_state_expr(my_max_id, expr, &capped);
	set_state_expr(my_min_id, expr, &capped);
}
Ejemplo n.º 12
0
static void match_condition(struct expression *expr)
{
	sval_t sval;

	if (expr->type != EXPR_BINOP)
		return;
	if (expr->op == '|') {
		if (get_value(expr->left, &sval) || get_value(expr->right, &sval))
			sm_msg("warn: suspicious bitop condition");
		return;
	}

	if (expr->op != '&')
		return;

	if (get_macro_name(expr->pos))
		return;
	if (is_unconstant_macro(expr->left) || is_unconstant_macro(expr->right))
		return;

	if ((get_value(expr->left, &sval) && sval.value == 0) ||
	    (get_value(expr->right, &sval) && sval.value == 0))
		sm_msg("warn: bitwise AND condition is false here");
}
Ejemplo n.º 13
0
static void match_free(const char *fn, struct expression *expr, void *data)
{
	struct expression *arg_expr;
	char *name;
	sval_t sval;

	arg_expr = get_argument_from_call_expr(expr->args, 0);
	if (!get_implied_value(arg_expr, &sval))
		return;
	if (sval.value != 0)
		return;
	name = expr_to_var(arg_expr);
	sm_msg("warn: calling %s() when '%s' is always NULL.", fn, name);
	free_string(name);
}
Ejemplo n.º 14
0
static void match_binop(struct expression *expr)
{
	const char *name;

	if (positions_eq(expr->pos, expr->right->pos))
		return;
	if (expr->op != '&')
		return;
	name = get_shifter(expr->right);
	if (!name)
		return;

	sm_msg("warn: bit shifter '%s' used for logical '%s'",
			name, show_special(expr->op));
}
Ejemplo n.º 15
0
static void match_assign(struct expression *expr)
{
	const char *name;

	if (expr->op != SPECIAL_OR_ASSIGN)
		return;
	if (positions_eq(expr->pos, expr->right->pos))
		return;
	name = get_shifter(expr->right);
	if (!name)
		return;

	sm_msg("warn: '%s' is a shifter (not for '%s').",
			name, show_special(expr->op));
}
Ejemplo n.º 16
0
static void match_inside(struct expression *expr, struct position pos)
{
	char *name;
	int matched = 0;

	if (positions_eq(expr->pos, pos))
		matched++;
	if (positions_eq(expr->unop->pos, pos))
		matched++;
	if (matched != 1)
		return;
	name = get_macro_name(pos);
	if (!name)
		return;
	sm_msg("warn: the '%s' macro might need parens", name);
}
Ejemplo n.º 17
0
static void match_condition(struct expression *expr)
{
	struct symbol *type;
	char *str;

	if (expr->type != EXPR_DEREF)
		return;
	type = get_type(expr);
	if (!type || type->type != SYM_ARRAY)
		return;
	if (get_macro_name(expr->pos))
		return;

	str = expr_to_str(expr);
	sm_msg("warn: this array is probably non-NULL. '%s'", str);
	free_string(str);
}
Ejemplo n.º 18
0
static void match_call(const char *fn, struct expression *expr, void *_arg_no)
{
	struct expression *arg_expr;
	int arg_no = PTR_INT(_arg_no);
	sval_t sval;
	char *name;

	arg_expr = get_argument_from_call_expr(expr->args, arg_no);
	if (positions_eq(expr->pos, arg_expr->pos))
		return;
	name = pos_ident(arg_expr->pos);
	if (!name)
		return;
	if (!get_value(arg_expr, &sval))
		return;
	sm_msg("info: bit shifter '%s' '%s'", name, sval_to_str(sval));
}
Ejemplo n.º 19
0
static void check_and(struct expression *expr)
{
	struct expression *left, *right;

	left = strip_expr(expr->left);
	right = strip_expr(expr->right);

	if (left->type != EXPR_COMPARE ||
			left->op != SPECIAL_EQUAL)
		return;
	if (right->type != EXPR_COMPARE ||
			right->op != SPECIAL_EQUAL)
		return;
	if (!inconsistent_check(left, right))
		return;

	sm_msg("warn: was || intended here instead of &&?");
}
Ejemplo n.º 20
0
static void match_binop_info(struct expression *expr)
{
	char *name;
	sval_t sval;

	if (positions_eq(expr->pos, expr->right->pos))
		return;
	if (expr->op != SPECIAL_LEFTSHIFT)
		return;
	if (expr->right->type != EXPR_VALUE)
		return;
	name = pos_ident(expr->right->pos);
	if (!name)
		return;
	if (!get_value(expr->right, &sval))
		return;
	sm_msg("info: bit shifter '%s' '%s'", name, sval_to_str(sval));
}
Ejemplo n.º 21
0
static void match_return(struct expression *ret_value)
{
	sval_t rval;
	sval_t lret;
	char *name;

	if (!get_value(ret_value, &rval) || rval.value >= 0)
		return;
	if (get_implied_value(last_return, &lret))
		return;
	if (!get_implied_max(last_return, &lret) || lret.value >= 0)
		return;
	if (get_implied_min(last_return, &lret) && !sval_is_min(lret))
		return;
	name = expr_to_var(last_return);
	sm_msg("info: why not propagate '%s' from %s() instead of %s?",
		name, get_fn_name(last_func), sval_to_str(rval));
	free_string(name);
}
Ejemplo n.º 22
0
static void match_one_side(struct expression *expr, struct position pos, int op)
{
	char *name;
	int matched = 0;

	if ((op == '+' || op == '*' || op == '|' || op == '&') && expr->op == op)
		return;
	if (positions_eq(expr->right->pos, pos))
		matched++;
	if (positions_eq(expr->left->pos, pos))
		matched++;
	if (matched != 1)
		return;
	name = get_macro_name(pos);
	if (!name)
		return;
	if (option_project == PROJ_WINE && !strcmp("BEGIN", name))
		return;
	sm_msg("warn: the '%s' macro might need parens", name);
}