static void match_dev_put(const char *fn, struct expression *expr, void *data) { struct expression *arg_expr; arg_expr = get_argument_from_call_expr(expr->args, 0); set_state_expr(my_id, arg_expr, &released); }
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); }
static int param_caps_return(struct expression *call, void *_arg, struct range_list **res) { int arg = PTR_INT(_arg); struct expression *expr; struct range_list *rl; expr = get_argument_from_call_expr(call->args, arg); if (get_implied_rl(expr, &rl) && rl_max(rl).value != 0) *res = alloc_rl(sval_type_val(rl_type(rl), 0), rl_max(rl)); return 1; }
static void match_capable(const char *fn, struct expression *expr, void *_param) { struct expression *arg; sval_t sval; char buf[32]; arg = get_argument_from_call_expr(expr->args, 0); if (!get_implied_value(arg, &sval)) return; snprintf(buf, sizeof(buf), "%s", sval_to_str(sval)); set_state(capable_id, buf, NULL, &capable); }
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); }
static void match_calloc(const char *fn, struct expression *expr, void *_arg_nr) { int arg_nr = PTR_INT(_arg_nr); struct expression *call = strip_expr(expr->right); struct expression *arg; int ptr_size; ptr_size = get_data_size(expr->left); if (!ptr_size) return; arg = get_argument_from_call_expr(call->args, arg_nr); check_size_matches(ptr_size, arg); }
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); }
static void match_resource(const char *fn, struct expression *expr, void *_arg_no) { struct expression *arg_expr; int arg_no = PTR_INT(_arg_no); arg_expr = get_argument_from_call_expr(expr->args, arg_no); arg_expr = strip_expr(arg_expr); if (!arg_expr) return; if (arg_expr->type == EXPR_SYMBOL) { handle_assigned_expr(arg_expr); return; } verify_size_expr(arg_expr); }
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)); }
static void match_alloc(const char *fn, struct expression *expr, void *unused) { struct expression *call = strip_expr(expr->right); struct expression *arg; int ptr_size; ptr_size = get_data_size(expr->left); if (!ptr_size) return; arg = get_argument_from_call_expr(call->args, 0); arg = strip_expr(arg); if (!arg || arg->type != EXPR_BINOP || arg->op != '*') return; if (expr->left->type == EXPR_SIZEOF) check_size_matches(ptr_size, arg->left); if (expr->right->type == EXPR_SIZEOF) check_size_matches(ptr_size, arg->right); }
static int match_strlen(struct expression *call, void *unused, struct range_list **rl) { struct expression *str; unsigned long max; str = get_argument_from_call_expr(call->args, 0); if (get_implied_strlen(str, rl) && sval_is_positive(rl_min(*rl))) { *rl = cast_rl(&ulong_ctype, *rl); return 1; } /* smatch_strlen.c is not very complete */ max = get_array_size_bytes_max(str); if (max == 0) { *rl = alloc_rl(sval_type_val(&ulong_ctype, 0), sval_type_val(&ulong_ctype, STRLEN_MAX_RET)); } else { max--; *rl = alloc_rl(sval_type_val(&ulong_ctype, 0), sval_type_val(&ulong_ctype, max)); } return 1; }
static void db_param_cleared(struct expression *expr, int param, char *key, char *value) { struct expression *arg; while (expr->type == EXPR_ASSIGNMENT) expr = strip_expr(expr->right); if (expr->type != EXPR_CALL) return; arg = get_argument_from_call_expr(expr->args, param); arg = strip_expr(arg); if (!arg) return; if (arg->type != EXPR_SYMBOL) return; if (get_param_num_from_sym(arg->symbol) < 0) return; if (strcmp(value, "0") == 0) set_state_expr(my_id, arg, &zeroed); else set_state_expr(my_id, arg, &cleared); }
static int match_strnlen(struct expression *call, void *unused, struct range_list **rl) { struct expression *limit; sval_t fixed; sval_t bound; sval_t ulong_max = sval_type_val(&ulong_ctype, ULONG_MAX); match_strlen(call, NULL, rl); limit = get_argument_from_call_expr(call->args, 1); if (!get_implied_max(limit, &bound)) return 1; if (sval_cmp(bound, ulong_max) == 0) return 1; if (rl_to_sval(*rl, &fixed) && sval_cmp(fixed, bound) >= 0) { *rl = alloc_rl(bound, bound); return 1; } bound.value++; *rl = remove_range(*rl, bound, ulong_max); return 1; }