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