51 static int my_id;
52
53 mtag_t str_to_mtag(const char *str)
54 {
55 unsigned char c[MD5_DIGEST_LENGTH];
56 unsigned long long *tag = (unsigned long long *)&c;
57 MD5_CTX mdContext;
58 int len;
59
60 len = strlen(str);
61 MD5_Init(&mdContext);
62 MD5_Update(&mdContext, str, len);
63 MD5_Final(c, &mdContext);
64
65 *tag &= ~MTAG_ALIAS_BIT;
66 *tag &= ~MTAG_OFFSET_MASK;
67
68 return *tag;
69 }
70
71 const struct {
72 const char *name;
73 int size_arg;
74 } allocator_info[] = {
75 { "kmalloc", 0 },
76 { "kzalloc", 0 },
77 { "devm_kmalloc", 1},
78 { "devm_kzalloc", 1},
79 };
80
81 static bool is_mtag_call(struct expression *expr)
82 {
83 struct expression *arg;
84 int i;
85 sval_t sval;
86
87 if (expr->type != EXPR_CALL ||
88 expr->fn->type != EXPR_SYMBOL ||
89 !expr->fn->symbol)
90 return false;
91
92 for (i = 0; i < ARRAY_SIZE(allocator_info); i++) {
93 if (strcmp(expr->fn->symbol->ident->name, allocator_info[i].name) == 0)
94 break;
95 }
96 if (i == ARRAY_SIZE(allocator_info))
97 return false;
98
99 arg = get_argument_from_call_expr(expr->args, allocator_info[i].size_arg);
100 if (!get_implied_value(arg, &sval))
101 return false;
102
103 return true;
104 }
105
106 struct smatch_state *swap_mtag_return(struct expression *expr, struct smatch_state *state)
107 {
108 struct expression *left, *right;
109 char *left_name, *right_name;
110 struct symbol *left_sym;
111 struct range_list *rl;
112 char buf[256];
113 mtag_t tag;
114 sval_t tag_sval;
115
116 if (!expr || expr->type != EXPR_ASSIGNMENT || expr->op != '=')
117 return state;
118
119 if (!estate_rl(state) || strcmp(state->name, "0,4096-ptr_max") != 0)
120 return state;
121
122 left = strip_expr(expr->left);
123 right = strip_expr(expr->right);
124
125 if (!is_mtag_call(right))
126 return state;
127
128 left_name = expr_to_str_sym(left, &left_sym);
129 if (!left_name || !left_sym)
130 return state;
131 right_name = expr_to_str(right);
132
133 snprintf(buf, sizeof(buf), "%s %s %s %s", get_filename(), get_function(),
134 left_name, right_name);
135 tag = str_to_mtag(buf);
136 tag_sval.type = estate_type(state);
137 tag_sval.uvalue = tag;
138
139 rl = rl_filter(estate_rl(state), valid_ptr_rl);
140 rl = clone_rl(rl);
141 add_range(&rl, tag_sval, tag_sval);
142
143 sql_insert_mtag_about(tag, left_name, buf);
144
145 free_string(left_name);
146 free_string(right_name);
147
148 return alloc_estate_rl(rl);
149 }
150
151 int get_string_mtag(struct expression *expr, mtag_t *tag)
152 {
153 mtag_t xor;
154
155 if (expr->type != EXPR_STRING || !expr->string)
156 return 0;
157
158 /* I was worried about collisions so I added a xor */
159 xor = str_to_mtag("__smatch string");
160 *tag = str_to_mtag(expr->string->data);
161 *tag = *tag ^ xor;
162
163 return 1;
|
51 static int my_id;
52
53 mtag_t str_to_mtag(const char *str)
54 {
55 unsigned char c[MD5_DIGEST_LENGTH];
56 unsigned long long *tag = (unsigned long long *)&c;
57 MD5_CTX mdContext;
58 int len;
59
60 len = strlen(str);
61 MD5_Init(&mdContext);
62 MD5_Update(&mdContext, str, len);
63 MD5_Final(c, &mdContext);
64
65 *tag &= ~MTAG_ALIAS_BIT;
66 *tag &= ~MTAG_OFFSET_MASK;
67
68 return *tag;
69 }
70
71 static int save_allocator(void *_allocator, int argc, char **argv, char **azColName)
72 {
73 char **allocator = _allocator;
74
75 if (*allocator) {
76 if (strcmp(*allocator, argv[0]) == 0)
77 return 0;
78 /* should be impossible */
79 free_string(*allocator);
80 *allocator = alloc_string("unknown");
81 return 0;
82 }
83 *allocator = alloc_string(argv[0]);
84 return 0;
85 }
86
87 char *get_allocator_info_from_tag(mtag_t tag)
88 {
89 char *allocator = NULL;
90
91 run_sql(save_allocator, &allocator,
92 "select value from mtag_info where tag = %lld and type = %d;",
93 tag, ALLOCATOR);
94
95 return allocator;
96 }
97
98 static char *get_allocator_info(struct expression *expr, struct smatch_state *state)
99 {
100 sval_t sval;
101
102 if (expr->type != EXPR_ASSIGNMENT)
103 return NULL;
104 if (estate_get_single_value(state, &sval))
105 return get_allocator_info_from_tag(sval.value);
106
107 expr = strip_expr(expr->right);
108 if (expr->type != EXPR_CALL ||
109 !expr->fn ||
110 expr->fn->type != EXPR_SYMBOL)
111 return NULL;
112 return expr_to_str(expr->fn);
113 }
114
115 static void update_mtag_info(struct expression *expr, mtag_t tag,
116 const char *left_name, const char *tag_info,
117 struct smatch_state *state)
118 {
119 char *allocator;
120
121 sql_insert_mtag_about(tag, left_name, tag_info);
122
123 allocator = get_allocator_info(expr, state);
124 if (allocator)
125 sql_insert_mtag_info(tag, ALLOCATOR, allocator);
126 }
127
128 struct smatch_state *get_mtag_return(struct expression *expr, struct smatch_state *state)
129 {
130 struct expression *left, *right;
131 char *left_name, *right_name;
132 struct symbol *left_sym;
133 struct range_list *rl;
134 char buf[256];
135 mtag_t tag;
136 sval_t tag_sval;
137
138 if (!expr || expr->type != EXPR_ASSIGNMENT || expr->op != '=')
139 return NULL;
140 if (!is_fresh_alloc(expr->right))
141 return NULL;
142 if (!rl_intersection(estate_rl(state), valid_ptr_rl))
143 return NULL;
144
145 left = strip_expr(expr->left);
146 right = strip_expr(expr->right);
147
148 left_name = expr_to_str_sym(left, &left_sym);
149 if (!left_name || !left_sym)
150 return NULL;
151 right_name = expr_to_str(right);
152
153 snprintf(buf, sizeof(buf), "%s %s %s %s", get_filename(), get_function(),
154 left_name, right_name);
155 tag = str_to_mtag(buf);
156 tag_sval.type = estate_type(state);
157 tag_sval.uvalue = tag;
158
159 rl = rl_filter(estate_rl(state), valid_ptr_rl);
160 rl = clone_rl(rl);
161 add_range(&rl, tag_sval, tag_sval);
162
163 update_mtag_info(expr, tag, left_name, buf, state);
164
165 free_string(left_name);
166 free_string(right_name);
167
168 return alloc_estate_rl(rl);
169 }
170
171 int get_string_mtag(struct expression *expr, mtag_t *tag)
172 {
173 mtag_t xor;
174
175 if (expr->type != EXPR_STRING || !expr->string)
176 return 0;
177
178 /* I was worried about collisions so I added a xor */
179 xor = str_to_mtag("__smatch string");
180 *tag = str_to_mtag(expr->string->data);
181 *tag = *tag ^ xor;
182
183 return 1;
|