• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Permission is hereby granted, free of charge, to any person obtaining
3  * a copy of this software and associated documentation files (the
4  * "Software"), to deal in the Software without restriction, including
5  * without limitation the rights to use, copy, modify, merge, publish,
6  * distribute, sublicense, and/or sell copies of the Software, and to
7  * permit persons to whom the Software is furnished to do so, subject to
8  * the following conditions:
9  *
10  * The above copyright notice and this permission notice (including the
11  * next paragraph) shall be included in all copies or substantial
12  * portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
18  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  */
23 
24 #include <stdlib.h>
25 #include <assert.h>
26 #include <errno.h>
27 #include <string.h>
28 #include <stdio.h>
29 #include <sys/un.h>
30 #include <unistd.h>
31 
32 #include "wayland-client.h"
33 #include "wayland-server.h"
34 #include "test-runner.h"
35 
36 /* Paths longer than what the .sun_path array can contain must be rejected.
37  * This is a hard limitation of assigning a name to AF_UNIX/AF_LOCAL sockets.
38  * See `man 7 unix`.
39  */
40 
41 static const struct sockaddr_un example_sockaddr_un;
42 
43 #define TOO_LONG (1 + sizeof example_sockaddr_un.sun_path)
44 
45 /* Ensure the connection doesn't fail due to lack of XDG_RUNTIME_DIR. */
46 static const char *
require_xdg_runtime_dir(void)47 require_xdg_runtime_dir(void)
48 {
49 	char *val = getenv("XDG_RUNTIME_DIR");
50 	assert(val && "set $XDG_RUNTIME_DIR to run this test");
51 
52 	return val;
53 }
54 
TEST(socket_path_overflow_client_connect)55 TEST(socket_path_overflow_client_connect)
56 {
57 	char path[TOO_LONG];
58 	struct wl_display *d;
59 
60 	require_xdg_runtime_dir();
61 
62 	memset(path, 'a', sizeof path);
63 	path[sizeof path - 1] = '\0';
64 
65 	d = wl_display_connect(path);
66 	assert(d == NULL);
67 	assert(errno == ENAMETOOLONG);
68 }
69 
TEST(socket_path_overflow_server_create)70 TEST(socket_path_overflow_server_create)
71 {
72 	char path[TOO_LONG];
73 	struct wl_display *d;
74 	int ret;
75 
76 	require_xdg_runtime_dir();
77 
78 	memset(path, 'a', sizeof path);
79 	path[sizeof path - 1] = '\0';
80 
81 	d = wl_display_create();
82 	assert(d != NULL);
83 
84 	ret = wl_display_add_socket(d, path);
85 	assert(ret < 0);
86 	assert(errno == ENAMETOOLONG);
87 
88 	wl_display_destroy(d);
89 }
90 
TEST(add_existing_socket)91 TEST(add_existing_socket)
92 {
93 	char path[sizeof example_sockaddr_un.sun_path];
94 	const char *name = "wayland-test-0";
95 	const char *xdg_runtime_dir;
96 	struct wl_display *d;
97 	int ret;
98 	size_t len;
99 
100 	xdg_runtime_dir = require_xdg_runtime_dir();
101 
102 	d = wl_display_create();
103 	assert(d != NULL);
104 
105 	/* this one should be OK */
106 	ret = wl_display_add_socket(d, name);
107 	assert(ret == 0);
108 
109 	/* this one should fail */
110 	ret = wl_display_add_socket(d, name);
111 	assert(ret < 0);
112 
113 	/* the original socket should still exist.
114 	 * this was a bug introduced in e2c0d47b0c77f18cd90e9c6eabb358c4d89681c8 */
115 	len = snprintf(path, sizeof example_sockaddr_un.sun_path, "%s/%s",
116 		       xdg_runtime_dir, name);
117 	assert(len < sizeof example_sockaddr_un.sun_path
118 	       && "Bug in test. Path too long");
119 
120 	assert(access(path, F_OK) != -1);
121 
122 	/* the original socket should still exist */
123 	ret = wl_display_add_socket(d, name);
124 	assert(ret < 0);
125 
126 	wl_display_destroy(d);
127 }
128 
TEST(add_socket_auto)129 TEST(add_socket_auto)
130 {
131 	/* the number of auto sockets is currently 32,
132 	 * set in wayland-server.c.
133 	 */
134 	const int MAX_SOCKETS = 32;
135 
136 	char path[sizeof example_sockaddr_un.sun_path];
137 	const char *name;
138 	const char *xdg_runtime_dir;
139 	struct wl_display *d;
140 	int i;
141 	size_t len;
142 
143 	xdg_runtime_dir = require_xdg_runtime_dir();
144 
145 	d = wl_display_create();
146 	assert(d != NULL);
147 
148 	for (i = 0; i <= MAX_SOCKETS; ++i) {
149 		name = wl_display_add_socket_auto(d);
150 		assert(name != NULL);
151 
152 		len = snprintf(path, sizeof example_sockaddr_un.sun_path,
153 			       "%s/%s", xdg_runtime_dir, name);
154 		assert(len < sizeof example_sockaddr_un.sun_path
155 		       && "Bug in test. Path too long");
156 
157 		/* was the socket created correctly? */
158 		assert(access(path, F_OK) != -1);
159 
160 		/* is the name sequential? */
161 		len = snprintf(path, sizeof example_sockaddr_un.sun_path,
162 			       "wayland-%d", i);
163 		assert(strcmp(name, path) == 0);
164 	}
165 
166 	/* next addition should return NULL */
167 	name = wl_display_add_socket_auto(d);
168 	assert(name == NULL);
169 
170 	/* check if the socket was not deleted the last time */
171 	name = wl_display_add_socket_auto(d);
172 	assert(name == NULL);
173 
174 	wl_display_destroy(d);
175 }
176