1 
2 #include <r_anal.h>
3 
4 #include "minunit.h"
5 
6 const RAnalHint empty_hint = {
7 	.addr = UT64_MAX,
8 	.ptr = 0,
9 	.val = UT64_MAX,
10 	.jump = UT64_MAX,
11 	.fail = UT64_MAX,
12 	.ret = UT64_MAX,
13 	.arch = 0,
14 	.opcode = NULL,
15 	.syntax = NULL,
16 	.esil = NULL,
17 	.offset = NULL,
18 	.type = 0,
19 	.size = 0,
20 	.bits = 0,
21 	.new_bits = 0,
22 	.immbase = 0,
23 	.high = 0,
24 	.nword = 0,
25 	.stackframe = UT64_MAX,
26 };
27 
hint_equals(const RAnalHint * a,const RAnalHint * b)28 bool hint_equals(const RAnalHint *a, const RAnalHint *b) {
29 #define CHECK_EQ(member) mu_assert_eq (a->member, b->member, "hint member " #member)
30 	CHECK_EQ (ptr);
31 	CHECK_EQ (val);
32 	CHECK_EQ (jump);
33 	CHECK_EQ (fail);
34 	CHECK_EQ (ret);
35 	CHECK_EQ (type);
36 	CHECK_EQ (size);
37 	CHECK_EQ (bits);
38 	CHECK_EQ (new_bits);
39 	CHECK_EQ (immbase);
40 	CHECK_EQ (high);
41 	CHECK_EQ (nword);
42 	CHECK_EQ (stackframe);
43 #undef CHECK_EQ
44 #define CHECK_STREQ(member) mu_assert_nullable_streq (a->member, b->member, "hint member " #member)
45 	CHECK_STREQ (arch);
46 	CHECK_STREQ (opcode);
47 	CHECK_STREQ (syntax);
48 	CHECK_STREQ (esil);
49 	CHECK_STREQ (offset);
50 #undef CHECK_STREQ
51 	return true;
52 }
53 
54 #define assert_hint_eq(actual, expected) do { \
55 	if (actual == NULL) \
56 		mu_assert ("hint", expected == &empty_hint); /* TODO: remove this part, only else should be used! */ \
57 	else \
58 		mu_assert ("hint", hint_equals (actual, expected)); \
59 } while (0)
60 
test_r_anal_addr_hints()61 bool test_r_anal_addr_hints() {
62 	RAnal *anal = r_anal_new ();
63 	RAnalHint *hint = r_anal_hint_get (anal, 0x1337);
64 	assert_hint_eq (hint, &empty_hint);
65 	r_anal_hint_free (hint);
66 
67 	RAnalHint cur = empty_hint;
68 #define CHECK \
69 	hint = r_anal_hint_get (anal, 0x1337); \
70 	assert_hint_eq (hint, &cur); \
71 	r_anal_hint_free (hint);
72 	hint = r_anal_hint_get (anal, 0x1338); \
73 	assert_hint_eq (hint, &empty_hint); \
74 	r_anal_hint_free (hint);
75 	hint = r_anal_hint_get (anal, 0x1336); \
76 	assert_hint_eq (hint, &empty_hint); \
77 	r_anal_hint_free (hint);
78 
79 	// set --------
80 
81 	r_anal_hint_set_syntax (anal, 0x1337, "mysyntax");
82 	cur.syntax = "mysyntax";
83 	CHECK
84 
85 	r_anal_hint_set_type (anal, 0x1337, R_ANAL_OP_TYPE_RET);
86 	cur.type = R_ANAL_OP_TYPE_RET;
87 	CHECK
88 
89 	r_anal_hint_set_jump (anal, 0x1337, 0xdeadbeef);
90 	cur.jump = 0xdeadbeef;
91 	CHECK
92 
93 	r_anal_hint_set_fail (anal, 0x1337, 0xc0ffee);
94 	cur.fail = 0xc0ffee;
95 	CHECK
96 
97 	r_anal_hint_set_nword (anal, 0x1337, 42);
98 	cur.nword = 42;
99 	CHECK
100 
101 	r_anal_hint_set_offset (anal, 0x1337, "mytypeoff");
102 	cur.offset = "mytypeoff";
103 	CHECK
104 
105 	r_anal_hint_set_immbase (anal, 0x1337, 7);
106 	cur.immbase = 7;
107 	CHECK
108 
109 	r_anal_hint_set_size (anal, 0x1337, 0x123);
110 	cur.size = 0x123;
111 	CHECK
112 
113 	r_anal_hint_set_opcode (anal, 0x1337, "myopcode");
114 	cur.opcode = "myopcode";
115 	CHECK
116 
117 	r_anal_hint_set_esil (anal, 0x1337, "/,-rf,rm");
118 	cur.esil = "/,-rf,rm";
119 	CHECK
120 
121 	r_anal_hint_set_pointer (anal, 0x1337, 0x4242);
122 	cur.ptr = 0x4242;
123 	CHECK
124 
125 	r_anal_hint_set_ret (anal, 0x1337, 0xf00d);
126 	cur.ret = 0xf00d;
127 	CHECK
128 
129 	r_anal_hint_set_high (anal, 0x1337);
130 	cur.high = true;
131 	CHECK
132 
133 	r_anal_hint_set_stackframe (anal, 0x1337, 0x4321);
134 	cur.stackframe = 0x4321;
135 	CHECK
136 
137 	r_anal_hint_set_val (anal, 0x1337, 0x112358d);
138 	cur.val = 0x112358d;
139 	CHECK
140 
141 	r_anal_hint_set_newbits (anal, 0x1337, 16);
142 	cur.new_bits = 16;
143 	CHECK
144 
145 	// unset --------
146 
147 	r_anal_hint_unset_syntax (anal, 0x1337);
148 	cur.syntax = NULL;
149 	CHECK
150 
151 	r_anal_hint_unset_type (anal, 0x1337);
152 	cur.type = 0;
153 	CHECK
154 
155 	r_anal_hint_unset_jump (anal, 0x1337);
156 	cur.jump = UT64_MAX;
157 	CHECK
158 
159 	r_anal_hint_unset_fail (anal, 0x1337);
160 	cur.fail = UT64_MAX;
161 	CHECK
162 
163 	r_anal_hint_unset_nword (anal, 0x1337);
164 	cur.nword = 0;
165 	CHECK
166 
167 	r_anal_hint_unset_offset (anal, 0x1337);
168 	cur.offset = NULL;
169 	CHECK
170 
171 	r_anal_hint_unset_immbase (anal, 0x1337);
172 	cur.immbase = 0;
173 	CHECK
174 
175 	r_anal_hint_unset_size (anal, 0x1337);
176 	cur.size = 0;
177 	CHECK
178 
179 	r_anal_hint_unset_opcode (anal, 0x1337);
180 	cur.opcode = NULL;
181 	CHECK
182 
183 	r_anal_hint_unset_esil (anal, 0x1337);
184 	cur.esil = NULL;
185 	CHECK
186 
187 	r_anal_hint_unset_pointer (anal, 0x1337);
188 	cur.ptr = 0;
189 	CHECK
190 
191 	r_anal_hint_unset_ret (anal, 0x1337);
192 	cur.ret = UT64_MAX;
193 	CHECK
194 
195 	r_anal_hint_unset_high (anal, 0x1337);
196 	cur.high = false;
197 	CHECK
198 
199 	r_anal_hint_unset_stackframe (anal, 0x1337);
200 	cur.stackframe = UT64_MAX;
201 	CHECK
202 
203 	r_anal_hint_unset_val (anal, 0x1337);
204 	cur.val = UT64_MAX;
205 	CHECK
206 
207 	r_anal_hint_unset_newbits (anal, 0x1337);
208 	cur.new_bits = 0;
209 	//CHECK
210 	hint = r_anal_hint_get (anal, 0x1337);
211 	assert_hint_eq (hint, &empty_hint);
212 	r_anal_hint_free (hint);
213 
214 	r_anal_free (anal);
215 	mu_end;
216 #undef CHECK
217 }
218 
219 #define RANGED_TEST(name, val, resetval, assert_val) \
220 bool test_r_anal_hints_##name() { \
221 	RAnal *anal = r_anal_new (); \
222 	\
223 	ut64 hint_addr = 0xdead; \
224 	assert_val (r_anal_hint_##name##_at (anal, 0x1337, &hint_addr), resetval, "no " #name ""); \
225 	mu_assert_eq (hint_addr, UT64_MAX, "hint addr"); \
226 	\
227 	r_anal_hint_##name##_at (anal, 0x1337, NULL); /* make sure this does not null-deref */ \
228 	\
229 	/* -- */ \
230 	r_anal_hint_set_##name (anal, 0x1337, val); \
231 	\
232 	hint_addr = 0xdead; \
233 	assert_val (r_anal_hint_##name##_at (anal, 0x1337, &hint_addr), val, #name " at addr"); \
234 	mu_assert_eq (hint_addr, 0x1337, "hint addr"); \
235 	hint_addr = 0xdead; \
236 	assert_val (r_anal_hint_##name##_at (anal, 0x1338, &hint_addr), val, #name " after addr"); \
237 	mu_assert_eq (hint_addr, 0x1337, "hint addr"); \
238 	hint_addr = 0xdead; \
239 	assert_val (r_anal_hint_##name##_at (anal, UT64_MAX, &hint_addr), val, #name " after addr"); \
240 	mu_assert_eq (hint_addr, 0x1337, "hint addr"); \
241 	hint_addr = 0xdead; \
242 	assert_val (r_anal_hint_##name##_at (anal, 0x1336, &hint_addr), resetval, "no " #name " before addr"); \
243 	mu_assert_eq (hint_addr, UT64_MAX, "hint addr"); \
244 	hint_addr = 0xdead; \
245 	assert_val (r_anal_hint_##name##_at (anal, 0, &hint_addr), resetval, "no " #name " before addr"); \
246 	mu_assert_eq (hint_addr, UT64_MAX, "hint addr"); \
247 	\
248 	r_anal_hint_##name##_at (anal, 0x1337, NULL); /* make sure this does not null-deref */ \
249 	\
250 	RAnalHint cur = empty_hint; \
251 	cur.name = val; \
252 	RAnalHint *hint = r_anal_hint_get (anal, 0x1337); \
253 	assert_hint_eq (hint, &cur); \
254 	r_anal_hint_free (hint); \
255 	hint = r_anal_hint_get (anal, 0x1338); \
256 	assert_hint_eq (hint, &cur); \
257 	r_anal_hint_free (hint); \
258 	hint = r_anal_hint_get (anal, 0x1336); \
259 	assert_hint_eq (hint, &empty_hint); \
260 	r_anal_hint_free (hint); \
261 	\
262 	/* -- */ \
263 	hint_addr = 0xdead; \
264 	assert_val (r_anal_hint_##name##_at (anal, 0xdeadbeef, &hint_addr), val, "before reset " #name " at addr"); \
265 	mu_assert_eq (hint_addr, 0x1337, "hint addr"); \
266 	r_anal_hint_set_##name (anal, 0xdeadbeef, resetval); \
267 	hint_addr = 0xdead; \
268 	assert_val (r_anal_hint_##name##_at (anal, 0xdeadbeef, &hint_addr), resetval, "reset " #name " at addr"); \
269 	mu_assert_eq (hint_addr, 0xdeadbeef, "hint addr"); \
270 	hint_addr = 0xdead; \
271 	assert_val (r_anal_hint_##name##_at (anal, 0xdeadbeef + 1, &hint_addr), resetval, "reset " #name " after addr"); \
272 	mu_assert_eq (hint_addr, 0xdeadbeef, "hint addr"); \
273 	hint_addr = 0xdead; \
274 	assert_val (r_anal_hint_##name##_at (anal, UT64_MAX, &hint_addr), resetval, "reset " #name " after addr"); \
275 	mu_assert_eq (hint_addr, 0xdeadbeef, "hint addr"); \
276 	hint_addr = 0xdead; \
277 	assert_val (r_anal_hint_##name##_at (anal, 0xdeadbeef - 1, &hint_addr), val, "" #name " before addr"); \
278 	mu_assert_eq (hint_addr, 0x1337, "hint addr"); \
279 	\
280 	/* -- */ \
281 	r_anal_hint_unset_##name (anal, 0xdeadbeef); \
282 	hint_addr = 0xdead; \
283 	assert_val (r_anal_hint_##name##_at (anal, 0x1337, &hint_addr), val, #name " at addr"); \
284 	mu_assert_eq (hint_addr, 0x1337, "hint addr"); \
285 	hint_addr = 0xdead; \
286 	assert_val (r_anal_hint_##name##_at (anal, 0x1338, &hint_addr), val, #name " after addr"); \
287 	mu_assert_eq (hint_addr, 0x1337, "hint addr"); \
288 	hint_addr = 0xdead; \
289 	assert_val (r_anal_hint_##name##_at (anal, UT64_MAX, &hint_addr), val, #name " after addr"); \
290 	mu_assert_eq (hint_addr, 0x1337, "hint addr"); \
291 	hint_addr = 0xdead; \
292 	assert_val (r_anal_hint_##name##_at (anal, 0x1336, &hint_addr), resetval, "no " #name " before addr"); \
293 	mu_assert_eq (hint_addr, UT64_MAX, "hint addr"); \
294 	hint_addr = 0xdead; \
295 	assert_val (r_anal_hint_##name##_at (anal, 0, &hint_addr), resetval, "no " #name " before addr"); \
296 	mu_assert_eq (hint_addr, UT64_MAX, "hint addr"); \
297 	hint_addr = 0xdead; \
298 	assert_val (r_anal_hint_##name##_at (anal, 0xdeadbeef, &hint_addr), val, "unset reset " #name " at addr"); \
299 	mu_assert_eq (hint_addr, 0x1337, "hint addr"); \
300 	hint_addr = 0xdead; \
301 	assert_val (r_anal_hint_##name##_at (anal, 0xdeadbeef + 1, &hint_addr), val, "unset reset " #name " after addr"); \
302 	mu_assert_eq (hint_addr, 0x1337, "hint addr"); \
303 	hint_addr = 0xdead; \
304 	assert_val (r_anal_hint_##name##_at (anal, UT64_MAX, &hint_addr), val, "unset reset " #name " after addr"); \
305 	mu_assert_eq (hint_addr, 0x1337, "hint addr"); \
306 	hint_addr = 0xdead; \
307 	assert_val (r_anal_hint_##name##_at (anal, 0xdeadbeef - 1, &hint_addr), val, #name " before addr"); \
308 	mu_assert_eq (hint_addr, 0x1337, "hint addr"); \
309 	\
310 	/* -- */ \
311 	r_anal_hint_unset_##name (anal, 0x1337); \
312 	hint_addr = 0xdead; \
313 	assert_val (r_anal_hint_##name##_at (anal, 0x1336, &hint_addr), resetval, "unset " #name ""); \
314 	mu_assert_eq (hint_addr, UT64_MAX, "hint addr"); \
315 	hint_addr = 0xdead; \
316 	assert_val (r_anal_hint_##name##_at (anal, 0, &hint_addr), resetval, "unset " #name ""); \
317 	mu_assert_eq (hint_addr, UT64_MAX, "hint addr"); \
318 	hint_addr = 0xdead; \
319 	assert_val (r_anal_hint_##name##_at (anal, 0x1337, &hint_addr), resetval, "unset " #name ""); \
320 	mu_assert_eq (hint_addr, UT64_MAX, "hint addr"); \
321 	hint_addr = 0xdead; \
322 	assert_val (r_anal_hint_##name##_at (anal, 0x1338, &hint_addr), resetval, "unset " #name ""); \
323 	mu_assert_eq (hint_addr, UT64_MAX, "hint addr"); \
324 	hint_addr = 0xdead; \
325 	assert_val (r_anal_hint_##name##_at (anal, UT64_MAX, &hint_addr), resetval, "unset " #name ""); \
326 	mu_assert_eq (hint_addr, UT64_MAX, "hint addr"); \
327 	hint_addr = 0xdead; \
328 	\
329 	r_anal_free (anal); \
330 	mu_end; \
331 }
332 
333 RANGED_TEST(arch, "6502", NULL, mu_assert_nullable_streq)
334 RANGED_TEST(bits, 16, 0, mu_assert_eq)
335 
all_tests()336 bool all_tests() {
337 	mu_run_test(test_r_anal_addr_hints);
338 	mu_run_test(test_r_anal_hints_arch);
339 	mu_run_test(test_r_anal_hints_bits);
340 	return tests_passed != tests_run;
341 }
342 
main(int argc,char ** argv)343 int main(int argc, char **argv) {
344 	return all_tests();
345 }
346