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