xref: /aosp_15_r20/external/wayland/tests/connection-test.c (revision 84e872a0dc482bffdb63672969dd03a827d67c73)
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