1 | /* |
2 | * Copyright © 2012 Intel Corporation |
3 | * |
4 | * Permission is hereby granted, free of charge, to any person obtaining |
5 | * a copy of this software and associated documentation files (the |
6 | * "Software"), to deal in the Software without restriction, including |
7 | * without limitation the rights to use, copy, modify, merge, publish, |
8 | * distribute, sublicense, and/or sell copies of the Software, and to |
9 | * permit persons to whom the Software is furnished to do so, subject to |
10 | * the following conditions: |
11 | * |
12 | * The above copyright notice and this permission notice (including the |
13 | * next paragraph) shall be included in all copies or substantial |
14 | * portions of the Software. |
15 | * |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
23 | * SOFTWARE. |
24 | */ |
25 | |
26 | #include <math.h> |
27 | #include <stdio.h> |
28 | #include <stdlib.h> |
29 | #include <stdarg.h> |
30 | #include <stdint.h> |
31 | #include <string.h> |
32 | #include <assert.h> |
33 | #include <sys/socket.h> |
34 | #include <unistd.h> |
35 | #include <errno.h> |
36 | #include <sys/types.h> |
37 | #include <sys/stat.h> |
38 | #include <poll.h> |
39 | |
40 | #include "wayland-private.h" |
41 | #include "test-runner.h" |
42 | #include "test-compositor.h" |
43 | |
44 | static const char message[] = "Hello, world" ; |
45 | |
46 | static struct wl_connection * |
47 | setup(int *s) |
48 | { |
49 | struct wl_connection *connection; |
50 | |
51 | assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); |
52 | |
53 | connection = wl_connection_create(fd: s[0]); |
54 | assert(connection); |
55 | |
56 | return connection; |
57 | } |
58 | |
59 | TEST(connection_create) |
60 | { |
61 | struct wl_connection *connection; |
62 | int s[2]; |
63 | |
64 | connection = setup(s); |
65 | wl_connection_destroy(connection); |
66 | close(fd: s[0]); |
67 | close(fd: s[1]); |
68 | } |
69 | |
70 | TEST(connection_write) |
71 | { |
72 | struct wl_connection *connection; |
73 | int s[2]; |
74 | char buffer[64]; |
75 | |
76 | connection = setup(s); |
77 | |
78 | assert(wl_connection_write(connection, message, sizeof message) == 0); |
79 | assert(wl_connection_flush(connection) == sizeof message); |
80 | assert(read(s[1], buffer, sizeof buffer) == sizeof message); |
81 | assert(memcmp(message, buffer, sizeof message) == 0); |
82 | |
83 | wl_connection_destroy(connection); |
84 | close(fd: s[0]); |
85 | close(fd: s[1]); |
86 | } |
87 | |
88 | TEST(connection_data) |
89 | { |
90 | struct wl_connection *connection; |
91 | int s[2]; |
92 | char buffer[64]; |
93 | |
94 | connection = setup(s); |
95 | |
96 | assert(write(s[1], message, sizeof message) == sizeof message); |
97 | assert(wl_connection_read(connection) == sizeof message); |
98 | wl_connection_copy(connection, data: buffer, size: sizeof message); |
99 | assert(memcmp(message, buffer, sizeof message) == 0); |
100 | wl_connection_consume(connection, size: sizeof message); |
101 | |
102 | wl_connection_destroy(connection); |
103 | close(fd: s[0]); |
104 | close(fd: s[1]); |
105 | } |
106 | |
107 | TEST(connection_queue) |
108 | { |
109 | struct wl_connection *connection; |
110 | int s[2]; |
111 | char buffer[64]; |
112 | |
113 | connection = setup(s); |
114 | |
115 | /* Test that wl_connection_queue() puts data in the output |
116 | * buffer without flush it. Verify that the data did get in |
117 | * the buffer by writing another message and making sure that |
118 | * we receive the two messages on the other fd. */ |
119 | |
120 | assert(wl_connection_queue(connection, message, sizeof message) == 0); |
121 | assert(wl_connection_flush(connection) == 0); |
122 | assert(wl_connection_write(connection, message, sizeof message) == 0); |
123 | assert(wl_connection_flush(connection) == 2 * sizeof message); |
124 | assert(read(s[1], buffer, sizeof buffer) == 2 * sizeof message); |
125 | assert(memcmp(message, buffer, sizeof message) == 0); |
126 | assert(memcmp(message, buffer + sizeof message, sizeof message) == 0); |
127 | |
128 | wl_connection_destroy(connection); |
129 | close(fd: s[0]); |
130 | close(fd: s[1]); |
131 | } |
132 | |
133 | static void |
134 | va_list_wrapper(const char *signature, union wl_argument *args, int count, ...) |
135 | { |
136 | va_list ap; |
137 | va_start(ap, count); |
138 | wl_argument_from_va_list(signature, args, count, ap); |
139 | va_end(ap); |
140 | } |
141 | |
142 | TEST(argument_from_va_list) |
143 | { |
144 | union wl_argument args[WL_CLOSURE_MAX_ARGS]; |
145 | struct wl_object fake_object, fake_new_object; |
146 | struct wl_array fake_array; |
147 | |
148 | va_list_wrapper(signature: "i" , args, count: 1, 100); |
149 | assert(args[0].i == 100); |
150 | |
151 | va_list_wrapper(signature: "is" , args, count: 2, 101, "value" ); |
152 | assert(args[0].i == 101); |
153 | assert(strcmp(args[1].s, "value" ) == 0); |
154 | |
155 | va_list_wrapper(signature: "?iuf?sonah" , args, count: 8, |
156 | 102, 103, wl_fixed_from_int(i: 104), "value" , |
157 | &fake_object, &fake_new_object, &fake_array, 106); |
158 | assert(args[0].i == 102); |
159 | assert(args[1].u == 103); |
160 | assert(args[2].f == wl_fixed_from_int(104)); |
161 | assert(strcmp(args[3].s, "value" ) == 0); |
162 | assert(args[4].o == &fake_object); |
163 | assert(args[5].o == &fake_new_object); |
164 | assert(args[6].a == &fake_array); |
165 | assert(args[7].h == 106); |
166 | } |
167 | |
168 | struct marshal_data { |
169 | struct wl_connection *read_connection; |
170 | struct wl_connection *write_connection; |
171 | int s[2]; |
172 | uint32_t buffer[10]; |
173 | union { |
174 | uint32_t u; |
175 | int32_t i; |
176 | const char *s; |
177 | int h; |
178 | } value; |
179 | }; |
180 | |
181 | static void |
182 | setup_marshal_data(struct marshal_data *data) |
183 | { |
184 | assert(socketpair(AF_UNIX, |
185 | SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0); |
186 | data->read_connection = wl_connection_create(fd: data->s[0]); |
187 | assert(data->read_connection); |
188 | data->write_connection = wl_connection_create(fd: data->s[1]); |
189 | assert(data->write_connection); |
190 | } |
191 | |
192 | static void |
193 | release_marshal_data(struct marshal_data *data) |
194 | { |
195 | close(fd: wl_connection_destroy(connection: data->read_connection)); |
196 | close(fd: wl_connection_destroy(connection: data->write_connection)); |
197 | } |
198 | |
199 | static void |
200 | marshal(struct marshal_data *data, const char *format, int size, ...) |
201 | { |
202 | struct wl_closure *closure; |
203 | static const uint32_t opcode = 4444; |
204 | static struct wl_object sender = { NULL, NULL, 1234 }; |
205 | struct wl_message message = { "test" , format, NULL }; |
206 | va_list ap; |
207 | |
208 | va_start(ap, size); |
209 | closure = wl_closure_vmarshal(sender: &sender, opcode, ap, message: &message); |
210 | va_end(ap); |
211 | |
212 | assert(closure); |
213 | assert(wl_closure_send(closure, data->write_connection) == 0); |
214 | wl_closure_destroy(closure); |
215 | assert(wl_connection_flush(data->write_connection) == size); |
216 | assert(read(data->s[0], data->buffer, sizeof data->buffer) == size); |
217 | |
218 | assert(data->buffer[0] == sender.id); |
219 | assert(data->buffer[1] == (opcode | (size << 16))); |
220 | } |
221 | |
222 | TEST(connection_marshal) |
223 | { |
224 | struct marshal_data data; |
225 | struct wl_object object; |
226 | struct wl_array array; |
227 | static const char text[] = "curry" ; |
228 | |
229 | setup_marshal_data(&data); |
230 | |
231 | marshal(data: &data, format: "i" , size: 12, 42); |
232 | assert(data.buffer[2] == 42); |
233 | |
234 | marshal(data: &data, format: "u" , size: 12, 55); |
235 | assert(data.buffer[2] == 55); |
236 | |
237 | marshal(data: &data, format: "s" , size: 20, "frappo" ); |
238 | assert(data.buffer[2] == 7); |
239 | assert(strcmp((char *) &data.buffer[3], "frappo" ) == 0); |
240 | |
241 | object.id = 557799; |
242 | marshal(data: &data, format: "o" , size: 12, &object); |
243 | assert(data.buffer[2] == object.id); |
244 | |
245 | marshal(data: &data, format: "n" , size: 12, &object); |
246 | assert(data.buffer[2] == object.id); |
247 | |
248 | marshal(data: &data, format: "?n" , size: 12, NULL); |
249 | assert(data.buffer[2] == 0); |
250 | |
251 | array.data = (void *) text; |
252 | array.size = sizeof text; |
253 | marshal(data: &data, format: "a" , size: 20, &array); |
254 | assert(data.buffer[2] == array.size); |
255 | assert(memcmp(&data.buffer[3], text, array.size) == 0); |
256 | |
257 | release_marshal_data(data: &data); |
258 | } |
259 | |
260 | static void |
261 | expected_fail_marshal(int expected_error, const char *format, ...) |
262 | { |
263 | struct wl_closure *closure; |
264 | static const uint32_t opcode = 4444; |
265 | static const struct wl_interface test_interface = { |
266 | .name = "test_object" |
267 | }; |
268 | static struct wl_object sender = { 0 }; |
269 | struct wl_message message = { "test" , format, NULL }; |
270 | |
271 | sender.interface = &test_interface; |
272 | sender.id = 1234; |
273 | va_list ap; |
274 | |
275 | va_start(ap, format); |
276 | closure = wl_closure_vmarshal(sender: &sender, opcode, ap, message: &message); |
277 | va_end(ap); |
278 | |
279 | assert(closure == NULL); |
280 | assert(errno == expected_error); |
281 | } |
282 | |
283 | static void |
284 | expected_fail_marshal_send(struct marshal_data *data, int expected_error, |
285 | const char *format, ...) |
286 | { |
287 | struct wl_closure *closure; |
288 | static const uint32_t opcode = 4444; |
289 | static struct wl_object sender = { NULL, NULL, 1234 }; |
290 | struct wl_message message = { "test" , format, NULL }; |
291 | va_list ap; |
292 | |
293 | va_start(ap, format); |
294 | closure = wl_closure_vmarshal(sender: &sender, opcode, ap, message: &message); |
295 | va_end(ap); |
296 | |
297 | assert(closure); |
298 | assert(wl_closure_send(closure, data->write_connection) < 0); |
299 | assert(errno == expected_error); |
300 | |
301 | wl_closure_destroy(closure); |
302 | } |
303 | |
304 | TEST(connection_marshal_nullables) |
305 | { |
306 | struct marshal_data data; |
307 | struct wl_object object; |
308 | struct wl_array array; |
309 | const char text[] = "curry" ; |
310 | |
311 | setup_marshal_data(&data); |
312 | |
313 | expected_fail_marshal(EINVAL, format: "o" , NULL); |
314 | expected_fail_marshal(EINVAL, format: "s" , NULL); |
315 | expected_fail_marshal(EINVAL, format: "a" , NULL); |
316 | |
317 | marshal(data: &data, format: "?o" , size: 12, NULL); |
318 | assert(data.buffer[2] == 0); |
319 | |
320 | marshal(data: &data, format: "?a" , size: 12, NULL); |
321 | assert(data.buffer[2] == 0); |
322 | |
323 | marshal(data: &data, format: "?s" , size: 12, NULL); |
324 | assert(data.buffer[2] == 0); |
325 | |
326 | object.id = 55293; |
327 | marshal(data: &data, format: "?o" , size: 12, &object); |
328 | assert(data.buffer[2] == object.id); |
329 | |
330 | array.data = (void *) text; |
331 | array.size = sizeof text; |
332 | marshal(data: &data, format: "?a" , size: 20, &array); |
333 | assert(data.buffer[2] == array.size); |
334 | assert(memcmp(&data.buffer[3], text, array.size) == 0); |
335 | |
336 | marshal(data: &data, format: "?s" , size: 20, text); |
337 | assert(data.buffer[2] == sizeof text); |
338 | assert(strcmp((char *) &data.buffer[3], text) == 0); |
339 | |
340 | release_marshal_data(data: &data); |
341 | } |
342 | |
343 | static void |
344 | validate_demarshal_u(struct marshal_data *data, |
345 | struct wl_object *object, uint32_t u) |
346 | { |
347 | assert(data->value.u == u); |
348 | } |
349 | |
350 | static void |
351 | validate_demarshal_i(struct marshal_data *data, |
352 | struct wl_object *object, int32_t i) |
353 | { |
354 | assert(data->value.i == i); |
355 | } |
356 | |
357 | static void |
358 | validate_demarshal_s(struct marshal_data *data, |
359 | struct wl_object *object, const char *s) |
360 | { |
361 | if (data->value.s != NULL) |
362 | assert(strcmp(data->value.s, s) == 0); |
363 | else |
364 | assert(s == NULL); |
365 | } |
366 | |
367 | static void |
368 | validate_demarshal_h(struct marshal_data *data, |
369 | struct wl_object *object, int fd) |
370 | { |
371 | struct stat buf1, buf2; |
372 | |
373 | assert(fd != data->value.h); |
374 | fstat(fd: fd, buf: &buf1); |
375 | fstat(fd: data->value.h, buf: &buf2); |
376 | assert(buf1.st_dev == buf2.st_dev); |
377 | assert(buf1.st_ino == buf2.st_ino); |
378 | close(fd: fd); |
379 | close(fd: data->value.h); |
380 | } |
381 | |
382 | static void |
383 | validate_demarshal_f(struct marshal_data *data, |
384 | struct wl_object *object, wl_fixed_t f) |
385 | { |
386 | assert(data->value.i == f); |
387 | } |
388 | |
389 | static void |
390 | demarshal(struct marshal_data *data, const char *format, |
391 | uint32_t *msg, void (*func)(void)) |
392 | { |
393 | struct wl_message message = { "test" , format, NULL }; |
394 | struct wl_closure *closure; |
395 | struct wl_map objects; |
396 | struct wl_object object = { NULL, &func, 0 }; |
397 | int size = msg[1] >> 16; |
398 | |
399 | assert(write(data->s[1], msg, size) == size); |
400 | assert(wl_connection_read(data->read_connection) == size); |
401 | |
402 | wl_map_init(map: &objects, WL_MAP_SERVER_SIDE); |
403 | object.id = msg[0]; |
404 | closure = wl_connection_demarshal(connection: data->read_connection, |
405 | size, objects: &objects, message: &message); |
406 | assert(closure); |
407 | wl_closure_invoke(closure, flags: WL_CLOSURE_INVOKE_SERVER, target: &object, opcode: 0, data); |
408 | wl_closure_destroy(closure); |
409 | } |
410 | |
411 | TEST(connection_demarshal) |
412 | { |
413 | struct marshal_data data; |
414 | uint32_t msg[10]; |
415 | |
416 | setup_marshal_data(&data); |
417 | |
418 | data.value.u = 8000; |
419 | msg[0] = 400200; /* object id */ |
420 | msg[1] = 12 << 16; /* size = 12, opcode = 0 */ |
421 | msg[2] = data.value.u; |
422 | demarshal(data: &data, format: "u" , msg, func: (void *) validate_demarshal_u); |
423 | |
424 | data.value.i = -557799; |
425 | msg[0] = 400200; |
426 | msg[1] = 12 << 16; |
427 | msg[2] = data.value.i; |
428 | demarshal(data: &data, format: "i" , msg, func: (void *) validate_demarshal_i); |
429 | |
430 | data.value.s = "superdude" ; |
431 | msg[0] = 400200; |
432 | msg[1] = 24 << 16; |
433 | msg[2] = 10; |
434 | msg[3 + msg[2]/4] = 0; |
435 | memcpy(dest: &msg[3], src: data.value.s, n: msg[2]); |
436 | demarshal(data: &data, format: "s" , msg, func: (void *) validate_demarshal_s); |
437 | |
438 | data.value.s = "superdude" ; |
439 | msg[0] = 400200; |
440 | msg[1] = 24 << 16; |
441 | msg[2] = 10; |
442 | msg[3 + msg[2]/4] = 0; |
443 | memcpy(dest: &msg[3], src: data.value.s, n: msg[2]); |
444 | demarshal(data: &data, format: "?s" , msg, func: (void *) validate_demarshal_s); |
445 | |
446 | data.value.i = wl_fixed_from_double(d: -90000.2390); |
447 | msg[0] = 400200; |
448 | msg[1] = 12 << 16; |
449 | msg[2] = data.value.i; |
450 | demarshal(data: &data, format: "f" , msg, func: (void *) validate_demarshal_f); |
451 | |
452 | data.value.s = NULL; |
453 | msg[0] = 400200; |
454 | msg[1] = 12 << 16; |
455 | msg[2] = 0; |
456 | demarshal(data: &data, format: "?s" , msg, func: (void *) validate_demarshal_s); |
457 | |
458 | release_marshal_data(data: &data); |
459 | } |
460 | |
461 | static void |
462 | marshal_demarshal(struct marshal_data *data, |
463 | void (*func)(void), int size, const char *format, ...) |
464 | { |
465 | struct wl_closure *closure; |
466 | static const int opcode = 4444; |
467 | static struct wl_object sender = { NULL, NULL, 1234 }; |
468 | struct wl_message message = { "test" , format, NULL }; |
469 | struct wl_map objects; |
470 | struct wl_object object = { NULL, &func, 0 }; |
471 | va_list ap; |
472 | uint32_t msg[1] = { 1234 }; |
473 | |
474 | va_start(ap, format); |
475 | closure = wl_closure_vmarshal(sender: &sender, opcode, ap, message: &message); |
476 | va_end(ap); |
477 | |
478 | assert(closure); |
479 | assert(wl_closure_send(closure, data->write_connection) == 0); |
480 | wl_closure_destroy(closure); |
481 | assert(wl_connection_flush(data->write_connection) == size); |
482 | |
483 | assert(wl_connection_read(data->read_connection) == size); |
484 | |
485 | wl_map_init(map: &objects, WL_MAP_SERVER_SIDE); |
486 | object.id = msg[0]; |
487 | closure = wl_connection_demarshal(connection: data->read_connection, |
488 | size, objects: &objects, message: &message); |
489 | assert(closure); |
490 | wl_closure_invoke(closure, flags: WL_CLOSURE_INVOKE_SERVER, target: &object, opcode: 0, data); |
491 | wl_closure_destroy(closure); |
492 | } |
493 | |
494 | TEST(connection_marshal_demarshal) |
495 | { |
496 | struct marshal_data data; |
497 | char f[] = "/tmp/wayland-tests-XXXXXX" ; |
498 | |
499 | setup_marshal_data(&data); |
500 | |
501 | data.value.u = 889911; |
502 | marshal_demarshal(data: &data, func: (void *) validate_demarshal_u, |
503 | size: 12, format: "u" , data.value.u); |
504 | |
505 | data.value.i = -13; |
506 | marshal_demarshal(data: &data, func: (void *) validate_demarshal_i, |
507 | size: 12, format: "i" , data.value.i); |
508 | |
509 | data.value.s = "cookie robots" ; |
510 | marshal_demarshal(data: &data, func: (void *) validate_demarshal_s, |
511 | size: 28, format: "s" , data.value.s); |
512 | |
513 | data.value.s = "cookie robots" ; |
514 | marshal_demarshal(data: &data, func: (void *) validate_demarshal_s, |
515 | size: 28, format: "?s" , data.value.s); |
516 | |
517 | data.value.h = mkstemp(template: f); |
518 | assert(data.value.h >= 0); |
519 | unlink(name: f); |
520 | marshal_demarshal(data: &data, func: (void *) validate_demarshal_h, |
521 | size: 8, format: "h" , data.value.h); |
522 | |
523 | data.value.i = wl_fixed_from_double(d: 1234.5678); |
524 | marshal_demarshal(data: &data, func: (void *) validate_demarshal_f, |
525 | size: 12, format: "f" , data.value.i); |
526 | |
527 | data.value.i = wl_fixed_from_double(d: -90000.2390); |
528 | marshal_demarshal(data: &data, func: (void *) validate_demarshal_f, |
529 | size: 12, format: "f" , data.value.i); |
530 | |
531 | data.value.i = wl_fixed_from_double(d: (1 << 23) - 1 + 0.0941); |
532 | marshal_demarshal(data: &data, func: (void *) validate_demarshal_f, |
533 | size: 12, format: "f" , data.value.i); |
534 | |
535 | release_marshal_data(data: &data); |
536 | } |
537 | |
538 | static void |
539 | expected_fail_demarshal(struct marshal_data *data, const char *format, |
540 | const uint32_t *msg, int expected_error) |
541 | { |
542 | struct wl_message message = { "test" , format, NULL }; |
543 | struct wl_closure *closure; |
544 | struct wl_map objects; |
545 | int size = (msg[1] >> 16); |
546 | |
547 | assert(write(data->s[1], msg, size) == size); |
548 | assert(wl_connection_read(data->read_connection) == size); |
549 | |
550 | wl_map_init(map: &objects, WL_MAP_SERVER_SIDE); |
551 | closure = wl_connection_demarshal(connection: data->read_connection, |
552 | size, objects: &objects, message: &message); |
553 | |
554 | assert(closure == NULL); |
555 | assert(errno == expected_error); |
556 | } |
557 | |
558 | TEST(connection_demarshal_null_strings) |
559 | { |
560 | struct marshal_data data; |
561 | uint32_t msg[3]; |
562 | |
563 | setup_marshal_data(&data); |
564 | |
565 | data.value.s = NULL; |
566 | msg[0] = 400200; /* object id */ |
567 | msg[1] = 12 << 16; /* size = 12, opcode = 0 */ |
568 | msg[2] = 0; /* string length = 0 */ |
569 | demarshal(data: &data, format: "?s" , msg, func: (void *) validate_demarshal_s); |
570 | |
571 | expected_fail_demarshal(data: &data, format: "s" , msg, EINVAL); |
572 | |
573 | release_marshal_data(data: &data); |
574 | } |
575 | |
576 | /* These tests are verifying that the demarshaling code will gracefully handle |
577 | * clients lying about string and array lengths and giving values near |
578 | * UINT32_MAX. Before fixes f7fdface and f5b9e3b9 this test would crash on |
579 | * 32bit systems. |
580 | */ |
581 | TEST(connection_demarshal_failures) |
582 | { |
583 | struct marshal_data data; |
584 | unsigned int i; |
585 | uint32_t msg[3]; |
586 | |
587 | const uint32_t overflowing_values[] = { |
588 | /* Values very close to UINT32_MAX. Before f5b9e3b9 these |
589 | * would cause integer overflow in DIV_ROUNDUP. */ |
590 | 0xffffffff, 0xfffffffe, 0xfffffffd, 0xfffffffc, |
591 | |
592 | /* Values at various offsets from UINT32_MAX. Before f7fdface |
593 | * these would overflow the "p" pointer on 32bit systems, |
594 | * effectively subtracting the offset from it. It had good |
595 | * chance to cause crash depending on what was stored at that |
596 | * offset before "p". */ |
597 | 0xfffff000, 0xffffd000, 0xffffc000, 0xffffb000 |
598 | }; |
599 | |
600 | setup_marshal_data(&data); |
601 | |
602 | /* sender_id, does not matter */ |
603 | msg[0] = 0; |
604 | |
605 | /* (size << 16 | opcode), opcode is 0, does not matter */ |
606 | msg[1] = sizeof(msg) << 16; |
607 | |
608 | for (i = 0; i < ARRAY_LENGTH(overflowing_values); i++) { |
609 | /* length of the string or array */ |
610 | msg[2] = overflowing_values[i]; |
611 | |
612 | expected_fail_demarshal(data: &data, format: "s" , msg, EINVAL); |
613 | expected_fail_demarshal(data: &data, format: "a" , msg, EINVAL); |
614 | } |
615 | |
616 | release_marshal_data(data: &data); |
617 | } |
618 | |
619 | TEST(connection_marshal_alot) |
620 | { |
621 | struct marshal_data data; |
622 | char f[64]; |
623 | int i; |
624 | |
625 | setup_marshal_data(&data); |
626 | |
627 | /* We iterate enough to make sure we wrap the circular buffers |
628 | * for both regular data an fds. */ |
629 | |
630 | for (i = 0; i < 2000; i++) { |
631 | strcpy(dest: f, src: "/tmp/wayland-tests-XXXXXX" ); |
632 | data.value.h = mkstemp(template: f); |
633 | assert(data.value.h >= 0); |
634 | unlink(name: f); |
635 | marshal_demarshal(data: &data, func: (void *) validate_demarshal_h, |
636 | size: 8, format: "h" , data.value.h); |
637 | } |
638 | |
639 | release_marshal_data(data: &data); |
640 | } |
641 | |
642 | TEST(connection_marshal_too_big) |
643 | { |
644 | struct marshal_data data; |
645 | char *big_string = malloc(size: 5000); |
646 | |
647 | assert(big_string); |
648 | |
649 | memset(s: big_string, c: ' ', n: 4999); |
650 | big_string[4999] = '\0'; |
651 | |
652 | setup_marshal_data(&data); |
653 | |
654 | expected_fail_marshal_send(data: &data, E2BIG, format: "s" , big_string); |
655 | |
656 | release_marshal_data(data: &data); |
657 | free(ptr: big_string); |
658 | } |
659 | |
660 | static void |
661 | marshal_helper(const char *format, void *handler, ...) |
662 | { |
663 | struct wl_closure *closure; |
664 | static struct wl_object sender = { NULL, NULL, 1234 }; |
665 | struct wl_object object = { NULL, &handler, 0 }; |
666 | static const int opcode = 4444; |
667 | struct wl_message message = { "test" , format, NULL }; |
668 | va_list ap; |
669 | int done; |
670 | |
671 | va_start(ap, handler); |
672 | closure = wl_closure_vmarshal(sender: &sender, opcode, ap, message: &message); |
673 | va_end(ap); |
674 | |
675 | assert(closure); |
676 | done = 0; |
677 | wl_closure_invoke(closure, flags: WL_CLOSURE_INVOKE_SERVER, target: &object, opcode: 0, data: &done); |
678 | wl_closure_destroy(closure); |
679 | assert(done); |
680 | } |
681 | |
682 | static void |
683 | suu_handler(void *data, struct wl_object *object, |
684 | const char *s, uint32_t u1, uint32_t u2) |
685 | { |
686 | int *done = data; |
687 | |
688 | assert(strcmp(s, "foo" ) == 0); |
689 | assert(u1 == 500); |
690 | assert(u2 == 404040); |
691 | *done = 1; |
692 | } |
693 | |
694 | TEST(invoke_closure) |
695 | { |
696 | marshal_helper(format: "suu" , handler: suu_handler, "foo" , 500, 404040); |
697 | } |
698 | |
699 | static void |
700 | leak_closure(void) |
701 | { |
702 | struct wl_callback *cb; |
703 | struct pollfd pfd; |
704 | struct client *c = client_connect(); |
705 | |
706 | cb = wl_display_sync(wl_display: c->wl_display); |
707 | assert(cb); |
708 | assert(wl_display_flush(c->wl_display) > 0); |
709 | |
710 | /* we don't need it, it is referenced */ |
711 | wl_callback_destroy(wl_callback: cb); |
712 | |
713 | pfd.fd = wl_display_get_fd(display: c->wl_display); |
714 | pfd.events = POLLIN; |
715 | |
716 | test_set_timeout(2); |
717 | assert(poll(&pfd, 1, -1) == 1); |
718 | |
719 | /* read events, but do not dispatch them */ |
720 | assert(wl_display_prepare_read(c->wl_display) == 0); |
721 | assert(wl_display_read_events(c->wl_display) == 0); |
722 | |
723 | /* |
724 | * now we have wl_callback.done and wl_display.delete_id queued; |
725 | * if we now release the queue (in wl_display_disconnect()) |
726 | * we should not leak memory |
727 | */ |
728 | |
729 | client_disconnect(c); |
730 | } |
731 | |
732 | TEST(closure_leaks) |
733 | { |
734 | struct display *d = display_create(); |
735 | |
736 | client_create_noarg(d, leak_closure); |
737 | display_run(d); |
738 | |
739 | display_destroy(d); |
740 | } |
741 | |
742 | static void |
743 | leak_after_error(void) |
744 | { |
745 | struct client *c = client_connect(); |
746 | |
747 | /* this should return -1, because we'll send error |
748 | * from server. */ |
749 | assert(stop_display(c, 1) == -1); |
750 | assert(wl_display_dispatch_pending(c->wl_display) == -1); |
751 | assert(wl_display_get_error(c->wl_display) == ENOMEM); |
752 | |
753 | /* after we got error, we have display_resume event |
754 | * in the queue. It should be freed in wl_display_disconnect(). |
755 | * Let's see! */ |
756 | |
757 | wl_proxy_destroy(proxy: (struct wl_proxy *) c->tc); |
758 | wl_display_disconnect(display: c->wl_display); |
759 | free(ptr: c); |
760 | } |
761 | |
762 | TEST(closure_leaks_after_error) |
763 | { |
764 | struct display *d = display_create(); |
765 | struct client_info *cl; |
766 | |
767 | cl = client_create_noarg(d, leak_after_error); |
768 | display_run(d); |
769 | |
770 | wl_client_post_no_memory(client: cl->wl_client); |
771 | display_resume(d); |
772 | |
773 | display_destroy(d); |
774 | } |
775 | |
776 | /** Raw read from socket expecting wl_display.error |
777 | * |
778 | * \param sockfd The socket to read from. |
779 | * \param expected_error The expected wl_display error code. |
780 | * |
781 | * Reads the socket and manually parses one message, expecting it to be a |
782 | * wl_display.error with the wl_display as the originating object. |
783 | * Asserts that the received error code is expected_error. |
784 | */ |
785 | static void |
786 | expect_error_recv(int sockfd, uint32_t expected_error) |
787 | { |
788 | uint32_t buf[1024]; |
789 | ssize_t slen; |
790 | uint32_t opcode; |
791 | int str_len; |
792 | |
793 | slen = recv(fd: sockfd, buf: buf, n: sizeof buf, flags: 0); |
794 | assert(slen >= 2 * (ssize_t)sizeof (uint32_t)); |
795 | opcode = buf[1] & 0xffff; |
796 | fprintf(stderr, format: "Received %zd bytes, object %u, opcode %u\n" , |
797 | slen, buf[0], opcode); |
798 | |
799 | /* check error event */ |
800 | assert(buf[0] == 1); |
801 | assert(opcode == WL_DISPLAY_ERROR); |
802 | |
803 | str_len = buf[4]; |
804 | assert(str_len > 0); |
805 | assert(str_len <= slen - 5 * (ssize_t)sizeof (uint32_t)); |
806 | fprintf(stderr, format: "Error event on object %u, code %u, message \"%*s\"\n" , |
807 | buf[2], buf[3], str_len, (const char *)&buf[5]); |
808 | |
809 | assert(buf[3] == expected_error); |
810 | } |
811 | |
812 | /* A test for https://gitlab.freedesktop.org/wayland/wayland/issues/52 |
813 | * trying to provoke a read from uninitialized memory in |
814 | * wl_connection_demarshal() for sender_id and opcode. |
815 | * |
816 | * This test might not fail as is even with #52 unfixed, since there is no way |
817 | * to detect what happens and the crash with zero size depends on stack content. |
818 | * However, running under Valgrind would point out invalid reads and use of |
819 | * uninitialized values. |
820 | */ |
821 | TEST(request_bogus_size) |
822 | { |
823 | struct wl_display *display; |
824 | struct wl_client *client; |
825 | int s[2]; |
826 | uint32_t msg[3]; |
827 | int bogus_size; |
828 | |
829 | test_set_timeout(1); |
830 | |
831 | /* |
832 | * The manufactured message has real size 12. Test all bogus sizes |
833 | * smaller than that, and zero as the last one since wl_closure_init |
834 | * handles zero specially and having garbage in the stack makes it more |
835 | * likely to crash in wl_connection_demarshal. |
836 | */ |
837 | for (bogus_size = 11; bogus_size >= 0; bogus_size--) { |
838 | fprintf(stderr, format: "* bogus size %d\n" , bogus_size); |
839 | |
840 | assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); |
841 | display = wl_display_create(); |
842 | assert(display); |
843 | client = wl_client_create(display, fd: s[0]); |
844 | assert(client); |
845 | |
846 | /* manufacture a request that lies about its size */ |
847 | msg[0] = 1; /* sender id: wl_display */ |
848 | msg[1] = (bogus_size << 16) | WL_DISPLAY_SYNC; /* size and opcode */ |
849 | msg[2] = 2; /* sync argument: new_id for wl_callback */ |
850 | |
851 | assert(send(s[1], msg, sizeof msg, 0) == sizeof msg); |
852 | |
853 | wl_event_loop_dispatch(loop: wl_display_get_event_loop(display), timeout: 0); |
854 | |
855 | expect_error_recv(sockfd: s[1], expected_error: WL_DISPLAY_ERROR_INVALID_METHOD); |
856 | |
857 | /* Do not wl_client_destroy, the error already caused it. */ |
858 | close(fd: s[1]); |
859 | wl_display_destroy(display); |
860 | } |
861 | } |
862 | |